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