blob: e1235c2266ad001d515d367950f6098b04697ad9 [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Howard Hinnantc566dc32010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00004//
Howard Hinnantee11c312010-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 Hinnantc51e1022010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
10#include "string"
11#include "locale"
Howard Hinnant7282c5a2010-05-30 21:39:41 +000012#include "codecvt"
Howard Hinnantc51e1022010-05-11 19:42:16 +000013#include "vector"
14#include "algorithm"
15#include "algorithm"
16#include "typeinfo"
Howard Hinnantbf6c0b42011-06-30 14:21:55 +000017#include "type_traits"
Howard Hinnantc51e1022010-05-11 19:42:16 +000018#include "clocale"
19#include "cstring"
20#include "cwctype"
21#include "__sso_allocator"
Howard Hinnantc51e1022010-05-11 19:42:16 +000022#include <langinfo.h>
23#include <stdlib.h>
24
Alexis Huntd4a24912011-07-13 06:40:50 +000025#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbf6c0b42011-06-30 14:21:55 +000026namespace {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +000027 decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnantbf6c0b42011-06-30 14:21:55 +000028 inline _LIBCPP_INLINE_VISIBILITY
29 mb_cur_max_l(locale_t loc)
30 {
31 return MB_CUR_MAX_L(loc);
32 }
Alexis Huntd4a24912011-07-13 06:40:50 +000033}
Howard Hinnantbf6c0b42011-06-30 14:21:55 +000034#endif
Howard Hinnantbf6c0b42011-06-30 14:21:55 +000035
Howard Hinnantc51e1022010-05-11 19:42:16 +000036_LIBCPP_BEGIN_NAMESPACE_STD
37
Alexis Hunt5a4dd562011-07-09 01:09:31 +000038#ifndef _LIBCPP_APPLE_STABLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +000039locale_t __cloc() {
40 // In theory this could create a race condition. In practice
41 // the race condition is non-fatal since it will just create
42 // a little resource leak. Better approach would be appreciated.
43#ifdef __APPLE__
44 return 0;
45#else
46 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
47 return result;
48#endif
49}
Alexis Hunt5a4dd562011-07-09 01:09:31 +000050#endif // _LIBCPP_APPLE_STABLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +000051
Howard Hinnantc51e1022010-05-11 19:42:16 +000052namespace {
53
54struct release
55{
56 void operator()(locale::facet* p) {p->__release_shared();}
57};
58
59template <class T, class A0>
60inline
61T&
62make(A0 a0)
63{
64 static typename aligned_storage<sizeof(T)>::type buf;
65 ::new (&buf) T(a0);
66 return *(T*)&buf;
67}
68
69template <class T, class A0, class A1>
70inline
71T&
72make(A0 a0, A1 a1)
73{
74 static typename aligned_storage<sizeof(T)>::type buf;
75 ::new (&buf) T(a0, a1);
76 return *(T*)&buf;
77}
78
79template <class T, class A0, class A1, class A2>
80inline
81T&
82make(A0 a0, A1 a1, A2 a2)
83{
84 static typename aligned_storage<sizeof(T)>::type buf;
85 ::new (&buf) T(a0, a1, a2);
86 return *(T*)&buf;
87}
88
89}
90
91class _LIBCPP_HIDDEN locale::__imp
92 : public facet
93{
94 enum {N = 28};
95 string name_;
96 vector<facet*, __sso_allocator<facet*, N> > facets_;
97public:
98 explicit __imp(size_t refs = 0);
99 explicit __imp(const string& name, size_t refs = 0);
100 __imp(const __imp&);
101 __imp(const __imp&, const string&, locale::category c);
102 __imp(const __imp& other, const __imp& one, locale::category c);
103 __imp(const __imp&, facet* f, long id);
104 ~__imp();
105
106 const string& name() const {return name_;}
107 bool has_facet(long id) const {return id < facets_.size() && facets_[id];}
108 const locale::facet* use_facet(long id) const;
109
110 static const locale& make_classic();
111 static locale& make_global();
112private:
113 void install(facet* f, long id);
114 template <class F> void install(F* f) {install(f, f->id.__get());}
115 template <class F> void install_from(const __imp& other);
116};
117
118locale::__imp::__imp(size_t refs)
119 : facet(refs),
120 name_("C"),
121 facets_(N)
122{
123 facets_.clear();
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000124 install(&make<_VSTD::collate<char> >(1));
125 install(&make<_VSTD::collate<wchar_t> >(1));
126 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1));
127 install(&make<_VSTD::ctype<wchar_t> >(1));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000128 install(&make<codecvt<char, char, mbstate_t> >(1));
129 install(&make<codecvt<wchar_t, char, mbstate_t> >(1));
130 install(&make<codecvt<char16_t, char, mbstate_t> >(1));
131 install(&make<codecvt<char32_t, char, mbstate_t> >(1));
132 install(&make<numpunct<char> >(1));
133 install(&make<numpunct<wchar_t> >(1));
134 install(&make<num_get<char> >(1));
135 install(&make<num_get<wchar_t> >(1));
136 install(&make<num_put<char> >(1));
137 install(&make<num_put<wchar_t> >(1));
138 install(&make<moneypunct<char, false> >(1));
139 install(&make<moneypunct<char, true> >(1));
140 install(&make<moneypunct<wchar_t, false> >(1));
141 install(&make<moneypunct<wchar_t, true> >(1));
142 install(&make<money_get<char> >(1));
143 install(&make<money_get<wchar_t> >(1));
144 install(&make<money_put<char> >(1));
145 install(&make<money_put<wchar_t> >(1));
146 install(&make<time_get<char> >(1));
147 install(&make<time_get<wchar_t> >(1));
148 install(&make<time_put<char> >(1));
149 install(&make<time_put<wchar_t> >(1));
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000150 install(&make<_VSTD::messages<char> >(1));
151 install(&make<_VSTD::messages<wchar_t> >(1));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000152}
153
154locale::__imp::__imp(const string& name, size_t refs)
155 : facet(refs),
156 name_(name),
157 facets_(N)
158{
Howard Hinnant72f73582010-08-11 17:04:31 +0000159#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000160 try
161 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000162#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000163 facets_ = locale::classic().__locale_->facets_;
164 for (unsigned i = 0; i < facets_.size(); ++i)
165 if (facets_[i])
166 facets_[i]->__add_shared();
167 install(new collate_byname<char>(name_));
168 install(new collate_byname<wchar_t>(name_));
169 install(new ctype_byname<char>(name_));
170 install(new ctype_byname<wchar_t>(name_));
171 install(new codecvt_byname<char, char, mbstate_t>(name_));
172 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
173 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
174 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
175 install(new numpunct_byname<char>(name_));
176 install(new numpunct_byname<wchar_t>(name_));
177 install(new moneypunct_byname<char, false>(name_));
178 install(new moneypunct_byname<char, true>(name_));
179 install(new moneypunct_byname<wchar_t, false>(name_));
180 install(new moneypunct_byname<wchar_t, true>(name_));
181 install(new time_get_byname<char>(name_));
182 install(new time_get_byname<wchar_t>(name_));
183 install(new time_put_byname<char>(name_));
184 install(new time_put_byname<wchar_t>(name_));
185 install(new messages_byname<char>(name_));
186 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000187#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000188 }
189 catch (...)
190 {
191 for (unsigned i = 0; i < facets_.size(); ++i)
192 if (facets_[i])
193 facets_[i]->__release_shared();
194 throw;
195 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000196#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000197}
198
199locale::__imp::__imp(const __imp& other)
200 : name_(other.name_),
201 facets_(max<size_t>(N, other.facets_.size()))
202{
203 facets_ = other.facets_;
204 for (unsigned i = 0; i < facets_.size(); ++i)
205 if (facets_[i])
206 facets_[i]->__add_shared();
207}
208
209locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
210 : name_("*"),
211 facets_(N)
212{
213 facets_ = other.facets_;
214 for (unsigned i = 0; i < facets_.size(); ++i)
215 if (facets_[i])
216 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000217#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000218 try
219 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000220#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000221 if (c & locale::collate)
222 {
223 install(new collate_byname<char>(name));
224 install(new collate_byname<wchar_t>(name));
225 }
226 if (c & locale::ctype)
227 {
228 install(new ctype_byname<char>(name));
229 install(new ctype_byname<wchar_t>(name));
230 install(new codecvt_byname<char, char, mbstate_t>(name));
231 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
232 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
233 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
234 }
235 if (c & locale::monetary)
236 {
237 install(new moneypunct_byname<char, false>(name));
238 install(new moneypunct_byname<char, true>(name));
239 install(new moneypunct_byname<wchar_t, false>(name));
240 install(new moneypunct_byname<wchar_t, true>(name));
241 }
242 if (c & locale::numeric)
243 {
244 install(new numpunct_byname<char>(name));
245 install(new numpunct_byname<wchar_t>(name));
246 }
247 if (c & locale::time)
248 {
249 install(new time_get_byname<char>(name));
250 install(new time_get_byname<wchar_t>(name));
251 install(new time_put_byname<char>(name));
252 install(new time_put_byname<wchar_t>(name));
253 }
254 if (c & locale::messages)
255 {
256 install(new messages_byname<char>(name));
257 install(new messages_byname<wchar_t>(name));
258 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000259#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000260 }
261 catch (...)
262 {
263 for (unsigned i = 0; i < facets_.size(); ++i)
264 if (facets_[i])
265 facets_[i]->__release_shared();
266 throw;
267 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000268#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000269}
270
271template<class F>
272inline
273void
274locale::__imp::install_from(const locale::__imp& one)
275{
276 long id = F::id.__get();
277 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
278}
279
280locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
281 : name_("*"),
282 facets_(N)
283{
284 facets_ = other.facets_;
285 for (unsigned i = 0; i < facets_.size(); ++i)
286 if (facets_[i])
287 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000288#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000289 try
290 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000291#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000292 if (c & locale::collate)
293 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000294 install_from<_VSTD::collate<char> >(one);
295 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000296 }
297 if (c & locale::ctype)
298 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000299 install_from<_VSTD::ctype<char> >(one);
300 install_from<_VSTD::ctype<wchar_t> >(one);
301 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
302 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
303 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
304 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000305 }
306 if (c & locale::monetary)
307 {
308 install_from<moneypunct<char, false> >(one);
309 install_from<moneypunct<char, true> >(one);
310 install_from<moneypunct<wchar_t, false> >(one);
311 install_from<moneypunct<wchar_t, true> >(one);
312 install_from<money_get<char> >(one);
313 install_from<money_get<wchar_t> >(one);
314 install_from<money_put<char> >(one);
315 install_from<money_put<wchar_t> >(one);
316 }
317 if (c & locale::numeric)
318 {
319 install_from<numpunct<char> >(one);
320 install_from<numpunct<wchar_t> >(one);
321 install_from<num_get<char> >(one);
322 install_from<num_get<wchar_t> >(one);
323 install_from<num_put<char> >(one);
324 install_from<num_put<wchar_t> >(one);
325 }
326 if (c & locale::time)
327 {
328 install_from<time_get<char> >(one);
329 install_from<time_get<wchar_t> >(one);
330 install_from<time_put<char> >(one);
331 install_from<time_put<wchar_t> >(one);
332 }
333 if (c & locale::messages)
334 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000335 install_from<_VSTD::messages<char> >(one);
336 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000337 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000338#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000339 }
340 catch (...)
341 {
342 for (unsigned i = 0; i < facets_.size(); ++i)
343 if (facets_[i])
344 facets_[i]->__release_shared();
345 throw;
346 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000347#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000348}
349
350locale::__imp::__imp(const __imp& other, facet* f, long id)
351 : name_("*"),
352 facets_(max<size_t>(N, other.facets_.size()+1))
353{
354 f->__add_shared();
355 unique_ptr<facet, release> hold(f);
356 facets_ = other.facets_;
357 for (unsigned i = 0; i < other.facets_.size(); ++i)
358 if (facets_[i])
359 facets_[i]->__add_shared();
360 install(hold.get(), id);
361}
362
363locale::__imp::~__imp()
364{
365 for (unsigned i = 0; i < facets_.size(); ++i)
366 if (facets_[i])
367 facets_[i]->__release_shared();
368}
369
370void
371locale::__imp::install(facet* f, long id)
372{
373 f->__add_shared();
374 unique_ptr<facet, release> hold(f);
375 if (id >= facets_.size())
376 facets_.resize(id+1);
377 if (facets_[id])
378 facets_[id]->__release_shared();
379 facets_[id] = hold.release();
380}
381
382const locale::facet*
383locale::__imp::use_facet(long id) const
384{
Howard Hinnant72f73582010-08-11 17:04:31 +0000385#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000386 if (!has_facet(id))
387 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000388#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000389 return facets_[id];
390}
391
392// locale
393
394const locale&
395locale::__imp::make_classic()
396{
397 // only one thread can get in here and it only gets in once
398 static aligned_storage<sizeof(locale)>::type buf;
399 locale* c = (locale*)&buf;
400 c->__locale_ = &make<__imp>(1);
401 return *c;
402}
403
404const locale&
405locale::classic()
406{
407 static const locale& c = __imp::make_classic();
408 return c;
409}
410
411locale&
412locale::__imp::make_global()
413{
414 // only one thread can get in here and it only gets in once
415 static aligned_storage<sizeof(locale)>::type buf;
416 locale* g = (locale*)&buf;
417 ::new (&buf) locale(locale::classic());
418 return *(locale*)&buf;
419}
420
421locale&
422locale::__global()
423{
424 static locale& g = __imp::make_global();
425 return g;
426}
427
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000428locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000429 : __locale_(__global().__locale_)
430{
431 __locale_->__add_shared();
432}
433
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000434locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000435 : __locale_(l.__locale_)
436{
437 __locale_->__add_shared();
438}
439
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000440locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000441{
442 __locale_->__release_shared();
443}
444
445const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000446locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000447{
448 other.__locale_->__add_shared();
449 __locale_->__release_shared();
450 __locale_ = other.__locale_;
451 return *this;
452}
453
454locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000455#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000456 : __locale_(name ? new __imp(name)
457 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000458#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000459 : __locale_(new __imp(name))
460#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000461{
462 __locale_->__add_shared();
463}
464
465locale::locale(const string& name)
466 : __locale_(new __imp(name))
467{
468 __locale_->__add_shared();
469}
470
471locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000472#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000473 : __locale_(name ? new __imp(*other.__locale_, name, c)
474 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000475#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000476 : __locale_(new __imp(*other.__locale_, name, c))
477#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000478{
479 __locale_->__add_shared();
480}
481
482locale::locale(const locale& other, const string& name, category c)
483 : __locale_(new __imp(*other.__locale_, name, c))
484{
485 __locale_->__add_shared();
486}
487
488locale::locale(const locale& other, const locale& one, category c)
489 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
490{
491 __locale_->__add_shared();
492}
493
494string
495locale::name() const
496{
497 return __locale_->name();
498}
499
500void
501locale::__install_ctor(const locale& other, facet* f, long id)
502{
503 if (f)
504 __locale_ = new __imp(*other.__locale_, f, id);
505 else
506 __locale_ = other.__locale_;
507 __locale_->__add_shared();
508}
509
510locale
511locale::global(const locale& loc)
512{
513 locale& g = __global();
514 locale r = g;
515 g = loc;
516 if (g.name() != "*")
517 setlocale(LC_ALL, g.name().c_str());
518 return r;
519}
520
521bool
522locale::has_facet(id& x) const
523{
524 return __locale_->has_facet(x.__get());
525}
526
527const locale::facet*
528locale::use_facet(id& x) const
529{
530 return __locale_->use_facet(x.__get());
531}
532
533bool
534locale::operator==(const locale& y) const
535{
536 return (__locale_ == y.__locale_)
537 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
538}
539
540// locale::facet
541
542locale::facet::~facet()
543{
544}
545
546void
Howard Hinnant719bda32011-05-28 14:41:13 +0000547locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000548{
549 delete this;
550}
551
552// locale::id
553
554int32_t locale::id::__next_id = 0;
555
556namespace
557{
558
559class __fake_bind
560{
561 locale::id* id_;
562 void (locale::id::* pmf_)();
563public:
564 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
565 : id_(id), pmf_(pmf) {}
566
567 void operator()() const
568 {
569 (id_->*pmf_)();
570 }
571};
572
573}
574
575long
576locale::id::__get()
577{
578 call_once(__flag_, __fake_bind(&locale::id::__init, this));
579 return __id_ - 1;
580}
581
582void
583locale::id::__init()
584{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000585 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000586}
587
588// template <> class collate_byname<char>
589
590collate_byname<char>::collate_byname(const char* n, size_t refs)
591 : collate<char>(refs),
592 __l(newlocale(LC_ALL_MASK, n, 0))
593{
Howard Hinnant72f73582010-08-11 17:04:31 +0000594#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000595 if (__l == 0)
596 throw runtime_error("collate_byname<char>::collate_byname"
597 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000598#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000599}
600
601collate_byname<char>::collate_byname(const string& name, size_t refs)
602 : collate<char>(refs),
603 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
604{
Howard Hinnant72f73582010-08-11 17:04:31 +0000605#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000606 if (__l == 0)
607 throw runtime_error("collate_byname<char>::collate_byname"
608 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000609#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000610}
611
612collate_byname<char>::~collate_byname()
613{
614 freelocale(__l);
615}
616
617int
618collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
619 const char_type* __lo2, const char_type* __hi2) const
620{
621 string_type lhs(__lo1, __hi1);
622 string_type rhs(__lo2, __hi2);
623 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
624 if (r < 0)
625 return -1;
626 if (r > 0)
627 return 1;
628 return r;
629}
630
631collate_byname<char>::string_type
632collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
633{
634 const string_type in(lo, hi);
635 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
636 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
637 return out;
638}
639
640// template <> class collate_byname<wchar_t>
641
642collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
643 : collate<wchar_t>(refs),
644 __l(newlocale(LC_ALL_MASK, n, 0))
645{
Howard Hinnant72f73582010-08-11 17:04:31 +0000646#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000647 if (__l == 0)
648 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
649 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000650#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000651}
652
653collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
654 : collate<wchar_t>(refs),
655 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
656{
Howard Hinnant72f73582010-08-11 17:04:31 +0000657#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000658 if (__l == 0)
659 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
660 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000661#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000662}
663
664collate_byname<wchar_t>::~collate_byname()
665{
666 freelocale(__l);
667}
668
669int
670collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
671 const char_type* __lo2, const char_type* __hi2) const
672{
673 string_type lhs(__lo1, __hi1);
674 string_type rhs(__lo2, __hi2);
675 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
676 if (r < 0)
677 return -1;
678 if (r > 0)
679 return 1;
680 return r;
681}
682
683collate_byname<wchar_t>::string_type
684collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
685{
686 const string_type in(lo, hi);
687 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
688 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
689 return out;
690}
691
692// template <> class ctype<wchar_t>;
693
694locale::id ctype<wchar_t>::id;
695
696ctype<wchar_t>::~ctype()
697{
698}
699
700bool
701ctype<wchar_t>::do_is(mask m, char_type c) const
702{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000703 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000704}
705
706const wchar_t*
707ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
708{
709 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000710 *vec = static_cast<mask>(isascii(*low) ?
711 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000712 return low;
713}
714
715const wchar_t*
716ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
717{
718 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000719 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000720 break;
721 return low;
722}
723
724const wchar_t*
725ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
726{
727 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000728 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000729 break;
730 return low;
731}
732
733wchar_t
734ctype<wchar_t>::do_toupper(char_type c) const
735{
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000736#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000737 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000738#else
739 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
740#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000741}
742
743const wchar_t*
744ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
745{
746 for (; low != high; ++low)
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000747#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000748 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
749 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000750#else
751 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
752#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000753 return low;
754}
755
756wchar_t
757ctype<wchar_t>::do_tolower(char_type c) const
758{
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000759#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000760 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000761#else
762 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
763#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000764}
765
766const wchar_t*
767ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
768{
769 for (; low != high; ++low)
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000770#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000771 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
772 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000773#else
774 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
775#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000776 return low;
777}
778
779wchar_t
780ctype<wchar_t>::do_widen(char c) const
781{
782 return c;
783}
784
785const char*
786ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
787{
788 for (; low != high; ++low, ++dest)
789 *dest = *low;
790 return low;
791}
792
793char
794ctype<wchar_t>::do_narrow(char_type c, char dfault) const
795{
796 if (isascii(c))
797 return static_cast<char>(c);
798 return dfault;
799}
800
801const wchar_t*
802ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
803{
804 for (; low != high; ++low, ++dest)
805 if (isascii(*low))
806 *dest = *low;
807 else
808 *dest = dfault;
809 return low;
810}
811
812// template <> class ctype<char>;
813
814locale::id ctype<char>::id;
815
816ctype<char>::ctype(const mask* tab, bool del, size_t refs)
817 : locale::facet(refs),
818 __tab_(tab),
819 __del_(del)
820{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000821 if (__tab_ == 0)
822 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000823}
824
825ctype<char>::~ctype()
826{
827 if (__tab_ && __del_)
828 delete [] __tab_;
829}
830
831char
832ctype<char>::do_toupper(char_type c) const
833{
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000834#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000835 return isascii(c) ? __classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000836#else
837 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
838#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000839}
840
841const char*
842ctype<char>::do_toupper(char_type* low, const char_type* high) const
843{
844 for (; low != high; ++low)
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000845#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000846 *low = isascii(*low) ? __classic_upper_table()[*low] : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000847#else
Howard Hinnant390fc292011-07-09 19:47:01 +0000848 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000849#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000850 return low;
851}
852
853char
854ctype<char>::do_tolower(char_type c) const
855{
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000856#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000857 return isascii(c) ? __classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000858#else
859 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
860#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000861}
862
863const char*
864ctype<char>::do_tolower(char_type* low, const char_type* high) const
865{
866 for (; low != high; ++low)
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000867#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000868 *low = isascii(*low) ? __classic_lower_table()[*low] : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000869#else
Howard Hinnant390fc292011-07-09 19:47:01 +0000870 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000871#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000872 return low;
873}
874
875char
876ctype<char>::do_widen(char c) const
877{
878 return c;
879}
880
881const char*
882ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
883{
884 for (; low != high; ++low, ++dest)
885 *dest = *low;
886 return low;
887}
888
889char
890ctype<char>::do_narrow(char_type c, char dfault) const
891{
892 if (isascii(c))
893 return static_cast<char>(c);
894 return dfault;
895}
896
897const char*
898ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
899{
900 for (; low != high; ++low, ++dest)
901 if (isascii(*low))
902 *dest = *low;
903 else
904 *dest = dfault;
905 return low;
906}
907
908const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000909ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000910{
Michael J. Spencer8d8164e2010-12-10 19:47:54 +0000911#ifdef __APPLE__
Howard Hinnantc51e1022010-05-11 19:42:16 +0000912 return _DefaultRuneLocale.__runetype;
Alexis Hunt92b0c812011-07-09 00:56:23 +0000913#elif defined(__GLIBC__)
914 return __cloc()->__ctype_b;
915// This is assumed to be safe.
916#else
917 return NULL;
918#endif
919}
920
Howard Hinnant390fc292011-07-09 19:47:01 +0000921#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000922const int*
923ctype<char>::__classic_lower_table() _NOEXCEPT
924{
925#ifdef __APPLE__
926 return _DefaultRuneLocale.__maplower;
927#elif defined(__GLIBC__)
928 return __cloc()->__ctype_tolower;
929#else
930 return NULL;
931#endif
932}
933
934const int*
935ctype<char>::__classic_upper_table() _NOEXCEPT
936{
937#ifdef __APPLE__
938 return _DefaultRuneLocale.__mapupper;
939#elif defined(__GLIBC__)
940 return __cloc()->__ctype_toupper;
Michael J. Spencer8d8164e2010-12-10 19:47:54 +0000941#else
942 return NULL;
943#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000944}
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000945#endif // _LIBCPP_APPLE_STABLE_ABI
Howard Hinnantc51e1022010-05-11 19:42:16 +0000946
947// template <> class ctype_byname<char>
948
949ctype_byname<char>::ctype_byname(const char* name, size_t refs)
950 : ctype<char>(0, false, refs),
951 __l(newlocale(LC_ALL_MASK, name, 0))
952{
Howard Hinnant72f73582010-08-11 17:04:31 +0000953#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000954 if (__l == 0)
955 throw runtime_error("ctype_byname<char>::ctype_byname"
956 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000957#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000958}
959
960ctype_byname<char>::ctype_byname(const string& name, size_t refs)
961 : ctype<char>(0, false, refs),
962 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
963{
Howard Hinnant72f73582010-08-11 17:04:31 +0000964#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000965 if (__l == 0)
966 throw runtime_error("ctype_byname<char>::ctype_byname"
967 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000968#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000969}
970
971ctype_byname<char>::~ctype_byname()
972{
973 freelocale(__l);
974}
975
976char
977ctype_byname<char>::do_toupper(char_type c) const
978{
979 return toupper_l(c, __l);
980}
981
982const char*
983ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
984{
985 for (; low != high; ++low)
986 *low = toupper_l(*low, __l);
987 return low;
988}
989
990char
991ctype_byname<char>::do_tolower(char_type c) const
992{
993 return tolower_l(c, __l);
994}
995
996const char*
997ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
998{
999 for (; low != high; ++low)
1000 *low = tolower_l(*low, __l);
1001 return low;
1002}
1003
1004// template <> class ctype_byname<wchar_t>
1005
1006ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1007 : ctype<wchar_t>(refs),
1008 __l(newlocale(LC_ALL_MASK, name, 0))
1009{
Howard Hinnant72f73582010-08-11 17:04:31 +00001010#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001011 if (__l == 0)
1012 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1013 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001014#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001015}
1016
1017ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1018 : ctype<wchar_t>(refs),
1019 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1020{
Howard Hinnant72f73582010-08-11 17:04:31 +00001021#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001022 if (__l == 0)
1023 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1024 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001025#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001026}
1027
1028ctype_byname<wchar_t>::~ctype_byname()
1029{
1030 freelocale(__l);
1031}
1032
1033bool
1034ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1035{
Alexis Huntc2017f12011-07-09 03:40:04 +00001036#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001037 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001038#else
1039 if (m & space && !iswspace_l(c, __l)) return false;
1040 if (m & print && !iswprint_l(c, __l)) return false;
1041 if (m & cntrl && !iswcntrl_l(c, __l)) return false;
1042 if (m & upper && !iswupper_l(c, __l)) return false;
1043 if (m & lower && !iswlower_l(c, __l)) return false;
1044 if (m & alpha && !iswalpha_l(c, __l)) return false;
1045 if (m & digit && !iswdigit_l(c, __l)) return false;
1046 if (m & punct && !iswpunct_l(c, __l)) return false;
1047 if (m & xdigit && !iswxdigit_l(c, __l)) return false;
1048 if (m & blank && !iswblank_l(c, __l)) return false;
1049 return true;
1050#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001051}
1052
1053const wchar_t*
1054ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1055{
1056 for (; low != high; ++low, ++vec)
1057 {
1058 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001059 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001060 else
1061 {
1062 *vec = 0;
1063 if (iswspace_l(*low, __l))
1064 *vec |= space;
1065 if (iswprint_l(*low, __l))
1066 *vec |= print;
1067 if (iswcntrl_l(*low, __l))
1068 *vec |= cntrl;
1069 if (iswupper_l(*low, __l))
1070 *vec |= upper;
1071 if (iswlower_l(*low, __l))
1072 *vec |= lower;
1073 if (iswalpha_l(*low, __l))
1074 *vec |= alpha;
1075 if (iswdigit_l(*low, __l))
1076 *vec |= digit;
1077 if (iswpunct_l(*low, __l))
1078 *vec |= punct;
1079 if (iswxdigit_l(*low, __l))
1080 *vec |= xdigit;
1081 }
1082 }
1083 return low;
1084}
1085
1086const wchar_t*
1087ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1088{
1089 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001090 {
1091#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001092 if (iswctype_l(*low, m, __l))
1093 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001094#else
1095 if (m & space && !iswspace_l(*low, __l)) continue;
1096 if (m & print && !iswprint_l(*low, __l)) continue;
1097 if (m & cntrl && !iswcntrl_l(*low, __l)) continue;
1098 if (m & upper && !iswupper_l(*low, __l)) continue;
1099 if (m & lower && !iswlower_l(*low, __l)) continue;
1100 if (m & alpha && !iswalpha_l(*low, __l)) continue;
1101 if (m & digit && !iswdigit_l(*low, __l)) continue;
1102 if (m & punct && !iswpunct_l(*low, __l)) continue;
1103 if (m & xdigit && !iswxdigit_l(*low, __l)) continue;
1104 if (m & blank && !iswblank_l(*low, __l)) continue;
1105 break;
1106#endif
1107 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001108 return low;
1109}
1110
1111const wchar_t*
1112ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1113{
1114 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001115 {
1116#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001117 if (!iswctype_l(*low, m, __l))
1118 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001119#else
1120 if (m & space && iswspace_l(*low, __l)) continue;
1121 if (m & print && iswprint_l(*low, __l)) continue;
1122 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1123 if (m & upper && iswupper_l(*low, __l)) continue;
1124 if (m & lower && iswlower_l(*low, __l)) continue;
1125 if (m & alpha && iswalpha_l(*low, __l)) continue;
1126 if (m & digit && iswdigit_l(*low, __l)) continue;
1127 if (m & punct && iswpunct_l(*low, __l)) continue;
1128 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1129 if (m & blank && iswblank_l(*low, __l)) continue;
1130 break;
1131#endif
1132 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001133 return low;
1134}
1135
1136wchar_t
1137ctype_byname<wchar_t>::do_toupper(char_type c) const
1138{
1139 return towupper_l(c, __l);
1140}
1141
1142const wchar_t*
1143ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1144{
1145 for (; low != high; ++low)
1146 *low = towupper_l(*low, __l);
1147 return low;
1148}
1149
1150wchar_t
1151ctype_byname<wchar_t>::do_tolower(char_type c) const
1152{
1153 return towlower_l(c, __l);
1154}
1155
1156const wchar_t*
1157ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1158{
1159 for (; low != high; ++low)
1160 *low = towlower_l(*low, __l);
1161 return low;
1162}
1163
1164wchar_t
1165ctype_byname<wchar_t>::do_widen(char c) const
1166{
Alexis Huntd4a24912011-07-13 06:40:50 +00001167 return __btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001168}
1169
1170const char*
1171ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1172{
1173 for (; low != high; ++low, ++dest)
Alexis Huntd4a24912011-07-13 06:40:50 +00001174 *dest = __btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001175 return low;
1176}
1177
1178char
1179ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1180{
Alexis Huntd4a24912011-07-13 06:40:50 +00001181 int r = __wctob_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001182 return r != WEOF ? static_cast<char>(r) : dfault;
1183}
1184
1185const wchar_t*
1186ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1187{
1188 for (; low != high; ++low, ++dest)
1189 {
Alexis Huntd4a24912011-07-13 06:40:50 +00001190 int r = __wctob_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001191 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1192 }
1193 return low;
1194}
1195
1196// template <> class codecvt<char, char, mbstate_t>
1197
Howard Hinnantffb308e2010-08-22 00:03:27 +00001198locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001199
1200codecvt<char, char, mbstate_t>::~codecvt()
1201{
1202}
1203
1204codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001205codecvt<char, char, mbstate_t>::do_out(state_type&,
1206 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001207 extern_type* to, extern_type*, extern_type*& to_nxt) const
1208{
1209 frm_nxt = frm;
1210 to_nxt = to;
1211 return noconv;
1212}
1213
1214codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001215codecvt<char, char, mbstate_t>::do_in(state_type&,
1216 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001217 intern_type* to, intern_type*, intern_type*& to_nxt) const
1218{
1219 frm_nxt = frm;
1220 to_nxt = to;
1221 return noconv;
1222}
1223
1224codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001225codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001226 extern_type* to, extern_type*, extern_type*& to_nxt) const
1227{
1228 to_nxt = to;
1229 return noconv;
1230}
1231
1232int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001233codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001234{
1235 return 1;
1236}
1237
1238bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001239codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001240{
1241 return true;
1242}
1243
1244int
1245codecvt<char, char, mbstate_t>::do_length(state_type&,
1246 const extern_type* frm, const extern_type* end, size_t mx) const
1247{
1248 return static_cast<int>(min<size_t>(mx, end-frm));
1249}
1250
1251int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001252codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001253{
1254 return 1;
1255}
1256
1257// template <> class codecvt<wchar_t, char, mbstate_t>
1258
Howard Hinnantffb308e2010-08-22 00:03:27 +00001259locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001260
1261codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1262 : locale::facet(refs),
1263 __l(0)
1264{
1265}
1266
1267codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1268 : locale::facet(refs),
1269 __l(newlocale(LC_ALL_MASK, nm, 0))
1270{
Howard Hinnant72f73582010-08-11 17:04:31 +00001271#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001272 if (__l == 0)
1273 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1274 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001275#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001276}
1277
1278codecvt<wchar_t, char, mbstate_t>::~codecvt()
1279{
1280 if (__l != 0)
1281 freelocale(__l);
1282}
1283
1284codecvt<wchar_t, char, mbstate_t>::result
1285codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001286 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001287 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1288{
1289 // look for first internal null in frm
1290 const intern_type* fend = frm;
1291 for (; fend != frm_end; ++fend)
1292 if (*fend == 0)
1293 break;
1294 // loop over all null-terminated sequences in frm
1295 to_nxt = to;
1296 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1297 {
1298 // save state in case needed to reover to_nxt on error
1299 mbstate_t save_state = st;
Alexis Huntd4a24912011-07-13 06:40:50 +00001300 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001301 if (n == size_t(-1))
1302 {
1303 // need to recover to_nxt
1304 for (to_nxt = to; frm != frm_nxt; ++frm)
1305 {
Alexis Huntd4a24912011-07-13 06:40:50 +00001306 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001307 if (n == size_t(-1))
1308 break;
1309 to_nxt += n;
1310 }
1311 frm_nxt = frm;
1312 return error;
1313 }
1314 if (n == 0)
1315 return partial;
1316 to_nxt += n;
1317 if (to_nxt == to_end)
1318 break;
1319 if (fend != frm_end) // set up next null terminated sequence
1320 {
1321 // Try to write the terminating null
1322 extern_type tmp[MB_LEN_MAX];
Alexis Huntd4a24912011-07-13 06:40:50 +00001323 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001324 if (n == size_t(-1)) // on error
1325 return error;
1326 if (n > to_end-to_nxt) // is there room?
1327 return partial;
1328 for (extern_type* p = tmp; n; --n) // write it
1329 *to_nxt++ = *p++;
1330 ++frm_nxt;
1331 // look for next null in frm
1332 for (fend = frm_nxt; fend != frm_end; ++fend)
1333 if (*fend == 0)
1334 break;
1335 }
1336 }
1337 return frm_nxt == frm_end ? ok : partial;
1338}
1339
1340codecvt<wchar_t, char, mbstate_t>::result
1341codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001342 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001343 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1344{
1345 // look for first internal null in frm
1346 const extern_type* fend = frm;
1347 for (; fend != frm_end; ++fend)
1348 if (*fend == 0)
1349 break;
1350 // loop over all null-terminated sequences in frm
1351 to_nxt = to;
1352 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1353 {
1354 // save state in case needed to reover to_nxt on error
1355 mbstate_t save_state = st;
Alexis Huntd4a24912011-07-13 06:40:50 +00001356 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001357 if (n == size_t(-1))
1358 {
1359 // need to recover to_nxt
1360 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1361 {
Alexis Huntd4a24912011-07-13 06:40:50 +00001362 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001363 switch (n)
1364 {
1365 case 0:
1366 ++frm;
1367 break;
1368 case -1:
1369 frm_nxt = frm;
1370 return error;
1371 case -2:
1372 frm_nxt = frm;
1373 return partial;
1374 default:
1375 frm += n;
1376 break;
1377 }
1378 }
1379 frm_nxt = frm;
1380 return frm_nxt == frm_end ? ok : partial;
1381 }
1382 if (n == 0)
1383 return error;
1384 to_nxt += n;
1385 if (to_nxt == to_end)
1386 break;
1387 if (fend != frm_end) // set up next null terminated sequence
1388 {
1389 // Try to write the terminating null
Alexis Huntd4a24912011-07-13 06:40:50 +00001390 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001391 if (n != 0) // on error
1392 return error;
1393 ++to_nxt;
1394 ++frm_nxt;
1395 // look for next null in frm
1396 for (fend = frm_nxt; fend != frm_end; ++fend)
1397 if (*fend == 0)
1398 break;
1399 }
1400 }
1401 return frm_nxt == frm_end ? ok : partial;
1402}
1403
1404codecvt<wchar_t, char, mbstate_t>::result
1405codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1406 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1407{
1408 to_nxt = to;
1409 extern_type tmp[MB_LEN_MAX];
Alexis Huntd4a24912011-07-13 06:40:50 +00001410 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001411 if (n == size_t(-1) || n == 0) // on error
1412 return error;
1413 --n;
1414 if (n > to_end-to_nxt) // is there room?
1415 return partial;
1416 for (extern_type* p = tmp; n; --n) // write it
1417 *to_nxt++ = *p++;
1418 return ok;
1419}
1420
1421int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001422codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001423{
Alexis Huntd4a24912011-07-13 06:40:50 +00001424 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001425 {
1426 // stateless encoding
Alexis Huntd4a24912011-07-13 06:40:50 +00001427 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Howard Hinnantc51e1022010-05-11 19:42:16 +00001428 return 1; // which take more than 1 char to form a wchar_t
1429 return 0;
1430 }
1431 return -1;
1432}
1433
1434bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001435codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001436{
1437 return false;
1438}
1439
1440int
1441codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1442 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1443{
1444 int nbytes = 0;
1445 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1446 {
Alexis Huntd4a24912011-07-13 06:40:50 +00001447 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001448 switch (n)
1449 {
1450 case 0:
1451 ++nbytes;
1452 ++frm;
1453 break;
1454 case -1:
1455 case -2:
1456 return nbytes;
1457 default:
1458 nbytes += n;
1459 frm += n;
1460 break;
1461 }
1462 }
1463 return nbytes;
1464}
1465
1466int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001467codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001468{
Alexis Huntd4a24912011-07-13 06:40:50 +00001469 return __l == 0 ? 1 : __mb_cur_max_l(__l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001470}
1471
1472// Valid UTF ranges
1473// UTF-32 UTF-16 UTF-8 # of code points
1474// first second first second third fourth
1475// 000000 - 00007F 0000 - 007F 00 - 7F 127
1476// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1477// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1478// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1479// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1480// 00D800 - 00DFFF invalid
1481// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1482// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1483// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1484// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1485
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001486static
1487codecvt_base::result
1488utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1489 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1490 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1491{
1492 frm_nxt = frm;
1493 to_nxt = to;
1494 if (mode & generate_header)
1495 {
1496 if (to_end-to_nxt < 3)
1497 return codecvt_base::partial;
1498 *to_nxt++ = static_cast<uint8_t>(0xEF);
1499 *to_nxt++ = static_cast<uint8_t>(0xBB);
1500 *to_nxt++ = static_cast<uint8_t>(0xBF);
1501 }
1502 for (; frm_nxt < frm_end; ++frm_nxt)
1503 {
1504 uint16_t wc1 = *frm_nxt;
1505 if (wc1 > Maxcode)
1506 return codecvt_base::error;
1507 if (wc1 < 0x0080)
1508 {
1509 if (to_end-to_nxt < 1)
1510 return codecvt_base::partial;
1511 *to_nxt++ = static_cast<uint8_t>(wc1);
1512 }
1513 else if (wc1 < 0x0800)
1514 {
1515 if (to_end-to_nxt < 2)
1516 return codecvt_base::partial;
1517 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1518 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1519 }
1520 else if (wc1 < 0xD800)
1521 {
1522 if (to_end-to_nxt < 3)
1523 return codecvt_base::partial;
1524 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1525 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1526 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1527 }
1528 else if (wc1 < 0xDC00)
1529 {
1530 if (frm_end-frm_nxt < 2)
1531 return codecvt_base::partial;
1532 uint16_t wc2 = frm_nxt[1];
1533 if ((wc2 & 0xFC00) != 0xDC00)
1534 return codecvt_base::error;
1535 if (to_end-to_nxt < 4)
1536 return codecvt_base::partial;
1537 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1538 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1539 return codecvt_base::error;
1540 ++frm_nxt;
1541 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1542 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1543 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1544 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1545 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1546 }
1547 else if (wc1 < 0xE000)
1548 {
1549 return codecvt_base::error;
1550 }
1551 else
1552 {
1553 if (to_end-to_nxt < 3)
1554 return codecvt_base::partial;
1555 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1556 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1557 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1558 }
1559 }
1560 return codecvt_base::ok;
1561}
1562
1563static
1564codecvt_base::result
1565utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1566 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1567 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1568{
1569 frm_nxt = frm;
1570 to_nxt = to;
1571 if (mode & generate_header)
1572 {
1573 if (to_end-to_nxt < 3)
1574 return codecvt_base::partial;
1575 *to_nxt++ = static_cast<uint8_t>(0xEF);
1576 *to_nxt++ = static_cast<uint8_t>(0xBB);
1577 *to_nxt++ = static_cast<uint8_t>(0xBF);
1578 }
1579 for (; frm_nxt < frm_end; ++frm_nxt)
1580 {
1581 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1582 if (wc1 > Maxcode)
1583 return codecvt_base::error;
1584 if (wc1 < 0x0080)
1585 {
1586 if (to_end-to_nxt < 1)
1587 return codecvt_base::partial;
1588 *to_nxt++ = static_cast<uint8_t>(wc1);
1589 }
1590 else if (wc1 < 0x0800)
1591 {
1592 if (to_end-to_nxt < 2)
1593 return codecvt_base::partial;
1594 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1595 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1596 }
1597 else if (wc1 < 0xD800)
1598 {
1599 if (to_end-to_nxt < 3)
1600 return codecvt_base::partial;
1601 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1602 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1603 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1604 }
1605 else if (wc1 < 0xDC00)
1606 {
1607 if (frm_end-frm_nxt < 2)
1608 return codecvt_base::partial;
1609 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1610 if ((wc2 & 0xFC00) != 0xDC00)
1611 return codecvt_base::error;
1612 if (to_end-to_nxt < 4)
1613 return codecvt_base::partial;
1614 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1615 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1616 return codecvt_base::error;
1617 ++frm_nxt;
1618 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1619 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1620 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1621 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1622 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1623 }
1624 else if (wc1 < 0xE000)
1625 {
1626 return codecvt_base::error;
1627 }
1628 else
1629 {
1630 if (to_end-to_nxt < 3)
1631 return codecvt_base::partial;
1632 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1633 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1634 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1635 }
1636 }
1637 return codecvt_base::ok;
1638}
1639
1640static
1641codecvt_base::result
1642utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1643 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1644 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1645{
1646 frm_nxt = frm;
1647 to_nxt = to;
1648 if (mode & consume_header)
1649 {
1650 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1651 frm_nxt[2] == 0xBF)
1652 frm_nxt += 3;
1653 }
1654 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1655 {
1656 uint8_t c1 = *frm_nxt;
1657 if (c1 > Maxcode)
1658 return codecvt_base::error;
1659 if (c1 < 0x80)
1660 {
1661 *to_nxt = static_cast<uint16_t>(c1);
1662 ++frm_nxt;
1663 }
1664 else if (c1 < 0xC2)
1665 {
1666 return codecvt_base::error;
1667 }
1668 else if (c1 < 0xE0)
1669 {
1670 if (frm_end-frm_nxt < 2)
1671 return codecvt_base::partial;
1672 uint8_t c2 = frm_nxt[1];
1673 if ((c2 & 0xC0) != 0x80)
1674 return codecvt_base::error;
1675 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1676 if (t > Maxcode)
1677 return codecvt_base::error;
1678 *to_nxt = t;
1679 frm_nxt += 2;
1680 }
1681 else if (c1 < 0xF0)
1682 {
1683 if (frm_end-frm_nxt < 3)
1684 return codecvt_base::partial;
1685 uint8_t c2 = frm_nxt[1];
1686 uint8_t c3 = frm_nxt[2];
1687 switch (c1)
1688 {
1689 case 0xE0:
1690 if ((c2 & 0xE0) != 0xA0)
1691 return codecvt_base::error;
1692 break;
1693 case 0xED:
1694 if ((c2 & 0xE0) != 0x80)
1695 return codecvt_base::error;
1696 break;
1697 default:
1698 if ((c2 & 0xC0) != 0x80)
1699 return codecvt_base::error;
1700 break;
1701 }
1702 if ((c3 & 0xC0) != 0x80)
1703 return codecvt_base::error;
1704 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1705 | ((c2 & 0x3F) << 6)
1706 | (c3 & 0x3F));
1707 if (t > Maxcode)
1708 return codecvt_base::error;
1709 *to_nxt = t;
1710 frm_nxt += 3;
1711 }
1712 else if (c1 < 0xF5)
1713 {
1714 if (frm_end-frm_nxt < 4)
1715 return codecvt_base::partial;
1716 uint8_t c2 = frm_nxt[1];
1717 uint8_t c3 = frm_nxt[2];
1718 uint8_t c4 = frm_nxt[3];
1719 switch (c1)
1720 {
1721 case 0xF0:
1722 if (!(0x90 <= c2 && c2 <= 0xBF))
1723 return codecvt_base::error;
1724 break;
1725 case 0xF4:
1726 if ((c2 & 0xF0) != 0x80)
1727 return codecvt_base::error;
1728 break;
1729 default:
1730 if ((c2 & 0xC0) != 0x80)
1731 return codecvt_base::error;
1732 break;
1733 }
1734 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1735 return codecvt_base::error;
1736 if (to_end-to_nxt < 2)
1737 return codecvt_base::partial;
1738 if (((((unsigned long)c1 & 7) << 18) +
1739 (((unsigned long)c2 & 0x3F) << 12) +
1740 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1741 return codecvt_base::error;
1742 *to_nxt = static_cast<uint16_t>(
1743 0xD800
1744 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1745 | ((c2 & 0x0F) << 2)
1746 | ((c3 & 0x30) >> 4));
1747 *++to_nxt = static_cast<uint16_t>(
1748 0xDC00
1749 | ((c3 & 0x0F) << 6)
1750 | (c4 & 0x3F));
1751 frm_nxt += 4;
1752 }
1753 else
1754 {
1755 return codecvt_base::error;
1756 }
1757 }
1758 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1759}
1760
1761static
1762codecvt_base::result
1763utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1764 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1765 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1766{
1767 frm_nxt = frm;
1768 to_nxt = to;
1769 if (mode & consume_header)
1770 {
1771 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1772 frm_nxt[2] == 0xBF)
1773 frm_nxt += 3;
1774 }
1775 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1776 {
1777 uint8_t c1 = *frm_nxt;
1778 if (c1 > Maxcode)
1779 return codecvt_base::error;
1780 if (c1 < 0x80)
1781 {
1782 *to_nxt = static_cast<uint32_t>(c1);
1783 ++frm_nxt;
1784 }
1785 else if (c1 < 0xC2)
1786 {
1787 return codecvt_base::error;
1788 }
1789 else if (c1 < 0xE0)
1790 {
1791 if (frm_end-frm_nxt < 2)
1792 return codecvt_base::partial;
1793 uint8_t c2 = frm_nxt[1];
1794 if ((c2 & 0xC0) != 0x80)
1795 return codecvt_base::error;
1796 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1797 if (t > Maxcode)
1798 return codecvt_base::error;
1799 *to_nxt = static_cast<uint32_t>(t);
1800 frm_nxt += 2;
1801 }
1802 else if (c1 < 0xF0)
1803 {
1804 if (frm_end-frm_nxt < 3)
1805 return codecvt_base::partial;
1806 uint8_t c2 = frm_nxt[1];
1807 uint8_t c3 = frm_nxt[2];
1808 switch (c1)
1809 {
1810 case 0xE0:
1811 if ((c2 & 0xE0) != 0xA0)
1812 return codecvt_base::error;
1813 break;
1814 case 0xED:
1815 if ((c2 & 0xE0) != 0x80)
1816 return codecvt_base::error;
1817 break;
1818 default:
1819 if ((c2 & 0xC0) != 0x80)
1820 return codecvt_base::error;
1821 break;
1822 }
1823 if ((c3 & 0xC0) != 0x80)
1824 return codecvt_base::error;
1825 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1826 | ((c2 & 0x3F) << 6)
1827 | (c3 & 0x3F));
1828 if (t > Maxcode)
1829 return codecvt_base::error;
1830 *to_nxt = static_cast<uint32_t>(t);
1831 frm_nxt += 3;
1832 }
1833 else if (c1 < 0xF5)
1834 {
1835 if (frm_end-frm_nxt < 4)
1836 return codecvt_base::partial;
1837 uint8_t c2 = frm_nxt[1];
1838 uint8_t c3 = frm_nxt[2];
1839 uint8_t c4 = frm_nxt[3];
1840 switch (c1)
1841 {
1842 case 0xF0:
1843 if (!(0x90 <= c2 && c2 <= 0xBF))
1844 return codecvt_base::error;
1845 break;
1846 case 0xF4:
1847 if ((c2 & 0xF0) != 0x80)
1848 return codecvt_base::error;
1849 break;
1850 default:
1851 if ((c2 & 0xC0) != 0x80)
1852 return codecvt_base::error;
1853 break;
1854 }
1855 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1856 return codecvt_base::error;
1857 if (to_end-to_nxt < 2)
1858 return codecvt_base::partial;
1859 if (((((unsigned long)c1 & 7) << 18) +
1860 (((unsigned long)c2 & 0x3F) << 12) +
1861 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1862 return codecvt_base::error;
1863 *to_nxt = static_cast<uint32_t>(
1864 0xD800
1865 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1866 | ((c2 & 0x0F) << 2)
1867 | ((c3 & 0x30) >> 4));
1868 *++to_nxt = static_cast<uint32_t>(
1869 0xDC00
1870 | ((c3 & 0x0F) << 6)
1871 | (c4 & 0x3F));
1872 frm_nxt += 4;
1873 }
1874 else
1875 {
1876 return codecvt_base::error;
1877 }
1878 }
1879 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1880}
1881
1882static
1883int
1884utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1885 size_t mx, unsigned long Maxcode = 0x10FFFF,
1886 codecvt_mode mode = codecvt_mode(0))
1887{
1888 const uint8_t* frm_nxt = frm;
1889 if (mode & consume_header)
1890 {
1891 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1892 frm_nxt[2] == 0xBF)
1893 frm_nxt += 3;
1894 }
1895 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1896 {
1897 uint8_t c1 = *frm_nxt;
1898 if (c1 > Maxcode)
1899 break;
1900 if (c1 < 0x80)
1901 {
1902 ++frm_nxt;
1903 }
1904 else if (c1 < 0xC2)
1905 {
1906 break;
1907 }
1908 else if (c1 < 0xE0)
1909 {
1910 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1911 break;
1912 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
1913 if (t > Maxcode)
1914 break;
1915 frm_nxt += 2;
1916 }
1917 else if (c1 < 0xF0)
1918 {
1919 if (frm_end-frm_nxt < 3)
1920 break;
1921 uint8_t c2 = frm_nxt[1];
1922 uint8_t c3 = frm_nxt[2];
1923 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1924 | ((c2 & 0x3F) << 6)
1925 | (c3 & 0x3F));
1926 switch (c1)
1927 {
1928 case 0xE0:
1929 if ((c2 & 0xE0) != 0xA0)
1930 return static_cast<int>(frm_nxt - frm);
1931 break;
1932 case 0xED:
1933 if ((c2 & 0xE0) != 0x80)
1934 return static_cast<int>(frm_nxt - frm);
1935 break;
1936 default:
1937 if ((c2 & 0xC0) != 0x80)
1938 return static_cast<int>(frm_nxt - frm);
1939 break;
1940 }
1941 if ((c3 & 0xC0) != 0x80)
1942 break;
1943 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
1944 break;
1945 frm_nxt += 3;
1946 }
1947 else if (c1 < 0xF5)
1948 {
1949 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
1950 break;
1951 uint8_t c2 = frm_nxt[1];
1952 uint8_t c3 = frm_nxt[2];
1953 uint8_t c4 = frm_nxt[3];
1954 switch (c1)
1955 {
1956 case 0xF0:
1957 if (!(0x90 <= c2 && c2 <= 0xBF))
1958 return static_cast<int>(frm_nxt - frm);
1959 break;
1960 case 0xF4:
1961 if ((c2 & 0xF0) != 0x80)
1962 return static_cast<int>(frm_nxt - frm);
1963 break;
1964 default:
1965 if ((c2 & 0xC0) != 0x80)
1966 return static_cast<int>(frm_nxt - frm);
1967 break;
1968 }
1969 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1970 break;
1971 if (((((unsigned long)c1 & 7) << 18) +
1972 (((unsigned long)c2 & 0x3F) << 12) +
1973 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1974 break;
1975 ++nchar16_t;
1976 frm_nxt += 4;
1977 }
1978 else
1979 {
1980 break;
1981 }
1982 }
1983 return static_cast<int>(frm_nxt - frm);
1984}
1985
1986static
1987codecvt_base::result
1988ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1989 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1990 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1991{
1992 frm_nxt = frm;
1993 to_nxt = to;
1994 if (mode & generate_header)
1995 {
1996 if (to_end-to_nxt < 3)
1997 return codecvt_base::partial;
1998 *to_nxt++ = static_cast<uint8_t>(0xEF);
1999 *to_nxt++ = static_cast<uint8_t>(0xBB);
2000 *to_nxt++ = static_cast<uint8_t>(0xBF);
2001 }
2002 for (; frm_nxt < frm_end; ++frm_nxt)
2003 {
2004 uint32_t wc = *frm_nxt;
2005 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2006 return codecvt_base::error;
2007 if (wc < 0x000080)
2008 {
2009 if (to_end-to_nxt < 1)
2010 return codecvt_base::partial;
2011 *to_nxt++ = static_cast<uint8_t>(wc);
2012 }
2013 else if (wc < 0x000800)
2014 {
2015 if (to_end-to_nxt < 2)
2016 return codecvt_base::partial;
2017 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2018 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2019 }
2020 else if (wc < 0x010000)
2021 {
2022 if (to_end-to_nxt < 3)
2023 return codecvt_base::partial;
2024 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2025 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2026 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2027 }
2028 else // if (wc < 0x110000)
2029 {
2030 if (to_end-to_nxt < 4)
2031 return codecvt_base::partial;
2032 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2033 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2034 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2035 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2036 }
2037 }
2038 return codecvt_base::ok;
2039}
2040
2041static
2042codecvt_base::result
2043utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2044 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2045 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2046{
2047 frm_nxt = frm;
2048 to_nxt = to;
2049 if (mode & consume_header)
2050 {
2051 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2052 frm_nxt[2] == 0xBF)
2053 frm_nxt += 3;
2054 }
2055 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2056 {
2057 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2058 if (c1 < 0x80)
2059 {
2060 if (c1 > Maxcode)
2061 return codecvt_base::error;
2062 *to_nxt = static_cast<uint32_t>(c1);
2063 ++frm_nxt;
2064 }
2065 else if (c1 < 0xC2)
2066 {
2067 return codecvt_base::error;
2068 }
2069 else if (c1 < 0xE0)
2070 {
2071 if (frm_end-frm_nxt < 2)
2072 return codecvt_base::partial;
2073 uint8_t c2 = frm_nxt[1];
2074 if ((c2 & 0xC0) != 0x80)
2075 return codecvt_base::error;
2076 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2077 | (c2 & 0x3F));
2078 if (t > Maxcode)
2079 return codecvt_base::error;
2080 *to_nxt = t;
2081 frm_nxt += 2;
2082 }
2083 else if (c1 < 0xF0)
2084 {
2085 if (frm_end-frm_nxt < 3)
2086 return codecvt_base::partial;
2087 uint8_t c2 = frm_nxt[1];
2088 uint8_t c3 = frm_nxt[2];
2089 switch (c1)
2090 {
2091 case 0xE0:
2092 if ((c2 & 0xE0) != 0xA0)
2093 return codecvt_base::error;
2094 break;
2095 case 0xED:
2096 if ((c2 & 0xE0) != 0x80)
2097 return codecvt_base::error;
2098 break;
2099 default:
2100 if ((c2 & 0xC0) != 0x80)
2101 return codecvt_base::error;
2102 break;
2103 }
2104 if ((c3 & 0xC0) != 0x80)
2105 return codecvt_base::error;
2106 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2107 | ((c2 & 0x3F) << 6)
2108 | (c3 & 0x3F));
2109 if (t > Maxcode)
2110 return codecvt_base::error;
2111 *to_nxt = t;
2112 frm_nxt += 3;
2113 }
2114 else if (c1 < 0xF5)
2115 {
2116 if (frm_end-frm_nxt < 4)
2117 return codecvt_base::partial;
2118 uint8_t c2 = frm_nxt[1];
2119 uint8_t c3 = frm_nxt[2];
2120 uint8_t c4 = frm_nxt[3];
2121 switch (c1)
2122 {
2123 case 0xF0:
2124 if (!(0x90 <= c2 && c2 <= 0xBF))
2125 return codecvt_base::error;
2126 break;
2127 case 0xF4:
2128 if ((c2 & 0xF0) != 0x80)
2129 return codecvt_base::error;
2130 break;
2131 default:
2132 if ((c2 & 0xC0) != 0x80)
2133 return codecvt_base::error;
2134 break;
2135 }
2136 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2137 return codecvt_base::error;
2138 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2139 | ((c2 & 0x3F) << 12)
2140 | ((c3 & 0x3F) << 6)
2141 | (c4 & 0x3F));
2142 if (t > Maxcode)
2143 return codecvt_base::error;
2144 *to_nxt = t;
2145 frm_nxt += 4;
2146 }
2147 else
2148 {
2149 return codecvt_base::error;
2150 }
2151 }
2152 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2153}
2154
2155static
2156int
2157utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2158 size_t mx, unsigned long Maxcode = 0x10FFFF,
2159 codecvt_mode mode = codecvt_mode(0))
2160{
2161 const uint8_t* frm_nxt = frm;
2162 if (mode & consume_header)
2163 {
2164 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2165 frm_nxt[2] == 0xBF)
2166 frm_nxt += 3;
2167 }
2168 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2169 {
2170 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2171 if (c1 < 0x80)
2172 {
2173 if (c1 > Maxcode)
2174 break;
2175 ++frm_nxt;
2176 }
2177 else if (c1 < 0xC2)
2178 {
2179 break;
2180 }
2181 else if (c1 < 0xE0)
2182 {
2183 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2184 break;
2185 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2186 break;
2187 frm_nxt += 2;
2188 }
2189 else if (c1 < 0xF0)
2190 {
2191 if (frm_end-frm_nxt < 3)
2192 break;
2193 uint8_t c2 = frm_nxt[1];
2194 uint8_t c3 = frm_nxt[2];
2195 switch (c1)
2196 {
2197 case 0xE0:
2198 if ((c2 & 0xE0) != 0xA0)
2199 return static_cast<int>(frm_nxt - frm);
2200 break;
2201 case 0xED:
2202 if ((c2 & 0xE0) != 0x80)
2203 return static_cast<int>(frm_nxt - frm);
2204 break;
2205 default:
2206 if ((c2 & 0xC0) != 0x80)
2207 return static_cast<int>(frm_nxt - frm);
2208 break;
2209 }
2210 if ((c3 & 0xC0) != 0x80)
2211 break;
2212 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2213 break;
2214 frm_nxt += 3;
2215 }
2216 else if (c1 < 0xF5)
2217 {
2218 if (frm_end-frm_nxt < 4)
2219 break;
2220 uint8_t c2 = frm_nxt[1];
2221 uint8_t c3 = frm_nxt[2];
2222 uint8_t c4 = frm_nxt[3];
2223 switch (c1)
2224 {
2225 case 0xF0:
2226 if (!(0x90 <= c2 && c2 <= 0xBF))
2227 return static_cast<int>(frm_nxt - frm);
2228 break;
2229 case 0xF4:
2230 if ((c2 & 0xF0) != 0x80)
2231 return static_cast<int>(frm_nxt - frm);
2232 break;
2233 default:
2234 if ((c2 & 0xC0) != 0x80)
2235 return static_cast<int>(frm_nxt - frm);
2236 break;
2237 }
2238 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2239 break;
2240 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2241 | ((c2 & 0x3F) << 12)
2242 | ((c3 & 0x3F) << 6)
2243 | (c4 & 0x3F));
2244 if ((((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) |
2245 ((c3 & 0x3F) << 6) | (c4 & 0x3F)) > Maxcode)
2246 break;
2247 frm_nxt += 4;
2248 }
2249 else
2250 {
2251 break;
2252 }
2253 }
2254 return static_cast<int>(frm_nxt - frm);
2255}
2256
2257static
2258codecvt_base::result
2259ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2260 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2261 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2262{
2263 frm_nxt = frm;
2264 to_nxt = to;
2265 if (mode & generate_header)
2266 {
2267 if (to_end-to_nxt < 3)
2268 return codecvt_base::partial;
2269 *to_nxt++ = static_cast<uint8_t>(0xEF);
2270 *to_nxt++ = static_cast<uint8_t>(0xBB);
2271 *to_nxt++ = static_cast<uint8_t>(0xBF);
2272 }
2273 for (; frm_nxt < frm_end; ++frm_nxt)
2274 {
2275 uint16_t wc = *frm_nxt;
2276 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2277 return codecvt_base::error;
2278 if (wc < 0x0080)
2279 {
2280 if (to_end-to_nxt < 1)
2281 return codecvt_base::partial;
2282 *to_nxt++ = static_cast<uint8_t>(wc);
2283 }
2284 else if (wc < 0x0800)
2285 {
2286 if (to_end-to_nxt < 2)
2287 return codecvt_base::partial;
2288 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2289 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2290 }
2291 else // if (wc <= 0xFFFF)
2292 {
2293 if (to_end-to_nxt < 3)
2294 return codecvt_base::partial;
2295 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2296 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2297 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2298 }
2299 }
2300 return codecvt_base::ok;
2301}
2302
2303static
2304codecvt_base::result
2305utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2306 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2307 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2308{
2309 frm_nxt = frm;
2310 to_nxt = to;
2311 if (mode & consume_header)
2312 {
2313 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2314 frm_nxt[2] == 0xBF)
2315 frm_nxt += 3;
2316 }
2317 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2318 {
2319 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2320 if (c1 < 0x80)
2321 {
2322 if (c1 > Maxcode)
2323 return codecvt_base::error;
2324 *to_nxt = static_cast<uint16_t>(c1);
2325 ++frm_nxt;
2326 }
2327 else if (c1 < 0xC2)
2328 {
2329 return codecvt_base::error;
2330 }
2331 else if (c1 < 0xE0)
2332 {
2333 if (frm_end-frm_nxt < 2)
2334 return codecvt_base::partial;
2335 uint8_t c2 = frm_nxt[1];
2336 if ((c2 & 0xC0) != 0x80)
2337 return codecvt_base::error;
2338 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2339 | (c2 & 0x3F));
2340 if (t > Maxcode)
2341 return codecvt_base::error;
2342 *to_nxt = t;
2343 frm_nxt += 2;
2344 }
2345 else if (c1 < 0xF0)
2346 {
2347 if (frm_end-frm_nxt < 3)
2348 return codecvt_base::partial;
2349 uint8_t c2 = frm_nxt[1];
2350 uint8_t c3 = frm_nxt[2];
2351 switch (c1)
2352 {
2353 case 0xE0:
2354 if ((c2 & 0xE0) != 0xA0)
2355 return codecvt_base::error;
2356 break;
2357 case 0xED:
2358 if ((c2 & 0xE0) != 0x80)
2359 return codecvt_base::error;
2360 break;
2361 default:
2362 if ((c2 & 0xC0) != 0x80)
2363 return codecvt_base::error;
2364 break;
2365 }
2366 if ((c3 & 0xC0) != 0x80)
2367 return codecvt_base::error;
2368 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2369 | ((c2 & 0x3F) << 6)
2370 | (c3 & 0x3F));
2371 if (t > Maxcode)
2372 return codecvt_base::error;
2373 *to_nxt = t;
2374 frm_nxt += 3;
2375 }
2376 else
2377 {
2378 return codecvt_base::error;
2379 }
2380 }
2381 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2382}
2383
2384static
2385int
2386utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2387 size_t mx, unsigned long Maxcode = 0x10FFFF,
2388 codecvt_mode mode = codecvt_mode(0))
2389{
2390 const uint8_t* frm_nxt = frm;
2391 if (mode & consume_header)
2392 {
2393 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2394 frm_nxt[2] == 0xBF)
2395 frm_nxt += 3;
2396 }
2397 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2398 {
2399 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2400 if (c1 < 0x80)
2401 {
2402 if (c1 > Maxcode)
2403 break;
2404 ++frm_nxt;
2405 }
2406 else if (c1 < 0xC2)
2407 {
2408 break;
2409 }
2410 else if (c1 < 0xE0)
2411 {
2412 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2413 break;
2414 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2415 break;
2416 frm_nxt += 2;
2417 }
2418 else if (c1 < 0xF0)
2419 {
2420 if (frm_end-frm_nxt < 3)
2421 break;
2422 uint8_t c2 = frm_nxt[1];
2423 uint8_t c3 = frm_nxt[2];
2424 switch (c1)
2425 {
2426 case 0xE0:
2427 if ((c2 & 0xE0) != 0xA0)
2428 return static_cast<int>(frm_nxt - frm);
2429 break;
2430 case 0xED:
2431 if ((c2 & 0xE0) != 0x80)
2432 return static_cast<int>(frm_nxt - frm);
2433 break;
2434 default:
2435 if ((c2 & 0xC0) != 0x80)
2436 return static_cast<int>(frm_nxt - frm);
2437 break;
2438 }
2439 if ((c3 & 0xC0) != 0x80)
2440 break;
2441 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2442 break;
2443 frm_nxt += 3;
2444 }
2445 else
2446 {
2447 break;
2448 }
2449 }
2450 return static_cast<int>(frm_nxt - frm);
2451}
2452
2453static
2454codecvt_base::result
2455ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2456 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2457 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2458{
2459 frm_nxt = frm;
2460 to_nxt = to;
2461 if (mode & generate_header)
2462 {
2463 if (to_end-to_nxt < 2)
2464 return codecvt_base::partial;
2465 *to_nxt++ = static_cast<uint8_t>(0xFE);
2466 *to_nxt++ = static_cast<uint8_t>(0xFF);
2467 }
2468 for (; frm_nxt < frm_end; ++frm_nxt)
2469 {
2470 uint32_t wc = *frm_nxt;
2471 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2472 return codecvt_base::error;
2473 if (wc < 0x010000)
2474 {
2475 if (to_end-to_nxt < 2)
2476 return codecvt_base::partial;
2477 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2478 *to_nxt++ = static_cast<uint8_t>(wc);
2479 }
2480 else
2481 {
2482 if (to_end-to_nxt < 4)
2483 return codecvt_base::partial;
2484 uint16_t t = static_cast<uint16_t>(
2485 0xD800
2486 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2487 | ((wc & 0x00FC00) >> 10));
2488 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2489 *to_nxt++ = static_cast<uint8_t>(t);
2490 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2491 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2492 *to_nxt++ = static_cast<uint8_t>(t);
2493 }
2494 }
2495 return codecvt_base::ok;
2496}
2497
2498static
2499codecvt_base::result
2500utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2501 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2502 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2503{
2504 frm_nxt = frm;
2505 to_nxt = to;
2506 if (mode & consume_header)
2507 {
2508 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2509 frm_nxt += 2;
2510 }
2511 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2512 {
2513 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2514 if ((c1 & 0xFC00) == 0xDC00)
2515 return codecvt_base::error;
2516 if ((c1 & 0xFC00) != 0xD800)
2517 {
2518 if (c1 > Maxcode)
2519 return codecvt_base::error;
2520 *to_nxt = static_cast<uint32_t>(c1);
2521 frm_nxt += 2;
2522 }
2523 else
2524 {
2525 if (frm_end-frm_nxt < 4)
2526 return codecvt_base::partial;
2527 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2528 if ((c2 & 0xFC00) != 0xDC00)
2529 return codecvt_base::error;
2530 uint32_t t = static_cast<uint32_t>(
2531 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2532 | ((c1 & 0x003F) << 10)
2533 | (c2 & 0x03FF));
2534 if (t > Maxcode)
2535 return codecvt_base::error;
2536 *to_nxt = t;
2537 frm_nxt += 4;
2538 }
2539 }
2540 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2541}
2542
2543static
2544int
2545utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2546 size_t mx, unsigned long Maxcode = 0x10FFFF,
2547 codecvt_mode mode = codecvt_mode(0))
2548{
2549 const uint8_t* frm_nxt = frm;
2550 frm_nxt = frm;
2551 if (mode & consume_header)
2552 {
2553 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2554 frm_nxt += 2;
2555 }
2556 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2557 {
2558 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2559 if ((c1 & 0xFC00) == 0xDC00)
2560 break;
2561 if ((c1 & 0xFC00) != 0xD800)
2562 {
2563 if (c1 > Maxcode)
2564 break;
2565 frm_nxt += 2;
2566 }
2567 else
2568 {
2569 if (frm_end-frm_nxt < 4)
2570 break;
2571 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2572 if ((c2 & 0xFC00) != 0xDC00)
2573 break;
2574 uint32_t t = static_cast<uint32_t>(
2575 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2576 | ((c1 & 0x003F) << 10)
2577 | (c2 & 0x03FF));
2578 if (t > Maxcode)
2579 break;
2580 frm_nxt += 4;
2581 }
2582 }
2583 return static_cast<int>(frm_nxt - frm);
2584}
2585
2586static
2587codecvt_base::result
2588ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2589 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2590 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2591{
2592 frm_nxt = frm;
2593 to_nxt = to;
2594 if (mode & generate_header)
2595 {
2596 if (to_end-to_nxt < 2)
2597 return codecvt_base::partial;
2598 *to_nxt++ = static_cast<uint8_t>(0xFF);
2599 *to_nxt++ = static_cast<uint8_t>(0xFE);
2600 }
2601 for (; frm_nxt < frm_end; ++frm_nxt)
2602 {
2603 uint32_t wc = *frm_nxt;
2604 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2605 return codecvt_base::error;
2606 if (wc < 0x010000)
2607 {
2608 if (to_end-to_nxt < 2)
2609 return codecvt_base::partial;
2610 *to_nxt++ = static_cast<uint8_t>(wc);
2611 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2612 }
2613 else
2614 {
2615 if (to_end-to_nxt < 4)
2616 return codecvt_base::partial;
2617 uint16_t t = static_cast<uint16_t>(
2618 0xD800
2619 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2620 | ((wc & 0x00FC00) >> 10));
2621 *to_nxt++ = static_cast<uint8_t>(t);
2622 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2623 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2624 *to_nxt++ = static_cast<uint8_t>(t);
2625 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2626 }
2627 }
2628 return codecvt_base::ok;
2629}
2630
2631static
2632codecvt_base::result
2633utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2634 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2635 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2636{
2637 frm_nxt = frm;
2638 to_nxt = to;
2639 if (mode & consume_header)
2640 {
2641 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2642 frm_nxt += 2;
2643 }
2644 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2645 {
2646 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2647 if ((c1 & 0xFC00) == 0xDC00)
2648 return codecvt_base::error;
2649 if ((c1 & 0xFC00) != 0xD800)
2650 {
2651 if (c1 > Maxcode)
2652 return codecvt_base::error;
2653 *to_nxt = static_cast<uint32_t>(c1);
2654 frm_nxt += 2;
2655 }
2656 else
2657 {
2658 if (frm_end-frm_nxt < 4)
2659 return codecvt_base::partial;
2660 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2661 if ((c2 & 0xFC00) != 0xDC00)
2662 return codecvt_base::error;
2663 uint32_t t = static_cast<uint32_t>(
2664 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2665 | ((c1 & 0x003F) << 10)
2666 | (c2 & 0x03FF));
2667 if (t > Maxcode)
2668 return codecvt_base::error;
2669 *to_nxt = t;
2670 frm_nxt += 4;
2671 }
2672 }
2673 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2674}
2675
2676static
2677int
2678utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2679 size_t mx, unsigned long Maxcode = 0x10FFFF,
2680 codecvt_mode mode = codecvt_mode(0))
2681{
2682 const uint8_t* frm_nxt = frm;
2683 frm_nxt = frm;
2684 if (mode & consume_header)
2685 {
2686 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2687 frm_nxt += 2;
2688 }
2689 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2690 {
2691 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2692 if ((c1 & 0xFC00) == 0xDC00)
2693 break;
2694 if ((c1 & 0xFC00) != 0xD800)
2695 {
2696 if (c1 > Maxcode)
2697 break;
2698 frm_nxt += 2;
2699 }
2700 else
2701 {
2702 if (frm_end-frm_nxt < 4)
2703 break;
2704 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2705 if ((c2 & 0xFC00) != 0xDC00)
2706 break;
2707 uint32_t t = static_cast<uint32_t>(
2708 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2709 | ((c1 & 0x003F) << 10)
2710 | (c2 & 0x03FF));
2711 if (t > Maxcode)
2712 break;
2713 frm_nxt += 4;
2714 }
2715 }
2716 return static_cast<int>(frm_nxt - frm);
2717}
2718
2719static
2720codecvt_base::result
2721ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2722 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2723 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2724{
2725 frm_nxt = frm;
2726 to_nxt = to;
2727 if (mode & generate_header)
2728 {
2729 if (to_end-to_nxt < 2)
2730 return codecvt_base::partial;
2731 *to_nxt++ = static_cast<uint8_t>(0xFE);
2732 *to_nxt++ = static_cast<uint8_t>(0xFF);
2733 }
2734 for (; frm_nxt < frm_end; ++frm_nxt)
2735 {
2736 uint16_t wc = *frm_nxt;
2737 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2738 return codecvt_base::error;
2739 if (to_end-to_nxt < 2)
2740 return codecvt_base::partial;
2741 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2742 *to_nxt++ = static_cast<uint8_t>(wc);
2743 }
2744 return codecvt_base::ok;
2745}
2746
2747static
2748codecvt_base::result
2749utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2750 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2751 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2752{
2753 frm_nxt = frm;
2754 to_nxt = to;
2755 if (mode & consume_header)
2756 {
2757 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2758 frm_nxt += 2;
2759 }
2760 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2761 {
2762 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2763 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2764 return codecvt_base::error;
2765 *to_nxt = c1;
2766 frm_nxt += 2;
2767 }
2768 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2769}
2770
2771static
2772int
2773utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2774 size_t mx, unsigned long Maxcode = 0x10FFFF,
2775 codecvt_mode mode = codecvt_mode(0))
2776{
2777 const uint8_t* frm_nxt = frm;
2778 frm_nxt = frm;
2779 if (mode & consume_header)
2780 {
2781 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2782 frm_nxt += 2;
2783 }
2784 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2785 {
2786 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2787 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2788 break;
2789 frm_nxt += 2;
2790 }
2791 return static_cast<int>(frm_nxt - frm);
2792}
2793
2794static
2795codecvt_base::result
2796ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2797 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2798 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2799{
2800 frm_nxt = frm;
2801 to_nxt = to;
2802 if (mode & generate_header)
2803 {
2804 if (to_end-to_nxt < 2)
2805 return codecvt_base::partial;
2806 *to_nxt++ = static_cast<uint8_t>(0xFF);
2807 *to_nxt++ = static_cast<uint8_t>(0xFE);
2808 }
2809 for (; frm_nxt < frm_end; ++frm_nxt)
2810 {
2811 uint16_t wc = *frm_nxt;
2812 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2813 return codecvt_base::error;
2814 if (to_end-to_nxt < 2)
2815 return codecvt_base::partial;
2816 *to_nxt++ = static_cast<uint8_t>(wc);
2817 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2818 }
2819 return codecvt_base::ok;
2820}
2821
2822static
2823codecvt_base::result
2824utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2825 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2826 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2827{
2828 frm_nxt = frm;
2829 to_nxt = to;
2830 if (mode & consume_header)
2831 {
2832 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2833 frm_nxt += 2;
2834 }
2835 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2836 {
2837 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2838 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2839 return codecvt_base::error;
2840 *to_nxt = c1;
2841 frm_nxt += 2;
2842 }
2843 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2844}
2845
2846static
2847int
2848utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2849 size_t mx, unsigned long Maxcode = 0x10FFFF,
2850 codecvt_mode mode = codecvt_mode(0))
2851{
2852 const uint8_t* frm_nxt = frm;
2853 frm_nxt = frm;
2854 if (mode & consume_header)
2855 {
2856 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2857 frm_nxt += 2;
2858 }
2859 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2860 {
2861 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2862 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2863 break;
2864 frm_nxt += 2;
2865 }
2866 return static_cast<int>(frm_nxt - frm);
2867}
2868
Howard Hinnantc51e1022010-05-11 19:42:16 +00002869// template <> class codecvt<char16_t, char, mbstate_t>
2870
Howard Hinnantffb308e2010-08-22 00:03:27 +00002871locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002872
2873codecvt<char16_t, char, mbstate_t>::~codecvt()
2874{
2875}
2876
2877codecvt<char16_t, char, mbstate_t>::result
2878codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00002879 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002880 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2881{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002882 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2883 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2884 const uint16_t* _frm_nxt = _frm;
2885 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2886 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2887 uint8_t* _to_nxt = _to;
2888 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2889 frm_nxt = frm + (_frm_nxt - _frm);
2890 to_nxt = to + (_to_nxt - _to);
2891 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002892}
2893
2894codecvt<char16_t, char, mbstate_t>::result
2895codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00002896 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002897 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2898{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002899 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2900 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2901 const uint8_t* _frm_nxt = _frm;
2902 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2903 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2904 uint16_t* _to_nxt = _to;
2905 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2906 frm_nxt = frm + (_frm_nxt - _frm);
2907 to_nxt = to + (_to_nxt - _to);
2908 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002909}
2910
2911codecvt<char16_t, char, mbstate_t>::result
2912codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
2913 extern_type* to, extern_type*, extern_type*& to_nxt) const
2914{
2915 to_nxt = to;
2916 return noconv;
2917}
2918
2919int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00002920codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00002921{
2922 return 0;
2923}
2924
2925bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00002926codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00002927{
2928 return false;
2929}
2930
2931int
2932codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
2933 const extern_type* frm, const extern_type* frm_end, size_t mx) const
2934{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002935 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2936 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2937 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002938}
2939
2940int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00002941codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00002942{
2943 return 4;
2944}
2945
2946// template <> class codecvt<char32_t, char, mbstate_t>
2947
Howard Hinnantffb308e2010-08-22 00:03:27 +00002948locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002949
2950codecvt<char32_t, char, mbstate_t>::~codecvt()
2951{
2952}
2953
2954codecvt<char32_t, char, mbstate_t>::result
2955codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00002956 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002957 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2958{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002959 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
2960 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
2961 const uint32_t* _frm_nxt = _frm;
2962 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2963 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2964 uint8_t* _to_nxt = _to;
2965 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2966 frm_nxt = frm + (_frm_nxt - _frm);
2967 to_nxt = to + (_to_nxt - _to);
2968 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002969}
2970
2971codecvt<char32_t, char, mbstate_t>::result
2972codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00002973 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002974 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2975{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002976 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2977 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2978 const uint8_t* _frm_nxt = _frm;
2979 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
2980 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
2981 uint32_t* _to_nxt = _to;
2982 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2983 frm_nxt = frm + (_frm_nxt - _frm);
2984 to_nxt = to + (_to_nxt - _to);
2985 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002986}
2987
2988codecvt<char32_t, char, mbstate_t>::result
2989codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
2990 extern_type* to, extern_type*, extern_type*& to_nxt) const
2991{
2992 to_nxt = to;
2993 return noconv;
2994}
2995
2996int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00002997codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00002998{
2999 return 0;
3000}
3001
3002bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003003codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003004{
3005 return false;
3006}
3007
3008int
3009codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3010 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3011{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003012 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3013 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3014 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003015}
3016
3017int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003018codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003019{
3020 return 4;
3021}
3022
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003023// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003024
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003025__codecvt_utf8<wchar_t>::result
3026__codecvt_utf8<wchar_t>::do_out(state_type&,
3027 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003028 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3029{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003030 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3031 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3032 const uint32_t* _frm_nxt = _frm;
3033 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3034 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3035 uint8_t* _to_nxt = _to;
3036 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3037 _Maxcode_, _Mode_);
3038 frm_nxt = frm + (_frm_nxt - _frm);
3039 to_nxt = to + (_to_nxt - _to);
3040 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003041}
3042
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003043__codecvt_utf8<wchar_t>::result
3044__codecvt_utf8<wchar_t>::do_in(state_type&,
3045 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003046 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3047{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003048 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3049 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3050 const uint8_t* _frm_nxt = _frm;
3051 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3052 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3053 uint32_t* _to_nxt = _to;
3054 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3055 _Maxcode_, _Mode_);
3056 frm_nxt = frm + (_frm_nxt - _frm);
3057 to_nxt = to + (_to_nxt - _to);
3058 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003059}
3060
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003061__codecvt_utf8<wchar_t>::result
3062__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003063 extern_type* to, extern_type*, extern_type*& to_nxt) const
3064{
3065 to_nxt = to;
3066 return noconv;
3067}
3068
3069int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003070__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003071{
3072 return 0;
3073}
3074
3075bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003076__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003077{
3078 return false;
3079}
3080
3081int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003082__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003083 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3084{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003085 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3086 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3087 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003088}
3089
3090int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003091__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003092{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003093 if (_Mode_ & consume_header)
3094 return 7;
3095 return 4;
3096}
3097
3098// __codecvt_utf8<char16_t>
3099
3100__codecvt_utf8<char16_t>::result
3101__codecvt_utf8<char16_t>::do_out(state_type&,
3102 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3103 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3104{
3105 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3106 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3107 const uint16_t* _frm_nxt = _frm;
3108 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3109 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3110 uint8_t* _to_nxt = _to;
3111 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3112 _Maxcode_, _Mode_);
3113 frm_nxt = frm + (_frm_nxt - _frm);
3114 to_nxt = to + (_to_nxt - _to);
3115 return r;
3116}
3117
3118__codecvt_utf8<char16_t>::result
3119__codecvt_utf8<char16_t>::do_in(state_type&,
3120 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3121 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3122{
3123 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3124 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3125 const uint8_t* _frm_nxt = _frm;
3126 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3127 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3128 uint16_t* _to_nxt = _to;
3129 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3130 _Maxcode_, _Mode_);
3131 frm_nxt = frm + (_frm_nxt - _frm);
3132 to_nxt = to + (_to_nxt - _to);
3133 return r;
3134}
3135
3136__codecvt_utf8<char16_t>::result
3137__codecvt_utf8<char16_t>::do_unshift(state_type&,
3138 extern_type* to, extern_type*, extern_type*& to_nxt) const
3139{
3140 to_nxt = to;
3141 return noconv;
3142}
3143
3144int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003145__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003146{
3147 return 0;
3148}
3149
3150bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003151__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003152{
3153 return false;
3154}
3155
3156int
3157__codecvt_utf8<char16_t>::do_length(state_type&,
3158 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3159{
3160 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3161 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3162 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3163}
3164
3165int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003166__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003167{
3168 if (_Mode_ & consume_header)
3169 return 6;
3170 return 3;
3171}
3172
3173// __codecvt_utf8<char32_t>
3174
3175__codecvt_utf8<char32_t>::result
3176__codecvt_utf8<char32_t>::do_out(state_type&,
3177 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3178 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3179{
3180 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3181 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3182 const uint32_t* _frm_nxt = _frm;
3183 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3184 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3185 uint8_t* _to_nxt = _to;
3186 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3187 _Maxcode_, _Mode_);
3188 frm_nxt = frm + (_frm_nxt - _frm);
3189 to_nxt = to + (_to_nxt - _to);
3190 return r;
3191}
3192
3193__codecvt_utf8<char32_t>::result
3194__codecvt_utf8<char32_t>::do_in(state_type&,
3195 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3196 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3197{
3198 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3199 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3200 const uint8_t* _frm_nxt = _frm;
3201 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3202 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3203 uint32_t* _to_nxt = _to;
3204 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3205 _Maxcode_, _Mode_);
3206 frm_nxt = frm + (_frm_nxt - _frm);
3207 to_nxt = to + (_to_nxt - _to);
3208 return r;
3209}
3210
3211__codecvt_utf8<char32_t>::result
3212__codecvt_utf8<char32_t>::do_unshift(state_type&,
3213 extern_type* to, extern_type*, extern_type*& to_nxt) const
3214{
3215 to_nxt = to;
3216 return noconv;
3217}
3218
3219int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003220__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003221{
3222 return 0;
3223}
3224
3225bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003226__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003227{
3228 return false;
3229}
3230
3231int
3232__codecvt_utf8<char32_t>::do_length(state_type&,
3233 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3234{
3235 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3236 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3237 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3238}
3239
3240int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003241__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003242{
3243 if (_Mode_ & consume_header)
3244 return 7;
3245 return 4;
3246}
3247
3248// __codecvt_utf16<wchar_t, false>
3249
3250__codecvt_utf16<wchar_t, false>::result
3251__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3252 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3253 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3254{
3255 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3256 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3257 const uint32_t* _frm_nxt = _frm;
3258 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3259 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3260 uint8_t* _to_nxt = _to;
3261 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3262 _Maxcode_, _Mode_);
3263 frm_nxt = frm + (_frm_nxt - _frm);
3264 to_nxt = to + (_to_nxt - _to);
3265 return r;
3266}
3267
3268__codecvt_utf16<wchar_t, false>::result
3269__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3270 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3271 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3272{
3273 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3274 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3275 const uint8_t* _frm_nxt = _frm;
3276 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3277 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3278 uint32_t* _to_nxt = _to;
3279 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3280 _Maxcode_, _Mode_);
3281 frm_nxt = frm + (_frm_nxt - _frm);
3282 to_nxt = to + (_to_nxt - _to);
3283 return r;
3284}
3285
3286__codecvt_utf16<wchar_t, false>::result
3287__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3288 extern_type* to, extern_type*, extern_type*& to_nxt) const
3289{
3290 to_nxt = to;
3291 return noconv;
3292}
3293
3294int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003295__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003296{
3297 return 0;
3298}
3299
3300bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003301__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003302{
3303 return false;
3304}
3305
3306int
3307__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3308 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3309{
3310 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3311 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3312 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3313}
3314
3315int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003316__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003317{
3318 if (_Mode_ & consume_header)
3319 return 6;
3320 return 4;
3321}
3322
3323// __codecvt_utf16<wchar_t, true>
3324
3325__codecvt_utf16<wchar_t, true>::result
3326__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3327 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3328 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3329{
3330 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3331 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3332 const uint32_t* _frm_nxt = _frm;
3333 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3334 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3335 uint8_t* _to_nxt = _to;
3336 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3337 _Maxcode_, _Mode_);
3338 frm_nxt = frm + (_frm_nxt - _frm);
3339 to_nxt = to + (_to_nxt - _to);
3340 return r;
3341}
3342
3343__codecvt_utf16<wchar_t, true>::result
3344__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3345 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3346 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3347{
3348 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3349 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3350 const uint8_t* _frm_nxt = _frm;
3351 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3352 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3353 uint32_t* _to_nxt = _to;
3354 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3355 _Maxcode_, _Mode_);
3356 frm_nxt = frm + (_frm_nxt - _frm);
3357 to_nxt = to + (_to_nxt - _to);
3358 return r;
3359}
3360
3361__codecvt_utf16<wchar_t, true>::result
3362__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3363 extern_type* to, extern_type*, extern_type*& to_nxt) const
3364{
3365 to_nxt = to;
3366 return noconv;
3367}
3368
3369int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003370__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003371{
3372 return 0;
3373}
3374
3375bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003376__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003377{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003378 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003379}
3380
3381int
3382__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3383 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3384{
3385 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3386 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3387 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3388}
3389
3390int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003391__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003392{
3393 if (_Mode_ & consume_header)
3394 return 6;
3395 return 4;
3396}
3397
3398// __codecvt_utf16<char16_t, false>
3399
3400__codecvt_utf16<char16_t, false>::result
3401__codecvt_utf16<char16_t, false>::do_out(state_type&,
3402 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3403 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3404{
3405 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3406 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3407 const uint16_t* _frm_nxt = _frm;
3408 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3409 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3410 uint8_t* _to_nxt = _to;
3411 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3412 _Maxcode_, _Mode_);
3413 frm_nxt = frm + (_frm_nxt - _frm);
3414 to_nxt = to + (_to_nxt - _to);
3415 return r;
3416}
3417
3418__codecvt_utf16<char16_t, false>::result
3419__codecvt_utf16<char16_t, false>::do_in(state_type&,
3420 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3421 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3422{
3423 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3424 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3425 const uint8_t* _frm_nxt = _frm;
3426 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3427 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3428 uint16_t* _to_nxt = _to;
3429 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3430 _Maxcode_, _Mode_);
3431 frm_nxt = frm + (_frm_nxt - _frm);
3432 to_nxt = to + (_to_nxt - _to);
3433 return r;
3434}
3435
3436__codecvt_utf16<char16_t, false>::result
3437__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3438 extern_type* to, extern_type*, extern_type*& to_nxt) const
3439{
3440 to_nxt = to;
3441 return noconv;
3442}
3443
3444int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003445__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003446{
3447 return 0;
3448}
3449
3450bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003451__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003452{
3453 return false;
3454}
3455
3456int
3457__codecvt_utf16<char16_t, false>::do_length(state_type&,
3458 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3459{
3460 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3461 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3462 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3463}
3464
3465int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003466__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003467{
3468 if (_Mode_ & consume_header)
3469 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003470 return 2;
3471}
3472
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003473// __codecvt_utf16<char16_t, true>
3474
3475__codecvt_utf16<char16_t, true>::result
3476__codecvt_utf16<char16_t, true>::do_out(state_type&,
3477 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3478 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3479{
3480 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3481 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3482 const uint16_t* _frm_nxt = _frm;
3483 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3484 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3485 uint8_t* _to_nxt = _to;
3486 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3487 _Maxcode_, _Mode_);
3488 frm_nxt = frm + (_frm_nxt - _frm);
3489 to_nxt = to + (_to_nxt - _to);
3490 return r;
3491}
3492
3493__codecvt_utf16<char16_t, true>::result
3494__codecvt_utf16<char16_t, true>::do_in(state_type&,
3495 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3496 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3497{
3498 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3499 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3500 const uint8_t* _frm_nxt = _frm;
3501 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3502 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3503 uint16_t* _to_nxt = _to;
3504 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3505 _Maxcode_, _Mode_);
3506 frm_nxt = frm + (_frm_nxt - _frm);
3507 to_nxt = to + (_to_nxt - _to);
3508 return r;
3509}
3510
3511__codecvt_utf16<char16_t, true>::result
3512__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3513 extern_type* to, extern_type*, extern_type*& to_nxt) const
3514{
3515 to_nxt = to;
3516 return noconv;
3517}
3518
3519int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003520__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003521{
3522 return 0;
3523}
3524
3525bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003526__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003527{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003528 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003529}
3530
3531int
3532__codecvt_utf16<char16_t, true>::do_length(state_type&,
3533 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3534{
3535 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3536 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3537 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3538}
3539
3540int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003541__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003542{
3543 if (_Mode_ & consume_header)
3544 return 4;
3545 return 2;
3546}
3547
3548// __codecvt_utf16<char32_t, false>
3549
3550__codecvt_utf16<char32_t, false>::result
3551__codecvt_utf16<char32_t, false>::do_out(state_type&,
3552 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3553 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3554{
3555 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3556 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3557 const uint32_t* _frm_nxt = _frm;
3558 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3559 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3560 uint8_t* _to_nxt = _to;
3561 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3562 _Maxcode_, _Mode_);
3563 frm_nxt = frm + (_frm_nxt - _frm);
3564 to_nxt = to + (_to_nxt - _to);
3565 return r;
3566}
3567
3568__codecvt_utf16<char32_t, false>::result
3569__codecvt_utf16<char32_t, false>::do_in(state_type&,
3570 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3571 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3572{
3573 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3574 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3575 const uint8_t* _frm_nxt = _frm;
3576 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3577 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3578 uint32_t* _to_nxt = _to;
3579 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3580 _Maxcode_, _Mode_);
3581 frm_nxt = frm + (_frm_nxt - _frm);
3582 to_nxt = to + (_to_nxt - _to);
3583 return r;
3584}
3585
3586__codecvt_utf16<char32_t, false>::result
3587__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3588 extern_type* to, extern_type*, extern_type*& to_nxt) const
3589{
3590 to_nxt = to;
3591 return noconv;
3592}
3593
3594int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003595__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003596{
3597 return 0;
3598}
3599
3600bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003601__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003602{
3603 return false;
3604}
3605
3606int
3607__codecvt_utf16<char32_t, false>::do_length(state_type&,
3608 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3609{
3610 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3611 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3612 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3613}
3614
3615int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003616__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003617{
3618 if (_Mode_ & consume_header)
3619 return 6;
3620 return 4;
3621}
3622
3623// __codecvt_utf16<char32_t, true>
3624
3625__codecvt_utf16<char32_t, true>::result
3626__codecvt_utf16<char32_t, true>::do_out(state_type&,
3627 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3628 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3629{
3630 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3631 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3632 const uint32_t* _frm_nxt = _frm;
3633 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3634 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3635 uint8_t* _to_nxt = _to;
3636 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3637 _Maxcode_, _Mode_);
3638 frm_nxt = frm + (_frm_nxt - _frm);
3639 to_nxt = to + (_to_nxt - _to);
3640 return r;
3641}
3642
3643__codecvt_utf16<char32_t, true>::result
3644__codecvt_utf16<char32_t, true>::do_in(state_type&,
3645 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3646 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3647{
3648 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3649 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3650 const uint8_t* _frm_nxt = _frm;
3651 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3652 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3653 uint32_t* _to_nxt = _to;
3654 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3655 _Maxcode_, _Mode_);
3656 frm_nxt = frm + (_frm_nxt - _frm);
3657 to_nxt = to + (_to_nxt - _to);
3658 return r;
3659}
3660
3661__codecvt_utf16<char32_t, true>::result
3662__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3663 extern_type* to, extern_type*, extern_type*& to_nxt) const
3664{
3665 to_nxt = to;
3666 return noconv;
3667}
3668
3669int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003670__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003671{
3672 return 0;
3673}
3674
3675bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003676__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003677{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003678 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003679}
3680
3681int
3682__codecvt_utf16<char32_t, true>::do_length(state_type&,
3683 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3684{
3685 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3686 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3687 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3688}
3689
3690int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003691__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003692{
3693 if (_Mode_ & consume_header)
3694 return 6;
3695 return 4;
3696}
3697
3698// __codecvt_utf8_utf16<wchar_t>
3699
3700__codecvt_utf8_utf16<wchar_t>::result
3701__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3702 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3703 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3704{
3705 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3706 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3707 const uint32_t* _frm_nxt = _frm;
3708 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3709 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3710 uint8_t* _to_nxt = _to;
3711 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3712 _Maxcode_, _Mode_);
3713 frm_nxt = frm + (_frm_nxt - _frm);
3714 to_nxt = to + (_to_nxt - _to);
3715 return r;
3716}
3717
3718__codecvt_utf8_utf16<wchar_t>::result
3719__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3720 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3721 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3722{
3723 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3724 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3725 const uint8_t* _frm_nxt = _frm;
3726 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3727 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3728 uint32_t* _to_nxt = _to;
3729 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3730 _Maxcode_, _Mode_);
3731 frm_nxt = frm + (_frm_nxt - _frm);
3732 to_nxt = to + (_to_nxt - _to);
3733 return r;
3734}
3735
3736__codecvt_utf8_utf16<wchar_t>::result
3737__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3738 extern_type* to, extern_type*, extern_type*& to_nxt) const
3739{
3740 to_nxt = to;
3741 return noconv;
3742}
3743
3744int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003745__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003746{
3747 return 0;
3748}
3749
3750bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003751__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003752{
3753 return false;
3754}
3755
3756int
3757__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3758 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3759{
3760 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3761 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3762 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3763}
3764
3765int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003766__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003767{
3768 if (_Mode_ & consume_header)
3769 return 7;
3770 return 4;
3771}
3772
3773// __codecvt_utf8_utf16<char16_t>
3774
3775__codecvt_utf8_utf16<char16_t>::result
3776__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3777 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3778 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3779{
3780 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3781 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3782 const uint16_t* _frm_nxt = _frm;
3783 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3784 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3785 uint8_t* _to_nxt = _to;
3786 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3787 _Maxcode_, _Mode_);
3788 frm_nxt = frm + (_frm_nxt - _frm);
3789 to_nxt = to + (_to_nxt - _to);
3790 return r;
3791}
3792
3793__codecvt_utf8_utf16<char16_t>::result
3794__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3795 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3796 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3797{
3798 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3799 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3800 const uint8_t* _frm_nxt = _frm;
3801 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3802 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3803 uint16_t* _to_nxt = _to;
3804 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3805 _Maxcode_, _Mode_);
3806 frm_nxt = frm + (_frm_nxt - _frm);
3807 to_nxt = to + (_to_nxt - _to);
3808 return r;
3809}
3810
3811__codecvt_utf8_utf16<char16_t>::result
3812__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3813 extern_type* to, extern_type*, extern_type*& to_nxt) const
3814{
3815 to_nxt = to;
3816 return noconv;
3817}
3818
3819int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003820__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003821{
3822 return 0;
3823}
3824
3825bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003826__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003827{
3828 return false;
3829}
3830
3831int
3832__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3833 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3834{
3835 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3836 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3837 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3838}
3839
3840int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003841__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003842{
3843 if (_Mode_ & consume_header)
3844 return 7;
3845 return 4;
3846}
3847
3848// __codecvt_utf8_utf16<char32_t>
3849
3850__codecvt_utf8_utf16<char32_t>::result
3851__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3852 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3853 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3854{
3855 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3856 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3857 const uint32_t* _frm_nxt = _frm;
3858 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3859 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3860 uint8_t* _to_nxt = _to;
3861 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3862 _Maxcode_, _Mode_);
3863 frm_nxt = frm + (_frm_nxt - _frm);
3864 to_nxt = to + (_to_nxt - _to);
3865 return r;
3866}
3867
3868__codecvt_utf8_utf16<char32_t>::result
3869__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3870 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3871 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3872{
3873 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3874 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3875 const uint8_t* _frm_nxt = _frm;
3876 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3877 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3878 uint32_t* _to_nxt = _to;
3879 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3880 _Maxcode_, _Mode_);
3881 frm_nxt = frm + (_frm_nxt - _frm);
3882 to_nxt = to + (_to_nxt - _to);
3883 return r;
3884}
3885
3886__codecvt_utf8_utf16<char32_t>::result
3887__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3888 extern_type* to, extern_type*, extern_type*& to_nxt) const
3889{
3890 to_nxt = to;
3891 return noconv;
3892}
3893
3894int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003895__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003896{
3897 return 0;
3898}
3899
3900bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003901__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003902{
3903 return false;
3904}
3905
3906int
3907__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3908 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3909{
3910 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3911 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3912 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3913}
3914
3915int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003916__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003917{
3918 if (_Mode_ & consume_header)
3919 return 7;
3920 return 4;
3921}
3922
Howard Hinnantc51e1022010-05-11 19:42:16 +00003923// __narrow_to_utf8<16>
3924
3925__narrow_to_utf8<16>::~__narrow_to_utf8()
3926{
3927}
3928
3929// __narrow_to_utf8<32>
3930
3931__narrow_to_utf8<32>::~__narrow_to_utf8()
3932{
3933}
3934
3935// __widen_from_utf8<16>
3936
3937__widen_from_utf8<16>::~__widen_from_utf8()
3938{
3939}
3940
3941// __widen_from_utf8<32>
3942
3943__widen_from_utf8<32>::~__widen_from_utf8()
3944{
3945}
3946
3947// numpunct<char> && numpunct<wchar_t>
3948
3949locale::id numpunct< char >::id;
3950locale::id numpunct<wchar_t>::id;
3951
3952numpunct<char>::numpunct(size_t refs)
3953 : locale::facet(refs),
3954 __decimal_point_('.'),
3955 __thousands_sep_(',')
3956{
3957}
3958
3959numpunct<wchar_t>::numpunct(size_t refs)
3960 : locale::facet(refs),
3961 __decimal_point_(L'.'),
3962 __thousands_sep_(L',')
3963{
3964}
3965
3966numpunct<char>::~numpunct()
3967{
3968}
3969
3970numpunct<wchar_t>::~numpunct()
3971{
3972}
3973
3974 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
3975wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
3976
3977 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
3978wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
3979
3980string numpunct< char >::do_grouping() const {return __grouping_;}
3981string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
3982
3983 string numpunct< char >::do_truename() const {return "true";}
3984wstring numpunct<wchar_t>::do_truename() const {return L"true";}
3985
3986 string numpunct< char >::do_falsename() const {return "false";}
3987wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
3988
3989// numpunct_byname<char>
3990
3991numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
3992 : numpunct<char>(refs)
3993{
3994 __init(nm);
3995}
3996
3997numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
3998 : numpunct<char>(refs)
3999{
4000 __init(nm.c_str());
4001}
4002
4003numpunct_byname<char>::~numpunct_byname()
4004{
4005}
4006
4007void
4008numpunct_byname<char>::__init(const char* nm)
4009{
4010 if (strcmp(nm, "C") != 0)
4011 {
Alexis Huntd4a24912011-07-13 06:40:50 +00004012 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004013#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004014 if (loc == 0)
4015 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4016 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004017#endif // _LIBCPP_NO_EXCEPTIONS
Alexis Huntd4a24912011-07-13 06:40:50 +00004018 lconv* lc = __localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004019 if (*lc->decimal_point)
4020 __decimal_point_ = *lc->decimal_point;
4021 if (*lc->thousands_sep)
4022 __thousands_sep_ = *lc->thousands_sep;
4023 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004024 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004025 }
4026}
4027
4028// numpunct_byname<wchar_t>
4029
4030numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4031 : numpunct<wchar_t>(refs)
4032{
4033 __init(nm);
4034}
4035
4036numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4037 : numpunct<wchar_t>(refs)
4038{
4039 __init(nm.c_str());
4040}
4041
4042numpunct_byname<wchar_t>::~numpunct_byname()
4043{
4044}
4045
4046void
4047numpunct_byname<wchar_t>::__init(const char* nm)
4048{
4049 if (strcmp(nm, "C") != 0)
4050 {
Alexis Huntd4a24912011-07-13 06:40:50 +00004051 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004052#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004053 if (loc == 0)
4054 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4055 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004056#endif // _LIBCPP_NO_EXCEPTIONS
Alexis Huntd4a24912011-07-13 06:40:50 +00004057 lconv* lc = __localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004058 if (*lc->decimal_point)
4059 __decimal_point_ = *lc->decimal_point;
4060 if (*lc->thousands_sep)
4061 __thousands_sep_ = *lc->thousands_sep;
4062 __grouping_ = lc->grouping;
4063 // locallization for truename and falsename is not available
4064 }
4065}
4066
4067// num_get helpers
4068
4069int
4070__num_get_base::__get_base(ios_base& iob)
4071{
4072 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4073 if (__basefield == ios_base::oct)
4074 return 8;
4075 else if (__basefield == ios_base::hex)
4076 return 16;
4077 else if (__basefield == 0)
4078 return 0;
4079 return 10;
4080}
4081
4082const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4083
4084void
4085__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4086 ios_base::iostate& __err)
4087{
4088 if (__grouping.size() != 0)
4089 {
4090 reverse(__g, __g_end);
4091 const char* __ig = __grouping.data();
4092 const char* __eg = __ig + __grouping.size();
4093 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4094 {
4095 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4096 {
4097 if (*__ig != *__r)
4098 {
4099 __err = ios_base::failbit;
4100 return;
4101 }
4102 }
4103 if (__eg - __ig > 1)
4104 ++__ig;
4105 }
4106 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4107 {
4108 if (*__ig < __g_end[-1] || __g_end[-1] == 0)
4109 __err = ios_base::failbit;
4110 }
4111 }
4112}
4113
4114void
4115__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4116 ios_base::fmtflags __flags)
4117{
4118 if (__flags & ios_base::showpos)
4119 *__fmtp++ = '+';
4120 if (__flags & ios_base::showbase)
4121 *__fmtp++ = '#';
4122 while(*__len)
4123 *__fmtp++ = *__len++;
4124 if ((__flags & ios_base::basefield) == ios_base::oct)
4125 *__fmtp = 'o';
4126 else if ((__flags & ios_base::basefield) == ios_base::hex)
4127 {
4128 if (__flags & ios_base::uppercase)
4129 *__fmtp = 'X';
4130 else
4131 *__fmtp = 'x';
4132 }
4133 else if (__signd)
4134 *__fmtp = 'd';
4135 else
4136 *__fmtp = 'u';
4137}
4138
4139bool
4140__num_put_base::__format_float(char* __fmtp, const char* __len,
4141 ios_base::fmtflags __flags)
4142{
4143 bool specify_precision = true;
4144 if (__flags & ios_base::showpos)
4145 *__fmtp++ = '+';
4146 if (__flags & ios_base::showpoint)
4147 *__fmtp++ = '#';
4148 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4149 bool uppercase = __flags & ios_base::uppercase;
4150 if (floatfield == (ios_base::fixed | ios_base::scientific))
4151 specify_precision = false;
4152 else
4153 {
4154 *__fmtp++ = '.';
4155 *__fmtp++ = '*';
4156 }
4157 while(*__len)
4158 *__fmtp++ = *__len++;
4159 if (floatfield == ios_base::fixed)
4160 {
4161 if (uppercase)
4162 *__fmtp = 'F';
4163 else
4164 *__fmtp = 'f';
4165 }
4166 else if (floatfield == ios_base::scientific)
4167 {
4168 if (uppercase)
4169 *__fmtp = 'E';
4170 else
4171 *__fmtp = 'e';
4172 }
4173 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4174 {
4175 if (uppercase)
4176 *__fmtp = 'A';
4177 else
4178 *__fmtp = 'a';
4179 }
4180 else
4181 {
4182 if (uppercase)
4183 *__fmtp = 'G';
4184 else
4185 *__fmtp = 'g';
4186 }
4187 return specify_precision;
4188}
4189
4190char*
4191__num_put_base::__identify_padding(char* __nb, char* __ne,
4192 const ios_base& __iob)
4193{
4194 switch (__iob.flags() & ios_base::adjustfield)
4195 {
4196 case ios_base::internal:
4197 if (__nb[0] == '-' || __nb[0] == '+')
4198 return __nb+1;
4199 if (__ne - __nb >= 2 && __nb[0] == '0'
4200 && (__nb[1] == 'x' || __nb[1] == 'X'))
4201 return __nb+2;
4202 break;
4203 case ios_base::left:
4204 return __ne;
4205 case ios_base::right:
4206 default:
4207 break;
4208 }
4209 return __nb;
4210}
4211
4212// time_get
4213
4214static
4215string*
4216init_weeks()
4217{
4218 static string weeks[14];
4219 weeks[0] = "Sunday";
4220 weeks[1] = "Monday";
4221 weeks[2] = "Tuesday";
4222 weeks[3] = "Wednesday";
4223 weeks[4] = "Thursday";
4224 weeks[5] = "Friday";
4225 weeks[6] = "Saturday";
4226 weeks[7] = "Sun";
4227 weeks[8] = "Mon";
4228 weeks[9] = "Tue";
4229 weeks[10] = "Wed";
4230 weeks[11] = "Thu";
4231 weeks[12] = "Fri";
4232 weeks[13] = "Sat";
4233 return weeks;
4234}
4235
4236static
4237wstring*
4238init_wweeks()
4239{
4240 static wstring weeks[14];
4241 weeks[0] = L"Sunday";
4242 weeks[1] = L"Monday";
4243 weeks[2] = L"Tuesday";
4244 weeks[3] = L"Wednesday";
4245 weeks[4] = L"Thursday";
4246 weeks[5] = L"Friday";
4247 weeks[6] = L"Saturday";
4248 weeks[7] = L"Sun";
4249 weeks[8] = L"Mon";
4250 weeks[9] = L"Tue";
4251 weeks[10] = L"Wed";
4252 weeks[11] = L"Thu";
4253 weeks[12] = L"Fri";
4254 weeks[13] = L"Sat";
4255 return weeks;
4256}
4257
4258template <>
4259const string*
4260__time_get_c_storage<char>::__weeks() const
4261{
4262 static const string* weeks = init_weeks();
4263 return weeks;
4264}
4265
4266template <>
4267const wstring*
4268__time_get_c_storage<wchar_t>::__weeks() const
4269{
4270 static const wstring* weeks = init_wweeks();
4271 return weeks;
4272}
4273
4274static
4275string*
4276init_months()
4277{
4278 static string months[24];
4279 months[0] = "January";
4280 months[1] = "February";
4281 months[2] = "March";
4282 months[3] = "April";
4283 months[4] = "May";
4284 months[5] = "June";
4285 months[6] = "July";
4286 months[7] = "August";
4287 months[8] = "September";
4288 months[9] = "October";
4289 months[10] = "November";
4290 months[11] = "December";
4291 months[12] = "Jan";
4292 months[13] = "Feb";
4293 months[14] = "Mar";
4294 months[15] = "Apr";
4295 months[16] = "May";
4296 months[17] = "Jun";
4297 months[18] = "Jul";
4298 months[19] = "Aug";
4299 months[20] = "Sep";
4300 months[21] = "Oct";
4301 months[22] = "Nov";
4302 months[23] = "Dec";
4303 return months;
4304}
4305
4306static
4307wstring*
4308init_wmonths()
4309{
4310 static wstring months[24];
4311 months[0] = L"January";
4312 months[1] = L"February";
4313 months[2] = L"March";
4314 months[3] = L"April";
4315 months[4] = L"May";
4316 months[5] = L"June";
4317 months[6] = L"July";
4318 months[7] = L"August";
4319 months[8] = L"September";
4320 months[9] = L"October";
4321 months[10] = L"November";
4322 months[11] = L"December";
4323 months[12] = L"Jan";
4324 months[13] = L"Feb";
4325 months[14] = L"Mar";
4326 months[15] = L"Apr";
4327 months[16] = L"May";
4328 months[17] = L"Jun";
4329 months[18] = L"Jul";
4330 months[19] = L"Aug";
4331 months[20] = L"Sep";
4332 months[21] = L"Oct";
4333 months[22] = L"Nov";
4334 months[23] = L"Dec";
4335 return months;
4336}
4337
4338template <>
4339const string*
4340__time_get_c_storage<char>::__months() const
4341{
4342 static const string* months = init_months();
4343 return months;
4344}
4345
4346template <>
4347const wstring*
4348__time_get_c_storage<wchar_t>::__months() const
4349{
4350 static const wstring* months = init_wmonths();
4351 return months;
4352}
4353
4354static
4355string*
4356init_am_pm()
4357{
4358 static string am_pm[24];
4359 am_pm[0] = "AM";
4360 am_pm[1] = "PM";
4361 return am_pm;
4362}
4363
4364static
4365wstring*
4366init_wam_pm()
4367{
4368 static wstring am_pm[24];
4369 am_pm[0] = L"AM";
4370 am_pm[1] = L"PM";
4371 return am_pm;
4372}
4373
4374template <>
4375const string*
4376__time_get_c_storage<char>::__am_pm() const
4377{
4378 static const string* am_pm = init_am_pm();
4379 return am_pm;
4380}
4381
4382template <>
4383const wstring*
4384__time_get_c_storage<wchar_t>::__am_pm() const
4385{
4386 static const wstring* am_pm = init_wam_pm();
4387 return am_pm;
4388}
4389
4390template <>
4391const string&
4392__time_get_c_storage<char>::__x() const
4393{
4394 static string s("%m/%d/%y");
4395 return s;
4396}
4397
4398template <>
4399const wstring&
4400__time_get_c_storage<wchar_t>::__x() const
4401{
4402 static wstring s(L"%m/%d/%y");
4403 return s;
4404}
4405
4406template <>
4407const string&
4408__time_get_c_storage<char>::__X() const
4409{
4410 static string s("%H:%M:%S");
4411 return s;
4412}
4413
4414template <>
4415const wstring&
4416__time_get_c_storage<wchar_t>::__X() const
4417{
4418 static wstring s(L"%H:%M:%S");
4419 return s;
4420}
4421
4422template <>
4423const string&
4424__time_get_c_storage<char>::__c() const
4425{
4426 static string s("%a %b %d %H:%M:%S %Y");
4427 return s;
4428}
4429
4430template <>
4431const wstring&
4432__time_get_c_storage<wchar_t>::__c() const
4433{
4434 static wstring s(L"%a %b %d %H:%M:%S %Y");
4435 return s;
4436}
4437
4438template <>
4439const string&
4440__time_get_c_storage<char>::__r() const
4441{
4442 static string s("%I:%M:%S %p");
4443 return s;
4444}
4445
4446template <>
4447const wstring&
4448__time_get_c_storage<wchar_t>::__r() const
4449{
4450 static wstring s(L"%I:%M:%S %p");
4451 return s;
4452}
4453
4454// time_get_byname
4455
4456__time_get::__time_get(const char* nm)
4457 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4458{
Howard Hinnant72f73582010-08-11 17:04:31 +00004459#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004460 if (__loc_ == 0)
4461 throw runtime_error("time_get_byname"
4462 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004463#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004464}
4465
4466__time_get::__time_get(const string& nm)
4467 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4468{
Howard Hinnant72f73582010-08-11 17:04:31 +00004469#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004470 if (__loc_ == 0)
4471 throw runtime_error("time_get_byname"
4472 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00004473#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004474}
4475
4476__time_get::~__time_get()
4477{
4478 freelocale(__loc_);
4479}
4480
4481template <>
4482string
4483__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4484{
4485 tm t;
4486 t.tm_sec = 59;
4487 t.tm_min = 55;
4488 t.tm_hour = 23;
4489 t.tm_mday = 31;
4490 t.tm_mon = 11;
4491 t.tm_year = 161;
4492 t.tm_wday = 6;
4493 t.tm_yday = 364;
4494 t.tm_isdst = -1;
4495 char buf[100];
4496 char f[3] = {0};
4497 f[0] = '%';
4498 f[1] = fmt;
4499 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4500 char* bb = buf;
4501 char* be = buf + n;
4502 string result;
4503 while (bb != be)
4504 {
4505 if (ct.is(ctype_base::space, *bb))
4506 {
4507 result.push_back(' ');
4508 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4509 ;
4510 continue;
4511 }
4512 char* w = bb;
4513 ios_base::iostate err = ios_base::goodbit;
4514 int i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4515 ct, err, false)
4516 - this->__weeks_;
4517 if (i < 14)
4518 {
4519 result.push_back('%');
4520 if (i < 7)
4521 result.push_back('A');
4522 else
4523 result.push_back('a');
4524 bb = w;
4525 continue;
4526 }
4527 w = bb;
4528 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4529 ct, err, false)
4530 - this->__months_;
4531 if (i < 24)
4532 {
4533 result.push_back('%');
4534 if (i < 12)
4535 result.push_back('B');
4536 else
4537 result.push_back('b');
4538 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4539 result.back() = 'm';
4540 bb = w;
4541 continue;
4542 }
4543 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4544 {
4545 w = bb;
4546 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4547 ct, err, false) - this->__am_pm_;
4548 if (i < 2)
4549 {
4550 result.push_back('%');
4551 result.push_back('p');
4552 bb = w;
4553 continue;
4554 }
4555 }
4556 w = bb;
4557 if (ct.is(ctype_base::digit, *bb))
4558 {
4559 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4560 {
4561 case 6:
4562 result.push_back('%');
4563 result.push_back('w');
4564 break;
4565 case 7:
4566 result.push_back('%');
4567 result.push_back('u');
4568 break;
4569 case 11:
4570 result.push_back('%');
4571 result.push_back('I');
4572 break;
4573 case 12:
4574 result.push_back('%');
4575 result.push_back('m');
4576 break;
4577 case 23:
4578 result.push_back('%');
4579 result.push_back('H');
4580 break;
4581 case 31:
4582 result.push_back('%');
4583 result.push_back('d');
4584 break;
4585 case 55:
4586 result.push_back('%');
4587 result.push_back('M');
4588 break;
4589 case 59:
4590 result.push_back('%');
4591 result.push_back('S');
4592 break;
4593 case 61:
4594 result.push_back('%');
4595 result.push_back('y');
4596 break;
4597 case 364:
4598 result.push_back('%');
4599 result.push_back('j');
4600 break;
4601 case 2061:
4602 result.push_back('%');
4603 result.push_back('Y');
4604 break;
4605 default:
4606 for (; w != bb; ++w)
4607 result.push_back(*w);
4608 break;
4609 }
4610 continue;
4611 }
4612 if (*bb == '%')
4613 {
4614 result.push_back('%');
4615 result.push_back('%');
4616 ++bb;
4617 continue;
4618 }
4619 result.push_back(*bb);
4620 ++bb;
4621 }
4622 return result;
4623}
4624
4625template <>
4626wstring
4627__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4628{
4629 tm t;
4630 t.tm_sec = 59;
4631 t.tm_min = 55;
4632 t.tm_hour = 23;
4633 t.tm_mday = 31;
4634 t.tm_mon = 11;
4635 t.tm_year = 161;
4636 t.tm_wday = 6;
4637 t.tm_yday = 364;
4638 t.tm_isdst = -1;
4639 char buf[100];
4640 char f[3] = {0};
4641 f[0] = '%';
4642 f[1] = fmt;
4643 size_t be = strftime_l(buf, 100, f, &t, __loc_);
4644 wchar_t wbuf[100];
4645 wchar_t* wbb = wbuf;
4646 mbstate_t mb = {0};
4647 const char* bb = buf;
Alexis Huntd4a24912011-07-13 06:40:50 +00004648 size_t i = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004649 if (i == -1)
4650 __throw_runtime_error("locale not supported");
4651 wchar_t* wbe = wbb + i;
4652 wstring result;
4653 while (wbb != wbe)
4654 {
4655 if (ct.is(ctype_base::space, *wbb))
4656 {
4657 result.push_back(L' ');
4658 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4659 ;
4660 continue;
4661 }
4662 wchar_t* w = wbb;
4663 ios_base::iostate err = ios_base::goodbit;
4664 int i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4665 ct, err, false)
4666 - this->__weeks_;
4667 if (i < 14)
4668 {
4669 result.push_back(L'%');
4670 if (i < 7)
4671 result.push_back(L'A');
4672 else
4673 result.push_back(L'a');
4674 wbb = w;
4675 continue;
4676 }
4677 w = wbb;
4678 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4679 ct, err, false)
4680 - this->__months_;
4681 if (i < 24)
4682 {
4683 result.push_back(L'%');
4684 if (i < 12)
4685 result.push_back(L'B');
4686 else
4687 result.push_back(L'b');
4688 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4689 result.back() = L'm';
4690 wbb = w;
4691 continue;
4692 }
4693 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4694 {
4695 w = wbb;
4696 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4697 ct, err, false) - this->__am_pm_;
4698 if (i < 2)
4699 {
4700 result.push_back(L'%');
4701 result.push_back(L'p');
4702 wbb = w;
4703 continue;
4704 }
4705 }
4706 w = wbb;
4707 if (ct.is(ctype_base::digit, *wbb))
4708 {
4709 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4710 {
4711 case 6:
4712 result.push_back(L'%');
4713 result.push_back(L'w');
4714 break;
4715 case 7:
4716 result.push_back(L'%');
4717 result.push_back(L'u');
4718 break;
4719 case 11:
4720 result.push_back(L'%');
4721 result.push_back(L'I');
4722 break;
4723 case 12:
4724 result.push_back(L'%');
4725 result.push_back(L'm');
4726 break;
4727 case 23:
4728 result.push_back(L'%');
4729 result.push_back(L'H');
4730 break;
4731 case 31:
4732 result.push_back(L'%');
4733 result.push_back(L'd');
4734 break;
4735 case 55:
4736 result.push_back(L'%');
4737 result.push_back(L'M');
4738 break;
4739 case 59:
4740 result.push_back(L'%');
4741 result.push_back(L'S');
4742 break;
4743 case 61:
4744 result.push_back(L'%');
4745 result.push_back(L'y');
4746 break;
4747 case 364:
4748 result.push_back(L'%');
4749 result.push_back(L'j');
4750 break;
4751 case 2061:
4752 result.push_back(L'%');
4753 result.push_back(L'Y');
4754 break;
4755 default:
4756 for (; w != wbb; ++w)
4757 result.push_back(*w);
4758 break;
4759 }
4760 continue;
4761 }
4762 if (ct.narrow(*wbb, 0) == '%')
4763 {
4764 result.push_back(L'%');
4765 result.push_back(L'%');
4766 ++wbb;
4767 continue;
4768 }
4769 result.push_back(*wbb);
4770 ++wbb;
4771 }
4772 return result;
4773}
4774
4775template <>
4776void
4777__time_get_storage<char>::init(const ctype<char>& ct)
4778{
4779 tm t;
4780 char buf[100];
4781 // __weeks_
4782 for (int i = 0; i < 7; ++i)
4783 {
4784 t.tm_wday = i;
4785 strftime_l(buf, 100, "%A", &t, __loc_);
4786 __weeks_[i] = buf;
4787 strftime_l(buf, 100, "%a", &t, __loc_);
4788 __weeks_[i+7] = buf;
4789 }
4790 // __months_
4791 for (int i = 0; i < 12; ++i)
4792 {
4793 t.tm_mon = i;
4794 strftime_l(buf, 100, "%B", &t, __loc_);
4795 __months_[i] = buf;
4796 strftime_l(buf, 100, "%b", &t, __loc_);
4797 __months_[i+12] = buf;
4798 }
4799 // __am_pm_
4800 t.tm_hour = 1;
4801 strftime_l(buf, 100, "%p", &t, __loc_);
4802 __am_pm_[0] = buf;
4803 t.tm_hour = 13;
4804 strftime_l(buf, 100, "%p", &t, __loc_);
4805 __am_pm_[1] = buf;
4806 __c_ = __analyze('c', ct);
4807 __r_ = __analyze('r', ct);
4808 __x_ = __analyze('x', ct);
4809 __X_ = __analyze('X', ct);
4810}
4811
4812template <>
4813void
4814__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4815{
4816 tm t = {0};
4817 char buf[100];
4818 size_t be;
4819 wchar_t wbuf[100];
4820 wchar_t* wbe;
4821 mbstate_t mb = {0};
4822 // __weeks_
4823 for (int i = 0; i < 7; ++i)
4824 {
4825 t.tm_wday = i;
4826 be = strftime_l(buf, 100, "%A", &t, __loc_);
4827 mb = mbstate_t();
4828 const char* bb = buf;
Alexis Huntd4a24912011-07-13 06:40:50 +00004829 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004830 if (j == -1)
4831 __throw_runtime_error("locale not supported");
4832 wbe = wbuf + j;
4833 __weeks_[i].assign(wbuf, wbe);
4834 be = strftime_l(buf, 100, "%a", &t, __loc_);
4835 mb = mbstate_t();
4836 bb = buf;
Alexis Huntd4a24912011-07-13 06:40:50 +00004837 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004838 if (j == -1)
4839 __throw_runtime_error("locale not supported");
4840 wbe = wbuf + j;
4841 __weeks_[i+7].assign(wbuf, wbe);
4842 }
4843 // __months_
4844 for (int i = 0; i < 12; ++i)
4845 {
4846 t.tm_mon = i;
4847 be = strftime_l(buf, 100, "%B", &t, __loc_);
4848 mb = mbstate_t();
4849 const char* bb = buf;
Alexis Huntd4a24912011-07-13 06:40:50 +00004850 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004851 if (j == -1)
4852 __throw_runtime_error("locale not supported");
4853 wbe = wbuf + j;
4854 __months_[i].assign(wbuf, wbe);
4855 be = strftime_l(buf, 100, "%b", &t, __loc_);
4856 mb = mbstate_t();
4857 bb = buf;
Alexis Huntd4a24912011-07-13 06:40:50 +00004858 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004859 if (j == -1)
4860 __throw_runtime_error("locale not supported");
4861 wbe = wbuf + j;
4862 __months_[i+12].assign(wbuf, wbe);
4863 }
4864 // __am_pm_
4865 t.tm_hour = 1;
4866 be = strftime_l(buf, 100, "%p", &t, __loc_);
4867 mb = mbstate_t();
4868 const char* bb = buf;
Alexis Huntd4a24912011-07-13 06:40:50 +00004869 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004870 if (j == -1)
4871 __throw_runtime_error("locale not supported");
4872 wbe = wbuf + j;
4873 __am_pm_[0].assign(wbuf, wbe);
4874 t.tm_hour = 13;
4875 be = strftime_l(buf, 100, "%p", &t, __loc_);
4876 mb = mbstate_t();
4877 bb = buf;
Alexis Huntd4a24912011-07-13 06:40:50 +00004878 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004879 if (j == -1)
4880 __throw_runtime_error("locale not supported");
4881 wbe = wbuf + j;
4882 __am_pm_[1].assign(wbuf, wbe);
4883 __c_ = __analyze('c', ct);
4884 __r_ = __analyze('r', ct);
4885 __x_ = __analyze('x', ct);
4886 __X_ = __analyze('X', ct);
4887}
4888
4889template <class CharT>
4890struct _LIBCPP_HIDDEN __time_get_temp
4891 : public ctype_byname<CharT>
4892{
4893 explicit __time_get_temp(const char* nm)
4894 : ctype_byname<CharT>(nm, 1) {}
4895 explicit __time_get_temp(const string& nm)
4896 : ctype_byname<CharT>(nm, 1) {}
4897};
4898
4899template <>
4900__time_get_storage<char>::__time_get_storage(const char* __nm)
4901 : __time_get(__nm)
4902{
4903 const __time_get_temp<char> ct(__nm);
4904 init(ct);
4905}
4906
4907template <>
4908__time_get_storage<char>::__time_get_storage(const string& __nm)
4909 : __time_get(__nm)
4910{
4911 const __time_get_temp<char> ct(__nm);
4912 init(ct);
4913}
4914
4915template <>
4916__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
4917 : __time_get(__nm)
4918{
4919 const __time_get_temp<wchar_t> ct(__nm);
4920 init(ct);
4921}
4922
4923template <>
4924__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
4925 : __time_get(__nm)
4926{
4927 const __time_get_temp<wchar_t> ct(__nm);
4928 init(ct);
4929}
4930
4931template <>
4932time_base::dateorder
4933__time_get_storage<char>::__do_date_order() const
4934{
4935 unsigned i;
4936 for (i = 0; i < __x_.size(); ++i)
4937 if (__x_[i] == '%')
4938 break;
4939 ++i;
4940 switch (__x_[i])
4941 {
4942 case 'y':
4943 case 'Y':
4944 for (++i; i < __x_.size(); ++i)
4945 if (__x_[i] == '%')
4946 break;
4947 if (i == __x_.size())
4948 break;
4949 ++i;
4950 switch (__x_[i])
4951 {
4952 case 'm':
4953 for (++i; i < __x_.size(); ++i)
4954 if (__x_[i] == '%')
4955 break;
4956 if (i == __x_.size())
4957 break;
4958 ++i;
4959 if (__x_[i] == 'd')
4960 return time_base::ymd;
4961 break;
4962 case 'd':
4963 for (++i; i < __x_.size(); ++i)
4964 if (__x_[i] == '%')
4965 break;
4966 if (i == __x_.size())
4967 break;
4968 ++i;
4969 if (__x_[i] == 'm')
4970 return time_base::ydm;
4971 break;
4972 }
4973 break;
4974 case 'm':
4975 for (++i; i < __x_.size(); ++i)
4976 if (__x_[i] == '%')
4977 break;
4978 if (i == __x_.size())
4979 break;
4980 ++i;
4981 if (__x_[i] == 'd')
4982 {
4983 for (++i; i < __x_.size(); ++i)
4984 if (__x_[i] == '%')
4985 break;
4986 if (i == __x_.size())
4987 break;
4988 ++i;
4989 if (__x_[i] == 'y' || __x_[i] == 'Y')
4990 return time_base::mdy;
4991 break;
4992 }
4993 break;
4994 case 'd':
4995 for (++i; i < __x_.size(); ++i)
4996 if (__x_[i] == '%')
4997 break;
4998 if (i == __x_.size())
4999 break;
5000 ++i;
5001 if (__x_[i] == 'm')
5002 {
5003 for (++i; i < __x_.size(); ++i)
5004 if (__x_[i] == '%')
5005 break;
5006 if (i == __x_.size())
5007 break;
5008 ++i;
5009 if (__x_[i] == 'y' || __x_[i] == 'Y')
5010 return time_base::dmy;
5011 break;
5012 }
5013 break;
5014 }
5015 return time_base::no_order;
5016}
5017
5018template <>
5019time_base::dateorder
5020__time_get_storage<wchar_t>::__do_date_order() const
5021{
5022 unsigned i;
5023 for (i = 0; i < __x_.size(); ++i)
5024 if (__x_[i] == L'%')
5025 break;
5026 ++i;
5027 switch (__x_[i])
5028 {
5029 case L'y':
5030 case L'Y':
5031 for (++i; i < __x_.size(); ++i)
5032 if (__x_[i] == L'%')
5033 break;
5034 if (i == __x_.size())
5035 break;
5036 ++i;
5037 switch (__x_[i])
5038 {
5039 case L'm':
5040 for (++i; i < __x_.size(); ++i)
5041 if (__x_[i] == L'%')
5042 break;
5043 if (i == __x_.size())
5044 break;
5045 ++i;
5046 if (__x_[i] == L'd')
5047 return time_base::ymd;
5048 break;
5049 case L'd':
5050 for (++i; i < __x_.size(); ++i)
5051 if (__x_[i] == L'%')
5052 break;
5053 if (i == __x_.size())
5054 break;
5055 ++i;
5056 if (__x_[i] == L'm')
5057 return time_base::ydm;
5058 break;
5059 }
5060 break;
5061 case L'm':
5062 for (++i; i < __x_.size(); ++i)
5063 if (__x_[i] == L'%')
5064 break;
5065 if (i == __x_.size())
5066 break;
5067 ++i;
5068 if (__x_[i] == L'd')
5069 {
5070 for (++i; i < __x_.size(); ++i)
5071 if (__x_[i] == L'%')
5072 break;
5073 if (i == __x_.size())
5074 break;
5075 ++i;
5076 if (__x_[i] == L'y' || __x_[i] == L'Y')
5077 return time_base::mdy;
5078 break;
5079 }
5080 break;
5081 case L'd':
5082 for (++i; i < __x_.size(); ++i)
5083 if (__x_[i] == L'%')
5084 break;
5085 if (i == __x_.size())
5086 break;
5087 ++i;
5088 if (__x_[i] == L'm')
5089 {
5090 for (++i; i < __x_.size(); ++i)
5091 if (__x_[i] == L'%')
5092 break;
5093 if (i == __x_.size())
5094 break;
5095 ++i;
5096 if (__x_[i] == L'y' || __x_[i] == L'Y')
5097 return time_base::dmy;
5098 break;
5099 }
5100 break;
5101 }
5102 return time_base::no_order;
5103}
5104
5105// time_put
5106
5107__time_put::__time_put(const char* nm)
5108 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5109{
Howard Hinnant72f73582010-08-11 17:04:31 +00005110#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005111 if (__loc_ == 0)
5112 throw runtime_error("time_put_byname"
5113 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005114#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005115}
5116
5117__time_put::__time_put(const string& nm)
5118 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5119{
Howard Hinnant72f73582010-08-11 17:04:31 +00005120#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005121 if (__loc_ == 0)
5122 throw runtime_error("time_put_byname"
5123 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00005124#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005125}
5126
5127__time_put::~__time_put()
5128{
5129 if (__loc_)
5130 freelocale(__loc_);
5131}
5132
5133void
5134__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5135 char __fmt, char __mod) const
5136{
5137 char fmt[] = {'%', __fmt, __mod, 0};
5138 if (__mod != 0)
5139 swap(fmt[1], fmt[2]);
5140 size_t n = strftime_l(__nb, __ne-__nb, fmt, __tm, __loc_);
5141 __ne = __nb + n;
5142}
5143
5144void
5145__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5146 char __fmt, char __mod) const
5147{
5148 char __nar[100];
5149 char* __ne = __nar + 100;
5150 __do_put(__nar, __ne, __tm, __fmt, __mod);
5151 mbstate_t mb = {0};
5152 const char* __nb = __nar;
Alexis Huntd4a24912011-07-13 06:40:50 +00005153 size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005154 if (j == -1)
5155 __throw_runtime_error("locale not supported");
5156 __we = __wb + j;
5157}
5158
5159// moneypunct_byname
5160
5161static
5162void
5163__init_pat(money_base::pattern& pat, char cs_precedes, char sep_by_space, char sign_posn)
5164{
5165 const char sign = static_cast<char>(money_base::sign);
5166 const char space = static_cast<char>(money_base::space);
5167 const char none = static_cast<char>(money_base::none);
5168 const char symbol = static_cast<char>(money_base::symbol);
5169 const char value = static_cast<char>(money_base::value);
5170 switch (cs_precedes)
5171 {
5172 case 0:
5173 switch (sign_posn)
5174 {
5175 case 0:
5176 pat.field[0] = sign;
5177 pat.field[1] = value;
5178 pat.field[3] = symbol;
5179 switch (sep_by_space)
5180 {
5181 case 0:
5182 pat.field[2] = none;
5183 return;
5184 case 1:
5185 case 2:
5186 pat.field[2] = space;
5187 return;
5188 default:
5189 break;
5190 }
5191 break;
5192 case 1:
5193 pat.field[0] = sign;
5194 pat.field[3] = symbol;
5195 switch (sep_by_space)
5196 {
5197 case 0:
5198 pat.field[1] = value;
5199 pat.field[2] = none;
5200 return;
5201 case 1:
5202 pat.field[1] = value;
5203 pat.field[2] = space;
5204 return;
5205 case 2:
5206 pat.field[1] = space;
5207 pat.field[2] = value;
5208 return;
5209 default:
5210 break;
5211 }
5212 break;
5213 case 2:
5214 pat.field[0] = value;
5215 pat.field[3] = sign;
5216 switch (sep_by_space)
5217 {
5218 case 0:
5219 pat.field[1] = none;
5220 pat.field[2] = symbol;
5221 return;
5222 case 1:
5223 pat.field[1] = space;
5224 pat.field[2] = symbol;
5225 return;
5226 case 2:
5227 pat.field[1] = symbol;
5228 pat.field[2] = space;
5229 return;
5230 default:
5231 break;
5232 }
5233 break;
5234 case 3:
5235 pat.field[0] = value;
5236 pat.field[3] = symbol;
5237 switch (sep_by_space)
5238 {
5239 case 0:
5240 pat.field[1] = none;
5241 pat.field[2] = sign;
5242 return;
5243 case 1:
5244 pat.field[1] = space;
5245 pat.field[2] = sign;
5246 return;
5247 case 2:
5248 pat.field[1] = sign;
5249 pat.field[2] = space;
5250 return;
5251 default:
5252 break;
5253 }
5254 break;
5255 case 4:
5256 pat.field[0] = value;
5257 pat.field[3] = sign;
5258 switch (sep_by_space)
5259 {
5260 case 0:
5261 pat.field[1] = none;
5262 pat.field[2] = symbol;
5263 return;
5264 case 1:
5265 pat.field[1] = space;
5266 pat.field[2] = symbol;
5267 return;
5268 case 2:
5269 pat.field[1] = symbol;
5270 pat.field[2] = space;
5271 return;
5272 default:
5273 break;
5274 }
5275 break;
5276 default:
5277 break;
5278 }
5279 break;
5280 case 1:
5281 switch (sign_posn)
5282 {
5283 case 0:
5284 pat.field[0] = sign;
5285 pat.field[1] = symbol;
5286 pat.field[3] = value;
5287 switch (sep_by_space)
5288 {
5289 case 0:
5290 pat.field[2] = none;
5291 return;
5292 case 1:
5293 case 2:
5294 pat.field[2] = space;
5295 return;
5296 default:
5297 break;
5298 }
5299 break;
5300 case 1:
5301 pat.field[0] = sign;
5302 pat.field[3] = value;
5303 switch (sep_by_space)
5304 {
5305 case 0:
5306 pat.field[1] = symbol;
5307 pat.field[2] = none;
5308 return;
5309 case 1:
5310 pat.field[1] = symbol;
5311 pat.field[2] = space;
5312 return;
5313 case 2:
5314 pat.field[1] = space;
5315 pat.field[2] = symbol;
5316 return;
5317 default:
5318 break;
5319 }
5320 break;
5321 case 2:
5322 pat.field[0] = symbol;
5323 pat.field[3] = sign;
5324 switch (sep_by_space)
5325 {
5326 case 0:
5327 pat.field[1] = none;
5328 pat.field[2] = value;
5329 return;
5330 case 1:
5331 pat.field[1] = space;
5332 pat.field[2] = value;
5333 return;
5334 case 2:
5335 pat.field[1] = value;
5336 pat.field[2] = space;
5337 return;
5338 default:
5339 break;
5340 }
5341 break;
5342 case 3:
5343 pat.field[0] = sign;
5344 pat.field[3] = value;
5345 switch (sep_by_space)
5346 {
5347 case 0:
5348 pat.field[1] = symbol;
5349 pat.field[2] = none;
5350 return;
5351 case 1:
5352 pat.field[1] = symbol;
5353 pat.field[2] = space;
5354 return;
5355 case 2:
5356 pat.field[1] = space;
5357 pat.field[2] = symbol;
5358 return;
5359 default:
5360 break;
5361 }
5362 break;
5363 case 4:
5364 pat.field[0] = symbol;
5365 pat.field[3] = value;
5366 switch (sep_by_space)
5367 {
5368 case 0:
5369 pat.field[1] = sign;
5370 pat.field[2] = none;
5371 return;
5372 case 1:
5373 pat.field[1] = sign;
5374 pat.field[2] = space;
5375 return;
5376 case 2:
5377 pat.field[1] = space;
5378 pat.field[2] = sign;
5379 return;
5380 default:
5381 break;
5382 }
5383 break;
5384 default:
5385 break;
5386 }
5387 break;
5388 default:
5389 break;
5390 }
5391 pat.field[0] = symbol;
5392 pat.field[1] = sign;
5393 pat.field[2] = none;
5394 pat.field[3] = value;
5395}
5396
5397template<>
5398void
5399moneypunct_byname<char, false>::init(const char* nm)
5400{
5401 typedef moneypunct<char, false> base;
Alexis Huntd4a24912011-07-13 06:40:50 +00005402 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005403#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005404 if (loc == 0)
5405 throw runtime_error("moneypunct_byname"
5406 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005407#endif // _LIBCPP_NO_EXCEPTIONS
Alexis Huntd4a24912011-07-13 06:40:50 +00005408 lconv* lc = __localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005409 if (*lc->mon_decimal_point)
5410 __decimal_point_ = *lc->mon_decimal_point;
5411 else
5412 __decimal_point_ = base::do_decimal_point();
5413 if (*lc->mon_thousands_sep)
5414 __thousands_sep_ = *lc->mon_thousands_sep;
5415 else
5416 __thousands_sep_ = base::do_thousands_sep();
5417 __grouping_ = lc->mon_grouping;
5418 __curr_symbol_ = lc->currency_symbol;
5419 if (lc->frac_digits != CHAR_MAX)
5420 __frac_digits_ = lc->frac_digits;
5421 else
5422 __frac_digits_ = base::do_frac_digits();
5423 if (lc->p_sign_posn == 0)
5424 __positive_sign_ = "()";
5425 else
5426 __positive_sign_ = lc->positive_sign;
5427 if (lc->n_sign_posn == 0)
5428 __negative_sign_ = "()";
5429 else
5430 __negative_sign_ = lc->negative_sign;
5431 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5432 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5433}
5434
5435template<>
5436void
5437moneypunct_byname<char, true>::init(const char* nm)
5438{
5439 typedef moneypunct<char, true> base;
Alexis Huntd4a24912011-07-13 06:40:50 +00005440 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005441#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005442 if (loc == 0)
5443 throw runtime_error("moneypunct_byname"
5444 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005445#endif // _LIBCPP_NO_EXCEPTIONS
Alexis Huntd4a24912011-07-13 06:40:50 +00005446 lconv* lc = __localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005447 if (*lc->mon_decimal_point)
5448 __decimal_point_ = *lc->mon_decimal_point;
5449 else
5450 __decimal_point_ = base::do_decimal_point();
5451 if (*lc->mon_thousands_sep)
5452 __thousands_sep_ = *lc->mon_thousands_sep;
5453 else
5454 __thousands_sep_ = base::do_thousands_sep();
5455 __grouping_ = lc->mon_grouping;
5456 __curr_symbol_ = lc->int_curr_symbol;
5457 if (lc->int_frac_digits != CHAR_MAX)
5458 __frac_digits_ = lc->int_frac_digits;
5459 else
5460 __frac_digits_ = base::do_frac_digits();
5461 if (lc->int_p_sign_posn == 0)
5462 __positive_sign_ = "()";
5463 else
5464 __positive_sign_ = lc->positive_sign;
5465 if (lc->int_n_sign_posn == 0)
5466 __negative_sign_ = "()";
5467 else
5468 __negative_sign_ = lc->negative_sign;
5469 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5470 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
5471}
5472
5473template<>
5474void
5475moneypunct_byname<wchar_t, false>::init(const char* nm)
5476{
5477 typedef moneypunct<wchar_t, false> base;
Alexis Huntd4a24912011-07-13 06:40:50 +00005478 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005479#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005480 if (loc == 0)
5481 throw runtime_error("moneypunct_byname"
5482 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005483#endif // _LIBCPP_NO_EXCEPTIONS
Alexis Huntd4a24912011-07-13 06:40:50 +00005484 lconv* lc = __localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005485 if (*lc->mon_decimal_point)
5486 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5487 else
5488 __decimal_point_ = base::do_decimal_point();
5489 if (*lc->mon_thousands_sep)
5490 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5491 else
5492 __thousands_sep_ = base::do_thousands_sep();
5493 __grouping_ = lc->mon_grouping;
5494 wchar_t wbuf[100];
5495 mbstate_t mb = {0};
5496 const char* bb = lc->currency_symbol;
Alexis Huntd4a24912011-07-13 06:40:50 +00005497 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005498 if (j == -1)
5499 __throw_runtime_error("locale not supported");
5500 wchar_t* wbe = wbuf + j;
5501 __curr_symbol_.assign(wbuf, wbe);
5502 if (lc->frac_digits != CHAR_MAX)
5503 __frac_digits_ = lc->frac_digits;
5504 else
5505 __frac_digits_ = base::do_frac_digits();
5506 if (lc->p_sign_posn == 0)
5507 __positive_sign_ = L"()";
5508 else
5509 {
5510 mb = mbstate_t();
5511 bb = lc->positive_sign;
Alexis Huntd4a24912011-07-13 06:40:50 +00005512 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005513 if (j == -1)
5514 __throw_runtime_error("locale not supported");
5515 wbe = wbuf + j;
5516 __positive_sign_.assign(wbuf, wbe);
5517 }
5518 if (lc->n_sign_posn == 0)
5519 __negative_sign_ = L"()";
5520 else
5521 {
5522 mb = mbstate_t();
5523 bb = lc->negative_sign;
Alexis Huntd4a24912011-07-13 06:40:50 +00005524 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005525 if (j == -1)
5526 __throw_runtime_error("locale not supported");
5527 wbe = wbuf + j;
5528 __negative_sign_.assign(wbuf, wbe);
5529 }
5530 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5531 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5532}
5533
5534template<>
5535void
5536moneypunct_byname<wchar_t, true>::init(const char* nm)
5537{
5538 typedef moneypunct<wchar_t, true> base;
Alexis Huntd4a24912011-07-13 06:40:50 +00005539 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005540#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005541 if (loc == 0)
5542 throw runtime_error("moneypunct_byname"
5543 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005544#endif // _LIBCPP_NO_EXCEPTIONS
Alexis Huntd4a24912011-07-13 06:40:50 +00005545 lconv* lc = __localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005546 if (*lc->mon_decimal_point)
5547 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5548 else
5549 __decimal_point_ = base::do_decimal_point();
5550 if (*lc->mon_thousands_sep)
5551 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5552 else
5553 __thousands_sep_ = base::do_thousands_sep();
5554 __grouping_ = lc->mon_grouping;
5555 wchar_t wbuf[100];
5556 mbstate_t mb = {0};
5557 const char* bb = lc->int_curr_symbol;
Alexis Huntd4a24912011-07-13 06:40:50 +00005558 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005559 if (j == -1)
5560 __throw_runtime_error("locale not supported");
5561 wchar_t* wbe = wbuf + j;
5562 __curr_symbol_.assign(wbuf, wbe);
5563 if (lc->int_frac_digits != CHAR_MAX)
5564 __frac_digits_ = lc->int_frac_digits;
5565 else
5566 __frac_digits_ = base::do_frac_digits();
5567 if (lc->int_p_sign_posn == 0)
5568 __positive_sign_ = L"()";
5569 else
5570 {
5571 mb = mbstate_t();
5572 bb = lc->positive_sign;
Alexis Huntd4a24912011-07-13 06:40:50 +00005573 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005574 if (j == -1)
5575 __throw_runtime_error("locale not supported");
5576 wbe = wbuf + j;
5577 __positive_sign_.assign(wbuf, wbe);
5578 }
5579 if (lc->int_n_sign_posn == 0)
5580 __negative_sign_ = L"()";
5581 else
5582 {
5583 mb = mbstate_t();
5584 bb = lc->negative_sign;
Alexis Huntd4a24912011-07-13 06:40:50 +00005585 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005586 if (j == -1)
5587 __throw_runtime_error("locale not supported");
5588 wbe = wbuf + j;
5589 __negative_sign_.assign(wbuf, wbe);
5590 }
5591 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5592 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
5593}
5594
5595void __do_nothing(void*) {}
5596
5597void __throw_runtime_error(const char* msg)
5598{
Howard Hinnant72f73582010-08-11 17:04:31 +00005599#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005600 throw runtime_error(msg);
Howard Hinnant72f73582010-08-11 17:04:31 +00005601#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005602}
5603
5604template class collate<char>;
5605template class collate<wchar_t>;
5606
5607template class num_get<char>;
5608template class num_get<wchar_t>;
5609
5610template class __num_get<char>;
5611template class __num_get<wchar_t>;
5612
5613template class num_put<char>;
5614template class num_put<wchar_t>;
5615
5616template class __num_put<char>;
5617template class __num_put<wchar_t>;
5618
5619template class time_get<char>;
5620template class time_get<wchar_t>;
5621
5622template class time_get_byname<char>;
5623template class time_get_byname<wchar_t>;
5624
5625template class time_put<char>;
5626template class time_put<wchar_t>;
5627
5628template class time_put_byname<char>;
5629template class time_put_byname<wchar_t>;
5630
5631template class moneypunct<char, false>;
5632template class moneypunct<char, true>;
5633template class moneypunct<wchar_t, false>;
5634template class moneypunct<wchar_t, true>;
5635
5636template class moneypunct_byname<char, false>;
5637template class moneypunct_byname<char, true>;
5638template class moneypunct_byname<wchar_t, false>;
5639template class moneypunct_byname<wchar_t, true>;
5640
5641template class money_get<char>;
5642template class money_get<wchar_t>;
5643
5644template class __money_get<char>;
5645template class __money_get<wchar_t>;
5646
5647template class money_put<char>;
5648template class money_put<wchar_t>;
5649
5650template class __money_put<char>;
5651template class __money_put<wchar_t>;
5652
5653template class messages<char>;
5654template class messages<wchar_t>;
5655
5656template class messages_byname<char>;
5657template class messages_byname<wchar_t>;
5658
5659template class codecvt_byname<char, char, mbstate_t>;
5660template class codecvt_byname<wchar_t, char, mbstate_t>;
5661template class codecvt_byname<char16_t, char, mbstate_t>;
5662template class codecvt_byname<char32_t, char, mbstate_t>;
5663
5664template class __vector_base_common<true>;
5665
5666_LIBCPP_END_NAMESPACE_STD