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