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