12#include "../Encoding.hpp"
13#include "../Macros.hpp"
41CLI11_INLINE
void set_unicode_locale() {
42 static const std::array<const char *, 2> unicode_locales{{
"C.UTF-8",
".UTF-8"}};
44 for(
const auto &locale_name : unicode_locales) {
45 if(std::setlocale(LC_ALL, locale_name) !=
nullptr) {
49 throw std::runtime_error(
"CLI::narrow: could not set locale to C.UTF-8");
52template <
typename F>
struct scope_guard_t {
55 explicit scope_guard_t(F closure_) : closure(closure_) {}
56 ~scope_guard_t() { closure(); }
59template <
typename F> CLI11_NODISCARD CLI11_INLINE scope_guard_t<F> scope_guard(F &&closure) {
60 return scope_guard_t<F>{std::forward<F>(closure)};
66CLI11_DIAGNOSTIC_IGNORE_DEPRECATED
68CLI11_INLINE std::string narrow_impl(
const wchar_t *str, std::size_t str_size) {
71 return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(str, str + str_size);
74 return std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(str, str + str_size);
82 std::wstring input(str, str_size);
83 const wchar_t *src = input.c_str();
84 const wchar_t *it = src;
86 std::mbstate_t state = std::mbstate_t();
88 std::string old_locale = std::setlocale(LC_ALL,
nullptr);
89 auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); });
92 std::size_t new_size = std::wcsrtombs(
nullptr, &it, 0, &state);
93 if(new_size ==
static_cast<std::size_t
>(-1)) {
94 throw std::runtime_error(
"CLI::narrow: conversion error in std::wcsrtombs at offset " +
95 std::to_string(it - src));
97 std::string result(new_size,
'\0');
98 std::wcsrtombs(
const_cast<char *
>(result.data()), &src, new_size, &state);
105CLI11_INLINE std::wstring widen_impl(
const char *str, std::size_t str_size) {
108 return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(str, str + str_size);
111 return std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(str, str + str_size);
119 std::string input(str, str_size);
120 const char *src = input.c_str();
121 const char *it = src;
123 std::mbstate_t state = std::mbstate_t();
125 std::string old_locale = std::setlocale(LC_ALL,
nullptr);
126 auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); });
127 set_unicode_locale();
129 std::size_t new_size = std::mbsrtowcs(
nullptr, &it, 0, &state);
130 if(new_size ==
static_cast<std::size_t
>(-1)) {
131 throw std::runtime_error(
"CLI::widen: conversion error in std::mbsrtowcs at offset " +
132 std::to_string(it - src));
134 std::wstring result(new_size, L
'\0');
135 std::mbsrtowcs(
const_cast<wchar_t *
>(result.data()), &src, new_size, &state);
146CLI11_INLINE std::string narrow(
const wchar_t *str, std::size_t str_size) {
return detail::narrow_impl(str, str_size); }
147CLI11_INLINE std::string narrow(
const std::wstring &str) {
return detail::narrow_impl(str.data(), str.size()); }
149CLI11_INLINE std::string narrow(
const wchar_t *str) {
return detail::narrow_impl(str, std::wcslen(str)); }
151CLI11_INLINE std::wstring widen(
const char *str, std::size_t str_size) {
return detail::widen_impl(str, str_size); }
152CLI11_INLINE std::wstring widen(
const std::string &str) {
return detail::widen_impl(str.data(), str.size()); }
154CLI11_INLINE std::wstring widen(
const char *str) {
return detail::widen_impl(str, std::strlen(str)); }
157CLI11_INLINE std::string narrow(std::wstring_view str) {
return detail::narrow_impl(str.data(), str.size()); }
158CLI11_INLINE std::wstring widen(std::string_view str) {
return detail::widen_impl(str.data(), str.size()); }
161#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
162CLI11_INLINE std::filesystem::path to_path(std::string_view str) {
163 return std::filesystem::path{