File indexing completed on 2025-04-10 08:42:59
0001
0002
0003
0004
0005
0006 #ifndef BOOST_PROCESS_LOCALE_HPP_
0007 #define BOOST_PROCESS_LOCALE_HPP_
0008
0009 #include <system_error>
0010 #include <boost/process/v1/detail/config.hpp>
0011
0012 #if defined(BOOST_WINDOWS_API)
0013 #include <boost/process/v1/detail/windows/locale.hpp>
0014 # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
0015 || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
0016 #include <codecvt>
0017 #endif
0018
0019 #include <locale>
0020
0021 namespace boost
0022 {
0023 namespace process
0024 {
0025 BOOST_PROCESS_V1_INLINE namespace v1
0026 {
0027 namespace detail
0028 {
0029
0030 class codecvt_category_t : public std::error_category
0031 {
0032 public:
0033 codecvt_category_t() = default;
0034 const char* name() const noexcept override {return "codecvt";}
0035 std::string message(int ev) const override
0036 {
0037 std::string str;
0038 switch (ev)
0039 {
0040 case std::codecvt_base::ok:
0041 str = "ok";
0042 break;
0043 case std::codecvt_base::partial:
0044 str = "partial";
0045 break;
0046 case std::codecvt_base::error:
0047 str = "error";
0048 break;
0049 case std::codecvt_base::noconv:
0050 str = "noconv";
0051 break;
0052 default:
0053 str = "unknown error";
0054 }
0055 return str;
0056 }
0057 };
0058
0059 }
0060
0061
0062 inline const std::error_category& codecvt_category()
0063 {
0064 static const ::boost::process::v1::detail::codecvt_category_t cat;
0065 return cat;
0066 }
0067
0068 namespace detail
0069 {
0070
0071 inline std::locale default_locale()
0072 {
0073 # if defined(BOOST_WINDOWS_API)
0074 std::locale global_loc = std::locale();
0075 return std::locale(global_loc, new boost::process::v1::detail::windows::windows_file_codecvt);
0076 # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
0077 || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
0078 std::locale global_loc = std::locale();
0079 return std::locale(global_loc, new std::codecvt_utf8<wchar_t>);
0080 # else
0081
0082 return std::locale();
0083 # endif
0084 }
0085
0086 inline std::locale& process_locale()
0087 {
0088 static std::locale loc(default_locale());
0089 return loc;
0090 }
0091
0092 }
0093
0094
0095 typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_type;
0096
0097
0098 inline const codecvt_type& codecvt()
0099 {
0100 return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(
0101 detail::process_locale());
0102 }
0103
0104
0105 inline std::locale imbue(const std::locale& loc)
0106 {
0107 std::locale temp(detail::process_locale());
0108 detail::process_locale() = loc;
0109 return temp;
0110 }
0111
0112
0113 namespace detail
0114 {
0115
0116 inline std::size_t convert(const char* from,
0117 const char* from_end,
0118 wchar_t* to, wchar_t* to_end,
0119 const ::boost::process::v1::codecvt_type & cvt =
0120 ::boost::process::v1::codecvt())
0121 {
0122 std::mbstate_t state = std::mbstate_t();
0123 const char* from_next;
0124 wchar_t* to_next;
0125
0126 auto res = cvt.in(state, from, from_end, from_next,
0127 to, to_end, to_next);
0128
0129 if (res != std::codecvt_base::ok)
0130 throw process_error(res, ::boost::process::v1::codecvt_category(),
0131 "boost::process codecvt to wchar_t");
0132
0133
0134 return to_next - to;
0135
0136 }
0137
0138 inline std::size_t convert(const wchar_t* from,
0139 const wchar_t* from_end,
0140 char* to, char* to_end,
0141 const ::boost::process::v1::codecvt_type & cvt =
0142 ::boost::process::v1::codecvt())
0143 {
0144 std::mbstate_t state = std::mbstate_t();
0145 const wchar_t* from_next;
0146 char* to_next;
0147
0148 std::codecvt_base::result res;
0149
0150 if ((res=cvt.out(state, from, from_end, from_next,
0151 to, to_end, to_next)) != std::codecvt_base::ok)
0152 throw process_error(res, ::boost::process::v1::codecvt_category(),
0153 "boost::process codecvt to char");
0154
0155 return to_next - to;
0156 }
0157
0158 inline std::wstring convert(const std::string & st,
0159 const ::boost::process::v1::codecvt_type & cvt =
0160 ::boost::process::v1::codecvt())
0161 {
0162 std::wstring out(st.size() + 10, ' ');
0163 auto sz = convert(st.c_str(), st.c_str() + st.size(),
0164 &out.front(), &out.back(), cvt);
0165
0166 out.resize(sz);
0167 return out;
0168 }
0169
0170 inline std::string convert(const std::wstring & st,
0171 const ::boost::process::v1::codecvt_type & cvt =
0172 ::boost::process::v1::codecvt())
0173 {
0174 std::string out(st.size() * 2, ' ');
0175 auto sz = convert(st.c_str(), st.c_str() + st.size(),
0176 &out.front(), &out.back(), cvt);
0177
0178 out.resize(sz);
0179 return out;
0180 }
0181
0182 inline std::vector<wchar_t> convert(const std::vector<char> & st,
0183 const ::boost::process::v1::codecvt_type & cvt =
0184 ::boost::process::v1::codecvt())
0185 {
0186 std::vector<wchar_t> out(st.size() + 10);
0187 auto sz = convert(st.data(), st.data() + st.size(),
0188 &out.front(), &out.back(), cvt);
0189
0190 out.resize(sz);
0191 return out;
0192 }
0193
0194 inline std::vector<char> convert(const std::vector<wchar_t> & st,
0195 const ::boost::process::v1::codecvt_type & cvt =
0196 ::boost::process::v1::codecvt())
0197 {
0198 std::vector<char> out(st.size() * 2);
0199 auto sz = convert(st.data(), st.data() + st.size(),
0200 &out.front(), &out.back(), cvt);
0201
0202 out.resize(sz);
0203 return out;
0204 }
0205
0206
0207 inline std::wstring convert(const char *begin, const char* end,
0208 const ::boost::process::v1::codecvt_type & cvt =
0209 ::boost::process::v1::codecvt())
0210 {
0211 auto size = end-begin;
0212 std::wstring out(size + 10, ' ');
0213 using namespace std;
0214 auto sz = convert(begin, end,
0215 &out.front(), &out.back(), cvt);
0216 out.resize(sz);
0217 return out;
0218 }
0219
0220 inline std::string convert(const wchar_t * begin, const wchar_t *end,
0221 const ::boost::process::v1::codecvt_type & cvt =
0222 ::boost::process::v1::codecvt())
0223 {
0224 auto size = end-begin;
0225
0226 std::string out(size * 2, ' ');
0227 auto sz = convert(begin, end ,
0228 &out.front(), &out.back(), cvt);
0229
0230 out.resize(sz);
0231 return out;
0232 }
0233
0234
0235
0236
0237 }
0238
0239
0240
0241 }}}
0242
0243 #endif