blob: 388660d2d85aee54088a85d801e913d9c2cfed19 [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
10#include "string"
11#include "locale"
Howard Hinnant87d1a8a2010-05-30 21:39:41 +000012#include "codecvt"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000013#include "vector"
14#include "algorithm"
15#include "algorithm"
16#include "typeinfo"
Howard Hinnantd318d492011-06-30 14:21:55 +000017#include "type_traits"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000018#include "clocale"
19#include "cstring"
20#include "cwctype"
21#include "__sso_allocator"
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000022#if _WIN32
23#include <locale.h>
24#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000025#include <langinfo.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000026#endif // _!WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000027#include <stdlib.h>
28
Sean Huntf3907e62011-07-15 05:40:33 +000029#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantd318d492011-06-30 14:21:55 +000030namespace {
Howard Hinnant0949eed2011-06-30 21:18:19 +000031 decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnantd318d492011-06-30 14:21:55 +000032 inline _LIBCPP_INLINE_VISIBILITY
33 mb_cur_max_l(locale_t loc)
34 {
35 return MB_CUR_MAX_L(loc);
36 }
Sean Huntf3907e62011-07-15 05:40:33 +000037}
Howard Hinnantd318d492011-06-30 14:21:55 +000038#endif
Howard Hinnantd318d492011-06-30 14:21:55 +000039
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000040_LIBCPP_BEGIN_NAMESPACE_STD
41
Howard Hinnant8caf4232011-07-31 17:16:32 +000042#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +000043locale_t __cloc() {
44 // In theory this could create a race condition. In practice
45 // the race condition is non-fatal since it will just create
46 // a little resource leak. Better approach would be appreciated.
47#ifdef __APPLE__
48 return 0;
49#else
50 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
51 return result;
52#endif
53}
Howard Hinnant8caf4232011-07-31 17:16:32 +000054#endif // _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +000055
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000056namespace {
57
58struct release
59{
60 void operator()(locale::facet* p) {p->__release_shared();}
61};
62
63template <class T, class A0>
64inline
65T&
66make(A0 a0)
67{
68 static typename aligned_storage<sizeof(T)>::type buf;
69 ::new (&buf) T(a0);
70 return *(T*)&buf;
71}
72
73template <class T, class A0, class A1>
74inline
75T&
76make(A0 a0, A1 a1)
77{
78 static typename aligned_storage<sizeof(T)>::type buf;
79 ::new (&buf) T(a0, a1);
80 return *(T*)&buf;
81}
82
83template <class T, class A0, class A1, class A2>
84inline
85T&
86make(A0 a0, A1 a1, A2 a2)
87{
88 static typename aligned_storage<sizeof(T)>::type buf;
89 ::new (&buf) T(a0, a1, a2);
90 return *(T*)&buf;
91}
92
93}
94
95class _LIBCPP_HIDDEN locale::__imp
96 : public facet
97{
98 enum {N = 28};
99 string name_;
100 vector<facet*, __sso_allocator<facet*, N> > facets_;
101public:
102 explicit __imp(size_t refs = 0);
103 explicit __imp(const string& name, size_t refs = 0);
104 __imp(const __imp&);
105 __imp(const __imp&, const string&, locale::category c);
106 __imp(const __imp& other, const __imp& one, locale::category c);
107 __imp(const __imp&, facet* f, long id);
108 ~__imp();
109
110 const string& name() const {return name_;}
111 bool has_facet(long id) const {return id < facets_.size() && facets_[id];}
112 const locale::facet* use_facet(long id) const;
113
114 static const locale& make_classic();
115 static locale& make_global();
116private:
117 void install(facet* f, long id);
118 template <class F> void install(F* f) {install(f, f->id.__get());}
119 template <class F> void install_from(const __imp& other);
120};
121
122locale::__imp::__imp(size_t refs)
123 : facet(refs),
124 name_("C"),
125 facets_(N)
126{
127 facets_.clear();
Howard Hinnant0949eed2011-06-30 21:18:19 +0000128 install(&make<_VSTD::collate<char> >(1));
129 install(&make<_VSTD::collate<wchar_t> >(1));
130 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1));
131 install(&make<_VSTD::ctype<wchar_t> >(1));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000132 install(&make<codecvt<char, char, mbstate_t> >(1));
133 install(&make<codecvt<wchar_t, char, mbstate_t> >(1));
134 install(&make<codecvt<char16_t, char, mbstate_t> >(1));
135 install(&make<codecvt<char32_t, char, mbstate_t> >(1));
136 install(&make<numpunct<char> >(1));
137 install(&make<numpunct<wchar_t> >(1));
138 install(&make<num_get<char> >(1));
139 install(&make<num_get<wchar_t> >(1));
140 install(&make<num_put<char> >(1));
141 install(&make<num_put<wchar_t> >(1));
142 install(&make<moneypunct<char, false> >(1));
143 install(&make<moneypunct<char, true> >(1));
144 install(&make<moneypunct<wchar_t, false> >(1));
145 install(&make<moneypunct<wchar_t, true> >(1));
146 install(&make<money_get<char> >(1));
147 install(&make<money_get<wchar_t> >(1));
148 install(&make<money_put<char> >(1));
149 install(&make<money_put<wchar_t> >(1));
150 install(&make<time_get<char> >(1));
151 install(&make<time_get<wchar_t> >(1));
152 install(&make<time_put<char> >(1));
153 install(&make<time_put<wchar_t> >(1));
Howard Hinnant0949eed2011-06-30 21:18:19 +0000154 install(&make<_VSTD::messages<char> >(1));
155 install(&make<_VSTD::messages<wchar_t> >(1));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000156}
157
158locale::__imp::__imp(const string& name, size_t refs)
159 : facet(refs),
160 name_(name),
161 facets_(N)
162{
Howard Hinnantd4444702010-08-11 17:04:31 +0000163#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000164 try
165 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000166#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000167 facets_ = locale::classic().__locale_->facets_;
168 for (unsigned i = 0; i < facets_.size(); ++i)
169 if (facets_[i])
170 facets_[i]->__add_shared();
171 install(new collate_byname<char>(name_));
172 install(new collate_byname<wchar_t>(name_));
173 install(new ctype_byname<char>(name_));
174 install(new ctype_byname<wchar_t>(name_));
175 install(new codecvt_byname<char, char, mbstate_t>(name_));
176 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
177 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
178 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
179 install(new numpunct_byname<char>(name_));
180 install(new numpunct_byname<wchar_t>(name_));
181 install(new moneypunct_byname<char, false>(name_));
182 install(new moneypunct_byname<char, true>(name_));
183 install(new moneypunct_byname<wchar_t, false>(name_));
184 install(new moneypunct_byname<wchar_t, true>(name_));
185 install(new time_get_byname<char>(name_));
186 install(new time_get_byname<wchar_t>(name_));
187 install(new time_put_byname<char>(name_));
188 install(new time_put_byname<wchar_t>(name_));
189 install(new messages_byname<char>(name_));
190 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000191#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192 }
193 catch (...)
194 {
195 for (unsigned i = 0; i < facets_.size(); ++i)
196 if (facets_[i])
197 facets_[i]->__release_shared();
198 throw;
199 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000200#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000201}
202
203locale::__imp::__imp(const __imp& other)
204 : name_(other.name_),
205 facets_(max<size_t>(N, other.facets_.size()))
206{
207 facets_ = other.facets_;
208 for (unsigned i = 0; i < facets_.size(); ++i)
209 if (facets_[i])
210 facets_[i]->__add_shared();
211}
212
213locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
214 : name_("*"),
215 facets_(N)
216{
217 facets_ = other.facets_;
218 for (unsigned i = 0; i < facets_.size(); ++i)
219 if (facets_[i])
220 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000221#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000222 try
223 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000224#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000225 if (c & locale::collate)
226 {
227 install(new collate_byname<char>(name));
228 install(new collate_byname<wchar_t>(name));
229 }
230 if (c & locale::ctype)
231 {
232 install(new ctype_byname<char>(name));
233 install(new ctype_byname<wchar_t>(name));
234 install(new codecvt_byname<char, char, mbstate_t>(name));
235 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
236 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
237 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
238 }
239 if (c & locale::monetary)
240 {
241 install(new moneypunct_byname<char, false>(name));
242 install(new moneypunct_byname<char, true>(name));
243 install(new moneypunct_byname<wchar_t, false>(name));
244 install(new moneypunct_byname<wchar_t, true>(name));
245 }
246 if (c & locale::numeric)
247 {
248 install(new numpunct_byname<char>(name));
249 install(new numpunct_byname<wchar_t>(name));
250 }
251 if (c & locale::time)
252 {
253 install(new time_get_byname<char>(name));
254 install(new time_get_byname<wchar_t>(name));
255 install(new time_put_byname<char>(name));
256 install(new time_put_byname<wchar_t>(name));
257 }
258 if (c & locale::messages)
259 {
260 install(new messages_byname<char>(name));
261 install(new messages_byname<wchar_t>(name));
262 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000263#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000264 }
265 catch (...)
266 {
267 for (unsigned i = 0; i < facets_.size(); ++i)
268 if (facets_[i])
269 facets_[i]->__release_shared();
270 throw;
271 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000272#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000273}
274
275template<class F>
276inline
277void
278locale::__imp::install_from(const locale::__imp& one)
279{
280 long id = F::id.__get();
281 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
282}
283
284locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
285 : name_("*"),
286 facets_(N)
287{
288 facets_ = other.facets_;
289 for (unsigned i = 0; i < facets_.size(); ++i)
290 if (facets_[i])
291 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000292#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000293 try
294 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000295#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000296 if (c & locale::collate)
297 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000298 install_from<_VSTD::collate<char> >(one);
299 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000300 }
301 if (c & locale::ctype)
302 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000303 install_from<_VSTD::ctype<char> >(one);
304 install_from<_VSTD::ctype<wchar_t> >(one);
305 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
306 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
307 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
308 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000309 }
310 if (c & locale::monetary)
311 {
312 install_from<moneypunct<char, false> >(one);
313 install_from<moneypunct<char, true> >(one);
314 install_from<moneypunct<wchar_t, false> >(one);
315 install_from<moneypunct<wchar_t, true> >(one);
316 install_from<money_get<char> >(one);
317 install_from<money_get<wchar_t> >(one);
318 install_from<money_put<char> >(one);
319 install_from<money_put<wchar_t> >(one);
320 }
321 if (c & locale::numeric)
322 {
323 install_from<numpunct<char> >(one);
324 install_from<numpunct<wchar_t> >(one);
325 install_from<num_get<char> >(one);
326 install_from<num_get<wchar_t> >(one);
327 install_from<num_put<char> >(one);
328 install_from<num_put<wchar_t> >(one);
329 }
330 if (c & locale::time)
331 {
332 install_from<time_get<char> >(one);
333 install_from<time_get<wchar_t> >(one);
334 install_from<time_put<char> >(one);
335 install_from<time_put<wchar_t> >(one);
336 }
337 if (c & locale::messages)
338 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000339 install_from<_VSTD::messages<char> >(one);
340 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000341 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000342#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000343 }
344 catch (...)
345 {
346 for (unsigned i = 0; i < facets_.size(); ++i)
347 if (facets_[i])
348 facets_[i]->__release_shared();
349 throw;
350 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000351#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000352}
353
354locale::__imp::__imp(const __imp& other, facet* f, long id)
355 : name_("*"),
356 facets_(max<size_t>(N, other.facets_.size()+1))
357{
358 f->__add_shared();
359 unique_ptr<facet, release> hold(f);
360 facets_ = other.facets_;
361 for (unsigned i = 0; i < other.facets_.size(); ++i)
362 if (facets_[i])
363 facets_[i]->__add_shared();
364 install(hold.get(), id);
365}
366
367locale::__imp::~__imp()
368{
369 for (unsigned i = 0; i < facets_.size(); ++i)
370 if (facets_[i])
371 facets_[i]->__release_shared();
372}
373
374void
375locale::__imp::install(facet* f, long id)
376{
377 f->__add_shared();
378 unique_ptr<facet, release> hold(f);
379 if (id >= facets_.size())
380 facets_.resize(id+1);
381 if (facets_[id])
382 facets_[id]->__release_shared();
383 facets_[id] = hold.release();
384}
385
386const locale::facet*
387locale::__imp::use_facet(long id) const
388{
Howard Hinnantd4444702010-08-11 17:04:31 +0000389#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000390 if (!has_facet(id))
391 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000392#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000393 return facets_[id];
394}
395
396// locale
397
398const locale&
399locale::__imp::make_classic()
400{
401 // only one thread can get in here and it only gets in once
402 static aligned_storage<sizeof(locale)>::type buf;
403 locale* c = (locale*)&buf;
404 c->__locale_ = &make<__imp>(1);
405 return *c;
406}
407
408const locale&
409locale::classic()
410{
411 static const locale& c = __imp::make_classic();
412 return c;
413}
414
415locale&
416locale::__imp::make_global()
417{
418 // only one thread can get in here and it only gets in once
419 static aligned_storage<sizeof(locale)>::type buf;
420 locale* g = (locale*)&buf;
421 ::new (&buf) locale(locale::classic());
422 return *(locale*)&buf;
423}
424
425locale&
426locale::__global()
427{
428 static locale& g = __imp::make_global();
429 return g;
430}
431
Howard Hinnantc9834542011-05-31 15:34:58 +0000432locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000433 : __locale_(__global().__locale_)
434{
435 __locale_->__add_shared();
436}
437
Howard Hinnantc9834542011-05-31 15:34:58 +0000438locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000439 : __locale_(l.__locale_)
440{
441 __locale_->__add_shared();
442}
443
Howard Hinnantc9834542011-05-31 15:34:58 +0000444locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000445{
446 __locale_->__release_shared();
447}
448
449const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000450locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000451{
452 other.__locale_->__add_shared();
453 __locale_->__release_shared();
454 __locale_ = other.__locale_;
455 return *this;
456}
457
458locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000459#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000460 : __locale_(name ? new __imp(name)
461 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000462#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000463 : __locale_(new __imp(name))
464#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000465{
466 __locale_->__add_shared();
467}
468
469locale::locale(const string& name)
470 : __locale_(new __imp(name))
471{
472 __locale_->__add_shared();
473}
474
475locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000476#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000477 : __locale_(name ? new __imp(*other.__locale_, name, c)
478 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000479#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000480 : __locale_(new __imp(*other.__locale_, name, c))
481#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000482{
483 __locale_->__add_shared();
484}
485
486locale::locale(const locale& other, const string& name, category c)
487 : __locale_(new __imp(*other.__locale_, name, c))
488{
489 __locale_->__add_shared();
490}
491
492locale::locale(const locale& other, const locale& one, category c)
493 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
494{
495 __locale_->__add_shared();
496}
497
498string
499locale::name() const
500{
501 return __locale_->name();
502}
503
504void
505locale::__install_ctor(const locale& other, facet* f, long id)
506{
507 if (f)
508 __locale_ = new __imp(*other.__locale_, f, id);
509 else
510 __locale_ = other.__locale_;
511 __locale_->__add_shared();
512}
513
514locale
515locale::global(const locale& loc)
516{
517 locale& g = __global();
518 locale r = g;
519 g = loc;
520 if (g.name() != "*")
521 setlocale(LC_ALL, g.name().c_str());
522 return r;
523}
524
525bool
526locale::has_facet(id& x) const
527{
528 return __locale_->has_facet(x.__get());
529}
530
531const locale::facet*
532locale::use_facet(id& x) const
533{
534 return __locale_->use_facet(x.__get());
535}
536
537bool
538locale::operator==(const locale& y) const
539{
540 return (__locale_ == y.__locale_)
541 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
542}
543
544// locale::facet
545
546locale::facet::~facet()
547{
548}
549
550void
Howard Hinnant1694d232011-05-28 14:41:13 +0000551locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000552{
553 delete this;
554}
555
556// locale::id
557
558int32_t locale::id::__next_id = 0;
559
560namespace
561{
562
563class __fake_bind
564{
565 locale::id* id_;
566 void (locale::id::* pmf_)();
567public:
568 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
569 : id_(id), pmf_(pmf) {}
570
571 void operator()() const
572 {
573 (id_->*pmf_)();
574 }
575};
576
577}
578
579long
580locale::id::__get()
581{
582 call_once(__flag_, __fake_bind(&locale::id::__init, this));
583 return __id_ - 1;
584}
585
586void
587locale::id::__init()
588{
Howard Hinnantadff4892010-05-24 17:49:41 +0000589 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000590}
591
592// template <> class collate_byname<char>
593
594collate_byname<char>::collate_byname(const char* n, size_t refs)
595 : collate<char>(refs),
596 __l(newlocale(LC_ALL_MASK, n, 0))
597{
Howard Hinnantd4444702010-08-11 17:04:31 +0000598#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000599 if (__l == 0)
600 throw runtime_error("collate_byname<char>::collate_byname"
601 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000602#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000603}
604
605collate_byname<char>::collate_byname(const string& name, size_t refs)
606 : collate<char>(refs),
607 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
608{
Howard Hinnantd4444702010-08-11 17:04:31 +0000609#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000610 if (__l == 0)
611 throw runtime_error("collate_byname<char>::collate_byname"
612 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000613#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000614}
615
616collate_byname<char>::~collate_byname()
617{
618 freelocale(__l);
619}
620
621int
622collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
623 const char_type* __lo2, const char_type* __hi2) const
624{
625 string_type lhs(__lo1, __hi1);
626 string_type rhs(__lo2, __hi2);
627 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
628 if (r < 0)
629 return -1;
630 if (r > 0)
631 return 1;
632 return r;
633}
634
635collate_byname<char>::string_type
636collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
637{
638 const string_type in(lo, hi);
639 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
640 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
641 return out;
642}
643
644// template <> class collate_byname<wchar_t>
645
646collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
647 : collate<wchar_t>(refs),
648 __l(newlocale(LC_ALL_MASK, n, 0))
649{
Howard Hinnantd4444702010-08-11 17:04:31 +0000650#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000651 if (__l == 0)
652 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
653 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000654#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000655}
656
657collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
658 : collate<wchar_t>(refs),
659 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
660{
Howard Hinnantd4444702010-08-11 17:04:31 +0000661#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000662 if (__l == 0)
663 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
664 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000665#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000666}
667
668collate_byname<wchar_t>::~collate_byname()
669{
670 freelocale(__l);
671}
672
673int
674collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
675 const char_type* __lo2, const char_type* __hi2) const
676{
677 string_type lhs(__lo1, __hi1);
678 string_type rhs(__lo2, __hi2);
679 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
680 if (r < 0)
681 return -1;
682 if (r > 0)
683 return 1;
684 return r;
685}
686
687collate_byname<wchar_t>::string_type
688collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
689{
690 const string_type in(lo, hi);
691 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
692 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
693 return out;
694}
695
696// template <> class ctype<wchar_t>;
697
698locale::id ctype<wchar_t>::id;
699
700ctype<wchar_t>::~ctype()
701{
702}
703
704bool
705ctype<wchar_t>::do_is(mask m, char_type c) const
706{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000707 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000708}
709
710const wchar_t*
711ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
712{
713 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000714 *vec = static_cast<mask>(isascii(*low) ?
715 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000716 return low;
717}
718
719const wchar_t*
720ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
721{
722 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000723 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000724 break;
725 return low;
726}
727
728const wchar_t*
729ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
730{
731 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000732 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000733 break;
734 return low;
735}
736
737wchar_t
738ctype<wchar_t>::do_toupper(char_type c) const
739{
David Chisnallc512df12011-09-21 08:39:44 +0000740#if !(defined(_LIBCPP_STABLE_APPLE_ABI) || defined(__FreeBSD__))
Sean Hunt62a6ac32011-07-09 00:56:23 +0000741 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000742#else
743 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
744#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000745}
746
747const wchar_t*
748ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
749{
750 for (; low != high; ++low)
David Chisnallc512df12011-09-21 08:39:44 +0000751#if !(defined(_LIBCPP_STABLE_APPLE_ABI) || defined(__FreeBSD__))
Sean Hunt62a6ac32011-07-09 00:56:23 +0000752 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
753 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000754#else
755 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
756#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000757 return low;
758}
759
760wchar_t
761ctype<wchar_t>::do_tolower(char_type c) const
762{
Sean Hunte59f7242011-07-09 01:09:31 +0000763#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000764 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000765#else
766 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
767#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000768}
769
770const wchar_t*
771ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
772{
773 for (; low != high; ++low)
Sean Hunte59f7242011-07-09 01:09:31 +0000774#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000775 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
776 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000777#else
778 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
779#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000780 return low;
781}
782
783wchar_t
784ctype<wchar_t>::do_widen(char c) const
785{
786 return c;
787}
788
789const char*
790ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
791{
792 for (; low != high; ++low, ++dest)
793 *dest = *low;
794 return low;
795}
796
797char
798ctype<wchar_t>::do_narrow(char_type c, char dfault) const
799{
800 if (isascii(c))
801 return static_cast<char>(c);
802 return dfault;
803}
804
805const wchar_t*
806ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
807{
808 for (; low != high; ++low, ++dest)
809 if (isascii(*low))
810 *dest = *low;
811 else
812 *dest = dfault;
813 return low;
814}
815
816// template <> class ctype<char>;
817
818locale::id ctype<char>::id;
819
820ctype<char>::ctype(const mask* tab, bool del, size_t refs)
821 : locale::facet(refs),
822 __tab_(tab),
823 __del_(del)
824{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000825 if (__tab_ == 0)
826 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000827}
828
829ctype<char>::~ctype()
830{
831 if (__tab_ && __del_)
832 delete [] __tab_;
833}
834
835char
836ctype<char>::do_toupper(char_type c) const
837{
Sean Hunte59f7242011-07-09 01:09:31 +0000838#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000839 return isascii(c) ? __classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000840#else
841 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
842#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000843}
844
845const char*
846ctype<char>::do_toupper(char_type* low, const char_type* high) const
847{
848 for (; low != high; ++low)
Sean Hunte59f7242011-07-09 01:09:31 +0000849#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000850 *low = isascii(*low) ? __classic_upper_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000851#else
Howard Hinnant66f26412011-07-09 19:47:01 +0000852 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000853#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000854 return low;
855}
856
857char
858ctype<char>::do_tolower(char_type c) const
859{
Sean Hunte59f7242011-07-09 01:09:31 +0000860#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000861 return isascii(c) ? __classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000862#else
863 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
864#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000865}
866
867const char*
868ctype<char>::do_tolower(char_type* low, const char_type* high) const
869{
870 for (; low != high; ++low)
Sean Hunte59f7242011-07-09 01:09:31 +0000871#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000872 *low = isascii(*low) ? __classic_lower_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000873#else
Howard Hinnant66f26412011-07-09 19:47:01 +0000874 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000875#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000876 return low;
877}
878
879char
880ctype<char>::do_widen(char c) const
881{
882 return c;
883}
884
885const char*
886ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
887{
888 for (; low != high; ++low, ++dest)
889 *dest = *low;
890 return low;
891}
892
893char
894ctype<char>::do_narrow(char_type c, char dfault) const
895{
896 if (isascii(c))
897 return static_cast<char>(c);
898 return dfault;
899}
900
901const char*
902ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
903{
904 for (; low != high; ++low, ++dest)
905 if (isascii(*low))
906 *dest = *low;
907 else
908 *dest = dfault;
909 return low;
910}
911
912const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000913ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000914{
David Chisnallc512df12011-09-21 08:39:44 +0000915#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000916 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000917#elif defined(__GLIBC__)
918 return __cloc()->__ctype_b;
David Chisnallc512df12011-09-21 08:39:44 +0000919// This is assumed to be safe, which is a nonsense assumption because we're
920// going to end up dereferencing it later...
Sean Hunt62a6ac32011-07-09 00:56:23 +0000921#else
922 return NULL;
923#endif
924}
925
Howard Hinnant66f26412011-07-09 19:47:01 +0000926#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000927const int*
928ctype<char>::__classic_lower_table() _NOEXCEPT
929{
David Chisnallc512df12011-09-21 08:39:44 +0000930#if defined(__APPLE__) || defined(__FreeBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000931 return _DefaultRuneLocale.__maplower;
932#elif defined(__GLIBC__)
933 return __cloc()->__ctype_tolower;
934#else
935 return NULL;
936#endif
937}
938
939const int*
940ctype<char>::__classic_upper_table() _NOEXCEPT
941{
David Chisnallc512df12011-09-21 08:39:44 +0000942#if defined(__APPLE__) || defined(__FreeBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000943 return _DefaultRuneLocale.__mapupper;
944#elif defined(__GLIBC__)
945 return __cloc()->__ctype_toupper;
Michael J. Spencer626916f2010-12-10 19:47:54 +0000946#else
947 return NULL;
948#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000949}
Howard Hinnant8caf4232011-07-31 17:16:32 +0000950#endif // _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000951
952// template <> class ctype_byname<char>
953
954ctype_byname<char>::ctype_byname(const char* name, size_t refs)
955 : ctype<char>(0, false, refs),
956 __l(newlocale(LC_ALL_MASK, name, 0))
957{
Howard Hinnantd4444702010-08-11 17:04:31 +0000958#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000959 if (__l == 0)
960 throw runtime_error("ctype_byname<char>::ctype_byname"
961 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000962#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000963}
964
965ctype_byname<char>::ctype_byname(const string& name, size_t refs)
966 : ctype<char>(0, false, refs),
967 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
968{
Howard Hinnantd4444702010-08-11 17:04:31 +0000969#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000970 if (__l == 0)
971 throw runtime_error("ctype_byname<char>::ctype_byname"
972 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000973#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000974}
975
976ctype_byname<char>::~ctype_byname()
977{
978 freelocale(__l);
979}
980
981char
982ctype_byname<char>::do_toupper(char_type c) const
983{
984 return toupper_l(c, __l);
985}
986
987const char*
988ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
989{
990 for (; low != high; ++low)
991 *low = toupper_l(*low, __l);
992 return low;
993}
994
995char
996ctype_byname<char>::do_tolower(char_type c) const
997{
998 return tolower_l(c, __l);
999}
1000
1001const char*
1002ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1003{
1004 for (; low != high; ++low)
1005 *low = tolower_l(*low, __l);
1006 return low;
1007}
1008
1009// template <> class ctype_byname<wchar_t>
1010
1011ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1012 : ctype<wchar_t>(refs),
1013 __l(newlocale(LC_ALL_MASK, name, 0))
1014{
Howard Hinnantd4444702010-08-11 17:04:31 +00001015#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001016 if (__l == 0)
1017 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1018 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001019#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001020}
1021
1022ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1023 : ctype<wchar_t>(refs),
1024 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1025{
Howard Hinnantd4444702010-08-11 17:04:31 +00001026#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001027 if (__l == 0)
1028 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1029 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001030#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001031}
1032
1033ctype_byname<wchar_t>::~ctype_byname()
1034{
1035 freelocale(__l);
1036}
1037
1038bool
1039ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1040{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001041#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001042 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001043#else
David Chisnallc512df12011-09-21 08:39:44 +00001044 // FIXME: This is broken for things that test more than one flag.
Sean Hunt6f0342c2011-07-09 03:40:04 +00001045 if (m & space && !iswspace_l(c, __l)) return false;
1046 if (m & print && !iswprint_l(c, __l)) return false;
1047 if (m & cntrl && !iswcntrl_l(c, __l)) return false;
1048 if (m & upper && !iswupper_l(c, __l)) return false;
1049 if (m & lower && !iswlower_l(c, __l)) return false;
1050 if (m & alpha && !iswalpha_l(c, __l)) return false;
1051 if (m & digit && !iswdigit_l(c, __l)) return false;
1052 if (m & punct && !iswpunct_l(c, __l)) return false;
1053 if (m & xdigit && !iswxdigit_l(c, __l)) return false;
1054 if (m & blank && !iswblank_l(c, __l)) return false;
1055 return true;
1056#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001057}
1058
1059const wchar_t*
1060ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1061{
1062 for (; low != high; ++low, ++vec)
1063 {
1064 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001065 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001066 else
1067 {
1068 *vec = 0;
1069 if (iswspace_l(*low, __l))
1070 *vec |= space;
1071 if (iswprint_l(*low, __l))
1072 *vec |= print;
1073 if (iswcntrl_l(*low, __l))
1074 *vec |= cntrl;
1075 if (iswupper_l(*low, __l))
1076 *vec |= upper;
1077 if (iswlower_l(*low, __l))
1078 *vec |= lower;
1079 if (iswalpha_l(*low, __l))
1080 *vec |= alpha;
1081 if (iswdigit_l(*low, __l))
1082 *vec |= digit;
1083 if (iswpunct_l(*low, __l))
1084 *vec |= punct;
1085 if (iswxdigit_l(*low, __l))
1086 *vec |= xdigit;
1087 }
1088 }
1089 return low;
1090}
1091
1092const wchar_t*
1093ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1094{
1095 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001096 {
1097#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001098 if (iswctype_l(*low, m, __l))
1099 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001100#else
1101 if (m & space && !iswspace_l(*low, __l)) continue;
1102 if (m & print && !iswprint_l(*low, __l)) continue;
1103 if (m & cntrl && !iswcntrl_l(*low, __l)) continue;
1104 if (m & upper && !iswupper_l(*low, __l)) continue;
1105 if (m & lower && !iswlower_l(*low, __l)) continue;
1106 if (m & alpha && !iswalpha_l(*low, __l)) continue;
1107 if (m & digit && !iswdigit_l(*low, __l)) continue;
1108 if (m & punct && !iswpunct_l(*low, __l)) continue;
1109 if (m & xdigit && !iswxdigit_l(*low, __l)) continue;
1110 if (m & blank && !iswblank_l(*low, __l)) continue;
1111 break;
1112#endif
1113 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001114 return low;
1115}
1116
1117const wchar_t*
1118ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1119{
1120 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001121 {
1122#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001123 if (!iswctype_l(*low, m, __l))
1124 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001125#else
1126 if (m & space && iswspace_l(*low, __l)) continue;
1127 if (m & print && iswprint_l(*low, __l)) continue;
1128 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1129 if (m & upper && iswupper_l(*low, __l)) continue;
1130 if (m & lower && iswlower_l(*low, __l)) continue;
1131 if (m & alpha && iswalpha_l(*low, __l)) continue;
1132 if (m & digit && iswdigit_l(*low, __l)) continue;
1133 if (m & punct && iswpunct_l(*low, __l)) continue;
1134 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1135 if (m & blank && iswblank_l(*low, __l)) continue;
1136 break;
1137#endif
1138 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001139 return low;
1140}
1141
1142wchar_t
1143ctype_byname<wchar_t>::do_toupper(char_type c) const
1144{
1145 return towupper_l(c, __l);
1146}
1147
1148const wchar_t*
1149ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1150{
1151 for (; low != high; ++low)
1152 *low = towupper_l(*low, __l);
1153 return low;
1154}
1155
1156wchar_t
1157ctype_byname<wchar_t>::do_tolower(char_type c) const
1158{
1159 return towlower_l(c, __l);
1160}
1161
1162const wchar_t*
1163ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1164{
1165 for (; low != high; ++low)
1166 *low = towlower_l(*low, __l);
1167 return low;
1168}
1169
1170wchar_t
1171ctype_byname<wchar_t>::do_widen(char c) const
1172{
Sean Huntf3907e62011-07-15 05:40:33 +00001173#ifdef _LIBCPP_STABLE_APPLE_ABI
1174 return btowc_l(c, __l);
1175#else
1176 return __btowc_l(c, __l);
1177#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001178}
1179
1180const char*
1181ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1182{
1183 for (; low != high; ++low, ++dest)
Sean Huntf3907e62011-07-15 05:40:33 +00001184#ifdef _LIBCPP_STABLE_APPLE_ABI
1185 *dest = btowc_l(*low, __l);
1186#else
1187 *dest = __btowc_l(*low, __l);
1188#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001189 return low;
1190}
1191
1192char
1193ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1194{
Sean Huntf3907e62011-07-15 05:40:33 +00001195#ifdef _LIBCPP_STABLE_APPLE_ABI
1196 int r = wctob_l(c, __l);
1197#else
1198 int r = __wctob_l(c, __l);
1199#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200 return r != WEOF ? static_cast<char>(r) : dfault;
1201}
1202
1203const wchar_t*
1204ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1205{
1206 for (; low != high; ++low, ++dest)
1207 {
Sean Huntf3907e62011-07-15 05:40:33 +00001208#ifdef _LIBCPP_STABLE_APPLE_ABI
1209 int r = wctob_l(*low, __l);
1210#else
1211 int r = __wctob_l(*low, __l);
1212#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001213 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1214 }
1215 return low;
1216}
1217
1218// template <> class codecvt<char, char, mbstate_t>
1219
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001220locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001221
1222codecvt<char, char, mbstate_t>::~codecvt()
1223{
1224}
1225
1226codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001227codecvt<char, char, mbstate_t>::do_out(state_type&,
1228 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001229 extern_type* to, extern_type*, extern_type*& to_nxt) const
1230{
1231 frm_nxt = frm;
1232 to_nxt = to;
1233 return noconv;
1234}
1235
1236codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001237codecvt<char, char, mbstate_t>::do_in(state_type&,
1238 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001239 intern_type* to, intern_type*, intern_type*& to_nxt) const
1240{
1241 frm_nxt = frm;
1242 to_nxt = to;
1243 return noconv;
1244}
1245
1246codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001247codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001248 extern_type* to, extern_type*, extern_type*& to_nxt) const
1249{
1250 to_nxt = to;
1251 return noconv;
1252}
1253
1254int
Howard Hinnantc9834542011-05-31 15:34:58 +00001255codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001256{
1257 return 1;
1258}
1259
1260bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001261codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001262{
1263 return true;
1264}
1265
1266int
1267codecvt<char, char, mbstate_t>::do_length(state_type&,
1268 const extern_type* frm, const extern_type* end, size_t mx) const
1269{
1270 return static_cast<int>(min<size_t>(mx, end-frm));
1271}
1272
1273int
Howard Hinnantc9834542011-05-31 15:34:58 +00001274codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001275{
1276 return 1;
1277}
1278
1279// template <> class codecvt<wchar_t, char, mbstate_t>
1280
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001281locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001282
1283codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1284 : locale::facet(refs),
1285 __l(0)
1286{
1287}
1288
1289codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1290 : locale::facet(refs),
1291 __l(newlocale(LC_ALL_MASK, nm, 0))
1292{
Howard Hinnantd4444702010-08-11 17:04:31 +00001293#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001294 if (__l == 0)
1295 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1296 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001297#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001298}
1299
1300codecvt<wchar_t, char, mbstate_t>::~codecvt()
1301{
1302 if (__l != 0)
1303 freelocale(__l);
1304}
1305
1306codecvt<wchar_t, char, mbstate_t>::result
1307codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001308 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001309 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1310{
1311 // look for first internal null in frm
1312 const intern_type* fend = frm;
1313 for (; fend != frm_end; ++fend)
1314 if (*fend == 0)
1315 break;
1316 // loop over all null-terminated sequences in frm
1317 to_nxt = to;
1318 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1319 {
1320 // save state in case needed to reover to_nxt on error
1321 mbstate_t save_state = st;
Sean Huntf3907e62011-07-15 05:40:33 +00001322#ifdef _LIBCPP_STABLE_APPLE_ABI
1323 size_t n = wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1324#else
1325 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1326#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001327 if (n == size_t(-1))
1328 {
1329 // need to recover to_nxt
1330 for (to_nxt = to; frm != frm_nxt; ++frm)
1331 {
Sean Huntf3907e62011-07-15 05:40:33 +00001332#ifdef _LIBCPP_STABLE_APPLE_ABI
1333 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1334#else
1335 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1336#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001337 if (n == size_t(-1))
1338 break;
1339 to_nxt += n;
1340 }
1341 frm_nxt = frm;
1342 return error;
1343 }
1344 if (n == 0)
1345 return partial;
1346 to_nxt += n;
1347 if (to_nxt == to_end)
1348 break;
1349 if (fend != frm_end) // set up next null terminated sequence
1350 {
1351 // Try to write the terminating null
1352 extern_type tmp[MB_LEN_MAX];
Sean Huntf3907e62011-07-15 05:40:33 +00001353#ifdef _LIBCPP_STABLE_APPLE_ABI
1354 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1355#else
1356 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1357#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001358 if (n == size_t(-1)) // on error
1359 return error;
1360 if (n > to_end-to_nxt) // is there room?
1361 return partial;
1362 for (extern_type* p = tmp; n; --n) // write it
1363 *to_nxt++ = *p++;
1364 ++frm_nxt;
1365 // look for next null in frm
1366 for (fend = frm_nxt; fend != frm_end; ++fend)
1367 if (*fend == 0)
1368 break;
1369 }
1370 }
1371 return frm_nxt == frm_end ? ok : partial;
1372}
1373
1374codecvt<wchar_t, char, mbstate_t>::result
1375codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001376 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001377 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1378{
1379 // look for first internal null in frm
1380 const extern_type* fend = frm;
1381 for (; fend != frm_end; ++fend)
1382 if (*fend == 0)
1383 break;
1384 // loop over all null-terminated sequences in frm
1385 to_nxt = to;
1386 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1387 {
1388 // save state in case needed to reover to_nxt on error
1389 mbstate_t save_state = st;
Sean Huntf3907e62011-07-15 05:40:33 +00001390#ifdef _LIBCPP_STABLE_APPLE_ABI
1391 size_t n = mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1392#else
1393 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1394#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001395 if (n == size_t(-1))
1396 {
1397 // need to recover to_nxt
1398 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1399 {
Sean Huntf3907e62011-07-15 05:40:33 +00001400#ifdef _LIBCPP_STABLE_APPLE_ABI
1401 n = mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1402#else
1403 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1404#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001405 switch (n)
1406 {
1407 case 0:
1408 ++frm;
1409 break;
1410 case -1:
1411 frm_nxt = frm;
1412 return error;
1413 case -2:
1414 frm_nxt = frm;
1415 return partial;
1416 default:
1417 frm += n;
1418 break;
1419 }
1420 }
1421 frm_nxt = frm;
1422 return frm_nxt == frm_end ? ok : partial;
1423 }
1424 if (n == 0)
1425 return error;
1426 to_nxt += n;
1427 if (to_nxt == to_end)
1428 break;
1429 if (fend != frm_end) // set up next null terminated sequence
1430 {
1431 // Try to write the terminating null
Sean Huntf3907e62011-07-15 05:40:33 +00001432#ifdef _LIBCPP_STABLE_APPLE_ABI
1433 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1434#else
1435 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1436#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001437 if (n != 0) // on error
1438 return error;
1439 ++to_nxt;
1440 ++frm_nxt;
1441 // look for next null in frm
1442 for (fend = frm_nxt; fend != frm_end; ++fend)
1443 if (*fend == 0)
1444 break;
1445 }
1446 }
1447 return frm_nxt == frm_end ? ok : partial;
1448}
1449
1450codecvt<wchar_t, char, mbstate_t>::result
1451codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1452 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1453{
1454 to_nxt = to;
1455 extern_type tmp[MB_LEN_MAX];
Sean Huntf3907e62011-07-15 05:40:33 +00001456#ifdef _LIBCPP_STABLE_APPLE_ABI
1457 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1458#else
1459 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1460#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001461 if (n == size_t(-1) || n == 0) // on error
1462 return error;
1463 --n;
1464 if (n > to_end-to_nxt) // is there room?
1465 return partial;
1466 for (extern_type* p = tmp; n; --n) // write it
1467 *to_nxt++ = *p++;
1468 return ok;
1469}
1470
1471int
Howard Hinnantc9834542011-05-31 15:34:58 +00001472codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001473{
Sean Huntf3907e62011-07-15 05:40:33 +00001474#ifdef _LIBCPP_STABLE_APPLE_ABI
1475 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1476#else
1477 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1478#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001479 {
1480 // stateless encoding
Sean Huntf3907e62011-07-15 05:40:33 +00001481#ifdef _LIBCPP_STABLE_APPLE_ABI
1482 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1483#else
1484 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1485#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001486 return 1; // which take more than 1 char to form a wchar_t
1487 return 0;
1488 }
1489 return -1;
1490}
1491
1492bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001493codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001494{
1495 return false;
1496}
1497
1498int
1499codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1500 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1501{
1502 int nbytes = 0;
1503 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1504 {
Sean Huntf3907e62011-07-15 05:40:33 +00001505#ifdef _LIBCPP_STABLE_APPLE_ABI
1506 size_t n = mbrlen_l(frm, frm_end-frm, &st, __l);
1507#else
1508 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1509#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001510 switch (n)
1511 {
1512 case 0:
1513 ++nbytes;
1514 ++frm;
1515 break;
1516 case -1:
1517 case -2:
1518 return nbytes;
1519 default:
1520 nbytes += n;
1521 frm += n;
1522 break;
1523 }
1524 }
1525 return nbytes;
1526}
1527
1528int
Howard Hinnantc9834542011-05-31 15:34:58 +00001529codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001530{
Sean Huntf3907e62011-07-15 05:40:33 +00001531#ifdef _LIBCPP_STABLE_APPLE_ABI
1532 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1533#else
1534 return __l == 0 ? 1 : __mb_cur_max_l(__l);
1535#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001536}
1537
1538// Valid UTF ranges
1539// UTF-32 UTF-16 UTF-8 # of code points
1540// first second first second third fourth
1541// 000000 - 00007F 0000 - 007F 00 - 7F 127
1542// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1543// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1544// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1545// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1546// 00D800 - 00DFFF invalid
1547// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1548// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1549// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1550// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1551
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001552static
1553codecvt_base::result
1554utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1555 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1556 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1557{
1558 frm_nxt = frm;
1559 to_nxt = to;
1560 if (mode & generate_header)
1561 {
1562 if (to_end-to_nxt < 3)
1563 return codecvt_base::partial;
1564 *to_nxt++ = static_cast<uint8_t>(0xEF);
1565 *to_nxt++ = static_cast<uint8_t>(0xBB);
1566 *to_nxt++ = static_cast<uint8_t>(0xBF);
1567 }
1568 for (; frm_nxt < frm_end; ++frm_nxt)
1569 {
1570 uint16_t wc1 = *frm_nxt;
1571 if (wc1 > Maxcode)
1572 return codecvt_base::error;
1573 if (wc1 < 0x0080)
1574 {
1575 if (to_end-to_nxt < 1)
1576 return codecvt_base::partial;
1577 *to_nxt++ = static_cast<uint8_t>(wc1);
1578 }
1579 else if (wc1 < 0x0800)
1580 {
1581 if (to_end-to_nxt < 2)
1582 return codecvt_base::partial;
1583 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1584 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1585 }
1586 else if (wc1 < 0xD800)
1587 {
1588 if (to_end-to_nxt < 3)
1589 return codecvt_base::partial;
1590 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1591 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1592 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1593 }
1594 else if (wc1 < 0xDC00)
1595 {
1596 if (frm_end-frm_nxt < 2)
1597 return codecvt_base::partial;
1598 uint16_t wc2 = frm_nxt[1];
1599 if ((wc2 & 0xFC00) != 0xDC00)
1600 return codecvt_base::error;
1601 if (to_end-to_nxt < 4)
1602 return codecvt_base::partial;
1603 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1604 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1605 return codecvt_base::error;
1606 ++frm_nxt;
1607 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1608 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1609 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1610 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1611 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1612 }
1613 else if (wc1 < 0xE000)
1614 {
1615 return codecvt_base::error;
1616 }
1617 else
1618 {
1619 if (to_end-to_nxt < 3)
1620 return codecvt_base::partial;
1621 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1622 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1623 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1624 }
1625 }
1626 return codecvt_base::ok;
1627}
1628
1629static
1630codecvt_base::result
1631utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1632 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1633 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1634{
1635 frm_nxt = frm;
1636 to_nxt = to;
1637 if (mode & generate_header)
1638 {
1639 if (to_end-to_nxt < 3)
1640 return codecvt_base::partial;
1641 *to_nxt++ = static_cast<uint8_t>(0xEF);
1642 *to_nxt++ = static_cast<uint8_t>(0xBB);
1643 *to_nxt++ = static_cast<uint8_t>(0xBF);
1644 }
1645 for (; frm_nxt < frm_end; ++frm_nxt)
1646 {
1647 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1648 if (wc1 > Maxcode)
1649 return codecvt_base::error;
1650 if (wc1 < 0x0080)
1651 {
1652 if (to_end-to_nxt < 1)
1653 return codecvt_base::partial;
1654 *to_nxt++ = static_cast<uint8_t>(wc1);
1655 }
1656 else if (wc1 < 0x0800)
1657 {
1658 if (to_end-to_nxt < 2)
1659 return codecvt_base::partial;
1660 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1661 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1662 }
1663 else if (wc1 < 0xD800)
1664 {
1665 if (to_end-to_nxt < 3)
1666 return codecvt_base::partial;
1667 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1668 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1669 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1670 }
1671 else if (wc1 < 0xDC00)
1672 {
1673 if (frm_end-frm_nxt < 2)
1674 return codecvt_base::partial;
1675 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1676 if ((wc2 & 0xFC00) != 0xDC00)
1677 return codecvt_base::error;
1678 if (to_end-to_nxt < 4)
1679 return codecvt_base::partial;
1680 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1681 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1682 return codecvt_base::error;
1683 ++frm_nxt;
1684 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1685 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1686 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1687 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1688 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1689 }
1690 else if (wc1 < 0xE000)
1691 {
1692 return codecvt_base::error;
1693 }
1694 else
1695 {
1696 if (to_end-to_nxt < 3)
1697 return codecvt_base::partial;
1698 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1699 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1700 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1701 }
1702 }
1703 return codecvt_base::ok;
1704}
1705
1706static
1707codecvt_base::result
1708utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1709 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1710 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1711{
1712 frm_nxt = frm;
1713 to_nxt = to;
1714 if (mode & consume_header)
1715 {
1716 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1717 frm_nxt[2] == 0xBF)
1718 frm_nxt += 3;
1719 }
1720 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1721 {
1722 uint8_t c1 = *frm_nxt;
1723 if (c1 > Maxcode)
1724 return codecvt_base::error;
1725 if (c1 < 0x80)
1726 {
1727 *to_nxt = static_cast<uint16_t>(c1);
1728 ++frm_nxt;
1729 }
1730 else if (c1 < 0xC2)
1731 {
1732 return codecvt_base::error;
1733 }
1734 else if (c1 < 0xE0)
1735 {
1736 if (frm_end-frm_nxt < 2)
1737 return codecvt_base::partial;
1738 uint8_t c2 = frm_nxt[1];
1739 if ((c2 & 0xC0) != 0x80)
1740 return codecvt_base::error;
1741 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1742 if (t > Maxcode)
1743 return codecvt_base::error;
1744 *to_nxt = t;
1745 frm_nxt += 2;
1746 }
1747 else if (c1 < 0xF0)
1748 {
1749 if (frm_end-frm_nxt < 3)
1750 return codecvt_base::partial;
1751 uint8_t c2 = frm_nxt[1];
1752 uint8_t c3 = frm_nxt[2];
1753 switch (c1)
1754 {
1755 case 0xE0:
1756 if ((c2 & 0xE0) != 0xA0)
1757 return codecvt_base::error;
1758 break;
1759 case 0xED:
1760 if ((c2 & 0xE0) != 0x80)
1761 return codecvt_base::error;
1762 break;
1763 default:
1764 if ((c2 & 0xC0) != 0x80)
1765 return codecvt_base::error;
1766 break;
1767 }
1768 if ((c3 & 0xC0) != 0x80)
1769 return codecvt_base::error;
1770 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1771 | ((c2 & 0x3F) << 6)
1772 | (c3 & 0x3F));
1773 if (t > Maxcode)
1774 return codecvt_base::error;
1775 *to_nxt = t;
1776 frm_nxt += 3;
1777 }
1778 else if (c1 < 0xF5)
1779 {
1780 if (frm_end-frm_nxt < 4)
1781 return codecvt_base::partial;
1782 uint8_t c2 = frm_nxt[1];
1783 uint8_t c3 = frm_nxt[2];
1784 uint8_t c4 = frm_nxt[3];
1785 switch (c1)
1786 {
1787 case 0xF0:
1788 if (!(0x90 <= c2 && c2 <= 0xBF))
1789 return codecvt_base::error;
1790 break;
1791 case 0xF4:
1792 if ((c2 & 0xF0) != 0x80)
1793 return codecvt_base::error;
1794 break;
1795 default:
1796 if ((c2 & 0xC0) != 0x80)
1797 return codecvt_base::error;
1798 break;
1799 }
1800 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1801 return codecvt_base::error;
1802 if (to_end-to_nxt < 2)
1803 return codecvt_base::partial;
1804 if (((((unsigned long)c1 & 7) << 18) +
1805 (((unsigned long)c2 & 0x3F) << 12) +
1806 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1807 return codecvt_base::error;
1808 *to_nxt = static_cast<uint16_t>(
1809 0xD800
1810 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1811 | ((c2 & 0x0F) << 2)
1812 | ((c3 & 0x30) >> 4));
1813 *++to_nxt = static_cast<uint16_t>(
1814 0xDC00
1815 | ((c3 & 0x0F) << 6)
1816 | (c4 & 0x3F));
1817 frm_nxt += 4;
1818 }
1819 else
1820 {
1821 return codecvt_base::error;
1822 }
1823 }
1824 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1825}
1826
1827static
1828codecvt_base::result
1829utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1830 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1831 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1832{
1833 frm_nxt = frm;
1834 to_nxt = to;
1835 if (mode & consume_header)
1836 {
1837 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1838 frm_nxt[2] == 0xBF)
1839 frm_nxt += 3;
1840 }
1841 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1842 {
1843 uint8_t c1 = *frm_nxt;
1844 if (c1 > Maxcode)
1845 return codecvt_base::error;
1846 if (c1 < 0x80)
1847 {
1848 *to_nxt = static_cast<uint32_t>(c1);
1849 ++frm_nxt;
1850 }
1851 else if (c1 < 0xC2)
1852 {
1853 return codecvt_base::error;
1854 }
1855 else if (c1 < 0xE0)
1856 {
1857 if (frm_end-frm_nxt < 2)
1858 return codecvt_base::partial;
1859 uint8_t c2 = frm_nxt[1];
1860 if ((c2 & 0xC0) != 0x80)
1861 return codecvt_base::error;
1862 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1863 if (t > Maxcode)
1864 return codecvt_base::error;
1865 *to_nxt = static_cast<uint32_t>(t);
1866 frm_nxt += 2;
1867 }
1868 else if (c1 < 0xF0)
1869 {
1870 if (frm_end-frm_nxt < 3)
1871 return codecvt_base::partial;
1872 uint8_t c2 = frm_nxt[1];
1873 uint8_t c3 = frm_nxt[2];
1874 switch (c1)
1875 {
1876 case 0xE0:
1877 if ((c2 & 0xE0) != 0xA0)
1878 return codecvt_base::error;
1879 break;
1880 case 0xED:
1881 if ((c2 & 0xE0) != 0x80)
1882 return codecvt_base::error;
1883 break;
1884 default:
1885 if ((c2 & 0xC0) != 0x80)
1886 return codecvt_base::error;
1887 break;
1888 }
1889 if ((c3 & 0xC0) != 0x80)
1890 return codecvt_base::error;
1891 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1892 | ((c2 & 0x3F) << 6)
1893 | (c3 & 0x3F));
1894 if (t > Maxcode)
1895 return codecvt_base::error;
1896 *to_nxt = static_cast<uint32_t>(t);
1897 frm_nxt += 3;
1898 }
1899 else if (c1 < 0xF5)
1900 {
1901 if (frm_end-frm_nxt < 4)
1902 return codecvt_base::partial;
1903 uint8_t c2 = frm_nxt[1];
1904 uint8_t c3 = frm_nxt[2];
1905 uint8_t c4 = frm_nxt[3];
1906 switch (c1)
1907 {
1908 case 0xF0:
1909 if (!(0x90 <= c2 && c2 <= 0xBF))
1910 return codecvt_base::error;
1911 break;
1912 case 0xF4:
1913 if ((c2 & 0xF0) != 0x80)
1914 return codecvt_base::error;
1915 break;
1916 default:
1917 if ((c2 & 0xC0) != 0x80)
1918 return codecvt_base::error;
1919 break;
1920 }
1921 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1922 return codecvt_base::error;
1923 if (to_end-to_nxt < 2)
1924 return codecvt_base::partial;
1925 if (((((unsigned long)c1 & 7) << 18) +
1926 (((unsigned long)c2 & 0x3F) << 12) +
1927 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1928 return codecvt_base::error;
1929 *to_nxt = static_cast<uint32_t>(
1930 0xD800
1931 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1932 | ((c2 & 0x0F) << 2)
1933 | ((c3 & 0x30) >> 4));
1934 *++to_nxt = static_cast<uint32_t>(
1935 0xDC00
1936 | ((c3 & 0x0F) << 6)
1937 | (c4 & 0x3F));
1938 frm_nxt += 4;
1939 }
1940 else
1941 {
1942 return codecvt_base::error;
1943 }
1944 }
1945 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1946}
1947
1948static
1949int
1950utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1951 size_t mx, unsigned long Maxcode = 0x10FFFF,
1952 codecvt_mode mode = codecvt_mode(0))
1953{
1954 const uint8_t* frm_nxt = frm;
1955 if (mode & consume_header)
1956 {
1957 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1958 frm_nxt[2] == 0xBF)
1959 frm_nxt += 3;
1960 }
1961 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1962 {
1963 uint8_t c1 = *frm_nxt;
1964 if (c1 > Maxcode)
1965 break;
1966 if (c1 < 0x80)
1967 {
1968 ++frm_nxt;
1969 }
1970 else if (c1 < 0xC2)
1971 {
1972 break;
1973 }
1974 else if (c1 < 0xE0)
1975 {
1976 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1977 break;
1978 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
1979 if (t > Maxcode)
1980 break;
1981 frm_nxt += 2;
1982 }
1983 else if (c1 < 0xF0)
1984 {
1985 if (frm_end-frm_nxt < 3)
1986 break;
1987 uint8_t c2 = frm_nxt[1];
1988 uint8_t c3 = frm_nxt[2];
1989 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1990 | ((c2 & 0x3F) << 6)
1991 | (c3 & 0x3F));
1992 switch (c1)
1993 {
1994 case 0xE0:
1995 if ((c2 & 0xE0) != 0xA0)
1996 return static_cast<int>(frm_nxt - frm);
1997 break;
1998 case 0xED:
1999 if ((c2 & 0xE0) != 0x80)
2000 return static_cast<int>(frm_nxt - frm);
2001 break;
2002 default:
2003 if ((c2 & 0xC0) != 0x80)
2004 return static_cast<int>(frm_nxt - frm);
2005 break;
2006 }
2007 if ((c3 & 0xC0) != 0x80)
2008 break;
2009 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2010 break;
2011 frm_nxt += 3;
2012 }
2013 else if (c1 < 0xF5)
2014 {
2015 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2016 break;
2017 uint8_t c2 = frm_nxt[1];
2018 uint8_t c3 = frm_nxt[2];
2019 uint8_t c4 = frm_nxt[3];
2020 switch (c1)
2021 {
2022 case 0xF0:
2023 if (!(0x90 <= c2 && c2 <= 0xBF))
2024 return static_cast<int>(frm_nxt - frm);
2025 break;
2026 case 0xF4:
2027 if ((c2 & 0xF0) != 0x80)
2028 return static_cast<int>(frm_nxt - frm);
2029 break;
2030 default:
2031 if ((c2 & 0xC0) != 0x80)
2032 return static_cast<int>(frm_nxt - frm);
2033 break;
2034 }
2035 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2036 break;
2037 if (((((unsigned long)c1 & 7) << 18) +
2038 (((unsigned long)c2 & 0x3F) << 12) +
2039 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2040 break;
2041 ++nchar16_t;
2042 frm_nxt += 4;
2043 }
2044 else
2045 {
2046 break;
2047 }
2048 }
2049 return static_cast<int>(frm_nxt - frm);
2050}
2051
2052static
2053codecvt_base::result
2054ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2055 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2056 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2057{
2058 frm_nxt = frm;
2059 to_nxt = to;
2060 if (mode & generate_header)
2061 {
2062 if (to_end-to_nxt < 3)
2063 return codecvt_base::partial;
2064 *to_nxt++ = static_cast<uint8_t>(0xEF);
2065 *to_nxt++ = static_cast<uint8_t>(0xBB);
2066 *to_nxt++ = static_cast<uint8_t>(0xBF);
2067 }
2068 for (; frm_nxt < frm_end; ++frm_nxt)
2069 {
2070 uint32_t wc = *frm_nxt;
2071 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2072 return codecvt_base::error;
2073 if (wc < 0x000080)
2074 {
2075 if (to_end-to_nxt < 1)
2076 return codecvt_base::partial;
2077 *to_nxt++ = static_cast<uint8_t>(wc);
2078 }
2079 else if (wc < 0x000800)
2080 {
2081 if (to_end-to_nxt < 2)
2082 return codecvt_base::partial;
2083 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2084 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2085 }
2086 else if (wc < 0x010000)
2087 {
2088 if (to_end-to_nxt < 3)
2089 return codecvt_base::partial;
2090 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2091 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2092 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2093 }
2094 else // if (wc < 0x110000)
2095 {
2096 if (to_end-to_nxt < 4)
2097 return codecvt_base::partial;
2098 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2099 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2100 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2101 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2102 }
2103 }
2104 return codecvt_base::ok;
2105}
2106
2107static
2108codecvt_base::result
2109utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2110 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2111 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2112{
2113 frm_nxt = frm;
2114 to_nxt = to;
2115 if (mode & consume_header)
2116 {
2117 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2118 frm_nxt[2] == 0xBF)
2119 frm_nxt += 3;
2120 }
2121 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2122 {
2123 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2124 if (c1 < 0x80)
2125 {
2126 if (c1 > Maxcode)
2127 return codecvt_base::error;
2128 *to_nxt = static_cast<uint32_t>(c1);
2129 ++frm_nxt;
2130 }
2131 else if (c1 < 0xC2)
2132 {
2133 return codecvt_base::error;
2134 }
2135 else if (c1 < 0xE0)
2136 {
2137 if (frm_end-frm_nxt < 2)
2138 return codecvt_base::partial;
2139 uint8_t c2 = frm_nxt[1];
2140 if ((c2 & 0xC0) != 0x80)
2141 return codecvt_base::error;
2142 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2143 | (c2 & 0x3F));
2144 if (t > Maxcode)
2145 return codecvt_base::error;
2146 *to_nxt = t;
2147 frm_nxt += 2;
2148 }
2149 else if (c1 < 0xF0)
2150 {
2151 if (frm_end-frm_nxt < 3)
2152 return codecvt_base::partial;
2153 uint8_t c2 = frm_nxt[1];
2154 uint8_t c3 = frm_nxt[2];
2155 switch (c1)
2156 {
2157 case 0xE0:
2158 if ((c2 & 0xE0) != 0xA0)
2159 return codecvt_base::error;
2160 break;
2161 case 0xED:
2162 if ((c2 & 0xE0) != 0x80)
2163 return codecvt_base::error;
2164 break;
2165 default:
2166 if ((c2 & 0xC0) != 0x80)
2167 return codecvt_base::error;
2168 break;
2169 }
2170 if ((c3 & 0xC0) != 0x80)
2171 return codecvt_base::error;
2172 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2173 | ((c2 & 0x3F) << 6)
2174 | (c3 & 0x3F));
2175 if (t > Maxcode)
2176 return codecvt_base::error;
2177 *to_nxt = t;
2178 frm_nxt += 3;
2179 }
2180 else if (c1 < 0xF5)
2181 {
2182 if (frm_end-frm_nxt < 4)
2183 return codecvt_base::partial;
2184 uint8_t c2 = frm_nxt[1];
2185 uint8_t c3 = frm_nxt[2];
2186 uint8_t c4 = frm_nxt[3];
2187 switch (c1)
2188 {
2189 case 0xF0:
2190 if (!(0x90 <= c2 && c2 <= 0xBF))
2191 return codecvt_base::error;
2192 break;
2193 case 0xF4:
2194 if ((c2 & 0xF0) != 0x80)
2195 return codecvt_base::error;
2196 break;
2197 default:
2198 if ((c2 & 0xC0) != 0x80)
2199 return codecvt_base::error;
2200 break;
2201 }
2202 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2203 return codecvt_base::error;
2204 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2205 | ((c2 & 0x3F) << 12)
2206 | ((c3 & 0x3F) << 6)
2207 | (c4 & 0x3F));
2208 if (t > Maxcode)
2209 return codecvt_base::error;
2210 *to_nxt = t;
2211 frm_nxt += 4;
2212 }
2213 else
2214 {
2215 return codecvt_base::error;
2216 }
2217 }
2218 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2219}
2220
2221static
2222int
2223utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2224 size_t mx, unsigned long Maxcode = 0x10FFFF,
2225 codecvt_mode mode = codecvt_mode(0))
2226{
2227 const uint8_t* frm_nxt = frm;
2228 if (mode & consume_header)
2229 {
2230 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2231 frm_nxt[2] == 0xBF)
2232 frm_nxt += 3;
2233 }
2234 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2235 {
2236 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2237 if (c1 < 0x80)
2238 {
2239 if (c1 > Maxcode)
2240 break;
2241 ++frm_nxt;
2242 }
2243 else if (c1 < 0xC2)
2244 {
2245 break;
2246 }
2247 else if (c1 < 0xE0)
2248 {
2249 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2250 break;
2251 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2252 break;
2253 frm_nxt += 2;
2254 }
2255 else if (c1 < 0xF0)
2256 {
2257 if (frm_end-frm_nxt < 3)
2258 break;
2259 uint8_t c2 = frm_nxt[1];
2260 uint8_t c3 = frm_nxt[2];
2261 switch (c1)
2262 {
2263 case 0xE0:
2264 if ((c2 & 0xE0) != 0xA0)
2265 return static_cast<int>(frm_nxt - frm);
2266 break;
2267 case 0xED:
2268 if ((c2 & 0xE0) != 0x80)
2269 return static_cast<int>(frm_nxt - frm);
2270 break;
2271 default:
2272 if ((c2 & 0xC0) != 0x80)
2273 return static_cast<int>(frm_nxt - frm);
2274 break;
2275 }
2276 if ((c3 & 0xC0) != 0x80)
2277 break;
2278 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2279 break;
2280 frm_nxt += 3;
2281 }
2282 else if (c1 < 0xF5)
2283 {
2284 if (frm_end-frm_nxt < 4)
2285 break;
2286 uint8_t c2 = frm_nxt[1];
2287 uint8_t c3 = frm_nxt[2];
2288 uint8_t c4 = frm_nxt[3];
2289 switch (c1)
2290 {
2291 case 0xF0:
2292 if (!(0x90 <= c2 && c2 <= 0xBF))
2293 return static_cast<int>(frm_nxt - frm);
2294 break;
2295 case 0xF4:
2296 if ((c2 & 0xF0) != 0x80)
2297 return static_cast<int>(frm_nxt - frm);
2298 break;
2299 default:
2300 if ((c2 & 0xC0) != 0x80)
2301 return static_cast<int>(frm_nxt - frm);
2302 break;
2303 }
2304 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2305 break;
2306 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2307 | ((c2 & 0x3F) << 12)
2308 | ((c3 & 0x3F) << 6)
2309 | (c4 & 0x3F));
2310 if ((((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) |
2311 ((c3 & 0x3F) << 6) | (c4 & 0x3F)) > Maxcode)
2312 break;
2313 frm_nxt += 4;
2314 }
2315 else
2316 {
2317 break;
2318 }
2319 }
2320 return static_cast<int>(frm_nxt - frm);
2321}
2322
2323static
2324codecvt_base::result
2325ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2326 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2327 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2328{
2329 frm_nxt = frm;
2330 to_nxt = to;
2331 if (mode & generate_header)
2332 {
2333 if (to_end-to_nxt < 3)
2334 return codecvt_base::partial;
2335 *to_nxt++ = static_cast<uint8_t>(0xEF);
2336 *to_nxt++ = static_cast<uint8_t>(0xBB);
2337 *to_nxt++ = static_cast<uint8_t>(0xBF);
2338 }
2339 for (; frm_nxt < frm_end; ++frm_nxt)
2340 {
2341 uint16_t wc = *frm_nxt;
2342 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2343 return codecvt_base::error;
2344 if (wc < 0x0080)
2345 {
2346 if (to_end-to_nxt < 1)
2347 return codecvt_base::partial;
2348 *to_nxt++ = static_cast<uint8_t>(wc);
2349 }
2350 else if (wc < 0x0800)
2351 {
2352 if (to_end-to_nxt < 2)
2353 return codecvt_base::partial;
2354 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2355 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2356 }
2357 else // if (wc <= 0xFFFF)
2358 {
2359 if (to_end-to_nxt < 3)
2360 return codecvt_base::partial;
2361 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2362 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2363 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2364 }
2365 }
2366 return codecvt_base::ok;
2367}
2368
2369static
2370codecvt_base::result
2371utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2372 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2373 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2374{
2375 frm_nxt = frm;
2376 to_nxt = to;
2377 if (mode & consume_header)
2378 {
2379 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2380 frm_nxt[2] == 0xBF)
2381 frm_nxt += 3;
2382 }
2383 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2384 {
2385 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2386 if (c1 < 0x80)
2387 {
2388 if (c1 > Maxcode)
2389 return codecvt_base::error;
2390 *to_nxt = static_cast<uint16_t>(c1);
2391 ++frm_nxt;
2392 }
2393 else if (c1 < 0xC2)
2394 {
2395 return codecvt_base::error;
2396 }
2397 else if (c1 < 0xE0)
2398 {
2399 if (frm_end-frm_nxt < 2)
2400 return codecvt_base::partial;
2401 uint8_t c2 = frm_nxt[1];
2402 if ((c2 & 0xC0) != 0x80)
2403 return codecvt_base::error;
2404 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2405 | (c2 & 0x3F));
2406 if (t > Maxcode)
2407 return codecvt_base::error;
2408 *to_nxt = t;
2409 frm_nxt += 2;
2410 }
2411 else if (c1 < 0xF0)
2412 {
2413 if (frm_end-frm_nxt < 3)
2414 return codecvt_base::partial;
2415 uint8_t c2 = frm_nxt[1];
2416 uint8_t c3 = frm_nxt[2];
2417 switch (c1)
2418 {
2419 case 0xE0:
2420 if ((c2 & 0xE0) != 0xA0)
2421 return codecvt_base::error;
2422 break;
2423 case 0xED:
2424 if ((c2 & 0xE0) != 0x80)
2425 return codecvt_base::error;
2426 break;
2427 default:
2428 if ((c2 & 0xC0) != 0x80)
2429 return codecvt_base::error;
2430 break;
2431 }
2432 if ((c3 & 0xC0) != 0x80)
2433 return codecvt_base::error;
2434 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2435 | ((c2 & 0x3F) << 6)
2436 | (c3 & 0x3F));
2437 if (t > Maxcode)
2438 return codecvt_base::error;
2439 *to_nxt = t;
2440 frm_nxt += 3;
2441 }
2442 else
2443 {
2444 return codecvt_base::error;
2445 }
2446 }
2447 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2448}
2449
2450static
2451int
2452utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2453 size_t mx, unsigned long Maxcode = 0x10FFFF,
2454 codecvt_mode mode = codecvt_mode(0))
2455{
2456 const uint8_t* frm_nxt = frm;
2457 if (mode & consume_header)
2458 {
2459 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2460 frm_nxt[2] == 0xBF)
2461 frm_nxt += 3;
2462 }
2463 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2464 {
2465 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2466 if (c1 < 0x80)
2467 {
2468 if (c1 > Maxcode)
2469 break;
2470 ++frm_nxt;
2471 }
2472 else if (c1 < 0xC2)
2473 {
2474 break;
2475 }
2476 else if (c1 < 0xE0)
2477 {
2478 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2479 break;
2480 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2481 break;
2482 frm_nxt += 2;
2483 }
2484 else if (c1 < 0xF0)
2485 {
2486 if (frm_end-frm_nxt < 3)
2487 break;
2488 uint8_t c2 = frm_nxt[1];
2489 uint8_t c3 = frm_nxt[2];
2490 switch (c1)
2491 {
2492 case 0xE0:
2493 if ((c2 & 0xE0) != 0xA0)
2494 return static_cast<int>(frm_nxt - frm);
2495 break;
2496 case 0xED:
2497 if ((c2 & 0xE0) != 0x80)
2498 return static_cast<int>(frm_nxt - frm);
2499 break;
2500 default:
2501 if ((c2 & 0xC0) != 0x80)
2502 return static_cast<int>(frm_nxt - frm);
2503 break;
2504 }
2505 if ((c3 & 0xC0) != 0x80)
2506 break;
2507 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2508 break;
2509 frm_nxt += 3;
2510 }
2511 else
2512 {
2513 break;
2514 }
2515 }
2516 return static_cast<int>(frm_nxt - frm);
2517}
2518
2519static
2520codecvt_base::result
2521ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2522 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2523 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2524{
2525 frm_nxt = frm;
2526 to_nxt = to;
2527 if (mode & generate_header)
2528 {
2529 if (to_end-to_nxt < 2)
2530 return codecvt_base::partial;
2531 *to_nxt++ = static_cast<uint8_t>(0xFE);
2532 *to_nxt++ = static_cast<uint8_t>(0xFF);
2533 }
2534 for (; frm_nxt < frm_end; ++frm_nxt)
2535 {
2536 uint32_t wc = *frm_nxt;
2537 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2538 return codecvt_base::error;
2539 if (wc < 0x010000)
2540 {
2541 if (to_end-to_nxt < 2)
2542 return codecvt_base::partial;
2543 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2544 *to_nxt++ = static_cast<uint8_t>(wc);
2545 }
2546 else
2547 {
2548 if (to_end-to_nxt < 4)
2549 return codecvt_base::partial;
2550 uint16_t t = static_cast<uint16_t>(
2551 0xD800
2552 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2553 | ((wc & 0x00FC00) >> 10));
2554 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2555 *to_nxt++ = static_cast<uint8_t>(t);
2556 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2557 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2558 *to_nxt++ = static_cast<uint8_t>(t);
2559 }
2560 }
2561 return codecvt_base::ok;
2562}
2563
2564static
2565codecvt_base::result
2566utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2567 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2568 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2569{
2570 frm_nxt = frm;
2571 to_nxt = to;
2572 if (mode & consume_header)
2573 {
2574 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2575 frm_nxt += 2;
2576 }
2577 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2578 {
2579 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2580 if ((c1 & 0xFC00) == 0xDC00)
2581 return codecvt_base::error;
2582 if ((c1 & 0xFC00) != 0xD800)
2583 {
2584 if (c1 > Maxcode)
2585 return codecvt_base::error;
2586 *to_nxt = static_cast<uint32_t>(c1);
2587 frm_nxt += 2;
2588 }
2589 else
2590 {
2591 if (frm_end-frm_nxt < 4)
2592 return codecvt_base::partial;
2593 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2594 if ((c2 & 0xFC00) != 0xDC00)
2595 return codecvt_base::error;
2596 uint32_t t = static_cast<uint32_t>(
2597 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2598 | ((c1 & 0x003F) << 10)
2599 | (c2 & 0x03FF));
2600 if (t > Maxcode)
2601 return codecvt_base::error;
2602 *to_nxt = t;
2603 frm_nxt += 4;
2604 }
2605 }
2606 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2607}
2608
2609static
2610int
2611utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2612 size_t mx, unsigned long Maxcode = 0x10FFFF,
2613 codecvt_mode mode = codecvt_mode(0))
2614{
2615 const uint8_t* frm_nxt = frm;
2616 frm_nxt = frm;
2617 if (mode & consume_header)
2618 {
2619 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2620 frm_nxt += 2;
2621 }
2622 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2623 {
2624 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2625 if ((c1 & 0xFC00) == 0xDC00)
2626 break;
2627 if ((c1 & 0xFC00) != 0xD800)
2628 {
2629 if (c1 > Maxcode)
2630 break;
2631 frm_nxt += 2;
2632 }
2633 else
2634 {
2635 if (frm_end-frm_nxt < 4)
2636 break;
2637 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2638 if ((c2 & 0xFC00) != 0xDC00)
2639 break;
2640 uint32_t t = static_cast<uint32_t>(
2641 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2642 | ((c1 & 0x003F) << 10)
2643 | (c2 & 0x03FF));
2644 if (t > Maxcode)
2645 break;
2646 frm_nxt += 4;
2647 }
2648 }
2649 return static_cast<int>(frm_nxt - frm);
2650}
2651
2652static
2653codecvt_base::result
2654ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2655 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2656 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2657{
2658 frm_nxt = frm;
2659 to_nxt = to;
2660 if (mode & generate_header)
2661 {
2662 if (to_end-to_nxt < 2)
2663 return codecvt_base::partial;
2664 *to_nxt++ = static_cast<uint8_t>(0xFF);
2665 *to_nxt++ = static_cast<uint8_t>(0xFE);
2666 }
2667 for (; frm_nxt < frm_end; ++frm_nxt)
2668 {
2669 uint32_t wc = *frm_nxt;
2670 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2671 return codecvt_base::error;
2672 if (wc < 0x010000)
2673 {
2674 if (to_end-to_nxt < 2)
2675 return codecvt_base::partial;
2676 *to_nxt++ = static_cast<uint8_t>(wc);
2677 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2678 }
2679 else
2680 {
2681 if (to_end-to_nxt < 4)
2682 return codecvt_base::partial;
2683 uint16_t t = static_cast<uint16_t>(
2684 0xD800
2685 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2686 | ((wc & 0x00FC00) >> 10));
2687 *to_nxt++ = static_cast<uint8_t>(t);
2688 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2689 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2690 *to_nxt++ = static_cast<uint8_t>(t);
2691 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2692 }
2693 }
2694 return codecvt_base::ok;
2695}
2696
2697static
2698codecvt_base::result
2699utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2700 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2701 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2702{
2703 frm_nxt = frm;
2704 to_nxt = to;
2705 if (mode & consume_header)
2706 {
2707 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2708 frm_nxt += 2;
2709 }
2710 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2711 {
2712 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2713 if ((c1 & 0xFC00) == 0xDC00)
2714 return codecvt_base::error;
2715 if ((c1 & 0xFC00) != 0xD800)
2716 {
2717 if (c1 > Maxcode)
2718 return codecvt_base::error;
2719 *to_nxt = static_cast<uint32_t>(c1);
2720 frm_nxt += 2;
2721 }
2722 else
2723 {
2724 if (frm_end-frm_nxt < 4)
2725 return codecvt_base::partial;
2726 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2727 if ((c2 & 0xFC00) != 0xDC00)
2728 return codecvt_base::error;
2729 uint32_t t = static_cast<uint32_t>(
2730 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2731 | ((c1 & 0x003F) << 10)
2732 | (c2 & 0x03FF));
2733 if (t > Maxcode)
2734 return codecvt_base::error;
2735 *to_nxt = t;
2736 frm_nxt += 4;
2737 }
2738 }
2739 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2740}
2741
2742static
2743int
2744utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2745 size_t mx, unsigned long Maxcode = 0x10FFFF,
2746 codecvt_mode mode = codecvt_mode(0))
2747{
2748 const uint8_t* frm_nxt = frm;
2749 frm_nxt = frm;
2750 if (mode & consume_header)
2751 {
2752 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2753 frm_nxt += 2;
2754 }
2755 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2756 {
2757 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2758 if ((c1 & 0xFC00) == 0xDC00)
2759 break;
2760 if ((c1 & 0xFC00) != 0xD800)
2761 {
2762 if (c1 > Maxcode)
2763 break;
2764 frm_nxt += 2;
2765 }
2766 else
2767 {
2768 if (frm_end-frm_nxt < 4)
2769 break;
2770 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2771 if ((c2 & 0xFC00) != 0xDC00)
2772 break;
2773 uint32_t t = static_cast<uint32_t>(
2774 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2775 | ((c1 & 0x003F) << 10)
2776 | (c2 & 0x03FF));
2777 if (t > Maxcode)
2778 break;
2779 frm_nxt += 4;
2780 }
2781 }
2782 return static_cast<int>(frm_nxt - frm);
2783}
2784
2785static
2786codecvt_base::result
2787ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2788 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2789 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2790{
2791 frm_nxt = frm;
2792 to_nxt = to;
2793 if (mode & generate_header)
2794 {
2795 if (to_end-to_nxt < 2)
2796 return codecvt_base::partial;
2797 *to_nxt++ = static_cast<uint8_t>(0xFE);
2798 *to_nxt++ = static_cast<uint8_t>(0xFF);
2799 }
2800 for (; frm_nxt < frm_end; ++frm_nxt)
2801 {
2802 uint16_t wc = *frm_nxt;
2803 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2804 return codecvt_base::error;
2805 if (to_end-to_nxt < 2)
2806 return codecvt_base::partial;
2807 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2808 *to_nxt++ = static_cast<uint8_t>(wc);
2809 }
2810 return codecvt_base::ok;
2811}
2812
2813static
2814codecvt_base::result
2815utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2816 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2817 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2818{
2819 frm_nxt = frm;
2820 to_nxt = to;
2821 if (mode & consume_header)
2822 {
2823 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2824 frm_nxt += 2;
2825 }
2826 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2827 {
2828 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2829 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2830 return codecvt_base::error;
2831 *to_nxt = c1;
2832 frm_nxt += 2;
2833 }
2834 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2835}
2836
2837static
2838int
2839utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2840 size_t mx, unsigned long Maxcode = 0x10FFFF,
2841 codecvt_mode mode = codecvt_mode(0))
2842{
2843 const uint8_t* frm_nxt = frm;
2844 frm_nxt = frm;
2845 if (mode & consume_header)
2846 {
2847 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2848 frm_nxt += 2;
2849 }
2850 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2851 {
2852 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2853 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2854 break;
2855 frm_nxt += 2;
2856 }
2857 return static_cast<int>(frm_nxt - frm);
2858}
2859
2860static
2861codecvt_base::result
2862ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2863 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2864 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2865{
2866 frm_nxt = frm;
2867 to_nxt = to;
2868 if (mode & generate_header)
2869 {
2870 if (to_end-to_nxt < 2)
2871 return codecvt_base::partial;
2872 *to_nxt++ = static_cast<uint8_t>(0xFF);
2873 *to_nxt++ = static_cast<uint8_t>(0xFE);
2874 }
2875 for (; frm_nxt < frm_end; ++frm_nxt)
2876 {
2877 uint16_t wc = *frm_nxt;
2878 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2879 return codecvt_base::error;
2880 if (to_end-to_nxt < 2)
2881 return codecvt_base::partial;
2882 *to_nxt++ = static_cast<uint8_t>(wc);
2883 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2884 }
2885 return codecvt_base::ok;
2886}
2887
2888static
2889codecvt_base::result
2890utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2891 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2892 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2893{
2894 frm_nxt = frm;
2895 to_nxt = to;
2896 if (mode & consume_header)
2897 {
2898 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2899 frm_nxt += 2;
2900 }
2901 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2902 {
2903 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2904 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2905 return codecvt_base::error;
2906 *to_nxt = c1;
2907 frm_nxt += 2;
2908 }
2909 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2910}
2911
2912static
2913int
2914utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2915 size_t mx, unsigned long Maxcode = 0x10FFFF,
2916 codecvt_mode mode = codecvt_mode(0))
2917{
2918 const uint8_t* frm_nxt = frm;
2919 frm_nxt = frm;
2920 if (mode & consume_header)
2921 {
2922 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2923 frm_nxt += 2;
2924 }
2925 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2926 {
2927 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2928 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2929 break;
2930 frm_nxt += 2;
2931 }
2932 return static_cast<int>(frm_nxt - frm);
2933}
2934
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002935// template <> class codecvt<char16_t, char, mbstate_t>
2936
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002937locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002938
2939codecvt<char16_t, char, mbstate_t>::~codecvt()
2940{
2941}
2942
2943codecvt<char16_t, char, mbstate_t>::result
2944codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002945 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002946 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2947{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002948 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2949 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2950 const uint16_t* _frm_nxt = _frm;
2951 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2952 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2953 uint8_t* _to_nxt = _to;
2954 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2955 frm_nxt = frm + (_frm_nxt - _frm);
2956 to_nxt = to + (_to_nxt - _to);
2957 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002958}
2959
2960codecvt<char16_t, char, mbstate_t>::result
2961codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002962 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002963 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2964{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002965 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2966 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2967 const uint8_t* _frm_nxt = _frm;
2968 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2969 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2970 uint16_t* _to_nxt = _to;
2971 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2972 frm_nxt = frm + (_frm_nxt - _frm);
2973 to_nxt = to + (_to_nxt - _to);
2974 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002975}
2976
2977codecvt<char16_t, char, mbstate_t>::result
2978codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
2979 extern_type* to, extern_type*, extern_type*& to_nxt) const
2980{
2981 to_nxt = to;
2982 return noconv;
2983}
2984
2985int
Howard Hinnantc9834542011-05-31 15:34:58 +00002986codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002987{
2988 return 0;
2989}
2990
2991bool
Howard Hinnantc9834542011-05-31 15:34:58 +00002992codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002993{
2994 return false;
2995}
2996
2997int
2998codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
2999 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3000{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003001 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3002 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3003 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003004}
3005
3006int
Howard Hinnantc9834542011-05-31 15:34:58 +00003007codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003008{
3009 return 4;
3010}
3011
3012// template <> class codecvt<char32_t, char, mbstate_t>
3013
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003014locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003015
3016codecvt<char32_t, char, mbstate_t>::~codecvt()
3017{
3018}
3019
3020codecvt<char32_t, char, mbstate_t>::result
3021codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003022 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003023 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3024{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003025 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3026 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3027 const uint32_t* _frm_nxt = _frm;
3028 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3029 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3030 uint8_t* _to_nxt = _to;
3031 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3032 frm_nxt = frm + (_frm_nxt - _frm);
3033 to_nxt = to + (_to_nxt - _to);
3034 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003035}
3036
3037codecvt<char32_t, char, mbstate_t>::result
3038codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003039 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003040 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3041{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003042 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3043 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3044 const uint8_t* _frm_nxt = _frm;
3045 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3046 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3047 uint32_t* _to_nxt = _to;
3048 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3049 frm_nxt = frm + (_frm_nxt - _frm);
3050 to_nxt = to + (_to_nxt - _to);
3051 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003052}
3053
3054codecvt<char32_t, char, mbstate_t>::result
3055codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3056 extern_type* to, extern_type*, extern_type*& to_nxt) const
3057{
3058 to_nxt = to;
3059 return noconv;
3060}
3061
3062int
Howard Hinnantc9834542011-05-31 15:34:58 +00003063codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003064{
3065 return 0;
3066}
3067
3068bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003069codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003070{
3071 return false;
3072}
3073
3074int
3075codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3076 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3077{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003078 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3079 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3080 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003081}
3082
3083int
Howard Hinnantc9834542011-05-31 15:34:58 +00003084codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003085{
3086 return 4;
3087}
3088
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003089// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003090
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003091__codecvt_utf8<wchar_t>::result
3092__codecvt_utf8<wchar_t>::do_out(state_type&,
3093 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003094 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3095{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003096 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3097 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3098 const uint32_t* _frm_nxt = _frm;
3099 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3100 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3101 uint8_t* _to_nxt = _to;
3102 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3103 _Maxcode_, _Mode_);
3104 frm_nxt = frm + (_frm_nxt - _frm);
3105 to_nxt = to + (_to_nxt - _to);
3106 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003107}
3108
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003109__codecvt_utf8<wchar_t>::result
3110__codecvt_utf8<wchar_t>::do_in(state_type&,
3111 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003112 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3113{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003114 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3115 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3116 const uint8_t* _frm_nxt = _frm;
3117 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3118 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3119 uint32_t* _to_nxt = _to;
3120 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3121 _Maxcode_, _Mode_);
3122 frm_nxt = frm + (_frm_nxt - _frm);
3123 to_nxt = to + (_to_nxt - _to);
3124 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003125}
3126
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003127__codecvt_utf8<wchar_t>::result
3128__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003129 extern_type* to, extern_type*, extern_type*& to_nxt) const
3130{
3131 to_nxt = to;
3132 return noconv;
3133}
3134
3135int
Howard Hinnantc9834542011-05-31 15:34:58 +00003136__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003137{
3138 return 0;
3139}
3140
3141bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003142__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003143{
3144 return false;
3145}
3146
3147int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003148__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003149 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3150{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003151 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3152 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3153 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003154}
3155
3156int
Howard Hinnantc9834542011-05-31 15:34:58 +00003157__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003158{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003159 if (_Mode_ & consume_header)
3160 return 7;
3161 return 4;
3162}
3163
3164// __codecvt_utf8<char16_t>
3165
3166__codecvt_utf8<char16_t>::result
3167__codecvt_utf8<char16_t>::do_out(state_type&,
3168 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3169 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3170{
3171 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3172 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3173 const uint16_t* _frm_nxt = _frm;
3174 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3175 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3176 uint8_t* _to_nxt = _to;
3177 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3178 _Maxcode_, _Mode_);
3179 frm_nxt = frm + (_frm_nxt - _frm);
3180 to_nxt = to + (_to_nxt - _to);
3181 return r;
3182}
3183
3184__codecvt_utf8<char16_t>::result
3185__codecvt_utf8<char16_t>::do_in(state_type&,
3186 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3187 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3188{
3189 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3190 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3191 const uint8_t* _frm_nxt = _frm;
3192 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3193 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3194 uint16_t* _to_nxt = _to;
3195 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3196 _Maxcode_, _Mode_);
3197 frm_nxt = frm + (_frm_nxt - _frm);
3198 to_nxt = to + (_to_nxt - _to);
3199 return r;
3200}
3201
3202__codecvt_utf8<char16_t>::result
3203__codecvt_utf8<char16_t>::do_unshift(state_type&,
3204 extern_type* to, extern_type*, extern_type*& to_nxt) const
3205{
3206 to_nxt = to;
3207 return noconv;
3208}
3209
3210int
Howard Hinnantc9834542011-05-31 15:34:58 +00003211__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003212{
3213 return 0;
3214}
3215
3216bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003217__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003218{
3219 return false;
3220}
3221
3222int
3223__codecvt_utf8<char16_t>::do_length(state_type&,
3224 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3225{
3226 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3227 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3228 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3229}
3230
3231int
Howard Hinnantc9834542011-05-31 15:34:58 +00003232__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003233{
3234 if (_Mode_ & consume_header)
3235 return 6;
3236 return 3;
3237}
3238
3239// __codecvt_utf8<char32_t>
3240
3241__codecvt_utf8<char32_t>::result
3242__codecvt_utf8<char32_t>::do_out(state_type&,
3243 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3244 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3245{
3246 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3247 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3248 const uint32_t* _frm_nxt = _frm;
3249 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3250 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3251 uint8_t* _to_nxt = _to;
3252 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3253 _Maxcode_, _Mode_);
3254 frm_nxt = frm + (_frm_nxt - _frm);
3255 to_nxt = to + (_to_nxt - _to);
3256 return r;
3257}
3258
3259__codecvt_utf8<char32_t>::result
3260__codecvt_utf8<char32_t>::do_in(state_type&,
3261 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3262 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3263{
3264 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3265 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3266 const uint8_t* _frm_nxt = _frm;
3267 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3268 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3269 uint32_t* _to_nxt = _to;
3270 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3271 _Maxcode_, _Mode_);
3272 frm_nxt = frm + (_frm_nxt - _frm);
3273 to_nxt = to + (_to_nxt - _to);
3274 return r;
3275}
3276
3277__codecvt_utf8<char32_t>::result
3278__codecvt_utf8<char32_t>::do_unshift(state_type&,
3279 extern_type* to, extern_type*, extern_type*& to_nxt) const
3280{
3281 to_nxt = to;
3282 return noconv;
3283}
3284
3285int
Howard Hinnantc9834542011-05-31 15:34:58 +00003286__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003287{
3288 return 0;
3289}
3290
3291bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003292__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003293{
3294 return false;
3295}
3296
3297int
3298__codecvt_utf8<char32_t>::do_length(state_type&,
3299 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3300{
3301 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3302 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3303 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3304}
3305
3306int
Howard Hinnantc9834542011-05-31 15:34:58 +00003307__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003308{
3309 if (_Mode_ & consume_header)
3310 return 7;
3311 return 4;
3312}
3313
3314// __codecvt_utf16<wchar_t, false>
3315
3316__codecvt_utf16<wchar_t, false>::result
3317__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3318 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3319 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3320{
3321 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3322 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3323 const uint32_t* _frm_nxt = _frm;
3324 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3325 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3326 uint8_t* _to_nxt = _to;
3327 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3328 _Maxcode_, _Mode_);
3329 frm_nxt = frm + (_frm_nxt - _frm);
3330 to_nxt = to + (_to_nxt - _to);
3331 return r;
3332}
3333
3334__codecvt_utf16<wchar_t, false>::result
3335__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3336 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3337 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3338{
3339 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3340 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3341 const uint8_t* _frm_nxt = _frm;
3342 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3343 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3344 uint32_t* _to_nxt = _to;
3345 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3346 _Maxcode_, _Mode_);
3347 frm_nxt = frm + (_frm_nxt - _frm);
3348 to_nxt = to + (_to_nxt - _to);
3349 return r;
3350}
3351
3352__codecvt_utf16<wchar_t, false>::result
3353__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3354 extern_type* to, extern_type*, extern_type*& to_nxt) const
3355{
3356 to_nxt = to;
3357 return noconv;
3358}
3359
3360int
Howard Hinnantc9834542011-05-31 15:34:58 +00003361__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003362{
3363 return 0;
3364}
3365
3366bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003367__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003368{
3369 return false;
3370}
3371
3372int
3373__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3374 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3375{
3376 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3377 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3378 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3379}
3380
3381int
Howard Hinnantc9834542011-05-31 15:34:58 +00003382__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003383{
3384 if (_Mode_ & consume_header)
3385 return 6;
3386 return 4;
3387}
3388
3389// __codecvt_utf16<wchar_t, true>
3390
3391__codecvt_utf16<wchar_t, true>::result
3392__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3393 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3394 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3395{
3396 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3397 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3398 const uint32_t* _frm_nxt = _frm;
3399 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3400 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3401 uint8_t* _to_nxt = _to;
3402 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3403 _Maxcode_, _Mode_);
3404 frm_nxt = frm + (_frm_nxt - _frm);
3405 to_nxt = to + (_to_nxt - _to);
3406 return r;
3407}
3408
3409__codecvt_utf16<wchar_t, true>::result
3410__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3411 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3412 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3413{
3414 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3415 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3416 const uint8_t* _frm_nxt = _frm;
3417 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3418 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3419 uint32_t* _to_nxt = _to;
3420 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3421 _Maxcode_, _Mode_);
3422 frm_nxt = frm + (_frm_nxt - _frm);
3423 to_nxt = to + (_to_nxt - _to);
3424 return r;
3425}
3426
3427__codecvt_utf16<wchar_t, true>::result
3428__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3429 extern_type* to, extern_type*, extern_type*& to_nxt) const
3430{
3431 to_nxt = to;
3432 return noconv;
3433}
3434
3435int
Howard Hinnantc9834542011-05-31 15:34:58 +00003436__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003437{
3438 return 0;
3439}
3440
3441bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003442__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003443{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003444 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003445}
3446
3447int
3448__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3449 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3450{
3451 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3452 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3453 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3454}
3455
3456int
Howard Hinnantc9834542011-05-31 15:34:58 +00003457__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003458{
3459 if (_Mode_ & consume_header)
3460 return 6;
3461 return 4;
3462}
3463
3464// __codecvt_utf16<char16_t, false>
3465
3466__codecvt_utf16<char16_t, false>::result
3467__codecvt_utf16<char16_t, false>::do_out(state_type&,
3468 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3469 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3470{
3471 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3472 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3473 const uint16_t* _frm_nxt = _frm;
3474 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3475 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3476 uint8_t* _to_nxt = _to;
3477 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3478 _Maxcode_, _Mode_);
3479 frm_nxt = frm + (_frm_nxt - _frm);
3480 to_nxt = to + (_to_nxt - _to);
3481 return r;
3482}
3483
3484__codecvt_utf16<char16_t, false>::result
3485__codecvt_utf16<char16_t, false>::do_in(state_type&,
3486 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3487 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3488{
3489 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3490 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3491 const uint8_t* _frm_nxt = _frm;
3492 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3493 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3494 uint16_t* _to_nxt = _to;
3495 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3496 _Maxcode_, _Mode_);
3497 frm_nxt = frm + (_frm_nxt - _frm);
3498 to_nxt = to + (_to_nxt - _to);
3499 return r;
3500}
3501
3502__codecvt_utf16<char16_t, false>::result
3503__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3504 extern_type* to, extern_type*, extern_type*& to_nxt) const
3505{
3506 to_nxt = to;
3507 return noconv;
3508}
3509
3510int
Howard Hinnantc9834542011-05-31 15:34:58 +00003511__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003512{
3513 return 0;
3514}
3515
3516bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003517__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003518{
3519 return false;
3520}
3521
3522int
3523__codecvt_utf16<char16_t, false>::do_length(state_type&,
3524 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3525{
3526 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3527 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3528 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3529}
3530
3531int
Howard Hinnantc9834542011-05-31 15:34:58 +00003532__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003533{
3534 if (_Mode_ & consume_header)
3535 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003536 return 2;
3537}
3538
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003539// __codecvt_utf16<char16_t, true>
3540
3541__codecvt_utf16<char16_t, true>::result
3542__codecvt_utf16<char16_t, true>::do_out(state_type&,
3543 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3544 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3545{
3546 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3547 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3548 const uint16_t* _frm_nxt = _frm;
3549 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3550 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3551 uint8_t* _to_nxt = _to;
3552 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3553 _Maxcode_, _Mode_);
3554 frm_nxt = frm + (_frm_nxt - _frm);
3555 to_nxt = to + (_to_nxt - _to);
3556 return r;
3557}
3558
3559__codecvt_utf16<char16_t, true>::result
3560__codecvt_utf16<char16_t, true>::do_in(state_type&,
3561 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3562 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3563{
3564 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3565 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3566 const uint8_t* _frm_nxt = _frm;
3567 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3568 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3569 uint16_t* _to_nxt = _to;
3570 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3571 _Maxcode_, _Mode_);
3572 frm_nxt = frm + (_frm_nxt - _frm);
3573 to_nxt = to + (_to_nxt - _to);
3574 return r;
3575}
3576
3577__codecvt_utf16<char16_t, true>::result
3578__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3579 extern_type* to, extern_type*, extern_type*& to_nxt) const
3580{
3581 to_nxt = to;
3582 return noconv;
3583}
3584
3585int
Howard Hinnantc9834542011-05-31 15:34:58 +00003586__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003587{
3588 return 0;
3589}
3590
3591bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003592__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003593{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003594 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003595}
3596
3597int
3598__codecvt_utf16<char16_t, true>::do_length(state_type&,
3599 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3600{
3601 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3602 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3603 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3604}
3605
3606int
Howard Hinnantc9834542011-05-31 15:34:58 +00003607__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003608{
3609 if (_Mode_ & consume_header)
3610 return 4;
3611 return 2;
3612}
3613
3614// __codecvt_utf16<char32_t, false>
3615
3616__codecvt_utf16<char32_t, false>::result
3617__codecvt_utf16<char32_t, false>::do_out(state_type&,
3618 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3619 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3620{
3621 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3622 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3623 const uint32_t* _frm_nxt = _frm;
3624 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3625 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3626 uint8_t* _to_nxt = _to;
3627 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3628 _Maxcode_, _Mode_);
3629 frm_nxt = frm + (_frm_nxt - _frm);
3630 to_nxt = to + (_to_nxt - _to);
3631 return r;
3632}
3633
3634__codecvt_utf16<char32_t, false>::result
3635__codecvt_utf16<char32_t, false>::do_in(state_type&,
3636 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3637 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3638{
3639 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3640 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3641 const uint8_t* _frm_nxt = _frm;
3642 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3643 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3644 uint32_t* _to_nxt = _to;
3645 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3646 _Maxcode_, _Mode_);
3647 frm_nxt = frm + (_frm_nxt - _frm);
3648 to_nxt = to + (_to_nxt - _to);
3649 return r;
3650}
3651
3652__codecvt_utf16<char32_t, false>::result
3653__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3654 extern_type* to, extern_type*, extern_type*& to_nxt) const
3655{
3656 to_nxt = to;
3657 return noconv;
3658}
3659
3660int
Howard Hinnantc9834542011-05-31 15:34:58 +00003661__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003662{
3663 return 0;
3664}
3665
3666bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003667__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003668{
3669 return false;
3670}
3671
3672int
3673__codecvt_utf16<char32_t, false>::do_length(state_type&,
3674 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3675{
3676 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3677 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3678 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3679}
3680
3681int
Howard Hinnantc9834542011-05-31 15:34:58 +00003682__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003683{
3684 if (_Mode_ & consume_header)
3685 return 6;
3686 return 4;
3687}
3688
3689// __codecvt_utf16<char32_t, true>
3690
3691__codecvt_utf16<char32_t, true>::result
3692__codecvt_utf16<char32_t, true>::do_out(state_type&,
3693 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3694 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3695{
3696 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3697 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3698 const uint32_t* _frm_nxt = _frm;
3699 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3700 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3701 uint8_t* _to_nxt = _to;
3702 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3703 _Maxcode_, _Mode_);
3704 frm_nxt = frm + (_frm_nxt - _frm);
3705 to_nxt = to + (_to_nxt - _to);
3706 return r;
3707}
3708
3709__codecvt_utf16<char32_t, true>::result
3710__codecvt_utf16<char32_t, true>::do_in(state_type&,
3711 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3712 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3713{
3714 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3715 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3716 const uint8_t* _frm_nxt = _frm;
3717 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3718 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3719 uint32_t* _to_nxt = _to;
3720 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3721 _Maxcode_, _Mode_);
3722 frm_nxt = frm + (_frm_nxt - _frm);
3723 to_nxt = to + (_to_nxt - _to);
3724 return r;
3725}
3726
3727__codecvt_utf16<char32_t, true>::result
3728__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3729 extern_type* to, extern_type*, extern_type*& to_nxt) const
3730{
3731 to_nxt = to;
3732 return noconv;
3733}
3734
3735int
Howard Hinnantc9834542011-05-31 15:34:58 +00003736__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003737{
3738 return 0;
3739}
3740
3741bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003742__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003743{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003744 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003745}
3746
3747int
3748__codecvt_utf16<char32_t, true>::do_length(state_type&,
3749 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3750{
3751 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3752 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3753 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3754}
3755
3756int
Howard Hinnantc9834542011-05-31 15:34:58 +00003757__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003758{
3759 if (_Mode_ & consume_header)
3760 return 6;
3761 return 4;
3762}
3763
3764// __codecvt_utf8_utf16<wchar_t>
3765
3766__codecvt_utf8_utf16<wchar_t>::result
3767__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3768 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3769 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3770{
3771 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3772 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3773 const uint32_t* _frm_nxt = _frm;
3774 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3775 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3776 uint8_t* _to_nxt = _to;
3777 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3778 _Maxcode_, _Mode_);
3779 frm_nxt = frm + (_frm_nxt - _frm);
3780 to_nxt = to + (_to_nxt - _to);
3781 return r;
3782}
3783
3784__codecvt_utf8_utf16<wchar_t>::result
3785__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3786 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3787 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3788{
3789 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3790 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3791 const uint8_t* _frm_nxt = _frm;
3792 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3793 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3794 uint32_t* _to_nxt = _to;
3795 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3796 _Maxcode_, _Mode_);
3797 frm_nxt = frm + (_frm_nxt - _frm);
3798 to_nxt = to + (_to_nxt - _to);
3799 return r;
3800}
3801
3802__codecvt_utf8_utf16<wchar_t>::result
3803__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3804 extern_type* to, extern_type*, extern_type*& to_nxt) const
3805{
3806 to_nxt = to;
3807 return noconv;
3808}
3809
3810int
Howard Hinnantc9834542011-05-31 15:34:58 +00003811__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003812{
3813 return 0;
3814}
3815
3816bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003817__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003818{
3819 return false;
3820}
3821
3822int
3823__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3824 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3825{
3826 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3827 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3828 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3829}
3830
3831int
Howard Hinnantc9834542011-05-31 15:34:58 +00003832__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003833{
3834 if (_Mode_ & consume_header)
3835 return 7;
3836 return 4;
3837}
3838
3839// __codecvt_utf8_utf16<char16_t>
3840
3841__codecvt_utf8_utf16<char16_t>::result
3842__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3843 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3844 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3845{
3846 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3847 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3848 const uint16_t* _frm_nxt = _frm;
3849 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3850 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3851 uint8_t* _to_nxt = _to;
3852 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3853 _Maxcode_, _Mode_);
3854 frm_nxt = frm + (_frm_nxt - _frm);
3855 to_nxt = to + (_to_nxt - _to);
3856 return r;
3857}
3858
3859__codecvt_utf8_utf16<char16_t>::result
3860__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3861 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3862 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3863{
3864 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3865 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3866 const uint8_t* _frm_nxt = _frm;
3867 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3868 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3869 uint16_t* _to_nxt = _to;
3870 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3871 _Maxcode_, _Mode_);
3872 frm_nxt = frm + (_frm_nxt - _frm);
3873 to_nxt = to + (_to_nxt - _to);
3874 return r;
3875}
3876
3877__codecvt_utf8_utf16<char16_t>::result
3878__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3879 extern_type* to, extern_type*, extern_type*& to_nxt) const
3880{
3881 to_nxt = to;
3882 return noconv;
3883}
3884
3885int
Howard Hinnantc9834542011-05-31 15:34:58 +00003886__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003887{
3888 return 0;
3889}
3890
3891bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003892__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003893{
3894 return false;
3895}
3896
3897int
3898__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3899 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3900{
3901 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3902 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3903 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3904}
3905
3906int
Howard Hinnantc9834542011-05-31 15:34:58 +00003907__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003908{
3909 if (_Mode_ & consume_header)
3910 return 7;
3911 return 4;
3912}
3913
3914// __codecvt_utf8_utf16<char32_t>
3915
3916__codecvt_utf8_utf16<char32_t>::result
3917__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3918 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3919 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3920{
3921 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3922 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3923 const uint32_t* _frm_nxt = _frm;
3924 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3925 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3926 uint8_t* _to_nxt = _to;
3927 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3928 _Maxcode_, _Mode_);
3929 frm_nxt = frm + (_frm_nxt - _frm);
3930 to_nxt = to + (_to_nxt - _to);
3931 return r;
3932}
3933
3934__codecvt_utf8_utf16<char32_t>::result
3935__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3936 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3937 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3938{
3939 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3940 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3941 const uint8_t* _frm_nxt = _frm;
3942 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3943 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3944 uint32_t* _to_nxt = _to;
3945 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3946 _Maxcode_, _Mode_);
3947 frm_nxt = frm + (_frm_nxt - _frm);
3948 to_nxt = to + (_to_nxt - _to);
3949 return r;
3950}
3951
3952__codecvt_utf8_utf16<char32_t>::result
3953__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3954 extern_type* to, extern_type*, extern_type*& to_nxt) const
3955{
3956 to_nxt = to;
3957 return noconv;
3958}
3959
3960int
Howard Hinnantc9834542011-05-31 15:34:58 +00003961__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003962{
3963 return 0;
3964}
3965
3966bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003967__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003968{
3969 return false;
3970}
3971
3972int
3973__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3974 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3975{
3976 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3977 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3978 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3979}
3980
3981int
Howard Hinnantc9834542011-05-31 15:34:58 +00003982__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003983{
3984 if (_Mode_ & consume_header)
3985 return 7;
3986 return 4;
3987}
3988
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003989// __narrow_to_utf8<16>
3990
3991__narrow_to_utf8<16>::~__narrow_to_utf8()
3992{
3993}
3994
3995// __narrow_to_utf8<32>
3996
3997__narrow_to_utf8<32>::~__narrow_to_utf8()
3998{
3999}
4000
4001// __widen_from_utf8<16>
4002
4003__widen_from_utf8<16>::~__widen_from_utf8()
4004{
4005}
4006
4007// __widen_from_utf8<32>
4008
4009__widen_from_utf8<32>::~__widen_from_utf8()
4010{
4011}
4012
4013// numpunct<char> && numpunct<wchar_t>
4014
4015locale::id numpunct< char >::id;
4016locale::id numpunct<wchar_t>::id;
4017
4018numpunct<char>::numpunct(size_t refs)
4019 : locale::facet(refs),
4020 __decimal_point_('.'),
4021 __thousands_sep_(',')
4022{
4023}
4024
4025numpunct<wchar_t>::numpunct(size_t refs)
4026 : locale::facet(refs),
4027 __decimal_point_(L'.'),
4028 __thousands_sep_(L',')
4029{
4030}
4031
4032numpunct<char>::~numpunct()
4033{
4034}
4035
4036numpunct<wchar_t>::~numpunct()
4037{
4038}
4039
4040 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4041wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4042
4043 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4044wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4045
4046string numpunct< char >::do_grouping() const {return __grouping_;}
4047string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4048
4049 string numpunct< char >::do_truename() const {return "true";}
4050wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4051
4052 string numpunct< char >::do_falsename() const {return "false";}
4053wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4054
4055// numpunct_byname<char>
4056
4057numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4058 : numpunct<char>(refs)
4059{
4060 __init(nm);
4061}
4062
4063numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4064 : numpunct<char>(refs)
4065{
4066 __init(nm.c_str());
4067}
4068
4069numpunct_byname<char>::~numpunct_byname()
4070{
4071}
4072
4073void
4074numpunct_byname<char>::__init(const char* nm)
4075{
4076 if (strcmp(nm, "C") != 0)
4077 {
Sean Huntf3907e62011-07-15 05:40:33 +00004078 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004079#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004080 if (loc == 0)
4081 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4082 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004083#endif // _LIBCPP_NO_EXCEPTIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004084#ifdef _LIBCPP_STABLE_APPLE_ABI
4085 lconv* lc = localeconv_l(loc.get());
4086#else
4087 lconv* lc = __localeconv_l(loc.get());
4088#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004089 if (*lc->decimal_point)
4090 __decimal_point_ = *lc->decimal_point;
4091 if (*lc->thousands_sep)
4092 __thousands_sep_ = *lc->thousands_sep;
4093 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004094 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004095 }
4096}
4097
4098// numpunct_byname<wchar_t>
4099
4100numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4101 : numpunct<wchar_t>(refs)
4102{
4103 __init(nm);
4104}
4105
4106numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4107 : numpunct<wchar_t>(refs)
4108{
4109 __init(nm.c_str());
4110}
4111
4112numpunct_byname<wchar_t>::~numpunct_byname()
4113{
4114}
4115
4116void
4117numpunct_byname<wchar_t>::__init(const char* nm)
4118{
4119 if (strcmp(nm, "C") != 0)
4120 {
Sean Huntf3907e62011-07-15 05:40:33 +00004121 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004122#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004123 if (loc == 0)
4124 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4125 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004126#endif // _LIBCPP_NO_EXCEPTIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004127#ifdef _LIBCPP_STABLE_APPLE_ABI
4128 lconv* lc = localeconv_l(loc.get());
4129#else
4130 lconv* lc = __localeconv_l(loc.get());
4131#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004132 if (*lc->decimal_point)
4133 __decimal_point_ = *lc->decimal_point;
4134 if (*lc->thousands_sep)
4135 __thousands_sep_ = *lc->thousands_sep;
4136 __grouping_ = lc->grouping;
4137 // locallization for truename and falsename is not available
4138 }
4139}
4140
4141// num_get helpers
4142
4143int
4144__num_get_base::__get_base(ios_base& iob)
4145{
4146 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4147 if (__basefield == ios_base::oct)
4148 return 8;
4149 else if (__basefield == ios_base::hex)
4150 return 16;
4151 else if (__basefield == 0)
4152 return 0;
4153 return 10;
4154}
4155
4156const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4157
4158void
4159__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4160 ios_base::iostate& __err)
4161{
4162 if (__grouping.size() != 0)
4163 {
4164 reverse(__g, __g_end);
4165 const char* __ig = __grouping.data();
4166 const char* __eg = __ig + __grouping.size();
4167 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4168 {
4169 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4170 {
4171 if (*__ig != *__r)
4172 {
4173 __err = ios_base::failbit;
4174 return;
4175 }
4176 }
4177 if (__eg - __ig > 1)
4178 ++__ig;
4179 }
4180 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4181 {
4182 if (*__ig < __g_end[-1] || __g_end[-1] == 0)
4183 __err = ios_base::failbit;
4184 }
4185 }
4186}
4187
4188void
4189__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4190 ios_base::fmtflags __flags)
4191{
4192 if (__flags & ios_base::showpos)
4193 *__fmtp++ = '+';
4194 if (__flags & ios_base::showbase)
4195 *__fmtp++ = '#';
4196 while(*__len)
4197 *__fmtp++ = *__len++;
4198 if ((__flags & ios_base::basefield) == ios_base::oct)
4199 *__fmtp = 'o';
4200 else if ((__flags & ios_base::basefield) == ios_base::hex)
4201 {
4202 if (__flags & ios_base::uppercase)
4203 *__fmtp = 'X';
4204 else
4205 *__fmtp = 'x';
4206 }
4207 else if (__signd)
4208 *__fmtp = 'd';
4209 else
4210 *__fmtp = 'u';
4211}
4212
4213bool
4214__num_put_base::__format_float(char* __fmtp, const char* __len,
4215 ios_base::fmtflags __flags)
4216{
4217 bool specify_precision = true;
4218 if (__flags & ios_base::showpos)
4219 *__fmtp++ = '+';
4220 if (__flags & ios_base::showpoint)
4221 *__fmtp++ = '#';
4222 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4223 bool uppercase = __flags & ios_base::uppercase;
4224 if (floatfield == (ios_base::fixed | ios_base::scientific))
4225 specify_precision = false;
4226 else
4227 {
4228 *__fmtp++ = '.';
4229 *__fmtp++ = '*';
4230 }
4231 while(*__len)
4232 *__fmtp++ = *__len++;
4233 if (floatfield == ios_base::fixed)
4234 {
4235 if (uppercase)
4236 *__fmtp = 'F';
4237 else
4238 *__fmtp = 'f';
4239 }
4240 else if (floatfield == ios_base::scientific)
4241 {
4242 if (uppercase)
4243 *__fmtp = 'E';
4244 else
4245 *__fmtp = 'e';
4246 }
4247 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4248 {
4249 if (uppercase)
4250 *__fmtp = 'A';
4251 else
4252 *__fmtp = 'a';
4253 }
4254 else
4255 {
4256 if (uppercase)
4257 *__fmtp = 'G';
4258 else
4259 *__fmtp = 'g';
4260 }
4261 return specify_precision;
4262}
4263
4264char*
4265__num_put_base::__identify_padding(char* __nb, char* __ne,
4266 const ios_base& __iob)
4267{
4268 switch (__iob.flags() & ios_base::adjustfield)
4269 {
4270 case ios_base::internal:
4271 if (__nb[0] == '-' || __nb[0] == '+')
4272 return __nb+1;
4273 if (__ne - __nb >= 2 && __nb[0] == '0'
4274 && (__nb[1] == 'x' || __nb[1] == 'X'))
4275 return __nb+2;
4276 break;
4277 case ios_base::left:
4278 return __ne;
4279 case ios_base::right:
4280 default:
4281 break;
4282 }
4283 return __nb;
4284}
4285
4286// time_get
4287
4288static
4289string*
4290init_weeks()
4291{
4292 static string weeks[14];
4293 weeks[0] = "Sunday";
4294 weeks[1] = "Monday";
4295 weeks[2] = "Tuesday";
4296 weeks[3] = "Wednesday";
4297 weeks[4] = "Thursday";
4298 weeks[5] = "Friday";
4299 weeks[6] = "Saturday";
4300 weeks[7] = "Sun";
4301 weeks[8] = "Mon";
4302 weeks[9] = "Tue";
4303 weeks[10] = "Wed";
4304 weeks[11] = "Thu";
4305 weeks[12] = "Fri";
4306 weeks[13] = "Sat";
4307 return weeks;
4308}
4309
4310static
4311wstring*
4312init_wweeks()
4313{
4314 static wstring weeks[14];
4315 weeks[0] = L"Sunday";
4316 weeks[1] = L"Monday";
4317 weeks[2] = L"Tuesday";
4318 weeks[3] = L"Wednesday";
4319 weeks[4] = L"Thursday";
4320 weeks[5] = L"Friday";
4321 weeks[6] = L"Saturday";
4322 weeks[7] = L"Sun";
4323 weeks[8] = L"Mon";
4324 weeks[9] = L"Tue";
4325 weeks[10] = L"Wed";
4326 weeks[11] = L"Thu";
4327 weeks[12] = L"Fri";
4328 weeks[13] = L"Sat";
4329 return weeks;
4330}
4331
4332template <>
4333const string*
4334__time_get_c_storage<char>::__weeks() const
4335{
4336 static const string* weeks = init_weeks();
4337 return weeks;
4338}
4339
4340template <>
4341const wstring*
4342__time_get_c_storage<wchar_t>::__weeks() const
4343{
4344 static const wstring* weeks = init_wweeks();
4345 return weeks;
4346}
4347
4348static
4349string*
4350init_months()
4351{
4352 static string months[24];
4353 months[0] = "January";
4354 months[1] = "February";
4355 months[2] = "March";
4356 months[3] = "April";
4357 months[4] = "May";
4358 months[5] = "June";
4359 months[6] = "July";
4360 months[7] = "August";
4361 months[8] = "September";
4362 months[9] = "October";
4363 months[10] = "November";
4364 months[11] = "December";
4365 months[12] = "Jan";
4366 months[13] = "Feb";
4367 months[14] = "Mar";
4368 months[15] = "Apr";
4369 months[16] = "May";
4370 months[17] = "Jun";
4371 months[18] = "Jul";
4372 months[19] = "Aug";
4373 months[20] = "Sep";
4374 months[21] = "Oct";
4375 months[22] = "Nov";
4376 months[23] = "Dec";
4377 return months;
4378}
4379
4380static
4381wstring*
4382init_wmonths()
4383{
4384 static wstring months[24];
4385 months[0] = L"January";
4386 months[1] = L"February";
4387 months[2] = L"March";
4388 months[3] = L"April";
4389 months[4] = L"May";
4390 months[5] = L"June";
4391 months[6] = L"July";
4392 months[7] = L"August";
4393 months[8] = L"September";
4394 months[9] = L"October";
4395 months[10] = L"November";
4396 months[11] = L"December";
4397 months[12] = L"Jan";
4398 months[13] = L"Feb";
4399 months[14] = L"Mar";
4400 months[15] = L"Apr";
4401 months[16] = L"May";
4402 months[17] = L"Jun";
4403 months[18] = L"Jul";
4404 months[19] = L"Aug";
4405 months[20] = L"Sep";
4406 months[21] = L"Oct";
4407 months[22] = L"Nov";
4408 months[23] = L"Dec";
4409 return months;
4410}
4411
4412template <>
4413const string*
4414__time_get_c_storage<char>::__months() const
4415{
4416 static const string* months = init_months();
4417 return months;
4418}
4419
4420template <>
4421const wstring*
4422__time_get_c_storage<wchar_t>::__months() const
4423{
4424 static const wstring* months = init_wmonths();
4425 return months;
4426}
4427
4428static
4429string*
4430init_am_pm()
4431{
4432 static string am_pm[24];
4433 am_pm[0] = "AM";
4434 am_pm[1] = "PM";
4435 return am_pm;
4436}
4437
4438static
4439wstring*
4440init_wam_pm()
4441{
4442 static wstring am_pm[24];
4443 am_pm[0] = L"AM";
4444 am_pm[1] = L"PM";
4445 return am_pm;
4446}
4447
4448template <>
4449const string*
4450__time_get_c_storage<char>::__am_pm() const
4451{
4452 static const string* am_pm = init_am_pm();
4453 return am_pm;
4454}
4455
4456template <>
4457const wstring*
4458__time_get_c_storage<wchar_t>::__am_pm() const
4459{
4460 static const wstring* am_pm = init_wam_pm();
4461 return am_pm;
4462}
4463
4464template <>
4465const string&
4466__time_get_c_storage<char>::__x() const
4467{
4468 static string s("%m/%d/%y");
4469 return s;
4470}
4471
4472template <>
4473const wstring&
4474__time_get_c_storage<wchar_t>::__x() const
4475{
4476 static wstring s(L"%m/%d/%y");
4477 return s;
4478}
4479
4480template <>
4481const string&
4482__time_get_c_storage<char>::__X() const
4483{
4484 static string s("%H:%M:%S");
4485 return s;
4486}
4487
4488template <>
4489const wstring&
4490__time_get_c_storage<wchar_t>::__X() const
4491{
4492 static wstring s(L"%H:%M:%S");
4493 return s;
4494}
4495
4496template <>
4497const string&
4498__time_get_c_storage<char>::__c() const
4499{
4500 static string s("%a %b %d %H:%M:%S %Y");
4501 return s;
4502}
4503
4504template <>
4505const wstring&
4506__time_get_c_storage<wchar_t>::__c() const
4507{
4508 static wstring s(L"%a %b %d %H:%M:%S %Y");
4509 return s;
4510}
4511
4512template <>
4513const string&
4514__time_get_c_storage<char>::__r() const
4515{
4516 static string s("%I:%M:%S %p");
4517 return s;
4518}
4519
4520template <>
4521const wstring&
4522__time_get_c_storage<wchar_t>::__r() const
4523{
4524 static wstring s(L"%I:%M:%S %p");
4525 return s;
4526}
4527
4528// time_get_byname
4529
4530__time_get::__time_get(const char* nm)
4531 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4532{
Howard Hinnantd4444702010-08-11 17:04:31 +00004533#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004534 if (__loc_ == 0)
4535 throw runtime_error("time_get_byname"
4536 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004537#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004538}
4539
4540__time_get::__time_get(const string& nm)
4541 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4542{
Howard Hinnantd4444702010-08-11 17:04:31 +00004543#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004544 if (__loc_ == 0)
4545 throw runtime_error("time_get_byname"
4546 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004547#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004548}
4549
4550__time_get::~__time_get()
4551{
4552 freelocale(__loc_);
4553}
4554
4555template <>
4556string
4557__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4558{
4559 tm t;
4560 t.tm_sec = 59;
4561 t.tm_min = 55;
4562 t.tm_hour = 23;
4563 t.tm_mday = 31;
4564 t.tm_mon = 11;
4565 t.tm_year = 161;
4566 t.tm_wday = 6;
4567 t.tm_yday = 364;
4568 t.tm_isdst = -1;
4569 char buf[100];
4570 char f[3] = {0};
4571 f[0] = '%';
4572 f[1] = fmt;
4573 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4574 char* bb = buf;
4575 char* be = buf + n;
4576 string result;
4577 while (bb != be)
4578 {
4579 if (ct.is(ctype_base::space, *bb))
4580 {
4581 result.push_back(' ');
4582 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4583 ;
4584 continue;
4585 }
4586 char* w = bb;
4587 ios_base::iostate err = ios_base::goodbit;
4588 int i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4589 ct, err, false)
4590 - this->__weeks_;
4591 if (i < 14)
4592 {
4593 result.push_back('%');
4594 if (i < 7)
4595 result.push_back('A');
4596 else
4597 result.push_back('a');
4598 bb = w;
4599 continue;
4600 }
4601 w = bb;
4602 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4603 ct, err, false)
4604 - this->__months_;
4605 if (i < 24)
4606 {
4607 result.push_back('%');
4608 if (i < 12)
4609 result.push_back('B');
4610 else
4611 result.push_back('b');
4612 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4613 result.back() = 'm';
4614 bb = w;
4615 continue;
4616 }
4617 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4618 {
4619 w = bb;
4620 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4621 ct, err, false) - this->__am_pm_;
4622 if (i < 2)
4623 {
4624 result.push_back('%');
4625 result.push_back('p');
4626 bb = w;
4627 continue;
4628 }
4629 }
4630 w = bb;
4631 if (ct.is(ctype_base::digit, *bb))
4632 {
4633 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4634 {
4635 case 6:
4636 result.push_back('%');
4637 result.push_back('w');
4638 break;
4639 case 7:
4640 result.push_back('%');
4641 result.push_back('u');
4642 break;
4643 case 11:
4644 result.push_back('%');
4645 result.push_back('I');
4646 break;
4647 case 12:
4648 result.push_back('%');
4649 result.push_back('m');
4650 break;
4651 case 23:
4652 result.push_back('%');
4653 result.push_back('H');
4654 break;
4655 case 31:
4656 result.push_back('%');
4657 result.push_back('d');
4658 break;
4659 case 55:
4660 result.push_back('%');
4661 result.push_back('M');
4662 break;
4663 case 59:
4664 result.push_back('%');
4665 result.push_back('S');
4666 break;
4667 case 61:
4668 result.push_back('%');
4669 result.push_back('y');
4670 break;
4671 case 364:
4672 result.push_back('%');
4673 result.push_back('j');
4674 break;
4675 case 2061:
4676 result.push_back('%');
4677 result.push_back('Y');
4678 break;
4679 default:
4680 for (; w != bb; ++w)
4681 result.push_back(*w);
4682 break;
4683 }
4684 continue;
4685 }
4686 if (*bb == '%')
4687 {
4688 result.push_back('%');
4689 result.push_back('%');
4690 ++bb;
4691 continue;
4692 }
4693 result.push_back(*bb);
4694 ++bb;
4695 }
4696 return result;
4697}
4698
4699template <>
4700wstring
4701__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4702{
4703 tm t;
4704 t.tm_sec = 59;
4705 t.tm_min = 55;
4706 t.tm_hour = 23;
4707 t.tm_mday = 31;
4708 t.tm_mon = 11;
4709 t.tm_year = 161;
4710 t.tm_wday = 6;
4711 t.tm_yday = 364;
4712 t.tm_isdst = -1;
4713 char buf[100];
4714 char f[3] = {0};
4715 f[0] = '%';
4716 f[1] = fmt;
4717 size_t be = strftime_l(buf, 100, f, &t, __loc_);
4718 wchar_t wbuf[100];
4719 wchar_t* wbb = wbuf;
4720 mbstate_t mb = {0};
4721 const char* bb = buf;
Sean Huntf3907e62011-07-15 05:40:33 +00004722#ifdef _LIBCPP_STABLE_APPLE_ABI
4723 size_t i = mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4724#else
4725 size_t i = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4726#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004727 if (i == -1)
4728 __throw_runtime_error("locale not supported");
4729 wchar_t* wbe = wbb + i;
4730 wstring result;
4731 while (wbb != wbe)
4732 {
4733 if (ct.is(ctype_base::space, *wbb))
4734 {
4735 result.push_back(L' ');
4736 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4737 ;
4738 continue;
4739 }
4740 wchar_t* w = wbb;
4741 ios_base::iostate err = ios_base::goodbit;
4742 int i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4743 ct, err, false)
4744 - this->__weeks_;
4745 if (i < 14)
4746 {
4747 result.push_back(L'%');
4748 if (i < 7)
4749 result.push_back(L'A');
4750 else
4751 result.push_back(L'a');
4752 wbb = w;
4753 continue;
4754 }
4755 w = wbb;
4756 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4757 ct, err, false)
4758 - this->__months_;
4759 if (i < 24)
4760 {
4761 result.push_back(L'%');
4762 if (i < 12)
4763 result.push_back(L'B');
4764 else
4765 result.push_back(L'b');
4766 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4767 result.back() = L'm';
4768 wbb = w;
4769 continue;
4770 }
4771 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4772 {
4773 w = wbb;
4774 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4775 ct, err, false) - this->__am_pm_;
4776 if (i < 2)
4777 {
4778 result.push_back(L'%');
4779 result.push_back(L'p');
4780 wbb = w;
4781 continue;
4782 }
4783 }
4784 w = wbb;
4785 if (ct.is(ctype_base::digit, *wbb))
4786 {
4787 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4788 {
4789 case 6:
4790 result.push_back(L'%');
4791 result.push_back(L'w');
4792 break;
4793 case 7:
4794 result.push_back(L'%');
4795 result.push_back(L'u');
4796 break;
4797 case 11:
4798 result.push_back(L'%');
4799 result.push_back(L'I');
4800 break;
4801 case 12:
4802 result.push_back(L'%');
4803 result.push_back(L'm');
4804 break;
4805 case 23:
4806 result.push_back(L'%');
4807 result.push_back(L'H');
4808 break;
4809 case 31:
4810 result.push_back(L'%');
4811 result.push_back(L'd');
4812 break;
4813 case 55:
4814 result.push_back(L'%');
4815 result.push_back(L'M');
4816 break;
4817 case 59:
4818 result.push_back(L'%');
4819 result.push_back(L'S');
4820 break;
4821 case 61:
4822 result.push_back(L'%');
4823 result.push_back(L'y');
4824 break;
4825 case 364:
4826 result.push_back(L'%');
4827 result.push_back(L'j');
4828 break;
4829 case 2061:
4830 result.push_back(L'%');
4831 result.push_back(L'Y');
4832 break;
4833 default:
4834 for (; w != wbb; ++w)
4835 result.push_back(*w);
4836 break;
4837 }
4838 continue;
4839 }
4840 if (ct.narrow(*wbb, 0) == '%')
4841 {
4842 result.push_back(L'%');
4843 result.push_back(L'%');
4844 ++wbb;
4845 continue;
4846 }
4847 result.push_back(*wbb);
4848 ++wbb;
4849 }
4850 return result;
4851}
4852
4853template <>
4854void
4855__time_get_storage<char>::init(const ctype<char>& ct)
4856{
4857 tm t;
4858 char buf[100];
4859 // __weeks_
4860 for (int i = 0; i < 7; ++i)
4861 {
4862 t.tm_wday = i;
4863 strftime_l(buf, 100, "%A", &t, __loc_);
4864 __weeks_[i] = buf;
4865 strftime_l(buf, 100, "%a", &t, __loc_);
4866 __weeks_[i+7] = buf;
4867 }
4868 // __months_
4869 for (int i = 0; i < 12; ++i)
4870 {
4871 t.tm_mon = i;
4872 strftime_l(buf, 100, "%B", &t, __loc_);
4873 __months_[i] = buf;
4874 strftime_l(buf, 100, "%b", &t, __loc_);
4875 __months_[i+12] = buf;
4876 }
4877 // __am_pm_
4878 t.tm_hour = 1;
4879 strftime_l(buf, 100, "%p", &t, __loc_);
4880 __am_pm_[0] = buf;
4881 t.tm_hour = 13;
4882 strftime_l(buf, 100, "%p", &t, __loc_);
4883 __am_pm_[1] = buf;
4884 __c_ = __analyze('c', ct);
4885 __r_ = __analyze('r', ct);
4886 __x_ = __analyze('x', ct);
4887 __X_ = __analyze('X', ct);
4888}
4889
4890template <>
4891void
4892__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4893{
4894 tm t = {0};
4895 char buf[100];
4896 size_t be;
4897 wchar_t wbuf[100];
4898 wchar_t* wbe;
4899 mbstate_t mb = {0};
4900 // __weeks_
4901 for (int i = 0; i < 7; ++i)
4902 {
4903 t.tm_wday = i;
4904 be = strftime_l(buf, 100, "%A", &t, __loc_);
4905 mb = mbstate_t();
4906 const char* bb = buf;
Sean Huntf3907e62011-07-15 05:40:33 +00004907#ifdef _LIBCPP_STABLE_APPLE_ABI
4908 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4909#else
4910 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4911#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004912 if (j == -1)
4913 __throw_runtime_error("locale not supported");
4914 wbe = wbuf + j;
4915 __weeks_[i].assign(wbuf, wbe);
4916 be = strftime_l(buf, 100, "%a", &t, __loc_);
4917 mb = mbstate_t();
4918 bb = buf;
Sean Huntf3907e62011-07-15 05:40:33 +00004919#ifdef _LIBCPP_STABLE_APPLE_ABI
4920 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4921#else
4922 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4923#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004924 if (j == -1)
4925 __throw_runtime_error("locale not supported");
4926 wbe = wbuf + j;
4927 __weeks_[i+7].assign(wbuf, wbe);
4928 }
4929 // __months_
4930 for (int i = 0; i < 12; ++i)
4931 {
4932 t.tm_mon = i;
4933 be = strftime_l(buf, 100, "%B", &t, __loc_);
4934 mb = mbstate_t();
4935 const char* bb = buf;
Sean Huntf3907e62011-07-15 05:40:33 +00004936#ifdef _LIBCPP_STABLE_APPLE_ABI
4937 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4938#else
4939 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4940#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004941 if (j == -1)
4942 __throw_runtime_error("locale not supported");
4943 wbe = wbuf + j;
4944 __months_[i].assign(wbuf, wbe);
4945 be = strftime_l(buf, 100, "%b", &t, __loc_);
4946 mb = mbstate_t();
4947 bb = buf;
Sean Huntf3907e62011-07-15 05:40:33 +00004948#ifdef _LIBCPP_STABLE_APPLE_ABI
4949 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4950#else
4951 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4952#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004953 if (j == -1)
4954 __throw_runtime_error("locale not supported");
4955 wbe = wbuf + j;
4956 __months_[i+12].assign(wbuf, wbe);
4957 }
4958 // __am_pm_
4959 t.tm_hour = 1;
4960 be = strftime_l(buf, 100, "%p", &t, __loc_);
4961 mb = mbstate_t();
4962 const char* bb = buf;
Sean Huntf3907e62011-07-15 05:40:33 +00004963#ifdef _LIBCPP_STABLE_APPLE_ABI
4964 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4965#else
4966 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4967#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004968 if (j == -1)
4969 __throw_runtime_error("locale not supported");
4970 wbe = wbuf + j;
4971 __am_pm_[0].assign(wbuf, wbe);
4972 t.tm_hour = 13;
4973 be = strftime_l(buf, 100, "%p", &t, __loc_);
4974 mb = mbstate_t();
4975 bb = buf;
Sean Huntf3907e62011-07-15 05:40:33 +00004976#ifdef _LIBCPP_STABLE_APPLE_ABI
4977 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4978#else
4979 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4980#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004981 if (j == -1)
4982 __throw_runtime_error("locale not supported");
4983 wbe = wbuf + j;
4984 __am_pm_[1].assign(wbuf, wbe);
4985 __c_ = __analyze('c', ct);
4986 __r_ = __analyze('r', ct);
4987 __x_ = __analyze('x', ct);
4988 __X_ = __analyze('X', ct);
4989}
4990
4991template <class CharT>
4992struct _LIBCPP_HIDDEN __time_get_temp
4993 : public ctype_byname<CharT>
4994{
4995 explicit __time_get_temp(const char* nm)
4996 : ctype_byname<CharT>(nm, 1) {}
4997 explicit __time_get_temp(const string& nm)
4998 : ctype_byname<CharT>(nm, 1) {}
4999};
5000
5001template <>
5002__time_get_storage<char>::__time_get_storage(const char* __nm)
5003 : __time_get(__nm)
5004{
5005 const __time_get_temp<char> ct(__nm);
5006 init(ct);
5007}
5008
5009template <>
5010__time_get_storage<char>::__time_get_storage(const string& __nm)
5011 : __time_get(__nm)
5012{
5013 const __time_get_temp<char> ct(__nm);
5014 init(ct);
5015}
5016
5017template <>
5018__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5019 : __time_get(__nm)
5020{
5021 const __time_get_temp<wchar_t> ct(__nm);
5022 init(ct);
5023}
5024
5025template <>
5026__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5027 : __time_get(__nm)
5028{
5029 const __time_get_temp<wchar_t> ct(__nm);
5030 init(ct);
5031}
5032
5033template <>
5034time_base::dateorder
5035__time_get_storage<char>::__do_date_order() const
5036{
5037 unsigned i;
5038 for (i = 0; i < __x_.size(); ++i)
5039 if (__x_[i] == '%')
5040 break;
5041 ++i;
5042 switch (__x_[i])
5043 {
5044 case 'y':
5045 case 'Y':
5046 for (++i; i < __x_.size(); ++i)
5047 if (__x_[i] == '%')
5048 break;
5049 if (i == __x_.size())
5050 break;
5051 ++i;
5052 switch (__x_[i])
5053 {
5054 case 'm':
5055 for (++i; i < __x_.size(); ++i)
5056 if (__x_[i] == '%')
5057 break;
5058 if (i == __x_.size())
5059 break;
5060 ++i;
5061 if (__x_[i] == 'd')
5062 return time_base::ymd;
5063 break;
5064 case 'd':
5065 for (++i; i < __x_.size(); ++i)
5066 if (__x_[i] == '%')
5067 break;
5068 if (i == __x_.size())
5069 break;
5070 ++i;
5071 if (__x_[i] == 'm')
5072 return time_base::ydm;
5073 break;
5074 }
5075 break;
5076 case 'm':
5077 for (++i; i < __x_.size(); ++i)
5078 if (__x_[i] == '%')
5079 break;
5080 if (i == __x_.size())
5081 break;
5082 ++i;
5083 if (__x_[i] == 'd')
5084 {
5085 for (++i; i < __x_.size(); ++i)
5086 if (__x_[i] == '%')
5087 break;
5088 if (i == __x_.size())
5089 break;
5090 ++i;
5091 if (__x_[i] == 'y' || __x_[i] == 'Y')
5092 return time_base::mdy;
5093 break;
5094 }
5095 break;
5096 case 'd':
5097 for (++i; i < __x_.size(); ++i)
5098 if (__x_[i] == '%')
5099 break;
5100 if (i == __x_.size())
5101 break;
5102 ++i;
5103 if (__x_[i] == 'm')
5104 {
5105 for (++i; i < __x_.size(); ++i)
5106 if (__x_[i] == '%')
5107 break;
5108 if (i == __x_.size())
5109 break;
5110 ++i;
5111 if (__x_[i] == 'y' || __x_[i] == 'Y')
5112 return time_base::dmy;
5113 break;
5114 }
5115 break;
5116 }
5117 return time_base::no_order;
5118}
5119
5120template <>
5121time_base::dateorder
5122__time_get_storage<wchar_t>::__do_date_order() const
5123{
5124 unsigned i;
5125 for (i = 0; i < __x_.size(); ++i)
5126 if (__x_[i] == L'%')
5127 break;
5128 ++i;
5129 switch (__x_[i])
5130 {
5131 case L'y':
5132 case L'Y':
5133 for (++i; i < __x_.size(); ++i)
5134 if (__x_[i] == L'%')
5135 break;
5136 if (i == __x_.size())
5137 break;
5138 ++i;
5139 switch (__x_[i])
5140 {
5141 case L'm':
5142 for (++i; i < __x_.size(); ++i)
5143 if (__x_[i] == L'%')
5144 break;
5145 if (i == __x_.size())
5146 break;
5147 ++i;
5148 if (__x_[i] == L'd')
5149 return time_base::ymd;
5150 break;
5151 case L'd':
5152 for (++i; i < __x_.size(); ++i)
5153 if (__x_[i] == L'%')
5154 break;
5155 if (i == __x_.size())
5156 break;
5157 ++i;
5158 if (__x_[i] == L'm')
5159 return time_base::ydm;
5160 break;
5161 }
5162 break;
5163 case L'm':
5164 for (++i; i < __x_.size(); ++i)
5165 if (__x_[i] == L'%')
5166 break;
5167 if (i == __x_.size())
5168 break;
5169 ++i;
5170 if (__x_[i] == L'd')
5171 {
5172 for (++i; i < __x_.size(); ++i)
5173 if (__x_[i] == L'%')
5174 break;
5175 if (i == __x_.size())
5176 break;
5177 ++i;
5178 if (__x_[i] == L'y' || __x_[i] == L'Y')
5179 return time_base::mdy;
5180 break;
5181 }
5182 break;
5183 case L'd':
5184 for (++i; i < __x_.size(); ++i)
5185 if (__x_[i] == L'%')
5186 break;
5187 if (i == __x_.size())
5188 break;
5189 ++i;
5190 if (__x_[i] == L'm')
5191 {
5192 for (++i; i < __x_.size(); ++i)
5193 if (__x_[i] == L'%')
5194 break;
5195 if (i == __x_.size())
5196 break;
5197 ++i;
5198 if (__x_[i] == L'y' || __x_[i] == L'Y')
5199 return time_base::dmy;
5200 break;
5201 }
5202 break;
5203 }
5204 return time_base::no_order;
5205}
5206
5207// time_put
5208
5209__time_put::__time_put(const char* nm)
5210 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5211{
Howard Hinnantd4444702010-08-11 17:04:31 +00005212#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005213 if (__loc_ == 0)
5214 throw runtime_error("time_put_byname"
5215 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005216#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005217}
5218
5219__time_put::__time_put(const string& nm)
5220 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5221{
Howard Hinnantd4444702010-08-11 17:04:31 +00005222#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005223 if (__loc_ == 0)
5224 throw runtime_error("time_put_byname"
5225 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005226#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005227}
5228
5229__time_put::~__time_put()
5230{
5231 if (__loc_)
5232 freelocale(__loc_);
5233}
5234
5235void
5236__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5237 char __fmt, char __mod) const
5238{
5239 char fmt[] = {'%', __fmt, __mod, 0};
5240 if (__mod != 0)
5241 swap(fmt[1], fmt[2]);
5242 size_t n = strftime_l(__nb, __ne-__nb, fmt, __tm, __loc_);
5243 __ne = __nb + n;
5244}
5245
5246void
5247__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5248 char __fmt, char __mod) const
5249{
5250 char __nar[100];
5251 char* __ne = __nar + 100;
5252 __do_put(__nar, __ne, __tm, __fmt, __mod);
5253 mbstate_t mb = {0};
5254 const char* __nb = __nar;
Sean Huntf3907e62011-07-15 05:40:33 +00005255#ifdef _LIBCPP_STABLE_APPLE_ABI
5256 size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5257#else
5258 size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5259#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005260 if (j == -1)
5261 __throw_runtime_error("locale not supported");
5262 __we = __wb + j;
5263}
5264
5265// moneypunct_byname
5266
5267static
5268void
5269__init_pat(money_base::pattern& pat, char cs_precedes, char sep_by_space, char sign_posn)
5270{
5271 const char sign = static_cast<char>(money_base::sign);
5272 const char space = static_cast<char>(money_base::space);
5273 const char none = static_cast<char>(money_base::none);
5274 const char symbol = static_cast<char>(money_base::symbol);
5275 const char value = static_cast<char>(money_base::value);
5276 switch (cs_precedes)
5277 {
5278 case 0:
5279 switch (sign_posn)
5280 {
5281 case 0:
5282 pat.field[0] = sign;
5283 pat.field[1] = value;
5284 pat.field[3] = symbol;
5285 switch (sep_by_space)
5286 {
5287 case 0:
5288 pat.field[2] = none;
5289 return;
5290 case 1:
5291 case 2:
5292 pat.field[2] = space;
5293 return;
5294 default:
5295 break;
5296 }
5297 break;
5298 case 1:
5299 pat.field[0] = sign;
5300 pat.field[3] = symbol;
5301 switch (sep_by_space)
5302 {
5303 case 0:
5304 pat.field[1] = value;
5305 pat.field[2] = none;
5306 return;
5307 case 1:
5308 pat.field[1] = value;
5309 pat.field[2] = space;
5310 return;
5311 case 2:
5312 pat.field[1] = space;
5313 pat.field[2] = value;
5314 return;
5315 default:
5316 break;
5317 }
5318 break;
5319 case 2:
5320 pat.field[0] = value;
5321 pat.field[3] = sign;
5322 switch (sep_by_space)
5323 {
5324 case 0:
5325 pat.field[1] = none;
5326 pat.field[2] = symbol;
5327 return;
5328 case 1:
5329 pat.field[1] = space;
5330 pat.field[2] = symbol;
5331 return;
5332 case 2:
5333 pat.field[1] = symbol;
5334 pat.field[2] = space;
5335 return;
5336 default:
5337 break;
5338 }
5339 break;
5340 case 3:
5341 pat.field[0] = value;
5342 pat.field[3] = symbol;
5343 switch (sep_by_space)
5344 {
5345 case 0:
5346 pat.field[1] = none;
5347 pat.field[2] = sign;
5348 return;
5349 case 1:
5350 pat.field[1] = space;
5351 pat.field[2] = sign;
5352 return;
5353 case 2:
5354 pat.field[1] = sign;
5355 pat.field[2] = space;
5356 return;
5357 default:
5358 break;
5359 }
5360 break;
5361 case 4:
5362 pat.field[0] = value;
5363 pat.field[3] = sign;
5364 switch (sep_by_space)
5365 {
5366 case 0:
5367 pat.field[1] = none;
5368 pat.field[2] = symbol;
5369 return;
5370 case 1:
5371 pat.field[1] = space;
5372 pat.field[2] = symbol;
5373 return;
5374 case 2:
5375 pat.field[1] = symbol;
5376 pat.field[2] = space;
5377 return;
5378 default:
5379 break;
5380 }
5381 break;
5382 default:
5383 break;
5384 }
5385 break;
5386 case 1:
5387 switch (sign_posn)
5388 {
5389 case 0:
5390 pat.field[0] = sign;
5391 pat.field[1] = symbol;
5392 pat.field[3] = value;
5393 switch (sep_by_space)
5394 {
5395 case 0:
5396 pat.field[2] = none;
5397 return;
5398 case 1:
5399 case 2:
5400 pat.field[2] = space;
5401 return;
5402 default:
5403 break;
5404 }
5405 break;
5406 case 1:
5407 pat.field[0] = sign;
5408 pat.field[3] = value;
5409 switch (sep_by_space)
5410 {
5411 case 0:
5412 pat.field[1] = symbol;
5413 pat.field[2] = none;
5414 return;
5415 case 1:
5416 pat.field[1] = symbol;
5417 pat.field[2] = space;
5418 return;
5419 case 2:
5420 pat.field[1] = space;
5421 pat.field[2] = symbol;
5422 return;
5423 default:
5424 break;
5425 }
5426 break;
5427 case 2:
5428 pat.field[0] = symbol;
5429 pat.field[3] = sign;
5430 switch (sep_by_space)
5431 {
5432 case 0:
5433 pat.field[1] = none;
5434 pat.field[2] = value;
5435 return;
5436 case 1:
5437 pat.field[1] = space;
5438 pat.field[2] = value;
5439 return;
5440 case 2:
5441 pat.field[1] = value;
5442 pat.field[2] = space;
5443 return;
5444 default:
5445 break;
5446 }
5447 break;
5448 case 3:
5449 pat.field[0] = sign;
5450 pat.field[3] = value;
5451 switch (sep_by_space)
5452 {
5453 case 0:
5454 pat.field[1] = symbol;
5455 pat.field[2] = none;
5456 return;
5457 case 1:
5458 pat.field[1] = symbol;
5459 pat.field[2] = space;
5460 return;
5461 case 2:
5462 pat.field[1] = space;
5463 pat.field[2] = symbol;
5464 return;
5465 default:
5466 break;
5467 }
5468 break;
5469 case 4:
5470 pat.field[0] = symbol;
5471 pat.field[3] = value;
5472 switch (sep_by_space)
5473 {
5474 case 0:
5475 pat.field[1] = sign;
5476 pat.field[2] = none;
5477 return;
5478 case 1:
5479 pat.field[1] = sign;
5480 pat.field[2] = space;
5481 return;
5482 case 2:
5483 pat.field[1] = space;
5484 pat.field[2] = sign;
5485 return;
5486 default:
5487 break;
5488 }
5489 break;
5490 default:
5491 break;
5492 }
5493 break;
5494 default:
5495 break;
5496 }
5497 pat.field[0] = symbol;
5498 pat.field[1] = sign;
5499 pat.field[2] = none;
5500 pat.field[3] = value;
5501}
5502
5503template<>
5504void
5505moneypunct_byname<char, false>::init(const char* nm)
5506{
5507 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005508 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005509#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005510 if (loc == 0)
5511 throw runtime_error("moneypunct_byname"
5512 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005513#endif // _LIBCPP_NO_EXCEPTIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005514#ifdef _LIBCPP_STABLE_APPLE_ABI
5515 lconv* lc = localeconv_l(loc.get());
5516#else
5517 lconv* lc = __localeconv_l(loc.get());
5518#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005519 if (*lc->mon_decimal_point)
5520 __decimal_point_ = *lc->mon_decimal_point;
5521 else
5522 __decimal_point_ = base::do_decimal_point();
5523 if (*lc->mon_thousands_sep)
5524 __thousands_sep_ = *lc->mon_thousands_sep;
5525 else
5526 __thousands_sep_ = base::do_thousands_sep();
5527 __grouping_ = lc->mon_grouping;
5528 __curr_symbol_ = lc->currency_symbol;
5529 if (lc->frac_digits != CHAR_MAX)
5530 __frac_digits_ = lc->frac_digits;
5531 else
5532 __frac_digits_ = base::do_frac_digits();
5533 if (lc->p_sign_posn == 0)
5534 __positive_sign_ = "()";
5535 else
5536 __positive_sign_ = lc->positive_sign;
5537 if (lc->n_sign_posn == 0)
5538 __negative_sign_ = "()";
5539 else
5540 __negative_sign_ = lc->negative_sign;
5541 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5542 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5543}
5544
5545template<>
5546void
5547moneypunct_byname<char, true>::init(const char* nm)
5548{
5549 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005550 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005551#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005552 if (loc == 0)
5553 throw runtime_error("moneypunct_byname"
5554 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005555#endif // _LIBCPP_NO_EXCEPTIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005556#ifdef _LIBCPP_STABLE_APPLE_ABI
5557 lconv* lc = localeconv_l(loc.get());
5558#else
5559 lconv* lc = __localeconv_l(loc.get());
5560#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005561 if (*lc->mon_decimal_point)
5562 __decimal_point_ = *lc->mon_decimal_point;
5563 else
5564 __decimal_point_ = base::do_decimal_point();
5565 if (*lc->mon_thousands_sep)
5566 __thousands_sep_ = *lc->mon_thousands_sep;
5567 else
5568 __thousands_sep_ = base::do_thousands_sep();
5569 __grouping_ = lc->mon_grouping;
5570 __curr_symbol_ = lc->int_curr_symbol;
5571 if (lc->int_frac_digits != CHAR_MAX)
5572 __frac_digits_ = lc->int_frac_digits;
5573 else
5574 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005575#if _WIN32
5576 if (lc->p_sign_posn == 0)
5577#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005578 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005579#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005580 __positive_sign_ = "()";
5581 else
5582 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005583#if _WIN32
5584 if(lc->n_sign_posn == 0)
5585#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005586 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005587#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005588 __negative_sign_ = "()";
5589 else
5590 __negative_sign_ = lc->negative_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005591#if _WIN32
5592 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5593 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5594#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005595 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5596 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005597#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005598}
5599
5600template<>
5601void
5602moneypunct_byname<wchar_t, false>::init(const char* nm)
5603{
5604 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005605 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005606#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005607 if (loc == 0)
5608 throw runtime_error("moneypunct_byname"
5609 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005610#endif // _LIBCPP_NO_EXCEPTIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005611#ifdef _LIBCPP_STABLE_APPLE_ABI
5612 lconv* lc = localeconv_l(loc.get());
5613#else
5614 lconv* lc = __localeconv_l(loc.get());
5615#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005616 if (*lc->mon_decimal_point)
5617 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5618 else
5619 __decimal_point_ = base::do_decimal_point();
5620 if (*lc->mon_thousands_sep)
5621 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5622 else
5623 __thousands_sep_ = base::do_thousands_sep();
5624 __grouping_ = lc->mon_grouping;
5625 wchar_t wbuf[100];
5626 mbstate_t mb = {0};
5627 const char* bb = lc->currency_symbol;
Sean Huntf3907e62011-07-15 05:40:33 +00005628#ifdef _LIBCPP_STABLE_APPLE_ABI
5629 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5630#else
5631 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5632#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005633 if (j == -1)
5634 __throw_runtime_error("locale not supported");
5635 wchar_t* wbe = wbuf + j;
5636 __curr_symbol_.assign(wbuf, wbe);
5637 if (lc->frac_digits != CHAR_MAX)
5638 __frac_digits_ = lc->frac_digits;
5639 else
5640 __frac_digits_ = base::do_frac_digits();
5641 if (lc->p_sign_posn == 0)
5642 __positive_sign_ = L"()";
5643 else
5644 {
5645 mb = mbstate_t();
5646 bb = lc->positive_sign;
Sean Huntf3907e62011-07-15 05:40:33 +00005647#ifdef _LIBCPP_STABLE_APPLE_ABI
5648 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5649#else
5650 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5651#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005652 if (j == -1)
5653 __throw_runtime_error("locale not supported");
5654 wbe = wbuf + j;
5655 __positive_sign_.assign(wbuf, wbe);
5656 }
5657 if (lc->n_sign_posn == 0)
5658 __negative_sign_ = L"()";
5659 else
5660 {
5661 mb = mbstate_t();
5662 bb = lc->negative_sign;
Sean Huntf3907e62011-07-15 05:40:33 +00005663#ifdef _LIBCPP_STABLE_APPLE_ABI
5664 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5665#else
5666 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5667#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005668 if (j == -1)
5669 __throw_runtime_error("locale not supported");
5670 wbe = wbuf + j;
5671 __negative_sign_.assign(wbuf, wbe);
5672 }
5673 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5674 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5675}
5676
5677template<>
5678void
5679moneypunct_byname<wchar_t, true>::init(const char* nm)
5680{
5681 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005682 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005683#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005684 if (loc == 0)
5685 throw runtime_error("moneypunct_byname"
5686 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005687#endif // _LIBCPP_NO_EXCEPTIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005688#ifdef _LIBCPP_STABLE_APPLE_ABI
5689 lconv* lc = localeconv_l(loc.get());
5690#else
5691 lconv* lc = __localeconv_l(loc.get());
5692#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005693 if (*lc->mon_decimal_point)
5694 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5695 else
5696 __decimal_point_ = base::do_decimal_point();
5697 if (*lc->mon_thousands_sep)
5698 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5699 else
5700 __thousands_sep_ = base::do_thousands_sep();
5701 __grouping_ = lc->mon_grouping;
5702 wchar_t wbuf[100];
5703 mbstate_t mb = {0};
5704 const char* bb = lc->int_curr_symbol;
Sean Huntf3907e62011-07-15 05:40:33 +00005705#ifdef _LIBCPP_STABLE_APPLE_ABI
5706 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5707#else
5708 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5709#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005710 if (j == -1)
5711 __throw_runtime_error("locale not supported");
5712 wchar_t* wbe = wbuf + j;
5713 __curr_symbol_.assign(wbuf, wbe);
5714 if (lc->int_frac_digits != CHAR_MAX)
5715 __frac_digits_ = lc->int_frac_digits;
5716 else
5717 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005718#if _WIN32
5719 if (lc->p_sign_posn == 0)
5720#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005721 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005722#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005723 __positive_sign_ = L"()";
5724 else
5725 {
5726 mb = mbstate_t();
5727 bb = lc->positive_sign;
Sean Huntf3907e62011-07-15 05:40:33 +00005728#ifdef _LIBCPP_STABLE_APPLE_ABI
5729 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5730#else
5731 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5732#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005733 if (j == -1)
5734 __throw_runtime_error("locale not supported");
5735 wbe = wbuf + j;
5736 __positive_sign_.assign(wbuf, wbe);
5737 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005738#if _WIN32
5739 if (lc->n_sign_posn == 0)
5740#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005741 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005742#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005743 __negative_sign_ = L"()";
5744 else
5745 {
5746 mb = mbstate_t();
5747 bb = lc->negative_sign;
Sean Huntf3907e62011-07-15 05:40:33 +00005748#ifdef _LIBCPP_STABLE_APPLE_ABI
5749 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5750#else
5751 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5752#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005753 if (j == -1)
5754 __throw_runtime_error("locale not supported");
5755 wbe = wbuf + j;
5756 __negative_sign_.assign(wbuf, wbe);
5757 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005758#if _WIN32
5759 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5760 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5761#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005762 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5763 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005764#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005765}
5766
5767void __do_nothing(void*) {}
5768
5769void __throw_runtime_error(const char* msg)
5770{
Howard Hinnantd4444702010-08-11 17:04:31 +00005771#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005772 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00005773#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005774}
5775
5776template class collate<char>;
5777template class collate<wchar_t>;
5778
5779template class num_get<char>;
5780template class num_get<wchar_t>;
5781
5782template class __num_get<char>;
5783template class __num_get<wchar_t>;
5784
5785template class num_put<char>;
5786template class num_put<wchar_t>;
5787
5788template class __num_put<char>;
5789template class __num_put<wchar_t>;
5790
5791template class time_get<char>;
5792template class time_get<wchar_t>;
5793
5794template class time_get_byname<char>;
5795template class time_get_byname<wchar_t>;
5796
5797template class time_put<char>;
5798template class time_put<wchar_t>;
5799
5800template class time_put_byname<char>;
5801template class time_put_byname<wchar_t>;
5802
5803template class moneypunct<char, false>;
5804template class moneypunct<char, true>;
5805template class moneypunct<wchar_t, false>;
5806template class moneypunct<wchar_t, true>;
5807
5808template class moneypunct_byname<char, false>;
5809template class moneypunct_byname<char, true>;
5810template class moneypunct_byname<wchar_t, false>;
5811template class moneypunct_byname<wchar_t, true>;
5812
5813template class money_get<char>;
5814template class money_get<wchar_t>;
5815
5816template class __money_get<char>;
5817template class __money_get<wchar_t>;
5818
5819template class money_put<char>;
5820template class money_put<wchar_t>;
5821
5822template class __money_put<char>;
5823template class __money_put<wchar_t>;
5824
5825template class messages<char>;
5826template class messages<wchar_t>;
5827
5828template class messages_byname<char>;
5829template class messages_byname<wchar_t>;
5830
5831template class codecvt_byname<char, char, mbstate_t>;
5832template class codecvt_byname<wchar_t, char, mbstate_t>;
5833template class codecvt_byname<char16_t, char, mbstate_t>;
5834template class codecvt_byname<char32_t, char, mbstate_t>;
5835
5836template class __vector_base_common<true>;
5837
5838_LIBCPP_END_NAMESPACE_STD