blob: 47c406123f091bf8e2f0ab63d1f480350538e2f1 [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>
34
Marshall Clow9ae96d02013-02-07 17:20:56 +000035// On Linux, wint_t and wchar_t have different signed-ness, and this causes
36// lots of noise in the build log, but no bugs that I know of.
37#pragma clang diagnostic ignored "-Wsign-conversion"
38
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000039_LIBCPP_BEGIN_NAMESPACE_STD
40
Howard Hinnant866569b2011-09-28 23:39:33 +000041#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000042locale_t __cloc() {
43 // In theory this could create a race condition. In practice
44 // the race condition is non-fatal since it will just create
45 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000046 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
47 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000048}
Howard Hinnant866569b2011-09-28 23:39:33 +000049#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000050
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051namespace {
52
53struct release
54{
55 void operator()(locale::facet* p) {p->__release_shared();}
56};
57
58template <class T, class A0>
59inline
60T&
61make(A0 a0)
62{
63 static typename aligned_storage<sizeof(T)>::type buf;
64 ::new (&buf) T(a0);
65 return *(T*)&buf;
66}
67
68template <class T, class A0, class A1>
69inline
70T&
71make(A0 a0, A1 a1)
72{
73 static typename aligned_storage<sizeof(T)>::type buf;
74 ::new (&buf) T(a0, a1);
75 return *(T*)&buf;
76}
77
78template <class T, class A0, class A1, class A2>
79inline
80T&
81make(A0 a0, A1 a1, A2 a2)
82{
83 static typename aligned_storage<sizeof(T)>::type buf;
84 ::new (&buf) T(a0, a1, a2);
85 return *(T*)&buf;
86}
87
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000088template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000089inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000090_LIBCPP_CONSTEXPR
91size_t
92countof(const T (&)[N])
93{
94 return N;
95}
96
97template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +000098inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000099_LIBCPP_CONSTEXPR
100size_t
101countof(const T * const begin, const T * const end)
102{
103 return static_cast<size_t>(end - begin);
104}
105
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000106}
107
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000108const locale::category locale::none;
109const locale::category locale::collate;
110const locale::category locale::ctype;
111const locale::category locale::monetary;
112const locale::category locale::numeric;
113const locale::category locale::time;
114const locale::category locale::messages;
115const locale::category locale::all;
116
Howard Hinnantec3773c2011-12-01 20:21:04 +0000117#pragma clang diagnostic push
118#pragma clang diagnostic ignored "-Wpadded"
119
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120class _LIBCPP_HIDDEN locale::__imp
121 : public facet
122{
123 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000124 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000125 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000126public:
127 explicit __imp(size_t refs = 0);
128 explicit __imp(const string& name, size_t refs = 0);
129 __imp(const __imp&);
130 __imp(const __imp&, const string&, locale::category c);
131 __imp(const __imp& other, const __imp& one, locale::category c);
132 __imp(const __imp&, facet* f, long id);
133 ~__imp();
134
135 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000136 bool has_facet(long id) const
137 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000138 const locale::facet* use_facet(long id) const;
139
140 static const locale& make_classic();
141 static locale& make_global();
142private:
143 void install(facet* f, long id);
144 template <class F> void install(F* f) {install(f, f->id.__get());}
145 template <class F> void install_from(const __imp& other);
146};
147
Howard Hinnantec3773c2011-12-01 20:21:04 +0000148#pragma clang diagnostic pop
149
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000150locale::__imp::__imp(size_t refs)
151 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000152 facets_(N),
153 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000154{
155 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000156 install(&make<_VSTD::collate<char> >(1u));
157 install(&make<_VSTD::collate<wchar_t> >(1u));
158 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
159 install(&make<_VSTD::ctype<wchar_t> >(1u));
160 install(&make<codecvt<char, char, mbstate_t> >(1u));
161 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
162 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
163 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
164 install(&make<numpunct<char> >(1u));
165 install(&make<numpunct<wchar_t> >(1u));
166 install(&make<num_get<char> >(1u));
167 install(&make<num_get<wchar_t> >(1u));
168 install(&make<num_put<char> >(1u));
169 install(&make<num_put<wchar_t> >(1u));
170 install(&make<moneypunct<char, false> >(1u));
171 install(&make<moneypunct<char, true> >(1u));
172 install(&make<moneypunct<wchar_t, false> >(1u));
173 install(&make<moneypunct<wchar_t, true> >(1u));
174 install(&make<money_get<char> >(1u));
175 install(&make<money_get<wchar_t> >(1u));
176 install(&make<money_put<char> >(1u));
177 install(&make<money_put<wchar_t> >(1u));
178 install(&make<time_get<char> >(1u));
179 install(&make<time_get<wchar_t> >(1u));
180 install(&make<time_put<char> >(1u));
181 install(&make<time_put<wchar_t> >(1u));
182 install(&make<_VSTD::messages<char> >(1u));
183 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000184}
185
186locale::__imp::__imp(const string& name, size_t refs)
187 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000188 facets_(N),
189 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000190{
Howard Hinnantd4444702010-08-11 17:04:31 +0000191#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192 try
193 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000194#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000195 facets_ = locale::classic().__locale_->facets_;
196 for (unsigned i = 0; i < facets_.size(); ++i)
197 if (facets_[i])
198 facets_[i]->__add_shared();
199 install(new collate_byname<char>(name_));
200 install(new collate_byname<wchar_t>(name_));
201 install(new ctype_byname<char>(name_));
202 install(new ctype_byname<wchar_t>(name_));
203 install(new codecvt_byname<char, char, mbstate_t>(name_));
204 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
205 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
206 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
207 install(new numpunct_byname<char>(name_));
208 install(new numpunct_byname<wchar_t>(name_));
209 install(new moneypunct_byname<char, false>(name_));
210 install(new moneypunct_byname<char, true>(name_));
211 install(new moneypunct_byname<wchar_t, false>(name_));
212 install(new moneypunct_byname<wchar_t, true>(name_));
213 install(new time_get_byname<char>(name_));
214 install(new time_get_byname<wchar_t>(name_));
215 install(new time_put_byname<char>(name_));
216 install(new time_put_byname<wchar_t>(name_));
217 install(new messages_byname<char>(name_));
218 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000219#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000220 }
221 catch (...)
222 {
223 for (unsigned i = 0; i < facets_.size(); ++i)
224 if (facets_[i])
225 facets_[i]->__release_shared();
226 throw;
227 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000228#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000229}
230
Howard Hinnant21772ec2012-12-28 18:15:01 +0000231// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000232// copy constructor` warning emitted by GCC
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000233#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000234#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000235#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000236#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000237
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000238locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000239 : facets_(max<size_t>(N, other.facets_.size())),
240 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000241{
242 facets_ = other.facets_;
243 for (unsigned i = 0; i < facets_.size(); ++i)
244 if (facets_[i])
245 facets_[i]->__add_shared();
246}
247
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000248#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000249#pragma GCC diagnostic pop
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000250#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000251
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000252locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000253 : facets_(N),
254 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000255{
256 facets_ = other.facets_;
257 for (unsigned i = 0; i < facets_.size(); ++i)
258 if (facets_[i])
259 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000260#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000261 try
262 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000263#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000264 if (c & locale::collate)
265 {
266 install(new collate_byname<char>(name));
267 install(new collate_byname<wchar_t>(name));
268 }
269 if (c & locale::ctype)
270 {
271 install(new ctype_byname<char>(name));
272 install(new ctype_byname<wchar_t>(name));
273 install(new codecvt_byname<char, char, mbstate_t>(name));
274 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
275 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
276 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
277 }
278 if (c & locale::monetary)
279 {
280 install(new moneypunct_byname<char, false>(name));
281 install(new moneypunct_byname<char, true>(name));
282 install(new moneypunct_byname<wchar_t, false>(name));
283 install(new moneypunct_byname<wchar_t, true>(name));
284 }
285 if (c & locale::numeric)
286 {
287 install(new numpunct_byname<char>(name));
288 install(new numpunct_byname<wchar_t>(name));
289 }
290 if (c & locale::time)
291 {
292 install(new time_get_byname<char>(name));
293 install(new time_get_byname<wchar_t>(name));
294 install(new time_put_byname<char>(name));
295 install(new time_put_byname<wchar_t>(name));
296 }
297 if (c & locale::messages)
298 {
299 install(new messages_byname<char>(name));
300 install(new messages_byname<wchar_t>(name));
301 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000302#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000303 }
304 catch (...)
305 {
306 for (unsigned i = 0; i < facets_.size(); ++i)
307 if (facets_[i])
308 facets_[i]->__release_shared();
309 throw;
310 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000311#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000312}
313
314template<class F>
315inline
316void
317locale::__imp::install_from(const locale::__imp& one)
318{
319 long id = F::id.__get();
320 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
321}
322
323locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000324 : facets_(N),
325 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000326{
327 facets_ = other.facets_;
328 for (unsigned i = 0; i < facets_.size(); ++i)
329 if (facets_[i])
330 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000331#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000332 try
333 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000334#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000335 if (c & locale::collate)
336 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000337 install_from<_VSTD::collate<char> >(one);
338 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000339 }
340 if (c & locale::ctype)
341 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000342 install_from<_VSTD::ctype<char> >(one);
343 install_from<_VSTD::ctype<wchar_t> >(one);
344 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
345 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
346 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
347 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000348 }
349 if (c & locale::monetary)
350 {
351 install_from<moneypunct<char, false> >(one);
352 install_from<moneypunct<char, true> >(one);
353 install_from<moneypunct<wchar_t, false> >(one);
354 install_from<moneypunct<wchar_t, true> >(one);
355 install_from<money_get<char> >(one);
356 install_from<money_get<wchar_t> >(one);
357 install_from<money_put<char> >(one);
358 install_from<money_put<wchar_t> >(one);
359 }
360 if (c & locale::numeric)
361 {
362 install_from<numpunct<char> >(one);
363 install_from<numpunct<wchar_t> >(one);
364 install_from<num_get<char> >(one);
365 install_from<num_get<wchar_t> >(one);
366 install_from<num_put<char> >(one);
367 install_from<num_put<wchar_t> >(one);
368 }
369 if (c & locale::time)
370 {
371 install_from<time_get<char> >(one);
372 install_from<time_get<wchar_t> >(one);
373 install_from<time_put<char> >(one);
374 install_from<time_put<wchar_t> >(one);
375 }
376 if (c & locale::messages)
377 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000378 install_from<_VSTD::messages<char> >(one);
379 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000380 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000381#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000382 }
383 catch (...)
384 {
385 for (unsigned i = 0; i < facets_.size(); ++i)
386 if (facets_[i])
387 facets_[i]->__release_shared();
388 throw;
389 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000390#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000391}
392
393locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000394 : facets_(max<size_t>(N, other.facets_.size()+1)),
395 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000396{
397 f->__add_shared();
398 unique_ptr<facet, release> hold(f);
399 facets_ = other.facets_;
400 for (unsigned i = 0; i < other.facets_.size(); ++i)
401 if (facets_[i])
402 facets_[i]->__add_shared();
403 install(hold.get(), id);
404}
405
406locale::__imp::~__imp()
407{
408 for (unsigned i = 0; i < facets_.size(); ++i)
409 if (facets_[i])
410 facets_[i]->__release_shared();
411}
412
413void
414locale::__imp::install(facet* f, long id)
415{
416 f->__add_shared();
417 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000418 if (static_cast<size_t>(id) >= facets_.size())
419 facets_.resize(static_cast<size_t>(id+1));
420 if (facets_[static_cast<size_t>(id)])
421 facets_[static_cast<size_t>(id)]->__release_shared();
422 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000423}
424
425const locale::facet*
426locale::__imp::use_facet(long id) const
427{
Howard Hinnantd4444702010-08-11 17:04:31 +0000428#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000429 if (!has_facet(id))
430 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000431#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000432 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000433}
434
435// locale
436
437const locale&
438locale::__imp::make_classic()
439{
440 // only one thread can get in here and it only gets in once
441 static aligned_storage<sizeof(locale)>::type buf;
442 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000443 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000444 return *c;
445}
446
447const locale&
448locale::classic()
449{
450 static const locale& c = __imp::make_classic();
451 return c;
452}
453
454locale&
455locale::__imp::make_global()
456{
457 // only one thread can get in here and it only gets in once
458 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000459 ::new (&buf) locale(locale::classic());
460 return *(locale*)&buf;
461}
462
463locale&
464locale::__global()
465{
466 static locale& g = __imp::make_global();
467 return g;
468}
469
Howard Hinnantc9834542011-05-31 15:34:58 +0000470locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000471 : __locale_(__global().__locale_)
472{
473 __locale_->__add_shared();
474}
475
Howard Hinnantc9834542011-05-31 15:34:58 +0000476locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000477 : __locale_(l.__locale_)
478{
479 __locale_->__add_shared();
480}
481
Howard Hinnantc9834542011-05-31 15:34:58 +0000482locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000483{
484 __locale_->__release_shared();
485}
486
487const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000488locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000489{
490 other.__locale_->__add_shared();
491 __locale_->__release_shared();
492 __locale_ = other.__locale_;
493 return *this;
494}
495
496locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000497#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000498 : __locale_(name ? new __imp(name)
499 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000500#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000501 : __locale_(new __imp(name))
502#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000503{
504 __locale_->__add_shared();
505}
506
507locale::locale(const string& name)
508 : __locale_(new __imp(name))
509{
510 __locale_->__add_shared();
511}
512
513locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000514#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000515 : __locale_(name ? new __imp(*other.__locale_, name, c)
516 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000517#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000518 : __locale_(new __imp(*other.__locale_, name, c))
519#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000520{
521 __locale_->__add_shared();
522}
523
524locale::locale(const locale& other, const string& name, category c)
525 : __locale_(new __imp(*other.__locale_, name, c))
526{
527 __locale_->__add_shared();
528}
529
530locale::locale(const locale& other, const locale& one, category c)
531 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
532{
533 __locale_->__add_shared();
534}
535
536string
537locale::name() const
538{
539 return __locale_->name();
540}
541
542void
543locale::__install_ctor(const locale& other, facet* f, long id)
544{
545 if (f)
546 __locale_ = new __imp(*other.__locale_, f, id);
547 else
548 __locale_ = other.__locale_;
549 __locale_->__add_shared();
550}
551
552locale
553locale::global(const locale& loc)
554{
555 locale& g = __global();
556 locale r = g;
557 g = loc;
558 if (g.name() != "*")
559 setlocale(LC_ALL, g.name().c_str());
560 return r;
561}
562
563bool
564locale::has_facet(id& x) const
565{
566 return __locale_->has_facet(x.__get());
567}
568
569const locale::facet*
570locale::use_facet(id& x) const
571{
572 return __locale_->use_facet(x.__get());
573}
574
575bool
576locale::operator==(const locale& y) const
577{
578 return (__locale_ == y.__locale_)
579 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
580}
581
582// locale::facet
583
584locale::facet::~facet()
585{
586}
587
588void
Howard Hinnant1694d232011-05-28 14:41:13 +0000589locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000590{
591 delete this;
592}
593
594// locale::id
595
596int32_t locale::id::__next_id = 0;
597
598namespace
599{
600
601class __fake_bind
602{
603 locale::id* id_;
604 void (locale::id::* pmf_)();
605public:
606 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
607 : id_(id), pmf_(pmf) {}
608
609 void operator()() const
610 {
611 (id_->*pmf_)();
612 }
613};
614
615}
616
617long
618locale::id::__get()
619{
620 call_once(__flag_, __fake_bind(&locale::id::__init, this));
621 return __id_ - 1;
622}
623
624void
625locale::id::__init()
626{
Howard Hinnantadff4892010-05-24 17:49:41 +0000627 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000628}
629
630// template <> class collate_byname<char>
631
632collate_byname<char>::collate_byname(const char* n, size_t refs)
633 : collate<char>(refs),
634 __l(newlocale(LC_ALL_MASK, n, 0))
635{
Howard Hinnantd4444702010-08-11 17:04:31 +0000636#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000637 if (__l == 0)
638 throw runtime_error("collate_byname<char>::collate_byname"
639 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000640#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000641}
642
643collate_byname<char>::collate_byname(const string& name, size_t refs)
644 : collate<char>(refs),
645 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
646{
Howard Hinnantd4444702010-08-11 17:04:31 +0000647#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000648 if (__l == 0)
649 throw runtime_error("collate_byname<char>::collate_byname"
650 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000651#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000652}
653
654collate_byname<char>::~collate_byname()
655{
656 freelocale(__l);
657}
658
659int
660collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
661 const char_type* __lo2, const char_type* __hi2) const
662{
663 string_type lhs(__lo1, __hi1);
664 string_type rhs(__lo2, __hi2);
665 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
666 if (r < 0)
667 return -1;
668 if (r > 0)
669 return 1;
670 return r;
671}
672
673collate_byname<char>::string_type
674collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
675{
676 const string_type in(lo, hi);
677 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
678 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
679 return out;
680}
681
682// template <> class collate_byname<wchar_t>
683
684collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
685 : collate<wchar_t>(refs),
686 __l(newlocale(LC_ALL_MASK, n, 0))
687{
Howard Hinnantd4444702010-08-11 17:04:31 +0000688#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000689 if (__l == 0)
690 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
691 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000692#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000693}
694
695collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
696 : collate<wchar_t>(refs),
697 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
698{
Howard Hinnantd4444702010-08-11 17:04:31 +0000699#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000700 if (__l == 0)
701 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
702 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000703#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000704}
705
706collate_byname<wchar_t>::~collate_byname()
707{
708 freelocale(__l);
709}
710
711int
712collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
713 const char_type* __lo2, const char_type* __hi2) const
714{
715 string_type lhs(__lo1, __hi1);
716 string_type rhs(__lo2, __hi2);
717 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
718 if (r < 0)
719 return -1;
720 if (r > 0)
721 return 1;
722 return r;
723}
724
725collate_byname<wchar_t>::string_type
726collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
727{
728 const string_type in(lo, hi);
729 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
730 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
731 return out;
732}
733
734// template <> class ctype<wchar_t>;
735
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000736const ctype_base::mask ctype_base::space;
737const ctype_base::mask ctype_base::print;
738const ctype_base::mask ctype_base::cntrl;
739const ctype_base::mask ctype_base::upper;
740const ctype_base::mask ctype_base::lower;
741const ctype_base::mask ctype_base::alpha;
742const ctype_base::mask ctype_base::digit;
743const ctype_base::mask ctype_base::punct;
744const ctype_base::mask ctype_base::xdigit;
745const ctype_base::mask ctype_base::blank;
746const ctype_base::mask ctype_base::alnum;
747const ctype_base::mask ctype_base::graph;
748
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000749locale::id ctype<wchar_t>::id;
750
751ctype<wchar_t>::~ctype()
752{
753}
754
755bool
756ctype<wchar_t>::do_is(mask m, char_type c) const
757{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000758 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000759}
760
761const wchar_t*
762ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
763{
764 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000765 *vec = static_cast<mask>(isascii(*low) ?
766 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000767 return low;
768}
769
770const wchar_t*
771ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
772{
773 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000774 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000775 break;
776 return low;
777}
778
779const wchar_t*
780ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
781{
782 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000783 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000784 break;
785 return low;
786}
787
788wchar_t
789ctype<wchar_t>::do_toupper(char_type c) const
790{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000791#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
792 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000793#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000794 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000795#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000796 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000797#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000798}
799
800const wchar_t*
801ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
802{
803 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000804#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
805 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000806#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000807 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
808 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000809#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000810 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000811#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000812 return low;
813}
814
815wchar_t
816ctype<wchar_t>::do_tolower(char_type c) const
817{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000818#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
819 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000820#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000821 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000822#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000823 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000824#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000825}
826
827const wchar_t*
828ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
829{
830 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000831#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
832 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000833#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000834 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
835 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000836#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000837 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000838#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000839 return low;
840}
841
842wchar_t
843ctype<wchar_t>::do_widen(char c) const
844{
845 return c;
846}
847
848const char*
849ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
850{
851 for (; low != high; ++low, ++dest)
852 *dest = *low;
853 return low;
854}
855
856char
857ctype<wchar_t>::do_narrow(char_type c, char dfault) const
858{
859 if (isascii(c))
860 return static_cast<char>(c);
861 return dfault;
862}
863
864const wchar_t*
865ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
866{
867 for (; low != high; ++low, ++dest)
868 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000869 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000870 else
871 *dest = dfault;
872 return low;
873}
874
875// template <> class ctype<char>;
876
877locale::id ctype<char>::id;
878
879ctype<char>::ctype(const mask* tab, bool del, size_t refs)
880 : locale::facet(refs),
881 __tab_(tab),
882 __del_(del)
883{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000884 if (__tab_ == 0)
885 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000886}
887
888ctype<char>::~ctype()
889{
890 if (__tab_ && __del_)
891 delete [] __tab_;
892}
893
894char
895ctype<char>::do_toupper(char_type c) const
896{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000897#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000898 return isascii(c) ?
899 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000900#elif defined(__NetBSD__)
901 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000902#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000903 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000904 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000905#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000906 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000907#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000908}
909
910const char*
911ctype<char>::do_toupper(char_type* low, const char_type* high) const
912{
913 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000914#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000915 *low = isascii(*low) ?
916 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000917#elif defined(__NetBSD__)
918 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000919#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000920 *low = isascii(*low) ?
921 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000922#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000923 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000924#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000925 return low;
926}
927
928char
929ctype<char>::do_tolower(char_type c) const
930{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000931#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000932 return isascii(c) ?
933 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000934#elif defined(__NetBSD__)
935 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
936#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Marshall Clow88c31902013-02-07 14:22:51 +0000937 return isascii(c) ?
938 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000939#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000940 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000941#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000942}
943
944const char*
945ctype<char>::do_tolower(char_type* low, const char_type* high) const
946{
947 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000948#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000949 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000950#elif defined(__NetBSD__)
951 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000952#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000953 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000954#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000955 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000956#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000957 return low;
958}
959
960char
961ctype<char>::do_widen(char c) const
962{
963 return c;
964}
965
966const char*
967ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
968{
969 for (; low != high; ++low, ++dest)
970 *dest = *low;
971 return low;
972}
973
974char
975ctype<char>::do_narrow(char_type c, char dfault) const
976{
977 if (isascii(c))
978 return static_cast<char>(c);
979 return dfault;
980}
981
982const char*
983ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
984{
985 for (; low != high; ++low, ++dest)
986 if (isascii(*low))
987 *dest = *low;
988 else
989 *dest = dfault;
990 return low;
991}
992
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000993#ifdef EMSCRIPTEN
994extern "C" const unsigned short ** __ctype_b_loc();
995extern "C" const int ** __ctype_tolower_loc();
996extern "C" const int ** __ctype_toupper_loc();
997#endif
998
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000999const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001000ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001001{
David Chisnallc512df12011-09-21 08:39:44 +00001002#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001003 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001004#elif defined(__NetBSD__)
1005 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001006#elif defined(__GLIBC__)
1007 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001008#elif __sun__
1009 return __ctype_mask;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00001010#elif defined(_WIN32)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001011 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001012// This is assumed to be safe, which is a nonsense assumption because we're
1013// going to end up dereferencing it later...
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001014#elif defined(EMSCRIPTEN)
1015 return *__ctype_b_loc();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001016#else
David Chisnall997e4542012-02-29 13:05:08 +00001017 // Platform not supported: abort so the person doing the port knows what to
1018 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001019# warning ctype<char>::classic_table() is not implemented
David Chisnall997e4542012-02-29 13:05:08 +00001020 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001021 return NULL;
1022#endif
1023}
1024
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001025#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001026const int*
1027ctype<char>::__classic_lower_table() _NOEXCEPT
1028{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001029 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001030}
1031
1032const int*
1033ctype<char>::__classic_upper_table() _NOEXCEPT
1034{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001035 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001036}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001037#elif __NetBSD__
1038const short*
1039ctype<char>::__classic_lower_table() _NOEXCEPT
1040{
1041 return _C_tolower_tab_ + 1;
1042}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001044const short*
1045ctype<char>::__classic_upper_table() _NOEXCEPT
1046{
1047 return _C_toupper_tab_ + 1;
1048}
1049
1050#elif defined(EMSCRIPTEN)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001051const int*
1052ctype<char>::__classic_lower_table() _NOEXCEPT
1053{
1054 return *__ctype_tolower_loc();
1055}
1056
1057const int*
1058ctype<char>::__classic_upper_table() _NOEXCEPT
1059{
1060 return *__ctype_toupper_loc();
1061}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001062#endif // __GLIBC__ || EMSCRIPTEN || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001063
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001064// template <> class ctype_byname<char>
1065
1066ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1067 : ctype<char>(0, false, refs),
1068 __l(newlocale(LC_ALL_MASK, name, 0))
1069{
Howard Hinnantd4444702010-08-11 17:04:31 +00001070#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001071 if (__l == 0)
1072 throw runtime_error("ctype_byname<char>::ctype_byname"
1073 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001074#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001075}
1076
1077ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1078 : ctype<char>(0, false, refs),
1079 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1080{
Howard Hinnantd4444702010-08-11 17:04:31 +00001081#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001082 if (__l == 0)
1083 throw runtime_error("ctype_byname<char>::ctype_byname"
1084 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001085#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001086}
1087
1088ctype_byname<char>::~ctype_byname()
1089{
1090 freelocale(__l);
1091}
1092
1093char
1094ctype_byname<char>::do_toupper(char_type c) const
1095{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001096 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001097}
1098
1099const char*
1100ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1101{
1102 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001103 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001104 return low;
1105}
1106
1107char
1108ctype_byname<char>::do_tolower(char_type c) const
1109{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001110 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001111}
1112
1113const char*
1114ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1115{
1116 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001117 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001118 return low;
1119}
1120
1121// template <> class ctype_byname<wchar_t>
1122
1123ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1124 : ctype<wchar_t>(refs),
1125 __l(newlocale(LC_ALL_MASK, name, 0))
1126{
Howard Hinnantd4444702010-08-11 17:04:31 +00001127#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001128 if (__l == 0)
1129 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1130 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001131#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001132}
1133
1134ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1135 : ctype<wchar_t>(refs),
1136 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1137{
Howard Hinnantd4444702010-08-11 17:04:31 +00001138#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001139 if (__l == 0)
1140 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1141 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001142#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001143}
1144
1145ctype_byname<wchar_t>::~ctype_byname()
1146{
1147 freelocale(__l);
1148}
1149
1150bool
1151ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1152{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001153#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001154 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001155#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001156 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001157 wint_t ch = static_cast<wint_t>(c);
1158 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1159 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1160 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1161 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1162 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1163 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1164 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1165 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1166 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1167 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001168 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001169#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001170}
1171
1172const wchar_t*
1173ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1174{
1175 for (; low != high; ++low, ++vec)
1176 {
1177 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001178 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001179 else
1180 {
1181 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001182 wint_t ch = static_cast<wint_t>(*low);
1183 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001184 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001185 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001186 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001187 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001188 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001189 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001190 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001191 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001192 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001193 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001194 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001195 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001196 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001197 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001198 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001199 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200 *vec |= xdigit;
1201 }
1202 }
1203 return low;
1204}
1205
1206const wchar_t*
1207ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1208{
1209 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001210 {
1211#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001212 if (iswctype_l(*low, m, __l))
1213 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001214#else
Marshall Clow88c31902013-02-07 14:22:51 +00001215 wint_t ch = static_cast<wint_t>(*low);
1216 if (m & space && iswspace_l(ch, __l)) break;
1217 if (m & print && iswprint_l(ch, __l)) break;
1218 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1219 if (m & upper && iswupper_l(ch, __l)) break;
1220 if (m & lower && iswlower_l(ch, __l)) break;
1221 if (m & alpha && iswalpha_l(ch, __l)) break;
1222 if (m & digit && iswdigit_l(ch, __l)) break;
1223 if (m & punct && iswpunct_l(ch, __l)) break;
1224 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1225 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001226#endif
1227 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001228 return low;
1229}
1230
1231const wchar_t*
1232ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1233{
1234 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001235 {
1236#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001237 if (!iswctype_l(*low, m, __l))
1238 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001239#else
Marshall Clow88c31902013-02-07 14:22:51 +00001240 wint_t ch = static_cast<wint_t>(*low);
1241 if (m & space && iswspace_l(ch, __l)) continue;
1242 if (m & print && iswprint_l(ch, __l)) continue;
1243 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1244 if (m & upper && iswupper_l(ch, __l)) continue;
1245 if (m & lower && iswlower_l(ch, __l)) continue;
1246 if (m & alpha && iswalpha_l(ch, __l)) continue;
1247 if (m & digit && iswdigit_l(ch, __l)) continue;
1248 if (m & punct && iswpunct_l(ch, __l)) continue;
1249 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1250 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001251 break;
1252#endif
1253 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001254 return low;
1255}
1256
1257wchar_t
1258ctype_byname<wchar_t>::do_toupper(char_type c) const
1259{
1260 return towupper_l(c, __l);
1261}
1262
1263const wchar_t*
1264ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1265{
1266 for (; low != high; ++low)
1267 *low = towupper_l(*low, __l);
1268 return low;
1269}
1270
1271wchar_t
1272ctype_byname<wchar_t>::do_tolower(char_type c) const
1273{
1274 return towlower_l(c, __l);
1275}
1276
1277const wchar_t*
1278ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1279{
1280 for (; low != high; ++low)
1281 *low = towlower_l(*low, __l);
1282 return low;
1283}
1284
1285wchar_t
1286ctype_byname<wchar_t>::do_widen(char c) const
1287{
Howard Hinnant866569b2011-09-28 23:39:33 +00001288#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001289 return btowc_l(c, __l);
1290#else
1291 return __btowc_l(c, __l);
1292#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001293}
1294
1295const char*
1296ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1297{
1298 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001299#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001300 *dest = btowc_l(*low, __l);
1301#else
1302 *dest = __btowc_l(*low, __l);
1303#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001304 return low;
1305}
1306
1307char
1308ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1309{
Howard Hinnant866569b2011-09-28 23:39:33 +00001310#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001311 int r = wctob_l(c, __l);
1312#else
1313 int r = __wctob_l(c, __l);
1314#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001315 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001316}
1317
1318const wchar_t*
1319ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1320{
1321 for (; low != high; ++low, ++dest)
1322 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001323#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001324 int r = wctob_l(*low, __l);
1325#else
1326 int r = __wctob_l(*low, __l);
1327#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001328 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001329 }
1330 return low;
1331}
1332
1333// template <> class codecvt<char, char, mbstate_t>
1334
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001335locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001336
1337codecvt<char, char, mbstate_t>::~codecvt()
1338{
1339}
1340
1341codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001342codecvt<char, char, mbstate_t>::do_out(state_type&,
1343 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001344 extern_type* to, extern_type*, extern_type*& to_nxt) const
1345{
1346 frm_nxt = frm;
1347 to_nxt = to;
1348 return noconv;
1349}
1350
1351codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001352codecvt<char, char, mbstate_t>::do_in(state_type&,
1353 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001354 intern_type* to, intern_type*, intern_type*& to_nxt) const
1355{
1356 frm_nxt = frm;
1357 to_nxt = to;
1358 return noconv;
1359}
1360
1361codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001362codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001363 extern_type* to, extern_type*, extern_type*& to_nxt) const
1364{
1365 to_nxt = to;
1366 return noconv;
1367}
1368
1369int
Howard Hinnantc9834542011-05-31 15:34:58 +00001370codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001371{
1372 return 1;
1373}
1374
1375bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001376codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001377{
1378 return true;
1379}
1380
1381int
1382codecvt<char, char, mbstate_t>::do_length(state_type&,
1383 const extern_type* frm, const extern_type* end, size_t mx) const
1384{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001385 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001386}
1387
1388int
Howard Hinnantc9834542011-05-31 15:34:58 +00001389codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001390{
1391 return 1;
1392}
1393
1394// template <> class codecvt<wchar_t, char, mbstate_t>
1395
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001396locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001397
1398codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1399 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001400 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001401{
1402}
1403
1404codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1405 : locale::facet(refs),
1406 __l(newlocale(LC_ALL_MASK, nm, 0))
1407{
Howard Hinnantd4444702010-08-11 17:04:31 +00001408#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001409 if (__l == 0)
1410 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1411 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001412#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001413}
1414
1415codecvt<wchar_t, char, mbstate_t>::~codecvt()
1416{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001417 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001418 freelocale(__l);
1419}
1420
1421codecvt<wchar_t, char, mbstate_t>::result
1422codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001423 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001424 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1425{
1426 // look for first internal null in frm
1427 const intern_type* fend = frm;
1428 for (; fend != frm_end; ++fend)
1429 if (*fend == 0)
1430 break;
1431 // loop over all null-terminated sequences in frm
1432 to_nxt = to;
1433 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1434 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001435 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001436 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001437#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001438 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1439 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001440#else
1441 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1442#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001443 if (n == size_t(-1))
1444 {
1445 // need to recover to_nxt
1446 for (to_nxt = to; frm != frm_nxt; ++frm)
1447 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001448#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001449 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1450#else
1451 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1452#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001453 if (n == size_t(-1))
1454 break;
1455 to_nxt += n;
1456 }
1457 frm_nxt = frm;
1458 return error;
1459 }
1460 if (n == 0)
1461 return partial;
1462 to_nxt += n;
1463 if (to_nxt == to_end)
1464 break;
1465 if (fend != frm_end) // set up next null terminated sequence
1466 {
1467 // Try to write the terminating null
1468 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001469#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001470 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1471#else
1472 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1473#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001474 if (n == size_t(-1)) // on error
1475 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001476 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001477 return partial;
1478 for (extern_type* p = tmp; n; --n) // write it
1479 *to_nxt++ = *p++;
1480 ++frm_nxt;
1481 // look for next null in frm
1482 for (fend = frm_nxt; fend != frm_end; ++fend)
1483 if (*fend == 0)
1484 break;
1485 }
1486 }
1487 return frm_nxt == frm_end ? ok : partial;
1488}
1489
1490codecvt<wchar_t, char, mbstate_t>::result
1491codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001492 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001493 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1494{
1495 // look for first internal null in frm
1496 const extern_type* fend = frm;
1497 for (; fend != frm_end; ++fend)
1498 if (*fend == 0)
1499 break;
1500 // loop over all null-terminated sequences in frm
1501 to_nxt = to;
1502 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1503 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001504 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001505 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001506#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001507 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1508 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001509#else
1510 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1511#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001512 if (n == size_t(-1))
1513 {
1514 // need to recover to_nxt
1515 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1516 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001517#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001518 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1519 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001520#else
1521 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1522#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001523 switch (n)
1524 {
1525 case 0:
1526 ++frm;
1527 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001528 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001529 frm_nxt = frm;
1530 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001531 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 frm_nxt = frm;
1533 return partial;
1534 default:
1535 frm += n;
1536 break;
1537 }
1538 }
1539 frm_nxt = frm;
1540 return frm_nxt == frm_end ? ok : partial;
1541 }
1542 if (n == 0)
1543 return error;
1544 to_nxt += n;
1545 if (to_nxt == to_end)
1546 break;
1547 if (fend != frm_end) // set up next null terminated sequence
1548 {
1549 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001550#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001551 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1552#else
1553 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1554#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001555 if (n != 0) // on error
1556 return error;
1557 ++to_nxt;
1558 ++frm_nxt;
1559 // look for next null in frm
1560 for (fend = frm_nxt; fend != frm_end; ++fend)
1561 if (*fend == 0)
1562 break;
1563 }
1564 }
1565 return frm_nxt == frm_end ? ok : partial;
1566}
1567
1568codecvt<wchar_t, char, mbstate_t>::result
1569codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1570 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1571{
1572 to_nxt = to;
1573 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001574#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001575 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1576#else
1577 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1578#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001579 if (n == size_t(-1) || n == 0) // on error
1580 return error;
1581 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001582 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001583 return partial;
1584 for (extern_type* p = tmp; n; --n) // write it
1585 *to_nxt++ = *p++;
1586 return ok;
1587}
1588
1589int
Howard Hinnantc9834542011-05-31 15:34:58 +00001590codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001591{
Howard Hinnant866569b2011-09-28 23:39:33 +00001592#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001593 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1594#else
1595 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1596#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001597 {
1598 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001599#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001600 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1601#else
1602 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1603#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001604 return 1; // which take more than 1 char to form a wchar_t
1605 return 0;
1606 }
1607 return -1;
1608}
1609
1610bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001611codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001612{
1613 return false;
1614}
1615
1616int
1617codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1618 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1619{
1620 int nbytes = 0;
1621 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1622 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001623#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001624 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001625#else
1626 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1627#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001628 switch (n)
1629 {
1630 case 0:
1631 ++nbytes;
1632 ++frm;
1633 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001634 case size_t(-1):
1635 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001636 return nbytes;
1637 default:
1638 nbytes += n;
1639 frm += n;
1640 break;
1641 }
1642 }
1643 return nbytes;
1644}
1645
1646int
Howard Hinnantc9834542011-05-31 15:34:58 +00001647codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001648{
Howard Hinnant866569b2011-09-28 23:39:33 +00001649#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001650 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001651#else
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#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001654}
1655
1656// Valid UTF ranges
1657// UTF-32 UTF-16 UTF-8 # of code points
1658// first second first second third fourth
1659// 000000 - 00007F 0000 - 007F 00 - 7F 127
1660// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1661// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1662// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1663// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1664// 00D800 - 00DFFF invalid
1665// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1666// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1667// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1668// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1669
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001670static
1671codecvt_base::result
1672utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1673 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1674 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1675{
1676 frm_nxt = frm;
1677 to_nxt = to;
1678 if (mode & generate_header)
1679 {
1680 if (to_end-to_nxt < 3)
1681 return codecvt_base::partial;
1682 *to_nxt++ = static_cast<uint8_t>(0xEF);
1683 *to_nxt++ = static_cast<uint8_t>(0xBB);
1684 *to_nxt++ = static_cast<uint8_t>(0xBF);
1685 }
1686 for (; frm_nxt < frm_end; ++frm_nxt)
1687 {
1688 uint16_t wc1 = *frm_nxt;
1689 if (wc1 > Maxcode)
1690 return codecvt_base::error;
1691 if (wc1 < 0x0080)
1692 {
1693 if (to_end-to_nxt < 1)
1694 return codecvt_base::partial;
1695 *to_nxt++ = static_cast<uint8_t>(wc1);
1696 }
1697 else if (wc1 < 0x0800)
1698 {
1699 if (to_end-to_nxt < 2)
1700 return codecvt_base::partial;
1701 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1702 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1703 }
1704 else if (wc1 < 0xD800)
1705 {
1706 if (to_end-to_nxt < 3)
1707 return codecvt_base::partial;
1708 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1709 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1710 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1711 }
1712 else if (wc1 < 0xDC00)
1713 {
1714 if (frm_end-frm_nxt < 2)
1715 return codecvt_base::partial;
1716 uint16_t wc2 = frm_nxt[1];
1717 if ((wc2 & 0xFC00) != 0xDC00)
1718 return codecvt_base::error;
1719 if (to_end-to_nxt < 4)
1720 return codecvt_base::partial;
1721 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1722 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1723 return codecvt_base::error;
1724 ++frm_nxt;
1725 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1726 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1727 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1728 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1729 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1730 }
1731 else if (wc1 < 0xE000)
1732 {
1733 return codecvt_base::error;
1734 }
1735 else
1736 {
1737 if (to_end-to_nxt < 3)
1738 return codecvt_base::partial;
1739 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1740 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1741 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1742 }
1743 }
1744 return codecvt_base::ok;
1745}
1746
1747static
1748codecvt_base::result
1749utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1750 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1751 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1752{
1753 frm_nxt = frm;
1754 to_nxt = to;
1755 if (mode & generate_header)
1756 {
1757 if (to_end-to_nxt < 3)
1758 return codecvt_base::partial;
1759 *to_nxt++ = static_cast<uint8_t>(0xEF);
1760 *to_nxt++ = static_cast<uint8_t>(0xBB);
1761 *to_nxt++ = static_cast<uint8_t>(0xBF);
1762 }
1763 for (; frm_nxt < frm_end; ++frm_nxt)
1764 {
1765 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1766 if (wc1 > Maxcode)
1767 return codecvt_base::error;
1768 if (wc1 < 0x0080)
1769 {
1770 if (to_end-to_nxt < 1)
1771 return codecvt_base::partial;
1772 *to_nxt++ = static_cast<uint8_t>(wc1);
1773 }
1774 else if (wc1 < 0x0800)
1775 {
1776 if (to_end-to_nxt < 2)
1777 return codecvt_base::partial;
1778 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1779 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1780 }
1781 else if (wc1 < 0xD800)
1782 {
1783 if (to_end-to_nxt < 3)
1784 return codecvt_base::partial;
1785 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1786 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1787 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1788 }
1789 else if (wc1 < 0xDC00)
1790 {
1791 if (frm_end-frm_nxt < 2)
1792 return codecvt_base::partial;
1793 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1794 if ((wc2 & 0xFC00) != 0xDC00)
1795 return codecvt_base::error;
1796 if (to_end-to_nxt < 4)
1797 return codecvt_base::partial;
1798 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1799 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1800 return codecvt_base::error;
1801 ++frm_nxt;
1802 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1803 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1804 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1805 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1806 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1807 }
1808 else if (wc1 < 0xE000)
1809 {
1810 return codecvt_base::error;
1811 }
1812 else
1813 {
1814 if (to_end-to_nxt < 3)
1815 return codecvt_base::partial;
1816 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1817 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1818 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1819 }
1820 }
1821 return codecvt_base::ok;
1822}
1823
1824static
1825codecvt_base::result
1826utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1827 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1828 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1829{
1830 frm_nxt = frm;
1831 to_nxt = to;
1832 if (mode & consume_header)
1833 {
1834 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1835 frm_nxt[2] == 0xBF)
1836 frm_nxt += 3;
1837 }
1838 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1839 {
1840 uint8_t c1 = *frm_nxt;
1841 if (c1 > Maxcode)
1842 return codecvt_base::error;
1843 if (c1 < 0x80)
1844 {
1845 *to_nxt = static_cast<uint16_t>(c1);
1846 ++frm_nxt;
1847 }
1848 else if (c1 < 0xC2)
1849 {
1850 return codecvt_base::error;
1851 }
1852 else if (c1 < 0xE0)
1853 {
1854 if (frm_end-frm_nxt < 2)
1855 return codecvt_base::partial;
1856 uint8_t c2 = frm_nxt[1];
1857 if ((c2 & 0xC0) != 0x80)
1858 return codecvt_base::error;
1859 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1860 if (t > Maxcode)
1861 return codecvt_base::error;
1862 *to_nxt = t;
1863 frm_nxt += 2;
1864 }
1865 else if (c1 < 0xF0)
1866 {
1867 if (frm_end-frm_nxt < 3)
1868 return codecvt_base::partial;
1869 uint8_t c2 = frm_nxt[1];
1870 uint8_t c3 = frm_nxt[2];
1871 switch (c1)
1872 {
1873 case 0xE0:
1874 if ((c2 & 0xE0) != 0xA0)
1875 return codecvt_base::error;
1876 break;
1877 case 0xED:
1878 if ((c2 & 0xE0) != 0x80)
1879 return codecvt_base::error;
1880 break;
1881 default:
1882 if ((c2 & 0xC0) != 0x80)
1883 return codecvt_base::error;
1884 break;
1885 }
1886 if ((c3 & 0xC0) != 0x80)
1887 return codecvt_base::error;
1888 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1889 | ((c2 & 0x3F) << 6)
1890 | (c3 & 0x3F));
1891 if (t > Maxcode)
1892 return codecvt_base::error;
1893 *to_nxt = t;
1894 frm_nxt += 3;
1895 }
1896 else if (c1 < 0xF5)
1897 {
1898 if (frm_end-frm_nxt < 4)
1899 return codecvt_base::partial;
1900 uint8_t c2 = frm_nxt[1];
1901 uint8_t c3 = frm_nxt[2];
1902 uint8_t c4 = frm_nxt[3];
1903 switch (c1)
1904 {
1905 case 0xF0:
1906 if (!(0x90 <= c2 && c2 <= 0xBF))
1907 return codecvt_base::error;
1908 break;
1909 case 0xF4:
1910 if ((c2 & 0xF0) != 0x80)
1911 return codecvt_base::error;
1912 break;
1913 default:
1914 if ((c2 & 0xC0) != 0x80)
1915 return codecvt_base::error;
1916 break;
1917 }
1918 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1919 return codecvt_base::error;
1920 if (to_end-to_nxt < 2)
1921 return codecvt_base::partial;
1922 if (((((unsigned long)c1 & 7) << 18) +
1923 (((unsigned long)c2 & 0x3F) << 12) +
1924 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1925 return codecvt_base::error;
1926 *to_nxt = static_cast<uint16_t>(
1927 0xD800
1928 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1929 | ((c2 & 0x0F) << 2)
1930 | ((c3 & 0x30) >> 4));
1931 *++to_nxt = static_cast<uint16_t>(
1932 0xDC00
1933 | ((c3 & 0x0F) << 6)
1934 | (c4 & 0x3F));
1935 frm_nxt += 4;
1936 }
1937 else
1938 {
1939 return codecvt_base::error;
1940 }
1941 }
1942 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1943}
1944
1945static
1946codecvt_base::result
1947utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1948 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1949 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1950{
1951 frm_nxt = frm;
1952 to_nxt = to;
1953 if (mode & consume_header)
1954 {
1955 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1956 frm_nxt[2] == 0xBF)
1957 frm_nxt += 3;
1958 }
1959 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1960 {
1961 uint8_t c1 = *frm_nxt;
1962 if (c1 > Maxcode)
1963 return codecvt_base::error;
1964 if (c1 < 0x80)
1965 {
1966 *to_nxt = static_cast<uint32_t>(c1);
1967 ++frm_nxt;
1968 }
1969 else if (c1 < 0xC2)
1970 {
1971 return codecvt_base::error;
1972 }
1973 else if (c1 < 0xE0)
1974 {
1975 if (frm_end-frm_nxt < 2)
1976 return codecvt_base::partial;
1977 uint8_t c2 = frm_nxt[1];
1978 if ((c2 & 0xC0) != 0x80)
1979 return codecvt_base::error;
1980 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1981 if (t > Maxcode)
1982 return codecvt_base::error;
1983 *to_nxt = static_cast<uint32_t>(t);
1984 frm_nxt += 2;
1985 }
1986 else if (c1 < 0xF0)
1987 {
1988 if (frm_end-frm_nxt < 3)
1989 return codecvt_base::partial;
1990 uint8_t c2 = frm_nxt[1];
1991 uint8_t c3 = frm_nxt[2];
1992 switch (c1)
1993 {
1994 case 0xE0:
1995 if ((c2 & 0xE0) != 0xA0)
1996 return codecvt_base::error;
1997 break;
1998 case 0xED:
1999 if ((c2 & 0xE0) != 0x80)
2000 return codecvt_base::error;
2001 break;
2002 default:
2003 if ((c2 & 0xC0) != 0x80)
2004 return codecvt_base::error;
2005 break;
2006 }
2007 if ((c3 & 0xC0) != 0x80)
2008 return codecvt_base::error;
2009 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2010 | ((c2 & 0x3F) << 6)
2011 | (c3 & 0x3F));
2012 if (t > Maxcode)
2013 return codecvt_base::error;
2014 *to_nxt = static_cast<uint32_t>(t);
2015 frm_nxt += 3;
2016 }
2017 else if (c1 < 0xF5)
2018 {
2019 if (frm_end-frm_nxt < 4)
2020 return codecvt_base::partial;
2021 uint8_t c2 = frm_nxt[1];
2022 uint8_t c3 = frm_nxt[2];
2023 uint8_t c4 = frm_nxt[3];
2024 switch (c1)
2025 {
2026 case 0xF0:
2027 if (!(0x90 <= c2 && c2 <= 0xBF))
2028 return codecvt_base::error;
2029 break;
2030 case 0xF4:
2031 if ((c2 & 0xF0) != 0x80)
2032 return codecvt_base::error;
2033 break;
2034 default:
2035 if ((c2 & 0xC0) != 0x80)
2036 return codecvt_base::error;
2037 break;
2038 }
2039 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2040 return codecvt_base::error;
2041 if (to_end-to_nxt < 2)
2042 return codecvt_base::partial;
2043 if (((((unsigned long)c1 & 7) << 18) +
2044 (((unsigned long)c2 & 0x3F) << 12) +
2045 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2046 return codecvt_base::error;
2047 *to_nxt = static_cast<uint32_t>(
2048 0xD800
2049 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2050 | ((c2 & 0x0F) << 2)
2051 | ((c3 & 0x30) >> 4));
2052 *++to_nxt = static_cast<uint32_t>(
2053 0xDC00
2054 | ((c3 & 0x0F) << 6)
2055 | (c4 & 0x3F));
2056 frm_nxt += 4;
2057 }
2058 else
2059 {
2060 return codecvt_base::error;
2061 }
2062 }
2063 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2064}
2065
2066static
2067int
2068utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2069 size_t mx, unsigned long Maxcode = 0x10FFFF,
2070 codecvt_mode mode = codecvt_mode(0))
2071{
2072 const uint8_t* frm_nxt = frm;
2073 if (mode & consume_header)
2074 {
2075 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2076 frm_nxt[2] == 0xBF)
2077 frm_nxt += 3;
2078 }
2079 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2080 {
2081 uint8_t c1 = *frm_nxt;
2082 if (c1 > Maxcode)
2083 break;
2084 if (c1 < 0x80)
2085 {
2086 ++frm_nxt;
2087 }
2088 else if (c1 < 0xC2)
2089 {
2090 break;
2091 }
2092 else if (c1 < 0xE0)
2093 {
2094 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2095 break;
2096 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2097 if (t > Maxcode)
2098 break;
2099 frm_nxt += 2;
2100 }
2101 else if (c1 < 0xF0)
2102 {
2103 if (frm_end-frm_nxt < 3)
2104 break;
2105 uint8_t c2 = frm_nxt[1];
2106 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002107 switch (c1)
2108 {
2109 case 0xE0:
2110 if ((c2 & 0xE0) != 0xA0)
2111 return static_cast<int>(frm_nxt - frm);
2112 break;
2113 case 0xED:
2114 if ((c2 & 0xE0) != 0x80)
2115 return static_cast<int>(frm_nxt - frm);
2116 break;
2117 default:
2118 if ((c2 & 0xC0) != 0x80)
2119 return static_cast<int>(frm_nxt - frm);
2120 break;
2121 }
2122 if ((c3 & 0xC0) != 0x80)
2123 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002124 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002125 break;
2126 frm_nxt += 3;
2127 }
2128 else if (c1 < 0xF5)
2129 {
2130 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2131 break;
2132 uint8_t c2 = frm_nxt[1];
2133 uint8_t c3 = frm_nxt[2];
2134 uint8_t c4 = frm_nxt[3];
2135 switch (c1)
2136 {
2137 case 0xF0:
2138 if (!(0x90 <= c2 && c2 <= 0xBF))
2139 return static_cast<int>(frm_nxt - frm);
2140 break;
2141 case 0xF4:
2142 if ((c2 & 0xF0) != 0x80)
2143 return static_cast<int>(frm_nxt - frm);
2144 break;
2145 default:
2146 if ((c2 & 0xC0) != 0x80)
2147 return static_cast<int>(frm_nxt - frm);
2148 break;
2149 }
2150 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2151 break;
2152 if (((((unsigned long)c1 & 7) << 18) +
2153 (((unsigned long)c2 & 0x3F) << 12) +
2154 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2155 break;
2156 ++nchar16_t;
2157 frm_nxt += 4;
2158 }
2159 else
2160 {
2161 break;
2162 }
2163 }
2164 return static_cast<int>(frm_nxt - frm);
2165}
2166
2167static
2168codecvt_base::result
2169ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2170 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2171 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2172{
2173 frm_nxt = frm;
2174 to_nxt = to;
2175 if (mode & generate_header)
2176 {
2177 if (to_end-to_nxt < 3)
2178 return codecvt_base::partial;
2179 *to_nxt++ = static_cast<uint8_t>(0xEF);
2180 *to_nxt++ = static_cast<uint8_t>(0xBB);
2181 *to_nxt++ = static_cast<uint8_t>(0xBF);
2182 }
2183 for (; frm_nxt < frm_end; ++frm_nxt)
2184 {
2185 uint32_t wc = *frm_nxt;
2186 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2187 return codecvt_base::error;
2188 if (wc < 0x000080)
2189 {
2190 if (to_end-to_nxt < 1)
2191 return codecvt_base::partial;
2192 *to_nxt++ = static_cast<uint8_t>(wc);
2193 }
2194 else if (wc < 0x000800)
2195 {
2196 if (to_end-to_nxt < 2)
2197 return codecvt_base::partial;
2198 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2199 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2200 }
2201 else if (wc < 0x010000)
2202 {
2203 if (to_end-to_nxt < 3)
2204 return codecvt_base::partial;
2205 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2206 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2207 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2208 }
2209 else // if (wc < 0x110000)
2210 {
2211 if (to_end-to_nxt < 4)
2212 return codecvt_base::partial;
2213 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2214 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2215 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2216 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2217 }
2218 }
2219 return codecvt_base::ok;
2220}
2221
2222static
2223codecvt_base::result
2224utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2225 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2226 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2227{
2228 frm_nxt = frm;
2229 to_nxt = to;
2230 if (mode & consume_header)
2231 {
2232 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2233 frm_nxt[2] == 0xBF)
2234 frm_nxt += 3;
2235 }
2236 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2237 {
2238 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2239 if (c1 < 0x80)
2240 {
2241 if (c1 > Maxcode)
2242 return codecvt_base::error;
2243 *to_nxt = static_cast<uint32_t>(c1);
2244 ++frm_nxt;
2245 }
2246 else if (c1 < 0xC2)
2247 {
2248 return codecvt_base::error;
2249 }
2250 else if (c1 < 0xE0)
2251 {
2252 if (frm_end-frm_nxt < 2)
2253 return codecvt_base::partial;
2254 uint8_t c2 = frm_nxt[1];
2255 if ((c2 & 0xC0) != 0x80)
2256 return codecvt_base::error;
2257 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2258 | (c2 & 0x3F));
2259 if (t > Maxcode)
2260 return codecvt_base::error;
2261 *to_nxt = t;
2262 frm_nxt += 2;
2263 }
2264 else if (c1 < 0xF0)
2265 {
2266 if (frm_end-frm_nxt < 3)
2267 return codecvt_base::partial;
2268 uint8_t c2 = frm_nxt[1];
2269 uint8_t c3 = frm_nxt[2];
2270 switch (c1)
2271 {
2272 case 0xE0:
2273 if ((c2 & 0xE0) != 0xA0)
2274 return codecvt_base::error;
2275 break;
2276 case 0xED:
2277 if ((c2 & 0xE0) != 0x80)
2278 return codecvt_base::error;
2279 break;
2280 default:
2281 if ((c2 & 0xC0) != 0x80)
2282 return codecvt_base::error;
2283 break;
2284 }
2285 if ((c3 & 0xC0) != 0x80)
2286 return codecvt_base::error;
2287 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2288 | ((c2 & 0x3F) << 6)
2289 | (c3 & 0x3F));
2290 if (t > Maxcode)
2291 return codecvt_base::error;
2292 *to_nxt = t;
2293 frm_nxt += 3;
2294 }
2295 else if (c1 < 0xF5)
2296 {
2297 if (frm_end-frm_nxt < 4)
2298 return codecvt_base::partial;
2299 uint8_t c2 = frm_nxt[1];
2300 uint8_t c3 = frm_nxt[2];
2301 uint8_t c4 = frm_nxt[3];
2302 switch (c1)
2303 {
2304 case 0xF0:
2305 if (!(0x90 <= c2 && c2 <= 0xBF))
2306 return codecvt_base::error;
2307 break;
2308 case 0xF4:
2309 if ((c2 & 0xF0) != 0x80)
2310 return codecvt_base::error;
2311 break;
2312 default:
2313 if ((c2 & 0xC0) != 0x80)
2314 return codecvt_base::error;
2315 break;
2316 }
2317 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2318 return codecvt_base::error;
2319 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2320 | ((c2 & 0x3F) << 12)
2321 | ((c3 & 0x3F) << 6)
2322 | (c4 & 0x3F));
2323 if (t > Maxcode)
2324 return codecvt_base::error;
2325 *to_nxt = t;
2326 frm_nxt += 4;
2327 }
2328 else
2329 {
2330 return codecvt_base::error;
2331 }
2332 }
2333 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2334}
2335
2336static
2337int
2338utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2339 size_t mx, unsigned long Maxcode = 0x10FFFF,
2340 codecvt_mode mode = codecvt_mode(0))
2341{
2342 const uint8_t* frm_nxt = frm;
2343 if (mode & consume_header)
2344 {
2345 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2346 frm_nxt[2] == 0xBF)
2347 frm_nxt += 3;
2348 }
2349 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2350 {
2351 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2352 if (c1 < 0x80)
2353 {
2354 if (c1 > Maxcode)
2355 break;
2356 ++frm_nxt;
2357 }
2358 else if (c1 < 0xC2)
2359 {
2360 break;
2361 }
2362 else if (c1 < 0xE0)
2363 {
2364 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2365 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002366 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002367 break;
2368 frm_nxt += 2;
2369 }
2370 else if (c1 < 0xF0)
2371 {
2372 if (frm_end-frm_nxt < 3)
2373 break;
2374 uint8_t c2 = frm_nxt[1];
2375 uint8_t c3 = frm_nxt[2];
2376 switch (c1)
2377 {
2378 case 0xE0:
2379 if ((c2 & 0xE0) != 0xA0)
2380 return static_cast<int>(frm_nxt - frm);
2381 break;
2382 case 0xED:
2383 if ((c2 & 0xE0) != 0x80)
2384 return static_cast<int>(frm_nxt - frm);
2385 break;
2386 default:
2387 if ((c2 & 0xC0) != 0x80)
2388 return static_cast<int>(frm_nxt - frm);
2389 break;
2390 }
2391 if ((c3 & 0xC0) != 0x80)
2392 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002393 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002394 break;
2395 frm_nxt += 3;
2396 }
2397 else if (c1 < 0xF5)
2398 {
2399 if (frm_end-frm_nxt < 4)
2400 break;
2401 uint8_t c2 = frm_nxt[1];
2402 uint8_t c3 = frm_nxt[2];
2403 uint8_t c4 = frm_nxt[3];
2404 switch (c1)
2405 {
2406 case 0xF0:
2407 if (!(0x90 <= c2 && c2 <= 0xBF))
2408 return static_cast<int>(frm_nxt - frm);
2409 break;
2410 case 0xF4:
2411 if ((c2 & 0xF0) != 0x80)
2412 return static_cast<int>(frm_nxt - frm);
2413 break;
2414 default:
2415 if ((c2 & 0xC0) != 0x80)
2416 return static_cast<int>(frm_nxt - frm);
2417 break;
2418 }
2419 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2420 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002421 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2422 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002423 break;
2424 frm_nxt += 4;
2425 }
2426 else
2427 {
2428 break;
2429 }
2430 }
2431 return static_cast<int>(frm_nxt - frm);
2432}
2433
2434static
2435codecvt_base::result
2436ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2437 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2438 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2439{
2440 frm_nxt = frm;
2441 to_nxt = to;
2442 if (mode & generate_header)
2443 {
2444 if (to_end-to_nxt < 3)
2445 return codecvt_base::partial;
2446 *to_nxt++ = static_cast<uint8_t>(0xEF);
2447 *to_nxt++ = static_cast<uint8_t>(0xBB);
2448 *to_nxt++ = static_cast<uint8_t>(0xBF);
2449 }
2450 for (; frm_nxt < frm_end; ++frm_nxt)
2451 {
2452 uint16_t wc = *frm_nxt;
2453 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2454 return codecvt_base::error;
2455 if (wc < 0x0080)
2456 {
2457 if (to_end-to_nxt < 1)
2458 return codecvt_base::partial;
2459 *to_nxt++ = static_cast<uint8_t>(wc);
2460 }
2461 else if (wc < 0x0800)
2462 {
2463 if (to_end-to_nxt < 2)
2464 return codecvt_base::partial;
2465 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2466 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2467 }
2468 else // if (wc <= 0xFFFF)
2469 {
2470 if (to_end-to_nxt < 3)
2471 return codecvt_base::partial;
2472 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2473 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2474 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2475 }
2476 }
2477 return codecvt_base::ok;
2478}
2479
2480static
2481codecvt_base::result
2482utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2483 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2484 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2485{
2486 frm_nxt = frm;
2487 to_nxt = to;
2488 if (mode & consume_header)
2489 {
2490 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2491 frm_nxt[2] == 0xBF)
2492 frm_nxt += 3;
2493 }
2494 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2495 {
2496 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2497 if (c1 < 0x80)
2498 {
2499 if (c1 > Maxcode)
2500 return codecvt_base::error;
2501 *to_nxt = static_cast<uint16_t>(c1);
2502 ++frm_nxt;
2503 }
2504 else if (c1 < 0xC2)
2505 {
2506 return codecvt_base::error;
2507 }
2508 else if (c1 < 0xE0)
2509 {
2510 if (frm_end-frm_nxt < 2)
2511 return codecvt_base::partial;
2512 uint8_t c2 = frm_nxt[1];
2513 if ((c2 & 0xC0) != 0x80)
2514 return codecvt_base::error;
2515 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2516 | (c2 & 0x3F));
2517 if (t > Maxcode)
2518 return codecvt_base::error;
2519 *to_nxt = t;
2520 frm_nxt += 2;
2521 }
2522 else if (c1 < 0xF0)
2523 {
2524 if (frm_end-frm_nxt < 3)
2525 return codecvt_base::partial;
2526 uint8_t c2 = frm_nxt[1];
2527 uint8_t c3 = frm_nxt[2];
2528 switch (c1)
2529 {
2530 case 0xE0:
2531 if ((c2 & 0xE0) != 0xA0)
2532 return codecvt_base::error;
2533 break;
2534 case 0xED:
2535 if ((c2 & 0xE0) != 0x80)
2536 return codecvt_base::error;
2537 break;
2538 default:
2539 if ((c2 & 0xC0) != 0x80)
2540 return codecvt_base::error;
2541 break;
2542 }
2543 if ((c3 & 0xC0) != 0x80)
2544 return codecvt_base::error;
2545 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2546 | ((c2 & 0x3F) << 6)
2547 | (c3 & 0x3F));
2548 if (t > Maxcode)
2549 return codecvt_base::error;
2550 *to_nxt = t;
2551 frm_nxt += 3;
2552 }
2553 else
2554 {
2555 return codecvt_base::error;
2556 }
2557 }
2558 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2559}
2560
2561static
2562int
2563utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2564 size_t mx, unsigned long Maxcode = 0x10FFFF,
2565 codecvt_mode mode = codecvt_mode(0))
2566{
2567 const uint8_t* frm_nxt = frm;
2568 if (mode & consume_header)
2569 {
2570 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2571 frm_nxt[2] == 0xBF)
2572 frm_nxt += 3;
2573 }
2574 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2575 {
2576 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2577 if (c1 < 0x80)
2578 {
2579 if (c1 > Maxcode)
2580 break;
2581 ++frm_nxt;
2582 }
2583 else if (c1 < 0xC2)
2584 {
2585 break;
2586 }
2587 else if (c1 < 0xE0)
2588 {
2589 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2590 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002591 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002592 break;
2593 frm_nxt += 2;
2594 }
2595 else if (c1 < 0xF0)
2596 {
2597 if (frm_end-frm_nxt < 3)
2598 break;
2599 uint8_t c2 = frm_nxt[1];
2600 uint8_t c3 = frm_nxt[2];
2601 switch (c1)
2602 {
2603 case 0xE0:
2604 if ((c2 & 0xE0) != 0xA0)
2605 return static_cast<int>(frm_nxt - frm);
2606 break;
2607 case 0xED:
2608 if ((c2 & 0xE0) != 0x80)
2609 return static_cast<int>(frm_nxt - frm);
2610 break;
2611 default:
2612 if ((c2 & 0xC0) != 0x80)
2613 return static_cast<int>(frm_nxt - frm);
2614 break;
2615 }
2616 if ((c3 & 0xC0) != 0x80)
2617 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002618 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002619 break;
2620 frm_nxt += 3;
2621 }
2622 else
2623 {
2624 break;
2625 }
2626 }
2627 return static_cast<int>(frm_nxt - frm);
2628}
2629
2630static
2631codecvt_base::result
2632ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2633 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2634 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2635{
2636 frm_nxt = frm;
2637 to_nxt = to;
2638 if (mode & generate_header)
2639 {
2640 if (to_end-to_nxt < 2)
2641 return codecvt_base::partial;
2642 *to_nxt++ = static_cast<uint8_t>(0xFE);
2643 *to_nxt++ = static_cast<uint8_t>(0xFF);
2644 }
2645 for (; frm_nxt < frm_end; ++frm_nxt)
2646 {
2647 uint32_t wc = *frm_nxt;
2648 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2649 return codecvt_base::error;
2650 if (wc < 0x010000)
2651 {
2652 if (to_end-to_nxt < 2)
2653 return codecvt_base::partial;
2654 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2655 *to_nxt++ = static_cast<uint8_t>(wc);
2656 }
2657 else
2658 {
2659 if (to_end-to_nxt < 4)
2660 return codecvt_base::partial;
2661 uint16_t t = static_cast<uint16_t>(
2662 0xD800
2663 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2664 | ((wc & 0x00FC00) >> 10));
2665 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2666 *to_nxt++ = static_cast<uint8_t>(t);
2667 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2668 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2669 *to_nxt++ = static_cast<uint8_t>(t);
2670 }
2671 }
2672 return codecvt_base::ok;
2673}
2674
2675static
2676codecvt_base::result
2677utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2678 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2679 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2680{
2681 frm_nxt = frm;
2682 to_nxt = to;
2683 if (mode & consume_header)
2684 {
2685 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2686 frm_nxt += 2;
2687 }
2688 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2689 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002690 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002691 if ((c1 & 0xFC00) == 0xDC00)
2692 return codecvt_base::error;
2693 if ((c1 & 0xFC00) != 0xD800)
2694 {
2695 if (c1 > Maxcode)
2696 return codecvt_base::error;
2697 *to_nxt = static_cast<uint32_t>(c1);
2698 frm_nxt += 2;
2699 }
2700 else
2701 {
2702 if (frm_end-frm_nxt < 4)
2703 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002704 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002705 if ((c2 & 0xFC00) != 0xDC00)
2706 return codecvt_base::error;
2707 uint32_t t = static_cast<uint32_t>(
2708 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2709 | ((c1 & 0x003F) << 10)
2710 | (c2 & 0x03FF));
2711 if (t > Maxcode)
2712 return codecvt_base::error;
2713 *to_nxt = t;
2714 frm_nxt += 4;
2715 }
2716 }
2717 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2718}
2719
2720static
2721int
2722utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2723 size_t mx, unsigned long Maxcode = 0x10FFFF,
2724 codecvt_mode mode = codecvt_mode(0))
2725{
2726 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002727 if (mode & consume_header)
2728 {
2729 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2730 frm_nxt += 2;
2731 }
2732 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2733 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002734 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002735 if ((c1 & 0xFC00) == 0xDC00)
2736 break;
2737 if ((c1 & 0xFC00) != 0xD800)
2738 {
2739 if (c1 > Maxcode)
2740 break;
2741 frm_nxt += 2;
2742 }
2743 else
2744 {
2745 if (frm_end-frm_nxt < 4)
2746 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002747 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002748 if ((c2 & 0xFC00) != 0xDC00)
2749 break;
2750 uint32_t t = static_cast<uint32_t>(
2751 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2752 | ((c1 & 0x003F) << 10)
2753 | (c2 & 0x03FF));
2754 if (t > Maxcode)
2755 break;
2756 frm_nxt += 4;
2757 }
2758 }
2759 return static_cast<int>(frm_nxt - frm);
2760}
2761
2762static
2763codecvt_base::result
2764ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2765 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2766 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2767{
2768 frm_nxt = frm;
2769 to_nxt = to;
2770 if (mode & generate_header)
2771 {
2772 if (to_end-to_nxt < 2)
2773 return codecvt_base::partial;
2774 *to_nxt++ = static_cast<uint8_t>(0xFF);
2775 *to_nxt++ = static_cast<uint8_t>(0xFE);
2776 }
2777 for (; frm_nxt < frm_end; ++frm_nxt)
2778 {
2779 uint32_t wc = *frm_nxt;
2780 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2781 return codecvt_base::error;
2782 if (wc < 0x010000)
2783 {
2784 if (to_end-to_nxt < 2)
2785 return codecvt_base::partial;
2786 *to_nxt++ = static_cast<uint8_t>(wc);
2787 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2788 }
2789 else
2790 {
2791 if (to_end-to_nxt < 4)
2792 return codecvt_base::partial;
2793 uint16_t t = static_cast<uint16_t>(
2794 0xD800
2795 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2796 | ((wc & 0x00FC00) >> 10));
2797 *to_nxt++ = static_cast<uint8_t>(t);
2798 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2799 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2800 *to_nxt++ = static_cast<uint8_t>(t);
2801 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2802 }
2803 }
2804 return codecvt_base::ok;
2805}
2806
2807static
2808codecvt_base::result
2809utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2810 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2811 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2812{
2813 frm_nxt = frm;
2814 to_nxt = to;
2815 if (mode & consume_header)
2816 {
2817 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2818 frm_nxt += 2;
2819 }
2820 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2821 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002822 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002823 if ((c1 & 0xFC00) == 0xDC00)
2824 return codecvt_base::error;
2825 if ((c1 & 0xFC00) != 0xD800)
2826 {
2827 if (c1 > Maxcode)
2828 return codecvt_base::error;
2829 *to_nxt = static_cast<uint32_t>(c1);
2830 frm_nxt += 2;
2831 }
2832 else
2833 {
2834 if (frm_end-frm_nxt < 4)
2835 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002836 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002837 if ((c2 & 0xFC00) != 0xDC00)
2838 return codecvt_base::error;
2839 uint32_t t = static_cast<uint32_t>(
2840 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2841 | ((c1 & 0x003F) << 10)
2842 | (c2 & 0x03FF));
2843 if (t > Maxcode)
2844 return codecvt_base::error;
2845 *to_nxt = t;
2846 frm_nxt += 4;
2847 }
2848 }
2849 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2850}
2851
2852static
2853int
2854utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2855 size_t mx, unsigned long Maxcode = 0x10FFFF,
2856 codecvt_mode mode = codecvt_mode(0))
2857{
2858 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002859 if (mode & consume_header)
2860 {
2861 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2862 frm_nxt += 2;
2863 }
2864 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2865 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002866 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002867 if ((c1 & 0xFC00) == 0xDC00)
2868 break;
2869 if ((c1 & 0xFC00) != 0xD800)
2870 {
2871 if (c1 > Maxcode)
2872 break;
2873 frm_nxt += 2;
2874 }
2875 else
2876 {
2877 if (frm_end-frm_nxt < 4)
2878 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002879 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002880 if ((c2 & 0xFC00) != 0xDC00)
2881 break;
2882 uint32_t t = static_cast<uint32_t>(
2883 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2884 | ((c1 & 0x003F) << 10)
2885 | (c2 & 0x03FF));
2886 if (t > Maxcode)
2887 break;
2888 frm_nxt += 4;
2889 }
2890 }
2891 return static_cast<int>(frm_nxt - frm);
2892}
2893
2894static
2895codecvt_base::result
2896ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2897 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2898 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2899{
2900 frm_nxt = frm;
2901 to_nxt = to;
2902 if (mode & generate_header)
2903 {
2904 if (to_end-to_nxt < 2)
2905 return codecvt_base::partial;
2906 *to_nxt++ = static_cast<uint8_t>(0xFE);
2907 *to_nxt++ = static_cast<uint8_t>(0xFF);
2908 }
2909 for (; frm_nxt < frm_end; ++frm_nxt)
2910 {
2911 uint16_t wc = *frm_nxt;
2912 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2913 return codecvt_base::error;
2914 if (to_end-to_nxt < 2)
2915 return codecvt_base::partial;
2916 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2917 *to_nxt++ = static_cast<uint8_t>(wc);
2918 }
2919 return codecvt_base::ok;
2920}
2921
2922static
2923codecvt_base::result
2924utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2925 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2926 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2927{
2928 frm_nxt = frm;
2929 to_nxt = to;
2930 if (mode & consume_header)
2931 {
2932 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2933 frm_nxt += 2;
2934 }
2935 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2936 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002937 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002938 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2939 return codecvt_base::error;
2940 *to_nxt = c1;
2941 frm_nxt += 2;
2942 }
2943 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2944}
2945
2946static
2947int
2948utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2949 size_t mx, unsigned long Maxcode = 0x10FFFF,
2950 codecvt_mode mode = codecvt_mode(0))
2951{
2952 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002953 if (mode & consume_header)
2954 {
2955 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2956 frm_nxt += 2;
2957 }
2958 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2959 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002960 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002961 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2962 break;
2963 frm_nxt += 2;
2964 }
2965 return static_cast<int>(frm_nxt - frm);
2966}
2967
2968static
2969codecvt_base::result
2970ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2971 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2972 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2973{
2974 frm_nxt = frm;
2975 to_nxt = to;
2976 if (mode & generate_header)
2977 {
2978 if (to_end-to_nxt < 2)
2979 return codecvt_base::partial;
2980 *to_nxt++ = static_cast<uint8_t>(0xFF);
2981 *to_nxt++ = static_cast<uint8_t>(0xFE);
2982 }
2983 for (; frm_nxt < frm_end; ++frm_nxt)
2984 {
2985 uint16_t wc = *frm_nxt;
2986 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2987 return codecvt_base::error;
2988 if (to_end-to_nxt < 2)
2989 return codecvt_base::partial;
2990 *to_nxt++ = static_cast<uint8_t>(wc);
2991 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2992 }
2993 return codecvt_base::ok;
2994}
2995
2996static
2997codecvt_base::result
2998utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2999 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3000 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3001{
3002 frm_nxt = frm;
3003 to_nxt = to;
3004 if (mode & consume_header)
3005 {
3006 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3007 frm_nxt += 2;
3008 }
3009 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3010 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003011 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003012 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3013 return codecvt_base::error;
3014 *to_nxt = c1;
3015 frm_nxt += 2;
3016 }
3017 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3018}
3019
3020static
3021int
3022utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3023 size_t mx, unsigned long Maxcode = 0x10FFFF,
3024 codecvt_mode mode = codecvt_mode(0))
3025{
3026 const uint8_t* frm_nxt = frm;
3027 frm_nxt = frm;
3028 if (mode & consume_header)
3029 {
3030 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3031 frm_nxt += 2;
3032 }
3033 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3034 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003035 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003036 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3037 break;
3038 frm_nxt += 2;
3039 }
3040 return static_cast<int>(frm_nxt - frm);
3041}
3042
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003043// template <> class codecvt<char16_t, char, mbstate_t>
3044
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003045locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003046
3047codecvt<char16_t, char, mbstate_t>::~codecvt()
3048{
3049}
3050
3051codecvt<char16_t, char, mbstate_t>::result
3052codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003053 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003054 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3055{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003056 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3057 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3058 const uint16_t* _frm_nxt = _frm;
3059 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3060 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3061 uint8_t* _to_nxt = _to;
3062 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3063 frm_nxt = frm + (_frm_nxt - _frm);
3064 to_nxt = to + (_to_nxt - _to);
3065 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003066}
3067
3068codecvt<char16_t, char, mbstate_t>::result
3069codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003070 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003071 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3072{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003073 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3074 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3075 const uint8_t* _frm_nxt = _frm;
3076 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3077 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3078 uint16_t* _to_nxt = _to;
3079 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3080 frm_nxt = frm + (_frm_nxt - _frm);
3081 to_nxt = to + (_to_nxt - _to);
3082 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003083}
3084
3085codecvt<char16_t, char, mbstate_t>::result
3086codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3087 extern_type* to, extern_type*, extern_type*& to_nxt) const
3088{
3089 to_nxt = to;
3090 return noconv;
3091}
3092
3093int
Howard Hinnantc9834542011-05-31 15:34:58 +00003094codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003095{
3096 return 0;
3097}
3098
3099bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003100codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003101{
3102 return false;
3103}
3104
3105int
3106codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3107 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3108{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003109 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3110 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3111 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003112}
3113
3114int
Howard Hinnantc9834542011-05-31 15:34:58 +00003115codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003116{
3117 return 4;
3118}
3119
3120// template <> class codecvt<char32_t, char, mbstate_t>
3121
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003122locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003123
3124codecvt<char32_t, char, mbstate_t>::~codecvt()
3125{
3126}
3127
3128codecvt<char32_t, char, mbstate_t>::result
3129codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003130 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003131 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3132{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003133 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3134 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3135 const uint32_t* _frm_nxt = _frm;
3136 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3137 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3138 uint8_t* _to_nxt = _to;
3139 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3140 frm_nxt = frm + (_frm_nxt - _frm);
3141 to_nxt = to + (_to_nxt - _to);
3142 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003143}
3144
3145codecvt<char32_t, char, mbstate_t>::result
3146codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003147 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003148 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3149{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003150 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3151 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3152 const uint8_t* _frm_nxt = _frm;
3153 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3154 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3155 uint32_t* _to_nxt = _to;
3156 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3157 frm_nxt = frm + (_frm_nxt - _frm);
3158 to_nxt = to + (_to_nxt - _to);
3159 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003160}
3161
3162codecvt<char32_t, char, mbstate_t>::result
3163codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3164 extern_type* to, extern_type*, extern_type*& to_nxt) const
3165{
3166 to_nxt = to;
3167 return noconv;
3168}
3169
3170int
Howard Hinnantc9834542011-05-31 15:34:58 +00003171codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003172{
3173 return 0;
3174}
3175
3176bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003177codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003178{
3179 return false;
3180}
3181
3182int
3183codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3184 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3185{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003186 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3187 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3188 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003189}
3190
3191int
Howard Hinnantc9834542011-05-31 15:34:58 +00003192codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003193{
3194 return 4;
3195}
3196
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003197// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003198
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003199__codecvt_utf8<wchar_t>::result
3200__codecvt_utf8<wchar_t>::do_out(state_type&,
3201 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003202 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3203{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003204#if _WIN32
3205 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3206 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3207 const uint16_t* _frm_nxt = _frm;
3208#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003209 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3210 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3211 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003212#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003213 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3214 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3215 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003216#if _WIN32
3217 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3218 _Maxcode_, _Mode_);
3219#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003220 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3221 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003222#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003223 frm_nxt = frm + (_frm_nxt - _frm);
3224 to_nxt = to + (_to_nxt - _to);
3225 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003226}
3227
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003228__codecvt_utf8<wchar_t>::result
3229__codecvt_utf8<wchar_t>::do_in(state_type&,
3230 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003231 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3232{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003233 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3234 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3235 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003236#if _WIN32
3237 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3238 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3239 uint16_t* _to_nxt = _to;
3240 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3241 _Maxcode_, _Mode_);
3242#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003243 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3244 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3245 uint32_t* _to_nxt = _to;
3246 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3247 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003248#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003249 frm_nxt = frm + (_frm_nxt - _frm);
3250 to_nxt = to + (_to_nxt - _to);
3251 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003252}
3253
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003254__codecvt_utf8<wchar_t>::result
3255__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003256 extern_type* to, extern_type*, extern_type*& to_nxt) const
3257{
3258 to_nxt = to;
3259 return noconv;
3260}
3261
3262int
Howard Hinnantc9834542011-05-31 15:34:58 +00003263__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003264{
3265 return 0;
3266}
3267
3268bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003269__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003270{
3271 return false;
3272}
3273
3274int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003275__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003276 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3277{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003278 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3279 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3280 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003281}
3282
3283int
Howard Hinnantc9834542011-05-31 15:34:58 +00003284__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003285{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003286 if (_Mode_ & consume_header)
3287 return 7;
3288 return 4;
3289}
3290
3291// __codecvt_utf8<char16_t>
3292
3293__codecvt_utf8<char16_t>::result
3294__codecvt_utf8<char16_t>::do_out(state_type&,
3295 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3296 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3297{
3298 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3299 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3300 const uint16_t* _frm_nxt = _frm;
3301 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3302 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3303 uint8_t* _to_nxt = _to;
3304 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3305 _Maxcode_, _Mode_);
3306 frm_nxt = frm + (_frm_nxt - _frm);
3307 to_nxt = to + (_to_nxt - _to);
3308 return r;
3309}
3310
3311__codecvt_utf8<char16_t>::result
3312__codecvt_utf8<char16_t>::do_in(state_type&,
3313 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3314 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3315{
3316 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3317 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3318 const uint8_t* _frm_nxt = _frm;
3319 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3320 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3321 uint16_t* _to_nxt = _to;
3322 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3323 _Maxcode_, _Mode_);
3324 frm_nxt = frm + (_frm_nxt - _frm);
3325 to_nxt = to + (_to_nxt - _to);
3326 return r;
3327}
3328
3329__codecvt_utf8<char16_t>::result
3330__codecvt_utf8<char16_t>::do_unshift(state_type&,
3331 extern_type* to, extern_type*, extern_type*& to_nxt) const
3332{
3333 to_nxt = to;
3334 return noconv;
3335}
3336
3337int
Howard Hinnantc9834542011-05-31 15:34:58 +00003338__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003339{
3340 return 0;
3341}
3342
3343bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003344__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003345{
3346 return false;
3347}
3348
3349int
3350__codecvt_utf8<char16_t>::do_length(state_type&,
3351 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3352{
3353 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3354 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3355 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3356}
3357
3358int
Howard Hinnantc9834542011-05-31 15:34:58 +00003359__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003360{
3361 if (_Mode_ & consume_header)
3362 return 6;
3363 return 3;
3364}
3365
3366// __codecvt_utf8<char32_t>
3367
3368__codecvt_utf8<char32_t>::result
3369__codecvt_utf8<char32_t>::do_out(state_type&,
3370 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3371 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3372{
3373 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3374 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3375 const uint32_t* _frm_nxt = _frm;
3376 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3377 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3378 uint8_t* _to_nxt = _to;
3379 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3380 _Maxcode_, _Mode_);
3381 frm_nxt = frm + (_frm_nxt - _frm);
3382 to_nxt = to + (_to_nxt - _to);
3383 return r;
3384}
3385
3386__codecvt_utf8<char32_t>::result
3387__codecvt_utf8<char32_t>::do_in(state_type&,
3388 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3389 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3390{
3391 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3392 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3393 const uint8_t* _frm_nxt = _frm;
3394 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3395 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3396 uint32_t* _to_nxt = _to;
3397 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3398 _Maxcode_, _Mode_);
3399 frm_nxt = frm + (_frm_nxt - _frm);
3400 to_nxt = to + (_to_nxt - _to);
3401 return r;
3402}
3403
3404__codecvt_utf8<char32_t>::result
3405__codecvt_utf8<char32_t>::do_unshift(state_type&,
3406 extern_type* to, extern_type*, extern_type*& to_nxt) const
3407{
3408 to_nxt = to;
3409 return noconv;
3410}
3411
3412int
Howard Hinnantc9834542011-05-31 15:34:58 +00003413__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003414{
3415 return 0;
3416}
3417
3418bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003419__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003420{
3421 return false;
3422}
3423
3424int
3425__codecvt_utf8<char32_t>::do_length(state_type&,
3426 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3427{
3428 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3429 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3430 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3431}
3432
3433int
Howard Hinnantc9834542011-05-31 15:34:58 +00003434__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003435{
3436 if (_Mode_ & consume_header)
3437 return 7;
3438 return 4;
3439}
3440
3441// __codecvt_utf16<wchar_t, false>
3442
3443__codecvt_utf16<wchar_t, false>::result
3444__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3445 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3446 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3447{
3448 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3449 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3450 const uint32_t* _frm_nxt = _frm;
3451 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3452 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3453 uint8_t* _to_nxt = _to;
3454 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3455 _Maxcode_, _Mode_);
3456 frm_nxt = frm + (_frm_nxt - _frm);
3457 to_nxt = to + (_to_nxt - _to);
3458 return r;
3459}
3460
3461__codecvt_utf16<wchar_t, false>::result
3462__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3463 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3464 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3465{
3466 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3467 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3468 const uint8_t* _frm_nxt = _frm;
3469 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3470 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3471 uint32_t* _to_nxt = _to;
3472 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3473 _Maxcode_, _Mode_);
3474 frm_nxt = frm + (_frm_nxt - _frm);
3475 to_nxt = to + (_to_nxt - _to);
3476 return r;
3477}
3478
3479__codecvt_utf16<wchar_t, false>::result
3480__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3481 extern_type* to, extern_type*, extern_type*& to_nxt) const
3482{
3483 to_nxt = to;
3484 return noconv;
3485}
3486
3487int
Howard Hinnantc9834542011-05-31 15:34:58 +00003488__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003489{
3490 return 0;
3491}
3492
3493bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003494__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003495{
3496 return false;
3497}
3498
3499int
3500__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3501 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3502{
3503 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3504 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3505 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3506}
3507
3508int
Howard Hinnantc9834542011-05-31 15:34:58 +00003509__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003510{
3511 if (_Mode_ & consume_header)
3512 return 6;
3513 return 4;
3514}
3515
3516// __codecvt_utf16<wchar_t, true>
3517
3518__codecvt_utf16<wchar_t, true>::result
3519__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3520 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3521 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3522{
3523 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3524 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3525 const uint32_t* _frm_nxt = _frm;
3526 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3527 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3528 uint8_t* _to_nxt = _to;
3529 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3530 _Maxcode_, _Mode_);
3531 frm_nxt = frm + (_frm_nxt - _frm);
3532 to_nxt = to + (_to_nxt - _to);
3533 return r;
3534}
3535
3536__codecvt_utf16<wchar_t, true>::result
3537__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3538 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3539 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3540{
3541 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3542 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3543 const uint8_t* _frm_nxt = _frm;
3544 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3545 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3546 uint32_t* _to_nxt = _to;
3547 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3548 _Maxcode_, _Mode_);
3549 frm_nxt = frm + (_frm_nxt - _frm);
3550 to_nxt = to + (_to_nxt - _to);
3551 return r;
3552}
3553
3554__codecvt_utf16<wchar_t, true>::result
3555__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3556 extern_type* to, extern_type*, extern_type*& to_nxt) const
3557{
3558 to_nxt = to;
3559 return noconv;
3560}
3561
3562int
Howard Hinnantc9834542011-05-31 15:34:58 +00003563__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003564{
3565 return 0;
3566}
3567
3568bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003569__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003570{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003571 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003572}
3573
3574int
3575__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3576 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3577{
3578 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3579 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3580 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3581}
3582
3583int
Howard Hinnantc9834542011-05-31 15:34:58 +00003584__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003585{
3586 if (_Mode_ & consume_header)
3587 return 6;
3588 return 4;
3589}
3590
3591// __codecvt_utf16<char16_t, false>
3592
3593__codecvt_utf16<char16_t, false>::result
3594__codecvt_utf16<char16_t, false>::do_out(state_type&,
3595 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3596 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3597{
3598 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3599 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3600 const uint16_t* _frm_nxt = _frm;
3601 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3602 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3603 uint8_t* _to_nxt = _to;
3604 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3605 _Maxcode_, _Mode_);
3606 frm_nxt = frm + (_frm_nxt - _frm);
3607 to_nxt = to + (_to_nxt - _to);
3608 return r;
3609}
3610
3611__codecvt_utf16<char16_t, false>::result
3612__codecvt_utf16<char16_t, false>::do_in(state_type&,
3613 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3614 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3615{
3616 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3617 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3618 const uint8_t* _frm_nxt = _frm;
3619 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3620 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3621 uint16_t* _to_nxt = _to;
3622 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3623 _Maxcode_, _Mode_);
3624 frm_nxt = frm + (_frm_nxt - _frm);
3625 to_nxt = to + (_to_nxt - _to);
3626 return r;
3627}
3628
3629__codecvt_utf16<char16_t, false>::result
3630__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3631 extern_type* to, extern_type*, extern_type*& to_nxt) const
3632{
3633 to_nxt = to;
3634 return noconv;
3635}
3636
3637int
Howard Hinnantc9834542011-05-31 15:34:58 +00003638__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003639{
3640 return 0;
3641}
3642
3643bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003644__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003645{
3646 return false;
3647}
3648
3649int
3650__codecvt_utf16<char16_t, false>::do_length(state_type&,
3651 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3652{
3653 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3654 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3655 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3656}
3657
3658int
Howard Hinnantc9834542011-05-31 15:34:58 +00003659__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003660{
3661 if (_Mode_ & consume_header)
3662 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003663 return 2;
3664}
3665
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003666// __codecvt_utf16<char16_t, true>
3667
3668__codecvt_utf16<char16_t, true>::result
3669__codecvt_utf16<char16_t, true>::do_out(state_type&,
3670 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3671 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3672{
3673 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3674 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3675 const uint16_t* _frm_nxt = _frm;
3676 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3677 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3678 uint8_t* _to_nxt = _to;
3679 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3680 _Maxcode_, _Mode_);
3681 frm_nxt = frm + (_frm_nxt - _frm);
3682 to_nxt = to + (_to_nxt - _to);
3683 return r;
3684}
3685
3686__codecvt_utf16<char16_t, true>::result
3687__codecvt_utf16<char16_t, true>::do_in(state_type&,
3688 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3689 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3690{
3691 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3692 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3693 const uint8_t* _frm_nxt = _frm;
3694 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3695 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3696 uint16_t* _to_nxt = _to;
3697 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3698 _Maxcode_, _Mode_);
3699 frm_nxt = frm + (_frm_nxt - _frm);
3700 to_nxt = to + (_to_nxt - _to);
3701 return r;
3702}
3703
3704__codecvt_utf16<char16_t, true>::result
3705__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3706 extern_type* to, extern_type*, extern_type*& to_nxt) const
3707{
3708 to_nxt = to;
3709 return noconv;
3710}
3711
3712int
Howard Hinnantc9834542011-05-31 15:34:58 +00003713__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003714{
3715 return 0;
3716}
3717
3718bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003719__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003720{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003721 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003722}
3723
3724int
3725__codecvt_utf16<char16_t, true>::do_length(state_type&,
3726 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3727{
3728 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3729 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3730 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3731}
3732
3733int
Howard Hinnantc9834542011-05-31 15:34:58 +00003734__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003735{
3736 if (_Mode_ & consume_header)
3737 return 4;
3738 return 2;
3739}
3740
3741// __codecvt_utf16<char32_t, false>
3742
3743__codecvt_utf16<char32_t, false>::result
3744__codecvt_utf16<char32_t, false>::do_out(state_type&,
3745 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3746 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3747{
3748 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3749 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3750 const uint32_t* _frm_nxt = _frm;
3751 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3752 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3753 uint8_t* _to_nxt = _to;
3754 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3755 _Maxcode_, _Mode_);
3756 frm_nxt = frm + (_frm_nxt - _frm);
3757 to_nxt = to + (_to_nxt - _to);
3758 return r;
3759}
3760
3761__codecvt_utf16<char32_t, false>::result
3762__codecvt_utf16<char32_t, false>::do_in(state_type&,
3763 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3764 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3765{
3766 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3767 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3768 const uint8_t* _frm_nxt = _frm;
3769 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3770 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3771 uint32_t* _to_nxt = _to;
3772 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3773 _Maxcode_, _Mode_);
3774 frm_nxt = frm + (_frm_nxt - _frm);
3775 to_nxt = to + (_to_nxt - _to);
3776 return r;
3777}
3778
3779__codecvt_utf16<char32_t, false>::result
3780__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3781 extern_type* to, extern_type*, extern_type*& to_nxt) const
3782{
3783 to_nxt = to;
3784 return noconv;
3785}
3786
3787int
Howard Hinnantc9834542011-05-31 15:34:58 +00003788__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003789{
3790 return 0;
3791}
3792
3793bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003794__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003795{
3796 return false;
3797}
3798
3799int
3800__codecvt_utf16<char32_t, false>::do_length(state_type&,
3801 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3802{
3803 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3804 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3805 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3806}
3807
3808int
Howard Hinnantc9834542011-05-31 15:34:58 +00003809__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003810{
3811 if (_Mode_ & consume_header)
3812 return 6;
3813 return 4;
3814}
3815
3816// __codecvt_utf16<char32_t, true>
3817
3818__codecvt_utf16<char32_t, true>::result
3819__codecvt_utf16<char32_t, true>::do_out(state_type&,
3820 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3821 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3822{
3823 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3824 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3825 const uint32_t* _frm_nxt = _frm;
3826 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3827 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3828 uint8_t* _to_nxt = _to;
3829 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3830 _Maxcode_, _Mode_);
3831 frm_nxt = frm + (_frm_nxt - _frm);
3832 to_nxt = to + (_to_nxt - _to);
3833 return r;
3834}
3835
3836__codecvt_utf16<char32_t, true>::result
3837__codecvt_utf16<char32_t, true>::do_in(state_type&,
3838 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3839 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3840{
3841 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3842 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3843 const uint8_t* _frm_nxt = _frm;
3844 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3845 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3846 uint32_t* _to_nxt = _to;
3847 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3848 _Maxcode_, _Mode_);
3849 frm_nxt = frm + (_frm_nxt - _frm);
3850 to_nxt = to + (_to_nxt - _to);
3851 return r;
3852}
3853
3854__codecvt_utf16<char32_t, true>::result
3855__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3856 extern_type* to, extern_type*, extern_type*& to_nxt) const
3857{
3858 to_nxt = to;
3859 return noconv;
3860}
3861
3862int
Howard Hinnantc9834542011-05-31 15:34:58 +00003863__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003864{
3865 return 0;
3866}
3867
3868bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003869__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003870{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003871 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003872}
3873
3874int
3875__codecvt_utf16<char32_t, true>::do_length(state_type&,
3876 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3877{
3878 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3879 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3880 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3881}
3882
3883int
Howard Hinnantc9834542011-05-31 15:34:58 +00003884__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003885{
3886 if (_Mode_ & consume_header)
3887 return 6;
3888 return 4;
3889}
3890
3891// __codecvt_utf8_utf16<wchar_t>
3892
3893__codecvt_utf8_utf16<wchar_t>::result
3894__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3895 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3896 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3897{
3898 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3899 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3900 const uint32_t* _frm_nxt = _frm;
3901 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3902 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3903 uint8_t* _to_nxt = _to;
3904 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3905 _Maxcode_, _Mode_);
3906 frm_nxt = frm + (_frm_nxt - _frm);
3907 to_nxt = to + (_to_nxt - _to);
3908 return r;
3909}
3910
3911__codecvt_utf8_utf16<wchar_t>::result
3912__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3913 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3914 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3915{
3916 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3917 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3918 const uint8_t* _frm_nxt = _frm;
3919 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3920 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3921 uint32_t* _to_nxt = _to;
3922 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3923 _Maxcode_, _Mode_);
3924 frm_nxt = frm + (_frm_nxt - _frm);
3925 to_nxt = to + (_to_nxt - _to);
3926 return r;
3927}
3928
3929__codecvt_utf8_utf16<wchar_t>::result
3930__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3931 extern_type* to, extern_type*, extern_type*& to_nxt) const
3932{
3933 to_nxt = to;
3934 return noconv;
3935}
3936
3937int
Howard Hinnantc9834542011-05-31 15:34:58 +00003938__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003939{
3940 return 0;
3941}
3942
3943bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003944__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003945{
3946 return false;
3947}
3948
3949int
3950__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3951 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3952{
3953 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3954 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3955 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3956}
3957
3958int
Howard Hinnantc9834542011-05-31 15:34:58 +00003959__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003960{
3961 if (_Mode_ & consume_header)
3962 return 7;
3963 return 4;
3964}
3965
3966// __codecvt_utf8_utf16<char16_t>
3967
3968__codecvt_utf8_utf16<char16_t>::result
3969__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3970 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3971 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3972{
3973 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3974 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3975 const uint16_t* _frm_nxt = _frm;
3976 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3977 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3978 uint8_t* _to_nxt = _to;
3979 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3980 _Maxcode_, _Mode_);
3981 frm_nxt = frm + (_frm_nxt - _frm);
3982 to_nxt = to + (_to_nxt - _to);
3983 return r;
3984}
3985
3986__codecvt_utf8_utf16<char16_t>::result
3987__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3988 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3989 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3990{
3991 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3992 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3993 const uint8_t* _frm_nxt = _frm;
3994 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3995 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3996 uint16_t* _to_nxt = _to;
3997 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3998 _Maxcode_, _Mode_);
3999 frm_nxt = frm + (_frm_nxt - _frm);
4000 to_nxt = to + (_to_nxt - _to);
4001 return r;
4002}
4003
4004__codecvt_utf8_utf16<char16_t>::result
4005__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4006 extern_type* to, extern_type*, extern_type*& to_nxt) const
4007{
4008 to_nxt = to;
4009 return noconv;
4010}
4011
4012int
Howard Hinnantc9834542011-05-31 15:34:58 +00004013__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004014{
4015 return 0;
4016}
4017
4018bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004019__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004020{
4021 return false;
4022}
4023
4024int
4025__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4026 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4027{
4028 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4029 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4030 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4031}
4032
4033int
Howard Hinnantc9834542011-05-31 15:34:58 +00004034__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004035{
4036 if (_Mode_ & consume_header)
4037 return 7;
4038 return 4;
4039}
4040
4041// __codecvt_utf8_utf16<char32_t>
4042
4043__codecvt_utf8_utf16<char32_t>::result
4044__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4045 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4046 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4047{
4048 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4049 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4050 const uint32_t* _frm_nxt = _frm;
4051 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4052 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4053 uint8_t* _to_nxt = _to;
4054 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4055 _Maxcode_, _Mode_);
4056 frm_nxt = frm + (_frm_nxt - _frm);
4057 to_nxt = to + (_to_nxt - _to);
4058 return r;
4059}
4060
4061__codecvt_utf8_utf16<char32_t>::result
4062__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4063 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4064 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4065{
4066 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4067 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4068 const uint8_t* _frm_nxt = _frm;
4069 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4070 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4071 uint32_t* _to_nxt = _to;
4072 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4073 _Maxcode_, _Mode_);
4074 frm_nxt = frm + (_frm_nxt - _frm);
4075 to_nxt = to + (_to_nxt - _to);
4076 return r;
4077}
4078
4079__codecvt_utf8_utf16<char32_t>::result
4080__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4081 extern_type* to, extern_type*, extern_type*& to_nxt) const
4082{
4083 to_nxt = to;
4084 return noconv;
4085}
4086
4087int
Howard Hinnantc9834542011-05-31 15:34:58 +00004088__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004089{
4090 return 0;
4091}
4092
4093bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004094__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004095{
4096 return false;
4097}
4098
4099int
4100__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4101 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4102{
4103 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4104 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4105 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4106}
4107
4108int
Howard Hinnantc9834542011-05-31 15:34:58 +00004109__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004110{
4111 if (_Mode_ & consume_header)
4112 return 7;
4113 return 4;
4114}
4115
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004116// __narrow_to_utf8<16>
4117
4118__narrow_to_utf8<16>::~__narrow_to_utf8()
4119{
4120}
4121
4122// __narrow_to_utf8<32>
4123
4124__narrow_to_utf8<32>::~__narrow_to_utf8()
4125{
4126}
4127
4128// __widen_from_utf8<16>
4129
4130__widen_from_utf8<16>::~__widen_from_utf8()
4131{
4132}
4133
4134// __widen_from_utf8<32>
4135
4136__widen_from_utf8<32>::~__widen_from_utf8()
4137{
4138}
4139
4140// numpunct<char> && numpunct<wchar_t>
4141
4142locale::id numpunct< char >::id;
4143locale::id numpunct<wchar_t>::id;
4144
4145numpunct<char>::numpunct(size_t refs)
4146 : locale::facet(refs),
4147 __decimal_point_('.'),
4148 __thousands_sep_(',')
4149{
4150}
4151
4152numpunct<wchar_t>::numpunct(size_t refs)
4153 : locale::facet(refs),
4154 __decimal_point_(L'.'),
4155 __thousands_sep_(L',')
4156{
4157}
4158
4159numpunct<char>::~numpunct()
4160{
4161}
4162
4163numpunct<wchar_t>::~numpunct()
4164{
4165}
4166
4167 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4168wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4169
4170 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4171wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4172
4173string numpunct< char >::do_grouping() const {return __grouping_;}
4174string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4175
4176 string numpunct< char >::do_truename() const {return "true";}
4177wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4178
4179 string numpunct< char >::do_falsename() const {return "false";}
4180wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4181
4182// numpunct_byname<char>
4183
4184numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4185 : numpunct<char>(refs)
4186{
4187 __init(nm);
4188}
4189
4190numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4191 : numpunct<char>(refs)
4192{
4193 __init(nm.c_str());
4194}
4195
4196numpunct_byname<char>::~numpunct_byname()
4197{
4198}
4199
4200void
4201numpunct_byname<char>::__init(const char* nm)
4202{
4203 if (strcmp(nm, "C") != 0)
4204 {
Sean Huntf3907e62011-07-15 05:40:33 +00004205 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004206#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004207 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004208 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4209 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004210#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004211#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004212 lconv* lc = localeconv_l(loc.get());
4213#else
4214 lconv* lc = __localeconv_l(loc.get());
4215#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004216 if (*lc->decimal_point)
4217 __decimal_point_ = *lc->decimal_point;
4218 if (*lc->thousands_sep)
4219 __thousands_sep_ = *lc->thousands_sep;
4220 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004221 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004222 }
4223}
4224
4225// numpunct_byname<wchar_t>
4226
4227numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4228 : numpunct<wchar_t>(refs)
4229{
4230 __init(nm);
4231}
4232
4233numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4234 : numpunct<wchar_t>(refs)
4235{
4236 __init(nm.c_str());
4237}
4238
4239numpunct_byname<wchar_t>::~numpunct_byname()
4240{
4241}
4242
4243void
4244numpunct_byname<wchar_t>::__init(const char* nm)
4245{
4246 if (strcmp(nm, "C") != 0)
4247 {
Sean Huntf3907e62011-07-15 05:40:33 +00004248 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004249#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004250 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004251 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4252 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004253#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004254#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004255 lconv* lc = localeconv_l(loc.get());
4256#else
4257 lconv* lc = __localeconv_l(loc.get());
4258#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004259 if (*lc->decimal_point)
4260 __decimal_point_ = *lc->decimal_point;
4261 if (*lc->thousands_sep)
4262 __thousands_sep_ = *lc->thousands_sep;
4263 __grouping_ = lc->grouping;
4264 // locallization for truename and falsename is not available
4265 }
4266}
4267
4268// num_get helpers
4269
4270int
4271__num_get_base::__get_base(ios_base& iob)
4272{
4273 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4274 if (__basefield == ios_base::oct)
4275 return 8;
4276 else if (__basefield == ios_base::hex)
4277 return 16;
4278 else if (__basefield == 0)
4279 return 0;
4280 return 10;
4281}
4282
4283const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4284
4285void
4286__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4287 ios_base::iostate& __err)
4288{
4289 if (__grouping.size() != 0)
4290 {
4291 reverse(__g, __g_end);
4292 const char* __ig = __grouping.data();
4293 const char* __eg = __ig + __grouping.size();
4294 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4295 {
4296 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4297 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004298 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004299 {
4300 __err = ios_base::failbit;
4301 return;
4302 }
4303 }
4304 if (__eg - __ig > 1)
4305 ++__ig;
4306 }
4307 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4308 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004309 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004310 __err = ios_base::failbit;
4311 }
4312 }
4313}
4314
4315void
4316__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4317 ios_base::fmtflags __flags)
4318{
4319 if (__flags & ios_base::showpos)
4320 *__fmtp++ = '+';
4321 if (__flags & ios_base::showbase)
4322 *__fmtp++ = '#';
4323 while(*__len)
4324 *__fmtp++ = *__len++;
4325 if ((__flags & ios_base::basefield) == ios_base::oct)
4326 *__fmtp = 'o';
4327 else if ((__flags & ios_base::basefield) == ios_base::hex)
4328 {
4329 if (__flags & ios_base::uppercase)
4330 *__fmtp = 'X';
4331 else
4332 *__fmtp = 'x';
4333 }
4334 else if (__signd)
4335 *__fmtp = 'd';
4336 else
4337 *__fmtp = 'u';
4338}
4339
4340bool
4341__num_put_base::__format_float(char* __fmtp, const char* __len,
4342 ios_base::fmtflags __flags)
4343{
4344 bool specify_precision = true;
4345 if (__flags & ios_base::showpos)
4346 *__fmtp++ = '+';
4347 if (__flags & ios_base::showpoint)
4348 *__fmtp++ = '#';
4349 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4350 bool uppercase = __flags & ios_base::uppercase;
4351 if (floatfield == (ios_base::fixed | ios_base::scientific))
4352 specify_precision = false;
4353 else
4354 {
4355 *__fmtp++ = '.';
4356 *__fmtp++ = '*';
4357 }
4358 while(*__len)
4359 *__fmtp++ = *__len++;
4360 if (floatfield == ios_base::fixed)
4361 {
4362 if (uppercase)
4363 *__fmtp = 'F';
4364 else
4365 *__fmtp = 'f';
4366 }
4367 else if (floatfield == ios_base::scientific)
4368 {
4369 if (uppercase)
4370 *__fmtp = 'E';
4371 else
4372 *__fmtp = 'e';
4373 }
4374 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4375 {
4376 if (uppercase)
4377 *__fmtp = 'A';
4378 else
4379 *__fmtp = 'a';
4380 }
4381 else
4382 {
4383 if (uppercase)
4384 *__fmtp = 'G';
4385 else
4386 *__fmtp = 'g';
4387 }
4388 return specify_precision;
4389}
4390
4391char*
4392__num_put_base::__identify_padding(char* __nb, char* __ne,
4393 const ios_base& __iob)
4394{
4395 switch (__iob.flags() & ios_base::adjustfield)
4396 {
4397 case ios_base::internal:
4398 if (__nb[0] == '-' || __nb[0] == '+')
4399 return __nb+1;
4400 if (__ne - __nb >= 2 && __nb[0] == '0'
4401 && (__nb[1] == 'x' || __nb[1] == 'X'))
4402 return __nb+2;
4403 break;
4404 case ios_base::left:
4405 return __ne;
4406 case ios_base::right:
4407 default:
4408 break;
4409 }
4410 return __nb;
4411}
4412
4413// time_get
4414
4415static
4416string*
4417init_weeks()
4418{
4419 static string weeks[14];
4420 weeks[0] = "Sunday";
4421 weeks[1] = "Monday";
4422 weeks[2] = "Tuesday";
4423 weeks[3] = "Wednesday";
4424 weeks[4] = "Thursday";
4425 weeks[5] = "Friday";
4426 weeks[6] = "Saturday";
4427 weeks[7] = "Sun";
4428 weeks[8] = "Mon";
4429 weeks[9] = "Tue";
4430 weeks[10] = "Wed";
4431 weeks[11] = "Thu";
4432 weeks[12] = "Fri";
4433 weeks[13] = "Sat";
4434 return weeks;
4435}
4436
4437static
4438wstring*
4439init_wweeks()
4440{
4441 static wstring weeks[14];
4442 weeks[0] = L"Sunday";
4443 weeks[1] = L"Monday";
4444 weeks[2] = L"Tuesday";
4445 weeks[3] = L"Wednesday";
4446 weeks[4] = L"Thursday";
4447 weeks[5] = L"Friday";
4448 weeks[6] = L"Saturday";
4449 weeks[7] = L"Sun";
4450 weeks[8] = L"Mon";
4451 weeks[9] = L"Tue";
4452 weeks[10] = L"Wed";
4453 weeks[11] = L"Thu";
4454 weeks[12] = L"Fri";
4455 weeks[13] = L"Sat";
4456 return weeks;
4457}
4458
4459template <>
4460const string*
4461__time_get_c_storage<char>::__weeks() const
4462{
4463 static const string* weeks = init_weeks();
4464 return weeks;
4465}
4466
4467template <>
4468const wstring*
4469__time_get_c_storage<wchar_t>::__weeks() const
4470{
4471 static const wstring* weeks = init_wweeks();
4472 return weeks;
4473}
4474
4475static
4476string*
4477init_months()
4478{
4479 static string months[24];
4480 months[0] = "January";
4481 months[1] = "February";
4482 months[2] = "March";
4483 months[3] = "April";
4484 months[4] = "May";
4485 months[5] = "June";
4486 months[6] = "July";
4487 months[7] = "August";
4488 months[8] = "September";
4489 months[9] = "October";
4490 months[10] = "November";
4491 months[11] = "December";
4492 months[12] = "Jan";
4493 months[13] = "Feb";
4494 months[14] = "Mar";
4495 months[15] = "Apr";
4496 months[16] = "May";
4497 months[17] = "Jun";
4498 months[18] = "Jul";
4499 months[19] = "Aug";
4500 months[20] = "Sep";
4501 months[21] = "Oct";
4502 months[22] = "Nov";
4503 months[23] = "Dec";
4504 return months;
4505}
4506
4507static
4508wstring*
4509init_wmonths()
4510{
4511 static wstring months[24];
4512 months[0] = L"January";
4513 months[1] = L"February";
4514 months[2] = L"March";
4515 months[3] = L"April";
4516 months[4] = L"May";
4517 months[5] = L"June";
4518 months[6] = L"July";
4519 months[7] = L"August";
4520 months[8] = L"September";
4521 months[9] = L"October";
4522 months[10] = L"November";
4523 months[11] = L"December";
4524 months[12] = L"Jan";
4525 months[13] = L"Feb";
4526 months[14] = L"Mar";
4527 months[15] = L"Apr";
4528 months[16] = L"May";
4529 months[17] = L"Jun";
4530 months[18] = L"Jul";
4531 months[19] = L"Aug";
4532 months[20] = L"Sep";
4533 months[21] = L"Oct";
4534 months[22] = L"Nov";
4535 months[23] = L"Dec";
4536 return months;
4537}
4538
4539template <>
4540const string*
4541__time_get_c_storage<char>::__months() const
4542{
4543 static const string* months = init_months();
4544 return months;
4545}
4546
4547template <>
4548const wstring*
4549__time_get_c_storage<wchar_t>::__months() const
4550{
4551 static const wstring* months = init_wmonths();
4552 return months;
4553}
4554
4555static
4556string*
4557init_am_pm()
4558{
4559 static string am_pm[24];
4560 am_pm[0] = "AM";
4561 am_pm[1] = "PM";
4562 return am_pm;
4563}
4564
4565static
4566wstring*
4567init_wam_pm()
4568{
4569 static wstring am_pm[24];
4570 am_pm[0] = L"AM";
4571 am_pm[1] = L"PM";
4572 return am_pm;
4573}
4574
4575template <>
4576const string*
4577__time_get_c_storage<char>::__am_pm() const
4578{
4579 static const string* am_pm = init_am_pm();
4580 return am_pm;
4581}
4582
4583template <>
4584const wstring*
4585__time_get_c_storage<wchar_t>::__am_pm() const
4586{
4587 static const wstring* am_pm = init_wam_pm();
4588 return am_pm;
4589}
4590
4591template <>
4592const string&
4593__time_get_c_storage<char>::__x() const
4594{
4595 static string s("%m/%d/%y");
4596 return s;
4597}
4598
4599template <>
4600const wstring&
4601__time_get_c_storage<wchar_t>::__x() const
4602{
4603 static wstring s(L"%m/%d/%y");
4604 return s;
4605}
4606
4607template <>
4608const string&
4609__time_get_c_storage<char>::__X() const
4610{
4611 static string s("%H:%M:%S");
4612 return s;
4613}
4614
4615template <>
4616const wstring&
4617__time_get_c_storage<wchar_t>::__X() const
4618{
4619 static wstring s(L"%H:%M:%S");
4620 return s;
4621}
4622
4623template <>
4624const string&
4625__time_get_c_storage<char>::__c() const
4626{
4627 static string s("%a %b %d %H:%M:%S %Y");
4628 return s;
4629}
4630
4631template <>
4632const wstring&
4633__time_get_c_storage<wchar_t>::__c() const
4634{
4635 static wstring s(L"%a %b %d %H:%M:%S %Y");
4636 return s;
4637}
4638
4639template <>
4640const string&
4641__time_get_c_storage<char>::__r() const
4642{
4643 static string s("%I:%M:%S %p");
4644 return s;
4645}
4646
4647template <>
4648const wstring&
4649__time_get_c_storage<wchar_t>::__r() const
4650{
4651 static wstring s(L"%I:%M:%S %p");
4652 return s;
4653}
4654
4655// time_get_byname
4656
4657__time_get::__time_get(const char* nm)
4658 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4659{
Howard Hinnantd4444702010-08-11 17:04:31 +00004660#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004661 if (__loc_ == 0)
4662 throw runtime_error("time_get_byname"
4663 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004664#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004665}
4666
4667__time_get::__time_get(const string& nm)
4668 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4669{
Howard Hinnantd4444702010-08-11 17:04:31 +00004670#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004671 if (__loc_ == 0)
4672 throw runtime_error("time_get_byname"
4673 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004674#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004675}
4676
4677__time_get::~__time_get()
4678{
4679 freelocale(__loc_);
4680}
4681
Howard Hinnant335b1512012-02-20 16:51:43 +00004682#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant21772ec2012-12-28 18:15:01 +00004683#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant335b1512012-02-20 16:51:43 +00004684
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004685template <>
4686string
4687__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4688{
Howard Hinnant3074a052012-02-19 14:55:32 +00004689 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004690 t.tm_sec = 59;
4691 t.tm_min = 55;
4692 t.tm_hour = 23;
4693 t.tm_mday = 31;
4694 t.tm_mon = 11;
4695 t.tm_year = 161;
4696 t.tm_wday = 6;
4697 t.tm_yday = 364;
4698 t.tm_isdst = -1;
4699 char buf[100];
4700 char f[3] = {0};
4701 f[0] = '%';
4702 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004703 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004704 char* bb = buf;
4705 char* be = buf + n;
4706 string result;
4707 while (bb != be)
4708 {
4709 if (ct.is(ctype_base::space, *bb))
4710 {
4711 result.push_back(' ');
4712 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4713 ;
4714 continue;
4715 }
4716 char* w = bb;
4717 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004718 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004719 ct, err, false)
4720 - this->__weeks_;
4721 if (i < 14)
4722 {
4723 result.push_back('%');
4724 if (i < 7)
4725 result.push_back('A');
4726 else
4727 result.push_back('a');
4728 bb = w;
4729 continue;
4730 }
4731 w = bb;
4732 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4733 ct, err, false)
4734 - this->__months_;
4735 if (i < 24)
4736 {
4737 result.push_back('%');
4738 if (i < 12)
4739 result.push_back('B');
4740 else
4741 result.push_back('b');
4742 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4743 result.back() = 'm';
4744 bb = w;
4745 continue;
4746 }
4747 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4748 {
4749 w = bb;
4750 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4751 ct, err, false) - this->__am_pm_;
4752 if (i < 2)
4753 {
4754 result.push_back('%');
4755 result.push_back('p');
4756 bb = w;
4757 continue;
4758 }
4759 }
4760 w = bb;
4761 if (ct.is(ctype_base::digit, *bb))
4762 {
4763 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4764 {
4765 case 6:
4766 result.push_back('%');
4767 result.push_back('w');
4768 break;
4769 case 7:
4770 result.push_back('%');
4771 result.push_back('u');
4772 break;
4773 case 11:
4774 result.push_back('%');
4775 result.push_back('I');
4776 break;
4777 case 12:
4778 result.push_back('%');
4779 result.push_back('m');
4780 break;
4781 case 23:
4782 result.push_back('%');
4783 result.push_back('H');
4784 break;
4785 case 31:
4786 result.push_back('%');
4787 result.push_back('d');
4788 break;
4789 case 55:
4790 result.push_back('%');
4791 result.push_back('M');
4792 break;
4793 case 59:
4794 result.push_back('%');
4795 result.push_back('S');
4796 break;
4797 case 61:
4798 result.push_back('%');
4799 result.push_back('y');
4800 break;
4801 case 364:
4802 result.push_back('%');
4803 result.push_back('j');
4804 break;
4805 case 2061:
4806 result.push_back('%');
4807 result.push_back('Y');
4808 break;
4809 default:
4810 for (; w != bb; ++w)
4811 result.push_back(*w);
4812 break;
4813 }
4814 continue;
4815 }
4816 if (*bb == '%')
4817 {
4818 result.push_back('%');
4819 result.push_back('%');
4820 ++bb;
4821 continue;
4822 }
4823 result.push_back(*bb);
4824 ++bb;
4825 }
4826 return result;
4827}
4828
Howard Hinnantec3773c2011-12-01 20:21:04 +00004829#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004830
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004831template <>
4832wstring
4833__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4834{
Howard Hinnant3074a052012-02-19 14:55:32 +00004835 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004836 t.tm_sec = 59;
4837 t.tm_min = 55;
4838 t.tm_hour = 23;
4839 t.tm_mday = 31;
4840 t.tm_mon = 11;
4841 t.tm_year = 161;
4842 t.tm_wday = 6;
4843 t.tm_yday = 364;
4844 t.tm_isdst = -1;
4845 char buf[100];
4846 char f[3] = {0};
4847 f[0] = '%';
4848 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004849 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004850 wchar_t wbuf[100];
4851 wchar_t* wbb = wbuf;
4852 mbstate_t mb = {0};
4853 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004854#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004855 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004856#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004859 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004860 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004861 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004862 wstring result;
4863 while (wbb != wbe)
4864 {
4865 if (ct.is(ctype_base::space, *wbb))
4866 {
4867 result.push_back(L' ');
4868 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4869 ;
4870 continue;
4871 }
4872 wchar_t* w = wbb;
4873 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004874 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004875 ct, err, false)
4876 - this->__weeks_;
4877 if (i < 14)
4878 {
4879 result.push_back(L'%');
4880 if (i < 7)
4881 result.push_back(L'A');
4882 else
4883 result.push_back(L'a');
4884 wbb = w;
4885 continue;
4886 }
4887 w = wbb;
4888 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4889 ct, err, false)
4890 - this->__months_;
4891 if (i < 24)
4892 {
4893 result.push_back(L'%');
4894 if (i < 12)
4895 result.push_back(L'B');
4896 else
4897 result.push_back(L'b');
4898 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4899 result.back() = L'm';
4900 wbb = w;
4901 continue;
4902 }
4903 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4904 {
4905 w = wbb;
4906 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4907 ct, err, false) - this->__am_pm_;
4908 if (i < 2)
4909 {
4910 result.push_back(L'%');
4911 result.push_back(L'p');
4912 wbb = w;
4913 continue;
4914 }
4915 }
4916 w = wbb;
4917 if (ct.is(ctype_base::digit, *wbb))
4918 {
4919 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4920 {
4921 case 6:
4922 result.push_back(L'%');
4923 result.push_back(L'w');
4924 break;
4925 case 7:
4926 result.push_back(L'%');
4927 result.push_back(L'u');
4928 break;
4929 case 11:
4930 result.push_back(L'%');
4931 result.push_back(L'I');
4932 break;
4933 case 12:
4934 result.push_back(L'%');
4935 result.push_back(L'm');
4936 break;
4937 case 23:
4938 result.push_back(L'%');
4939 result.push_back(L'H');
4940 break;
4941 case 31:
4942 result.push_back(L'%');
4943 result.push_back(L'd');
4944 break;
4945 case 55:
4946 result.push_back(L'%');
4947 result.push_back(L'M');
4948 break;
4949 case 59:
4950 result.push_back(L'%');
4951 result.push_back(L'S');
4952 break;
4953 case 61:
4954 result.push_back(L'%');
4955 result.push_back(L'y');
4956 break;
4957 case 364:
4958 result.push_back(L'%');
4959 result.push_back(L'j');
4960 break;
4961 case 2061:
4962 result.push_back(L'%');
4963 result.push_back(L'Y');
4964 break;
4965 default:
4966 for (; w != wbb; ++w)
4967 result.push_back(*w);
4968 break;
4969 }
4970 continue;
4971 }
4972 if (ct.narrow(*wbb, 0) == '%')
4973 {
4974 result.push_back(L'%');
4975 result.push_back(L'%');
4976 ++wbb;
4977 continue;
4978 }
4979 result.push_back(*wbb);
4980 ++wbb;
4981 }
4982 return result;
4983}
4984
4985template <>
4986void
4987__time_get_storage<char>::init(const ctype<char>& ct)
4988{
Howard Hinnantcd992362012-08-02 18:44:17 +00004989 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004990 char buf[100];
4991 // __weeks_
4992 for (int i = 0; i < 7; ++i)
4993 {
4994 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004995 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004996 __weeks_[i] = buf;
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+7] = buf;
4999 }
5000 // __months_
5001 for (int i = 0; i < 12; ++i)
5002 {
5003 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005004 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005005 __months_[i] = buf;
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+12] = buf;
5008 }
5009 // __am_pm_
5010 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005011 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005012 __am_pm_[0] = buf;
5013 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005014 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005015 __am_pm_[1] = buf;
5016 __c_ = __analyze('c', ct);
5017 __r_ = __analyze('r', ct);
5018 __x_ = __analyze('x', ct);
5019 __X_ = __analyze('X', ct);
5020}
5021
5022template <>
5023void
5024__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5025{
5026 tm t = {0};
5027 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005028 wchar_t wbuf[100];
5029 wchar_t* wbe;
5030 mbstate_t mb = {0};
5031 // __weeks_
5032 for (int i = 0; i < 7; ++i)
5033 {
5034 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005035 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005036 mb = mbstate_t();
5037 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005038#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005039 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005040#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005043 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005044 __throw_runtime_error("locale not supported");
5045 wbe = wbuf + j;
5046 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005047 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005048 mb = mbstate_t();
5049 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005050#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005051 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005052#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005055 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005056 __throw_runtime_error("locale not supported");
5057 wbe = wbuf + j;
5058 __weeks_[i+7].assign(wbuf, wbe);
5059 }
5060 // __months_
5061 for (int i = 0; i < 12; ++i)
5062 {
5063 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005064 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005065 mb = mbstate_t();
5066 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005067#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005068 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005069#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005072 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005073 __throw_runtime_error("locale not supported");
5074 wbe = wbuf + j;
5075 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005076 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005077 mb = mbstate_t();
5078 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005079#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005080 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005081#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005084 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005085 __throw_runtime_error("locale not supported");
5086 wbe = wbuf + j;
5087 __months_[i+12].assign(wbuf, wbe);
5088 }
5089 // __am_pm_
5090 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005091 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005092 mb = mbstate_t();
5093 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005094#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005095 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005096#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005099 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005100 __throw_runtime_error("locale not supported");
5101 wbe = wbuf + j;
5102 __am_pm_[0].assign(wbuf, wbe);
5103 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005104 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005105 mb = mbstate_t();
5106 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005107#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005108 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005109#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005112 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005113 __throw_runtime_error("locale not supported");
5114 wbe = wbuf + j;
5115 __am_pm_[1].assign(wbuf, wbe);
5116 __c_ = __analyze('c', ct);
5117 __r_ = __analyze('r', ct);
5118 __x_ = __analyze('x', ct);
5119 __X_ = __analyze('X', ct);
5120}
5121
5122template <class CharT>
5123struct _LIBCPP_HIDDEN __time_get_temp
5124 : public ctype_byname<CharT>
5125{
5126 explicit __time_get_temp(const char* nm)
5127 : ctype_byname<CharT>(nm, 1) {}
5128 explicit __time_get_temp(const string& nm)
5129 : ctype_byname<CharT>(nm, 1) {}
5130};
5131
5132template <>
5133__time_get_storage<char>::__time_get_storage(const char* __nm)
5134 : __time_get(__nm)
5135{
5136 const __time_get_temp<char> ct(__nm);
5137 init(ct);
5138}
5139
5140template <>
5141__time_get_storage<char>::__time_get_storage(const string& __nm)
5142 : __time_get(__nm)
5143{
5144 const __time_get_temp<char> ct(__nm);
5145 init(ct);
5146}
5147
5148template <>
5149__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5150 : __time_get(__nm)
5151{
5152 const __time_get_temp<wchar_t> ct(__nm);
5153 init(ct);
5154}
5155
5156template <>
5157__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5158 : __time_get(__nm)
5159{
5160 const __time_get_temp<wchar_t> ct(__nm);
5161 init(ct);
5162}
5163
5164template <>
5165time_base::dateorder
5166__time_get_storage<char>::__do_date_order() const
5167{
5168 unsigned i;
5169 for (i = 0; i < __x_.size(); ++i)
5170 if (__x_[i] == '%')
5171 break;
5172 ++i;
5173 switch (__x_[i])
5174 {
5175 case 'y':
5176 case 'Y':
5177 for (++i; i < __x_.size(); ++i)
5178 if (__x_[i] == '%')
5179 break;
5180 if (i == __x_.size())
5181 break;
5182 ++i;
5183 switch (__x_[i])
5184 {
5185 case 'm':
5186 for (++i; i < __x_.size(); ++i)
5187 if (__x_[i] == '%')
5188 break;
5189 if (i == __x_.size())
5190 break;
5191 ++i;
5192 if (__x_[i] == 'd')
5193 return time_base::ymd;
5194 break;
5195 case 'd':
5196 for (++i; i < __x_.size(); ++i)
5197 if (__x_[i] == '%')
5198 break;
5199 if (i == __x_.size())
5200 break;
5201 ++i;
5202 if (__x_[i] == 'm')
5203 return time_base::ydm;
5204 break;
5205 }
5206 break;
5207 case 'm':
5208 for (++i; i < __x_.size(); ++i)
5209 if (__x_[i] == '%')
5210 break;
5211 if (i == __x_.size())
5212 break;
5213 ++i;
5214 if (__x_[i] == 'd')
5215 {
5216 for (++i; i < __x_.size(); ++i)
5217 if (__x_[i] == '%')
5218 break;
5219 if (i == __x_.size())
5220 break;
5221 ++i;
5222 if (__x_[i] == 'y' || __x_[i] == 'Y')
5223 return time_base::mdy;
5224 break;
5225 }
5226 break;
5227 case 'd':
5228 for (++i; i < __x_.size(); ++i)
5229 if (__x_[i] == '%')
5230 break;
5231 if (i == __x_.size())
5232 break;
5233 ++i;
5234 if (__x_[i] == 'm')
5235 {
5236 for (++i; i < __x_.size(); ++i)
5237 if (__x_[i] == '%')
5238 break;
5239 if (i == __x_.size())
5240 break;
5241 ++i;
5242 if (__x_[i] == 'y' || __x_[i] == 'Y')
5243 return time_base::dmy;
5244 break;
5245 }
5246 break;
5247 }
5248 return time_base::no_order;
5249}
5250
5251template <>
5252time_base::dateorder
5253__time_get_storage<wchar_t>::__do_date_order() const
5254{
5255 unsigned i;
5256 for (i = 0; i < __x_.size(); ++i)
5257 if (__x_[i] == L'%')
5258 break;
5259 ++i;
5260 switch (__x_[i])
5261 {
5262 case L'y':
5263 case L'Y':
5264 for (++i; i < __x_.size(); ++i)
5265 if (__x_[i] == L'%')
5266 break;
5267 if (i == __x_.size())
5268 break;
5269 ++i;
5270 switch (__x_[i])
5271 {
5272 case L'm':
5273 for (++i; i < __x_.size(); ++i)
5274 if (__x_[i] == L'%')
5275 break;
5276 if (i == __x_.size())
5277 break;
5278 ++i;
5279 if (__x_[i] == L'd')
5280 return time_base::ymd;
5281 break;
5282 case L'd':
5283 for (++i; i < __x_.size(); ++i)
5284 if (__x_[i] == L'%')
5285 break;
5286 if (i == __x_.size())
5287 break;
5288 ++i;
5289 if (__x_[i] == L'm')
5290 return time_base::ydm;
5291 break;
5292 }
5293 break;
5294 case L'm':
5295 for (++i; i < __x_.size(); ++i)
5296 if (__x_[i] == L'%')
5297 break;
5298 if (i == __x_.size())
5299 break;
5300 ++i;
5301 if (__x_[i] == L'd')
5302 {
5303 for (++i; i < __x_.size(); ++i)
5304 if (__x_[i] == L'%')
5305 break;
5306 if (i == __x_.size())
5307 break;
5308 ++i;
5309 if (__x_[i] == L'y' || __x_[i] == L'Y')
5310 return time_base::mdy;
5311 break;
5312 }
5313 break;
5314 case L'd':
5315 for (++i; i < __x_.size(); ++i)
5316 if (__x_[i] == L'%')
5317 break;
5318 if (i == __x_.size())
5319 break;
5320 ++i;
5321 if (__x_[i] == L'm')
5322 {
5323 for (++i; i < __x_.size(); ++i)
5324 if (__x_[i] == L'%')
5325 break;
5326 if (i == __x_.size())
5327 break;
5328 ++i;
5329 if (__x_[i] == L'y' || __x_[i] == L'Y')
5330 return time_base::dmy;
5331 break;
5332 }
5333 break;
5334 }
5335 return time_base::no_order;
5336}
5337
5338// time_put
5339
5340__time_put::__time_put(const char* nm)
5341 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5342{
Howard Hinnantd4444702010-08-11 17:04:31 +00005343#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005344 if (__loc_ == 0)
5345 throw runtime_error("time_put_byname"
5346 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005347#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005348}
5349
5350__time_put::__time_put(const string& nm)
5351 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5352{
Howard Hinnantd4444702010-08-11 17:04:31 +00005353#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005354 if (__loc_ == 0)
5355 throw runtime_error("time_put_byname"
5356 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005357#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005358}
5359
5360__time_put::~__time_put()
5361{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005362 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005363 freelocale(__loc_);
5364}
5365
5366void
5367__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5368 char __fmt, char __mod) const
5369{
5370 char fmt[] = {'%', __fmt, __mod, 0};
5371 if (__mod != 0)
5372 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005373 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005374 __ne = __nb + n;
5375}
5376
5377void
5378__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5379 char __fmt, char __mod) const
5380{
5381 char __nar[100];
5382 char* __ne = __nar + 100;
5383 __do_put(__nar, __ne, __tm, __fmt, __mod);
5384 mbstate_t mb = {0};
5385 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005386#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005387 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005388#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005391 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005392 __throw_runtime_error("locale not supported");
5393 __we = __wb + j;
5394}
5395
5396// moneypunct_byname
5397
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005398template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005399static
5400void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005401__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5402 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5403 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005404{
5405 const char sign = static_cast<char>(money_base::sign);
5406 const char space = static_cast<char>(money_base::space);
5407 const char none = static_cast<char>(money_base::none);
5408 const char symbol = static_cast<char>(money_base::symbol);
5409 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005410 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5411
5412 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5413 // function'. "Space between sign and symbol or value" means that
5414 // if the sign is adjacent to the symbol, there's a space between
5415 // them, and otherwise there's a space between the sign and value.
5416 //
5417 // C11's localeconv specifies that the fourth character of an
5418 // international curr_symbol is used to separate the sign and
5419 // value when sep_by_space says to do so. C++ can't represent
5420 // that, so we just use a space. When sep_by_space says to
5421 // separate the symbol and value-or-sign with a space, we rearrange the
5422 // curr_symbol to put its spacing character on the correct side of
5423 // the symbol.
5424 //
5425 // We also need to avoid adding an extra space between the sign
5426 // and value when the currency symbol is suppressed (by not
5427 // setting showbase). We match glibc's strfmon by interpreting
5428 // sep_by_space==1 as "omit the space when the currency symbol is
5429 // absent".
5430 //
5431 // Users who want to get this right should use ICU instead.
5432
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005433 switch (cs_precedes)
5434 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005435 case 0: // value before curr_symbol
5436 if (symbol_contains_sep) {
5437 // Move the separator to before the symbol, to place it
5438 // between the value and symbol.
5439 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5440 __curr_symbol_.end());
5441 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005442 switch (sign_posn)
5443 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005444 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005445 pat.field[0] = sign;
5446 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005447 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005448 pat.field[3] = symbol;
5449 switch (sep_by_space)
5450 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005451 case 0: // No space separates the currency symbol and value.
5452 // This case may have changed between C99 and C11;
5453 // assume the currency symbol matches the intention.
5454 case 2: // Space between sign and currency or value.
5455 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005456 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005457 case 1: // Space between currency-and-sign or currency and value.
5458 if (!symbol_contains_sep) {
5459 // We insert the space into the symbol instead of
5460 // setting pat.field[2]=space so that when
5461 // showbase is not set, the space goes away too.
5462 __curr_symbol_.insert(0, 1, space_char);
5463 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005464 return;
5465 default:
5466 break;
5467 }
5468 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005469 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005470 pat.field[0] = sign;
5471 pat.field[3] = symbol;
5472 switch (sep_by_space)
5473 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005474 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005475 pat.field[1] = value;
5476 pat.field[2] = none;
5477 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005478 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005479 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005480 pat.field[2] = none;
5481 if (!symbol_contains_sep) {
5482 // We insert the space into the symbol instead of
5483 // setting pat.field[2]=space so that when
5484 // showbase is not set, the space goes away too.
5485 __curr_symbol_.insert(0, 1, space_char);
5486 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005487 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005488 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005489 pat.field[1] = space;
5490 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005491 if (symbol_contains_sep) {
5492 // Remove the separator from the symbol, since it
5493 // has already appeared after the sign.
5494 __curr_symbol_.erase(__curr_symbol_.begin());
5495 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005496 return;
5497 default:
5498 break;
5499 }
5500 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005501 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005502 pat.field[0] = value;
5503 pat.field[3] = sign;
5504 switch (sep_by_space)
5505 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005506 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005507 pat.field[1] = none;
5508 pat.field[2] = symbol;
5509 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005510 case 1: // Space between currency-and-sign or currency and value.
5511 if (!symbol_contains_sep) {
5512 // We insert the space into the symbol instead of
5513 // setting pat.field[1]=space so that when
5514 // showbase is not set, the space goes away too.
5515 __curr_symbol_.insert(0, 1, space_char);
5516 }
5517 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005518 pat.field[2] = symbol;
5519 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005520 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005521 pat.field[1] = symbol;
5522 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005523 if (symbol_contains_sep) {
5524 // Remove the separator from the symbol, since it
5525 // should not be removed if showbase is absent.
5526 __curr_symbol_.erase(__curr_symbol_.begin());
5527 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005528 return;
5529 default:
5530 break;
5531 }
5532 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005533 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005534 pat.field[0] = value;
5535 pat.field[3] = symbol;
5536 switch (sep_by_space)
5537 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005538 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005539 pat.field[1] = none;
5540 pat.field[2] = sign;
5541 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005542 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005543 pat.field[1] = space;
5544 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005545 if (symbol_contains_sep) {
5546 // Remove the separator from the symbol, since it
5547 // has already appeared before the sign.
5548 __curr_symbol_.erase(__curr_symbol_.begin());
5549 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005550 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005551 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005552 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005553 pat.field[2] = none;
5554 if (!symbol_contains_sep) {
5555 // We insert the space into the symbol instead of
5556 // setting pat.field[2]=space so that when
5557 // showbase is not set, the space goes away too.
5558 __curr_symbol_.insert(0, 1, space_char);
5559 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005560 return;
5561 default:
5562 break;
5563 }
5564 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005565 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005566 pat.field[0] = value;
5567 pat.field[3] = sign;
5568 switch (sep_by_space)
5569 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005570 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005571 pat.field[1] = none;
5572 pat.field[2] = symbol;
5573 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005574 case 1: // Space between currency-and-sign or currency and value.
5575 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005576 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005577 if (!symbol_contains_sep) {
5578 // We insert the space into the symbol instead of
5579 // setting pat.field[1]=space so that when
5580 // showbase is not set, the space goes away too.
5581 __curr_symbol_.insert(0, 1, space_char);
5582 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005583 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005584 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005585 pat.field[1] = symbol;
5586 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005587 if (symbol_contains_sep) {
5588 // Remove the separator from the symbol, since it
5589 // should not disappear when showbase is absent.
5590 __curr_symbol_.erase(__curr_symbol_.begin());
5591 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005592 return;
5593 default:
5594 break;
5595 }
5596 break;
5597 default:
5598 break;
5599 }
5600 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005601 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005602 switch (sign_posn)
5603 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005604 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005605 pat.field[0] = sign;
5606 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005607 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005608 pat.field[3] = value;
5609 switch (sep_by_space)
5610 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005611 case 0: // No space separates the currency symbol and value.
5612 // This case may have changed between C99 and C11;
5613 // assume the currency symbol matches the intention.
5614 case 2: // Space between sign and currency or value.
5615 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005616 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005617 case 1: // Space between currency-and-sign or currency and value.
5618 if (!symbol_contains_sep) {
5619 // We insert the space into the symbol instead of
5620 // setting pat.field[2]=space so that when
5621 // showbase is not set, the space goes away too.
5622 __curr_symbol_.insert(0, 1, space_char);
5623 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005624 return;
5625 default:
5626 break;
5627 }
5628 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005629 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005630 pat.field[0] = sign;
5631 pat.field[3] = value;
5632 switch (sep_by_space)
5633 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005634 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005635 pat.field[1] = symbol;
5636 pat.field[2] = none;
5637 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005638 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005639 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005640 pat.field[2] = none;
5641 if (!symbol_contains_sep) {
5642 // We insert the space into the symbol instead of
5643 // setting pat.field[2]=space so that when
5644 // showbase is not set, the space goes away too.
5645 __curr_symbol_.push_back(space_char);
5646 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005647 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005648 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005649 pat.field[1] = space;
5650 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005651 if (symbol_contains_sep) {
5652 // Remove the separator from the symbol, since it
5653 // has already appeared after the sign.
5654 __curr_symbol_.pop_back();
5655 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005656 return;
5657 default:
5658 break;
5659 }
5660 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005661 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005662 pat.field[0] = symbol;
5663 pat.field[3] = sign;
5664 switch (sep_by_space)
5665 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005666 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005667 pat.field[1] = none;
5668 pat.field[2] = value;
5669 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005670 case 1: // Space between currency-and-sign or currency and value.
5671 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005672 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005673 if (!symbol_contains_sep) {
5674 // We insert the space into the symbol instead of
5675 // setting pat.field[1]=space so that when
5676 // showbase is not set, the space goes away too.
5677 __curr_symbol_.push_back(space_char);
5678 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005679 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005680 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005681 pat.field[1] = value;
5682 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005683 if (symbol_contains_sep) {
5684 // Remove the separator from the symbol, since it
5685 // will appear before the sign.
5686 __curr_symbol_.pop_back();
5687 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005688 return;
5689 default:
5690 break;
5691 }
5692 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005693 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005694 pat.field[0] = sign;
5695 pat.field[3] = value;
5696 switch (sep_by_space)
5697 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005698 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005699 pat.field[1] = symbol;
5700 pat.field[2] = none;
5701 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005702 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005703 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005704 pat.field[2] = none;
5705 if (!symbol_contains_sep) {
5706 // We insert the space into the symbol instead of
5707 // setting pat.field[2]=space so that when
5708 // showbase is not set, the space goes away too.
5709 __curr_symbol_.push_back(space_char);
5710 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005711 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005712 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005713 pat.field[1] = space;
5714 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005715 if (symbol_contains_sep) {
5716 // Remove the separator from the symbol, since it
5717 // has already appeared after the sign.
5718 __curr_symbol_.pop_back();
5719 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005720 return;
5721 default:
5722 break;
5723 }
5724 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005725 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005726 pat.field[0] = symbol;
5727 pat.field[3] = value;
5728 switch (sep_by_space)
5729 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005730 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005731 pat.field[1] = sign;
5732 pat.field[2] = none;
5733 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005734 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005735 pat.field[1] = sign;
5736 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005737 if (symbol_contains_sep) {
5738 // Remove the separator from the symbol, since it
5739 // should not disappear when showbase is absent.
5740 __curr_symbol_.pop_back();
5741 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005742 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005743 case 2: // Space between sign and currency or value.
5744 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005745 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005746 if (!symbol_contains_sep) {
5747 // We insert the space into the symbol instead of
5748 // setting pat.field[1]=space so that when
5749 // showbase is not set, the space goes away too.
5750 __curr_symbol_.push_back(space_char);
5751 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005752 return;
5753 default:
5754 break;
5755 }
5756 break;
5757 default:
5758 break;
5759 }
5760 break;
5761 default:
5762 break;
5763 }
5764 pat.field[0] = symbol;
5765 pat.field[1] = sign;
5766 pat.field[2] = none;
5767 pat.field[3] = value;
5768}
5769
5770template<>
5771void
5772moneypunct_byname<char, false>::init(const char* nm)
5773{
5774 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005775 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005776#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005777 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005778 throw runtime_error("moneypunct_byname"
5779 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005780#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005781#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005782 lconv* lc = localeconv_l(loc.get());
5783#else
5784 lconv* lc = __localeconv_l(loc.get());
5785#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005786 if (*lc->mon_decimal_point)
5787 __decimal_point_ = *lc->mon_decimal_point;
5788 else
5789 __decimal_point_ = base::do_decimal_point();
5790 if (*lc->mon_thousands_sep)
5791 __thousands_sep_ = *lc->mon_thousands_sep;
5792 else
5793 __thousands_sep_ = base::do_thousands_sep();
5794 __grouping_ = lc->mon_grouping;
5795 __curr_symbol_ = lc->currency_symbol;
5796 if (lc->frac_digits != CHAR_MAX)
5797 __frac_digits_ = lc->frac_digits;
5798 else
5799 __frac_digits_ = base::do_frac_digits();
5800 if (lc->p_sign_posn == 0)
5801 __positive_sign_ = "()";
5802 else
5803 __positive_sign_ = lc->positive_sign;
5804 if (lc->n_sign_posn == 0)
5805 __negative_sign_ = "()";
5806 else
5807 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005808 // Assume the positive and negative formats will want spaces in
5809 // the same places in curr_symbol since there's no way to
5810 // represent anything else.
5811 string_type __dummy_curr_symbol = __curr_symbol_;
5812 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5813 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5814 __init_pat(__neg_format_, __curr_symbol_, false,
5815 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005816}
5817
5818template<>
5819void
5820moneypunct_byname<char, true>::init(const char* nm)
5821{
5822 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005823 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005824#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005825 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005826 throw runtime_error("moneypunct_byname"
5827 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005828#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005829#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005830 lconv* lc = localeconv_l(loc.get());
5831#else
5832 lconv* lc = __localeconv_l(loc.get());
5833#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005834 if (*lc->mon_decimal_point)
5835 __decimal_point_ = *lc->mon_decimal_point;
5836 else
5837 __decimal_point_ = base::do_decimal_point();
5838 if (*lc->mon_thousands_sep)
5839 __thousands_sep_ = *lc->mon_thousands_sep;
5840 else
5841 __thousands_sep_ = base::do_thousands_sep();
5842 __grouping_ = lc->mon_grouping;
5843 __curr_symbol_ = lc->int_curr_symbol;
5844 if (lc->int_frac_digits != CHAR_MAX)
5845 __frac_digits_ = lc->int_frac_digits;
5846 else
5847 __frac_digits_ = base::do_frac_digits();
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005848#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005849 if (lc->p_sign_posn == 0)
5850#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005851 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005852#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005853 __positive_sign_ = "()";
5854 else
5855 __positive_sign_ = lc->positive_sign;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005856#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005857 if(lc->n_sign_posn == 0)
5858#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005859 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005860#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005861 __negative_sign_ = "()";
5862 else
5863 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005864 // Assume the positive and negative formats will want spaces in
5865 // the same places in curr_symbol since there's no way to
5866 // represent anything else.
5867 string_type __dummy_curr_symbol = __curr_symbol_;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005868#ifdef _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005869 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5870 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5871 __init_pat(__neg_format_, __curr_symbol_, true,
5872 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005873#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005874 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5875 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5876 lc->int_p_sign_posn, ' ');
5877 __init_pat(__neg_format_, __curr_symbol_, true,
5878 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5879 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005880#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005881}
5882
5883template<>
5884void
5885moneypunct_byname<wchar_t, false>::init(const char* nm)
5886{
5887 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005888 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005889#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005890 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005891 throw runtime_error("moneypunct_byname"
5892 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005893#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005894#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005895 lconv* lc = localeconv_l(loc.get());
5896#else
5897 lconv* lc = __localeconv_l(loc.get());
5898#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005899 if (*lc->mon_decimal_point)
5900 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5901 else
5902 __decimal_point_ = base::do_decimal_point();
5903 if (*lc->mon_thousands_sep)
5904 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5905 else
5906 __thousands_sep_ = base::do_thousands_sep();
5907 __grouping_ = lc->mon_grouping;
5908 wchar_t wbuf[100];
5909 mbstate_t mb = {0};
5910 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005911#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005912 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005913#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005916 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005917 __throw_runtime_error("locale not supported");
5918 wchar_t* wbe = wbuf + j;
5919 __curr_symbol_.assign(wbuf, wbe);
5920 if (lc->frac_digits != CHAR_MAX)
5921 __frac_digits_ = lc->frac_digits;
5922 else
5923 __frac_digits_ = base::do_frac_digits();
5924 if (lc->p_sign_posn == 0)
5925 __positive_sign_ = L"()";
5926 else
5927 {
5928 mb = mbstate_t();
5929 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005930#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005931 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005932#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005935 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005936 __throw_runtime_error("locale not supported");
5937 wbe = wbuf + j;
5938 __positive_sign_.assign(wbuf, wbe);
5939 }
5940 if (lc->n_sign_posn == 0)
5941 __negative_sign_ = L"()";
5942 else
5943 {
5944 mb = mbstate_t();
5945 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005946#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005947 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005948#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005951 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005952 __throw_runtime_error("locale not supported");
5953 wbe = wbuf + j;
5954 __negative_sign_.assign(wbuf, wbe);
5955 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005956 // Assume the positive and negative formats will want spaces in
5957 // the same places in curr_symbol since there's no way to
5958 // represent anything else.
5959 string_type __dummy_curr_symbol = __curr_symbol_;
5960 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5961 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5962 __init_pat(__neg_format_, __curr_symbol_, false,
5963 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005964}
5965
5966template<>
5967void
5968moneypunct_byname<wchar_t, true>::init(const char* nm)
5969{
5970 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005971 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005972#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005973 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005974 throw runtime_error("moneypunct_byname"
5975 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005976#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005977#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005978 lconv* lc = localeconv_l(loc.get());
5979#else
5980 lconv* lc = __localeconv_l(loc.get());
5981#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005982 if (*lc->mon_decimal_point)
5983 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5984 else
5985 __decimal_point_ = base::do_decimal_point();
5986 if (*lc->mon_thousands_sep)
5987 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5988 else
5989 __thousands_sep_ = base::do_thousands_sep();
5990 __grouping_ = lc->mon_grouping;
5991 wchar_t wbuf[100];
5992 mbstate_t mb = {0};
5993 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005994#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005995 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005996#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005999 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006000 __throw_runtime_error("locale not supported");
6001 wchar_t* wbe = wbuf + j;
6002 __curr_symbol_.assign(wbuf, wbe);
6003 if (lc->int_frac_digits != CHAR_MAX)
6004 __frac_digits_ = lc->int_frac_digits;
6005 else
6006 __frac_digits_ = base::do_frac_digits();
Marshall Clowa22d2ad2013-03-18 17:04:29 +00006007#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006008 if (lc->p_sign_posn == 0)
6009#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006010 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006011#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006012 __positive_sign_ = L"()";
6013 else
6014 {
6015 mb = mbstate_t();
6016 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006017#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006018 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006019#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006022 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006023 __throw_runtime_error("locale not supported");
6024 wbe = wbuf + j;
6025 __positive_sign_.assign(wbuf, wbe);
6026 }
Marshall Clowa22d2ad2013-03-18 17:04:29 +00006027#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006028 if (lc->n_sign_posn == 0)
6029#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006030 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006031#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006032 __negative_sign_ = L"()";
6033 else
6034 {
6035 mb = mbstate_t();
6036 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006037#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006038 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006039#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006042 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006043 __throw_runtime_error("locale not supported");
6044 wbe = wbuf + j;
6045 __negative_sign_.assign(wbuf, wbe);
6046 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006047 // Assume the positive and negative formats will want spaces in
6048 // the same places in curr_symbol since there's no way to
6049 // represent anything else.
6050 string_type __dummy_curr_symbol = __curr_symbol_;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00006051#ifdef _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006052 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6053 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6054 __init_pat(__neg_format_, __curr_symbol_, true,
6055 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006056#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006057 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6058 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6059 lc->int_p_sign_posn, L' ');
6060 __init_pat(__neg_format_, __curr_symbol_, true,
6061 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6062 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006063#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006064}
6065
6066void __do_nothing(void*) {}
6067
6068void __throw_runtime_error(const char* msg)
6069{
Howard Hinnantd4444702010-08-11 17:04:31 +00006070#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006071 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006072#else
6073 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006074#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006075}
6076
6077template class collate<char>;
6078template class collate<wchar_t>;
6079
6080template class num_get<char>;
6081template class num_get<wchar_t>;
6082
Howard Hinnantec3773c2011-12-01 20:21:04 +00006083template struct __num_get<char>;
6084template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006085
6086template class num_put<char>;
6087template class num_put<wchar_t>;
6088
Howard Hinnantec3773c2011-12-01 20:21:04 +00006089template struct __num_put<char>;
6090template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006091
6092template class time_get<char>;
6093template class time_get<wchar_t>;
6094
6095template class time_get_byname<char>;
6096template class time_get_byname<wchar_t>;
6097
6098template class time_put<char>;
6099template class time_put<wchar_t>;
6100
6101template class time_put_byname<char>;
6102template class time_put_byname<wchar_t>;
6103
6104template class moneypunct<char, false>;
6105template class moneypunct<char, true>;
6106template class moneypunct<wchar_t, false>;
6107template class moneypunct<wchar_t, true>;
6108
6109template class moneypunct_byname<char, false>;
6110template class moneypunct_byname<char, true>;
6111template class moneypunct_byname<wchar_t, false>;
6112template class moneypunct_byname<wchar_t, true>;
6113
6114template class money_get<char>;
6115template class money_get<wchar_t>;
6116
6117template class __money_get<char>;
6118template class __money_get<wchar_t>;
6119
6120template class money_put<char>;
6121template class money_put<wchar_t>;
6122
6123template class __money_put<char>;
6124template class __money_put<wchar_t>;
6125
6126template class messages<char>;
6127template class messages<wchar_t>;
6128
6129template class messages_byname<char>;
6130template class messages_byname<wchar_t>;
6131
6132template class codecvt_byname<char, char, mbstate_t>;
6133template class codecvt_byname<wchar_t, char, mbstate_t>;
6134template class codecvt_byname<char16_t, char, mbstate_t>;
6135template class codecvt_byname<char32_t, char, mbstate_t>;
6136
6137template class __vector_base_common<true>;
6138
6139_LIBCPP_END_NAMESPACE_STD