blob: bf95732ed7de6f285bdbd9bea84be68d7fb86015 [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
David Chisnall997e4542012-02-29 13:05:08 +000010// On Solaris, we need to define something to make the C99 parts of localeconv
11// visible.
12#ifdef __sun__
13#define _LCONV_C99
14#endif
15
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000016#include "string"
17#include "locale"
Howard Hinnant87d1a8a2010-05-30 21:39:41 +000018#include "codecvt"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000019#include "vector"
20#include "algorithm"
21#include "algorithm"
22#include "typeinfo"
Howard Hinnantd318d492011-06-30 14:21:55 +000023#include "type_traits"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024#include "clocale"
25#include "cstring"
26#include "cwctype"
27#include "__sso_allocator"
Marshall Clowa22d2ad2013-03-18 17:04:29 +000028#ifdef _WIN32
Howard Hinnant14fa9f92011-09-29 20:33:10 +000029#include <support/win32/locale_win32.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000030#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031#include <langinfo.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000032#endif // _!WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000033#include <stdlib.h>
Howard Hinnanted14a762013-07-23 16:05:56 +000034#include <stdio.h>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000035
Marshall Clow9ae96d02013-02-07 17:20:56 +000036// On Linux, wint_t and wchar_t have different signed-ness, and this causes
37// lots of noise in the build log, but no bugs that I know of.
38#pragma clang diagnostic ignored "-Wsign-conversion"
39
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000040_LIBCPP_BEGIN_NAMESPACE_STD
41
Howard Hinnant866569b2011-09-28 23:39:33 +000042#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000043locale_t __cloc() {
44 // In theory this could create a race condition. In practice
45 // the race condition is non-fatal since it will just create
46 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000047 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
48 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000049}
Howard Hinnant866569b2011-09-28 23:39:33 +000050#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000051
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000052namespace {
53
54struct release
55{
56 void operator()(locale::facet* p) {p->__release_shared();}
57};
58
59template <class T, class A0>
60inline
61T&
62make(A0 a0)
63{
64 static typename aligned_storage<sizeof(T)>::type buf;
65 ::new (&buf) T(a0);
66 return *(T*)&buf;
67}
68
69template <class T, class A0, class A1>
70inline
71T&
72make(A0 a0, A1 a1)
73{
74 static typename aligned_storage<sizeof(T)>::type buf;
75 ::new (&buf) T(a0, a1);
76 return *(T*)&buf;
77}
78
79template <class T, class A0, class A1, class A2>
80inline
81T&
82make(A0 a0, A1 a1, A2 a2)
83{
84 static typename aligned_storage<sizeof(T)>::type buf;
85 ::new (&buf) T(a0, a1, a2);
86 return *(T*)&buf;
87}
88
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000089template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000090inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000091_LIBCPP_CONSTEXPR
92size_t
93countof(const T (&)[N])
94{
95 return N;
96}
97
98template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +000099inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +0000100_LIBCPP_CONSTEXPR
101size_t
102countof(const T * const begin, const T * const end)
103{
104 return static_cast<size_t>(end - begin);
105}
106
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000107}
108
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000109const locale::category locale::none;
110const locale::category locale::collate;
111const locale::category locale::ctype;
112const locale::category locale::monetary;
113const locale::category locale::numeric;
114const locale::category locale::time;
115const locale::category locale::messages;
116const locale::category locale::all;
117
Howard Hinnantec3773c2011-12-01 20:21:04 +0000118#pragma clang diagnostic push
119#pragma clang diagnostic ignored "-Wpadded"
120
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000121class _LIBCPP_HIDDEN locale::__imp
122 : public facet
123{
124 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000125 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000126 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000127public:
128 explicit __imp(size_t refs = 0);
129 explicit __imp(const string& name, size_t refs = 0);
130 __imp(const __imp&);
131 __imp(const __imp&, const string&, locale::category c);
132 __imp(const __imp& other, const __imp& one, locale::category c);
133 __imp(const __imp&, facet* f, long id);
134 ~__imp();
135
136 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000137 bool has_facet(long id) const
138 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000139 const locale::facet* use_facet(long id) const;
140
141 static const locale& make_classic();
142 static locale& make_global();
143private:
144 void install(facet* f, long id);
145 template <class F> void install(F* f) {install(f, f->id.__get());}
146 template <class F> void install_from(const __imp& other);
147};
148
Howard Hinnantec3773c2011-12-01 20:21:04 +0000149#pragma clang diagnostic pop
150
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000151locale::__imp::__imp(size_t refs)
152 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000153 facets_(N),
154 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000155{
156 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000157 install(&make<_VSTD::collate<char> >(1u));
158 install(&make<_VSTD::collate<wchar_t> >(1u));
159 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
160 install(&make<_VSTD::ctype<wchar_t> >(1u));
161 install(&make<codecvt<char, char, mbstate_t> >(1u));
162 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
163 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
164 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
165 install(&make<numpunct<char> >(1u));
166 install(&make<numpunct<wchar_t> >(1u));
167 install(&make<num_get<char> >(1u));
168 install(&make<num_get<wchar_t> >(1u));
169 install(&make<num_put<char> >(1u));
170 install(&make<num_put<wchar_t> >(1u));
171 install(&make<moneypunct<char, false> >(1u));
172 install(&make<moneypunct<char, true> >(1u));
173 install(&make<moneypunct<wchar_t, false> >(1u));
174 install(&make<moneypunct<wchar_t, true> >(1u));
175 install(&make<money_get<char> >(1u));
176 install(&make<money_get<wchar_t> >(1u));
177 install(&make<money_put<char> >(1u));
178 install(&make<money_put<wchar_t> >(1u));
179 install(&make<time_get<char> >(1u));
180 install(&make<time_get<wchar_t> >(1u));
181 install(&make<time_put<char> >(1u));
182 install(&make<time_put<wchar_t> >(1u));
183 install(&make<_VSTD::messages<char> >(1u));
184 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000185}
186
187locale::__imp::__imp(const string& name, size_t refs)
188 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000189 facets_(N),
190 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000191{
Howard Hinnantd4444702010-08-11 17:04:31 +0000192#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000193 try
194 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000195#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000196 facets_ = locale::classic().__locale_->facets_;
197 for (unsigned i = 0; i < facets_.size(); ++i)
198 if (facets_[i])
199 facets_[i]->__add_shared();
200 install(new collate_byname<char>(name_));
201 install(new collate_byname<wchar_t>(name_));
202 install(new ctype_byname<char>(name_));
203 install(new ctype_byname<wchar_t>(name_));
204 install(new codecvt_byname<char, char, mbstate_t>(name_));
205 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
206 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
207 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
208 install(new numpunct_byname<char>(name_));
209 install(new numpunct_byname<wchar_t>(name_));
210 install(new moneypunct_byname<char, false>(name_));
211 install(new moneypunct_byname<char, true>(name_));
212 install(new moneypunct_byname<wchar_t, false>(name_));
213 install(new moneypunct_byname<wchar_t, true>(name_));
214 install(new time_get_byname<char>(name_));
215 install(new time_get_byname<wchar_t>(name_));
216 install(new time_put_byname<char>(name_));
217 install(new time_put_byname<wchar_t>(name_));
218 install(new messages_byname<char>(name_));
219 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000220#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000221 }
222 catch (...)
223 {
224 for (unsigned i = 0; i < facets_.size(); ++i)
225 if (facets_[i])
226 facets_[i]->__release_shared();
227 throw;
228 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000229#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000230}
231
Howard Hinnant21772ec2012-12-28 18:15:01 +0000232// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000233// copy constructor` warning emitted by GCC
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000234#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000235#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000236#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000237#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000238
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000239locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000240 : facets_(max<size_t>(N, other.facets_.size())),
241 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000242{
243 facets_ = other.facets_;
244 for (unsigned i = 0; i < facets_.size(); ++i)
245 if (facets_[i])
246 facets_[i]->__add_shared();
247}
248
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000249#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000250#pragma GCC diagnostic pop
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000251#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000252
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000253locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000254 : facets_(N),
255 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000256{
257 facets_ = other.facets_;
258 for (unsigned i = 0; i < facets_.size(); ++i)
259 if (facets_[i])
260 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000261#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000262 try
263 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000264#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000265 if (c & locale::collate)
266 {
267 install(new collate_byname<char>(name));
268 install(new collate_byname<wchar_t>(name));
269 }
270 if (c & locale::ctype)
271 {
272 install(new ctype_byname<char>(name));
273 install(new ctype_byname<wchar_t>(name));
274 install(new codecvt_byname<char, char, mbstate_t>(name));
275 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
276 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
277 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
278 }
279 if (c & locale::monetary)
280 {
281 install(new moneypunct_byname<char, false>(name));
282 install(new moneypunct_byname<char, true>(name));
283 install(new moneypunct_byname<wchar_t, false>(name));
284 install(new moneypunct_byname<wchar_t, true>(name));
285 }
286 if (c & locale::numeric)
287 {
288 install(new numpunct_byname<char>(name));
289 install(new numpunct_byname<wchar_t>(name));
290 }
291 if (c & locale::time)
292 {
293 install(new time_get_byname<char>(name));
294 install(new time_get_byname<wchar_t>(name));
295 install(new time_put_byname<char>(name));
296 install(new time_put_byname<wchar_t>(name));
297 }
298 if (c & locale::messages)
299 {
300 install(new messages_byname<char>(name));
301 install(new messages_byname<wchar_t>(name));
302 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000303#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000304 }
305 catch (...)
306 {
307 for (unsigned i = 0; i < facets_.size(); ++i)
308 if (facets_[i])
309 facets_[i]->__release_shared();
310 throw;
311 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000312#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000313}
314
315template<class F>
316inline
317void
318locale::__imp::install_from(const locale::__imp& one)
319{
320 long id = F::id.__get();
321 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
322}
323
324locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000325 : facets_(N),
326 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000327{
328 facets_ = other.facets_;
329 for (unsigned i = 0; i < facets_.size(); ++i)
330 if (facets_[i])
331 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000332#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000333 try
334 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000335#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000336 if (c & locale::collate)
337 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000338 install_from<_VSTD::collate<char> >(one);
339 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000340 }
341 if (c & locale::ctype)
342 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000343 install_from<_VSTD::ctype<char> >(one);
344 install_from<_VSTD::ctype<wchar_t> >(one);
345 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
346 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
347 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
348 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000349 }
350 if (c & locale::monetary)
351 {
352 install_from<moneypunct<char, false> >(one);
353 install_from<moneypunct<char, true> >(one);
354 install_from<moneypunct<wchar_t, false> >(one);
355 install_from<moneypunct<wchar_t, true> >(one);
356 install_from<money_get<char> >(one);
357 install_from<money_get<wchar_t> >(one);
358 install_from<money_put<char> >(one);
359 install_from<money_put<wchar_t> >(one);
360 }
361 if (c & locale::numeric)
362 {
363 install_from<numpunct<char> >(one);
364 install_from<numpunct<wchar_t> >(one);
365 install_from<num_get<char> >(one);
366 install_from<num_get<wchar_t> >(one);
367 install_from<num_put<char> >(one);
368 install_from<num_put<wchar_t> >(one);
369 }
370 if (c & locale::time)
371 {
372 install_from<time_get<char> >(one);
373 install_from<time_get<wchar_t> >(one);
374 install_from<time_put<char> >(one);
375 install_from<time_put<wchar_t> >(one);
376 }
377 if (c & locale::messages)
378 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000379 install_from<_VSTD::messages<char> >(one);
380 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000381 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000382#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000383 }
384 catch (...)
385 {
386 for (unsigned i = 0; i < facets_.size(); ++i)
387 if (facets_[i])
388 facets_[i]->__release_shared();
389 throw;
390 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000391#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000392}
393
394locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000395 : facets_(max<size_t>(N, other.facets_.size()+1)),
396 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000397{
398 f->__add_shared();
399 unique_ptr<facet, release> hold(f);
400 facets_ = other.facets_;
401 for (unsigned i = 0; i < other.facets_.size(); ++i)
402 if (facets_[i])
403 facets_[i]->__add_shared();
404 install(hold.get(), id);
405}
406
407locale::__imp::~__imp()
408{
409 for (unsigned i = 0; i < facets_.size(); ++i)
410 if (facets_[i])
411 facets_[i]->__release_shared();
412}
413
414void
415locale::__imp::install(facet* f, long id)
416{
417 f->__add_shared();
418 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000419 if (static_cast<size_t>(id) >= facets_.size())
420 facets_.resize(static_cast<size_t>(id+1));
421 if (facets_[static_cast<size_t>(id)])
422 facets_[static_cast<size_t>(id)]->__release_shared();
423 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000424}
425
426const locale::facet*
427locale::__imp::use_facet(long id) const
428{
Howard Hinnantd4444702010-08-11 17:04:31 +0000429#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000430 if (!has_facet(id))
431 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000432#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000433 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000434}
435
436// locale
437
438const locale&
439locale::__imp::make_classic()
440{
441 // only one thread can get in here and it only gets in once
442 static aligned_storage<sizeof(locale)>::type buf;
443 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000444 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000445 return *c;
446}
447
448const locale&
449locale::classic()
450{
451 static const locale& c = __imp::make_classic();
452 return c;
453}
454
455locale&
456locale::__imp::make_global()
457{
458 // only one thread can get in here and it only gets in once
459 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000460 ::new (&buf) locale(locale::classic());
461 return *(locale*)&buf;
462}
463
464locale&
465locale::__global()
466{
467 static locale& g = __imp::make_global();
468 return g;
469}
470
Howard Hinnantc9834542011-05-31 15:34:58 +0000471locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000472 : __locale_(__global().__locale_)
473{
474 __locale_->__add_shared();
475}
476
Howard Hinnantc9834542011-05-31 15:34:58 +0000477locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000478 : __locale_(l.__locale_)
479{
480 __locale_->__add_shared();
481}
482
Howard Hinnantc9834542011-05-31 15:34:58 +0000483locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000484{
485 __locale_->__release_shared();
486}
487
488const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000489locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000490{
491 other.__locale_->__add_shared();
492 __locale_->__release_shared();
493 __locale_ = other.__locale_;
494 return *this;
495}
496
497locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000498#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000499 : __locale_(name ? new __imp(name)
500 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000501#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000502 : __locale_(new __imp(name))
503#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000504{
505 __locale_->__add_shared();
506}
507
508locale::locale(const string& name)
509 : __locale_(new __imp(name))
510{
511 __locale_->__add_shared();
512}
513
514locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000515#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000516 : __locale_(name ? new __imp(*other.__locale_, name, c)
517 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000518#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000519 : __locale_(new __imp(*other.__locale_, name, c))
520#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000521{
522 __locale_->__add_shared();
523}
524
525locale::locale(const locale& other, const string& name, category c)
526 : __locale_(new __imp(*other.__locale_, name, c))
527{
528 __locale_->__add_shared();
529}
530
531locale::locale(const locale& other, const locale& one, category c)
532 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
533{
534 __locale_->__add_shared();
535}
536
537string
538locale::name() const
539{
540 return __locale_->name();
541}
542
543void
544locale::__install_ctor(const locale& other, facet* f, long id)
545{
546 if (f)
547 __locale_ = new __imp(*other.__locale_, f, id);
548 else
549 __locale_ = other.__locale_;
550 __locale_->__add_shared();
551}
552
553locale
554locale::global(const locale& loc)
555{
556 locale& g = __global();
557 locale r = g;
558 g = loc;
559 if (g.name() != "*")
560 setlocale(LC_ALL, g.name().c_str());
561 return r;
562}
563
564bool
565locale::has_facet(id& x) const
566{
567 return __locale_->has_facet(x.__get());
568}
569
570const locale::facet*
571locale::use_facet(id& x) const
572{
573 return __locale_->use_facet(x.__get());
574}
575
576bool
577locale::operator==(const locale& y) const
578{
579 return (__locale_ == y.__locale_)
580 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
581}
582
583// locale::facet
584
585locale::facet::~facet()
586{
587}
588
589void
Howard Hinnant1694d232011-05-28 14:41:13 +0000590locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000591{
592 delete this;
593}
594
595// locale::id
596
597int32_t locale::id::__next_id = 0;
598
599namespace
600{
601
602class __fake_bind
603{
604 locale::id* id_;
605 void (locale::id::* pmf_)();
606public:
607 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
608 : id_(id), pmf_(pmf) {}
609
610 void operator()() const
611 {
612 (id_->*pmf_)();
613 }
614};
615
616}
617
618long
619locale::id::__get()
620{
621 call_once(__flag_, __fake_bind(&locale::id::__init, this));
622 return __id_ - 1;
623}
624
625void
626locale::id::__init()
627{
Howard Hinnantadff4892010-05-24 17:49:41 +0000628 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000629}
630
631// template <> class collate_byname<char>
632
633collate_byname<char>::collate_byname(const char* n, size_t refs)
634 : collate<char>(refs),
635 __l(newlocale(LC_ALL_MASK, n, 0))
636{
Howard Hinnantd4444702010-08-11 17:04:31 +0000637#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000638 if (__l == 0)
639 throw runtime_error("collate_byname<char>::collate_byname"
640 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000641#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000642}
643
644collate_byname<char>::collate_byname(const string& name, size_t refs)
645 : collate<char>(refs),
646 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
647{
Howard Hinnantd4444702010-08-11 17:04:31 +0000648#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000649 if (__l == 0)
650 throw runtime_error("collate_byname<char>::collate_byname"
651 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000652#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000653}
654
655collate_byname<char>::~collate_byname()
656{
657 freelocale(__l);
658}
659
660int
661collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
662 const char_type* __lo2, const char_type* __hi2) const
663{
664 string_type lhs(__lo1, __hi1);
665 string_type rhs(__lo2, __hi2);
666 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
667 if (r < 0)
668 return -1;
669 if (r > 0)
670 return 1;
671 return r;
672}
673
674collate_byname<char>::string_type
675collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
676{
677 const string_type in(lo, hi);
678 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
679 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
680 return out;
681}
682
683// template <> class collate_byname<wchar_t>
684
685collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
686 : collate<wchar_t>(refs),
687 __l(newlocale(LC_ALL_MASK, n, 0))
688{
Howard Hinnantd4444702010-08-11 17:04:31 +0000689#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000690 if (__l == 0)
691 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
692 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000693#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000694}
695
696collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
697 : collate<wchar_t>(refs),
698 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
699{
Howard Hinnantd4444702010-08-11 17:04:31 +0000700#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000701 if (__l == 0)
702 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
703 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000704#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000705}
706
707collate_byname<wchar_t>::~collate_byname()
708{
709 freelocale(__l);
710}
711
712int
713collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
714 const char_type* __lo2, const char_type* __hi2) const
715{
716 string_type lhs(__lo1, __hi1);
717 string_type rhs(__lo2, __hi2);
718 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
719 if (r < 0)
720 return -1;
721 if (r > 0)
722 return 1;
723 return r;
724}
725
726collate_byname<wchar_t>::string_type
727collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
728{
729 const string_type in(lo, hi);
730 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
731 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
732 return out;
733}
734
735// template <> class ctype<wchar_t>;
736
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000737const ctype_base::mask ctype_base::space;
738const ctype_base::mask ctype_base::print;
739const ctype_base::mask ctype_base::cntrl;
740const ctype_base::mask ctype_base::upper;
741const ctype_base::mask ctype_base::lower;
742const ctype_base::mask ctype_base::alpha;
743const ctype_base::mask ctype_base::digit;
744const ctype_base::mask ctype_base::punct;
745const ctype_base::mask ctype_base::xdigit;
746const ctype_base::mask ctype_base::blank;
747const ctype_base::mask ctype_base::alnum;
748const ctype_base::mask ctype_base::graph;
749
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000750locale::id ctype<wchar_t>::id;
751
752ctype<wchar_t>::~ctype()
753{
754}
755
756bool
757ctype<wchar_t>::do_is(mask m, char_type c) const
758{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000759 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000760}
761
762const wchar_t*
763ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
764{
765 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000766 *vec = static_cast<mask>(isascii(*low) ?
767 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000768 return low;
769}
770
771const wchar_t*
772ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
773{
774 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000775 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000776 break;
777 return low;
778}
779
780const wchar_t*
781ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
782{
783 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000784 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000785 break;
786 return low;
787}
788
789wchar_t
790ctype<wchar_t>::do_toupper(char_type c) const
791{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000792#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
793 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000794#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000795 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000796#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000797 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000798#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000799}
800
801const wchar_t*
802ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
803{
804 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000805#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
806 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000807#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000808 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
809 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000810#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000811 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000812#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000813 return low;
814}
815
816wchar_t
817ctype<wchar_t>::do_tolower(char_type c) const
818{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000819#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
820 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000821#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000822 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000823#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000824 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000825#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000826}
827
828const wchar_t*
829ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
830{
831 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000832#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
833 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000834#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000835 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
836 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000837#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000838 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000839#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000840 return low;
841}
842
843wchar_t
844ctype<wchar_t>::do_widen(char c) const
845{
846 return c;
847}
848
849const char*
850ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
851{
852 for (; low != high; ++low, ++dest)
853 *dest = *low;
854 return low;
855}
856
857char
858ctype<wchar_t>::do_narrow(char_type c, char dfault) const
859{
860 if (isascii(c))
861 return static_cast<char>(c);
862 return dfault;
863}
864
865const wchar_t*
866ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
867{
868 for (; low != high; ++low, ++dest)
869 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000870 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000871 else
872 *dest = dfault;
873 return low;
874}
875
876// template <> class ctype<char>;
877
878locale::id ctype<char>::id;
879
880ctype<char>::ctype(const mask* tab, bool del, size_t refs)
881 : locale::facet(refs),
882 __tab_(tab),
883 __del_(del)
884{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000885 if (__tab_ == 0)
886 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000887}
888
889ctype<char>::~ctype()
890{
891 if (__tab_ && __del_)
892 delete [] __tab_;
893}
894
895char
896ctype<char>::do_toupper(char_type c) const
897{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000898#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000899 return isascii(c) ?
900 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000901#elif defined(__NetBSD__)
902 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000903#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000904 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000905 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000906#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000907 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000908#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000909}
910
911const char*
912ctype<char>::do_toupper(char_type* low, const char_type* high) const
913{
914 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000915#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000916 *low = isascii(*low) ?
917 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000918#elif defined(__NetBSD__)
919 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000920#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000921 *low = isascii(*low) ?
922 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000923#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000924 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000925#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000926 return low;
927}
928
929char
930ctype<char>::do_tolower(char_type c) const
931{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000932#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000933 return isascii(c) ?
934 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000935#elif defined(__NetBSD__)
936 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
937#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Marshall Clow88c31902013-02-07 14:22:51 +0000938 return isascii(c) ?
939 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000940#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000941 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000942#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000943}
944
945const char*
946ctype<char>::do_tolower(char_type* low, const char_type* high) const
947{
948 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000949#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000950 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000951#elif defined(__NetBSD__)
952 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000953#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000954 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000955#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000956 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000957#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000958 return low;
959}
960
961char
962ctype<char>::do_widen(char c) const
963{
964 return c;
965}
966
967const char*
968ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
969{
970 for (; low != high; ++low, ++dest)
971 *dest = *low;
972 return low;
973}
974
975char
976ctype<char>::do_narrow(char_type c, char dfault) const
977{
978 if (isascii(c))
979 return static_cast<char>(c);
980 return dfault;
981}
982
983const char*
984ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
985{
986 for (; low != high; ++low, ++dest)
987 if (isascii(*low))
988 *dest = *low;
989 else
990 *dest = dfault;
991 return low;
992}
993
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000994#ifdef EMSCRIPTEN
995extern "C" const unsigned short ** __ctype_b_loc();
996extern "C" const int ** __ctype_tolower_loc();
997extern "C" const int ** __ctype_toupper_loc();
998#endif
999
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001000const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001001ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001002{
David Chisnallc512df12011-09-21 08:39:44 +00001003#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001004 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001005#elif defined(__NetBSD__)
1006 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001007#elif defined(__GLIBC__)
1008 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001009#elif __sun__
1010 return __ctype_mask;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00001011#elif defined(_WIN32)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001012 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001013// This is assumed to be safe, which is a nonsense assumption because we're
1014// going to end up dereferencing it later...
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001015#elif defined(EMSCRIPTEN)
1016 return *__ctype_b_loc();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001017#else
David Chisnall997e4542012-02-29 13:05:08 +00001018 // Platform not supported: abort so the person doing the port knows what to
1019 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001020# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001021 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001022 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001023 return NULL;
1024#endif
1025}
1026
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001027#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001028const int*
1029ctype<char>::__classic_lower_table() _NOEXCEPT
1030{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001031 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001032}
1033
1034const int*
1035ctype<char>::__classic_upper_table() _NOEXCEPT
1036{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001037 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001038}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001039#elif __NetBSD__
1040const short*
1041ctype<char>::__classic_lower_table() _NOEXCEPT
1042{
1043 return _C_tolower_tab_ + 1;
1044}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001045
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001046const short*
1047ctype<char>::__classic_upper_table() _NOEXCEPT
1048{
1049 return _C_toupper_tab_ + 1;
1050}
1051
1052#elif defined(EMSCRIPTEN)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001053const int*
1054ctype<char>::__classic_lower_table() _NOEXCEPT
1055{
1056 return *__ctype_tolower_loc();
1057}
1058
1059const int*
1060ctype<char>::__classic_upper_table() _NOEXCEPT
1061{
1062 return *__ctype_toupper_loc();
1063}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001064#endif // __GLIBC__ || EMSCRIPTEN || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001065
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001066// template <> class ctype_byname<char>
1067
1068ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1069 : ctype<char>(0, false, refs),
1070 __l(newlocale(LC_ALL_MASK, name, 0))
1071{
Howard Hinnantd4444702010-08-11 17:04:31 +00001072#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001073 if (__l == 0)
1074 throw runtime_error("ctype_byname<char>::ctype_byname"
1075 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001076#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001077}
1078
1079ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1080 : ctype<char>(0, false, refs),
1081 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1082{
Howard Hinnantd4444702010-08-11 17:04:31 +00001083#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001084 if (__l == 0)
1085 throw runtime_error("ctype_byname<char>::ctype_byname"
1086 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001087#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001088}
1089
1090ctype_byname<char>::~ctype_byname()
1091{
1092 freelocale(__l);
1093}
1094
1095char
1096ctype_byname<char>::do_toupper(char_type c) const
1097{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001098 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001099}
1100
1101const char*
1102ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1103{
1104 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001105 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001106 return low;
1107}
1108
1109char
1110ctype_byname<char>::do_tolower(char_type c) const
1111{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001112 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001113}
1114
1115const char*
1116ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1117{
1118 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001119 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001120 return low;
1121}
1122
1123// template <> class ctype_byname<wchar_t>
1124
1125ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1126 : ctype<wchar_t>(refs),
1127 __l(newlocale(LC_ALL_MASK, name, 0))
1128{
Howard Hinnantd4444702010-08-11 17:04:31 +00001129#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001130 if (__l == 0)
1131 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1132 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001133#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001134}
1135
1136ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1137 : ctype<wchar_t>(refs),
1138 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1139{
Howard Hinnantd4444702010-08-11 17:04:31 +00001140#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001141 if (__l == 0)
1142 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1143 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001144#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001145}
1146
1147ctype_byname<wchar_t>::~ctype_byname()
1148{
1149 freelocale(__l);
1150}
1151
1152bool
1153ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1154{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001155#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001156 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001157#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001158 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001159 wint_t ch = static_cast<wint_t>(c);
1160 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1161 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1162 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1163 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1164 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1165 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1166 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1167 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1168 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1169 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001170 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001171#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001172}
1173
1174const wchar_t*
1175ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1176{
1177 for (; low != high; ++low, ++vec)
1178 {
1179 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001180 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001181 else
1182 {
1183 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001184 wint_t ch = static_cast<wint_t>(*low);
1185 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001186 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001187 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001188 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001189 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001190 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001191 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001192 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001193 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001194 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001195 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001196 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001197 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001198 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001199 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001201 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001202 *vec |= xdigit;
1203 }
1204 }
1205 return low;
1206}
1207
1208const wchar_t*
1209ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1210{
1211 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001212 {
1213#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001214 if (iswctype_l(*low, m, __l))
1215 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001216#else
Marshall Clow88c31902013-02-07 14:22:51 +00001217 wint_t ch = static_cast<wint_t>(*low);
1218 if (m & space && iswspace_l(ch, __l)) break;
1219 if (m & print && iswprint_l(ch, __l)) break;
1220 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1221 if (m & upper && iswupper_l(ch, __l)) break;
1222 if (m & lower && iswlower_l(ch, __l)) break;
1223 if (m & alpha && iswalpha_l(ch, __l)) break;
1224 if (m & digit && iswdigit_l(ch, __l)) break;
1225 if (m & punct && iswpunct_l(ch, __l)) break;
1226 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1227 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001228#endif
1229 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001230 return low;
1231}
1232
1233const wchar_t*
1234ctype_byname<wchar_t>::do_scan_not(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)) continue;
1244 if (m & print && iswprint_l(ch, __l)) continue;
1245 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1246 if (m & upper && iswupper_l(ch, __l)) continue;
1247 if (m & lower && iswlower_l(ch, __l)) continue;
1248 if (m & alpha && iswalpha_l(ch, __l)) continue;
1249 if (m & digit && iswdigit_l(ch, __l)) continue;
1250 if (m & punct && iswpunct_l(ch, __l)) continue;
1251 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1252 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001253 break;
1254#endif
1255 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001256 return low;
1257}
1258
1259wchar_t
1260ctype_byname<wchar_t>::do_toupper(char_type c) const
1261{
1262 return towupper_l(c, __l);
1263}
1264
1265const wchar_t*
1266ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1267{
1268 for (; low != high; ++low)
1269 *low = towupper_l(*low, __l);
1270 return low;
1271}
1272
1273wchar_t
1274ctype_byname<wchar_t>::do_tolower(char_type c) const
1275{
1276 return towlower_l(c, __l);
1277}
1278
1279const wchar_t*
1280ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1281{
1282 for (; low != high; ++low)
1283 *low = towlower_l(*low, __l);
1284 return low;
1285}
1286
1287wchar_t
1288ctype_byname<wchar_t>::do_widen(char c) const
1289{
Howard Hinnant866569b2011-09-28 23:39:33 +00001290#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001291 return btowc_l(c, __l);
1292#else
1293 return __btowc_l(c, __l);
1294#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001295}
1296
1297const char*
1298ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1299{
1300 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001301#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001302 *dest = btowc_l(*low, __l);
1303#else
1304 *dest = __btowc_l(*low, __l);
1305#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001306 return low;
1307}
1308
1309char
1310ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1311{
Howard Hinnant866569b2011-09-28 23:39:33 +00001312#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001313 int r = wctob_l(c, __l);
1314#else
1315 int r = __wctob_l(c, __l);
1316#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001317 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001318}
1319
1320const wchar_t*
1321ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1322{
1323 for (; low != high; ++low, ++dest)
1324 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001325#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001326 int r = wctob_l(*low, __l);
1327#else
1328 int r = __wctob_l(*low, __l);
1329#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001330 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001331 }
1332 return low;
1333}
1334
1335// template <> class codecvt<char, char, mbstate_t>
1336
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001337locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001338
1339codecvt<char, char, mbstate_t>::~codecvt()
1340{
1341}
1342
1343codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001344codecvt<char, char, mbstate_t>::do_out(state_type&,
1345 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001346 extern_type* to, extern_type*, extern_type*& to_nxt) const
1347{
1348 frm_nxt = frm;
1349 to_nxt = to;
1350 return noconv;
1351}
1352
1353codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001354codecvt<char, char, mbstate_t>::do_in(state_type&,
1355 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001356 intern_type* to, intern_type*, intern_type*& to_nxt) const
1357{
1358 frm_nxt = frm;
1359 to_nxt = to;
1360 return noconv;
1361}
1362
1363codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001364codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001365 extern_type* to, extern_type*, extern_type*& to_nxt) const
1366{
1367 to_nxt = to;
1368 return noconv;
1369}
1370
1371int
Howard Hinnantc9834542011-05-31 15:34:58 +00001372codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001373{
1374 return 1;
1375}
1376
1377bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001378codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001379{
1380 return true;
1381}
1382
1383int
1384codecvt<char, char, mbstate_t>::do_length(state_type&,
1385 const extern_type* frm, const extern_type* end, size_t mx) const
1386{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001387 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001388}
1389
1390int
Howard Hinnantc9834542011-05-31 15:34:58 +00001391codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001392{
1393 return 1;
1394}
1395
1396// template <> class codecvt<wchar_t, char, mbstate_t>
1397
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001398locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001399
1400codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1401 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001402 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001403{
1404}
1405
1406codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1407 : locale::facet(refs),
1408 __l(newlocale(LC_ALL_MASK, nm, 0))
1409{
Howard Hinnantd4444702010-08-11 17:04:31 +00001410#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001411 if (__l == 0)
1412 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1413 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001414#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001415}
1416
1417codecvt<wchar_t, char, mbstate_t>::~codecvt()
1418{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001419 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001420 freelocale(__l);
1421}
1422
1423codecvt<wchar_t, char, mbstate_t>::result
1424codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001425 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001426 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1427{
1428 // look for first internal null in frm
1429 const intern_type* fend = frm;
1430 for (; fend != frm_end; ++fend)
1431 if (*fend == 0)
1432 break;
1433 // loop over all null-terminated sequences in frm
1434 to_nxt = to;
1435 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1436 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001437 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001438 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001439#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001440 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1441 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001442#else
1443 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1444#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001445 if (n == size_t(-1))
1446 {
1447 // need to recover to_nxt
1448 for (to_nxt = to; frm != frm_nxt; ++frm)
1449 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001450#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001451 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1452#else
1453 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1454#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001455 if (n == size_t(-1))
1456 break;
1457 to_nxt += n;
1458 }
1459 frm_nxt = frm;
1460 return error;
1461 }
1462 if (n == 0)
1463 return partial;
1464 to_nxt += n;
1465 if (to_nxt == to_end)
1466 break;
1467 if (fend != frm_end) // set up next null terminated sequence
1468 {
1469 // Try to write the terminating null
1470 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001471#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001472 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1473#else
1474 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1475#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001476 if (n == size_t(-1)) // on error
1477 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001478 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001479 return partial;
1480 for (extern_type* p = tmp; n; --n) // write it
1481 *to_nxt++ = *p++;
1482 ++frm_nxt;
1483 // look for next null in frm
1484 for (fend = frm_nxt; fend != frm_end; ++fend)
1485 if (*fend == 0)
1486 break;
1487 }
1488 }
1489 return frm_nxt == frm_end ? ok : partial;
1490}
1491
1492codecvt<wchar_t, char, mbstate_t>::result
1493codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001494 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001495 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1496{
1497 // look for first internal null in frm
1498 const extern_type* fend = frm;
1499 for (; fend != frm_end; ++fend)
1500 if (*fend == 0)
1501 break;
1502 // loop over all null-terminated sequences in frm
1503 to_nxt = to;
1504 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1505 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001506 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001507 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001508#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001509 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1510 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001511#else
1512 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1513#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001514 if (n == size_t(-1))
1515 {
1516 // need to recover to_nxt
1517 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1518 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001519#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001520 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1521 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001522#else
1523 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1524#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001525 switch (n)
1526 {
1527 case 0:
1528 ++frm;
1529 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001530 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001531 frm_nxt = frm;
1532 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001533 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001534 frm_nxt = frm;
1535 return partial;
1536 default:
1537 frm += n;
1538 break;
1539 }
1540 }
1541 frm_nxt = frm;
1542 return frm_nxt == frm_end ? ok : partial;
1543 }
1544 if (n == 0)
1545 return error;
1546 to_nxt += n;
1547 if (to_nxt == to_end)
1548 break;
1549 if (fend != frm_end) // set up next null terminated sequence
1550 {
1551 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001552#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001553 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1554#else
1555 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1556#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001557 if (n != 0) // on error
1558 return error;
1559 ++to_nxt;
1560 ++frm_nxt;
1561 // look for next null in frm
1562 for (fend = frm_nxt; fend != frm_end; ++fend)
1563 if (*fend == 0)
1564 break;
1565 }
1566 }
1567 return frm_nxt == frm_end ? ok : partial;
1568}
1569
1570codecvt<wchar_t, char, mbstate_t>::result
1571codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1572 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1573{
1574 to_nxt = to;
1575 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001576#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001577 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1578#else
1579 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1580#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001581 if (n == size_t(-1) || n == 0) // on error
1582 return error;
1583 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001584 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001585 return partial;
1586 for (extern_type* p = tmp; n; --n) // write it
1587 *to_nxt++ = *p++;
1588 return ok;
1589}
1590
1591int
Howard Hinnantc9834542011-05-31 15:34:58 +00001592codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001593{
Howard Hinnant866569b2011-09-28 23:39:33 +00001594#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001595 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1596#else
1597 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1598#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001599 {
1600 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001601#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001602 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1603#else
1604 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1605#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001606 return 1; // which take more than 1 char to form a wchar_t
1607 return 0;
1608 }
1609 return -1;
1610}
1611
1612bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001613codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001614{
1615 return false;
1616}
1617
1618int
1619codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1620 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1621{
1622 int nbytes = 0;
1623 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1624 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001625#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001626 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001627#else
1628 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1629#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001630 switch (n)
1631 {
1632 case 0:
1633 ++nbytes;
1634 ++frm;
1635 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001636 case size_t(-1):
1637 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001638 return nbytes;
1639 default:
1640 nbytes += n;
1641 frm += n;
1642 break;
1643 }
1644 }
1645 return nbytes;
1646}
1647
1648int
Howard Hinnantc9834542011-05-31 15:34:58 +00001649codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001650{
Howard Hinnant866569b2011-09-28 23:39:33 +00001651#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001652 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001653#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001654 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001655#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001656}
1657
1658// Valid UTF ranges
1659// UTF-32 UTF-16 UTF-8 # of code points
1660// first second first second third fourth
1661// 000000 - 00007F 0000 - 007F 00 - 7F 127
1662// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1663// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1664// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1665// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1666// 00D800 - 00DFFF invalid
1667// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1668// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1669// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1670// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1671
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001672static
1673codecvt_base::result
1674utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1675 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1676 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1677{
1678 frm_nxt = frm;
1679 to_nxt = to;
1680 if (mode & generate_header)
1681 {
1682 if (to_end-to_nxt < 3)
1683 return codecvt_base::partial;
1684 *to_nxt++ = static_cast<uint8_t>(0xEF);
1685 *to_nxt++ = static_cast<uint8_t>(0xBB);
1686 *to_nxt++ = static_cast<uint8_t>(0xBF);
1687 }
1688 for (; frm_nxt < frm_end; ++frm_nxt)
1689 {
1690 uint16_t wc1 = *frm_nxt;
1691 if (wc1 > Maxcode)
1692 return codecvt_base::error;
1693 if (wc1 < 0x0080)
1694 {
1695 if (to_end-to_nxt < 1)
1696 return codecvt_base::partial;
1697 *to_nxt++ = static_cast<uint8_t>(wc1);
1698 }
1699 else if (wc1 < 0x0800)
1700 {
1701 if (to_end-to_nxt < 2)
1702 return codecvt_base::partial;
1703 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1704 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1705 }
1706 else if (wc1 < 0xD800)
1707 {
1708 if (to_end-to_nxt < 3)
1709 return codecvt_base::partial;
1710 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1711 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1712 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1713 }
1714 else if (wc1 < 0xDC00)
1715 {
1716 if (frm_end-frm_nxt < 2)
1717 return codecvt_base::partial;
1718 uint16_t wc2 = frm_nxt[1];
1719 if ((wc2 & 0xFC00) != 0xDC00)
1720 return codecvt_base::error;
1721 if (to_end-to_nxt < 4)
1722 return codecvt_base::partial;
1723 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1724 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1725 return codecvt_base::error;
1726 ++frm_nxt;
1727 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1728 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1729 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1730 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1731 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1732 }
1733 else if (wc1 < 0xE000)
1734 {
1735 return codecvt_base::error;
1736 }
1737 else
1738 {
1739 if (to_end-to_nxt < 3)
1740 return codecvt_base::partial;
1741 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1742 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1743 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1744 }
1745 }
1746 return codecvt_base::ok;
1747}
1748
1749static
1750codecvt_base::result
1751utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1752 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1753 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1754{
1755 frm_nxt = frm;
1756 to_nxt = to;
1757 if (mode & generate_header)
1758 {
1759 if (to_end-to_nxt < 3)
1760 return codecvt_base::partial;
1761 *to_nxt++ = static_cast<uint8_t>(0xEF);
1762 *to_nxt++ = static_cast<uint8_t>(0xBB);
1763 *to_nxt++ = static_cast<uint8_t>(0xBF);
1764 }
1765 for (; frm_nxt < frm_end; ++frm_nxt)
1766 {
1767 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1768 if (wc1 > Maxcode)
1769 return codecvt_base::error;
1770 if (wc1 < 0x0080)
1771 {
1772 if (to_end-to_nxt < 1)
1773 return codecvt_base::partial;
1774 *to_nxt++ = static_cast<uint8_t>(wc1);
1775 }
1776 else if (wc1 < 0x0800)
1777 {
1778 if (to_end-to_nxt < 2)
1779 return codecvt_base::partial;
1780 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1781 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1782 }
1783 else if (wc1 < 0xD800)
1784 {
1785 if (to_end-to_nxt < 3)
1786 return codecvt_base::partial;
1787 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1788 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1789 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1790 }
1791 else if (wc1 < 0xDC00)
1792 {
1793 if (frm_end-frm_nxt < 2)
1794 return codecvt_base::partial;
1795 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1796 if ((wc2 & 0xFC00) != 0xDC00)
1797 return codecvt_base::error;
1798 if (to_end-to_nxt < 4)
1799 return codecvt_base::partial;
1800 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1801 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1802 return codecvt_base::error;
1803 ++frm_nxt;
1804 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1805 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1806 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1807 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1808 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1809 }
1810 else if (wc1 < 0xE000)
1811 {
1812 return codecvt_base::error;
1813 }
1814 else
1815 {
1816 if (to_end-to_nxt < 3)
1817 return codecvt_base::partial;
1818 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1819 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1820 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1821 }
1822 }
1823 return codecvt_base::ok;
1824}
1825
1826static
1827codecvt_base::result
1828utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1829 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1830 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1831{
1832 frm_nxt = frm;
1833 to_nxt = to;
1834 if (mode & consume_header)
1835 {
1836 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1837 frm_nxt[2] == 0xBF)
1838 frm_nxt += 3;
1839 }
1840 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1841 {
1842 uint8_t c1 = *frm_nxt;
1843 if (c1 > Maxcode)
1844 return codecvt_base::error;
1845 if (c1 < 0x80)
1846 {
1847 *to_nxt = static_cast<uint16_t>(c1);
1848 ++frm_nxt;
1849 }
1850 else if (c1 < 0xC2)
1851 {
1852 return codecvt_base::error;
1853 }
1854 else if (c1 < 0xE0)
1855 {
1856 if (frm_end-frm_nxt < 2)
1857 return codecvt_base::partial;
1858 uint8_t c2 = frm_nxt[1];
1859 if ((c2 & 0xC0) != 0x80)
1860 return codecvt_base::error;
1861 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1862 if (t > Maxcode)
1863 return codecvt_base::error;
1864 *to_nxt = t;
1865 frm_nxt += 2;
1866 }
1867 else if (c1 < 0xF0)
1868 {
1869 if (frm_end-frm_nxt < 3)
1870 return codecvt_base::partial;
1871 uint8_t c2 = frm_nxt[1];
1872 uint8_t c3 = frm_nxt[2];
1873 switch (c1)
1874 {
1875 case 0xE0:
1876 if ((c2 & 0xE0) != 0xA0)
1877 return codecvt_base::error;
1878 break;
1879 case 0xED:
1880 if ((c2 & 0xE0) != 0x80)
1881 return codecvt_base::error;
1882 break;
1883 default:
1884 if ((c2 & 0xC0) != 0x80)
1885 return codecvt_base::error;
1886 break;
1887 }
1888 if ((c3 & 0xC0) != 0x80)
1889 return codecvt_base::error;
1890 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1891 | ((c2 & 0x3F) << 6)
1892 | (c3 & 0x3F));
1893 if (t > Maxcode)
1894 return codecvt_base::error;
1895 *to_nxt = t;
1896 frm_nxt += 3;
1897 }
1898 else if (c1 < 0xF5)
1899 {
1900 if (frm_end-frm_nxt < 4)
1901 return codecvt_base::partial;
1902 uint8_t c2 = frm_nxt[1];
1903 uint8_t c3 = frm_nxt[2];
1904 uint8_t c4 = frm_nxt[3];
1905 switch (c1)
1906 {
1907 case 0xF0:
1908 if (!(0x90 <= c2 && c2 <= 0xBF))
1909 return codecvt_base::error;
1910 break;
1911 case 0xF4:
1912 if ((c2 & 0xF0) != 0x80)
1913 return codecvt_base::error;
1914 break;
1915 default:
1916 if ((c2 & 0xC0) != 0x80)
1917 return codecvt_base::error;
1918 break;
1919 }
1920 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1921 return codecvt_base::error;
1922 if (to_end-to_nxt < 2)
1923 return codecvt_base::partial;
1924 if (((((unsigned long)c1 & 7) << 18) +
1925 (((unsigned long)c2 & 0x3F) << 12) +
1926 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1927 return codecvt_base::error;
1928 *to_nxt = static_cast<uint16_t>(
1929 0xD800
1930 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1931 | ((c2 & 0x0F) << 2)
1932 | ((c3 & 0x30) >> 4));
1933 *++to_nxt = static_cast<uint16_t>(
1934 0xDC00
1935 | ((c3 & 0x0F) << 6)
1936 | (c4 & 0x3F));
1937 frm_nxt += 4;
1938 }
1939 else
1940 {
1941 return codecvt_base::error;
1942 }
1943 }
1944 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1945}
1946
1947static
1948codecvt_base::result
1949utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1950 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1951 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1952{
1953 frm_nxt = frm;
1954 to_nxt = to;
1955 if (mode & consume_header)
1956 {
1957 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1958 frm_nxt[2] == 0xBF)
1959 frm_nxt += 3;
1960 }
1961 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1962 {
1963 uint8_t c1 = *frm_nxt;
1964 if (c1 > Maxcode)
1965 return codecvt_base::error;
1966 if (c1 < 0x80)
1967 {
1968 *to_nxt = static_cast<uint32_t>(c1);
1969 ++frm_nxt;
1970 }
1971 else if (c1 < 0xC2)
1972 {
1973 return codecvt_base::error;
1974 }
1975 else if (c1 < 0xE0)
1976 {
1977 if (frm_end-frm_nxt < 2)
1978 return codecvt_base::partial;
1979 uint8_t c2 = frm_nxt[1];
1980 if ((c2 & 0xC0) != 0x80)
1981 return codecvt_base::error;
1982 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1983 if (t > Maxcode)
1984 return codecvt_base::error;
1985 *to_nxt = static_cast<uint32_t>(t);
1986 frm_nxt += 2;
1987 }
1988 else if (c1 < 0xF0)
1989 {
1990 if (frm_end-frm_nxt < 3)
1991 return codecvt_base::partial;
1992 uint8_t c2 = frm_nxt[1];
1993 uint8_t c3 = frm_nxt[2];
1994 switch (c1)
1995 {
1996 case 0xE0:
1997 if ((c2 & 0xE0) != 0xA0)
1998 return codecvt_base::error;
1999 break;
2000 case 0xED:
2001 if ((c2 & 0xE0) != 0x80)
2002 return codecvt_base::error;
2003 break;
2004 default:
2005 if ((c2 & 0xC0) != 0x80)
2006 return codecvt_base::error;
2007 break;
2008 }
2009 if ((c3 & 0xC0) != 0x80)
2010 return codecvt_base::error;
2011 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2012 | ((c2 & 0x3F) << 6)
2013 | (c3 & 0x3F));
2014 if (t > Maxcode)
2015 return codecvt_base::error;
2016 *to_nxt = static_cast<uint32_t>(t);
2017 frm_nxt += 3;
2018 }
2019 else if (c1 < 0xF5)
2020 {
2021 if (frm_end-frm_nxt < 4)
2022 return codecvt_base::partial;
2023 uint8_t c2 = frm_nxt[1];
2024 uint8_t c3 = frm_nxt[2];
2025 uint8_t c4 = frm_nxt[3];
2026 switch (c1)
2027 {
2028 case 0xF0:
2029 if (!(0x90 <= c2 && c2 <= 0xBF))
2030 return codecvt_base::error;
2031 break;
2032 case 0xF4:
2033 if ((c2 & 0xF0) != 0x80)
2034 return codecvt_base::error;
2035 break;
2036 default:
2037 if ((c2 & 0xC0) != 0x80)
2038 return codecvt_base::error;
2039 break;
2040 }
2041 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2042 return codecvt_base::error;
2043 if (to_end-to_nxt < 2)
2044 return codecvt_base::partial;
2045 if (((((unsigned long)c1 & 7) << 18) +
2046 (((unsigned long)c2 & 0x3F) << 12) +
2047 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2048 return codecvt_base::error;
2049 *to_nxt = static_cast<uint32_t>(
2050 0xD800
2051 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2052 | ((c2 & 0x0F) << 2)
2053 | ((c3 & 0x30) >> 4));
2054 *++to_nxt = static_cast<uint32_t>(
2055 0xDC00
2056 | ((c3 & 0x0F) << 6)
2057 | (c4 & 0x3F));
2058 frm_nxt += 4;
2059 }
2060 else
2061 {
2062 return codecvt_base::error;
2063 }
2064 }
2065 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2066}
2067
2068static
2069int
2070utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2071 size_t mx, unsigned long Maxcode = 0x10FFFF,
2072 codecvt_mode mode = codecvt_mode(0))
2073{
2074 const uint8_t* frm_nxt = frm;
2075 if (mode & consume_header)
2076 {
2077 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2078 frm_nxt[2] == 0xBF)
2079 frm_nxt += 3;
2080 }
2081 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2082 {
2083 uint8_t c1 = *frm_nxt;
2084 if (c1 > Maxcode)
2085 break;
2086 if (c1 < 0x80)
2087 {
2088 ++frm_nxt;
2089 }
2090 else if (c1 < 0xC2)
2091 {
2092 break;
2093 }
2094 else if (c1 < 0xE0)
2095 {
2096 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2097 break;
2098 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2099 if (t > Maxcode)
2100 break;
2101 frm_nxt += 2;
2102 }
2103 else if (c1 < 0xF0)
2104 {
2105 if (frm_end-frm_nxt < 3)
2106 break;
2107 uint8_t c2 = frm_nxt[1];
2108 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002109 switch (c1)
2110 {
2111 case 0xE0:
2112 if ((c2 & 0xE0) != 0xA0)
2113 return static_cast<int>(frm_nxt - frm);
2114 break;
2115 case 0xED:
2116 if ((c2 & 0xE0) != 0x80)
2117 return static_cast<int>(frm_nxt - frm);
2118 break;
2119 default:
2120 if ((c2 & 0xC0) != 0x80)
2121 return static_cast<int>(frm_nxt - frm);
2122 break;
2123 }
2124 if ((c3 & 0xC0) != 0x80)
2125 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002126 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002127 break;
2128 frm_nxt += 3;
2129 }
2130 else if (c1 < 0xF5)
2131 {
2132 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2133 break;
2134 uint8_t c2 = frm_nxt[1];
2135 uint8_t c3 = frm_nxt[2];
2136 uint8_t c4 = frm_nxt[3];
2137 switch (c1)
2138 {
2139 case 0xF0:
2140 if (!(0x90 <= c2 && c2 <= 0xBF))
2141 return static_cast<int>(frm_nxt - frm);
2142 break;
2143 case 0xF4:
2144 if ((c2 & 0xF0) != 0x80)
2145 return static_cast<int>(frm_nxt - frm);
2146 break;
2147 default:
2148 if ((c2 & 0xC0) != 0x80)
2149 return static_cast<int>(frm_nxt - frm);
2150 break;
2151 }
2152 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2153 break;
2154 if (((((unsigned long)c1 & 7) << 18) +
2155 (((unsigned long)c2 & 0x3F) << 12) +
2156 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2157 break;
2158 ++nchar16_t;
2159 frm_nxt += 4;
2160 }
2161 else
2162 {
2163 break;
2164 }
2165 }
2166 return static_cast<int>(frm_nxt - frm);
2167}
2168
2169static
2170codecvt_base::result
2171ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2172 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2173 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2174{
2175 frm_nxt = frm;
2176 to_nxt = to;
2177 if (mode & generate_header)
2178 {
2179 if (to_end-to_nxt < 3)
2180 return codecvt_base::partial;
2181 *to_nxt++ = static_cast<uint8_t>(0xEF);
2182 *to_nxt++ = static_cast<uint8_t>(0xBB);
2183 *to_nxt++ = static_cast<uint8_t>(0xBF);
2184 }
2185 for (; frm_nxt < frm_end; ++frm_nxt)
2186 {
2187 uint32_t wc = *frm_nxt;
2188 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2189 return codecvt_base::error;
2190 if (wc < 0x000080)
2191 {
2192 if (to_end-to_nxt < 1)
2193 return codecvt_base::partial;
2194 *to_nxt++ = static_cast<uint8_t>(wc);
2195 }
2196 else if (wc < 0x000800)
2197 {
2198 if (to_end-to_nxt < 2)
2199 return codecvt_base::partial;
2200 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2201 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2202 }
2203 else if (wc < 0x010000)
2204 {
2205 if (to_end-to_nxt < 3)
2206 return codecvt_base::partial;
2207 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2208 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2209 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2210 }
2211 else // if (wc < 0x110000)
2212 {
2213 if (to_end-to_nxt < 4)
2214 return codecvt_base::partial;
2215 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2216 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2217 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2218 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2219 }
2220 }
2221 return codecvt_base::ok;
2222}
2223
2224static
2225codecvt_base::result
2226utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2227 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2228 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2229{
2230 frm_nxt = frm;
2231 to_nxt = to;
2232 if (mode & consume_header)
2233 {
2234 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2235 frm_nxt[2] == 0xBF)
2236 frm_nxt += 3;
2237 }
2238 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2239 {
2240 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2241 if (c1 < 0x80)
2242 {
2243 if (c1 > Maxcode)
2244 return codecvt_base::error;
2245 *to_nxt = static_cast<uint32_t>(c1);
2246 ++frm_nxt;
2247 }
2248 else if (c1 < 0xC2)
2249 {
2250 return codecvt_base::error;
2251 }
2252 else if (c1 < 0xE0)
2253 {
2254 if (frm_end-frm_nxt < 2)
2255 return codecvt_base::partial;
2256 uint8_t c2 = frm_nxt[1];
2257 if ((c2 & 0xC0) != 0x80)
2258 return codecvt_base::error;
2259 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2260 | (c2 & 0x3F));
2261 if (t > Maxcode)
2262 return codecvt_base::error;
2263 *to_nxt = t;
2264 frm_nxt += 2;
2265 }
2266 else if (c1 < 0xF0)
2267 {
2268 if (frm_end-frm_nxt < 3)
2269 return codecvt_base::partial;
2270 uint8_t c2 = frm_nxt[1];
2271 uint8_t c3 = frm_nxt[2];
2272 switch (c1)
2273 {
2274 case 0xE0:
2275 if ((c2 & 0xE0) != 0xA0)
2276 return codecvt_base::error;
2277 break;
2278 case 0xED:
2279 if ((c2 & 0xE0) != 0x80)
2280 return codecvt_base::error;
2281 break;
2282 default:
2283 if ((c2 & 0xC0) != 0x80)
2284 return codecvt_base::error;
2285 break;
2286 }
2287 if ((c3 & 0xC0) != 0x80)
2288 return codecvt_base::error;
2289 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2290 | ((c2 & 0x3F) << 6)
2291 | (c3 & 0x3F));
2292 if (t > Maxcode)
2293 return codecvt_base::error;
2294 *to_nxt = t;
2295 frm_nxt += 3;
2296 }
2297 else if (c1 < 0xF5)
2298 {
2299 if (frm_end-frm_nxt < 4)
2300 return codecvt_base::partial;
2301 uint8_t c2 = frm_nxt[1];
2302 uint8_t c3 = frm_nxt[2];
2303 uint8_t c4 = frm_nxt[3];
2304 switch (c1)
2305 {
2306 case 0xF0:
2307 if (!(0x90 <= c2 && c2 <= 0xBF))
2308 return codecvt_base::error;
2309 break;
2310 case 0xF4:
2311 if ((c2 & 0xF0) != 0x80)
2312 return codecvt_base::error;
2313 break;
2314 default:
2315 if ((c2 & 0xC0) != 0x80)
2316 return codecvt_base::error;
2317 break;
2318 }
2319 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2320 return codecvt_base::error;
2321 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2322 | ((c2 & 0x3F) << 12)
2323 | ((c3 & 0x3F) << 6)
2324 | (c4 & 0x3F));
2325 if (t > Maxcode)
2326 return codecvt_base::error;
2327 *to_nxt = t;
2328 frm_nxt += 4;
2329 }
2330 else
2331 {
2332 return codecvt_base::error;
2333 }
2334 }
2335 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2336}
2337
2338static
2339int
2340utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2341 size_t mx, unsigned long Maxcode = 0x10FFFF,
2342 codecvt_mode mode = codecvt_mode(0))
2343{
2344 const uint8_t* frm_nxt = frm;
2345 if (mode & consume_header)
2346 {
2347 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2348 frm_nxt[2] == 0xBF)
2349 frm_nxt += 3;
2350 }
2351 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2352 {
2353 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2354 if (c1 < 0x80)
2355 {
2356 if (c1 > Maxcode)
2357 break;
2358 ++frm_nxt;
2359 }
2360 else if (c1 < 0xC2)
2361 {
2362 break;
2363 }
2364 else if (c1 < 0xE0)
2365 {
2366 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2367 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002368 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002369 break;
2370 frm_nxt += 2;
2371 }
2372 else if (c1 < 0xF0)
2373 {
2374 if (frm_end-frm_nxt < 3)
2375 break;
2376 uint8_t c2 = frm_nxt[1];
2377 uint8_t c3 = frm_nxt[2];
2378 switch (c1)
2379 {
2380 case 0xE0:
2381 if ((c2 & 0xE0) != 0xA0)
2382 return static_cast<int>(frm_nxt - frm);
2383 break;
2384 case 0xED:
2385 if ((c2 & 0xE0) != 0x80)
2386 return static_cast<int>(frm_nxt - frm);
2387 break;
2388 default:
2389 if ((c2 & 0xC0) != 0x80)
2390 return static_cast<int>(frm_nxt - frm);
2391 break;
2392 }
2393 if ((c3 & 0xC0) != 0x80)
2394 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002395 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002396 break;
2397 frm_nxt += 3;
2398 }
2399 else if (c1 < 0xF5)
2400 {
2401 if (frm_end-frm_nxt < 4)
2402 break;
2403 uint8_t c2 = frm_nxt[1];
2404 uint8_t c3 = frm_nxt[2];
2405 uint8_t c4 = frm_nxt[3];
2406 switch (c1)
2407 {
2408 case 0xF0:
2409 if (!(0x90 <= c2 && c2 <= 0xBF))
2410 return static_cast<int>(frm_nxt - frm);
2411 break;
2412 case 0xF4:
2413 if ((c2 & 0xF0) != 0x80)
2414 return static_cast<int>(frm_nxt - frm);
2415 break;
2416 default:
2417 if ((c2 & 0xC0) != 0x80)
2418 return static_cast<int>(frm_nxt - frm);
2419 break;
2420 }
2421 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2422 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002423 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2424 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002425 break;
2426 frm_nxt += 4;
2427 }
2428 else
2429 {
2430 break;
2431 }
2432 }
2433 return static_cast<int>(frm_nxt - frm);
2434}
2435
2436static
2437codecvt_base::result
2438ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2439 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2440 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2441{
2442 frm_nxt = frm;
2443 to_nxt = to;
2444 if (mode & generate_header)
2445 {
2446 if (to_end-to_nxt < 3)
2447 return codecvt_base::partial;
2448 *to_nxt++ = static_cast<uint8_t>(0xEF);
2449 *to_nxt++ = static_cast<uint8_t>(0xBB);
2450 *to_nxt++ = static_cast<uint8_t>(0xBF);
2451 }
2452 for (; frm_nxt < frm_end; ++frm_nxt)
2453 {
2454 uint16_t wc = *frm_nxt;
2455 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2456 return codecvt_base::error;
2457 if (wc < 0x0080)
2458 {
2459 if (to_end-to_nxt < 1)
2460 return codecvt_base::partial;
2461 *to_nxt++ = static_cast<uint8_t>(wc);
2462 }
2463 else if (wc < 0x0800)
2464 {
2465 if (to_end-to_nxt < 2)
2466 return codecvt_base::partial;
2467 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2468 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2469 }
2470 else // if (wc <= 0xFFFF)
2471 {
2472 if (to_end-to_nxt < 3)
2473 return codecvt_base::partial;
2474 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2475 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2476 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2477 }
2478 }
2479 return codecvt_base::ok;
2480}
2481
2482static
2483codecvt_base::result
2484utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2485 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2486 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2487{
2488 frm_nxt = frm;
2489 to_nxt = to;
2490 if (mode & consume_header)
2491 {
2492 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2493 frm_nxt[2] == 0xBF)
2494 frm_nxt += 3;
2495 }
2496 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2497 {
2498 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2499 if (c1 < 0x80)
2500 {
2501 if (c1 > Maxcode)
2502 return codecvt_base::error;
2503 *to_nxt = static_cast<uint16_t>(c1);
2504 ++frm_nxt;
2505 }
2506 else if (c1 < 0xC2)
2507 {
2508 return codecvt_base::error;
2509 }
2510 else if (c1 < 0xE0)
2511 {
2512 if (frm_end-frm_nxt < 2)
2513 return codecvt_base::partial;
2514 uint8_t c2 = frm_nxt[1];
2515 if ((c2 & 0xC0) != 0x80)
2516 return codecvt_base::error;
2517 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2518 | (c2 & 0x3F));
2519 if (t > Maxcode)
2520 return codecvt_base::error;
2521 *to_nxt = t;
2522 frm_nxt += 2;
2523 }
2524 else if (c1 < 0xF0)
2525 {
2526 if (frm_end-frm_nxt < 3)
2527 return codecvt_base::partial;
2528 uint8_t c2 = frm_nxt[1];
2529 uint8_t c3 = frm_nxt[2];
2530 switch (c1)
2531 {
2532 case 0xE0:
2533 if ((c2 & 0xE0) != 0xA0)
2534 return codecvt_base::error;
2535 break;
2536 case 0xED:
2537 if ((c2 & 0xE0) != 0x80)
2538 return codecvt_base::error;
2539 break;
2540 default:
2541 if ((c2 & 0xC0) != 0x80)
2542 return codecvt_base::error;
2543 break;
2544 }
2545 if ((c3 & 0xC0) != 0x80)
2546 return codecvt_base::error;
2547 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2548 | ((c2 & 0x3F) << 6)
2549 | (c3 & 0x3F));
2550 if (t > Maxcode)
2551 return codecvt_base::error;
2552 *to_nxt = t;
2553 frm_nxt += 3;
2554 }
2555 else
2556 {
2557 return codecvt_base::error;
2558 }
2559 }
2560 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2561}
2562
2563static
2564int
2565utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2566 size_t mx, unsigned long Maxcode = 0x10FFFF,
2567 codecvt_mode mode = codecvt_mode(0))
2568{
2569 const uint8_t* frm_nxt = frm;
2570 if (mode & consume_header)
2571 {
2572 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2573 frm_nxt[2] == 0xBF)
2574 frm_nxt += 3;
2575 }
2576 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2577 {
2578 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2579 if (c1 < 0x80)
2580 {
2581 if (c1 > Maxcode)
2582 break;
2583 ++frm_nxt;
2584 }
2585 else if (c1 < 0xC2)
2586 {
2587 break;
2588 }
2589 else if (c1 < 0xE0)
2590 {
2591 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2592 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002593 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002594 break;
2595 frm_nxt += 2;
2596 }
2597 else if (c1 < 0xF0)
2598 {
2599 if (frm_end-frm_nxt < 3)
2600 break;
2601 uint8_t c2 = frm_nxt[1];
2602 uint8_t c3 = frm_nxt[2];
2603 switch (c1)
2604 {
2605 case 0xE0:
2606 if ((c2 & 0xE0) != 0xA0)
2607 return static_cast<int>(frm_nxt - frm);
2608 break;
2609 case 0xED:
2610 if ((c2 & 0xE0) != 0x80)
2611 return static_cast<int>(frm_nxt - frm);
2612 break;
2613 default:
2614 if ((c2 & 0xC0) != 0x80)
2615 return static_cast<int>(frm_nxt - frm);
2616 break;
2617 }
2618 if ((c3 & 0xC0) != 0x80)
2619 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002620 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002621 break;
2622 frm_nxt += 3;
2623 }
2624 else
2625 {
2626 break;
2627 }
2628 }
2629 return static_cast<int>(frm_nxt - frm);
2630}
2631
2632static
2633codecvt_base::result
2634ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2635 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2636 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2637{
2638 frm_nxt = frm;
2639 to_nxt = to;
2640 if (mode & generate_header)
2641 {
2642 if (to_end-to_nxt < 2)
2643 return codecvt_base::partial;
2644 *to_nxt++ = static_cast<uint8_t>(0xFE);
2645 *to_nxt++ = static_cast<uint8_t>(0xFF);
2646 }
2647 for (; frm_nxt < frm_end; ++frm_nxt)
2648 {
2649 uint32_t wc = *frm_nxt;
2650 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2651 return codecvt_base::error;
2652 if (wc < 0x010000)
2653 {
2654 if (to_end-to_nxt < 2)
2655 return codecvt_base::partial;
2656 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2657 *to_nxt++ = static_cast<uint8_t>(wc);
2658 }
2659 else
2660 {
2661 if (to_end-to_nxt < 4)
2662 return codecvt_base::partial;
2663 uint16_t t = static_cast<uint16_t>(
2664 0xD800
2665 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2666 | ((wc & 0x00FC00) >> 10));
2667 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2668 *to_nxt++ = static_cast<uint8_t>(t);
2669 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2670 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2671 *to_nxt++ = static_cast<uint8_t>(t);
2672 }
2673 }
2674 return codecvt_base::ok;
2675}
2676
2677static
2678codecvt_base::result
2679utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2680 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2681 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2682{
2683 frm_nxt = frm;
2684 to_nxt = to;
2685 if (mode & consume_header)
2686 {
2687 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2688 frm_nxt += 2;
2689 }
2690 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2691 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002692 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002693 if ((c1 & 0xFC00) == 0xDC00)
2694 return codecvt_base::error;
2695 if ((c1 & 0xFC00) != 0xD800)
2696 {
2697 if (c1 > Maxcode)
2698 return codecvt_base::error;
2699 *to_nxt = static_cast<uint32_t>(c1);
2700 frm_nxt += 2;
2701 }
2702 else
2703 {
2704 if (frm_end-frm_nxt < 4)
2705 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002706 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002707 if ((c2 & 0xFC00) != 0xDC00)
2708 return codecvt_base::error;
2709 uint32_t t = static_cast<uint32_t>(
2710 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2711 | ((c1 & 0x003F) << 10)
2712 | (c2 & 0x03FF));
2713 if (t > Maxcode)
2714 return codecvt_base::error;
2715 *to_nxt = t;
2716 frm_nxt += 4;
2717 }
2718 }
2719 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2720}
2721
2722static
2723int
2724utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2725 size_t mx, unsigned long Maxcode = 0x10FFFF,
2726 codecvt_mode mode = codecvt_mode(0))
2727{
2728 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002729 if (mode & consume_header)
2730 {
2731 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2732 frm_nxt += 2;
2733 }
2734 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2735 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002736 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002737 if ((c1 & 0xFC00) == 0xDC00)
2738 break;
2739 if ((c1 & 0xFC00) != 0xD800)
2740 {
2741 if (c1 > Maxcode)
2742 break;
2743 frm_nxt += 2;
2744 }
2745 else
2746 {
2747 if (frm_end-frm_nxt < 4)
2748 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002749 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002750 if ((c2 & 0xFC00) != 0xDC00)
2751 break;
2752 uint32_t t = static_cast<uint32_t>(
2753 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2754 | ((c1 & 0x003F) << 10)
2755 | (c2 & 0x03FF));
2756 if (t > Maxcode)
2757 break;
2758 frm_nxt += 4;
2759 }
2760 }
2761 return static_cast<int>(frm_nxt - frm);
2762}
2763
2764static
2765codecvt_base::result
2766ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2767 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2768 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2769{
2770 frm_nxt = frm;
2771 to_nxt = to;
2772 if (mode & generate_header)
2773 {
2774 if (to_end-to_nxt < 2)
2775 return codecvt_base::partial;
2776 *to_nxt++ = static_cast<uint8_t>(0xFF);
2777 *to_nxt++ = static_cast<uint8_t>(0xFE);
2778 }
2779 for (; frm_nxt < frm_end; ++frm_nxt)
2780 {
2781 uint32_t wc = *frm_nxt;
2782 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2783 return codecvt_base::error;
2784 if (wc < 0x010000)
2785 {
2786 if (to_end-to_nxt < 2)
2787 return codecvt_base::partial;
2788 *to_nxt++ = static_cast<uint8_t>(wc);
2789 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2790 }
2791 else
2792 {
2793 if (to_end-to_nxt < 4)
2794 return codecvt_base::partial;
2795 uint16_t t = static_cast<uint16_t>(
2796 0xD800
2797 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2798 | ((wc & 0x00FC00) >> 10));
2799 *to_nxt++ = static_cast<uint8_t>(t);
2800 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2801 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2802 *to_nxt++ = static_cast<uint8_t>(t);
2803 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2804 }
2805 }
2806 return codecvt_base::ok;
2807}
2808
2809static
2810codecvt_base::result
2811utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2812 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2813 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2814{
2815 frm_nxt = frm;
2816 to_nxt = to;
2817 if (mode & consume_header)
2818 {
2819 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2820 frm_nxt += 2;
2821 }
2822 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2823 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002824 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002825 if ((c1 & 0xFC00) == 0xDC00)
2826 return codecvt_base::error;
2827 if ((c1 & 0xFC00) != 0xD800)
2828 {
2829 if (c1 > Maxcode)
2830 return codecvt_base::error;
2831 *to_nxt = static_cast<uint32_t>(c1);
2832 frm_nxt += 2;
2833 }
2834 else
2835 {
2836 if (frm_end-frm_nxt < 4)
2837 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002838 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002839 if ((c2 & 0xFC00) != 0xDC00)
2840 return codecvt_base::error;
2841 uint32_t t = static_cast<uint32_t>(
2842 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2843 | ((c1 & 0x003F) << 10)
2844 | (c2 & 0x03FF));
2845 if (t > Maxcode)
2846 return codecvt_base::error;
2847 *to_nxt = t;
2848 frm_nxt += 4;
2849 }
2850 }
2851 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2852}
2853
2854static
2855int
2856utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2857 size_t mx, unsigned long Maxcode = 0x10FFFF,
2858 codecvt_mode mode = codecvt_mode(0))
2859{
2860 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002861 if (mode & consume_header)
2862 {
2863 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2864 frm_nxt += 2;
2865 }
2866 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2867 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002868 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002869 if ((c1 & 0xFC00) == 0xDC00)
2870 break;
2871 if ((c1 & 0xFC00) != 0xD800)
2872 {
2873 if (c1 > Maxcode)
2874 break;
2875 frm_nxt += 2;
2876 }
2877 else
2878 {
2879 if (frm_end-frm_nxt < 4)
2880 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002881 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002882 if ((c2 & 0xFC00) != 0xDC00)
2883 break;
2884 uint32_t t = static_cast<uint32_t>(
2885 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2886 | ((c1 & 0x003F) << 10)
2887 | (c2 & 0x03FF));
2888 if (t > Maxcode)
2889 break;
2890 frm_nxt += 4;
2891 }
2892 }
2893 return static_cast<int>(frm_nxt - frm);
2894}
2895
2896static
2897codecvt_base::result
2898ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2899 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2900 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2901{
2902 frm_nxt = frm;
2903 to_nxt = to;
2904 if (mode & generate_header)
2905 {
2906 if (to_end-to_nxt < 2)
2907 return codecvt_base::partial;
2908 *to_nxt++ = static_cast<uint8_t>(0xFE);
2909 *to_nxt++ = static_cast<uint8_t>(0xFF);
2910 }
2911 for (; frm_nxt < frm_end; ++frm_nxt)
2912 {
2913 uint16_t wc = *frm_nxt;
2914 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2915 return codecvt_base::error;
2916 if (to_end-to_nxt < 2)
2917 return codecvt_base::partial;
2918 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2919 *to_nxt++ = static_cast<uint8_t>(wc);
2920 }
2921 return codecvt_base::ok;
2922}
2923
2924static
2925codecvt_base::result
2926utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2927 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2928 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2929{
2930 frm_nxt = frm;
2931 to_nxt = to;
2932 if (mode & consume_header)
2933 {
2934 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2935 frm_nxt += 2;
2936 }
2937 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2938 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002939 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002940 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2941 return codecvt_base::error;
2942 *to_nxt = c1;
2943 frm_nxt += 2;
2944 }
2945 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2946}
2947
2948static
2949int
2950utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2951 size_t mx, unsigned long Maxcode = 0x10FFFF,
2952 codecvt_mode mode = codecvt_mode(0))
2953{
2954 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002955 if (mode & consume_header)
2956 {
2957 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2958 frm_nxt += 2;
2959 }
2960 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2961 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002962 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002963 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2964 break;
2965 frm_nxt += 2;
2966 }
2967 return static_cast<int>(frm_nxt - frm);
2968}
2969
2970static
2971codecvt_base::result
2972ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2973 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2974 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2975{
2976 frm_nxt = frm;
2977 to_nxt = to;
2978 if (mode & generate_header)
2979 {
2980 if (to_end-to_nxt < 2)
2981 return codecvt_base::partial;
2982 *to_nxt++ = static_cast<uint8_t>(0xFF);
2983 *to_nxt++ = static_cast<uint8_t>(0xFE);
2984 }
2985 for (; frm_nxt < frm_end; ++frm_nxt)
2986 {
2987 uint16_t wc = *frm_nxt;
2988 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2989 return codecvt_base::error;
2990 if (to_end-to_nxt < 2)
2991 return codecvt_base::partial;
2992 *to_nxt++ = static_cast<uint8_t>(wc);
2993 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2994 }
2995 return codecvt_base::ok;
2996}
2997
2998static
2999codecvt_base::result
3000utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3001 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3002 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3003{
3004 frm_nxt = frm;
3005 to_nxt = to;
3006 if (mode & consume_header)
3007 {
3008 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3009 frm_nxt += 2;
3010 }
3011 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3012 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003013 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003014 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3015 return codecvt_base::error;
3016 *to_nxt = c1;
3017 frm_nxt += 2;
3018 }
3019 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3020}
3021
3022static
3023int
3024utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3025 size_t mx, unsigned long Maxcode = 0x10FFFF,
3026 codecvt_mode mode = codecvt_mode(0))
3027{
3028 const uint8_t* frm_nxt = frm;
3029 frm_nxt = frm;
3030 if (mode & consume_header)
3031 {
3032 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3033 frm_nxt += 2;
3034 }
3035 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3036 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003037 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003038 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3039 break;
3040 frm_nxt += 2;
3041 }
3042 return static_cast<int>(frm_nxt - frm);
3043}
3044
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003045// template <> class codecvt<char16_t, char, mbstate_t>
3046
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003047locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003048
3049codecvt<char16_t, char, mbstate_t>::~codecvt()
3050{
3051}
3052
3053codecvt<char16_t, char, mbstate_t>::result
3054codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003055 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003056 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3057{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003058 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3059 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3060 const uint16_t* _frm_nxt = _frm;
3061 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3062 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3063 uint8_t* _to_nxt = _to;
3064 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3065 frm_nxt = frm + (_frm_nxt - _frm);
3066 to_nxt = to + (_to_nxt - _to);
3067 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003068}
3069
3070codecvt<char16_t, char, mbstate_t>::result
3071codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003072 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003073 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3074{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003075 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3076 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3077 const uint8_t* _frm_nxt = _frm;
3078 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3079 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3080 uint16_t* _to_nxt = _to;
3081 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3082 frm_nxt = frm + (_frm_nxt - _frm);
3083 to_nxt = to + (_to_nxt - _to);
3084 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003085}
3086
3087codecvt<char16_t, char, mbstate_t>::result
3088codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3089 extern_type* to, extern_type*, extern_type*& to_nxt) const
3090{
3091 to_nxt = to;
3092 return noconv;
3093}
3094
3095int
Howard Hinnantc9834542011-05-31 15:34:58 +00003096codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003097{
3098 return 0;
3099}
3100
3101bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003102codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003103{
3104 return false;
3105}
3106
3107int
3108codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3109 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3110{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003111 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3112 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3113 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003114}
3115
3116int
Howard Hinnantc9834542011-05-31 15:34:58 +00003117codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003118{
3119 return 4;
3120}
3121
3122// template <> class codecvt<char32_t, char, mbstate_t>
3123
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003124locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003125
3126codecvt<char32_t, char, mbstate_t>::~codecvt()
3127{
3128}
3129
3130codecvt<char32_t, char, mbstate_t>::result
3131codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003132 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003133 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3134{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003135 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3136 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3137 const uint32_t* _frm_nxt = _frm;
3138 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3139 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3140 uint8_t* _to_nxt = _to;
3141 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3142 frm_nxt = frm + (_frm_nxt - _frm);
3143 to_nxt = to + (_to_nxt - _to);
3144 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003145}
3146
3147codecvt<char32_t, char, mbstate_t>::result
3148codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003149 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003150 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3151{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003152 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3153 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3154 const uint8_t* _frm_nxt = _frm;
3155 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3156 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3157 uint32_t* _to_nxt = _to;
3158 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3159 frm_nxt = frm + (_frm_nxt - _frm);
3160 to_nxt = to + (_to_nxt - _to);
3161 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003162}
3163
3164codecvt<char32_t, char, mbstate_t>::result
3165codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3166 extern_type* to, extern_type*, extern_type*& to_nxt) const
3167{
3168 to_nxt = to;
3169 return noconv;
3170}
3171
3172int
Howard Hinnantc9834542011-05-31 15:34:58 +00003173codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003174{
3175 return 0;
3176}
3177
3178bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003179codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003180{
3181 return false;
3182}
3183
3184int
3185codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3186 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3187{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003188 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3189 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3190 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003191}
3192
3193int
Howard Hinnantc9834542011-05-31 15:34:58 +00003194codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003195{
3196 return 4;
3197}
3198
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003199// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003200
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003201__codecvt_utf8<wchar_t>::result
3202__codecvt_utf8<wchar_t>::do_out(state_type&,
3203 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003204 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3205{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003206#if _WIN32
3207 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3208 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3209 const uint16_t* _frm_nxt = _frm;
3210#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003211 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3212 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3213 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003214#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003215 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3216 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3217 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003218#if _WIN32
3219 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3220 _Maxcode_, _Mode_);
3221#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003222 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3223 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003224#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003225 frm_nxt = frm + (_frm_nxt - _frm);
3226 to_nxt = to + (_to_nxt - _to);
3227 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003228}
3229
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003230__codecvt_utf8<wchar_t>::result
3231__codecvt_utf8<wchar_t>::do_in(state_type&,
3232 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003233 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3234{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003235 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3236 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3237 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003238#if _WIN32
3239 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3240 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3241 uint16_t* _to_nxt = _to;
3242 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3243 _Maxcode_, _Mode_);
3244#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003245 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3246 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3247 uint32_t* _to_nxt = _to;
3248 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3249 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003250#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003251 frm_nxt = frm + (_frm_nxt - _frm);
3252 to_nxt = to + (_to_nxt - _to);
3253 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003254}
3255
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003256__codecvt_utf8<wchar_t>::result
3257__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003258 extern_type* to, extern_type*, extern_type*& to_nxt) const
3259{
3260 to_nxt = to;
3261 return noconv;
3262}
3263
3264int
Howard Hinnantc9834542011-05-31 15:34:58 +00003265__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003266{
3267 return 0;
3268}
3269
3270bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003271__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003272{
3273 return false;
3274}
3275
3276int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003277__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003278 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3279{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003280 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3281 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3282 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003283}
3284
3285int
Howard Hinnantc9834542011-05-31 15:34:58 +00003286__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003287{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003288 if (_Mode_ & consume_header)
3289 return 7;
3290 return 4;
3291}
3292
3293// __codecvt_utf8<char16_t>
3294
3295__codecvt_utf8<char16_t>::result
3296__codecvt_utf8<char16_t>::do_out(state_type&,
3297 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3298 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3299{
3300 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3301 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3302 const uint16_t* _frm_nxt = _frm;
3303 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3304 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3305 uint8_t* _to_nxt = _to;
3306 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3307 _Maxcode_, _Mode_);
3308 frm_nxt = frm + (_frm_nxt - _frm);
3309 to_nxt = to + (_to_nxt - _to);
3310 return r;
3311}
3312
3313__codecvt_utf8<char16_t>::result
3314__codecvt_utf8<char16_t>::do_in(state_type&,
3315 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3316 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3317{
3318 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3319 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3320 const uint8_t* _frm_nxt = _frm;
3321 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3322 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3323 uint16_t* _to_nxt = _to;
3324 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3325 _Maxcode_, _Mode_);
3326 frm_nxt = frm + (_frm_nxt - _frm);
3327 to_nxt = to + (_to_nxt - _to);
3328 return r;
3329}
3330
3331__codecvt_utf8<char16_t>::result
3332__codecvt_utf8<char16_t>::do_unshift(state_type&,
3333 extern_type* to, extern_type*, extern_type*& to_nxt) const
3334{
3335 to_nxt = to;
3336 return noconv;
3337}
3338
3339int
Howard Hinnantc9834542011-05-31 15:34:58 +00003340__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003341{
3342 return 0;
3343}
3344
3345bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003346__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003347{
3348 return false;
3349}
3350
3351int
3352__codecvt_utf8<char16_t>::do_length(state_type&,
3353 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3354{
3355 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3356 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3357 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3358}
3359
3360int
Howard Hinnantc9834542011-05-31 15:34:58 +00003361__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003362{
3363 if (_Mode_ & consume_header)
3364 return 6;
3365 return 3;
3366}
3367
3368// __codecvt_utf8<char32_t>
3369
3370__codecvt_utf8<char32_t>::result
3371__codecvt_utf8<char32_t>::do_out(state_type&,
3372 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3373 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3374{
3375 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3376 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3377 const uint32_t* _frm_nxt = _frm;
3378 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3379 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3380 uint8_t* _to_nxt = _to;
3381 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3382 _Maxcode_, _Mode_);
3383 frm_nxt = frm + (_frm_nxt - _frm);
3384 to_nxt = to + (_to_nxt - _to);
3385 return r;
3386}
3387
3388__codecvt_utf8<char32_t>::result
3389__codecvt_utf8<char32_t>::do_in(state_type&,
3390 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3391 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3392{
3393 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3394 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3395 const uint8_t* _frm_nxt = _frm;
3396 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3397 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3398 uint32_t* _to_nxt = _to;
3399 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3400 _Maxcode_, _Mode_);
3401 frm_nxt = frm + (_frm_nxt - _frm);
3402 to_nxt = to + (_to_nxt - _to);
3403 return r;
3404}
3405
3406__codecvt_utf8<char32_t>::result
3407__codecvt_utf8<char32_t>::do_unshift(state_type&,
3408 extern_type* to, extern_type*, extern_type*& to_nxt) const
3409{
3410 to_nxt = to;
3411 return noconv;
3412}
3413
3414int
Howard Hinnantc9834542011-05-31 15:34:58 +00003415__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003416{
3417 return 0;
3418}
3419
3420bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003421__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003422{
3423 return false;
3424}
3425
3426int
3427__codecvt_utf8<char32_t>::do_length(state_type&,
3428 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3429{
3430 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3431 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3432 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3433}
3434
3435int
Howard Hinnantc9834542011-05-31 15:34:58 +00003436__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003437{
3438 if (_Mode_ & consume_header)
3439 return 7;
3440 return 4;
3441}
3442
3443// __codecvt_utf16<wchar_t, false>
3444
3445__codecvt_utf16<wchar_t, false>::result
3446__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3447 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3448 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3449{
3450 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3451 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3452 const uint32_t* _frm_nxt = _frm;
3453 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3454 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3455 uint8_t* _to_nxt = _to;
3456 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3457 _Maxcode_, _Mode_);
3458 frm_nxt = frm + (_frm_nxt - _frm);
3459 to_nxt = to + (_to_nxt - _to);
3460 return r;
3461}
3462
3463__codecvt_utf16<wchar_t, false>::result
3464__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3465 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3466 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3467{
3468 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3469 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3470 const uint8_t* _frm_nxt = _frm;
3471 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3472 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3473 uint32_t* _to_nxt = _to;
3474 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3475 _Maxcode_, _Mode_);
3476 frm_nxt = frm + (_frm_nxt - _frm);
3477 to_nxt = to + (_to_nxt - _to);
3478 return r;
3479}
3480
3481__codecvt_utf16<wchar_t, false>::result
3482__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3483 extern_type* to, extern_type*, extern_type*& to_nxt) const
3484{
3485 to_nxt = to;
3486 return noconv;
3487}
3488
3489int
Howard Hinnantc9834542011-05-31 15:34:58 +00003490__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003491{
3492 return 0;
3493}
3494
3495bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003496__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003497{
3498 return false;
3499}
3500
3501int
3502__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3503 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3504{
3505 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3506 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3507 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3508}
3509
3510int
Howard Hinnantc9834542011-05-31 15:34:58 +00003511__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003512{
3513 if (_Mode_ & consume_header)
3514 return 6;
3515 return 4;
3516}
3517
3518// __codecvt_utf16<wchar_t, true>
3519
3520__codecvt_utf16<wchar_t, true>::result
3521__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3522 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3523 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3524{
3525 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3526 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3527 const uint32_t* _frm_nxt = _frm;
3528 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3529 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3530 uint8_t* _to_nxt = _to;
3531 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3532 _Maxcode_, _Mode_);
3533 frm_nxt = frm + (_frm_nxt - _frm);
3534 to_nxt = to + (_to_nxt - _to);
3535 return r;
3536}
3537
3538__codecvt_utf16<wchar_t, true>::result
3539__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3540 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3541 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3542{
3543 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3544 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3545 const uint8_t* _frm_nxt = _frm;
3546 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3547 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3548 uint32_t* _to_nxt = _to;
3549 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3550 _Maxcode_, _Mode_);
3551 frm_nxt = frm + (_frm_nxt - _frm);
3552 to_nxt = to + (_to_nxt - _to);
3553 return r;
3554}
3555
3556__codecvt_utf16<wchar_t, true>::result
3557__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3558 extern_type* to, extern_type*, extern_type*& to_nxt) const
3559{
3560 to_nxt = to;
3561 return noconv;
3562}
3563
3564int
Howard Hinnantc9834542011-05-31 15:34:58 +00003565__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003566{
3567 return 0;
3568}
3569
3570bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003571__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003572{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003573 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003574}
3575
3576int
3577__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3578 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3579{
3580 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3581 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3582 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3583}
3584
3585int
Howard Hinnantc9834542011-05-31 15:34:58 +00003586__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003587{
3588 if (_Mode_ & consume_header)
3589 return 6;
3590 return 4;
3591}
3592
3593// __codecvt_utf16<char16_t, false>
3594
3595__codecvt_utf16<char16_t, false>::result
3596__codecvt_utf16<char16_t, false>::do_out(state_type&,
3597 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3598 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3599{
3600 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3601 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3602 const uint16_t* _frm_nxt = _frm;
3603 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3604 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3605 uint8_t* _to_nxt = _to;
3606 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3607 _Maxcode_, _Mode_);
3608 frm_nxt = frm + (_frm_nxt - _frm);
3609 to_nxt = to + (_to_nxt - _to);
3610 return r;
3611}
3612
3613__codecvt_utf16<char16_t, false>::result
3614__codecvt_utf16<char16_t, false>::do_in(state_type&,
3615 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3616 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3617{
3618 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3619 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3620 const uint8_t* _frm_nxt = _frm;
3621 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3622 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3623 uint16_t* _to_nxt = _to;
3624 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3625 _Maxcode_, _Mode_);
3626 frm_nxt = frm + (_frm_nxt - _frm);
3627 to_nxt = to + (_to_nxt - _to);
3628 return r;
3629}
3630
3631__codecvt_utf16<char16_t, false>::result
3632__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3633 extern_type* to, extern_type*, extern_type*& to_nxt) const
3634{
3635 to_nxt = to;
3636 return noconv;
3637}
3638
3639int
Howard Hinnantc9834542011-05-31 15:34:58 +00003640__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003641{
3642 return 0;
3643}
3644
3645bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003646__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003647{
3648 return false;
3649}
3650
3651int
3652__codecvt_utf16<char16_t, false>::do_length(state_type&,
3653 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3654{
3655 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3656 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3657 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3658}
3659
3660int
Howard Hinnantc9834542011-05-31 15:34:58 +00003661__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003662{
3663 if (_Mode_ & consume_header)
3664 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003665 return 2;
3666}
3667
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003668// __codecvt_utf16<char16_t, true>
3669
3670__codecvt_utf16<char16_t, true>::result
3671__codecvt_utf16<char16_t, true>::do_out(state_type&,
3672 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3673 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3674{
3675 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3676 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3677 const uint16_t* _frm_nxt = _frm;
3678 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3679 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3680 uint8_t* _to_nxt = _to;
3681 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3682 _Maxcode_, _Mode_);
3683 frm_nxt = frm + (_frm_nxt - _frm);
3684 to_nxt = to + (_to_nxt - _to);
3685 return r;
3686}
3687
3688__codecvt_utf16<char16_t, true>::result
3689__codecvt_utf16<char16_t, true>::do_in(state_type&,
3690 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3691 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3692{
3693 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3694 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3695 const uint8_t* _frm_nxt = _frm;
3696 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3697 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3698 uint16_t* _to_nxt = _to;
3699 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3700 _Maxcode_, _Mode_);
3701 frm_nxt = frm + (_frm_nxt - _frm);
3702 to_nxt = to + (_to_nxt - _to);
3703 return r;
3704}
3705
3706__codecvt_utf16<char16_t, true>::result
3707__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3708 extern_type* to, extern_type*, extern_type*& to_nxt) const
3709{
3710 to_nxt = to;
3711 return noconv;
3712}
3713
3714int
Howard Hinnantc9834542011-05-31 15:34:58 +00003715__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003716{
3717 return 0;
3718}
3719
3720bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003721__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003722{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003723 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003724}
3725
3726int
3727__codecvt_utf16<char16_t, true>::do_length(state_type&,
3728 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3729{
3730 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3731 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3732 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3733}
3734
3735int
Howard Hinnantc9834542011-05-31 15:34:58 +00003736__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003737{
3738 if (_Mode_ & consume_header)
3739 return 4;
3740 return 2;
3741}
3742
3743// __codecvt_utf16<char32_t, false>
3744
3745__codecvt_utf16<char32_t, false>::result
3746__codecvt_utf16<char32_t, false>::do_out(state_type&,
3747 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3748 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3749{
3750 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3751 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3752 const uint32_t* _frm_nxt = _frm;
3753 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3754 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3755 uint8_t* _to_nxt = _to;
3756 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3757 _Maxcode_, _Mode_);
3758 frm_nxt = frm + (_frm_nxt - _frm);
3759 to_nxt = to + (_to_nxt - _to);
3760 return r;
3761}
3762
3763__codecvt_utf16<char32_t, false>::result
3764__codecvt_utf16<char32_t, false>::do_in(state_type&,
3765 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3766 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3767{
3768 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3769 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3770 const uint8_t* _frm_nxt = _frm;
3771 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3772 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3773 uint32_t* _to_nxt = _to;
3774 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3775 _Maxcode_, _Mode_);
3776 frm_nxt = frm + (_frm_nxt - _frm);
3777 to_nxt = to + (_to_nxt - _to);
3778 return r;
3779}
3780
3781__codecvt_utf16<char32_t, false>::result
3782__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3783 extern_type* to, extern_type*, extern_type*& to_nxt) const
3784{
3785 to_nxt = to;
3786 return noconv;
3787}
3788
3789int
Howard Hinnantc9834542011-05-31 15:34:58 +00003790__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003791{
3792 return 0;
3793}
3794
3795bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003796__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003797{
3798 return false;
3799}
3800
3801int
3802__codecvt_utf16<char32_t, false>::do_length(state_type&,
3803 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3804{
3805 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3806 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3807 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3808}
3809
3810int
Howard Hinnantc9834542011-05-31 15:34:58 +00003811__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003812{
3813 if (_Mode_ & consume_header)
3814 return 6;
3815 return 4;
3816}
3817
3818// __codecvt_utf16<char32_t, true>
3819
3820__codecvt_utf16<char32_t, true>::result
3821__codecvt_utf16<char32_t, true>::do_out(state_type&,
3822 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3823 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3824{
3825 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3826 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3827 const uint32_t* _frm_nxt = _frm;
3828 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3829 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3830 uint8_t* _to_nxt = _to;
3831 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3832 _Maxcode_, _Mode_);
3833 frm_nxt = frm + (_frm_nxt - _frm);
3834 to_nxt = to + (_to_nxt - _to);
3835 return r;
3836}
3837
3838__codecvt_utf16<char32_t, true>::result
3839__codecvt_utf16<char32_t, true>::do_in(state_type&,
3840 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3841 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3842{
3843 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3844 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3845 const uint8_t* _frm_nxt = _frm;
3846 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3847 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3848 uint32_t* _to_nxt = _to;
3849 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3850 _Maxcode_, _Mode_);
3851 frm_nxt = frm + (_frm_nxt - _frm);
3852 to_nxt = to + (_to_nxt - _to);
3853 return r;
3854}
3855
3856__codecvt_utf16<char32_t, true>::result
3857__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3858 extern_type* to, extern_type*, extern_type*& to_nxt) const
3859{
3860 to_nxt = to;
3861 return noconv;
3862}
3863
3864int
Howard Hinnantc9834542011-05-31 15:34:58 +00003865__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003866{
3867 return 0;
3868}
3869
3870bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003871__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003872{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003873 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003874}
3875
3876int
3877__codecvt_utf16<char32_t, true>::do_length(state_type&,
3878 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3879{
3880 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3881 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3882 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3883}
3884
3885int
Howard Hinnantc9834542011-05-31 15:34:58 +00003886__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003887{
3888 if (_Mode_ & consume_header)
3889 return 6;
3890 return 4;
3891}
3892
3893// __codecvt_utf8_utf16<wchar_t>
3894
3895__codecvt_utf8_utf16<wchar_t>::result
3896__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3897 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3898 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3899{
3900 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3901 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3902 const uint32_t* _frm_nxt = _frm;
3903 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3904 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3905 uint8_t* _to_nxt = _to;
3906 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3907 _Maxcode_, _Mode_);
3908 frm_nxt = frm + (_frm_nxt - _frm);
3909 to_nxt = to + (_to_nxt - _to);
3910 return r;
3911}
3912
3913__codecvt_utf8_utf16<wchar_t>::result
3914__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3915 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3916 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3917{
3918 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3919 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3920 const uint8_t* _frm_nxt = _frm;
3921 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3922 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3923 uint32_t* _to_nxt = _to;
3924 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3925 _Maxcode_, _Mode_);
3926 frm_nxt = frm + (_frm_nxt - _frm);
3927 to_nxt = to + (_to_nxt - _to);
3928 return r;
3929}
3930
3931__codecvt_utf8_utf16<wchar_t>::result
3932__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3933 extern_type* to, extern_type*, extern_type*& to_nxt) const
3934{
3935 to_nxt = to;
3936 return noconv;
3937}
3938
3939int
Howard Hinnantc9834542011-05-31 15:34:58 +00003940__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003941{
3942 return 0;
3943}
3944
3945bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003946__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003947{
3948 return false;
3949}
3950
3951int
3952__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3953 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3954{
3955 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3956 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3957 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3958}
3959
3960int
Howard Hinnantc9834542011-05-31 15:34:58 +00003961__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003962{
3963 if (_Mode_ & consume_header)
3964 return 7;
3965 return 4;
3966}
3967
3968// __codecvt_utf8_utf16<char16_t>
3969
3970__codecvt_utf8_utf16<char16_t>::result
3971__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3972 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3973 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3974{
3975 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3976 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3977 const uint16_t* _frm_nxt = _frm;
3978 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3979 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3980 uint8_t* _to_nxt = _to;
3981 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3982 _Maxcode_, _Mode_);
3983 frm_nxt = frm + (_frm_nxt - _frm);
3984 to_nxt = to + (_to_nxt - _to);
3985 return r;
3986}
3987
3988__codecvt_utf8_utf16<char16_t>::result
3989__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3990 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3991 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3992{
3993 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3994 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3995 const uint8_t* _frm_nxt = _frm;
3996 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3997 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3998 uint16_t* _to_nxt = _to;
3999 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4000 _Maxcode_, _Mode_);
4001 frm_nxt = frm + (_frm_nxt - _frm);
4002 to_nxt = to + (_to_nxt - _to);
4003 return r;
4004}
4005
4006__codecvt_utf8_utf16<char16_t>::result
4007__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4008 extern_type* to, extern_type*, extern_type*& to_nxt) const
4009{
4010 to_nxt = to;
4011 return noconv;
4012}
4013
4014int
Howard Hinnantc9834542011-05-31 15:34:58 +00004015__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004016{
4017 return 0;
4018}
4019
4020bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004021__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004022{
4023 return false;
4024}
4025
4026int
4027__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4028 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4029{
4030 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4031 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4032 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4033}
4034
4035int
Howard Hinnantc9834542011-05-31 15:34:58 +00004036__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004037{
4038 if (_Mode_ & consume_header)
4039 return 7;
4040 return 4;
4041}
4042
4043// __codecvt_utf8_utf16<char32_t>
4044
4045__codecvt_utf8_utf16<char32_t>::result
4046__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4047 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4048 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4049{
4050 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4051 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4052 const uint32_t* _frm_nxt = _frm;
4053 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4054 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4055 uint8_t* _to_nxt = _to;
4056 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4057 _Maxcode_, _Mode_);
4058 frm_nxt = frm + (_frm_nxt - _frm);
4059 to_nxt = to + (_to_nxt - _to);
4060 return r;
4061}
4062
4063__codecvt_utf8_utf16<char32_t>::result
4064__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4065 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4066 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4067{
4068 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4069 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4070 const uint8_t* _frm_nxt = _frm;
4071 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4072 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4073 uint32_t* _to_nxt = _to;
4074 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4075 _Maxcode_, _Mode_);
4076 frm_nxt = frm + (_frm_nxt - _frm);
4077 to_nxt = to + (_to_nxt - _to);
4078 return r;
4079}
4080
4081__codecvt_utf8_utf16<char32_t>::result
4082__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4083 extern_type* to, extern_type*, extern_type*& to_nxt) const
4084{
4085 to_nxt = to;
4086 return noconv;
4087}
4088
4089int
Howard Hinnantc9834542011-05-31 15:34:58 +00004090__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004091{
4092 return 0;
4093}
4094
4095bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004096__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004097{
4098 return false;
4099}
4100
4101int
4102__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4103 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4104{
4105 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4106 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4107 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4108}
4109
4110int
Howard Hinnantc9834542011-05-31 15:34:58 +00004111__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004112{
4113 if (_Mode_ & consume_header)
4114 return 7;
4115 return 4;
4116}
4117
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004118// __narrow_to_utf8<16>
4119
4120__narrow_to_utf8<16>::~__narrow_to_utf8()
4121{
4122}
4123
4124// __narrow_to_utf8<32>
4125
4126__narrow_to_utf8<32>::~__narrow_to_utf8()
4127{
4128}
4129
4130// __widen_from_utf8<16>
4131
4132__widen_from_utf8<16>::~__widen_from_utf8()
4133{
4134}
4135
4136// __widen_from_utf8<32>
4137
4138__widen_from_utf8<32>::~__widen_from_utf8()
4139{
4140}
4141
4142// numpunct<char> && numpunct<wchar_t>
4143
4144locale::id numpunct< char >::id;
4145locale::id numpunct<wchar_t>::id;
4146
4147numpunct<char>::numpunct(size_t refs)
4148 : locale::facet(refs),
4149 __decimal_point_('.'),
4150 __thousands_sep_(',')
4151{
4152}
4153
4154numpunct<wchar_t>::numpunct(size_t refs)
4155 : locale::facet(refs),
4156 __decimal_point_(L'.'),
4157 __thousands_sep_(L',')
4158{
4159}
4160
4161numpunct<char>::~numpunct()
4162{
4163}
4164
4165numpunct<wchar_t>::~numpunct()
4166{
4167}
4168
4169 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4170wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4171
4172 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4173wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4174
4175string numpunct< char >::do_grouping() const {return __grouping_;}
4176string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4177
4178 string numpunct< char >::do_truename() const {return "true";}
4179wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4180
4181 string numpunct< char >::do_falsename() const {return "false";}
4182wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4183
4184// numpunct_byname<char>
4185
4186numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4187 : numpunct<char>(refs)
4188{
4189 __init(nm);
4190}
4191
4192numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4193 : numpunct<char>(refs)
4194{
4195 __init(nm.c_str());
4196}
4197
4198numpunct_byname<char>::~numpunct_byname()
4199{
4200}
4201
4202void
4203numpunct_byname<char>::__init(const char* nm)
4204{
4205 if (strcmp(nm, "C") != 0)
4206 {
Sean Huntf3907e62011-07-15 05:40:33 +00004207 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004208#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004209 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004210 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4211 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004212#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004213#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004214 lconv* lc = localeconv_l(loc.get());
4215#else
4216 lconv* lc = __localeconv_l(loc.get());
4217#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004218 if (*lc->decimal_point)
4219 __decimal_point_ = *lc->decimal_point;
4220 if (*lc->thousands_sep)
4221 __thousands_sep_ = *lc->thousands_sep;
4222 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004223 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004224 }
4225}
4226
4227// numpunct_byname<wchar_t>
4228
4229numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4230 : numpunct<wchar_t>(refs)
4231{
4232 __init(nm);
4233}
4234
4235numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4236 : numpunct<wchar_t>(refs)
4237{
4238 __init(nm.c_str());
4239}
4240
4241numpunct_byname<wchar_t>::~numpunct_byname()
4242{
4243}
4244
4245void
4246numpunct_byname<wchar_t>::__init(const char* nm)
4247{
4248 if (strcmp(nm, "C") != 0)
4249 {
Sean Huntf3907e62011-07-15 05:40:33 +00004250 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004251#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004252 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004253 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4254 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004255#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004256#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004257 lconv* lc = localeconv_l(loc.get());
4258#else
4259 lconv* lc = __localeconv_l(loc.get());
4260#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004261 if (*lc->decimal_point)
4262 __decimal_point_ = *lc->decimal_point;
4263 if (*lc->thousands_sep)
4264 __thousands_sep_ = *lc->thousands_sep;
4265 __grouping_ = lc->grouping;
4266 // locallization for truename and falsename is not available
4267 }
4268}
4269
4270// num_get helpers
4271
4272int
4273__num_get_base::__get_base(ios_base& iob)
4274{
4275 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4276 if (__basefield == ios_base::oct)
4277 return 8;
4278 else if (__basefield == ios_base::hex)
4279 return 16;
4280 else if (__basefield == 0)
4281 return 0;
4282 return 10;
4283}
4284
4285const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4286
4287void
4288__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4289 ios_base::iostate& __err)
4290{
4291 if (__grouping.size() != 0)
4292 {
4293 reverse(__g, __g_end);
4294 const char* __ig = __grouping.data();
4295 const char* __eg = __ig + __grouping.size();
4296 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4297 {
4298 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4299 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004300 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004301 {
4302 __err = ios_base::failbit;
4303 return;
4304 }
4305 }
4306 if (__eg - __ig > 1)
4307 ++__ig;
4308 }
4309 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4310 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004311 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004312 __err = ios_base::failbit;
4313 }
4314 }
4315}
4316
4317void
4318__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4319 ios_base::fmtflags __flags)
4320{
4321 if (__flags & ios_base::showpos)
4322 *__fmtp++ = '+';
4323 if (__flags & ios_base::showbase)
4324 *__fmtp++ = '#';
4325 while(*__len)
4326 *__fmtp++ = *__len++;
4327 if ((__flags & ios_base::basefield) == ios_base::oct)
4328 *__fmtp = 'o';
4329 else if ((__flags & ios_base::basefield) == ios_base::hex)
4330 {
4331 if (__flags & ios_base::uppercase)
4332 *__fmtp = 'X';
4333 else
4334 *__fmtp = 'x';
4335 }
4336 else if (__signd)
4337 *__fmtp = 'd';
4338 else
4339 *__fmtp = 'u';
4340}
4341
4342bool
4343__num_put_base::__format_float(char* __fmtp, const char* __len,
4344 ios_base::fmtflags __flags)
4345{
4346 bool specify_precision = true;
4347 if (__flags & ios_base::showpos)
4348 *__fmtp++ = '+';
4349 if (__flags & ios_base::showpoint)
4350 *__fmtp++ = '#';
4351 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4352 bool uppercase = __flags & ios_base::uppercase;
4353 if (floatfield == (ios_base::fixed | ios_base::scientific))
4354 specify_precision = false;
4355 else
4356 {
4357 *__fmtp++ = '.';
4358 *__fmtp++ = '*';
4359 }
4360 while(*__len)
4361 *__fmtp++ = *__len++;
4362 if (floatfield == ios_base::fixed)
4363 {
4364 if (uppercase)
4365 *__fmtp = 'F';
4366 else
4367 *__fmtp = 'f';
4368 }
4369 else if (floatfield == ios_base::scientific)
4370 {
4371 if (uppercase)
4372 *__fmtp = 'E';
4373 else
4374 *__fmtp = 'e';
4375 }
4376 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4377 {
4378 if (uppercase)
4379 *__fmtp = 'A';
4380 else
4381 *__fmtp = 'a';
4382 }
4383 else
4384 {
4385 if (uppercase)
4386 *__fmtp = 'G';
4387 else
4388 *__fmtp = 'g';
4389 }
4390 return specify_precision;
4391}
4392
4393char*
4394__num_put_base::__identify_padding(char* __nb, char* __ne,
4395 const ios_base& __iob)
4396{
4397 switch (__iob.flags() & ios_base::adjustfield)
4398 {
4399 case ios_base::internal:
4400 if (__nb[0] == '-' || __nb[0] == '+')
4401 return __nb+1;
4402 if (__ne - __nb >= 2 && __nb[0] == '0'
4403 && (__nb[1] == 'x' || __nb[1] == 'X'))
4404 return __nb+2;
4405 break;
4406 case ios_base::left:
4407 return __ne;
4408 case ios_base::right:
4409 default:
4410 break;
4411 }
4412 return __nb;
4413}
4414
4415// time_get
4416
4417static
4418string*
4419init_weeks()
4420{
4421 static string weeks[14];
4422 weeks[0] = "Sunday";
4423 weeks[1] = "Monday";
4424 weeks[2] = "Tuesday";
4425 weeks[3] = "Wednesday";
4426 weeks[4] = "Thursday";
4427 weeks[5] = "Friday";
4428 weeks[6] = "Saturday";
4429 weeks[7] = "Sun";
4430 weeks[8] = "Mon";
4431 weeks[9] = "Tue";
4432 weeks[10] = "Wed";
4433 weeks[11] = "Thu";
4434 weeks[12] = "Fri";
4435 weeks[13] = "Sat";
4436 return weeks;
4437}
4438
4439static
4440wstring*
4441init_wweeks()
4442{
4443 static wstring weeks[14];
4444 weeks[0] = L"Sunday";
4445 weeks[1] = L"Monday";
4446 weeks[2] = L"Tuesday";
4447 weeks[3] = L"Wednesday";
4448 weeks[4] = L"Thursday";
4449 weeks[5] = L"Friday";
4450 weeks[6] = L"Saturday";
4451 weeks[7] = L"Sun";
4452 weeks[8] = L"Mon";
4453 weeks[9] = L"Tue";
4454 weeks[10] = L"Wed";
4455 weeks[11] = L"Thu";
4456 weeks[12] = L"Fri";
4457 weeks[13] = L"Sat";
4458 return weeks;
4459}
4460
4461template <>
4462const string*
4463__time_get_c_storage<char>::__weeks() const
4464{
4465 static const string* weeks = init_weeks();
4466 return weeks;
4467}
4468
4469template <>
4470const wstring*
4471__time_get_c_storage<wchar_t>::__weeks() const
4472{
4473 static const wstring* weeks = init_wweeks();
4474 return weeks;
4475}
4476
4477static
4478string*
4479init_months()
4480{
4481 static string months[24];
4482 months[0] = "January";
4483 months[1] = "February";
4484 months[2] = "March";
4485 months[3] = "April";
4486 months[4] = "May";
4487 months[5] = "June";
4488 months[6] = "July";
4489 months[7] = "August";
4490 months[8] = "September";
4491 months[9] = "October";
4492 months[10] = "November";
4493 months[11] = "December";
4494 months[12] = "Jan";
4495 months[13] = "Feb";
4496 months[14] = "Mar";
4497 months[15] = "Apr";
4498 months[16] = "May";
4499 months[17] = "Jun";
4500 months[18] = "Jul";
4501 months[19] = "Aug";
4502 months[20] = "Sep";
4503 months[21] = "Oct";
4504 months[22] = "Nov";
4505 months[23] = "Dec";
4506 return months;
4507}
4508
4509static
4510wstring*
4511init_wmonths()
4512{
4513 static wstring months[24];
4514 months[0] = L"January";
4515 months[1] = L"February";
4516 months[2] = L"March";
4517 months[3] = L"April";
4518 months[4] = L"May";
4519 months[5] = L"June";
4520 months[6] = L"July";
4521 months[7] = L"August";
4522 months[8] = L"September";
4523 months[9] = L"October";
4524 months[10] = L"November";
4525 months[11] = L"December";
4526 months[12] = L"Jan";
4527 months[13] = L"Feb";
4528 months[14] = L"Mar";
4529 months[15] = L"Apr";
4530 months[16] = L"May";
4531 months[17] = L"Jun";
4532 months[18] = L"Jul";
4533 months[19] = L"Aug";
4534 months[20] = L"Sep";
4535 months[21] = L"Oct";
4536 months[22] = L"Nov";
4537 months[23] = L"Dec";
4538 return months;
4539}
4540
4541template <>
4542const string*
4543__time_get_c_storage<char>::__months() const
4544{
4545 static const string* months = init_months();
4546 return months;
4547}
4548
4549template <>
4550const wstring*
4551__time_get_c_storage<wchar_t>::__months() const
4552{
4553 static const wstring* months = init_wmonths();
4554 return months;
4555}
4556
4557static
4558string*
4559init_am_pm()
4560{
4561 static string am_pm[24];
4562 am_pm[0] = "AM";
4563 am_pm[1] = "PM";
4564 return am_pm;
4565}
4566
4567static
4568wstring*
4569init_wam_pm()
4570{
4571 static wstring am_pm[24];
4572 am_pm[0] = L"AM";
4573 am_pm[1] = L"PM";
4574 return am_pm;
4575}
4576
4577template <>
4578const string*
4579__time_get_c_storage<char>::__am_pm() const
4580{
4581 static const string* am_pm = init_am_pm();
4582 return am_pm;
4583}
4584
4585template <>
4586const wstring*
4587__time_get_c_storage<wchar_t>::__am_pm() const
4588{
4589 static const wstring* am_pm = init_wam_pm();
4590 return am_pm;
4591}
4592
4593template <>
4594const string&
4595__time_get_c_storage<char>::__x() const
4596{
4597 static string s("%m/%d/%y");
4598 return s;
4599}
4600
4601template <>
4602const wstring&
4603__time_get_c_storage<wchar_t>::__x() const
4604{
4605 static wstring s(L"%m/%d/%y");
4606 return s;
4607}
4608
4609template <>
4610const string&
4611__time_get_c_storage<char>::__X() const
4612{
4613 static string s("%H:%M:%S");
4614 return s;
4615}
4616
4617template <>
4618const wstring&
4619__time_get_c_storage<wchar_t>::__X() const
4620{
4621 static wstring s(L"%H:%M:%S");
4622 return s;
4623}
4624
4625template <>
4626const string&
4627__time_get_c_storage<char>::__c() const
4628{
4629 static string s("%a %b %d %H:%M:%S %Y");
4630 return s;
4631}
4632
4633template <>
4634const wstring&
4635__time_get_c_storage<wchar_t>::__c() const
4636{
4637 static wstring s(L"%a %b %d %H:%M:%S %Y");
4638 return s;
4639}
4640
4641template <>
4642const string&
4643__time_get_c_storage<char>::__r() const
4644{
4645 static string s("%I:%M:%S %p");
4646 return s;
4647}
4648
4649template <>
4650const wstring&
4651__time_get_c_storage<wchar_t>::__r() const
4652{
4653 static wstring s(L"%I:%M:%S %p");
4654 return s;
4655}
4656
4657// time_get_byname
4658
4659__time_get::__time_get(const char* nm)
4660 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4661{
Howard Hinnantd4444702010-08-11 17:04:31 +00004662#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004663 if (__loc_ == 0)
4664 throw runtime_error("time_get_byname"
4665 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004666#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004667}
4668
4669__time_get::__time_get(const string& nm)
4670 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4671{
Howard Hinnantd4444702010-08-11 17:04:31 +00004672#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004673 if (__loc_ == 0)
4674 throw runtime_error("time_get_byname"
4675 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004676#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004677}
4678
4679__time_get::~__time_get()
4680{
4681 freelocale(__loc_);
4682}
4683
Howard Hinnant335b1512012-02-20 16:51:43 +00004684#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant21772ec2012-12-28 18:15:01 +00004685#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant335b1512012-02-20 16:51:43 +00004686
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004687template <>
4688string
4689__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4690{
Howard Hinnant3074a052012-02-19 14:55:32 +00004691 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004692 t.tm_sec = 59;
4693 t.tm_min = 55;
4694 t.tm_hour = 23;
4695 t.tm_mday = 31;
4696 t.tm_mon = 11;
4697 t.tm_year = 161;
4698 t.tm_wday = 6;
4699 t.tm_yday = 364;
4700 t.tm_isdst = -1;
4701 char buf[100];
4702 char f[3] = {0};
4703 f[0] = '%';
4704 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004705 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004706 char* bb = buf;
4707 char* be = buf + n;
4708 string result;
4709 while (bb != be)
4710 {
4711 if (ct.is(ctype_base::space, *bb))
4712 {
4713 result.push_back(' ');
4714 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4715 ;
4716 continue;
4717 }
4718 char* w = bb;
4719 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004720 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004721 ct, err, false)
4722 - this->__weeks_;
4723 if (i < 14)
4724 {
4725 result.push_back('%');
4726 if (i < 7)
4727 result.push_back('A');
4728 else
4729 result.push_back('a');
4730 bb = w;
4731 continue;
4732 }
4733 w = bb;
4734 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4735 ct, err, false)
4736 - this->__months_;
4737 if (i < 24)
4738 {
4739 result.push_back('%');
4740 if (i < 12)
4741 result.push_back('B');
4742 else
4743 result.push_back('b');
4744 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4745 result.back() = 'm';
4746 bb = w;
4747 continue;
4748 }
4749 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4750 {
4751 w = bb;
4752 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4753 ct, err, false) - this->__am_pm_;
4754 if (i < 2)
4755 {
4756 result.push_back('%');
4757 result.push_back('p');
4758 bb = w;
4759 continue;
4760 }
4761 }
4762 w = bb;
4763 if (ct.is(ctype_base::digit, *bb))
4764 {
4765 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4766 {
4767 case 6:
4768 result.push_back('%');
4769 result.push_back('w');
4770 break;
4771 case 7:
4772 result.push_back('%');
4773 result.push_back('u');
4774 break;
4775 case 11:
4776 result.push_back('%');
4777 result.push_back('I');
4778 break;
4779 case 12:
4780 result.push_back('%');
4781 result.push_back('m');
4782 break;
4783 case 23:
4784 result.push_back('%');
4785 result.push_back('H');
4786 break;
4787 case 31:
4788 result.push_back('%');
4789 result.push_back('d');
4790 break;
4791 case 55:
4792 result.push_back('%');
4793 result.push_back('M');
4794 break;
4795 case 59:
4796 result.push_back('%');
4797 result.push_back('S');
4798 break;
4799 case 61:
4800 result.push_back('%');
4801 result.push_back('y');
4802 break;
4803 case 364:
4804 result.push_back('%');
4805 result.push_back('j');
4806 break;
4807 case 2061:
4808 result.push_back('%');
4809 result.push_back('Y');
4810 break;
4811 default:
4812 for (; w != bb; ++w)
4813 result.push_back(*w);
4814 break;
4815 }
4816 continue;
4817 }
4818 if (*bb == '%')
4819 {
4820 result.push_back('%');
4821 result.push_back('%');
4822 ++bb;
4823 continue;
4824 }
4825 result.push_back(*bb);
4826 ++bb;
4827 }
4828 return result;
4829}
4830
Howard Hinnantec3773c2011-12-01 20:21:04 +00004831#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004832
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004833template <>
4834wstring
4835__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4836{
Howard Hinnant3074a052012-02-19 14:55:32 +00004837 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004838 t.tm_sec = 59;
4839 t.tm_min = 55;
4840 t.tm_hour = 23;
4841 t.tm_mday = 31;
4842 t.tm_mon = 11;
4843 t.tm_year = 161;
4844 t.tm_wday = 6;
4845 t.tm_yday = 364;
4846 t.tm_isdst = -1;
4847 char buf[100];
4848 char f[3] = {0};
4849 f[0] = '%';
4850 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004851 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004852 wchar_t wbuf[100];
4853 wchar_t* wbb = wbuf;
4854 mbstate_t mb = {0};
4855 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004856#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004857 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004858#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004859 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004860#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004861 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004862 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004863 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004864 wstring result;
4865 while (wbb != wbe)
4866 {
4867 if (ct.is(ctype_base::space, *wbb))
4868 {
4869 result.push_back(L' ');
4870 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4871 ;
4872 continue;
4873 }
4874 wchar_t* w = wbb;
4875 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004876 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004877 ct, err, false)
4878 - this->__weeks_;
4879 if (i < 14)
4880 {
4881 result.push_back(L'%');
4882 if (i < 7)
4883 result.push_back(L'A');
4884 else
4885 result.push_back(L'a');
4886 wbb = w;
4887 continue;
4888 }
4889 w = wbb;
4890 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4891 ct, err, false)
4892 - this->__months_;
4893 if (i < 24)
4894 {
4895 result.push_back(L'%');
4896 if (i < 12)
4897 result.push_back(L'B');
4898 else
4899 result.push_back(L'b');
4900 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4901 result.back() = L'm';
4902 wbb = w;
4903 continue;
4904 }
4905 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4906 {
4907 w = wbb;
4908 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4909 ct, err, false) - this->__am_pm_;
4910 if (i < 2)
4911 {
4912 result.push_back(L'%');
4913 result.push_back(L'p');
4914 wbb = w;
4915 continue;
4916 }
4917 }
4918 w = wbb;
4919 if (ct.is(ctype_base::digit, *wbb))
4920 {
4921 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4922 {
4923 case 6:
4924 result.push_back(L'%');
4925 result.push_back(L'w');
4926 break;
4927 case 7:
4928 result.push_back(L'%');
4929 result.push_back(L'u');
4930 break;
4931 case 11:
4932 result.push_back(L'%');
4933 result.push_back(L'I');
4934 break;
4935 case 12:
4936 result.push_back(L'%');
4937 result.push_back(L'm');
4938 break;
4939 case 23:
4940 result.push_back(L'%');
4941 result.push_back(L'H');
4942 break;
4943 case 31:
4944 result.push_back(L'%');
4945 result.push_back(L'd');
4946 break;
4947 case 55:
4948 result.push_back(L'%');
4949 result.push_back(L'M');
4950 break;
4951 case 59:
4952 result.push_back(L'%');
4953 result.push_back(L'S');
4954 break;
4955 case 61:
4956 result.push_back(L'%');
4957 result.push_back(L'y');
4958 break;
4959 case 364:
4960 result.push_back(L'%');
4961 result.push_back(L'j');
4962 break;
4963 case 2061:
4964 result.push_back(L'%');
4965 result.push_back(L'Y');
4966 break;
4967 default:
4968 for (; w != wbb; ++w)
4969 result.push_back(*w);
4970 break;
4971 }
4972 continue;
4973 }
4974 if (ct.narrow(*wbb, 0) == '%')
4975 {
4976 result.push_back(L'%');
4977 result.push_back(L'%');
4978 ++wbb;
4979 continue;
4980 }
4981 result.push_back(*wbb);
4982 ++wbb;
4983 }
4984 return result;
4985}
4986
4987template <>
4988void
4989__time_get_storage<char>::init(const ctype<char>& ct)
4990{
Howard Hinnantcd992362012-08-02 18:44:17 +00004991 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004992 char buf[100];
4993 // __weeks_
4994 for (int i = 0; i < 7; ++i)
4995 {
4996 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004997 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004998 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004999 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005000 __weeks_[i+7] = buf;
5001 }
5002 // __months_
5003 for (int i = 0; i < 12; ++i)
5004 {
5005 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005006 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005007 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005008 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005009 __months_[i+12] = buf;
5010 }
5011 // __am_pm_
5012 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005013 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005014 __am_pm_[0] = buf;
5015 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005016 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005017 __am_pm_[1] = buf;
5018 __c_ = __analyze('c', ct);
5019 __r_ = __analyze('r', ct);
5020 __x_ = __analyze('x', ct);
5021 __X_ = __analyze('X', ct);
5022}
5023
5024template <>
5025void
5026__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5027{
5028 tm t = {0};
5029 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005030 wchar_t wbuf[100];
5031 wchar_t* wbe;
5032 mbstate_t mb = {0};
5033 // __weeks_
5034 for (int i = 0; i < 7; ++i)
5035 {
5036 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005037 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005038 mb = mbstate_t();
5039 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005040#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005041 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005042#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005043 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005044#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005045 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005046 __throw_runtime_error("locale not supported");
5047 wbe = wbuf + j;
5048 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005049 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005050 mb = mbstate_t();
5051 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005052#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005053 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005054#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005055 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005056#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005057 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005058 __throw_runtime_error("locale not supported");
5059 wbe = wbuf + j;
5060 __weeks_[i+7].assign(wbuf, wbe);
5061 }
5062 // __months_
5063 for (int i = 0; i < 12; ++i)
5064 {
5065 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005066 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005067 mb = mbstate_t();
5068 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005069#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005070 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005071#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005072 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005073#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005074 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005075 __throw_runtime_error("locale not supported");
5076 wbe = wbuf + j;
5077 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005078 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005079 mb = mbstate_t();
5080 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005081#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005082 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005083#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005084 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005085#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005086 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005087 __throw_runtime_error("locale not supported");
5088 wbe = wbuf + j;
5089 __months_[i+12].assign(wbuf, wbe);
5090 }
5091 // __am_pm_
5092 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005093 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005094 mb = mbstate_t();
5095 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005096#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005097 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005098#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005099 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005100#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005101 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005102 __throw_runtime_error("locale not supported");
5103 wbe = wbuf + j;
5104 __am_pm_[0].assign(wbuf, wbe);
5105 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005106 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005107 mb = mbstate_t();
5108 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005109#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005110 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005111#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005114 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005115 __throw_runtime_error("locale not supported");
5116 wbe = wbuf + j;
5117 __am_pm_[1].assign(wbuf, wbe);
5118 __c_ = __analyze('c', ct);
5119 __r_ = __analyze('r', ct);
5120 __x_ = __analyze('x', ct);
5121 __X_ = __analyze('X', ct);
5122}
5123
5124template <class CharT>
5125struct _LIBCPP_HIDDEN __time_get_temp
5126 : public ctype_byname<CharT>
5127{
5128 explicit __time_get_temp(const char* nm)
5129 : ctype_byname<CharT>(nm, 1) {}
5130 explicit __time_get_temp(const string& nm)
5131 : ctype_byname<CharT>(nm, 1) {}
5132};
5133
5134template <>
5135__time_get_storage<char>::__time_get_storage(const char* __nm)
5136 : __time_get(__nm)
5137{
5138 const __time_get_temp<char> ct(__nm);
5139 init(ct);
5140}
5141
5142template <>
5143__time_get_storage<char>::__time_get_storage(const string& __nm)
5144 : __time_get(__nm)
5145{
5146 const __time_get_temp<char> ct(__nm);
5147 init(ct);
5148}
5149
5150template <>
5151__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5152 : __time_get(__nm)
5153{
5154 const __time_get_temp<wchar_t> ct(__nm);
5155 init(ct);
5156}
5157
5158template <>
5159__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5160 : __time_get(__nm)
5161{
5162 const __time_get_temp<wchar_t> ct(__nm);
5163 init(ct);
5164}
5165
5166template <>
5167time_base::dateorder
5168__time_get_storage<char>::__do_date_order() const
5169{
5170 unsigned i;
5171 for (i = 0; i < __x_.size(); ++i)
5172 if (__x_[i] == '%')
5173 break;
5174 ++i;
5175 switch (__x_[i])
5176 {
5177 case 'y':
5178 case 'Y':
5179 for (++i; i < __x_.size(); ++i)
5180 if (__x_[i] == '%')
5181 break;
5182 if (i == __x_.size())
5183 break;
5184 ++i;
5185 switch (__x_[i])
5186 {
5187 case 'm':
5188 for (++i; i < __x_.size(); ++i)
5189 if (__x_[i] == '%')
5190 break;
5191 if (i == __x_.size())
5192 break;
5193 ++i;
5194 if (__x_[i] == 'd')
5195 return time_base::ymd;
5196 break;
5197 case 'd':
5198 for (++i; i < __x_.size(); ++i)
5199 if (__x_[i] == '%')
5200 break;
5201 if (i == __x_.size())
5202 break;
5203 ++i;
5204 if (__x_[i] == 'm')
5205 return time_base::ydm;
5206 break;
5207 }
5208 break;
5209 case 'm':
5210 for (++i; i < __x_.size(); ++i)
5211 if (__x_[i] == '%')
5212 break;
5213 if (i == __x_.size())
5214 break;
5215 ++i;
5216 if (__x_[i] == 'd')
5217 {
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] == 'y' || __x_[i] == 'Y')
5225 return time_base::mdy;
5226 break;
5227 }
5228 break;
5229 case 'd':
5230 for (++i; i < __x_.size(); ++i)
5231 if (__x_[i] == '%')
5232 break;
5233 if (i == __x_.size())
5234 break;
5235 ++i;
5236 if (__x_[i] == 'm')
5237 {
5238 for (++i; i < __x_.size(); ++i)
5239 if (__x_[i] == '%')
5240 break;
5241 if (i == __x_.size())
5242 break;
5243 ++i;
5244 if (__x_[i] == 'y' || __x_[i] == 'Y')
5245 return time_base::dmy;
5246 break;
5247 }
5248 break;
5249 }
5250 return time_base::no_order;
5251}
5252
5253template <>
5254time_base::dateorder
5255__time_get_storage<wchar_t>::__do_date_order() const
5256{
5257 unsigned i;
5258 for (i = 0; i < __x_.size(); ++i)
5259 if (__x_[i] == L'%')
5260 break;
5261 ++i;
5262 switch (__x_[i])
5263 {
5264 case L'y':
5265 case L'Y':
5266 for (++i; i < __x_.size(); ++i)
5267 if (__x_[i] == L'%')
5268 break;
5269 if (i == __x_.size())
5270 break;
5271 ++i;
5272 switch (__x_[i])
5273 {
5274 case L'm':
5275 for (++i; i < __x_.size(); ++i)
5276 if (__x_[i] == L'%')
5277 break;
5278 if (i == __x_.size())
5279 break;
5280 ++i;
5281 if (__x_[i] == L'd')
5282 return time_base::ymd;
5283 break;
5284 case L'd':
5285 for (++i; i < __x_.size(); ++i)
5286 if (__x_[i] == L'%')
5287 break;
5288 if (i == __x_.size())
5289 break;
5290 ++i;
5291 if (__x_[i] == L'm')
5292 return time_base::ydm;
5293 break;
5294 }
5295 break;
5296 case L'm':
5297 for (++i; i < __x_.size(); ++i)
5298 if (__x_[i] == L'%')
5299 break;
5300 if (i == __x_.size())
5301 break;
5302 ++i;
5303 if (__x_[i] == L'd')
5304 {
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'y' || __x_[i] == L'Y')
5312 return time_base::mdy;
5313 break;
5314 }
5315 break;
5316 case L'd':
5317 for (++i; i < __x_.size(); ++i)
5318 if (__x_[i] == L'%')
5319 break;
5320 if (i == __x_.size())
5321 break;
5322 ++i;
5323 if (__x_[i] == L'm')
5324 {
5325 for (++i; i < __x_.size(); ++i)
5326 if (__x_[i] == L'%')
5327 break;
5328 if (i == __x_.size())
5329 break;
5330 ++i;
5331 if (__x_[i] == L'y' || __x_[i] == L'Y')
5332 return time_base::dmy;
5333 break;
5334 }
5335 break;
5336 }
5337 return time_base::no_order;
5338}
5339
5340// time_put
5341
5342__time_put::__time_put(const char* nm)
5343 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5344{
Howard Hinnantd4444702010-08-11 17:04:31 +00005345#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005346 if (__loc_ == 0)
5347 throw runtime_error("time_put_byname"
5348 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005349#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005350}
5351
5352__time_put::__time_put(const string& nm)
5353 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5354{
Howard Hinnantd4444702010-08-11 17:04:31 +00005355#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005356 if (__loc_ == 0)
5357 throw runtime_error("time_put_byname"
5358 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005359#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005360}
5361
5362__time_put::~__time_put()
5363{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005364 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005365 freelocale(__loc_);
5366}
5367
5368void
5369__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5370 char __fmt, char __mod) const
5371{
5372 char fmt[] = {'%', __fmt, __mod, 0};
5373 if (__mod != 0)
5374 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005375 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005376 __ne = __nb + n;
5377}
5378
5379void
5380__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5381 char __fmt, char __mod) const
5382{
5383 char __nar[100];
5384 char* __ne = __nar + 100;
5385 __do_put(__nar, __ne, __tm, __fmt, __mod);
5386 mbstate_t mb = {0};
5387 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005388#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005389 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005390#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005391 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005392#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005393 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005394 __throw_runtime_error("locale not supported");
5395 __we = __wb + j;
5396}
5397
5398// moneypunct_byname
5399
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005400template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005401static
5402void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005403__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5404 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5405 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005406{
5407 const char sign = static_cast<char>(money_base::sign);
5408 const char space = static_cast<char>(money_base::space);
5409 const char none = static_cast<char>(money_base::none);
5410 const char symbol = static_cast<char>(money_base::symbol);
5411 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005412 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5413
5414 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5415 // function'. "Space between sign and symbol or value" means that
5416 // if the sign is adjacent to the symbol, there's a space between
5417 // them, and otherwise there's a space between the sign and value.
5418 //
5419 // C11's localeconv specifies that the fourth character of an
5420 // international curr_symbol is used to separate the sign and
5421 // value when sep_by_space says to do so. C++ can't represent
5422 // that, so we just use a space. When sep_by_space says to
5423 // separate the symbol and value-or-sign with a space, we rearrange the
5424 // curr_symbol to put its spacing character on the correct side of
5425 // the symbol.
5426 //
5427 // We also need to avoid adding an extra space between the sign
5428 // and value when the currency symbol is suppressed (by not
5429 // setting showbase). We match glibc's strfmon by interpreting
5430 // sep_by_space==1 as "omit the space when the currency symbol is
5431 // absent".
5432 //
5433 // Users who want to get this right should use ICU instead.
5434
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005435 switch (cs_precedes)
5436 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005437 case 0: // value before curr_symbol
5438 if (symbol_contains_sep) {
5439 // Move the separator to before the symbol, to place it
5440 // between the value and symbol.
5441 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5442 __curr_symbol_.end());
5443 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005444 switch (sign_posn)
5445 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005446 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005447 pat.field[0] = sign;
5448 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005449 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005450 pat.field[3] = symbol;
5451 switch (sep_by_space)
5452 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005453 case 0: // No space separates the currency symbol and value.
5454 // This case may have changed between C99 and C11;
5455 // assume the currency symbol matches the intention.
5456 case 2: // Space between sign and currency or value.
5457 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005458 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005459 case 1: // Space between currency-and-sign or currency and value.
5460 if (!symbol_contains_sep) {
5461 // We insert the space into the symbol instead of
5462 // setting pat.field[2]=space so that when
5463 // showbase is not set, the space goes away too.
5464 __curr_symbol_.insert(0, 1, space_char);
5465 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005466 return;
5467 default:
5468 break;
5469 }
5470 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005471 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005472 pat.field[0] = sign;
5473 pat.field[3] = symbol;
5474 switch (sep_by_space)
5475 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005476 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005477 pat.field[1] = value;
5478 pat.field[2] = none;
5479 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005480 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005481 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005482 pat.field[2] = none;
5483 if (!symbol_contains_sep) {
5484 // We insert the space into the symbol instead of
5485 // setting pat.field[2]=space so that when
5486 // showbase is not set, the space goes away too.
5487 __curr_symbol_.insert(0, 1, space_char);
5488 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005489 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005490 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005491 pat.field[1] = space;
5492 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005493 if (symbol_contains_sep) {
5494 // Remove the separator from the symbol, since it
5495 // has already appeared after the sign.
5496 __curr_symbol_.erase(__curr_symbol_.begin());
5497 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005498 return;
5499 default:
5500 break;
5501 }
5502 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005503 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005504 pat.field[0] = value;
5505 pat.field[3] = sign;
5506 switch (sep_by_space)
5507 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005508 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005509 pat.field[1] = none;
5510 pat.field[2] = symbol;
5511 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005512 case 1: // Space between currency-and-sign or currency and value.
5513 if (!symbol_contains_sep) {
5514 // We insert the space into the symbol instead of
5515 // setting pat.field[1]=space so that when
5516 // showbase is not set, the space goes away too.
5517 __curr_symbol_.insert(0, 1, space_char);
5518 }
5519 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005520 pat.field[2] = symbol;
5521 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005522 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005523 pat.field[1] = symbol;
5524 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005525 if (symbol_contains_sep) {
5526 // Remove the separator from the symbol, since it
5527 // should not be removed if showbase is absent.
5528 __curr_symbol_.erase(__curr_symbol_.begin());
5529 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005530 return;
5531 default:
5532 break;
5533 }
5534 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005535 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005536 pat.field[0] = value;
5537 pat.field[3] = symbol;
5538 switch (sep_by_space)
5539 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005540 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005541 pat.field[1] = none;
5542 pat.field[2] = sign;
5543 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005544 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005545 pat.field[1] = space;
5546 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005547 if (symbol_contains_sep) {
5548 // Remove the separator from the symbol, since it
5549 // has already appeared before the sign.
5550 __curr_symbol_.erase(__curr_symbol_.begin());
5551 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005552 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005553 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005554 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005555 pat.field[2] = none;
5556 if (!symbol_contains_sep) {
5557 // We insert the space into the symbol instead of
5558 // setting pat.field[2]=space so that when
5559 // showbase is not set, the space goes away too.
5560 __curr_symbol_.insert(0, 1, space_char);
5561 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005562 return;
5563 default:
5564 break;
5565 }
5566 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005567 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005568 pat.field[0] = value;
5569 pat.field[3] = sign;
5570 switch (sep_by_space)
5571 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005572 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005573 pat.field[1] = none;
5574 pat.field[2] = symbol;
5575 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005576 case 1: // Space between currency-and-sign or currency and value.
5577 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005578 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005579 if (!symbol_contains_sep) {
5580 // We insert the space into the symbol instead of
5581 // setting pat.field[1]=space so that when
5582 // showbase is not set, the space goes away too.
5583 __curr_symbol_.insert(0, 1, space_char);
5584 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005585 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005586 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005587 pat.field[1] = symbol;
5588 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005589 if (symbol_contains_sep) {
5590 // Remove the separator from the symbol, since it
5591 // should not disappear when showbase is absent.
5592 __curr_symbol_.erase(__curr_symbol_.begin());
5593 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005594 return;
5595 default:
5596 break;
5597 }
5598 break;
5599 default:
5600 break;
5601 }
5602 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005603 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005604 switch (sign_posn)
5605 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005606 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005607 pat.field[0] = sign;
5608 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005609 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005610 pat.field[3] = value;
5611 switch (sep_by_space)
5612 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005613 case 0: // No space separates the currency symbol and value.
5614 // This case may have changed between C99 and C11;
5615 // assume the currency symbol matches the intention.
5616 case 2: // Space between sign and currency or value.
5617 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005618 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005619 case 1: // Space between currency-and-sign or currency and value.
5620 if (!symbol_contains_sep) {
5621 // We insert the space into the symbol instead of
5622 // setting pat.field[2]=space so that when
5623 // showbase is not set, the space goes away too.
5624 __curr_symbol_.insert(0, 1, space_char);
5625 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005626 return;
5627 default:
5628 break;
5629 }
5630 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005631 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005632 pat.field[0] = sign;
5633 pat.field[3] = value;
5634 switch (sep_by_space)
5635 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005636 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005637 pat.field[1] = symbol;
5638 pat.field[2] = none;
5639 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005640 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005641 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005642 pat.field[2] = none;
5643 if (!symbol_contains_sep) {
5644 // We insert the space into the symbol instead of
5645 // setting pat.field[2]=space so that when
5646 // showbase is not set, the space goes away too.
5647 __curr_symbol_.push_back(space_char);
5648 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005649 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005650 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005651 pat.field[1] = space;
5652 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005653 if (symbol_contains_sep) {
5654 // Remove the separator from the symbol, since it
5655 // has already appeared after the sign.
5656 __curr_symbol_.pop_back();
5657 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005658 return;
5659 default:
5660 break;
5661 }
5662 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005663 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005664 pat.field[0] = symbol;
5665 pat.field[3] = sign;
5666 switch (sep_by_space)
5667 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005668 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005669 pat.field[1] = none;
5670 pat.field[2] = value;
5671 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005672 case 1: // Space between currency-and-sign or currency and value.
5673 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005674 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005675 if (!symbol_contains_sep) {
5676 // We insert the space into the symbol instead of
5677 // setting pat.field[1]=space so that when
5678 // showbase is not set, the space goes away too.
5679 __curr_symbol_.push_back(space_char);
5680 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005681 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005682 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005683 pat.field[1] = value;
5684 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005685 if (symbol_contains_sep) {
5686 // Remove the separator from the symbol, since it
5687 // will appear before the sign.
5688 __curr_symbol_.pop_back();
5689 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005690 return;
5691 default:
5692 break;
5693 }
5694 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005695 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005696 pat.field[0] = sign;
5697 pat.field[3] = value;
5698 switch (sep_by_space)
5699 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005700 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005701 pat.field[1] = symbol;
5702 pat.field[2] = none;
5703 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005704 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005705 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005706 pat.field[2] = none;
5707 if (!symbol_contains_sep) {
5708 // We insert the space into the symbol instead of
5709 // setting pat.field[2]=space so that when
5710 // showbase is not set, the space goes away too.
5711 __curr_symbol_.push_back(space_char);
5712 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005713 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005714 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005715 pat.field[1] = space;
5716 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005717 if (symbol_contains_sep) {
5718 // Remove the separator from the symbol, since it
5719 // has already appeared after the sign.
5720 __curr_symbol_.pop_back();
5721 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005722 return;
5723 default:
5724 break;
5725 }
5726 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005727 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005728 pat.field[0] = symbol;
5729 pat.field[3] = value;
5730 switch (sep_by_space)
5731 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005732 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005733 pat.field[1] = sign;
5734 pat.field[2] = none;
5735 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005736 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005737 pat.field[1] = sign;
5738 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005739 if (symbol_contains_sep) {
5740 // Remove the separator from the symbol, since it
5741 // should not disappear when showbase is absent.
5742 __curr_symbol_.pop_back();
5743 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005744 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005745 case 2: // Space between sign and currency or value.
5746 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005747 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005748 if (!symbol_contains_sep) {
5749 // We insert the space into the symbol instead of
5750 // setting pat.field[1]=space so that when
5751 // showbase is not set, the space goes away too.
5752 __curr_symbol_.push_back(space_char);
5753 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005754 return;
5755 default:
5756 break;
5757 }
5758 break;
5759 default:
5760 break;
5761 }
5762 break;
5763 default:
5764 break;
5765 }
5766 pat.field[0] = symbol;
5767 pat.field[1] = sign;
5768 pat.field[2] = none;
5769 pat.field[3] = value;
5770}
5771
5772template<>
5773void
5774moneypunct_byname<char, false>::init(const char* nm)
5775{
5776 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005777 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005778#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005779 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005780 throw runtime_error("moneypunct_byname"
5781 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005782#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005783#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005784 lconv* lc = localeconv_l(loc.get());
5785#else
5786 lconv* lc = __localeconv_l(loc.get());
5787#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005788 if (*lc->mon_decimal_point)
5789 __decimal_point_ = *lc->mon_decimal_point;
5790 else
5791 __decimal_point_ = base::do_decimal_point();
5792 if (*lc->mon_thousands_sep)
5793 __thousands_sep_ = *lc->mon_thousands_sep;
5794 else
5795 __thousands_sep_ = base::do_thousands_sep();
5796 __grouping_ = lc->mon_grouping;
5797 __curr_symbol_ = lc->currency_symbol;
5798 if (lc->frac_digits != CHAR_MAX)
5799 __frac_digits_ = lc->frac_digits;
5800 else
5801 __frac_digits_ = base::do_frac_digits();
5802 if (lc->p_sign_posn == 0)
5803 __positive_sign_ = "()";
5804 else
5805 __positive_sign_ = lc->positive_sign;
5806 if (lc->n_sign_posn == 0)
5807 __negative_sign_ = "()";
5808 else
5809 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005810 // Assume the positive and negative formats will want spaces in
5811 // the same places in curr_symbol since there's no way to
5812 // represent anything else.
5813 string_type __dummy_curr_symbol = __curr_symbol_;
5814 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5815 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5816 __init_pat(__neg_format_, __curr_symbol_, false,
5817 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005818}
5819
5820template<>
5821void
5822moneypunct_byname<char, true>::init(const char* nm)
5823{
5824 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005825 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005826#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005827 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005828 throw runtime_error("moneypunct_byname"
5829 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005830#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005831#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005832 lconv* lc = localeconv_l(loc.get());
5833#else
5834 lconv* lc = __localeconv_l(loc.get());
5835#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005836 if (*lc->mon_decimal_point)
5837 __decimal_point_ = *lc->mon_decimal_point;
5838 else
5839 __decimal_point_ = base::do_decimal_point();
5840 if (*lc->mon_thousands_sep)
5841 __thousands_sep_ = *lc->mon_thousands_sep;
5842 else
5843 __thousands_sep_ = base::do_thousands_sep();
5844 __grouping_ = lc->mon_grouping;
5845 __curr_symbol_ = lc->int_curr_symbol;
5846 if (lc->int_frac_digits != CHAR_MAX)
5847 __frac_digits_ = lc->int_frac_digits;
5848 else
5849 __frac_digits_ = base::do_frac_digits();
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005850#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005851 if (lc->p_sign_posn == 0)
5852#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005853 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005854#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005855 __positive_sign_ = "()";
5856 else
5857 __positive_sign_ = lc->positive_sign;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005858#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005859 if(lc->n_sign_posn == 0)
5860#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005861 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005862#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005863 __negative_sign_ = "()";
5864 else
5865 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005866 // Assume the positive and negative formats will want spaces in
5867 // the same places in curr_symbol since there's no way to
5868 // represent anything else.
5869 string_type __dummy_curr_symbol = __curr_symbol_;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005870#ifdef _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005871 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5872 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5873 __init_pat(__neg_format_, __curr_symbol_, true,
5874 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005875#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005876 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5877 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5878 lc->int_p_sign_posn, ' ');
5879 __init_pat(__neg_format_, __curr_symbol_, true,
5880 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5881 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005882#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005883}
5884
5885template<>
5886void
5887moneypunct_byname<wchar_t, false>::init(const char* nm)
5888{
5889 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005890 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005891#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005892 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005893 throw runtime_error("moneypunct_byname"
5894 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005895#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005896#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005897 lconv* lc = localeconv_l(loc.get());
5898#else
5899 lconv* lc = __localeconv_l(loc.get());
5900#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005901 if (*lc->mon_decimal_point)
5902 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5903 else
5904 __decimal_point_ = base::do_decimal_point();
5905 if (*lc->mon_thousands_sep)
5906 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5907 else
5908 __thousands_sep_ = base::do_thousands_sep();
5909 __grouping_ = lc->mon_grouping;
5910 wchar_t wbuf[100];
5911 mbstate_t mb = {0};
5912 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005913#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005914 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005915#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005916 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005917#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005918 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005919 __throw_runtime_error("locale not supported");
5920 wchar_t* wbe = wbuf + j;
5921 __curr_symbol_.assign(wbuf, wbe);
5922 if (lc->frac_digits != CHAR_MAX)
5923 __frac_digits_ = lc->frac_digits;
5924 else
5925 __frac_digits_ = base::do_frac_digits();
5926 if (lc->p_sign_posn == 0)
5927 __positive_sign_ = L"()";
5928 else
5929 {
5930 mb = mbstate_t();
5931 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005932#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005933 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005934#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005935 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005936#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005937 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005938 __throw_runtime_error("locale not supported");
5939 wbe = wbuf + j;
5940 __positive_sign_.assign(wbuf, wbe);
5941 }
5942 if (lc->n_sign_posn == 0)
5943 __negative_sign_ = L"()";
5944 else
5945 {
5946 mb = mbstate_t();
5947 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005948#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005949 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005950#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005951 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005952#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005953 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005954 __throw_runtime_error("locale not supported");
5955 wbe = wbuf + j;
5956 __negative_sign_.assign(wbuf, wbe);
5957 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005958 // Assume the positive and negative formats will want spaces in
5959 // the same places in curr_symbol since there's no way to
5960 // represent anything else.
5961 string_type __dummy_curr_symbol = __curr_symbol_;
5962 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5963 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5964 __init_pat(__neg_format_, __curr_symbol_, false,
5965 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005966}
5967
5968template<>
5969void
5970moneypunct_byname<wchar_t, true>::init(const char* nm)
5971{
5972 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005973 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005974#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005975 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005976 throw runtime_error("moneypunct_byname"
5977 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005978#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005979#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005980 lconv* lc = localeconv_l(loc.get());
5981#else
5982 lconv* lc = __localeconv_l(loc.get());
5983#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005984 if (*lc->mon_decimal_point)
5985 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5986 else
5987 __decimal_point_ = base::do_decimal_point();
5988 if (*lc->mon_thousands_sep)
5989 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5990 else
5991 __thousands_sep_ = base::do_thousands_sep();
5992 __grouping_ = lc->mon_grouping;
5993 wchar_t wbuf[100];
5994 mbstate_t mb = {0};
5995 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005996#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005997 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005998#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005999 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006000#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006001 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006002 __throw_runtime_error("locale not supported");
6003 wchar_t* wbe = wbuf + j;
6004 __curr_symbol_.assign(wbuf, wbe);
6005 if (lc->int_frac_digits != CHAR_MAX)
6006 __frac_digits_ = lc->int_frac_digits;
6007 else
6008 __frac_digits_ = base::do_frac_digits();
Marshall Clowa22d2ad2013-03-18 17:04:29 +00006009#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006010 if (lc->p_sign_posn == 0)
6011#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006012 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006013#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006014 __positive_sign_ = L"()";
6015 else
6016 {
6017 mb = mbstate_t();
6018 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006019#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006020 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006021#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006022 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006023#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006024 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006025 __throw_runtime_error("locale not supported");
6026 wbe = wbuf + j;
6027 __positive_sign_.assign(wbuf, wbe);
6028 }
Marshall Clowa22d2ad2013-03-18 17:04:29 +00006029#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006030 if (lc->n_sign_posn == 0)
6031#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006032 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006033#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006034 __negative_sign_ = L"()";
6035 else
6036 {
6037 mb = mbstate_t();
6038 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006039#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006040 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006041#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006042 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006043#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006044 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006045 __throw_runtime_error("locale not supported");
6046 wbe = wbuf + j;
6047 __negative_sign_.assign(wbuf, wbe);
6048 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006049 // Assume the positive and negative formats will want spaces in
6050 // the same places in curr_symbol since there's no way to
6051 // represent anything else.
6052 string_type __dummy_curr_symbol = __curr_symbol_;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00006053#ifdef _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006054 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6055 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6056 __init_pat(__neg_format_, __curr_symbol_, true,
6057 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006058#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006059 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6060 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6061 lc->int_p_sign_posn, L' ');
6062 __init_pat(__neg_format_, __curr_symbol_, true,
6063 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6064 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006065#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006066}
6067
6068void __do_nothing(void*) {}
6069
6070void __throw_runtime_error(const char* msg)
6071{
Howard Hinnantd4444702010-08-11 17:04:31 +00006072#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006073 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006074#else
6075 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006076#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006077}
6078
6079template class collate<char>;
6080template class collate<wchar_t>;
6081
6082template class num_get<char>;
6083template class num_get<wchar_t>;
6084
Howard Hinnantec3773c2011-12-01 20:21:04 +00006085template struct __num_get<char>;
6086template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006087
6088template class num_put<char>;
6089template class num_put<wchar_t>;
6090
Howard Hinnantec3773c2011-12-01 20:21:04 +00006091template struct __num_put<char>;
6092template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006093
6094template class time_get<char>;
6095template class time_get<wchar_t>;
6096
6097template class time_get_byname<char>;
6098template class time_get_byname<wchar_t>;
6099
6100template class time_put<char>;
6101template class time_put<wchar_t>;
6102
6103template class time_put_byname<char>;
6104template class time_put_byname<wchar_t>;
6105
6106template class moneypunct<char, false>;
6107template class moneypunct<char, true>;
6108template class moneypunct<wchar_t, false>;
6109template class moneypunct<wchar_t, true>;
6110
6111template class moneypunct_byname<char, false>;
6112template class moneypunct_byname<char, true>;
6113template class moneypunct_byname<wchar_t, false>;
6114template class moneypunct_byname<wchar_t, true>;
6115
6116template class money_get<char>;
6117template class money_get<wchar_t>;
6118
6119template class __money_get<char>;
6120template class __money_get<wchar_t>;
6121
6122template class money_put<char>;
6123template class money_put<wchar_t>;
6124
6125template class __money_put<char>;
6126template class __money_put<wchar_t>;
6127
6128template class messages<char>;
6129template class messages<wchar_t>;
6130
6131template class messages_byname<char>;
6132template class messages_byname<wchar_t>;
6133
6134template class codecvt_byname<char, char, mbstate_t>;
6135template class codecvt_byname<wchar_t, char, mbstate_t>;
6136template class codecvt_byname<char16_t, char, mbstate_t>;
6137template class codecvt_byname<char32_t, char, mbstate_t>;
6138
6139template class __vector_base_common<true>;
6140
6141_LIBCPP_END_NAMESPACE_STD