blob: e626528fc56623964cd54b30582204439b6b1b5c [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
Dan Albert938c6a02014-12-03 21:33:51 -080010#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
11
David Chisnall997e4542012-02-29 13:05:08 +000012// On Solaris, we need to define something to make the C99 parts of localeconv
13// visible.
14#ifdef __sun__
15#define _LCONV_C99
16#endif
17
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000018#include "string"
19#include "locale"
Howard Hinnant87d1a8a2010-05-30 21:39:41 +000020#include "codecvt"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000021#include "vector"
22#include "algorithm"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000023#include "typeinfo"
Howard Hinnantb87922c2013-07-28 18:20:00 +000024#ifndef _LIBCPP_NO_EXCEPTIONS
25# include "type_traits"
26#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000027#include "clocale"
28#include "cstring"
29#include "cwctype"
30#include "__sso_allocator"
Howard Hinnantef5aa932013-09-17 01:34:47 +000031#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant14fa9f92011-09-29 20:33:10 +000032#include <support/win32/locale_win32.h>
Marshall Clowe45cf3e2014-07-10 15:20:28 +000033#elif !defined(__ANDROID__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000034#include <langinfo.h>
Marshall Clowe45cf3e2014-07-10 15:20:28 +000035#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000036#include <stdlib.h>
Howard Hinnanted14a762013-07-23 16:05:56 +000037#include <stdio.h>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000038
Marshall Clow9ae96d02013-02-07 17:20:56 +000039// On Linux, wint_t and wchar_t have different signed-ness, and this causes
40// lots of noise in the build log, but no bugs that I know of.
Marshall Clowa3645132013-10-21 15:07:28 +000041#if defined(__clang__)
Marshall Clow9ae96d02013-02-07 17:20:56 +000042#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowa3645132013-10-21 15:07:28 +000043#endif
Marshall Clow9ae96d02013-02-07 17:20:56 +000044
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000045_LIBCPP_BEGIN_NAMESPACE_STD
46
Howard Hinnant866569b2011-09-28 23:39:33 +000047#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000048locale_t __cloc() {
49 // In theory this could create a race condition. In practice
50 // the race condition is non-fatal since it will just create
51 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000052 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
53 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000054}
Howard Hinnant866569b2011-09-28 23:39:33 +000055#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000056
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000057namespace {
58
59struct release
60{
61 void operator()(locale::facet* p) {p->__release_shared();}
62};
63
64template <class T, class A0>
65inline
66T&
67make(A0 a0)
68{
69 static typename aligned_storage<sizeof(T)>::type buf;
70 ::new (&buf) T(a0);
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +000071 return *reinterpret_cast<T*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000072}
73
74template <class T, class A0, class A1>
75inline
76T&
77make(A0 a0, A1 a1)
78{
79 static typename aligned_storage<sizeof(T)>::type buf;
80 ::new (&buf) T(a0, a1);
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +000081 return *reinterpret_cast<T*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000082}
83
84template <class T, class A0, class A1, class A2>
85inline
86T&
87make(A0 a0, A1 a1, A2 a2)
88{
89 static typename aligned_storage<sizeof(T)>::type buf;
90 ::new (&buf) T(a0, a1, a2);
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +000091 return *reinterpret_cast<T*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000092}
93
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000094template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000095inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000096_LIBCPP_CONSTEXPR
97size_t
98countof(const T (&)[N])
99{
100 return N;
101}
102
103template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +0000104inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +0000105_LIBCPP_CONSTEXPR
106size_t
107countof(const T * const begin, const T * const end)
108{
109 return static_cast<size_t>(end - begin);
110}
111
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000112}
113
Howard Hinnant51437222013-08-29 23:37:50 +0000114#if defined(_AIX)
115// Set priority to INT_MIN + 256 + 150
116# pragma priority ( -2147483242 )
117#endif
118
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000119const locale::category locale::none;
120const locale::category locale::collate;
121const locale::category locale::ctype;
122const locale::category locale::monetary;
123const locale::category locale::numeric;
124const locale::category locale::time;
125const locale::category locale::messages;
126const locale::category locale::all;
127
Marshall Clowa3645132013-10-21 15:07:28 +0000128#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000129#pragma clang diagnostic push
130#pragma clang diagnostic ignored "-Wpadded"
Marshall Clowa3645132013-10-21 15:07:28 +0000131#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000132
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000133class _LIBCPP_HIDDEN locale::__imp
134 : public facet
135{
136 enum {N = 28};
Marshall Clowa3645132013-10-21 15:07:28 +0000137#if defined(_LIBCPP_MSVC)
138// FIXME: MSVC doesn't support aligned parameters by value.
139// I can't get the __sso_allocator to work here
140// for MSVC I think for this reason.
141 vector<facet*> facets_;
142#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000143 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowa3645132013-10-21 15:07:28 +0000144#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000145 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000146public:
147 explicit __imp(size_t refs = 0);
148 explicit __imp(const string& name, size_t refs = 0);
149 __imp(const __imp&);
150 __imp(const __imp&, const string&, locale::category c);
151 __imp(const __imp& other, const __imp& one, locale::category c);
152 __imp(const __imp&, facet* f, long id);
153 ~__imp();
154
155 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000156 bool has_facet(long id) const
157 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000158 const locale::facet* use_facet(long id) const;
159
160 static const locale& make_classic();
161 static locale& make_global();
162private:
163 void install(facet* f, long id);
164 template <class F> void install(F* f) {install(f, f->id.__get());}
165 template <class F> void install_from(const __imp& other);
166};
167
Marshall Clowa3645132013-10-21 15:07:28 +0000168#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000169#pragma clang diagnostic pop
Marshall Clowa3645132013-10-21 15:07:28 +0000170#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000171
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000172locale::__imp::__imp(size_t refs)
173 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000174 facets_(N),
175 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000176{
177 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000178 install(&make<_VSTD::collate<char> >(1u));
179 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000180 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnantec3773c2011-12-01 20:21:04 +0000181 install(&make<_VSTD::ctype<wchar_t> >(1u));
182 install(&make<codecvt<char, char, mbstate_t> >(1u));
183 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
184 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
185 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
186 install(&make<numpunct<char> >(1u));
187 install(&make<numpunct<wchar_t> >(1u));
188 install(&make<num_get<char> >(1u));
189 install(&make<num_get<wchar_t> >(1u));
190 install(&make<num_put<char> >(1u));
191 install(&make<num_put<wchar_t> >(1u));
192 install(&make<moneypunct<char, false> >(1u));
193 install(&make<moneypunct<char, true> >(1u));
194 install(&make<moneypunct<wchar_t, false> >(1u));
195 install(&make<moneypunct<wchar_t, true> >(1u));
196 install(&make<money_get<char> >(1u));
197 install(&make<money_get<wchar_t> >(1u));
198 install(&make<money_put<char> >(1u));
199 install(&make<money_put<wchar_t> >(1u));
200 install(&make<time_get<char> >(1u));
201 install(&make<time_get<wchar_t> >(1u));
202 install(&make<time_put<char> >(1u));
203 install(&make<time_put<wchar_t> >(1u));
204 install(&make<_VSTD::messages<char> >(1u));
205 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000206}
207
208locale::__imp::__imp(const string& name, size_t refs)
209 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000210 facets_(N),
211 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000212{
Howard Hinnantd4444702010-08-11 17:04:31 +0000213#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000214 try
215 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000216#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000217 facets_ = locale::classic().__locale_->facets_;
218 for (unsigned i = 0; i < facets_.size(); ++i)
219 if (facets_[i])
220 facets_[i]->__add_shared();
221 install(new collate_byname<char>(name_));
222 install(new collate_byname<wchar_t>(name_));
223 install(new ctype_byname<char>(name_));
224 install(new ctype_byname<wchar_t>(name_));
225 install(new codecvt_byname<char, char, mbstate_t>(name_));
226 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
227 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
228 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
229 install(new numpunct_byname<char>(name_));
230 install(new numpunct_byname<wchar_t>(name_));
231 install(new moneypunct_byname<char, false>(name_));
232 install(new moneypunct_byname<char, true>(name_));
233 install(new moneypunct_byname<wchar_t, false>(name_));
234 install(new moneypunct_byname<wchar_t, true>(name_));
235 install(new time_get_byname<char>(name_));
236 install(new time_get_byname<wchar_t>(name_));
237 install(new time_put_byname<char>(name_));
238 install(new time_put_byname<wchar_t>(name_));
239 install(new messages_byname<char>(name_));
240 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000241#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000242 }
243 catch (...)
244 {
245 for (unsigned i = 0; i < facets_.size(); ++i)
246 if (facets_[i])
247 facets_[i]->__release_shared();
248 throw;
249 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000250#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000251}
252
Howard Hinnant21772ec2012-12-28 18:15:01 +0000253// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000254// copy constructor` warning emitted by GCC
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000255#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000256#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000257#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000258#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000259
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000260locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000261 : facets_(max<size_t>(N, other.facets_.size())),
262 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000263{
264 facets_ = other.facets_;
265 for (unsigned i = 0; i < facets_.size(); ++i)
266 if (facets_[i])
267 facets_[i]->__add_shared();
268}
269
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000270#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000271#pragma GCC diagnostic pop
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000272#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000273
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000274locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000275 : facets_(N),
276 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000277{
278 facets_ = other.facets_;
279 for (unsigned i = 0; i < facets_.size(); ++i)
280 if (facets_[i])
281 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000282#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000283 try
284 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000285#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000286 if (c & locale::collate)
287 {
288 install(new collate_byname<char>(name));
289 install(new collate_byname<wchar_t>(name));
290 }
291 if (c & locale::ctype)
292 {
293 install(new ctype_byname<char>(name));
294 install(new ctype_byname<wchar_t>(name));
295 install(new codecvt_byname<char, char, mbstate_t>(name));
296 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
297 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
298 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
299 }
300 if (c & locale::monetary)
301 {
302 install(new moneypunct_byname<char, false>(name));
303 install(new moneypunct_byname<char, true>(name));
304 install(new moneypunct_byname<wchar_t, false>(name));
305 install(new moneypunct_byname<wchar_t, true>(name));
306 }
307 if (c & locale::numeric)
308 {
309 install(new numpunct_byname<char>(name));
310 install(new numpunct_byname<wchar_t>(name));
311 }
312 if (c & locale::time)
313 {
314 install(new time_get_byname<char>(name));
315 install(new time_get_byname<wchar_t>(name));
316 install(new time_put_byname<char>(name));
317 install(new time_put_byname<wchar_t>(name));
318 }
319 if (c & locale::messages)
320 {
321 install(new messages_byname<char>(name));
322 install(new messages_byname<wchar_t>(name));
323 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000324#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000325 }
326 catch (...)
327 {
328 for (unsigned i = 0; i < facets_.size(); ++i)
329 if (facets_[i])
330 facets_[i]->__release_shared();
331 throw;
332 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000333#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000334}
335
336template<class F>
337inline
338void
339locale::__imp::install_from(const locale::__imp& one)
340{
341 long id = F::id.__get();
342 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
343}
344
345locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000346 : facets_(N),
347 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000348{
349 facets_ = other.facets_;
350 for (unsigned i = 0; i < facets_.size(); ++i)
351 if (facets_[i])
352 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000353#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000354 try
355 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000356#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000357 if (c & locale::collate)
358 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000359 install_from<_VSTD::collate<char> >(one);
360 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000361 }
362 if (c & locale::ctype)
363 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000364 install_from<_VSTD::ctype<char> >(one);
365 install_from<_VSTD::ctype<wchar_t> >(one);
366 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
367 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
368 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
369 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000370 }
371 if (c & locale::monetary)
372 {
373 install_from<moneypunct<char, false> >(one);
374 install_from<moneypunct<char, true> >(one);
375 install_from<moneypunct<wchar_t, false> >(one);
376 install_from<moneypunct<wchar_t, true> >(one);
377 install_from<money_get<char> >(one);
378 install_from<money_get<wchar_t> >(one);
379 install_from<money_put<char> >(one);
380 install_from<money_put<wchar_t> >(one);
381 }
382 if (c & locale::numeric)
383 {
384 install_from<numpunct<char> >(one);
385 install_from<numpunct<wchar_t> >(one);
386 install_from<num_get<char> >(one);
387 install_from<num_get<wchar_t> >(one);
388 install_from<num_put<char> >(one);
389 install_from<num_put<wchar_t> >(one);
390 }
391 if (c & locale::time)
392 {
393 install_from<time_get<char> >(one);
394 install_from<time_get<wchar_t> >(one);
395 install_from<time_put<char> >(one);
396 install_from<time_put<wchar_t> >(one);
397 }
398 if (c & locale::messages)
399 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000400 install_from<_VSTD::messages<char> >(one);
401 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000402 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000403#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000404 }
405 catch (...)
406 {
407 for (unsigned i = 0; i < facets_.size(); ++i)
408 if (facets_[i])
409 facets_[i]->__release_shared();
410 throw;
411 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000412#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000413}
414
415locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000416 : facets_(max<size_t>(N, other.facets_.size()+1)),
417 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000418{
419 f->__add_shared();
420 unique_ptr<facet, release> hold(f);
421 facets_ = other.facets_;
422 for (unsigned i = 0; i < other.facets_.size(); ++i)
423 if (facets_[i])
424 facets_[i]->__add_shared();
425 install(hold.get(), id);
426}
427
428locale::__imp::~__imp()
429{
430 for (unsigned i = 0; i < facets_.size(); ++i)
431 if (facets_[i])
432 facets_[i]->__release_shared();
433}
434
435void
436locale::__imp::install(facet* f, long id)
437{
438 f->__add_shared();
439 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000440 if (static_cast<size_t>(id) >= facets_.size())
441 facets_.resize(static_cast<size_t>(id+1));
442 if (facets_[static_cast<size_t>(id)])
443 facets_[static_cast<size_t>(id)]->__release_shared();
444 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000445}
446
447const locale::facet*
448locale::__imp::use_facet(long id) const
449{
Howard Hinnantd4444702010-08-11 17:04:31 +0000450#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000451 if (!has_facet(id))
452 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000453#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000454 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000455}
456
457// locale
458
459const locale&
460locale::__imp::make_classic()
461{
462 // only one thread can get in here and it only gets in once
463 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000464 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000465 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000466 return *c;
467}
468
469const locale&
470locale::classic()
471{
472 static const locale& c = __imp::make_classic();
473 return c;
474}
475
476locale&
477locale::__imp::make_global()
478{
479 // only one thread can get in here and it only gets in once
480 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000481 ::new (&buf) locale(locale::classic());
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000482 return *reinterpret_cast<locale*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000483}
484
485locale&
486locale::__global()
487{
488 static locale& g = __imp::make_global();
489 return g;
490}
491
Howard Hinnantc9834542011-05-31 15:34:58 +0000492locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000493 : __locale_(__global().__locale_)
494{
495 __locale_->__add_shared();
496}
497
Howard Hinnantc9834542011-05-31 15:34:58 +0000498locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000499 : __locale_(l.__locale_)
500{
501 __locale_->__add_shared();
502}
503
Howard Hinnantc9834542011-05-31 15:34:58 +0000504locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000505{
506 __locale_->__release_shared();
507}
508
509const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000510locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000511{
512 other.__locale_->__add_shared();
513 __locale_->__release_shared();
514 __locale_ = other.__locale_;
515 return *this;
516}
517
518locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000519#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000520 : __locale_(name ? new __imp(name)
521 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000522#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000523 : __locale_(new __imp(name))
524#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000525{
526 __locale_->__add_shared();
527}
528
529locale::locale(const string& name)
530 : __locale_(new __imp(name))
531{
532 __locale_->__add_shared();
533}
534
535locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000536#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000537 : __locale_(name ? new __imp(*other.__locale_, name, c)
538 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000539#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000540 : __locale_(new __imp(*other.__locale_, name, c))
541#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000542{
543 __locale_->__add_shared();
544}
545
546locale::locale(const locale& other, const string& name, category c)
547 : __locale_(new __imp(*other.__locale_, name, c))
548{
549 __locale_->__add_shared();
550}
551
552locale::locale(const locale& other, const locale& one, category c)
553 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
554{
555 __locale_->__add_shared();
556}
557
558string
559locale::name() const
560{
561 return __locale_->name();
562}
563
564void
565locale::__install_ctor(const locale& other, facet* f, long id)
566{
567 if (f)
568 __locale_ = new __imp(*other.__locale_, f, id);
569 else
570 __locale_ = other.__locale_;
571 __locale_->__add_shared();
572}
573
574locale
575locale::global(const locale& loc)
576{
577 locale& g = __global();
578 locale r = g;
579 g = loc;
580 if (g.name() != "*")
581 setlocale(LC_ALL, g.name().c_str());
582 return r;
583}
584
585bool
586locale::has_facet(id& x) const
587{
588 return __locale_->has_facet(x.__get());
589}
590
591const locale::facet*
592locale::use_facet(id& x) const
593{
594 return __locale_->use_facet(x.__get());
595}
596
597bool
598locale::operator==(const locale& y) const
599{
600 return (__locale_ == y.__locale_)
601 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
602}
603
604// locale::facet
605
606locale::facet::~facet()
607{
608}
609
610void
Howard Hinnant1694d232011-05-28 14:41:13 +0000611locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000612{
613 delete this;
614}
615
616// locale::id
617
618int32_t locale::id::__next_id = 0;
619
620namespace
621{
622
623class __fake_bind
624{
625 locale::id* id_;
626 void (locale::id::* pmf_)();
627public:
628 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
629 : id_(id), pmf_(pmf) {}
630
631 void operator()() const
632 {
633 (id_->*pmf_)();
634 }
635};
636
637}
638
639long
640locale::id::__get()
641{
642 call_once(__flag_, __fake_bind(&locale::id::__init, this));
643 return __id_ - 1;
644}
645
646void
647locale::id::__init()
648{
Howard Hinnantadff4892010-05-24 17:49:41 +0000649 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000650}
651
652// template <> class collate_byname<char>
653
654collate_byname<char>::collate_byname(const char* n, size_t refs)
655 : collate<char>(refs),
656 __l(newlocale(LC_ALL_MASK, n, 0))
657{
Howard Hinnantd4444702010-08-11 17:04:31 +0000658#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000659 if (__l == 0)
660 throw runtime_error("collate_byname<char>::collate_byname"
661 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000662#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000663}
664
665collate_byname<char>::collate_byname(const string& name, size_t refs)
666 : collate<char>(refs),
667 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
668{
Howard Hinnantd4444702010-08-11 17:04:31 +0000669#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000670 if (__l == 0)
671 throw runtime_error("collate_byname<char>::collate_byname"
672 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000673#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000674}
675
676collate_byname<char>::~collate_byname()
677{
678 freelocale(__l);
679}
680
681int
682collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
683 const char_type* __lo2, const char_type* __hi2) const
684{
685 string_type lhs(__lo1, __hi1);
686 string_type rhs(__lo2, __hi2);
687 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
688 if (r < 0)
689 return -1;
690 if (r > 0)
691 return 1;
692 return r;
693}
694
695collate_byname<char>::string_type
696collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
697{
698 const string_type in(lo, hi);
699 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
700 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
701 return out;
702}
703
704// template <> class collate_byname<wchar_t>
705
706collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
707 : collate<wchar_t>(refs),
708 __l(newlocale(LC_ALL_MASK, n, 0))
709{
Howard Hinnantd4444702010-08-11 17:04:31 +0000710#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000711 if (__l == 0)
712 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
713 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000714#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000715}
716
717collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
718 : collate<wchar_t>(refs),
719 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
720{
Howard Hinnantd4444702010-08-11 17:04:31 +0000721#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000722 if (__l == 0)
723 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
724 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000725#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000726}
727
728collate_byname<wchar_t>::~collate_byname()
729{
730 freelocale(__l);
731}
732
733int
734collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
735 const char_type* __lo2, const char_type* __hi2) const
736{
737 string_type lhs(__lo1, __hi1);
738 string_type rhs(__lo2, __hi2);
739 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
740 if (r < 0)
741 return -1;
742 if (r > 0)
743 return 1;
744 return r;
745}
746
747collate_byname<wchar_t>::string_type
748collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
749{
750 const string_type in(lo, hi);
751 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
752 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
753 return out;
754}
755
756// template <> class ctype<wchar_t>;
757
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000758const ctype_base::mask ctype_base::space;
759const ctype_base::mask ctype_base::print;
760const ctype_base::mask ctype_base::cntrl;
761const ctype_base::mask ctype_base::upper;
762const ctype_base::mask ctype_base::lower;
763const ctype_base::mask ctype_base::alpha;
764const ctype_base::mask ctype_base::digit;
765const ctype_base::mask ctype_base::punct;
766const ctype_base::mask ctype_base::xdigit;
767const ctype_base::mask ctype_base::blank;
768const ctype_base::mask ctype_base::alnum;
769const ctype_base::mask ctype_base::graph;
770
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000771locale::id ctype<wchar_t>::id;
772
773ctype<wchar_t>::~ctype()
774{
775}
776
777bool
778ctype<wchar_t>::do_is(mask m, char_type c) const
779{
Marshall Clowa3645132013-10-21 15:07:28 +0000780 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000781}
782
783const wchar_t*
784ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
785{
786 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000787 *vec = static_cast<mask>(isascii(*low) ?
788 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000789 return low;
790}
791
792const wchar_t*
793ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
794{
795 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000796 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000797 break;
798 return low;
799}
800
801const wchar_t*
802ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
803{
804 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000805 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000806 break;
807 return low;
808}
809
810wchar_t
811ctype<wchar_t>::do_toupper(char_type c) const
812{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000813#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
814 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000815#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000816 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000817#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000818 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000819#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000820}
821
822const wchar_t*
823ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
824{
825 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000826#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
827 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000828#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000829 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
830 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000831#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000832 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000833#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000834 return low;
835}
836
837wchar_t
838ctype<wchar_t>::do_tolower(char_type c) const
839{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000840#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
841 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000842#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000843 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000844#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000845 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000846#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000847}
848
849const wchar_t*
850ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
851{
852 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000853#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
854 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000855#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000856 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
857 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000858#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000859 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000860#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000861 return low;
862}
863
864wchar_t
865ctype<wchar_t>::do_widen(char c) const
866{
867 return c;
868}
869
870const char*
871ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
872{
873 for (; low != high; ++low, ++dest)
874 *dest = *low;
875 return low;
876}
877
878char
879ctype<wchar_t>::do_narrow(char_type c, char dfault) const
880{
881 if (isascii(c))
882 return static_cast<char>(c);
883 return dfault;
884}
885
886const wchar_t*
887ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
888{
889 for (; low != high; ++low, ++dest)
890 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000891 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000892 else
893 *dest = dfault;
894 return low;
895}
896
897// template <> class ctype<char>;
898
899locale::id ctype<char>::id;
900
901ctype<char>::ctype(const mask* tab, bool del, size_t refs)
902 : locale::facet(refs),
903 __tab_(tab),
904 __del_(del)
905{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000906 if (__tab_ == 0)
907 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000908}
909
910ctype<char>::~ctype()
911{
912 if (__tab_ && __del_)
913 delete [] __tab_;
914}
915
916char
917ctype<char>::do_toupper(char_type c) const
918{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000919#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000920 return isascii(c) ?
921 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000922#elif defined(__NetBSD__)
923 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000924#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000925 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000926 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000927#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000928 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000929#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000930}
931
932const char*
933ctype<char>::do_toupper(char_type* low, const char_type* high) const
934{
935 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000936#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000937 *low = isascii(*low) ?
938 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000939#elif defined(__NetBSD__)
940 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000941#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000942 *low = isascii(*low) ?
943 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000944#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000945 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000946#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000947 return low;
948}
949
950char
951ctype<char>::do_tolower(char_type c) const
952{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000953#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000954 return isascii(c) ?
955 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000956#elif defined(__NetBSD__)
957 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000958#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Marshall Clow88c31902013-02-07 14:22:51 +0000959 return isascii(c) ?
960 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000961#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000962 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000963#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000964}
965
966const char*
967ctype<char>::do_tolower(char_type* low, const char_type* high) const
968{
969 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000970#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000971 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000972#elif defined(__NetBSD__)
973 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000974#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000975 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000976#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000977 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000978#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000979 return low;
980}
981
982char
983ctype<char>::do_widen(char c) const
984{
985 return c;
986}
987
988const char*
989ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
990{
991 for (; low != high; ++low, ++dest)
992 *dest = *low;
993 return low;
994}
995
996char
997ctype<char>::do_narrow(char_type c, char dfault) const
998{
999 if (isascii(c))
1000 return static_cast<char>(c);
1001 return dfault;
1002}
1003
1004const char*
1005ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1006{
1007 for (; low != high; ++low, ++dest)
1008 if (isascii(*low))
1009 *dest = *low;
1010 else
1011 *dest = dfault;
1012 return low;
1013}
1014
Marshall Clow2ccffef2013-11-19 18:05:03 +00001015#ifdef __EMSCRIPTEN__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001016extern "C" const unsigned short ** __ctype_b_loc();
1017extern "C" const int ** __ctype_tolower_loc();
1018extern "C" const int ** __ctype_toupper_loc();
1019#endif
1020
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001021const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001022ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001023{
David Chisnallc512df12011-09-21 08:39:44 +00001024#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001026#elif defined(__NetBSD__)
1027 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001028#elif defined(__GLIBC__)
1029 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001030#elif __sun__
1031 return __ctype_mask;
Howard Hinnantef5aa932013-09-17 01:34:47 +00001032#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001033 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001034// This is assumed to be safe, which is a nonsense assumption because we're
1035// going to end up dereferencing it later...
Marshall Clow2ccffef2013-11-19 18:05:03 +00001036#elif defined(__EMSCRIPTEN__)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001037 return *__ctype_b_loc();
Howard Hinnant7f764502013-08-14 18:00:20 +00001038#elif defined(_AIX)
Marshall Clow016d4e82013-11-19 19:16:03 +00001039 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Dan Albert2517f4f2014-04-17 17:42:46 -07001040#elif defined(__ANDROID__)
Dan Albert5d148832014-07-31 21:04:08 +00001041 return reinterpret_cast<const unsigned char*>(_ctype_) + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001042#else
David Chisnall997e4542012-02-29 13:05:08 +00001043 // Platform not supported: abort so the person doing the port knows what to
1044 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001045# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001046 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001047 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001048 return NULL;
1049#endif
1050}
1051
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001052#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001053const int*
1054ctype<char>::__classic_lower_table() _NOEXCEPT
1055{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001056 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001057}
1058
1059const int*
1060ctype<char>::__classic_upper_table() _NOEXCEPT
1061{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001062 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001063}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001064#elif __NetBSD__
1065const short*
1066ctype<char>::__classic_lower_table() _NOEXCEPT
1067{
1068 return _C_tolower_tab_ + 1;
1069}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001070
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001071const short*
1072ctype<char>::__classic_upper_table() _NOEXCEPT
1073{
1074 return _C_toupper_tab_ + 1;
1075}
1076
Marshall Clow2ccffef2013-11-19 18:05:03 +00001077#elif defined(__EMSCRIPTEN__)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001078const int*
1079ctype<char>::__classic_lower_table() _NOEXCEPT
1080{
1081 return *__ctype_tolower_loc();
1082}
1083
1084const int*
1085ctype<char>::__classic_upper_table() _NOEXCEPT
1086{
1087 return *__ctype_toupper_loc();
1088}
Marshall Clow2ccffef2013-11-19 18:05:03 +00001089#endif // __GLIBC__ || __EMSCRIPTEN__ || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001090
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001091// template <> class ctype_byname<char>
1092
1093ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1094 : ctype<char>(0, false, refs),
1095 __l(newlocale(LC_ALL_MASK, name, 0))
1096{
Howard Hinnantd4444702010-08-11 17:04:31 +00001097#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001098 if (__l == 0)
1099 throw runtime_error("ctype_byname<char>::ctype_byname"
1100 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001101#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001102}
1103
1104ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1105 : ctype<char>(0, false, refs),
1106 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1107{
Howard Hinnantd4444702010-08-11 17:04:31 +00001108#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001109 if (__l == 0)
1110 throw runtime_error("ctype_byname<char>::ctype_byname"
1111 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001112#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001113}
1114
1115ctype_byname<char>::~ctype_byname()
1116{
1117 freelocale(__l);
1118}
1119
1120char
1121ctype_byname<char>::do_toupper(char_type c) const
1122{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001123 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001124}
1125
1126const char*
1127ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1128{
1129 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001130 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001131 return low;
1132}
1133
1134char
1135ctype_byname<char>::do_tolower(char_type c) const
1136{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001137 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001138}
1139
1140const char*
1141ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1142{
1143 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001144 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001145 return low;
1146}
1147
1148// template <> class ctype_byname<wchar_t>
1149
1150ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1151 : ctype<wchar_t>(refs),
1152 __l(newlocale(LC_ALL_MASK, name, 0))
1153{
Howard Hinnantd4444702010-08-11 17:04:31 +00001154#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001155 if (__l == 0)
1156 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1157 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001158#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001159}
1160
1161ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1162 : ctype<wchar_t>(refs),
1163 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1164{
Howard Hinnantd4444702010-08-11 17:04:31 +00001165#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001166 if (__l == 0)
1167 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1168 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001169#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001170}
1171
1172ctype_byname<wchar_t>::~ctype_byname()
1173{
1174 freelocale(__l);
1175}
1176
1177bool
1178ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1179{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001180#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001181 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001182#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001183 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001184 wint_t ch = static_cast<wint_t>(c);
1185 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1186 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1187 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1188 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1189 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1190 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1191 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1192 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1193 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1194 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001195 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001196#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001197}
1198
1199const wchar_t*
1200ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1201{
1202 for (; low != high; ++low, ++vec)
1203 {
1204 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001205 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001206 else
1207 {
1208 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001209 wint_t ch = static_cast<wint_t>(*low);
1210 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001211 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001212 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001213 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001214 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001215 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001216 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001217 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001218 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001219 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001220 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001221 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001222 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001223 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001224 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001225 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001226 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001227 *vec |= xdigit;
1228 }
1229 }
1230 return low;
1231}
1232
1233const wchar_t*
1234ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1235{
1236 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001237 {
1238#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001239 if (iswctype_l(*low, m, __l))
1240 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001241#else
Marshall Clow88c31902013-02-07 14:22:51 +00001242 wint_t ch = static_cast<wint_t>(*low);
1243 if (m & space && iswspace_l(ch, __l)) break;
1244 if (m & print && iswprint_l(ch, __l)) break;
1245 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1246 if (m & upper && iswupper_l(ch, __l)) break;
1247 if (m & lower && iswlower_l(ch, __l)) break;
1248 if (m & alpha && iswalpha_l(ch, __l)) break;
1249 if (m & digit && iswdigit_l(ch, __l)) break;
1250 if (m & punct && iswpunct_l(ch, __l)) break;
1251 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1252 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001253#endif
1254 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001255 return low;
1256}
1257
1258const wchar_t*
1259ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1260{
1261 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001262 {
1263#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001264 if (!iswctype_l(*low, m, __l))
1265 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001266#else
Marshall Clow88c31902013-02-07 14:22:51 +00001267 wint_t ch = static_cast<wint_t>(*low);
1268 if (m & space && iswspace_l(ch, __l)) continue;
1269 if (m & print && iswprint_l(ch, __l)) continue;
1270 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1271 if (m & upper && iswupper_l(ch, __l)) continue;
1272 if (m & lower && iswlower_l(ch, __l)) continue;
1273 if (m & alpha && iswalpha_l(ch, __l)) continue;
1274 if (m & digit && iswdigit_l(ch, __l)) continue;
1275 if (m & punct && iswpunct_l(ch, __l)) continue;
1276 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1277 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001278 break;
1279#endif
1280 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001281 return low;
1282}
1283
1284wchar_t
1285ctype_byname<wchar_t>::do_toupper(char_type c) const
1286{
1287 return towupper_l(c, __l);
1288}
1289
1290const wchar_t*
1291ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1292{
1293 for (; low != high; ++low)
1294 *low = towupper_l(*low, __l);
1295 return low;
1296}
1297
1298wchar_t
1299ctype_byname<wchar_t>::do_tolower(char_type c) const
1300{
1301 return towlower_l(c, __l);
1302}
1303
1304const wchar_t*
1305ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1306{
1307 for (; low != high; ++low)
1308 *low = towlower_l(*low, __l);
1309 return low;
1310}
1311
1312wchar_t
1313ctype_byname<wchar_t>::do_widen(char c) const
1314{
Howard Hinnant866569b2011-09-28 23:39:33 +00001315#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001316 return btowc_l(c, __l);
1317#else
1318 return __btowc_l(c, __l);
1319#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001320}
1321
1322const char*
1323ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1324{
1325 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001326#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001327 *dest = btowc_l(*low, __l);
1328#else
1329 *dest = __btowc_l(*low, __l);
1330#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001331 return low;
1332}
1333
1334char
1335ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1336{
Howard Hinnant866569b2011-09-28 23:39:33 +00001337#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001338 int r = wctob_l(c, __l);
1339#else
1340 int r = __wctob_l(c, __l);
1341#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001342 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001343}
1344
1345const wchar_t*
1346ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1347{
1348 for (; low != high; ++low, ++dest)
1349 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001350#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001351 int r = wctob_l(*low, __l);
1352#else
1353 int r = __wctob_l(*low, __l);
1354#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001355 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001356 }
1357 return low;
1358}
1359
1360// template <> class codecvt<char, char, mbstate_t>
1361
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001362locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001363
1364codecvt<char, char, mbstate_t>::~codecvt()
1365{
1366}
1367
1368codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001369codecvt<char, char, mbstate_t>::do_out(state_type&,
1370 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001371 extern_type* to, extern_type*, extern_type*& to_nxt) const
1372{
1373 frm_nxt = frm;
1374 to_nxt = to;
1375 return noconv;
1376}
1377
1378codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001379codecvt<char, char, mbstate_t>::do_in(state_type&,
1380 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001381 intern_type* to, intern_type*, intern_type*& to_nxt) const
1382{
1383 frm_nxt = frm;
1384 to_nxt = to;
1385 return noconv;
1386}
1387
1388codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001389codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001390 extern_type* to, extern_type*, extern_type*& to_nxt) const
1391{
1392 to_nxt = to;
1393 return noconv;
1394}
1395
1396int
Howard Hinnantc9834542011-05-31 15:34:58 +00001397codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001398{
1399 return 1;
1400}
1401
1402bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001403codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001404{
1405 return true;
1406}
1407
1408int
1409codecvt<char, char, mbstate_t>::do_length(state_type&,
1410 const extern_type* frm, const extern_type* end, size_t mx) const
1411{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001412 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001413}
1414
1415int
Howard Hinnantc9834542011-05-31 15:34:58 +00001416codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001417{
1418 return 1;
1419}
1420
1421// template <> class codecvt<wchar_t, char, mbstate_t>
1422
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001423locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001424
1425codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1426 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001427 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001428{
1429}
1430
1431codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1432 : locale::facet(refs),
1433 __l(newlocale(LC_ALL_MASK, nm, 0))
1434{
Howard Hinnantd4444702010-08-11 17:04:31 +00001435#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001436 if (__l == 0)
1437 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1438 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001439#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001440}
1441
1442codecvt<wchar_t, char, mbstate_t>::~codecvt()
1443{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001444 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001445 freelocale(__l);
1446}
1447
1448codecvt<wchar_t, char, mbstate_t>::result
1449codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001450 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001451 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1452{
1453 // look for first internal null in frm
1454 const intern_type* fend = frm;
1455 for (; fend != frm_end; ++fend)
1456 if (*fend == 0)
1457 break;
1458 // loop over all null-terminated sequences in frm
1459 to_nxt = to;
1460 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1461 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001462 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001463 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001464#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001465 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1466 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001467#else
1468 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1469#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001470 if (n == size_t(-1))
1471 {
1472 // need to recover to_nxt
1473 for (to_nxt = to; frm != frm_nxt; ++frm)
1474 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001475#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001476 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1477#else
1478 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1479#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001480 if (n == size_t(-1))
1481 break;
1482 to_nxt += n;
1483 }
1484 frm_nxt = frm;
1485 return error;
1486 }
1487 if (n == 0)
1488 return partial;
1489 to_nxt += n;
1490 if (to_nxt == to_end)
1491 break;
1492 if (fend != frm_end) // set up next null terminated sequence
1493 {
1494 // Try to write the terminating null
1495 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001496#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001497 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1498#else
1499 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1500#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001501 if (n == size_t(-1)) // on error
1502 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001503 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001504 return partial;
1505 for (extern_type* p = tmp; n; --n) // write it
1506 *to_nxt++ = *p++;
1507 ++frm_nxt;
1508 // look for next null in frm
1509 for (fend = frm_nxt; fend != frm_end; ++fend)
1510 if (*fend == 0)
1511 break;
1512 }
1513 }
1514 return frm_nxt == frm_end ? ok : partial;
1515}
1516
1517codecvt<wchar_t, char, mbstate_t>::result
1518codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001519 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001520 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1521{
1522 // look for first internal null in frm
1523 const extern_type* fend = frm;
1524 for (; fend != frm_end; ++fend)
1525 if (*fend == 0)
1526 break;
1527 // loop over all null-terminated sequences in frm
1528 to_nxt = to;
1529 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1530 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001531 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001533#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001534 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1535 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001536#else
1537 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1538#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001539 if (n == size_t(-1))
1540 {
1541 // need to recover to_nxt
1542 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1543 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001544#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001545 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1546 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001547#else
1548 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1549#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001550 switch (n)
1551 {
1552 case 0:
1553 ++frm;
1554 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001555 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001556 frm_nxt = frm;
1557 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001558 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001559 frm_nxt = frm;
1560 return partial;
1561 default:
1562 frm += n;
1563 break;
1564 }
1565 }
1566 frm_nxt = frm;
1567 return frm_nxt == frm_end ? ok : partial;
1568 }
1569 if (n == 0)
1570 return error;
1571 to_nxt += n;
1572 if (to_nxt == to_end)
1573 break;
1574 if (fend != frm_end) // set up next null terminated sequence
1575 {
1576 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001577#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001578 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1579#else
1580 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1581#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001582 if (n != 0) // on error
1583 return error;
1584 ++to_nxt;
1585 ++frm_nxt;
1586 // look for next null in frm
1587 for (fend = frm_nxt; fend != frm_end; ++fend)
1588 if (*fend == 0)
1589 break;
1590 }
1591 }
1592 return frm_nxt == frm_end ? ok : partial;
1593}
1594
1595codecvt<wchar_t, char, mbstate_t>::result
1596codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1597 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1598{
1599 to_nxt = to;
1600 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001601#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001602 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1603#else
1604 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1605#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001606 if (n == size_t(-1) || n == 0) // on error
1607 return error;
1608 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001609 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001610 return partial;
1611 for (extern_type* p = tmp; n; --n) // write it
1612 *to_nxt++ = *p++;
1613 return ok;
1614}
1615
1616int
Howard Hinnantc9834542011-05-31 15:34:58 +00001617codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001618{
Howard Hinnant866569b2011-09-28 23:39:33 +00001619#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001620 if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001621#else
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001622 if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001623#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001624 {
1625 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001626#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001627 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1628#else
1629 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1630#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001631 return 1; // which take more than 1 char to form a wchar_t
1632 return 0;
1633 }
1634 return -1;
1635}
1636
1637bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001638codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001639{
1640 return false;
1641}
1642
1643int
1644codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1645 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1646{
1647 int nbytes = 0;
1648 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1649 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001650#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001651 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001652#else
1653 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1654#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001655 switch (n)
1656 {
1657 case 0:
1658 ++nbytes;
1659 ++frm;
1660 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001661 case size_t(-1):
1662 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001663 return nbytes;
1664 default:
1665 nbytes += n;
1666 frm += n;
1667 break;
1668 }
1669 }
1670 return nbytes;
1671}
1672
1673int
Howard Hinnantc9834542011-05-31 15:34:58 +00001674codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001675{
Howard Hinnant866569b2011-09-28 23:39:33 +00001676#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001677 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001678#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001679 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001680#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001681}
1682
1683// Valid UTF ranges
1684// UTF-32 UTF-16 UTF-8 # of code points
1685// first second first second third fourth
1686// 000000 - 00007F 0000 - 007F 00 - 7F 127
1687// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1688// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1689// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1690// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1691// 00D800 - 00DFFF invalid
1692// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1693// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1694// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1695// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1696
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001697static
1698codecvt_base::result
1699utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1700 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1701 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1702{
1703 frm_nxt = frm;
1704 to_nxt = to;
1705 if (mode & generate_header)
1706 {
1707 if (to_end-to_nxt < 3)
1708 return codecvt_base::partial;
1709 *to_nxt++ = static_cast<uint8_t>(0xEF);
1710 *to_nxt++ = static_cast<uint8_t>(0xBB);
1711 *to_nxt++ = static_cast<uint8_t>(0xBF);
1712 }
1713 for (; frm_nxt < frm_end; ++frm_nxt)
1714 {
1715 uint16_t wc1 = *frm_nxt;
1716 if (wc1 > Maxcode)
1717 return codecvt_base::error;
1718 if (wc1 < 0x0080)
1719 {
1720 if (to_end-to_nxt < 1)
1721 return codecvt_base::partial;
1722 *to_nxt++ = static_cast<uint8_t>(wc1);
1723 }
1724 else if (wc1 < 0x0800)
1725 {
1726 if (to_end-to_nxt < 2)
1727 return codecvt_base::partial;
1728 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1729 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1730 }
1731 else if (wc1 < 0xD800)
1732 {
1733 if (to_end-to_nxt < 3)
1734 return codecvt_base::partial;
1735 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1736 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1737 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1738 }
1739 else if (wc1 < 0xDC00)
1740 {
1741 if (frm_end-frm_nxt < 2)
1742 return codecvt_base::partial;
1743 uint16_t wc2 = frm_nxt[1];
1744 if ((wc2 & 0xFC00) != 0xDC00)
1745 return codecvt_base::error;
1746 if (to_end-to_nxt < 4)
1747 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001748 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1749 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001750 return codecvt_base::error;
1751 ++frm_nxt;
1752 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1753 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1754 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1755 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1756 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1757 }
1758 else if (wc1 < 0xE000)
1759 {
1760 return codecvt_base::error;
1761 }
1762 else
1763 {
1764 if (to_end-to_nxt < 3)
1765 return codecvt_base::partial;
1766 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1767 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1768 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1769 }
1770 }
1771 return codecvt_base::ok;
1772}
1773
1774static
1775codecvt_base::result
1776utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1777 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1778 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1779{
1780 frm_nxt = frm;
1781 to_nxt = to;
1782 if (mode & generate_header)
1783 {
1784 if (to_end-to_nxt < 3)
1785 return codecvt_base::partial;
1786 *to_nxt++ = static_cast<uint8_t>(0xEF);
1787 *to_nxt++ = static_cast<uint8_t>(0xBB);
1788 *to_nxt++ = static_cast<uint8_t>(0xBF);
1789 }
1790 for (; frm_nxt < frm_end; ++frm_nxt)
1791 {
1792 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1793 if (wc1 > Maxcode)
1794 return codecvt_base::error;
1795 if (wc1 < 0x0080)
1796 {
1797 if (to_end-to_nxt < 1)
1798 return codecvt_base::partial;
1799 *to_nxt++ = static_cast<uint8_t>(wc1);
1800 }
1801 else if (wc1 < 0x0800)
1802 {
1803 if (to_end-to_nxt < 2)
1804 return codecvt_base::partial;
1805 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1806 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1807 }
1808 else if (wc1 < 0xD800)
1809 {
1810 if (to_end-to_nxt < 3)
1811 return codecvt_base::partial;
1812 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1813 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1814 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1815 }
1816 else if (wc1 < 0xDC00)
1817 {
1818 if (frm_end-frm_nxt < 2)
1819 return codecvt_base::partial;
1820 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1821 if ((wc2 & 0xFC00) != 0xDC00)
1822 return codecvt_base::error;
1823 if (to_end-to_nxt < 4)
1824 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001825 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1826 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001827 return codecvt_base::error;
1828 ++frm_nxt;
1829 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1830 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1831 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1832 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1833 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1834 }
1835 else if (wc1 < 0xE000)
1836 {
1837 return codecvt_base::error;
1838 }
1839 else
1840 {
1841 if (to_end-to_nxt < 3)
1842 return codecvt_base::partial;
1843 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1844 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1845 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1846 }
1847 }
1848 return codecvt_base::ok;
1849}
1850
1851static
1852codecvt_base::result
1853utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1854 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1855 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1856{
1857 frm_nxt = frm;
1858 to_nxt = to;
1859 if (mode & consume_header)
1860 {
1861 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1862 frm_nxt[2] == 0xBF)
1863 frm_nxt += 3;
1864 }
1865 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1866 {
1867 uint8_t c1 = *frm_nxt;
1868 if (c1 > Maxcode)
1869 return codecvt_base::error;
1870 if (c1 < 0x80)
1871 {
1872 *to_nxt = static_cast<uint16_t>(c1);
1873 ++frm_nxt;
1874 }
1875 else if (c1 < 0xC2)
1876 {
1877 return codecvt_base::error;
1878 }
1879 else if (c1 < 0xE0)
1880 {
1881 if (frm_end-frm_nxt < 2)
1882 return codecvt_base::partial;
1883 uint8_t c2 = frm_nxt[1];
1884 if ((c2 & 0xC0) != 0x80)
1885 return codecvt_base::error;
1886 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1887 if (t > Maxcode)
1888 return codecvt_base::error;
1889 *to_nxt = t;
1890 frm_nxt += 2;
1891 }
1892 else if (c1 < 0xF0)
1893 {
1894 if (frm_end-frm_nxt < 3)
1895 return codecvt_base::partial;
1896 uint8_t c2 = frm_nxt[1];
1897 uint8_t c3 = frm_nxt[2];
1898 switch (c1)
1899 {
1900 case 0xE0:
1901 if ((c2 & 0xE0) != 0xA0)
1902 return codecvt_base::error;
1903 break;
1904 case 0xED:
1905 if ((c2 & 0xE0) != 0x80)
1906 return codecvt_base::error;
1907 break;
1908 default:
1909 if ((c2 & 0xC0) != 0x80)
1910 return codecvt_base::error;
1911 break;
1912 }
1913 if ((c3 & 0xC0) != 0x80)
1914 return codecvt_base::error;
1915 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1916 | ((c2 & 0x3F) << 6)
1917 | (c3 & 0x3F));
1918 if (t > Maxcode)
1919 return codecvt_base::error;
1920 *to_nxt = t;
1921 frm_nxt += 3;
1922 }
1923 else if (c1 < 0xF5)
1924 {
1925 if (frm_end-frm_nxt < 4)
1926 return codecvt_base::partial;
1927 uint8_t c2 = frm_nxt[1];
1928 uint8_t c3 = frm_nxt[2];
1929 uint8_t c4 = frm_nxt[3];
1930 switch (c1)
1931 {
1932 case 0xF0:
1933 if (!(0x90 <= c2 && c2 <= 0xBF))
1934 return codecvt_base::error;
1935 break;
1936 case 0xF4:
1937 if ((c2 & 0xF0) != 0x80)
1938 return codecvt_base::error;
1939 break;
1940 default:
1941 if ((c2 & 0xC0) != 0x80)
1942 return codecvt_base::error;
1943 break;
1944 }
1945 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1946 return codecvt_base::error;
1947 if (to_end-to_nxt < 2)
1948 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001949 if ((((c1 & 7UL) << 18) +
1950 ((c2 & 0x3FUL) << 12) +
1951 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001952 return codecvt_base::error;
1953 *to_nxt = static_cast<uint16_t>(
1954 0xD800
1955 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1956 | ((c2 & 0x0F) << 2)
1957 | ((c3 & 0x30) >> 4));
1958 *++to_nxt = static_cast<uint16_t>(
1959 0xDC00
1960 | ((c3 & 0x0F) << 6)
1961 | (c4 & 0x3F));
1962 frm_nxt += 4;
1963 }
1964 else
1965 {
1966 return codecvt_base::error;
1967 }
1968 }
1969 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1970}
1971
1972static
1973codecvt_base::result
1974utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1975 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1976 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1977{
1978 frm_nxt = frm;
1979 to_nxt = to;
1980 if (mode & consume_header)
1981 {
1982 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1983 frm_nxt[2] == 0xBF)
1984 frm_nxt += 3;
1985 }
1986 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1987 {
1988 uint8_t c1 = *frm_nxt;
1989 if (c1 > Maxcode)
1990 return codecvt_base::error;
1991 if (c1 < 0x80)
1992 {
1993 *to_nxt = static_cast<uint32_t>(c1);
1994 ++frm_nxt;
1995 }
1996 else if (c1 < 0xC2)
1997 {
1998 return codecvt_base::error;
1999 }
2000 else if (c1 < 0xE0)
2001 {
2002 if (frm_end-frm_nxt < 2)
2003 return codecvt_base::partial;
2004 uint8_t c2 = frm_nxt[1];
2005 if ((c2 & 0xC0) != 0x80)
2006 return codecvt_base::error;
2007 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2008 if (t > Maxcode)
2009 return codecvt_base::error;
2010 *to_nxt = static_cast<uint32_t>(t);
2011 frm_nxt += 2;
2012 }
2013 else if (c1 < 0xF0)
2014 {
2015 if (frm_end-frm_nxt < 3)
2016 return codecvt_base::partial;
2017 uint8_t c2 = frm_nxt[1];
2018 uint8_t c3 = frm_nxt[2];
2019 switch (c1)
2020 {
2021 case 0xE0:
2022 if ((c2 & 0xE0) != 0xA0)
2023 return codecvt_base::error;
2024 break;
2025 case 0xED:
2026 if ((c2 & 0xE0) != 0x80)
2027 return codecvt_base::error;
2028 break;
2029 default:
2030 if ((c2 & 0xC0) != 0x80)
2031 return codecvt_base::error;
2032 break;
2033 }
2034 if ((c3 & 0xC0) != 0x80)
2035 return codecvt_base::error;
2036 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2037 | ((c2 & 0x3F) << 6)
2038 | (c3 & 0x3F));
2039 if (t > Maxcode)
2040 return codecvt_base::error;
2041 *to_nxt = static_cast<uint32_t>(t);
2042 frm_nxt += 3;
2043 }
2044 else if (c1 < 0xF5)
2045 {
2046 if (frm_end-frm_nxt < 4)
2047 return codecvt_base::partial;
2048 uint8_t c2 = frm_nxt[1];
2049 uint8_t c3 = frm_nxt[2];
2050 uint8_t c4 = frm_nxt[3];
2051 switch (c1)
2052 {
2053 case 0xF0:
2054 if (!(0x90 <= c2 && c2 <= 0xBF))
2055 return codecvt_base::error;
2056 break;
2057 case 0xF4:
2058 if ((c2 & 0xF0) != 0x80)
2059 return codecvt_base::error;
2060 break;
2061 default:
2062 if ((c2 & 0xC0) != 0x80)
2063 return codecvt_base::error;
2064 break;
2065 }
2066 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2067 return codecvt_base::error;
2068 if (to_end-to_nxt < 2)
2069 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002070 if ((((c1 & 7UL) << 18) +
2071 ((c2 & 0x3FUL) << 12) +
2072 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002073 return codecvt_base::error;
2074 *to_nxt = static_cast<uint32_t>(
2075 0xD800
2076 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2077 | ((c2 & 0x0F) << 2)
2078 | ((c3 & 0x30) >> 4));
2079 *++to_nxt = static_cast<uint32_t>(
2080 0xDC00
2081 | ((c3 & 0x0F) << 6)
2082 | (c4 & 0x3F));
2083 frm_nxt += 4;
2084 }
2085 else
2086 {
2087 return codecvt_base::error;
2088 }
2089 }
2090 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2091}
2092
2093static
2094int
2095utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2096 size_t mx, unsigned long Maxcode = 0x10FFFF,
2097 codecvt_mode mode = codecvt_mode(0))
2098{
2099 const uint8_t* frm_nxt = frm;
2100 if (mode & consume_header)
2101 {
2102 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2103 frm_nxt[2] == 0xBF)
2104 frm_nxt += 3;
2105 }
2106 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2107 {
2108 uint8_t c1 = *frm_nxt;
2109 if (c1 > Maxcode)
2110 break;
2111 if (c1 < 0x80)
2112 {
2113 ++frm_nxt;
2114 }
2115 else if (c1 < 0xC2)
2116 {
2117 break;
2118 }
2119 else if (c1 < 0xE0)
2120 {
2121 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2122 break;
2123 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2124 if (t > Maxcode)
2125 break;
2126 frm_nxt += 2;
2127 }
2128 else if (c1 < 0xF0)
2129 {
2130 if (frm_end-frm_nxt < 3)
2131 break;
2132 uint8_t c2 = frm_nxt[1];
2133 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002134 switch (c1)
2135 {
2136 case 0xE0:
2137 if ((c2 & 0xE0) != 0xA0)
2138 return static_cast<int>(frm_nxt - frm);
2139 break;
2140 case 0xED:
2141 if ((c2 & 0xE0) != 0x80)
2142 return static_cast<int>(frm_nxt - frm);
2143 break;
2144 default:
2145 if ((c2 & 0xC0) != 0x80)
2146 return static_cast<int>(frm_nxt - frm);
2147 break;
2148 }
2149 if ((c3 & 0xC0) != 0x80)
2150 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002151 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002152 break;
2153 frm_nxt += 3;
2154 }
2155 else if (c1 < 0xF5)
2156 {
2157 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2158 break;
2159 uint8_t c2 = frm_nxt[1];
2160 uint8_t c3 = frm_nxt[2];
2161 uint8_t c4 = frm_nxt[3];
2162 switch (c1)
2163 {
2164 case 0xF0:
2165 if (!(0x90 <= c2 && c2 <= 0xBF))
2166 return static_cast<int>(frm_nxt - frm);
2167 break;
2168 case 0xF4:
2169 if ((c2 & 0xF0) != 0x80)
2170 return static_cast<int>(frm_nxt - frm);
2171 break;
2172 default:
2173 if ((c2 & 0xC0) != 0x80)
2174 return static_cast<int>(frm_nxt - frm);
2175 break;
2176 }
2177 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2178 break;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002179 if ((((c1 & 7UL) << 18) +
2180 ((c2 & 0x3FUL) << 12) +
2181 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002182 break;
2183 ++nchar16_t;
2184 frm_nxt += 4;
2185 }
2186 else
2187 {
2188 break;
2189 }
2190 }
2191 return static_cast<int>(frm_nxt - frm);
2192}
2193
2194static
2195codecvt_base::result
2196ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2197 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2198 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2199{
2200 frm_nxt = frm;
2201 to_nxt = to;
2202 if (mode & generate_header)
2203 {
2204 if (to_end-to_nxt < 3)
2205 return codecvt_base::partial;
2206 *to_nxt++ = static_cast<uint8_t>(0xEF);
2207 *to_nxt++ = static_cast<uint8_t>(0xBB);
2208 *to_nxt++ = static_cast<uint8_t>(0xBF);
2209 }
2210 for (; frm_nxt < frm_end; ++frm_nxt)
2211 {
2212 uint32_t wc = *frm_nxt;
2213 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2214 return codecvt_base::error;
2215 if (wc < 0x000080)
2216 {
2217 if (to_end-to_nxt < 1)
2218 return codecvt_base::partial;
2219 *to_nxt++ = static_cast<uint8_t>(wc);
2220 }
2221 else if (wc < 0x000800)
2222 {
2223 if (to_end-to_nxt < 2)
2224 return codecvt_base::partial;
2225 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2226 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2227 }
2228 else if (wc < 0x010000)
2229 {
2230 if (to_end-to_nxt < 3)
2231 return codecvt_base::partial;
2232 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2233 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2234 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2235 }
2236 else // if (wc < 0x110000)
2237 {
2238 if (to_end-to_nxt < 4)
2239 return codecvt_base::partial;
2240 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2241 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2242 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2243 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2244 }
2245 }
2246 return codecvt_base::ok;
2247}
2248
2249static
2250codecvt_base::result
2251utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2252 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2253 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2254{
2255 frm_nxt = frm;
2256 to_nxt = to;
2257 if (mode & consume_header)
2258 {
2259 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2260 frm_nxt[2] == 0xBF)
2261 frm_nxt += 3;
2262 }
2263 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2264 {
2265 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2266 if (c1 < 0x80)
2267 {
2268 if (c1 > Maxcode)
2269 return codecvt_base::error;
2270 *to_nxt = static_cast<uint32_t>(c1);
2271 ++frm_nxt;
2272 }
2273 else if (c1 < 0xC2)
2274 {
2275 return codecvt_base::error;
2276 }
2277 else if (c1 < 0xE0)
2278 {
2279 if (frm_end-frm_nxt < 2)
2280 return codecvt_base::partial;
2281 uint8_t c2 = frm_nxt[1];
2282 if ((c2 & 0xC0) != 0x80)
2283 return codecvt_base::error;
2284 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2285 | (c2 & 0x3F));
2286 if (t > Maxcode)
2287 return codecvt_base::error;
2288 *to_nxt = t;
2289 frm_nxt += 2;
2290 }
2291 else if (c1 < 0xF0)
2292 {
2293 if (frm_end-frm_nxt < 3)
2294 return codecvt_base::partial;
2295 uint8_t c2 = frm_nxt[1];
2296 uint8_t c3 = frm_nxt[2];
2297 switch (c1)
2298 {
2299 case 0xE0:
2300 if ((c2 & 0xE0) != 0xA0)
2301 return codecvt_base::error;
2302 break;
2303 case 0xED:
2304 if ((c2 & 0xE0) != 0x80)
2305 return codecvt_base::error;
2306 break;
2307 default:
2308 if ((c2 & 0xC0) != 0x80)
2309 return codecvt_base::error;
2310 break;
2311 }
2312 if ((c3 & 0xC0) != 0x80)
2313 return codecvt_base::error;
2314 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2315 | ((c2 & 0x3F) << 6)
2316 | (c3 & 0x3F));
2317 if (t > Maxcode)
2318 return codecvt_base::error;
2319 *to_nxt = t;
2320 frm_nxt += 3;
2321 }
2322 else if (c1 < 0xF5)
2323 {
2324 if (frm_end-frm_nxt < 4)
2325 return codecvt_base::partial;
2326 uint8_t c2 = frm_nxt[1];
2327 uint8_t c3 = frm_nxt[2];
2328 uint8_t c4 = frm_nxt[3];
2329 switch (c1)
2330 {
2331 case 0xF0:
2332 if (!(0x90 <= c2 && c2 <= 0xBF))
2333 return codecvt_base::error;
2334 break;
2335 case 0xF4:
2336 if ((c2 & 0xF0) != 0x80)
2337 return codecvt_base::error;
2338 break;
2339 default:
2340 if ((c2 & 0xC0) != 0x80)
2341 return codecvt_base::error;
2342 break;
2343 }
2344 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2345 return codecvt_base::error;
2346 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2347 | ((c2 & 0x3F) << 12)
2348 | ((c3 & 0x3F) << 6)
2349 | (c4 & 0x3F));
2350 if (t > Maxcode)
2351 return codecvt_base::error;
2352 *to_nxt = t;
2353 frm_nxt += 4;
2354 }
2355 else
2356 {
2357 return codecvt_base::error;
2358 }
2359 }
2360 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2361}
2362
2363static
2364int
2365utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2366 size_t mx, unsigned long Maxcode = 0x10FFFF,
2367 codecvt_mode mode = codecvt_mode(0))
2368{
2369 const uint8_t* frm_nxt = frm;
2370 if (mode & consume_header)
2371 {
2372 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2373 frm_nxt[2] == 0xBF)
2374 frm_nxt += 3;
2375 }
2376 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2377 {
2378 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2379 if (c1 < 0x80)
2380 {
2381 if (c1 > Maxcode)
2382 break;
2383 ++frm_nxt;
2384 }
2385 else if (c1 < 0xC2)
2386 {
2387 break;
2388 }
2389 else if (c1 < 0xE0)
2390 {
2391 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2392 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002393 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002394 break;
2395 frm_nxt += 2;
2396 }
2397 else if (c1 < 0xF0)
2398 {
2399 if (frm_end-frm_nxt < 3)
2400 break;
2401 uint8_t c2 = frm_nxt[1];
2402 uint8_t c3 = frm_nxt[2];
2403 switch (c1)
2404 {
2405 case 0xE0:
2406 if ((c2 & 0xE0) != 0xA0)
2407 return static_cast<int>(frm_nxt - frm);
2408 break;
2409 case 0xED:
2410 if ((c2 & 0xE0) != 0x80)
2411 return static_cast<int>(frm_nxt - frm);
2412 break;
2413 default:
2414 if ((c2 & 0xC0) != 0x80)
2415 return static_cast<int>(frm_nxt - frm);
2416 break;
2417 }
2418 if ((c3 & 0xC0) != 0x80)
2419 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002420 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002421 break;
2422 frm_nxt += 3;
2423 }
2424 else if (c1 < 0xF5)
2425 {
2426 if (frm_end-frm_nxt < 4)
2427 break;
2428 uint8_t c2 = frm_nxt[1];
2429 uint8_t c3 = frm_nxt[2];
2430 uint8_t c4 = frm_nxt[3];
2431 switch (c1)
2432 {
2433 case 0xF0:
2434 if (!(0x90 <= c2 && c2 <= 0xBF))
2435 return static_cast<int>(frm_nxt - frm);
2436 break;
2437 case 0xF4:
2438 if ((c2 & 0xF0) != 0x80)
2439 return static_cast<int>(frm_nxt - frm);
2440 break;
2441 default:
2442 if ((c2 & 0xC0) != 0x80)
2443 return static_cast<int>(frm_nxt - frm);
2444 break;
2445 }
2446 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2447 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002448 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2449 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002450 break;
2451 frm_nxt += 4;
2452 }
2453 else
2454 {
2455 break;
2456 }
2457 }
2458 return static_cast<int>(frm_nxt - frm);
2459}
2460
2461static
2462codecvt_base::result
2463ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2464 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2465 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2466{
2467 frm_nxt = frm;
2468 to_nxt = to;
2469 if (mode & generate_header)
2470 {
2471 if (to_end-to_nxt < 3)
2472 return codecvt_base::partial;
2473 *to_nxt++ = static_cast<uint8_t>(0xEF);
2474 *to_nxt++ = static_cast<uint8_t>(0xBB);
2475 *to_nxt++ = static_cast<uint8_t>(0xBF);
2476 }
2477 for (; frm_nxt < frm_end; ++frm_nxt)
2478 {
2479 uint16_t wc = *frm_nxt;
2480 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2481 return codecvt_base::error;
2482 if (wc < 0x0080)
2483 {
2484 if (to_end-to_nxt < 1)
2485 return codecvt_base::partial;
2486 *to_nxt++ = static_cast<uint8_t>(wc);
2487 }
2488 else if (wc < 0x0800)
2489 {
2490 if (to_end-to_nxt < 2)
2491 return codecvt_base::partial;
2492 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2493 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2494 }
2495 else // if (wc <= 0xFFFF)
2496 {
2497 if (to_end-to_nxt < 3)
2498 return codecvt_base::partial;
2499 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2500 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2501 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2502 }
2503 }
2504 return codecvt_base::ok;
2505}
2506
2507static
2508codecvt_base::result
2509utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2510 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2511 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2512{
2513 frm_nxt = frm;
2514 to_nxt = to;
2515 if (mode & consume_header)
2516 {
2517 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2518 frm_nxt[2] == 0xBF)
2519 frm_nxt += 3;
2520 }
2521 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2522 {
2523 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2524 if (c1 < 0x80)
2525 {
2526 if (c1 > Maxcode)
2527 return codecvt_base::error;
2528 *to_nxt = static_cast<uint16_t>(c1);
2529 ++frm_nxt;
2530 }
2531 else if (c1 < 0xC2)
2532 {
2533 return codecvt_base::error;
2534 }
2535 else if (c1 < 0xE0)
2536 {
2537 if (frm_end-frm_nxt < 2)
2538 return codecvt_base::partial;
2539 uint8_t c2 = frm_nxt[1];
2540 if ((c2 & 0xC0) != 0x80)
2541 return codecvt_base::error;
2542 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2543 | (c2 & 0x3F));
2544 if (t > Maxcode)
2545 return codecvt_base::error;
2546 *to_nxt = t;
2547 frm_nxt += 2;
2548 }
2549 else if (c1 < 0xF0)
2550 {
2551 if (frm_end-frm_nxt < 3)
2552 return codecvt_base::partial;
2553 uint8_t c2 = frm_nxt[1];
2554 uint8_t c3 = frm_nxt[2];
2555 switch (c1)
2556 {
2557 case 0xE0:
2558 if ((c2 & 0xE0) != 0xA0)
2559 return codecvt_base::error;
2560 break;
2561 case 0xED:
2562 if ((c2 & 0xE0) != 0x80)
2563 return codecvt_base::error;
2564 break;
2565 default:
2566 if ((c2 & 0xC0) != 0x80)
2567 return codecvt_base::error;
2568 break;
2569 }
2570 if ((c3 & 0xC0) != 0x80)
2571 return codecvt_base::error;
2572 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2573 | ((c2 & 0x3F) << 6)
2574 | (c3 & 0x3F));
2575 if (t > Maxcode)
2576 return codecvt_base::error;
2577 *to_nxt = t;
2578 frm_nxt += 3;
2579 }
2580 else
2581 {
2582 return codecvt_base::error;
2583 }
2584 }
2585 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2586}
2587
2588static
2589int
2590utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2591 size_t mx, unsigned long Maxcode = 0x10FFFF,
2592 codecvt_mode mode = codecvt_mode(0))
2593{
2594 const uint8_t* frm_nxt = frm;
2595 if (mode & consume_header)
2596 {
2597 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2598 frm_nxt[2] == 0xBF)
2599 frm_nxt += 3;
2600 }
2601 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2602 {
2603 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2604 if (c1 < 0x80)
2605 {
2606 if (c1 > Maxcode)
2607 break;
2608 ++frm_nxt;
2609 }
2610 else if (c1 < 0xC2)
2611 {
2612 break;
2613 }
2614 else if (c1 < 0xE0)
2615 {
2616 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2617 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002618 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002619 break;
2620 frm_nxt += 2;
2621 }
2622 else if (c1 < 0xF0)
2623 {
2624 if (frm_end-frm_nxt < 3)
2625 break;
2626 uint8_t c2 = frm_nxt[1];
2627 uint8_t c3 = frm_nxt[2];
2628 switch (c1)
2629 {
2630 case 0xE0:
2631 if ((c2 & 0xE0) != 0xA0)
2632 return static_cast<int>(frm_nxt - frm);
2633 break;
2634 case 0xED:
2635 if ((c2 & 0xE0) != 0x80)
2636 return static_cast<int>(frm_nxt - frm);
2637 break;
2638 default:
2639 if ((c2 & 0xC0) != 0x80)
2640 return static_cast<int>(frm_nxt - frm);
2641 break;
2642 }
2643 if ((c3 & 0xC0) != 0x80)
2644 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002645 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002646 break;
2647 frm_nxt += 3;
2648 }
2649 else
2650 {
2651 break;
2652 }
2653 }
2654 return static_cast<int>(frm_nxt - frm);
2655}
2656
2657static
2658codecvt_base::result
2659ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2660 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2661 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2662{
2663 frm_nxt = frm;
2664 to_nxt = to;
2665 if (mode & generate_header)
2666 {
2667 if (to_end-to_nxt < 2)
2668 return codecvt_base::partial;
2669 *to_nxt++ = static_cast<uint8_t>(0xFE);
2670 *to_nxt++ = static_cast<uint8_t>(0xFF);
2671 }
2672 for (; frm_nxt < frm_end; ++frm_nxt)
2673 {
2674 uint32_t wc = *frm_nxt;
2675 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2676 return codecvt_base::error;
2677 if (wc < 0x010000)
2678 {
2679 if (to_end-to_nxt < 2)
2680 return codecvt_base::partial;
2681 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2682 *to_nxt++ = static_cast<uint8_t>(wc);
2683 }
2684 else
2685 {
2686 if (to_end-to_nxt < 4)
2687 return codecvt_base::partial;
2688 uint16_t t = static_cast<uint16_t>(
2689 0xD800
2690 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2691 | ((wc & 0x00FC00) >> 10));
2692 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2693 *to_nxt++ = static_cast<uint8_t>(t);
2694 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2695 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2696 *to_nxt++ = static_cast<uint8_t>(t);
2697 }
2698 }
2699 return codecvt_base::ok;
2700}
2701
2702static
2703codecvt_base::result
2704utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2705 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2706 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2707{
2708 frm_nxt = frm;
2709 to_nxt = to;
2710 if (mode & consume_header)
2711 {
2712 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2713 frm_nxt += 2;
2714 }
2715 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2716 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002717 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002718 if ((c1 & 0xFC00) == 0xDC00)
2719 return codecvt_base::error;
2720 if ((c1 & 0xFC00) != 0xD800)
2721 {
2722 if (c1 > Maxcode)
2723 return codecvt_base::error;
2724 *to_nxt = static_cast<uint32_t>(c1);
2725 frm_nxt += 2;
2726 }
2727 else
2728 {
2729 if (frm_end-frm_nxt < 4)
2730 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002731 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002732 if ((c2 & 0xFC00) != 0xDC00)
2733 return codecvt_base::error;
2734 uint32_t t = static_cast<uint32_t>(
2735 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2736 | ((c1 & 0x003F) << 10)
2737 | (c2 & 0x03FF));
2738 if (t > Maxcode)
2739 return codecvt_base::error;
2740 *to_nxt = t;
2741 frm_nxt += 4;
2742 }
2743 }
2744 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2745}
2746
2747static
2748int
2749utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2750 size_t mx, unsigned long Maxcode = 0x10FFFF,
2751 codecvt_mode mode = codecvt_mode(0))
2752{
2753 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002754 if (mode & consume_header)
2755 {
2756 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2757 frm_nxt += 2;
2758 }
2759 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2760 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002761 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002762 if ((c1 & 0xFC00) == 0xDC00)
2763 break;
2764 if ((c1 & 0xFC00) != 0xD800)
2765 {
2766 if (c1 > Maxcode)
2767 break;
2768 frm_nxt += 2;
2769 }
2770 else
2771 {
2772 if (frm_end-frm_nxt < 4)
2773 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002774 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002775 if ((c2 & 0xFC00) != 0xDC00)
2776 break;
2777 uint32_t t = static_cast<uint32_t>(
2778 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2779 | ((c1 & 0x003F) << 10)
2780 | (c2 & 0x03FF));
2781 if (t > Maxcode)
2782 break;
2783 frm_nxt += 4;
2784 }
2785 }
2786 return static_cast<int>(frm_nxt - frm);
2787}
2788
2789static
2790codecvt_base::result
2791ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2792 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2793 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2794{
2795 frm_nxt = frm;
2796 to_nxt = to;
2797 if (mode & generate_header)
2798 {
2799 if (to_end-to_nxt < 2)
2800 return codecvt_base::partial;
2801 *to_nxt++ = static_cast<uint8_t>(0xFF);
2802 *to_nxt++ = static_cast<uint8_t>(0xFE);
2803 }
2804 for (; frm_nxt < frm_end; ++frm_nxt)
2805 {
2806 uint32_t wc = *frm_nxt;
2807 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2808 return codecvt_base::error;
2809 if (wc < 0x010000)
2810 {
2811 if (to_end-to_nxt < 2)
2812 return codecvt_base::partial;
2813 *to_nxt++ = static_cast<uint8_t>(wc);
2814 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2815 }
2816 else
2817 {
2818 if (to_end-to_nxt < 4)
2819 return codecvt_base::partial;
2820 uint16_t t = static_cast<uint16_t>(
2821 0xD800
2822 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2823 | ((wc & 0x00FC00) >> 10));
2824 *to_nxt++ = static_cast<uint8_t>(t);
2825 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2826 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2827 *to_nxt++ = static_cast<uint8_t>(t);
2828 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2829 }
2830 }
2831 return codecvt_base::ok;
2832}
2833
2834static
2835codecvt_base::result
2836utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2837 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2838 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2839{
2840 frm_nxt = frm;
2841 to_nxt = to;
2842 if (mode & consume_header)
2843 {
2844 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2845 frm_nxt += 2;
2846 }
2847 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2848 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002849 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002850 if ((c1 & 0xFC00) == 0xDC00)
2851 return codecvt_base::error;
2852 if ((c1 & 0xFC00) != 0xD800)
2853 {
2854 if (c1 > Maxcode)
2855 return codecvt_base::error;
2856 *to_nxt = static_cast<uint32_t>(c1);
2857 frm_nxt += 2;
2858 }
2859 else
2860 {
2861 if (frm_end-frm_nxt < 4)
2862 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002863 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002864 if ((c2 & 0xFC00) != 0xDC00)
2865 return codecvt_base::error;
2866 uint32_t t = static_cast<uint32_t>(
2867 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2868 | ((c1 & 0x003F) << 10)
2869 | (c2 & 0x03FF));
2870 if (t > Maxcode)
2871 return codecvt_base::error;
2872 *to_nxt = t;
2873 frm_nxt += 4;
2874 }
2875 }
2876 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2877}
2878
2879static
2880int
2881utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2882 size_t mx, unsigned long Maxcode = 0x10FFFF,
2883 codecvt_mode mode = codecvt_mode(0))
2884{
2885 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002886 if (mode & consume_header)
2887 {
2888 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2889 frm_nxt += 2;
2890 }
2891 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2892 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002893 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002894 if ((c1 & 0xFC00) == 0xDC00)
2895 break;
2896 if ((c1 & 0xFC00) != 0xD800)
2897 {
2898 if (c1 > Maxcode)
2899 break;
2900 frm_nxt += 2;
2901 }
2902 else
2903 {
2904 if (frm_end-frm_nxt < 4)
2905 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002906 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002907 if ((c2 & 0xFC00) != 0xDC00)
2908 break;
2909 uint32_t t = static_cast<uint32_t>(
2910 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2911 | ((c1 & 0x003F) << 10)
2912 | (c2 & 0x03FF));
2913 if (t > Maxcode)
2914 break;
2915 frm_nxt += 4;
2916 }
2917 }
2918 return static_cast<int>(frm_nxt - frm);
2919}
2920
2921static
2922codecvt_base::result
2923ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2924 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2925 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2926{
2927 frm_nxt = frm;
2928 to_nxt = to;
2929 if (mode & generate_header)
2930 {
2931 if (to_end-to_nxt < 2)
2932 return codecvt_base::partial;
2933 *to_nxt++ = static_cast<uint8_t>(0xFE);
2934 *to_nxt++ = static_cast<uint8_t>(0xFF);
2935 }
2936 for (; frm_nxt < frm_end; ++frm_nxt)
2937 {
2938 uint16_t wc = *frm_nxt;
2939 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2940 return codecvt_base::error;
2941 if (to_end-to_nxt < 2)
2942 return codecvt_base::partial;
2943 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2944 *to_nxt++ = static_cast<uint8_t>(wc);
2945 }
2946 return codecvt_base::ok;
2947}
2948
2949static
2950codecvt_base::result
2951utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2952 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2953 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2954{
2955 frm_nxt = frm;
2956 to_nxt = to;
2957 if (mode & consume_header)
2958 {
2959 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2960 frm_nxt += 2;
2961 }
2962 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2963 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002964 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002965 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2966 return codecvt_base::error;
2967 *to_nxt = c1;
2968 frm_nxt += 2;
2969 }
2970 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2971}
2972
2973static
2974int
2975utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2976 size_t mx, unsigned long Maxcode = 0x10FFFF,
2977 codecvt_mode mode = codecvt_mode(0))
2978{
2979 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002980 if (mode & consume_header)
2981 {
2982 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2983 frm_nxt += 2;
2984 }
2985 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2986 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002987 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002988 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2989 break;
2990 frm_nxt += 2;
2991 }
2992 return static_cast<int>(frm_nxt - frm);
2993}
2994
2995static
2996codecvt_base::result
2997ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2998 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2999 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3000{
3001 frm_nxt = frm;
3002 to_nxt = to;
3003 if (mode & generate_header)
3004 {
3005 if (to_end-to_nxt < 2)
3006 return codecvt_base::partial;
3007 *to_nxt++ = static_cast<uint8_t>(0xFF);
3008 *to_nxt++ = static_cast<uint8_t>(0xFE);
3009 }
3010 for (; frm_nxt < frm_end; ++frm_nxt)
3011 {
3012 uint16_t wc = *frm_nxt;
3013 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3014 return codecvt_base::error;
3015 if (to_end-to_nxt < 2)
3016 return codecvt_base::partial;
3017 *to_nxt++ = static_cast<uint8_t>(wc);
3018 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3019 }
3020 return codecvt_base::ok;
3021}
3022
3023static
3024codecvt_base::result
3025utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3026 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3027 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3028{
3029 frm_nxt = frm;
3030 to_nxt = to;
3031 if (mode & consume_header)
3032 {
3033 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3034 frm_nxt += 2;
3035 }
3036 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3037 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003038 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003039 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3040 return codecvt_base::error;
3041 *to_nxt = c1;
3042 frm_nxt += 2;
3043 }
3044 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3045}
3046
3047static
3048int
3049utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3050 size_t mx, unsigned long Maxcode = 0x10FFFF,
3051 codecvt_mode mode = codecvt_mode(0))
3052{
3053 const uint8_t* frm_nxt = frm;
3054 frm_nxt = frm;
3055 if (mode & consume_header)
3056 {
3057 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3058 frm_nxt += 2;
3059 }
3060 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3061 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003062 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003063 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3064 break;
3065 frm_nxt += 2;
3066 }
3067 return static_cast<int>(frm_nxt - frm);
3068}
3069
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003070// template <> class codecvt<char16_t, char, mbstate_t>
3071
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003072locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003073
3074codecvt<char16_t, char, mbstate_t>::~codecvt()
3075{
3076}
3077
3078codecvt<char16_t, char, mbstate_t>::result
3079codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003080 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003081 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3082{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003083 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3084 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3085 const uint16_t* _frm_nxt = _frm;
3086 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3087 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3088 uint8_t* _to_nxt = _to;
3089 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3090 frm_nxt = frm + (_frm_nxt - _frm);
3091 to_nxt = to + (_to_nxt - _to);
3092 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003093}
3094
3095codecvt<char16_t, char, mbstate_t>::result
3096codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003097 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003098 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3099{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003100 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3101 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3102 const uint8_t* _frm_nxt = _frm;
3103 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3104 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3105 uint16_t* _to_nxt = _to;
3106 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3107 frm_nxt = frm + (_frm_nxt - _frm);
3108 to_nxt = to + (_to_nxt - _to);
3109 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003110}
3111
3112codecvt<char16_t, char, mbstate_t>::result
3113codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3114 extern_type* to, extern_type*, extern_type*& to_nxt) const
3115{
3116 to_nxt = to;
3117 return noconv;
3118}
3119
3120int
Howard Hinnantc9834542011-05-31 15:34:58 +00003121codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003122{
3123 return 0;
3124}
3125
3126bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003127codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003128{
3129 return false;
3130}
3131
3132int
3133codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3134 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3135{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003136 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3137 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3138 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003139}
3140
3141int
Howard Hinnantc9834542011-05-31 15:34:58 +00003142codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003143{
3144 return 4;
3145}
3146
3147// template <> class codecvt<char32_t, char, mbstate_t>
3148
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003149locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003150
3151codecvt<char32_t, char, mbstate_t>::~codecvt()
3152{
3153}
3154
3155codecvt<char32_t, char, mbstate_t>::result
3156codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003157 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003158 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3159{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003160 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3161 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3162 const uint32_t* _frm_nxt = _frm;
3163 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3164 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3165 uint8_t* _to_nxt = _to;
3166 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3167 frm_nxt = frm + (_frm_nxt - _frm);
3168 to_nxt = to + (_to_nxt - _to);
3169 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003170}
3171
3172codecvt<char32_t, char, mbstate_t>::result
3173codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003174 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003175 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3176{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003177 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3178 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3179 const uint8_t* _frm_nxt = _frm;
3180 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3181 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3182 uint32_t* _to_nxt = _to;
3183 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3184 frm_nxt = frm + (_frm_nxt - _frm);
3185 to_nxt = to + (_to_nxt - _to);
3186 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003187}
3188
3189codecvt<char32_t, char, mbstate_t>::result
3190codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3191 extern_type* to, extern_type*, extern_type*& to_nxt) const
3192{
3193 to_nxt = to;
3194 return noconv;
3195}
3196
3197int
Howard Hinnantc9834542011-05-31 15:34:58 +00003198codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003199{
3200 return 0;
3201}
3202
3203bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003204codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003205{
3206 return false;
3207}
3208
3209int
3210codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3211 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3212{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003213 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3214 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3215 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003216}
3217
3218int
Howard Hinnantc9834542011-05-31 15:34:58 +00003219codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003220{
3221 return 4;
3222}
3223
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003224// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003225
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003226__codecvt_utf8<wchar_t>::result
3227__codecvt_utf8<wchar_t>::do_out(state_type&,
3228 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003229 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3230{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003231#if _WIN32
3232 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3233 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3234 const uint16_t* _frm_nxt = _frm;
3235#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003236 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3237 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3238 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003239#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003240 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3241 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3242 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003243#if _WIN32
3244 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3245 _Maxcode_, _Mode_);
3246#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003247 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3248 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003249#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003250 frm_nxt = frm + (_frm_nxt - _frm);
3251 to_nxt = to + (_to_nxt - _to);
3252 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003253}
3254
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003255__codecvt_utf8<wchar_t>::result
3256__codecvt_utf8<wchar_t>::do_in(state_type&,
3257 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003258 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3259{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003260 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3261 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3262 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003263#if _WIN32
3264 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3265 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3266 uint16_t* _to_nxt = _to;
3267 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3268 _Maxcode_, _Mode_);
3269#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003270 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3271 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3272 uint32_t* _to_nxt = _to;
3273 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3274 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003275#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003276 frm_nxt = frm + (_frm_nxt - _frm);
3277 to_nxt = to + (_to_nxt - _to);
3278 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003279}
3280
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003281__codecvt_utf8<wchar_t>::result
3282__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003283 extern_type* to, extern_type*, extern_type*& to_nxt) const
3284{
3285 to_nxt = to;
3286 return noconv;
3287}
3288
3289int
Howard Hinnantc9834542011-05-31 15:34:58 +00003290__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003291{
3292 return 0;
3293}
3294
3295bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003296__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003297{
3298 return false;
3299}
3300
3301int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003302__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003303 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3304{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003305 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3306 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3307 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003308}
3309
3310int
Howard Hinnantc9834542011-05-31 15:34:58 +00003311__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003312{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003313 if (_Mode_ & consume_header)
3314 return 7;
3315 return 4;
3316}
3317
3318// __codecvt_utf8<char16_t>
3319
3320__codecvt_utf8<char16_t>::result
3321__codecvt_utf8<char16_t>::do_out(state_type&,
3322 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3323 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3324{
3325 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3326 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3327 const uint16_t* _frm_nxt = _frm;
3328 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3329 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3330 uint8_t* _to_nxt = _to;
3331 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3332 _Maxcode_, _Mode_);
3333 frm_nxt = frm + (_frm_nxt - _frm);
3334 to_nxt = to + (_to_nxt - _to);
3335 return r;
3336}
3337
3338__codecvt_utf8<char16_t>::result
3339__codecvt_utf8<char16_t>::do_in(state_type&,
3340 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3341 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3342{
3343 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3344 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3345 const uint8_t* _frm_nxt = _frm;
3346 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3347 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3348 uint16_t* _to_nxt = _to;
3349 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3350 _Maxcode_, _Mode_);
3351 frm_nxt = frm + (_frm_nxt - _frm);
3352 to_nxt = to + (_to_nxt - _to);
3353 return r;
3354}
3355
3356__codecvt_utf8<char16_t>::result
3357__codecvt_utf8<char16_t>::do_unshift(state_type&,
3358 extern_type* to, extern_type*, extern_type*& to_nxt) const
3359{
3360 to_nxt = to;
3361 return noconv;
3362}
3363
3364int
Howard Hinnantc9834542011-05-31 15:34:58 +00003365__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003366{
3367 return 0;
3368}
3369
3370bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003371__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003372{
3373 return false;
3374}
3375
3376int
3377__codecvt_utf8<char16_t>::do_length(state_type&,
3378 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3379{
3380 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3381 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3382 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3383}
3384
3385int
Howard Hinnantc9834542011-05-31 15:34:58 +00003386__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003387{
3388 if (_Mode_ & consume_header)
3389 return 6;
3390 return 3;
3391}
3392
3393// __codecvt_utf8<char32_t>
3394
3395__codecvt_utf8<char32_t>::result
3396__codecvt_utf8<char32_t>::do_out(state_type&,
3397 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3398 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3399{
3400 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3401 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3402 const uint32_t* _frm_nxt = _frm;
3403 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3404 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3405 uint8_t* _to_nxt = _to;
3406 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3407 _Maxcode_, _Mode_);
3408 frm_nxt = frm + (_frm_nxt - _frm);
3409 to_nxt = to + (_to_nxt - _to);
3410 return r;
3411}
3412
3413__codecvt_utf8<char32_t>::result
3414__codecvt_utf8<char32_t>::do_in(state_type&,
3415 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3416 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3417{
3418 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3419 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3420 const uint8_t* _frm_nxt = _frm;
3421 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3422 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3423 uint32_t* _to_nxt = _to;
3424 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3425 _Maxcode_, _Mode_);
3426 frm_nxt = frm + (_frm_nxt - _frm);
3427 to_nxt = to + (_to_nxt - _to);
3428 return r;
3429}
3430
3431__codecvt_utf8<char32_t>::result
3432__codecvt_utf8<char32_t>::do_unshift(state_type&,
3433 extern_type* to, extern_type*, extern_type*& to_nxt) const
3434{
3435 to_nxt = to;
3436 return noconv;
3437}
3438
3439int
Howard Hinnantc9834542011-05-31 15:34:58 +00003440__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003441{
3442 return 0;
3443}
3444
3445bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003446__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003447{
3448 return false;
3449}
3450
3451int
3452__codecvt_utf8<char32_t>::do_length(state_type&,
3453 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3454{
3455 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3456 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3457 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3458}
3459
3460int
Howard Hinnantc9834542011-05-31 15:34:58 +00003461__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003462{
3463 if (_Mode_ & consume_header)
3464 return 7;
3465 return 4;
3466}
3467
3468// __codecvt_utf16<wchar_t, false>
3469
3470__codecvt_utf16<wchar_t, false>::result
3471__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3472 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3473 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3474{
3475 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3476 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3477 const uint32_t* _frm_nxt = _frm;
3478 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3479 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3480 uint8_t* _to_nxt = _to;
3481 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3482 _Maxcode_, _Mode_);
3483 frm_nxt = frm + (_frm_nxt - _frm);
3484 to_nxt = to + (_to_nxt - _to);
3485 return r;
3486}
3487
3488__codecvt_utf16<wchar_t, false>::result
3489__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3490 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3491 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3492{
3493 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3494 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3495 const uint8_t* _frm_nxt = _frm;
3496 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3497 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3498 uint32_t* _to_nxt = _to;
3499 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3500 _Maxcode_, _Mode_);
3501 frm_nxt = frm + (_frm_nxt - _frm);
3502 to_nxt = to + (_to_nxt - _to);
3503 return r;
3504}
3505
3506__codecvt_utf16<wchar_t, false>::result
3507__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3508 extern_type* to, extern_type*, extern_type*& to_nxt) const
3509{
3510 to_nxt = to;
3511 return noconv;
3512}
3513
3514int
Howard Hinnantc9834542011-05-31 15:34:58 +00003515__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003516{
3517 return 0;
3518}
3519
3520bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003521__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003522{
3523 return false;
3524}
3525
3526int
3527__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3528 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3529{
3530 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3531 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3532 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3533}
3534
3535int
Howard Hinnantc9834542011-05-31 15:34:58 +00003536__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003537{
3538 if (_Mode_ & consume_header)
3539 return 6;
3540 return 4;
3541}
3542
3543// __codecvt_utf16<wchar_t, true>
3544
3545__codecvt_utf16<wchar_t, true>::result
3546__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3547 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3548 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3549{
3550 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3551 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3552 const uint32_t* _frm_nxt = _frm;
3553 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3554 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3555 uint8_t* _to_nxt = _to;
3556 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3557 _Maxcode_, _Mode_);
3558 frm_nxt = frm + (_frm_nxt - _frm);
3559 to_nxt = to + (_to_nxt - _to);
3560 return r;
3561}
3562
3563__codecvt_utf16<wchar_t, true>::result
3564__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3565 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3566 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3567{
3568 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3569 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3570 const uint8_t* _frm_nxt = _frm;
3571 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3572 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3573 uint32_t* _to_nxt = _to;
3574 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3575 _Maxcode_, _Mode_);
3576 frm_nxt = frm + (_frm_nxt - _frm);
3577 to_nxt = to + (_to_nxt - _to);
3578 return r;
3579}
3580
3581__codecvt_utf16<wchar_t, true>::result
3582__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3583 extern_type* to, extern_type*, extern_type*& to_nxt) const
3584{
3585 to_nxt = to;
3586 return noconv;
3587}
3588
3589int
Howard Hinnantc9834542011-05-31 15:34:58 +00003590__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003591{
3592 return 0;
3593}
3594
3595bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003596__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003597{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003598 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003599}
3600
3601int
3602__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3603 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3604{
3605 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3606 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3607 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3608}
3609
3610int
Howard Hinnantc9834542011-05-31 15:34:58 +00003611__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003612{
3613 if (_Mode_ & consume_header)
3614 return 6;
3615 return 4;
3616}
3617
3618// __codecvt_utf16<char16_t, false>
3619
3620__codecvt_utf16<char16_t, false>::result
3621__codecvt_utf16<char16_t, false>::do_out(state_type&,
3622 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3623 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3624{
3625 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3626 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3627 const uint16_t* _frm_nxt = _frm;
3628 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3629 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3630 uint8_t* _to_nxt = _to;
3631 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3632 _Maxcode_, _Mode_);
3633 frm_nxt = frm + (_frm_nxt - _frm);
3634 to_nxt = to + (_to_nxt - _to);
3635 return r;
3636}
3637
3638__codecvt_utf16<char16_t, false>::result
3639__codecvt_utf16<char16_t, false>::do_in(state_type&,
3640 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3641 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3642{
3643 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3644 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3645 const uint8_t* _frm_nxt = _frm;
3646 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3647 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3648 uint16_t* _to_nxt = _to;
3649 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3650 _Maxcode_, _Mode_);
3651 frm_nxt = frm + (_frm_nxt - _frm);
3652 to_nxt = to + (_to_nxt - _to);
3653 return r;
3654}
3655
3656__codecvt_utf16<char16_t, false>::result
3657__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3658 extern_type* to, extern_type*, extern_type*& to_nxt) const
3659{
3660 to_nxt = to;
3661 return noconv;
3662}
3663
3664int
Howard Hinnantc9834542011-05-31 15:34:58 +00003665__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003666{
3667 return 0;
3668}
3669
3670bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003671__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003672{
3673 return false;
3674}
3675
3676int
3677__codecvt_utf16<char16_t, false>::do_length(state_type&,
3678 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3679{
3680 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3681 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3682 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3683}
3684
3685int
Howard Hinnantc9834542011-05-31 15:34:58 +00003686__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003687{
3688 if (_Mode_ & consume_header)
3689 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003690 return 2;
3691}
3692
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003693// __codecvt_utf16<char16_t, true>
3694
3695__codecvt_utf16<char16_t, true>::result
3696__codecvt_utf16<char16_t, true>::do_out(state_type&,
3697 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3698 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3699{
3700 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3701 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3702 const uint16_t* _frm_nxt = _frm;
3703 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3704 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3705 uint8_t* _to_nxt = _to;
3706 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3707 _Maxcode_, _Mode_);
3708 frm_nxt = frm + (_frm_nxt - _frm);
3709 to_nxt = to + (_to_nxt - _to);
3710 return r;
3711}
3712
3713__codecvt_utf16<char16_t, true>::result
3714__codecvt_utf16<char16_t, true>::do_in(state_type&,
3715 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3716 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3717{
3718 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3719 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3720 const uint8_t* _frm_nxt = _frm;
3721 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3722 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3723 uint16_t* _to_nxt = _to;
3724 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3725 _Maxcode_, _Mode_);
3726 frm_nxt = frm + (_frm_nxt - _frm);
3727 to_nxt = to + (_to_nxt - _to);
3728 return r;
3729}
3730
3731__codecvt_utf16<char16_t, true>::result
3732__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3733 extern_type* to, extern_type*, extern_type*& to_nxt) const
3734{
3735 to_nxt = to;
3736 return noconv;
3737}
3738
3739int
Howard Hinnantc9834542011-05-31 15:34:58 +00003740__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003741{
3742 return 0;
3743}
3744
3745bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003746__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003747{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003748 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003749}
3750
3751int
3752__codecvt_utf16<char16_t, true>::do_length(state_type&,
3753 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3754{
3755 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3756 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3757 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3758}
3759
3760int
Howard Hinnantc9834542011-05-31 15:34:58 +00003761__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003762{
3763 if (_Mode_ & consume_header)
3764 return 4;
3765 return 2;
3766}
3767
3768// __codecvt_utf16<char32_t, false>
3769
3770__codecvt_utf16<char32_t, false>::result
3771__codecvt_utf16<char32_t, false>::do_out(state_type&,
3772 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3773 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3774{
3775 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3776 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3777 const uint32_t* _frm_nxt = _frm;
3778 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3779 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3780 uint8_t* _to_nxt = _to;
3781 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3782 _Maxcode_, _Mode_);
3783 frm_nxt = frm + (_frm_nxt - _frm);
3784 to_nxt = to + (_to_nxt - _to);
3785 return r;
3786}
3787
3788__codecvt_utf16<char32_t, false>::result
3789__codecvt_utf16<char32_t, false>::do_in(state_type&,
3790 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3791 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3792{
3793 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3794 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3795 const uint8_t* _frm_nxt = _frm;
3796 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3797 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3798 uint32_t* _to_nxt = _to;
3799 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3800 _Maxcode_, _Mode_);
3801 frm_nxt = frm + (_frm_nxt - _frm);
3802 to_nxt = to + (_to_nxt - _to);
3803 return r;
3804}
3805
3806__codecvt_utf16<char32_t, false>::result
3807__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3808 extern_type* to, extern_type*, extern_type*& to_nxt) const
3809{
3810 to_nxt = to;
3811 return noconv;
3812}
3813
3814int
Howard Hinnantc9834542011-05-31 15:34:58 +00003815__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003816{
3817 return 0;
3818}
3819
3820bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003821__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003822{
3823 return false;
3824}
3825
3826int
3827__codecvt_utf16<char32_t, false>::do_length(state_type&,
3828 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3829{
3830 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3831 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3832 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3833}
3834
3835int
Howard Hinnantc9834542011-05-31 15:34:58 +00003836__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003837{
3838 if (_Mode_ & consume_header)
3839 return 6;
3840 return 4;
3841}
3842
3843// __codecvt_utf16<char32_t, true>
3844
3845__codecvt_utf16<char32_t, true>::result
3846__codecvt_utf16<char32_t, true>::do_out(state_type&,
3847 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3848 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3849{
3850 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3851 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3852 const uint32_t* _frm_nxt = _frm;
3853 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3854 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3855 uint8_t* _to_nxt = _to;
3856 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3857 _Maxcode_, _Mode_);
3858 frm_nxt = frm + (_frm_nxt - _frm);
3859 to_nxt = to + (_to_nxt - _to);
3860 return r;
3861}
3862
3863__codecvt_utf16<char32_t, true>::result
3864__codecvt_utf16<char32_t, true>::do_in(state_type&,
3865 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3866 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3867{
3868 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3869 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3870 const uint8_t* _frm_nxt = _frm;
3871 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3872 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3873 uint32_t* _to_nxt = _to;
3874 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3875 _Maxcode_, _Mode_);
3876 frm_nxt = frm + (_frm_nxt - _frm);
3877 to_nxt = to + (_to_nxt - _to);
3878 return r;
3879}
3880
3881__codecvt_utf16<char32_t, true>::result
3882__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3883 extern_type* to, extern_type*, extern_type*& to_nxt) const
3884{
3885 to_nxt = to;
3886 return noconv;
3887}
3888
3889int
Howard Hinnantc9834542011-05-31 15:34:58 +00003890__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003891{
3892 return 0;
3893}
3894
3895bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003896__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003897{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003898 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003899}
3900
3901int
3902__codecvt_utf16<char32_t, true>::do_length(state_type&,
3903 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3904{
3905 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3906 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3907 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3908}
3909
3910int
Howard Hinnantc9834542011-05-31 15:34:58 +00003911__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003912{
3913 if (_Mode_ & consume_header)
3914 return 6;
3915 return 4;
3916}
3917
3918// __codecvt_utf8_utf16<wchar_t>
3919
3920__codecvt_utf8_utf16<wchar_t>::result
3921__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3922 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3923 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3924{
3925 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3926 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3927 const uint32_t* _frm_nxt = _frm;
3928 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3929 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3930 uint8_t* _to_nxt = _to;
3931 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3932 _Maxcode_, _Mode_);
3933 frm_nxt = frm + (_frm_nxt - _frm);
3934 to_nxt = to + (_to_nxt - _to);
3935 return r;
3936}
3937
3938__codecvt_utf8_utf16<wchar_t>::result
3939__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3940 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3941 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3942{
3943 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3944 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3945 const uint8_t* _frm_nxt = _frm;
3946 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3947 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3948 uint32_t* _to_nxt = _to;
3949 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3950 _Maxcode_, _Mode_);
3951 frm_nxt = frm + (_frm_nxt - _frm);
3952 to_nxt = to + (_to_nxt - _to);
3953 return r;
3954}
3955
3956__codecvt_utf8_utf16<wchar_t>::result
3957__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3958 extern_type* to, extern_type*, extern_type*& to_nxt) const
3959{
3960 to_nxt = to;
3961 return noconv;
3962}
3963
3964int
Howard Hinnantc9834542011-05-31 15:34:58 +00003965__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003966{
3967 return 0;
3968}
3969
3970bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003971__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003972{
3973 return false;
3974}
3975
3976int
3977__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3978 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3979{
3980 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3981 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3982 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3983}
3984
3985int
Howard Hinnantc9834542011-05-31 15:34:58 +00003986__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003987{
3988 if (_Mode_ & consume_header)
3989 return 7;
3990 return 4;
3991}
3992
3993// __codecvt_utf8_utf16<char16_t>
3994
3995__codecvt_utf8_utf16<char16_t>::result
3996__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3997 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3998 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3999{
4000 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4001 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4002 const uint16_t* _frm_nxt = _frm;
4003 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4004 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4005 uint8_t* _to_nxt = _to;
4006 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4007 _Maxcode_, _Mode_);
4008 frm_nxt = frm + (_frm_nxt - _frm);
4009 to_nxt = to + (_to_nxt - _to);
4010 return r;
4011}
4012
4013__codecvt_utf8_utf16<char16_t>::result
4014__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4015 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4016 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4017{
4018 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4019 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4020 const uint8_t* _frm_nxt = _frm;
4021 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4022 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4023 uint16_t* _to_nxt = _to;
4024 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4025 _Maxcode_, _Mode_);
4026 frm_nxt = frm + (_frm_nxt - _frm);
4027 to_nxt = to + (_to_nxt - _to);
4028 return r;
4029}
4030
4031__codecvt_utf8_utf16<char16_t>::result
4032__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4033 extern_type* to, extern_type*, extern_type*& to_nxt) const
4034{
4035 to_nxt = to;
4036 return noconv;
4037}
4038
4039int
Howard Hinnantc9834542011-05-31 15:34:58 +00004040__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004041{
4042 return 0;
4043}
4044
4045bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004046__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004047{
4048 return false;
4049}
4050
4051int
4052__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4053 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4054{
4055 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4056 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4057 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4058}
4059
4060int
Howard Hinnantc9834542011-05-31 15:34:58 +00004061__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004062{
4063 if (_Mode_ & consume_header)
4064 return 7;
4065 return 4;
4066}
4067
4068// __codecvt_utf8_utf16<char32_t>
4069
4070__codecvt_utf8_utf16<char32_t>::result
4071__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4072 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4073 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4074{
4075 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4076 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4077 const uint32_t* _frm_nxt = _frm;
4078 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4079 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4080 uint8_t* _to_nxt = _to;
4081 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4082 _Maxcode_, _Mode_);
4083 frm_nxt = frm + (_frm_nxt - _frm);
4084 to_nxt = to + (_to_nxt - _to);
4085 return r;
4086}
4087
4088__codecvt_utf8_utf16<char32_t>::result
4089__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4090 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4091 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4092{
4093 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4094 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4095 const uint8_t* _frm_nxt = _frm;
4096 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4097 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4098 uint32_t* _to_nxt = _to;
4099 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4100 _Maxcode_, _Mode_);
4101 frm_nxt = frm + (_frm_nxt - _frm);
4102 to_nxt = to + (_to_nxt - _to);
4103 return r;
4104}
4105
4106__codecvt_utf8_utf16<char32_t>::result
4107__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4108 extern_type* to, extern_type*, extern_type*& to_nxt) const
4109{
4110 to_nxt = to;
4111 return noconv;
4112}
4113
4114int
Howard Hinnantc9834542011-05-31 15:34:58 +00004115__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004116{
4117 return 0;
4118}
4119
4120bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004121__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004122{
4123 return false;
4124}
4125
4126int
4127__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4128 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4129{
4130 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4131 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4132 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4133}
4134
4135int
Howard Hinnantc9834542011-05-31 15:34:58 +00004136__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004137{
4138 if (_Mode_ & consume_header)
4139 return 7;
4140 return 4;
4141}
4142
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004143// __narrow_to_utf8<16>
4144
4145__narrow_to_utf8<16>::~__narrow_to_utf8()
4146{
4147}
4148
4149// __narrow_to_utf8<32>
4150
4151__narrow_to_utf8<32>::~__narrow_to_utf8()
4152{
4153}
4154
4155// __widen_from_utf8<16>
4156
4157__widen_from_utf8<16>::~__widen_from_utf8()
4158{
4159}
4160
4161// __widen_from_utf8<32>
4162
4163__widen_from_utf8<32>::~__widen_from_utf8()
4164{
4165}
4166
4167// numpunct<char> && numpunct<wchar_t>
4168
4169locale::id numpunct< char >::id;
4170locale::id numpunct<wchar_t>::id;
4171
4172numpunct<char>::numpunct(size_t refs)
4173 : locale::facet(refs),
4174 __decimal_point_('.'),
4175 __thousands_sep_(',')
4176{
4177}
4178
4179numpunct<wchar_t>::numpunct(size_t refs)
4180 : locale::facet(refs),
4181 __decimal_point_(L'.'),
4182 __thousands_sep_(L',')
4183{
4184}
4185
4186numpunct<char>::~numpunct()
4187{
4188}
4189
4190numpunct<wchar_t>::~numpunct()
4191{
4192}
4193
4194 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4195wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4196
4197 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4198wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4199
4200string numpunct< char >::do_grouping() const {return __grouping_;}
4201string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4202
4203 string numpunct< char >::do_truename() const {return "true";}
4204wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4205
4206 string numpunct< char >::do_falsename() const {return "false";}
4207wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4208
4209// numpunct_byname<char>
4210
4211numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4212 : numpunct<char>(refs)
4213{
4214 __init(nm);
4215}
4216
4217numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4218 : numpunct<char>(refs)
4219{
4220 __init(nm.c_str());
4221}
4222
4223numpunct_byname<char>::~numpunct_byname()
4224{
4225}
4226
4227void
4228numpunct_byname<char>::__init(const char* nm)
4229{
4230 if (strcmp(nm, "C") != 0)
4231 {
Sean Huntf3907e62011-07-15 05:40:33 +00004232 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004233#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004234 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004235 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4236 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004237#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004238#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004239 lconv* lc = localeconv_l(loc.get());
4240#else
4241 lconv* lc = __localeconv_l(loc.get());
4242#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004243 if (*lc->decimal_point)
4244 __decimal_point_ = *lc->decimal_point;
4245 if (*lc->thousands_sep)
4246 __thousands_sep_ = *lc->thousands_sep;
4247 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004248 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004249 }
4250}
4251
4252// numpunct_byname<wchar_t>
4253
4254numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4255 : numpunct<wchar_t>(refs)
4256{
4257 __init(nm);
4258}
4259
4260numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4261 : numpunct<wchar_t>(refs)
4262{
4263 __init(nm.c_str());
4264}
4265
4266numpunct_byname<wchar_t>::~numpunct_byname()
4267{
4268}
4269
4270void
4271numpunct_byname<wchar_t>::__init(const char* nm)
4272{
4273 if (strcmp(nm, "C") != 0)
4274 {
Sean Huntf3907e62011-07-15 05:40:33 +00004275 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004276#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004277 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004278 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4279 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004280#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004281#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004282 lconv* lc = localeconv_l(loc.get());
4283#else
4284 lconv* lc = __localeconv_l(loc.get());
4285#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004286 if (*lc->decimal_point)
4287 __decimal_point_ = *lc->decimal_point;
4288 if (*lc->thousands_sep)
4289 __thousands_sep_ = *lc->thousands_sep;
4290 __grouping_ = lc->grouping;
4291 // locallization for truename and falsename is not available
4292 }
4293}
4294
4295// num_get helpers
4296
4297int
4298__num_get_base::__get_base(ios_base& iob)
4299{
4300 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4301 if (__basefield == ios_base::oct)
4302 return 8;
4303 else if (__basefield == ios_base::hex)
4304 return 16;
4305 else if (__basefield == 0)
4306 return 0;
4307 return 10;
4308}
4309
4310const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4311
4312void
4313__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4314 ios_base::iostate& __err)
4315{
4316 if (__grouping.size() != 0)
4317 {
4318 reverse(__g, __g_end);
4319 const char* __ig = __grouping.data();
4320 const char* __eg = __ig + __grouping.size();
4321 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4322 {
4323 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4324 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004325 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004326 {
4327 __err = ios_base::failbit;
4328 return;
4329 }
4330 }
4331 if (__eg - __ig > 1)
4332 ++__ig;
4333 }
4334 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4335 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004336 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004337 __err = ios_base::failbit;
4338 }
4339 }
4340}
4341
4342void
4343__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4344 ios_base::fmtflags __flags)
4345{
4346 if (__flags & ios_base::showpos)
4347 *__fmtp++ = '+';
4348 if (__flags & ios_base::showbase)
4349 *__fmtp++ = '#';
4350 while(*__len)
4351 *__fmtp++ = *__len++;
4352 if ((__flags & ios_base::basefield) == ios_base::oct)
4353 *__fmtp = 'o';
4354 else if ((__flags & ios_base::basefield) == ios_base::hex)
4355 {
4356 if (__flags & ios_base::uppercase)
4357 *__fmtp = 'X';
4358 else
4359 *__fmtp = 'x';
4360 }
4361 else if (__signd)
4362 *__fmtp = 'd';
4363 else
4364 *__fmtp = 'u';
4365}
4366
4367bool
4368__num_put_base::__format_float(char* __fmtp, const char* __len,
4369 ios_base::fmtflags __flags)
4370{
4371 bool specify_precision = true;
4372 if (__flags & ios_base::showpos)
4373 *__fmtp++ = '+';
4374 if (__flags & ios_base::showpoint)
4375 *__fmtp++ = '#';
4376 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowa3645132013-10-21 15:07:28 +00004377 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004378 if (floatfield == (ios_base::fixed | ios_base::scientific))
4379 specify_precision = false;
4380 else
4381 {
4382 *__fmtp++ = '.';
4383 *__fmtp++ = '*';
4384 }
4385 while(*__len)
4386 *__fmtp++ = *__len++;
4387 if (floatfield == ios_base::fixed)
4388 {
4389 if (uppercase)
4390 *__fmtp = 'F';
4391 else
4392 *__fmtp = 'f';
4393 }
4394 else if (floatfield == ios_base::scientific)
4395 {
4396 if (uppercase)
4397 *__fmtp = 'E';
4398 else
4399 *__fmtp = 'e';
4400 }
4401 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4402 {
4403 if (uppercase)
4404 *__fmtp = 'A';
4405 else
4406 *__fmtp = 'a';
4407 }
4408 else
4409 {
4410 if (uppercase)
4411 *__fmtp = 'G';
4412 else
4413 *__fmtp = 'g';
4414 }
4415 return specify_precision;
4416}
4417
4418char*
4419__num_put_base::__identify_padding(char* __nb, char* __ne,
4420 const ios_base& __iob)
4421{
4422 switch (__iob.flags() & ios_base::adjustfield)
4423 {
4424 case ios_base::internal:
4425 if (__nb[0] == '-' || __nb[0] == '+')
4426 return __nb+1;
4427 if (__ne - __nb >= 2 && __nb[0] == '0'
4428 && (__nb[1] == 'x' || __nb[1] == 'X'))
4429 return __nb+2;
4430 break;
4431 case ios_base::left:
4432 return __ne;
4433 case ios_base::right:
4434 default:
4435 break;
4436 }
4437 return __nb;
4438}
4439
4440// time_get
4441
4442static
4443string*
4444init_weeks()
4445{
4446 static string weeks[14];
4447 weeks[0] = "Sunday";
4448 weeks[1] = "Monday";
4449 weeks[2] = "Tuesday";
4450 weeks[3] = "Wednesday";
4451 weeks[4] = "Thursday";
4452 weeks[5] = "Friday";
4453 weeks[6] = "Saturday";
4454 weeks[7] = "Sun";
4455 weeks[8] = "Mon";
4456 weeks[9] = "Tue";
4457 weeks[10] = "Wed";
4458 weeks[11] = "Thu";
4459 weeks[12] = "Fri";
4460 weeks[13] = "Sat";
4461 return weeks;
4462}
4463
4464static
4465wstring*
4466init_wweeks()
4467{
4468 static wstring weeks[14];
4469 weeks[0] = L"Sunday";
4470 weeks[1] = L"Monday";
4471 weeks[2] = L"Tuesday";
4472 weeks[3] = L"Wednesday";
4473 weeks[4] = L"Thursday";
4474 weeks[5] = L"Friday";
4475 weeks[6] = L"Saturday";
4476 weeks[7] = L"Sun";
4477 weeks[8] = L"Mon";
4478 weeks[9] = L"Tue";
4479 weeks[10] = L"Wed";
4480 weeks[11] = L"Thu";
4481 weeks[12] = L"Fri";
4482 weeks[13] = L"Sat";
4483 return weeks;
4484}
4485
4486template <>
4487const string*
4488__time_get_c_storage<char>::__weeks() const
4489{
4490 static const string* weeks = init_weeks();
4491 return weeks;
4492}
4493
4494template <>
4495const wstring*
4496__time_get_c_storage<wchar_t>::__weeks() const
4497{
4498 static const wstring* weeks = init_wweeks();
4499 return weeks;
4500}
4501
4502static
4503string*
4504init_months()
4505{
4506 static string months[24];
4507 months[0] = "January";
4508 months[1] = "February";
4509 months[2] = "March";
4510 months[3] = "April";
4511 months[4] = "May";
4512 months[5] = "June";
4513 months[6] = "July";
4514 months[7] = "August";
4515 months[8] = "September";
4516 months[9] = "October";
4517 months[10] = "November";
4518 months[11] = "December";
4519 months[12] = "Jan";
4520 months[13] = "Feb";
4521 months[14] = "Mar";
4522 months[15] = "Apr";
4523 months[16] = "May";
4524 months[17] = "Jun";
4525 months[18] = "Jul";
4526 months[19] = "Aug";
4527 months[20] = "Sep";
4528 months[21] = "Oct";
4529 months[22] = "Nov";
4530 months[23] = "Dec";
4531 return months;
4532}
4533
4534static
4535wstring*
4536init_wmonths()
4537{
4538 static wstring months[24];
4539 months[0] = L"January";
4540 months[1] = L"February";
4541 months[2] = L"March";
4542 months[3] = L"April";
4543 months[4] = L"May";
4544 months[5] = L"June";
4545 months[6] = L"July";
4546 months[7] = L"August";
4547 months[8] = L"September";
4548 months[9] = L"October";
4549 months[10] = L"November";
4550 months[11] = L"December";
4551 months[12] = L"Jan";
4552 months[13] = L"Feb";
4553 months[14] = L"Mar";
4554 months[15] = L"Apr";
4555 months[16] = L"May";
4556 months[17] = L"Jun";
4557 months[18] = L"Jul";
4558 months[19] = L"Aug";
4559 months[20] = L"Sep";
4560 months[21] = L"Oct";
4561 months[22] = L"Nov";
4562 months[23] = L"Dec";
4563 return months;
4564}
4565
4566template <>
4567const string*
4568__time_get_c_storage<char>::__months() const
4569{
4570 static const string* months = init_months();
4571 return months;
4572}
4573
4574template <>
4575const wstring*
4576__time_get_c_storage<wchar_t>::__months() const
4577{
4578 static const wstring* months = init_wmonths();
4579 return months;
4580}
4581
4582static
4583string*
4584init_am_pm()
4585{
4586 static string am_pm[24];
4587 am_pm[0] = "AM";
4588 am_pm[1] = "PM";
4589 return am_pm;
4590}
4591
4592static
4593wstring*
4594init_wam_pm()
4595{
4596 static wstring am_pm[24];
4597 am_pm[0] = L"AM";
4598 am_pm[1] = L"PM";
4599 return am_pm;
4600}
4601
4602template <>
4603const string*
4604__time_get_c_storage<char>::__am_pm() const
4605{
4606 static const string* am_pm = init_am_pm();
4607 return am_pm;
4608}
4609
4610template <>
4611const wstring*
4612__time_get_c_storage<wchar_t>::__am_pm() const
4613{
4614 static const wstring* am_pm = init_wam_pm();
4615 return am_pm;
4616}
4617
4618template <>
4619const string&
4620__time_get_c_storage<char>::__x() const
4621{
4622 static string s("%m/%d/%y");
4623 return s;
4624}
4625
4626template <>
4627const wstring&
4628__time_get_c_storage<wchar_t>::__x() const
4629{
4630 static wstring s(L"%m/%d/%y");
4631 return s;
4632}
4633
4634template <>
4635const string&
4636__time_get_c_storage<char>::__X() const
4637{
4638 static string s("%H:%M:%S");
4639 return s;
4640}
4641
4642template <>
4643const wstring&
4644__time_get_c_storage<wchar_t>::__X() const
4645{
4646 static wstring s(L"%H:%M:%S");
4647 return s;
4648}
4649
4650template <>
4651const string&
4652__time_get_c_storage<char>::__c() const
4653{
4654 static string s("%a %b %d %H:%M:%S %Y");
4655 return s;
4656}
4657
4658template <>
4659const wstring&
4660__time_get_c_storage<wchar_t>::__c() const
4661{
4662 static wstring s(L"%a %b %d %H:%M:%S %Y");
4663 return s;
4664}
4665
4666template <>
4667const string&
4668__time_get_c_storage<char>::__r() const
4669{
4670 static string s("%I:%M:%S %p");
4671 return s;
4672}
4673
4674template <>
4675const wstring&
4676__time_get_c_storage<wchar_t>::__r() const
4677{
4678 static wstring s(L"%I:%M:%S %p");
4679 return s;
4680}
4681
4682// time_get_byname
4683
4684__time_get::__time_get(const char* nm)
4685 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4686{
Howard Hinnantd4444702010-08-11 17:04:31 +00004687#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004688 if (__loc_ == 0)
4689 throw runtime_error("time_get_byname"
4690 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004691#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004692}
4693
4694__time_get::__time_get(const string& nm)
4695 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4696{
Howard Hinnantd4444702010-08-11 17:04:31 +00004697#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004698 if (__loc_ == 0)
4699 throw runtime_error("time_get_byname"
4700 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004701#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004702}
4703
4704__time_get::~__time_get()
4705{
4706 freelocale(__loc_);
4707}
Marshall Clowa3645132013-10-21 15:07:28 +00004708#if defined(__clang__)
Howard Hinnant335b1512012-02-20 16:51:43 +00004709#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004710#endif
4711#if defined(__GNUG__)
Howard Hinnant21772ec2012-12-28 18:15:01 +00004712#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004713#endif
Howard Hinnant335b1512012-02-20 16:51:43 +00004714
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004715template <>
4716string
4717__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4718{
Howard Hinnant3074a052012-02-19 14:55:32 +00004719 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004720 t.tm_sec = 59;
4721 t.tm_min = 55;
4722 t.tm_hour = 23;
4723 t.tm_mday = 31;
4724 t.tm_mon = 11;
4725 t.tm_year = 161;
4726 t.tm_wday = 6;
4727 t.tm_yday = 364;
4728 t.tm_isdst = -1;
4729 char buf[100];
4730 char f[3] = {0};
4731 f[0] = '%';
4732 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004733 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004734 char* bb = buf;
4735 char* be = buf + n;
4736 string result;
4737 while (bb != be)
4738 {
4739 if (ct.is(ctype_base::space, *bb))
4740 {
4741 result.push_back(' ');
4742 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4743 ;
4744 continue;
4745 }
4746 char* w = bb;
4747 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004748 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004749 ct, err, false)
4750 - this->__weeks_;
4751 if (i < 14)
4752 {
4753 result.push_back('%');
4754 if (i < 7)
4755 result.push_back('A');
4756 else
4757 result.push_back('a');
4758 bb = w;
4759 continue;
4760 }
4761 w = bb;
4762 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4763 ct, err, false)
4764 - this->__months_;
4765 if (i < 24)
4766 {
4767 result.push_back('%');
4768 if (i < 12)
4769 result.push_back('B');
4770 else
4771 result.push_back('b');
4772 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4773 result.back() = 'm';
4774 bb = w;
4775 continue;
4776 }
4777 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4778 {
4779 w = bb;
4780 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4781 ct, err, false) - this->__am_pm_;
4782 if (i < 2)
4783 {
4784 result.push_back('%');
4785 result.push_back('p');
4786 bb = w;
4787 continue;
4788 }
4789 }
4790 w = bb;
4791 if (ct.is(ctype_base::digit, *bb))
4792 {
4793 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4794 {
4795 case 6:
4796 result.push_back('%');
4797 result.push_back('w');
4798 break;
4799 case 7:
4800 result.push_back('%');
4801 result.push_back('u');
4802 break;
4803 case 11:
4804 result.push_back('%');
4805 result.push_back('I');
4806 break;
4807 case 12:
4808 result.push_back('%');
4809 result.push_back('m');
4810 break;
4811 case 23:
4812 result.push_back('%');
4813 result.push_back('H');
4814 break;
4815 case 31:
4816 result.push_back('%');
4817 result.push_back('d');
4818 break;
4819 case 55:
4820 result.push_back('%');
4821 result.push_back('M');
4822 break;
4823 case 59:
4824 result.push_back('%');
4825 result.push_back('S');
4826 break;
4827 case 61:
4828 result.push_back('%');
4829 result.push_back('y');
4830 break;
4831 case 364:
4832 result.push_back('%');
4833 result.push_back('j');
4834 break;
4835 case 2061:
4836 result.push_back('%');
4837 result.push_back('Y');
4838 break;
4839 default:
4840 for (; w != bb; ++w)
4841 result.push_back(*w);
4842 break;
4843 }
4844 continue;
4845 }
4846 if (*bb == '%')
4847 {
4848 result.push_back('%');
4849 result.push_back('%');
4850 ++bb;
4851 continue;
4852 }
4853 result.push_back(*bb);
4854 ++bb;
4855 }
4856 return result;
4857}
4858
Marshall Clowa3645132013-10-21 15:07:28 +00004859#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +00004860#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowa3645132013-10-21 15:07:28 +00004861#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004862
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004863template <>
4864wstring
4865__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4866{
Howard Hinnant3074a052012-02-19 14:55:32 +00004867 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004868 t.tm_sec = 59;
4869 t.tm_min = 55;
4870 t.tm_hour = 23;
4871 t.tm_mday = 31;
4872 t.tm_mon = 11;
4873 t.tm_year = 161;
4874 t.tm_wday = 6;
4875 t.tm_yday = 364;
4876 t.tm_isdst = -1;
4877 char buf[100];
4878 char f[3] = {0};
4879 f[0] = '%';
4880 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004881 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004882 wchar_t wbuf[100];
4883 wchar_t* wbb = wbuf;
4884 mbstate_t mb = {0};
4885 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004886#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004887 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004888#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004889 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004890#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004891 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004892 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004893 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004894 wstring result;
4895 while (wbb != wbe)
4896 {
4897 if (ct.is(ctype_base::space, *wbb))
4898 {
4899 result.push_back(L' ');
4900 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4901 ;
4902 continue;
4903 }
4904 wchar_t* w = wbb;
4905 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004906 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004907 ct, err, false)
4908 - this->__weeks_;
4909 if (i < 14)
4910 {
4911 result.push_back(L'%');
4912 if (i < 7)
4913 result.push_back(L'A');
4914 else
4915 result.push_back(L'a');
4916 wbb = w;
4917 continue;
4918 }
4919 w = wbb;
4920 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4921 ct, err, false)
4922 - this->__months_;
4923 if (i < 24)
4924 {
4925 result.push_back(L'%');
4926 if (i < 12)
4927 result.push_back(L'B');
4928 else
4929 result.push_back(L'b');
4930 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4931 result.back() = L'm';
4932 wbb = w;
4933 continue;
4934 }
4935 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4936 {
4937 w = wbb;
4938 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4939 ct, err, false) - this->__am_pm_;
4940 if (i < 2)
4941 {
4942 result.push_back(L'%');
4943 result.push_back(L'p');
4944 wbb = w;
4945 continue;
4946 }
4947 }
4948 w = wbb;
4949 if (ct.is(ctype_base::digit, *wbb))
4950 {
4951 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4952 {
4953 case 6:
4954 result.push_back(L'%');
4955 result.push_back(L'w');
4956 break;
4957 case 7:
4958 result.push_back(L'%');
4959 result.push_back(L'u');
4960 break;
4961 case 11:
4962 result.push_back(L'%');
4963 result.push_back(L'I');
4964 break;
4965 case 12:
4966 result.push_back(L'%');
4967 result.push_back(L'm');
4968 break;
4969 case 23:
4970 result.push_back(L'%');
4971 result.push_back(L'H');
4972 break;
4973 case 31:
4974 result.push_back(L'%');
4975 result.push_back(L'd');
4976 break;
4977 case 55:
4978 result.push_back(L'%');
4979 result.push_back(L'M');
4980 break;
4981 case 59:
4982 result.push_back(L'%');
4983 result.push_back(L'S');
4984 break;
4985 case 61:
4986 result.push_back(L'%');
4987 result.push_back(L'y');
4988 break;
4989 case 364:
4990 result.push_back(L'%');
4991 result.push_back(L'j');
4992 break;
4993 case 2061:
4994 result.push_back(L'%');
4995 result.push_back(L'Y');
4996 break;
4997 default:
4998 for (; w != wbb; ++w)
4999 result.push_back(*w);
5000 break;
5001 }
5002 continue;
5003 }
5004 if (ct.narrow(*wbb, 0) == '%')
5005 {
5006 result.push_back(L'%');
5007 result.push_back(L'%');
5008 ++wbb;
5009 continue;
5010 }
5011 result.push_back(*wbb);
5012 ++wbb;
5013 }
5014 return result;
5015}
5016
5017template <>
5018void
5019__time_get_storage<char>::init(const ctype<char>& ct)
5020{
Howard Hinnantcd992362012-08-02 18:44:17 +00005021 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005022 char buf[100];
5023 // __weeks_
5024 for (int i = 0; i < 7; ++i)
5025 {
5026 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005027 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005028 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005029 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005030 __weeks_[i+7] = buf;
5031 }
5032 // __months_
5033 for (int i = 0; i < 12; ++i)
5034 {
5035 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005036 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005037 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005038 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005039 __months_[i+12] = buf;
5040 }
5041 // __am_pm_
5042 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005043 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005044 __am_pm_[0] = buf;
5045 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005046 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005047 __am_pm_[1] = buf;
5048 __c_ = __analyze('c', ct);
5049 __r_ = __analyze('r', ct);
5050 __x_ = __analyze('x', ct);
5051 __X_ = __analyze('X', ct);
5052}
5053
5054template <>
5055void
5056__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5057{
5058 tm t = {0};
5059 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005060 wchar_t wbuf[100];
5061 wchar_t* wbe;
5062 mbstate_t mb = {0};
5063 // __weeks_
5064 for (int i = 0; i < 7; ++i)
5065 {
5066 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005067 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005068 mb = mbstate_t();
5069 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005070#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005071 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005072#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005073 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005074#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005075 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005076 __throw_runtime_error("locale not supported");
5077 wbe = wbuf + j;
5078 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005079 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005080 mb = mbstate_t();
5081 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005082#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005083 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005084#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005085 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005086#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005087 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005088 __throw_runtime_error("locale not supported");
5089 wbe = wbuf + j;
5090 __weeks_[i+7].assign(wbuf, wbe);
5091 }
5092 // __months_
5093 for (int i = 0; i < 12; ++i)
5094 {
5095 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005096 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005097 mb = mbstate_t();
5098 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005099#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005100 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005101#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005102 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005103#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005104 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005105 __throw_runtime_error("locale not supported");
5106 wbe = wbuf + j;
5107 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005108 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005109 mb = mbstate_t();
5110 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005111#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005112 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005113#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005114 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005115#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005116 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005117 __throw_runtime_error("locale not supported");
5118 wbe = wbuf + j;
5119 __months_[i+12].assign(wbuf, wbe);
5120 }
5121 // __am_pm_
5122 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005123 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005124 mb = mbstate_t();
5125 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005126#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005127 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005128#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005129 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005130#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005131 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005132 __throw_runtime_error("locale not supported");
5133 wbe = wbuf + j;
5134 __am_pm_[0].assign(wbuf, wbe);
5135 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005136 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005137 mb = mbstate_t();
5138 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005139#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005140 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005141#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005142 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005143#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005144 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005145 __throw_runtime_error("locale not supported");
5146 wbe = wbuf + j;
5147 __am_pm_[1].assign(wbuf, wbe);
5148 __c_ = __analyze('c', ct);
5149 __r_ = __analyze('r', ct);
5150 __x_ = __analyze('x', ct);
5151 __X_ = __analyze('X', ct);
5152}
5153
5154template <class CharT>
5155struct _LIBCPP_HIDDEN __time_get_temp
5156 : public ctype_byname<CharT>
5157{
5158 explicit __time_get_temp(const char* nm)
5159 : ctype_byname<CharT>(nm, 1) {}
5160 explicit __time_get_temp(const string& nm)
5161 : ctype_byname<CharT>(nm, 1) {}
5162};
5163
5164template <>
5165__time_get_storage<char>::__time_get_storage(const char* __nm)
5166 : __time_get(__nm)
5167{
5168 const __time_get_temp<char> ct(__nm);
5169 init(ct);
5170}
5171
5172template <>
5173__time_get_storage<char>::__time_get_storage(const string& __nm)
5174 : __time_get(__nm)
5175{
5176 const __time_get_temp<char> ct(__nm);
5177 init(ct);
5178}
5179
5180template <>
5181__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5182 : __time_get(__nm)
5183{
5184 const __time_get_temp<wchar_t> ct(__nm);
5185 init(ct);
5186}
5187
5188template <>
5189__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5190 : __time_get(__nm)
5191{
5192 const __time_get_temp<wchar_t> ct(__nm);
5193 init(ct);
5194}
5195
5196template <>
5197time_base::dateorder
5198__time_get_storage<char>::__do_date_order() const
5199{
5200 unsigned i;
5201 for (i = 0; i < __x_.size(); ++i)
5202 if (__x_[i] == '%')
5203 break;
5204 ++i;
5205 switch (__x_[i])
5206 {
5207 case 'y':
5208 case 'Y':
5209 for (++i; i < __x_.size(); ++i)
5210 if (__x_[i] == '%')
5211 break;
5212 if (i == __x_.size())
5213 break;
5214 ++i;
5215 switch (__x_[i])
5216 {
5217 case 'm':
5218 for (++i; i < __x_.size(); ++i)
5219 if (__x_[i] == '%')
5220 break;
5221 if (i == __x_.size())
5222 break;
5223 ++i;
5224 if (__x_[i] == 'd')
5225 return time_base::ymd;
5226 break;
5227 case 'd':
5228 for (++i; i < __x_.size(); ++i)
5229 if (__x_[i] == '%')
5230 break;
5231 if (i == __x_.size())
5232 break;
5233 ++i;
5234 if (__x_[i] == 'm')
5235 return time_base::ydm;
5236 break;
5237 }
5238 break;
5239 case 'm':
5240 for (++i; i < __x_.size(); ++i)
5241 if (__x_[i] == '%')
5242 break;
5243 if (i == __x_.size())
5244 break;
5245 ++i;
5246 if (__x_[i] == 'd')
5247 {
5248 for (++i; i < __x_.size(); ++i)
5249 if (__x_[i] == '%')
5250 break;
5251 if (i == __x_.size())
5252 break;
5253 ++i;
5254 if (__x_[i] == 'y' || __x_[i] == 'Y')
5255 return time_base::mdy;
5256 break;
5257 }
5258 break;
5259 case 'd':
5260 for (++i; i < __x_.size(); ++i)
5261 if (__x_[i] == '%')
5262 break;
5263 if (i == __x_.size())
5264 break;
5265 ++i;
5266 if (__x_[i] == 'm')
5267 {
5268 for (++i; i < __x_.size(); ++i)
5269 if (__x_[i] == '%')
5270 break;
5271 if (i == __x_.size())
5272 break;
5273 ++i;
5274 if (__x_[i] == 'y' || __x_[i] == 'Y')
5275 return time_base::dmy;
5276 break;
5277 }
5278 break;
5279 }
5280 return time_base::no_order;
5281}
5282
5283template <>
5284time_base::dateorder
5285__time_get_storage<wchar_t>::__do_date_order() const
5286{
5287 unsigned i;
5288 for (i = 0; i < __x_.size(); ++i)
5289 if (__x_[i] == L'%')
5290 break;
5291 ++i;
5292 switch (__x_[i])
5293 {
5294 case L'y':
5295 case L'Y':
5296 for (++i; i < __x_.size(); ++i)
5297 if (__x_[i] == L'%')
5298 break;
5299 if (i == __x_.size())
5300 break;
5301 ++i;
5302 switch (__x_[i])
5303 {
5304 case L'm':
5305 for (++i; i < __x_.size(); ++i)
5306 if (__x_[i] == L'%')
5307 break;
5308 if (i == __x_.size())
5309 break;
5310 ++i;
5311 if (__x_[i] == L'd')
5312 return time_base::ymd;
5313 break;
5314 case L'd':
5315 for (++i; i < __x_.size(); ++i)
5316 if (__x_[i] == L'%')
5317 break;
5318 if (i == __x_.size())
5319 break;
5320 ++i;
5321 if (__x_[i] == L'm')
5322 return time_base::ydm;
5323 break;
5324 }
5325 break;
5326 case L'm':
5327 for (++i; i < __x_.size(); ++i)
5328 if (__x_[i] == L'%')
5329 break;
5330 if (i == __x_.size())
5331 break;
5332 ++i;
5333 if (__x_[i] == L'd')
5334 {
5335 for (++i; i < __x_.size(); ++i)
5336 if (__x_[i] == L'%')
5337 break;
5338 if (i == __x_.size())
5339 break;
5340 ++i;
5341 if (__x_[i] == L'y' || __x_[i] == L'Y')
5342 return time_base::mdy;
5343 break;
5344 }
5345 break;
5346 case L'd':
5347 for (++i; i < __x_.size(); ++i)
5348 if (__x_[i] == L'%')
5349 break;
5350 if (i == __x_.size())
5351 break;
5352 ++i;
5353 if (__x_[i] == L'm')
5354 {
5355 for (++i; i < __x_.size(); ++i)
5356 if (__x_[i] == L'%')
5357 break;
5358 if (i == __x_.size())
5359 break;
5360 ++i;
5361 if (__x_[i] == L'y' || __x_[i] == L'Y')
5362 return time_base::dmy;
5363 break;
5364 }
5365 break;
5366 }
5367 return time_base::no_order;
5368}
5369
5370// time_put
5371
5372__time_put::__time_put(const char* nm)
5373 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5374{
Howard Hinnantd4444702010-08-11 17:04:31 +00005375#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005376 if (__loc_ == 0)
5377 throw runtime_error("time_put_byname"
5378 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005379#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005380}
5381
5382__time_put::__time_put(const string& nm)
5383 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5384{
Howard Hinnantd4444702010-08-11 17:04:31 +00005385#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005386 if (__loc_ == 0)
5387 throw runtime_error("time_put_byname"
5388 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005389#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005390}
5391
5392__time_put::~__time_put()
5393{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005394 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005395 freelocale(__loc_);
5396}
5397
5398void
5399__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5400 char __fmt, char __mod) const
5401{
5402 char fmt[] = {'%', __fmt, __mod, 0};
5403 if (__mod != 0)
5404 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005405 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005406 __ne = __nb + n;
5407}
5408
5409void
5410__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5411 char __fmt, char __mod) const
5412{
5413 char __nar[100];
5414 char* __ne = __nar + 100;
5415 __do_put(__nar, __ne, __tm, __fmt, __mod);
5416 mbstate_t mb = {0};
5417 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005418#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005419 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005420#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005421 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005422#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005423 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005424 __throw_runtime_error("locale not supported");
5425 __we = __wb + j;
5426}
5427
5428// moneypunct_byname
5429
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005430template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005431static
5432void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005433__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5434 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5435 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005436{
5437 const char sign = static_cast<char>(money_base::sign);
5438 const char space = static_cast<char>(money_base::space);
5439 const char none = static_cast<char>(money_base::none);
5440 const char symbol = static_cast<char>(money_base::symbol);
5441 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005442 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5443
5444 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5445 // function'. "Space between sign and symbol or value" means that
5446 // if the sign is adjacent to the symbol, there's a space between
5447 // them, and otherwise there's a space between the sign and value.
5448 //
5449 // C11's localeconv specifies that the fourth character of an
5450 // international curr_symbol is used to separate the sign and
5451 // value when sep_by_space says to do so. C++ can't represent
5452 // that, so we just use a space. When sep_by_space says to
5453 // separate the symbol and value-or-sign with a space, we rearrange the
5454 // curr_symbol to put its spacing character on the correct side of
5455 // the symbol.
5456 //
5457 // We also need to avoid adding an extra space between the sign
5458 // and value when the currency symbol is suppressed (by not
5459 // setting showbase). We match glibc's strfmon by interpreting
5460 // sep_by_space==1 as "omit the space when the currency symbol is
5461 // absent".
5462 //
5463 // Users who want to get this right should use ICU instead.
5464
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005465 switch (cs_precedes)
5466 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005467 case 0: // value before curr_symbol
5468 if (symbol_contains_sep) {
5469 // Move the separator to before the symbol, to place it
5470 // between the value and symbol.
5471 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5472 __curr_symbol_.end());
5473 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005474 switch (sign_posn)
5475 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005476 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005477 pat.field[0] = sign;
5478 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005479 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005480 pat.field[3] = symbol;
5481 switch (sep_by_space)
5482 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005483 case 0: // No space separates the currency symbol and value.
5484 // This case may have changed between C99 and C11;
5485 // assume the currency symbol matches the intention.
5486 case 2: // Space between sign and currency or value.
5487 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005488 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005489 case 1: // Space between currency-and-sign or currency and value.
5490 if (!symbol_contains_sep) {
5491 // We insert the space into the symbol instead of
5492 // setting pat.field[2]=space so that when
5493 // showbase is not set, the space goes away too.
5494 __curr_symbol_.insert(0, 1, space_char);
5495 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005496 return;
5497 default:
5498 break;
5499 }
5500 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005501 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005502 pat.field[0] = sign;
5503 pat.field[3] = symbol;
5504 switch (sep_by_space)
5505 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005506 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005507 pat.field[1] = value;
5508 pat.field[2] = none;
5509 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005510 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005511 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005512 pat.field[2] = none;
5513 if (!symbol_contains_sep) {
5514 // We insert the space into the symbol instead of
5515 // setting pat.field[2]=space so that when
5516 // showbase is not set, the space goes away too.
5517 __curr_symbol_.insert(0, 1, space_char);
5518 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005519 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005520 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005521 pat.field[1] = space;
5522 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005523 if (symbol_contains_sep) {
5524 // Remove the separator from the symbol, since it
5525 // has already appeared after the sign.
5526 __curr_symbol_.erase(__curr_symbol_.begin());
5527 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005528 return;
5529 default:
5530 break;
5531 }
5532 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005533 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005534 pat.field[0] = value;
5535 pat.field[3] = sign;
5536 switch (sep_by_space)
5537 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005538 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005539 pat.field[1] = none;
5540 pat.field[2] = symbol;
5541 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005542 case 1: // Space between currency-and-sign or currency and value.
5543 if (!symbol_contains_sep) {
5544 // We insert the space into the symbol instead of
5545 // setting pat.field[1]=space so that when
5546 // showbase is not set, the space goes away too.
5547 __curr_symbol_.insert(0, 1, space_char);
5548 }
5549 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005550 pat.field[2] = symbol;
5551 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005552 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005553 pat.field[1] = symbol;
5554 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005555 if (symbol_contains_sep) {
5556 // Remove the separator from the symbol, since it
5557 // should not be removed if showbase is absent.
5558 __curr_symbol_.erase(__curr_symbol_.begin());
5559 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005560 return;
5561 default:
5562 break;
5563 }
5564 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005565 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005566 pat.field[0] = value;
5567 pat.field[3] = symbol;
5568 switch (sep_by_space)
5569 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005570 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005571 pat.field[1] = none;
5572 pat.field[2] = sign;
5573 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005574 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005575 pat.field[1] = space;
5576 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005577 if (symbol_contains_sep) {
5578 // Remove the separator from the symbol, since it
5579 // has already appeared before the sign.
5580 __curr_symbol_.erase(__curr_symbol_.begin());
5581 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005582 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005583 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005584 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005585 pat.field[2] = none;
5586 if (!symbol_contains_sep) {
5587 // We insert the space into the symbol instead of
5588 // setting pat.field[2]=space so that when
5589 // showbase is not set, the space goes away too.
5590 __curr_symbol_.insert(0, 1, space_char);
5591 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005592 return;
5593 default:
5594 break;
5595 }
5596 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005597 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005598 pat.field[0] = value;
5599 pat.field[3] = sign;
5600 switch (sep_by_space)
5601 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005602 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005603 pat.field[1] = none;
5604 pat.field[2] = symbol;
5605 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005606 case 1: // Space between currency-and-sign or currency and value.
5607 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005608 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005609 if (!symbol_contains_sep) {
5610 // We insert the space into the symbol instead of
5611 // setting pat.field[1]=space so that when
5612 // showbase is not set, the space goes away too.
5613 __curr_symbol_.insert(0, 1, space_char);
5614 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005615 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005616 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005617 pat.field[1] = symbol;
5618 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005619 if (symbol_contains_sep) {
5620 // Remove the separator from the symbol, since it
5621 // should not disappear when showbase is absent.
5622 __curr_symbol_.erase(__curr_symbol_.begin());
5623 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005624 return;
5625 default:
5626 break;
5627 }
5628 break;
5629 default:
5630 break;
5631 }
5632 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005633 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005634 switch (sign_posn)
5635 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005636 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005637 pat.field[0] = sign;
5638 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005639 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005640 pat.field[3] = value;
5641 switch (sep_by_space)
5642 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005643 case 0: // No space separates the currency symbol and value.
5644 // This case may have changed between C99 and C11;
5645 // assume the currency symbol matches the intention.
5646 case 2: // Space between sign and currency or value.
5647 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005648 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005649 case 1: // Space between currency-and-sign or currency and value.
5650 if (!symbol_contains_sep) {
5651 // We insert the space into the symbol instead of
5652 // setting pat.field[2]=space so that when
5653 // showbase is not set, the space goes away too.
5654 __curr_symbol_.insert(0, 1, space_char);
5655 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005656 return;
5657 default:
5658 break;
5659 }
5660 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005661 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005662 pat.field[0] = sign;
5663 pat.field[3] = value;
5664 switch (sep_by_space)
5665 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005666 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005667 pat.field[1] = symbol;
5668 pat.field[2] = none;
5669 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005670 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005671 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005672 pat.field[2] = none;
5673 if (!symbol_contains_sep) {
5674 // We insert the space into the symbol instead of
5675 // setting pat.field[2]=space so that when
5676 // showbase is not set, the space goes away too.
5677 __curr_symbol_.push_back(space_char);
5678 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005679 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005680 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005681 pat.field[1] = space;
5682 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005683 if (symbol_contains_sep) {
5684 // Remove the separator from the symbol, since it
5685 // has already appeared after the sign.
5686 __curr_symbol_.pop_back();
5687 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005688 return;
5689 default:
5690 break;
5691 }
5692 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005693 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005694 pat.field[0] = symbol;
5695 pat.field[3] = sign;
5696 switch (sep_by_space)
5697 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005698 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005699 pat.field[1] = none;
5700 pat.field[2] = value;
5701 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005702 case 1: // Space between currency-and-sign or currency and value.
5703 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005704 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005705 if (!symbol_contains_sep) {
5706 // We insert the space into the symbol instead of
5707 // setting pat.field[1]=space so that when
5708 // showbase is not set, the space goes away too.
5709 __curr_symbol_.push_back(space_char);
5710 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005711 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005712 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005713 pat.field[1] = value;
5714 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005715 if (symbol_contains_sep) {
5716 // Remove the separator from the symbol, since it
5717 // will appear before the sign.
5718 __curr_symbol_.pop_back();
5719 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005720 return;
5721 default:
5722 break;
5723 }
5724 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005725 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005726 pat.field[0] = sign;
5727 pat.field[3] = value;
5728 switch (sep_by_space)
5729 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005730 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005731 pat.field[1] = symbol;
5732 pat.field[2] = none;
5733 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005734 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005735 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005736 pat.field[2] = none;
5737 if (!symbol_contains_sep) {
5738 // We insert the space into the symbol instead of
5739 // setting pat.field[2]=space so that when
5740 // showbase is not set, the space goes away too.
5741 __curr_symbol_.push_back(space_char);
5742 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005743 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005744 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005745 pat.field[1] = space;
5746 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005747 if (symbol_contains_sep) {
5748 // Remove the separator from the symbol, since it
5749 // has already appeared after the sign.
5750 __curr_symbol_.pop_back();
5751 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005752 return;
5753 default:
5754 break;
5755 }
5756 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005757 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005758 pat.field[0] = symbol;
5759 pat.field[3] = value;
5760 switch (sep_by_space)
5761 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005762 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005763 pat.field[1] = sign;
5764 pat.field[2] = none;
5765 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005766 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005767 pat.field[1] = sign;
5768 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005769 if (symbol_contains_sep) {
5770 // Remove the separator from the symbol, since it
5771 // should not disappear when showbase is absent.
5772 __curr_symbol_.pop_back();
5773 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005774 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005775 case 2: // Space between sign and currency or value.
5776 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005777 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005778 if (!symbol_contains_sep) {
5779 // We insert the space into the symbol instead of
5780 // setting pat.field[1]=space so that when
5781 // showbase is not set, the space goes away too.
5782 __curr_symbol_.push_back(space_char);
5783 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005784 return;
5785 default:
5786 break;
5787 }
5788 break;
5789 default:
5790 break;
5791 }
5792 break;
5793 default:
5794 break;
5795 }
5796 pat.field[0] = symbol;
5797 pat.field[1] = sign;
5798 pat.field[2] = none;
5799 pat.field[3] = value;
5800}
5801
5802template<>
5803void
5804moneypunct_byname<char, false>::init(const char* nm)
5805{
5806 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005807 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005808#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005809 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005810 throw runtime_error("moneypunct_byname"
5811 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005812#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005813#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005814 lconv* lc = localeconv_l(loc.get());
5815#else
5816 lconv* lc = __localeconv_l(loc.get());
5817#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005818 if (*lc->mon_decimal_point)
5819 __decimal_point_ = *lc->mon_decimal_point;
5820 else
5821 __decimal_point_ = base::do_decimal_point();
5822 if (*lc->mon_thousands_sep)
5823 __thousands_sep_ = *lc->mon_thousands_sep;
5824 else
5825 __thousands_sep_ = base::do_thousands_sep();
5826 __grouping_ = lc->mon_grouping;
5827 __curr_symbol_ = lc->currency_symbol;
5828 if (lc->frac_digits != CHAR_MAX)
5829 __frac_digits_ = lc->frac_digits;
5830 else
5831 __frac_digits_ = base::do_frac_digits();
5832 if (lc->p_sign_posn == 0)
5833 __positive_sign_ = "()";
5834 else
5835 __positive_sign_ = lc->positive_sign;
5836 if (lc->n_sign_posn == 0)
5837 __negative_sign_ = "()";
5838 else
5839 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005840 // Assume the positive and negative formats will want spaces in
5841 // the same places in curr_symbol since there's no way to
5842 // represent anything else.
5843 string_type __dummy_curr_symbol = __curr_symbol_;
5844 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5845 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5846 __init_pat(__neg_format_, __curr_symbol_, false,
5847 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005848}
5849
5850template<>
5851void
5852moneypunct_byname<char, true>::init(const char* nm)
5853{
5854 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005855 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005856#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005857 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005858 throw runtime_error("moneypunct_byname"
5859 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005860#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005861#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005862 lconv* lc = localeconv_l(loc.get());
5863#else
5864 lconv* lc = __localeconv_l(loc.get());
5865#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005866 if (*lc->mon_decimal_point)
5867 __decimal_point_ = *lc->mon_decimal_point;
5868 else
5869 __decimal_point_ = base::do_decimal_point();
5870 if (*lc->mon_thousands_sep)
5871 __thousands_sep_ = *lc->mon_thousands_sep;
5872 else
5873 __thousands_sep_ = base::do_thousands_sep();
5874 __grouping_ = lc->mon_grouping;
5875 __curr_symbol_ = lc->int_curr_symbol;
5876 if (lc->int_frac_digits != CHAR_MAX)
5877 __frac_digits_ = lc->int_frac_digits;
5878 else
5879 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00005880#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005881 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005882#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005883 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005884#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005885 __positive_sign_ = "()";
5886 else
5887 __positive_sign_ = lc->positive_sign;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005888#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005889 if(lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005890#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005891 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005892#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005893 __negative_sign_ = "()";
5894 else
5895 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005896 // Assume the positive and negative formats will want spaces in
5897 // the same places in curr_symbol since there's no way to
5898 // represent anything else.
5899 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005900#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005901 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5902 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5903 __init_pat(__neg_format_, __curr_symbol_, true,
5904 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005905#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005906 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5907 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5908 lc->int_p_sign_posn, ' ');
5909 __init_pat(__neg_format_, __curr_symbol_, true,
5910 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5911 lc->int_n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005912#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005913}
5914
5915template<>
5916void
5917moneypunct_byname<wchar_t, false>::init(const char* nm)
5918{
5919 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005920 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005921#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005922 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005923 throw runtime_error("moneypunct_byname"
5924 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005925#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005926#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005927 lconv* lc = localeconv_l(loc.get());
5928#else
5929 lconv* lc = __localeconv_l(loc.get());
5930#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005931 if (*lc->mon_decimal_point)
5932 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5933 else
5934 __decimal_point_ = base::do_decimal_point();
5935 if (*lc->mon_thousands_sep)
5936 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5937 else
5938 __thousands_sep_ = base::do_thousands_sep();
5939 __grouping_ = lc->mon_grouping;
5940 wchar_t wbuf[100];
5941 mbstate_t mb = {0};
5942 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005943#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005944 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005945#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005946 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005947#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005948 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005949 __throw_runtime_error("locale not supported");
5950 wchar_t* wbe = wbuf + j;
5951 __curr_symbol_.assign(wbuf, wbe);
5952 if (lc->frac_digits != CHAR_MAX)
5953 __frac_digits_ = lc->frac_digits;
5954 else
5955 __frac_digits_ = base::do_frac_digits();
5956 if (lc->p_sign_posn == 0)
5957 __positive_sign_ = L"()";
5958 else
5959 {
5960 mb = mbstate_t();
5961 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005962#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005963 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005964#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005965 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005966#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005967 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005968 __throw_runtime_error("locale not supported");
5969 wbe = wbuf + j;
5970 __positive_sign_.assign(wbuf, wbe);
5971 }
5972 if (lc->n_sign_posn == 0)
5973 __negative_sign_ = L"()";
5974 else
5975 {
5976 mb = mbstate_t();
5977 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005978#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005979 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005980#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005981 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005982#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005983 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005984 __throw_runtime_error("locale not supported");
5985 wbe = wbuf + j;
5986 __negative_sign_.assign(wbuf, wbe);
5987 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005988 // Assume the positive and negative formats will want spaces in
5989 // the same places in curr_symbol since there's no way to
5990 // represent anything else.
5991 string_type __dummy_curr_symbol = __curr_symbol_;
5992 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5993 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5994 __init_pat(__neg_format_, __curr_symbol_, false,
5995 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005996}
5997
5998template<>
5999void
6000moneypunct_byname<wchar_t, true>::init(const char* nm)
6001{
6002 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00006003 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00006004#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00006005 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006006 throw runtime_error("moneypunct_byname"
6007 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00006008#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00006009#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00006010 lconv* lc = localeconv_l(loc.get());
6011#else
6012 lconv* lc = __localeconv_l(loc.get());
6013#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006014 if (*lc->mon_decimal_point)
6015 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6016 else
6017 __decimal_point_ = base::do_decimal_point();
6018 if (*lc->mon_thousands_sep)
6019 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6020 else
6021 __thousands_sep_ = base::do_thousands_sep();
6022 __grouping_ = lc->mon_grouping;
6023 wchar_t wbuf[100];
6024 mbstate_t mb = {0};
6025 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006026#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006027 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006028#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006029 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006030#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006031 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006032 __throw_runtime_error("locale not supported");
6033 wchar_t* wbe = wbuf + j;
6034 __curr_symbol_.assign(wbuf, wbe);
6035 if (lc->int_frac_digits != CHAR_MAX)
6036 __frac_digits_ = lc->int_frac_digits;
6037 else
6038 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00006039#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006040 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006041#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006042 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006043#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006044 __positive_sign_ = L"()";
6045 else
6046 {
6047 mb = mbstate_t();
6048 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006049#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006050 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006051#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006052 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006053#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006054 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006055 __throw_runtime_error("locale not supported");
6056 wbe = wbuf + j;
6057 __positive_sign_.assign(wbuf, wbe);
6058 }
Howard Hinnantef5aa932013-09-17 01:34:47 +00006059#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006060 if (lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006061#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006062 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006063#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006064 __negative_sign_ = L"()";
6065 else
6066 {
6067 mb = mbstate_t();
6068 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006069#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006070 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006071#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006072 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006073#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006074 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006075 __throw_runtime_error("locale not supported");
6076 wbe = wbuf + j;
6077 __negative_sign_.assign(wbuf, wbe);
6078 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006079 // Assume the positive and negative formats will want spaces in
6080 // the same places in curr_symbol since there's no way to
6081 // represent anything else.
6082 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00006083#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006084 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6085 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6086 __init_pat(__neg_format_, __curr_symbol_, true,
6087 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006088#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006089 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6090 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6091 lc->int_p_sign_posn, L' ');
6092 __init_pat(__neg_format_, __curr_symbol_, true,
6093 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6094 lc->int_n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006095#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006096}
6097
6098void __do_nothing(void*) {}
6099
6100void __throw_runtime_error(const char* msg)
6101{
Howard Hinnantd4444702010-08-11 17:04:31 +00006102#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006103 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006104#else
6105 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006106#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006107}
6108
6109template class collate<char>;
6110template class collate<wchar_t>;
6111
6112template class num_get<char>;
6113template class num_get<wchar_t>;
6114
Howard Hinnantec3773c2011-12-01 20:21:04 +00006115template struct __num_get<char>;
6116template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006117
6118template class num_put<char>;
6119template class num_put<wchar_t>;
6120
Howard Hinnantec3773c2011-12-01 20:21:04 +00006121template struct __num_put<char>;
6122template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006123
6124template class time_get<char>;
6125template class time_get<wchar_t>;
6126
6127template class time_get_byname<char>;
6128template class time_get_byname<wchar_t>;
6129
6130template class time_put<char>;
6131template class time_put<wchar_t>;
6132
6133template class time_put_byname<char>;
6134template class time_put_byname<wchar_t>;
6135
6136template class moneypunct<char, false>;
6137template class moneypunct<char, true>;
6138template class moneypunct<wchar_t, false>;
6139template class moneypunct<wchar_t, true>;
6140
6141template class moneypunct_byname<char, false>;
6142template class moneypunct_byname<char, true>;
6143template class moneypunct_byname<wchar_t, false>;
6144template class moneypunct_byname<wchar_t, true>;
6145
6146template class money_get<char>;
6147template class money_get<wchar_t>;
6148
6149template class __money_get<char>;
6150template class __money_get<wchar_t>;
6151
6152template class money_put<char>;
6153template class money_put<wchar_t>;
6154
6155template class __money_put<char>;
6156template class __money_put<wchar_t>;
6157
6158template class messages<char>;
6159template class messages<wchar_t>;
6160
6161template class messages_byname<char>;
6162template class messages_byname<wchar_t>;
6163
6164template class codecvt_byname<char, char, mbstate_t>;
6165template class codecvt_byname<wchar_t, char, mbstate_t>;
6166template class codecvt_byname<char16_t, char, mbstate_t>;
6167template class codecvt_byname<char32_t, char, mbstate_t>;
6168
6169template class __vector_base_common<true>;
6170
6171_LIBCPP_END_NAMESPACE_STD