12#include "../Encoding.hpp"
13#include "../Macros.hpp"
35CLI11_INLINE
void set_unicode_locale() {
36 static const std::array<const char *, 3> unicode_locales{{
"C.UTF-8",
"en_US.UTF-8",
".UTF-8"}};
38 for(
const auto &locale_name : unicode_locales) {
39 if(std::setlocale(LC_ALL, locale_name) !=
nullptr) {
43 throw std::runtime_error(
"CLI::narrow: could not set locale to C.UTF-8");
46template <
typename F>
struct scope_guard_t {
49 explicit scope_guard_t(F closure_) : closure(closure_) {}
50 ~scope_guard_t() { closure(); }
53template <
typename F> CLI11_NODISCARD CLI11_INLINE scope_guard_t<F> scope_guard(F &&closure) {
54 return scope_guard_t<F>{std::forward<F>(closure)};
60CLI11_DIAGNOSTIC_IGNORE_DEPRECATED
62CLI11_INLINE std::string narrow_impl(
const wchar_t *str, std::size_t str_size) {
65 return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(str, str + str_size);
68 return std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(str, str + str_size);
73 std::mbstate_t state = std::mbstate_t();
74 const wchar_t *it = str;
76 std::string old_locale = std::setlocale(LC_ALL,
nullptr);
77 auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); });
80 std::size_t new_size = std::wcsrtombs(
nullptr, &it, 0, &state);
81 if(new_size ==
static_cast<std::size_t
>(-1)) {
82 throw std::runtime_error(
"CLI::narrow: conversion error in std::wcsrtombs at offset " +
83 std::to_string(it - str));
85 std::string result(new_size,
'\0');
86 std::wcsrtombs(
const_cast<char *
>(result.data()), &str, new_size, &state);
93CLI11_INLINE std::wstring widen_impl(
const char *str, std::size_t str_size) {
96 return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(str, str + str_size);
99 return std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(str, str + str_size);
104 std::mbstate_t state = std::mbstate_t();
105 const char *it = str;
107 std::string old_locale = std::setlocale(LC_ALL,
nullptr);
108 auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); });
109 set_unicode_locale();
111 std::size_t new_size = std::mbsrtowcs(
nullptr, &it, 0, &state);
112 if(new_size ==
static_cast<std::size_t
>(-1)) {
113 throw std::runtime_error(
"CLI::widen: conversion error in std::mbsrtowcs at offset " +
114 std::to_string(it - str));
116 std::wstring result(new_size, L
'\0');
117 std::mbsrtowcs(
const_cast<wchar_t *
>(result.data()), &str, new_size, &state);
128CLI11_INLINE std::string narrow(
const wchar_t *str, std::size_t str_size) {
return detail::narrow_impl(str, str_size); }
129CLI11_INLINE std::string narrow(
const std::wstring &str) {
return detail::narrow_impl(str.data(), str.size()); }
131CLI11_INLINE std::string narrow(
const wchar_t *str) {
return detail::narrow_impl(str, std::wcslen(str)); }
133CLI11_INLINE std::wstring widen(
const char *str, std::size_t str_size) {
return detail::widen_impl(str, str_size); }
134CLI11_INLINE std::wstring widen(
const std::string &str) {
return detail::widen_impl(str.data(), str.size()); }
136CLI11_INLINE std::wstring widen(
const char *str) {
return detail::widen_impl(str, std::strlen(str)); }
139CLI11_INLINE std::string narrow(std::wstring_view str) {
return detail::narrow_impl(str.data(), str.size()); }
140CLI11_INLINE std::wstring widen(std::string_view str) {
return detail::widen_impl(str.data(), str.size()); }
143#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
144CLI11_INLINE std::filesystem::path to_path(std::string_view str) {
145 return std::filesystem::path{