locale.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // Copyright (c) 2016 Klemens D. Morgenstern
  2. // Copyright (c) 2008 Beman Dawes
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_PROCESS_LOCALE_HPP_
  6. #define BOOST_PROCESS_LOCALE_HPP_
  7. #include <system_error>
  8. #include <boost/process/v1/detail/config.hpp>
  9. #if defined(BOOST_WINDOWS_API)
  10. #include <boost/process/v1/detail/windows/locale.hpp>
  11. # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
  12. || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
  13. #include <codecvt>
  14. #endif
  15. #include <locale>
  16. namespace boost
  17. {
  18. namespace process
  19. {
  20. BOOST_PROCESS_V1_INLINE namespace v1
  21. {
  22. namespace detail
  23. {
  24. class codecvt_category_t : public std::error_category
  25. {
  26. public:
  27. codecvt_category_t() = default;
  28. const char* name() const noexcept override {return "codecvt";}
  29. std::string message(int ev) const override
  30. {
  31. std::string str;
  32. switch (ev)
  33. {
  34. case std::codecvt_base::ok:
  35. str = "ok";
  36. break;
  37. case std::codecvt_base::partial:
  38. str = "partial";
  39. break;
  40. case std::codecvt_base::error:
  41. str = "error";
  42. break;
  43. case std::codecvt_base::noconv:
  44. str = "noconv";
  45. break;
  46. default:
  47. str = "unknown error";
  48. }
  49. return str;
  50. }
  51. };
  52. }
  53. ///Internally used error cateory for code conversion.
  54. inline const std::error_category& codecvt_category()
  55. {
  56. static const ::boost::process::v1::detail::codecvt_category_t cat;
  57. return cat;
  58. }
  59. namespace detail
  60. {
  61. //copied from boost.filesystem
  62. inline std::locale default_locale()
  63. {
  64. # if defined(BOOST_WINDOWS_API)
  65. std::locale global_loc = std::locale();
  66. return std::locale(global_loc, new boost::process::v1::detail::windows::windows_file_codecvt);
  67. # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
  68. || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
  69. std::locale global_loc = std::locale();
  70. return std::locale(global_loc, new std::codecvt_utf8<wchar_t>);
  71. # else // Other POSIX
  72. // ISO C calls std::locale("") "the locale-specific native environment", and this
  73. // locale is the default for many POSIX-based operating systems such as Linux.
  74. return std::locale("");
  75. # endif
  76. }
  77. inline std::locale& process_locale()
  78. {
  79. static std::locale loc(default_locale());
  80. return loc;
  81. }
  82. }
  83. ///The internally used type for code conversion.
  84. typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_type;
  85. ///Get a reference to the currently used code converter.
  86. inline const codecvt_type& codecvt()
  87. {
  88. return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(
  89. detail::process_locale());
  90. }
  91. ///Set the locale of the library.
  92. inline std::locale imbue(const std::locale& loc)
  93. {
  94. std::locale temp(detail::process_locale());
  95. detail::process_locale() = loc;
  96. return temp;
  97. }
  98. namespace detail
  99. {
  100. inline std::size_t convert(const char* from,
  101. const char* from_end,
  102. wchar_t* to, wchar_t* to_end,
  103. const ::boost::process::v1::codecvt_type & cvt =
  104. ::boost::process::v1::codecvt())
  105. {
  106. std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports
  107. const char* from_next;
  108. wchar_t* to_next;
  109. auto res = cvt.in(state, from, from_end, from_next,
  110. to, to_end, to_next);
  111. if (res != std::codecvt_base::ok)
  112. throw process_error(res, ::boost::process::v1::codecvt_category(),
  113. "boost::process codecvt to wchar_t");
  114. return to_next - to;
  115. }
  116. inline std::size_t convert(const wchar_t* from,
  117. const wchar_t* from_end,
  118. char* to, char* to_end,
  119. const ::boost::process::v1::codecvt_type & cvt =
  120. ::boost::process::v1::codecvt())
  121. {
  122. std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports
  123. const wchar_t* from_next;
  124. char* to_next;
  125. std::codecvt_base::result res;
  126. if ((res=cvt.out(state, from, from_end, from_next,
  127. to, to_end, to_next)) != std::codecvt_base::ok)
  128. throw process_error(res, ::boost::process::v1::codecvt_category(),
  129. "boost::process codecvt to char");
  130. return to_next - to;
  131. }
  132. inline std::wstring convert(const std::string & st,
  133. const ::boost::process::v1::codecvt_type & cvt =
  134. ::boost::process::v1::codecvt())
  135. {
  136. std::wstring out(st.size() + 10, ' '); //just to be sure
  137. auto sz = convert(st.c_str(), st.c_str() + st.size(),
  138. &out.front(), &out.back(), cvt);
  139. out.resize(sz);
  140. return out;
  141. }
  142. inline std::string convert(const std::wstring & st,
  143. const ::boost::process::v1::codecvt_type & cvt =
  144. ::boost::process::v1::codecvt())
  145. {
  146. std::string out(st.size() * 2, ' '); //just to be sure
  147. auto sz = convert(st.c_str(), st.c_str() + st.size(),
  148. &out.front(), &out.back(), cvt);
  149. out.resize(sz);
  150. return out;
  151. }
  152. inline std::vector<wchar_t> convert(const std::vector<char> & st,
  153. const ::boost::process::v1::codecvt_type & cvt =
  154. ::boost::process::v1::codecvt())
  155. {
  156. std::vector<wchar_t> out(st.size() + 10); //just to be sure
  157. auto sz = convert(st.data(), st.data() + st.size(),
  158. &out.front(), &out.back(), cvt);
  159. out.resize(sz);
  160. return out;
  161. }
  162. inline std::vector<char> convert(const std::vector<wchar_t> & st,
  163. const ::boost::process::v1::codecvt_type & cvt =
  164. ::boost::process::v1::codecvt())
  165. {
  166. std::vector<char> out(st.size() * 2); //just to be sure
  167. auto sz = convert(st.data(), st.data() + st.size(),
  168. &out.front(), &out.back(), cvt);
  169. out.resize(sz);
  170. return out;
  171. }
  172. inline std::wstring convert(const char *begin, const char* end,
  173. const ::boost::process::v1::codecvt_type & cvt =
  174. ::boost::process::v1::codecvt())
  175. {
  176. auto size = end-begin;
  177. std::wstring out(size + 10, ' '); //just to be sure
  178. using namespace std;
  179. auto sz = convert(begin, end,
  180. &out.front(), &out.back(), cvt);
  181. out.resize(sz);
  182. return out;
  183. }
  184. inline std::string convert(const wchar_t * begin, const wchar_t *end,
  185. const ::boost::process::v1::codecvt_type & cvt =
  186. ::boost::process::v1::codecvt())
  187. {
  188. auto size = end-begin;
  189. std::string out(size * 2, ' '); //just to be sure
  190. auto sz = convert(begin, end ,
  191. &out.front(), &out.back(), cvt);
  192. out.resize(sz);
  193. return out;
  194. }
  195. }
  196. }}}
  197. #endif /* BOOST_PROCESS_LOCALE_HPP_ */