blob: 7c2a60780104941cdb258237baa7703f6b5f7574 [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
Howard Hinnantbf6c0b42011-06-30 14:21:55 +000025namespace {
26 typedef std::remove_pointer<locale_t>::type locale_struct;
27 typedef std::unique_ptr<locale_struct, decltype(&freelocale)> locale_unique_ptr;
28 typedef std::unique_ptr<locale_struct, decltype(&uselocale)> locale_raii;
29}
30
31namespace with_locale { namespace {
32#ifdef __APPLE__
33 using ::btowc_l;
34 using ::wctob_l;
35 using ::wcsnrtombs_l;
36 using ::wcrtomb_l;
37 using ::mbsnrtowcs_l;
38 using ::mbrtowc_l;
39 using ::mbtowc_l;
40 using ::mbrlen_l;
41 using ::localeconv_l;
42 using ::mbsrtowcs_l;
43
Howard Hinnantb1ad5a82011-06-30 21:18:19 +000044 decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnantbf6c0b42011-06-30 14:21:55 +000045 inline _LIBCPP_INLINE_VISIBILITY
46 mb_cur_max_l(locale_t loc)
47 {
48 return MB_CUR_MAX_L(loc);
49 }
50#else
51 template
52 <typename Function, typename ...Args>
53 auto using_locale(Function f, locale_t loc, Args&&... params) -> decltype(f(std::forward<Args>(params)...))
54 {
55 locale_raii current(uselocale(loc), uselocale);
56 return f(std::forward<Args>(params)...);
57 }
58
59 decltype(MB_CUR_MAX)
60 mb_cur_max_l(locale_t loc)
61 {
62 locale_raii current(uselocale(loc), uselocale);
63 return MB_CUR_MAX;
64 }
65
66 wint_t btowc_l(int c, locale_t l) { return using_locale(&btowc, l, c); }
67 int wctob_l(wint_t c, locale_t l) { return using_locale(&wctob, l, c); }
68 size_t wcsnrtombs_l(char * dest,
69 const wchar_t * * src,
70 size_t nwc,
71 size_t len,
72 mbstate_t * ps,
73 locale_t l)
74 {
75 return using_locale(&wcsnrtombs, l, dest, src, nwc, len, ps);
76 }
77 size_t wcrtomb_l(char *s, wchar_t wc, mbstate_t *ps, locale_t l)
78 {
79 return using_locale(&wcrtomb, l, s, wc, ps);
80 }
81 size_t mbsnrtowcs_l(wchar_t * dest,
82 const char * * src,
83 size_t nms,
84 size_t len,
85 mbstate_t * ps,
86 locale_t l)
87 {
88 return using_locale(&mbsnrtowcs, l, dest, src, nms, len, ps);
89 }
90 size_t mbrtowc_l(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps, locale_t l)
91 {
92 return using_locale(&mbrtowc, l, pwc, s, n, ps);
93 }
94 int mbtowc_l(wchar_t * pwc, const char * pmb, size_t max, locale_t l)
95 {
96 return using_locale(&mbtowc, l, pwc, pmb, max);
97 }
98 size_t mbrlen_l(const char *s, size_t n, mbstate_t *ps, locale_t l)
99 {
100 return using_locale(&mbrlen, l, s, n, ps);
101 }
102 struct lconv *localeconv_l(locale_t l)
103 {
104 return using_locale(&localeconv, l);
105 }
106 size_t mbsrtowcs_l(wchar_t * dest,
107 const char * * src,
108 size_t len,
109 mbstate_t * ps,
110 locale_t l)
111 {
112 return using_locale(&mbsrtowcs, l, dest, src, len, ps);
113 }
114#endif
115} }
116
Howard Hinnantc51e1022010-05-11 19:42:16 +0000117_LIBCPP_BEGIN_NAMESPACE_STD
118
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000119#ifndef _LIBCPP_APPLE_STABLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000120locale_t __cloc() {
121 // In theory this could create a race condition. In practice
122 // the race condition is non-fatal since it will just create
123 // a little resource leak. Better approach would be appreciated.
124#ifdef __APPLE__
125 return 0;
126#else
127 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
128 return result;
129#endif
130}
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000131#endif // _LIBCPP_APPLE_STABLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000132
Howard Hinnantc51e1022010-05-11 19:42:16 +0000133namespace {
134
135struct release
136{
137 void operator()(locale::facet* p) {p->__release_shared();}
138};
139
140template <class T, class A0>
141inline
142T&
143make(A0 a0)
144{
145 static typename aligned_storage<sizeof(T)>::type buf;
146 ::new (&buf) T(a0);
147 return *(T*)&buf;
148}
149
150template <class T, class A0, class A1>
151inline
152T&
153make(A0 a0, A1 a1)
154{
155 static typename aligned_storage<sizeof(T)>::type buf;
156 ::new (&buf) T(a0, a1);
157 return *(T*)&buf;
158}
159
160template <class T, class A0, class A1, class A2>
161inline
162T&
163make(A0 a0, A1 a1, A2 a2)
164{
165 static typename aligned_storage<sizeof(T)>::type buf;
166 ::new (&buf) T(a0, a1, a2);
167 return *(T*)&buf;
168}
169
170}
171
172class _LIBCPP_HIDDEN locale::__imp
173 : public facet
174{
175 enum {N = 28};
176 string name_;
177 vector<facet*, __sso_allocator<facet*, N> > facets_;
178public:
179 explicit __imp(size_t refs = 0);
180 explicit __imp(const string& name, size_t refs = 0);
181 __imp(const __imp&);
182 __imp(const __imp&, const string&, locale::category c);
183 __imp(const __imp& other, const __imp& one, locale::category c);
184 __imp(const __imp&, facet* f, long id);
185 ~__imp();
186
187 const string& name() const {return name_;}
188 bool has_facet(long id) const {return id < facets_.size() && facets_[id];}
189 const locale::facet* use_facet(long id) const;
190
191 static const locale& make_classic();
192 static locale& make_global();
193private:
194 void install(facet* f, long id);
195 template <class F> void install(F* f) {install(f, f->id.__get());}
196 template <class F> void install_from(const __imp& other);
197};
198
199locale::__imp::__imp(size_t refs)
200 : facet(refs),
201 name_("C"),
202 facets_(N)
203{
204 facets_.clear();
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000205 install(&make<_VSTD::collate<char> >(1));
206 install(&make<_VSTD::collate<wchar_t> >(1));
207 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1));
208 install(&make<_VSTD::ctype<wchar_t> >(1));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000209 install(&make<codecvt<char, char, mbstate_t> >(1));
210 install(&make<codecvt<wchar_t, char, mbstate_t> >(1));
211 install(&make<codecvt<char16_t, char, mbstate_t> >(1));
212 install(&make<codecvt<char32_t, char, mbstate_t> >(1));
213 install(&make<numpunct<char> >(1));
214 install(&make<numpunct<wchar_t> >(1));
215 install(&make<num_get<char> >(1));
216 install(&make<num_get<wchar_t> >(1));
217 install(&make<num_put<char> >(1));
218 install(&make<num_put<wchar_t> >(1));
219 install(&make<moneypunct<char, false> >(1));
220 install(&make<moneypunct<char, true> >(1));
221 install(&make<moneypunct<wchar_t, false> >(1));
222 install(&make<moneypunct<wchar_t, true> >(1));
223 install(&make<money_get<char> >(1));
224 install(&make<money_get<wchar_t> >(1));
225 install(&make<money_put<char> >(1));
226 install(&make<money_put<wchar_t> >(1));
227 install(&make<time_get<char> >(1));
228 install(&make<time_get<wchar_t> >(1));
229 install(&make<time_put<char> >(1));
230 install(&make<time_put<wchar_t> >(1));
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000231 install(&make<_VSTD::messages<char> >(1));
232 install(&make<_VSTD::messages<wchar_t> >(1));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000233}
234
235locale::__imp::__imp(const string& name, size_t refs)
236 : facet(refs),
237 name_(name),
238 facets_(N)
239{
Howard Hinnant72f73582010-08-11 17:04:31 +0000240#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000241 try
242 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000243#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000244 facets_ = locale::classic().__locale_->facets_;
245 for (unsigned i = 0; i < facets_.size(); ++i)
246 if (facets_[i])
247 facets_[i]->__add_shared();
248 install(new collate_byname<char>(name_));
249 install(new collate_byname<wchar_t>(name_));
250 install(new ctype_byname<char>(name_));
251 install(new ctype_byname<wchar_t>(name_));
252 install(new codecvt_byname<char, char, mbstate_t>(name_));
253 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
254 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
255 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
256 install(new numpunct_byname<char>(name_));
257 install(new numpunct_byname<wchar_t>(name_));
258 install(new moneypunct_byname<char, false>(name_));
259 install(new moneypunct_byname<char, true>(name_));
260 install(new moneypunct_byname<wchar_t, false>(name_));
261 install(new moneypunct_byname<wchar_t, true>(name_));
262 install(new time_get_byname<char>(name_));
263 install(new time_get_byname<wchar_t>(name_));
264 install(new time_put_byname<char>(name_));
265 install(new time_put_byname<wchar_t>(name_));
266 install(new messages_byname<char>(name_));
267 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000268#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000269 }
270 catch (...)
271 {
272 for (unsigned i = 0; i < facets_.size(); ++i)
273 if (facets_[i])
274 facets_[i]->__release_shared();
275 throw;
276 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000277#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000278}
279
280locale::__imp::__imp(const __imp& other)
281 : name_(other.name_),
282 facets_(max<size_t>(N, other.facets_.size()))
283{
284 facets_ = other.facets_;
285 for (unsigned i = 0; i < facets_.size(); ++i)
286 if (facets_[i])
287 facets_[i]->__add_shared();
288}
289
290locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
291 : name_("*"),
292 facets_(N)
293{
294 facets_ = other.facets_;
295 for (unsigned i = 0; i < facets_.size(); ++i)
296 if (facets_[i])
297 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000298#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000299 try
300 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000301#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000302 if (c & locale::collate)
303 {
304 install(new collate_byname<char>(name));
305 install(new collate_byname<wchar_t>(name));
306 }
307 if (c & locale::ctype)
308 {
309 install(new ctype_byname<char>(name));
310 install(new ctype_byname<wchar_t>(name));
311 install(new codecvt_byname<char, char, mbstate_t>(name));
312 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
313 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
314 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
315 }
316 if (c & locale::monetary)
317 {
318 install(new moneypunct_byname<char, false>(name));
319 install(new moneypunct_byname<char, true>(name));
320 install(new moneypunct_byname<wchar_t, false>(name));
321 install(new moneypunct_byname<wchar_t, true>(name));
322 }
323 if (c & locale::numeric)
324 {
325 install(new numpunct_byname<char>(name));
326 install(new numpunct_byname<wchar_t>(name));
327 }
328 if (c & locale::time)
329 {
330 install(new time_get_byname<char>(name));
331 install(new time_get_byname<wchar_t>(name));
332 install(new time_put_byname<char>(name));
333 install(new time_put_byname<wchar_t>(name));
334 }
335 if (c & locale::messages)
336 {
337 install(new messages_byname<char>(name));
338 install(new messages_byname<wchar_t>(name));
339 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000340#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000341 }
342 catch (...)
343 {
344 for (unsigned i = 0; i < facets_.size(); ++i)
345 if (facets_[i])
346 facets_[i]->__release_shared();
347 throw;
348 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000349#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000350}
351
352template<class F>
353inline
354void
355locale::__imp::install_from(const locale::__imp& one)
356{
357 long id = F::id.__get();
358 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
359}
360
361locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
362 : name_("*"),
363 facets_(N)
364{
365 facets_ = other.facets_;
366 for (unsigned i = 0; i < facets_.size(); ++i)
367 if (facets_[i])
368 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000369#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000370 try
371 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000372#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000373 if (c & locale::collate)
374 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000375 install_from<_VSTD::collate<char> >(one);
376 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000377 }
378 if (c & locale::ctype)
379 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000380 install_from<_VSTD::ctype<char> >(one);
381 install_from<_VSTD::ctype<wchar_t> >(one);
382 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
383 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
384 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
385 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000386 }
387 if (c & locale::monetary)
388 {
389 install_from<moneypunct<char, false> >(one);
390 install_from<moneypunct<char, true> >(one);
391 install_from<moneypunct<wchar_t, false> >(one);
392 install_from<moneypunct<wchar_t, true> >(one);
393 install_from<money_get<char> >(one);
394 install_from<money_get<wchar_t> >(one);
395 install_from<money_put<char> >(one);
396 install_from<money_put<wchar_t> >(one);
397 }
398 if (c & locale::numeric)
399 {
400 install_from<numpunct<char> >(one);
401 install_from<numpunct<wchar_t> >(one);
402 install_from<num_get<char> >(one);
403 install_from<num_get<wchar_t> >(one);
404 install_from<num_put<char> >(one);
405 install_from<num_put<wchar_t> >(one);
406 }
407 if (c & locale::time)
408 {
409 install_from<time_get<char> >(one);
410 install_from<time_get<wchar_t> >(one);
411 install_from<time_put<char> >(one);
412 install_from<time_put<wchar_t> >(one);
413 }
414 if (c & locale::messages)
415 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000416 install_from<_VSTD::messages<char> >(one);
417 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000418 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000419#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000420 }
421 catch (...)
422 {
423 for (unsigned i = 0; i < facets_.size(); ++i)
424 if (facets_[i])
425 facets_[i]->__release_shared();
426 throw;
427 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000428#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000429}
430
431locale::__imp::__imp(const __imp& other, facet* f, long id)
432 : name_("*"),
433 facets_(max<size_t>(N, other.facets_.size()+1))
434{
435 f->__add_shared();
436 unique_ptr<facet, release> hold(f);
437 facets_ = other.facets_;
438 for (unsigned i = 0; i < other.facets_.size(); ++i)
439 if (facets_[i])
440 facets_[i]->__add_shared();
441 install(hold.get(), id);
442}
443
444locale::__imp::~__imp()
445{
446 for (unsigned i = 0; i < facets_.size(); ++i)
447 if (facets_[i])
448 facets_[i]->__release_shared();
449}
450
451void
452locale::__imp::install(facet* f, long id)
453{
454 f->__add_shared();
455 unique_ptr<facet, release> hold(f);
456 if (id >= facets_.size())
457 facets_.resize(id+1);
458 if (facets_[id])
459 facets_[id]->__release_shared();
460 facets_[id] = hold.release();
461}
462
463const locale::facet*
464locale::__imp::use_facet(long id) const
465{
Howard Hinnant72f73582010-08-11 17:04:31 +0000466#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000467 if (!has_facet(id))
468 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000469#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000470 return facets_[id];
471}
472
473// locale
474
475const locale&
476locale::__imp::make_classic()
477{
478 // only one thread can get in here and it only gets in once
479 static aligned_storage<sizeof(locale)>::type buf;
480 locale* c = (locale*)&buf;
481 c->__locale_ = &make<__imp>(1);
482 return *c;
483}
484
485const locale&
486locale::classic()
487{
488 static const locale& c = __imp::make_classic();
489 return c;
490}
491
492locale&
493locale::__imp::make_global()
494{
495 // only one thread can get in here and it only gets in once
496 static aligned_storage<sizeof(locale)>::type buf;
497 locale* g = (locale*)&buf;
498 ::new (&buf) locale(locale::classic());
499 return *(locale*)&buf;
500}
501
502locale&
503locale::__global()
504{
505 static locale& g = __imp::make_global();
506 return g;
507}
508
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000509locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000510 : __locale_(__global().__locale_)
511{
512 __locale_->__add_shared();
513}
514
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000515locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000516 : __locale_(l.__locale_)
517{
518 __locale_->__add_shared();
519}
520
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000521locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000522{
523 __locale_->__release_shared();
524}
525
526const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000527locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000528{
529 other.__locale_->__add_shared();
530 __locale_->__release_shared();
531 __locale_ = other.__locale_;
532 return *this;
533}
534
535locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000536#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000537 : __locale_(name ? new __imp(name)
538 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000539#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000540 : __locale_(new __imp(name))
541#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000542{
543 __locale_->__add_shared();
544}
545
546locale::locale(const string& name)
547 : __locale_(new __imp(name))
548{
549 __locale_->__add_shared();
550}
551
552locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000553#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000554 : __locale_(name ? new __imp(*other.__locale_, name, c)
555 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000556#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000557 : __locale_(new __imp(*other.__locale_, name, c))
558#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000559{
560 __locale_->__add_shared();
561}
562
563locale::locale(const locale& other, const string& name, category c)
564 : __locale_(new __imp(*other.__locale_, name, c))
565{
566 __locale_->__add_shared();
567}
568
569locale::locale(const locale& other, const locale& one, category c)
570 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
571{
572 __locale_->__add_shared();
573}
574
575string
576locale::name() const
577{
578 return __locale_->name();
579}
580
581void
582locale::__install_ctor(const locale& other, facet* f, long id)
583{
584 if (f)
585 __locale_ = new __imp(*other.__locale_, f, id);
586 else
587 __locale_ = other.__locale_;
588 __locale_->__add_shared();
589}
590
591locale
592locale::global(const locale& loc)
593{
594 locale& g = __global();
595 locale r = g;
596 g = loc;
597 if (g.name() != "*")
598 setlocale(LC_ALL, g.name().c_str());
599 return r;
600}
601
602bool
603locale::has_facet(id& x) const
604{
605 return __locale_->has_facet(x.__get());
606}
607
608const locale::facet*
609locale::use_facet(id& x) const
610{
611 return __locale_->use_facet(x.__get());
612}
613
614bool
615locale::operator==(const locale& y) const
616{
617 return (__locale_ == y.__locale_)
618 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
619}
620
621// locale::facet
622
623locale::facet::~facet()
624{
625}
626
627void
Howard Hinnant719bda32011-05-28 14:41:13 +0000628locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000629{
630 delete this;
631}
632
633// locale::id
634
635int32_t locale::id::__next_id = 0;
636
637namespace
638{
639
640class __fake_bind
641{
642 locale::id* id_;
643 void (locale::id::* pmf_)();
644public:
645 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
646 : id_(id), pmf_(pmf) {}
647
648 void operator()() const
649 {
650 (id_->*pmf_)();
651 }
652};
653
654}
655
656long
657locale::id::__get()
658{
659 call_once(__flag_, __fake_bind(&locale::id::__init, this));
660 return __id_ - 1;
661}
662
663void
664locale::id::__init()
665{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000666 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000667}
668
669// template <> class collate_byname<char>
670
671collate_byname<char>::collate_byname(const char* n, size_t refs)
672 : collate<char>(refs),
673 __l(newlocale(LC_ALL_MASK, n, 0))
674{
Howard Hinnant72f73582010-08-11 17:04:31 +0000675#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000676 if (__l == 0)
677 throw runtime_error("collate_byname<char>::collate_byname"
678 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000679#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000680}
681
682collate_byname<char>::collate_byname(const string& name, size_t refs)
683 : collate<char>(refs),
684 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
685{
Howard Hinnant72f73582010-08-11 17:04:31 +0000686#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000687 if (__l == 0)
688 throw runtime_error("collate_byname<char>::collate_byname"
689 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000690#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000691}
692
693collate_byname<char>::~collate_byname()
694{
695 freelocale(__l);
696}
697
698int
699collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
700 const char_type* __lo2, const char_type* __hi2) const
701{
702 string_type lhs(__lo1, __hi1);
703 string_type rhs(__lo2, __hi2);
704 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
705 if (r < 0)
706 return -1;
707 if (r > 0)
708 return 1;
709 return r;
710}
711
712collate_byname<char>::string_type
713collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
714{
715 const string_type in(lo, hi);
716 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
717 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
718 return out;
719}
720
721// template <> class collate_byname<wchar_t>
722
723collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
724 : collate<wchar_t>(refs),
725 __l(newlocale(LC_ALL_MASK, n, 0))
726{
Howard Hinnant72f73582010-08-11 17:04:31 +0000727#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000728 if (__l == 0)
729 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
730 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000731#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000732}
733
734collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
735 : collate<wchar_t>(refs),
736 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
737{
Howard Hinnant72f73582010-08-11 17:04:31 +0000738#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000739 if (__l == 0)
740 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
741 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000742#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000743}
744
745collate_byname<wchar_t>::~collate_byname()
746{
747 freelocale(__l);
748}
749
750int
751collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
752 const char_type* __lo2, const char_type* __hi2) const
753{
754 string_type lhs(__lo1, __hi1);
755 string_type rhs(__lo2, __hi2);
756 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
757 if (r < 0)
758 return -1;
759 if (r > 0)
760 return 1;
761 return r;
762}
763
764collate_byname<wchar_t>::string_type
765collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
766{
767 const string_type in(lo, hi);
768 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
769 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
770 return out;
771}
772
773// template <> class ctype<wchar_t>;
774
775locale::id ctype<wchar_t>::id;
776
777ctype<wchar_t>::~ctype()
778{
779}
780
781bool
782ctype<wchar_t>::do_is(mask m, char_type c) const
783{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000784 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000785}
786
787const wchar_t*
788ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
789{
790 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000791 *vec = static_cast<mask>(isascii(*low) ?
792 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000793 return low;
794}
795
796const wchar_t*
797ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
798{
799 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000800 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000801 break;
802 return low;
803}
804
805const wchar_t*
806ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
807{
808 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000809 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000810 break;
811 return low;
812}
813
814wchar_t
815ctype<wchar_t>::do_toupper(char_type c) const
816{
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000817#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000818 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000819#else
820 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
821#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000822}
823
824const wchar_t*
825ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
826{
827 for (; low != high; ++low)
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000828#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000829 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
830 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000831#else
832 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
833#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000834 return low;
835}
836
837wchar_t
838ctype<wchar_t>::do_tolower(char_type c) const
839{
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000840#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000841 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000842#else
843 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
844#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000845}
846
847const wchar_t*
848ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
849{
850 for (; low != high; ++low)
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000851#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000852 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
853 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000854#else
855 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
856#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000857 return low;
858}
859
860wchar_t
861ctype<wchar_t>::do_widen(char c) const
862{
863 return c;
864}
865
866const char*
867ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
868{
869 for (; low != high; ++low, ++dest)
870 *dest = *low;
871 return low;
872}
873
874char
875ctype<wchar_t>::do_narrow(char_type c, char dfault) const
876{
877 if (isascii(c))
878 return static_cast<char>(c);
879 return dfault;
880}
881
882const wchar_t*
883ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
884{
885 for (; low != high; ++low, ++dest)
886 if (isascii(*low))
887 *dest = *low;
888 else
889 *dest = dfault;
890 return low;
891}
892
893// template <> class ctype<char>;
894
895locale::id ctype<char>::id;
896
897ctype<char>::ctype(const mask* tab, bool del, size_t refs)
898 : locale::facet(refs),
899 __tab_(tab),
900 __del_(del)
901{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000902 if (__tab_ == 0)
903 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000904}
905
906ctype<char>::~ctype()
907{
908 if (__tab_ && __del_)
909 delete [] __tab_;
910}
911
912char
913ctype<char>::do_toupper(char_type c) const
914{
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000915#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000916 return isascii(c) ? __classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000917#else
918 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
919#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000920}
921
922const char*
923ctype<char>::do_toupper(char_type* low, const char_type* high) const
924{
925 for (; low != high; ++low)
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000926#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000927 *low = isascii(*low) ? __classic_upper_table()[*low] : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000928#else
Howard Hinnant390fc292011-07-09 19:47:01 +0000929 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000930#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000931 return low;
932}
933
934char
935ctype<char>::do_tolower(char_type c) const
936{
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000937#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000938 return isascii(c) ? __classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000939#else
940 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
941#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000942}
943
944const char*
945ctype<char>::do_tolower(char_type* low, const char_type* high) const
946{
947 for (; low != high; ++low)
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000948#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +0000949 *low = isascii(*low) ? __classic_lower_table()[*low] : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000950#else
Howard Hinnant390fc292011-07-09 19:47:01 +0000951 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000952#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000953 return low;
954}
955
956char
957ctype<char>::do_widen(char c) const
958{
959 return c;
960}
961
962const char*
963ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
964{
965 for (; low != high; ++low, ++dest)
966 *dest = *low;
967 return low;
968}
969
970char
971ctype<char>::do_narrow(char_type c, char dfault) const
972{
973 if (isascii(c))
974 return static_cast<char>(c);
975 return dfault;
976}
977
978const char*
979ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
980{
981 for (; low != high; ++low, ++dest)
982 if (isascii(*low))
983 *dest = *low;
984 else
985 *dest = dfault;
986 return low;
987}
988
989const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000990ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000991{
Michael J. Spencer8d8164e2010-12-10 19:47:54 +0000992#ifdef __APPLE__
Howard Hinnantc51e1022010-05-11 19:42:16 +0000993 return _DefaultRuneLocale.__runetype;
Alexis Hunt92b0c812011-07-09 00:56:23 +0000994#elif defined(__GLIBC__)
995 return __cloc()->__ctype_b;
996// This is assumed to be safe.
997#else
998 return NULL;
999#endif
1000}
1001
Howard Hinnant390fc292011-07-09 19:47:01 +00001002#ifndef _LIBCPP_STABLE_APPLE_ABI
Alexis Hunt92b0c812011-07-09 00:56:23 +00001003const int*
1004ctype<char>::__classic_lower_table() _NOEXCEPT
1005{
1006#ifdef __APPLE__
1007 return _DefaultRuneLocale.__maplower;
1008#elif defined(__GLIBC__)
1009 return __cloc()->__ctype_tolower;
1010#else
1011 return NULL;
1012#endif
1013}
1014
1015const int*
1016ctype<char>::__classic_upper_table() _NOEXCEPT
1017{
1018#ifdef __APPLE__
1019 return _DefaultRuneLocale.__mapupper;
1020#elif defined(__GLIBC__)
1021 return __cloc()->__ctype_toupper;
Michael J. Spencer8d8164e2010-12-10 19:47:54 +00001022#else
1023 return NULL;
1024#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001025}
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001026#endif // _LIBCPP_APPLE_STABLE_ABI
Howard Hinnantc51e1022010-05-11 19:42:16 +00001027
1028// template <> class ctype_byname<char>
1029
1030ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1031 : ctype<char>(0, false, refs),
1032 __l(newlocale(LC_ALL_MASK, name, 0))
1033{
Howard Hinnant72f73582010-08-11 17:04:31 +00001034#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001035 if (__l == 0)
1036 throw runtime_error("ctype_byname<char>::ctype_byname"
1037 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001038#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001039}
1040
1041ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1042 : ctype<char>(0, false, refs),
1043 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1044{
Howard Hinnant72f73582010-08-11 17:04:31 +00001045#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001046 if (__l == 0)
1047 throw runtime_error("ctype_byname<char>::ctype_byname"
1048 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001049#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001050}
1051
1052ctype_byname<char>::~ctype_byname()
1053{
1054 freelocale(__l);
1055}
1056
1057char
1058ctype_byname<char>::do_toupper(char_type c) const
1059{
1060 return toupper_l(c, __l);
1061}
1062
1063const char*
1064ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1065{
1066 for (; low != high; ++low)
1067 *low = toupper_l(*low, __l);
1068 return low;
1069}
1070
1071char
1072ctype_byname<char>::do_tolower(char_type c) const
1073{
1074 return tolower_l(c, __l);
1075}
1076
1077const char*
1078ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1079{
1080 for (; low != high; ++low)
1081 *low = tolower_l(*low, __l);
1082 return low;
1083}
1084
1085// template <> class ctype_byname<wchar_t>
1086
1087ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1088 : ctype<wchar_t>(refs),
1089 __l(newlocale(LC_ALL_MASK, name, 0))
1090{
Howard Hinnant72f73582010-08-11 17:04:31 +00001091#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001092 if (__l == 0)
1093 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1094 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001095#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001096}
1097
1098ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1099 : ctype<wchar_t>(refs),
1100 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1101{
Howard Hinnant72f73582010-08-11 17:04:31 +00001102#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001103 if (__l == 0)
1104 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1105 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001106#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001107}
1108
1109ctype_byname<wchar_t>::~ctype_byname()
1110{
1111 freelocale(__l);
1112}
1113
1114bool
1115ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1116{
Alexis Huntc2017f12011-07-09 03:40:04 +00001117#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001118 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001119#else
1120 if (m & space && !iswspace_l(c, __l)) return false;
1121 if (m & print && !iswprint_l(c, __l)) return false;
1122 if (m & cntrl && !iswcntrl_l(c, __l)) return false;
1123 if (m & upper && !iswupper_l(c, __l)) return false;
1124 if (m & lower && !iswlower_l(c, __l)) return false;
1125 if (m & alpha && !iswalpha_l(c, __l)) return false;
1126 if (m & digit && !iswdigit_l(c, __l)) return false;
1127 if (m & punct && !iswpunct_l(c, __l)) return false;
1128 if (m & xdigit && !iswxdigit_l(c, __l)) return false;
1129 if (m & blank && !iswblank_l(c, __l)) return false;
1130 return true;
1131#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001132}
1133
1134const wchar_t*
1135ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1136{
1137 for (; low != high; ++low, ++vec)
1138 {
1139 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001140 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001141 else
1142 {
1143 *vec = 0;
1144 if (iswspace_l(*low, __l))
1145 *vec |= space;
1146 if (iswprint_l(*low, __l))
1147 *vec |= print;
1148 if (iswcntrl_l(*low, __l))
1149 *vec |= cntrl;
1150 if (iswupper_l(*low, __l))
1151 *vec |= upper;
1152 if (iswlower_l(*low, __l))
1153 *vec |= lower;
1154 if (iswalpha_l(*low, __l))
1155 *vec |= alpha;
1156 if (iswdigit_l(*low, __l))
1157 *vec |= digit;
1158 if (iswpunct_l(*low, __l))
1159 *vec |= punct;
1160 if (iswxdigit_l(*low, __l))
1161 *vec |= xdigit;
1162 }
1163 }
1164 return low;
1165}
1166
1167const wchar_t*
1168ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1169{
1170 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001171 {
1172#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001173 if (iswctype_l(*low, m, __l))
1174 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001175#else
1176 if (m & space && !iswspace_l(*low, __l)) continue;
1177 if (m & print && !iswprint_l(*low, __l)) continue;
1178 if (m & cntrl && !iswcntrl_l(*low, __l)) continue;
1179 if (m & upper && !iswupper_l(*low, __l)) continue;
1180 if (m & lower && !iswlower_l(*low, __l)) continue;
1181 if (m & alpha && !iswalpha_l(*low, __l)) continue;
1182 if (m & digit && !iswdigit_l(*low, __l)) continue;
1183 if (m & punct && !iswpunct_l(*low, __l)) continue;
1184 if (m & xdigit && !iswxdigit_l(*low, __l)) continue;
1185 if (m & blank && !iswblank_l(*low, __l)) continue;
1186 break;
1187#endif
1188 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001189 return low;
1190}
1191
1192const wchar_t*
1193ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1194{
1195 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001196 {
1197#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001198 if (!iswctype_l(*low, m, __l))
1199 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001200#else
1201 if (m & space && iswspace_l(*low, __l)) continue;
1202 if (m & print && iswprint_l(*low, __l)) continue;
1203 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1204 if (m & upper && iswupper_l(*low, __l)) continue;
1205 if (m & lower && iswlower_l(*low, __l)) continue;
1206 if (m & alpha && iswalpha_l(*low, __l)) continue;
1207 if (m & digit && iswdigit_l(*low, __l)) continue;
1208 if (m & punct && iswpunct_l(*low, __l)) continue;
1209 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1210 if (m & blank && iswblank_l(*low, __l)) continue;
1211 break;
1212#endif
1213 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001214 return low;
1215}
1216
1217wchar_t
1218ctype_byname<wchar_t>::do_toupper(char_type c) const
1219{
1220 return towupper_l(c, __l);
1221}
1222
1223const wchar_t*
1224ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1225{
1226 for (; low != high; ++low)
1227 *low = towupper_l(*low, __l);
1228 return low;
1229}
1230
1231wchar_t
1232ctype_byname<wchar_t>::do_tolower(char_type c) const
1233{
1234 return towlower_l(c, __l);
1235}
1236
1237const wchar_t*
1238ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1239{
1240 for (; low != high; ++low)
1241 *low = towlower_l(*low, __l);
1242 return low;
1243}
1244
1245wchar_t
1246ctype_byname<wchar_t>::do_widen(char c) const
1247{
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001248 return with_locale::btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001249}
1250
1251const char*
1252ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1253{
1254 for (; low != high; ++low, ++dest)
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001255 *dest = with_locale::btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001256 return low;
1257}
1258
1259char
1260ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1261{
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001262 int r = with_locale::wctob_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001263 return r != WEOF ? static_cast<char>(r) : dfault;
1264}
1265
1266const wchar_t*
1267ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1268{
1269 for (; low != high; ++low, ++dest)
1270 {
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001271 int r = with_locale::wctob_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001272 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1273 }
1274 return low;
1275}
1276
1277// template <> class codecvt<char, char, mbstate_t>
1278
Howard Hinnantffb308e2010-08-22 00:03:27 +00001279locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001280
1281codecvt<char, char, mbstate_t>::~codecvt()
1282{
1283}
1284
1285codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001286codecvt<char, char, mbstate_t>::do_out(state_type&,
1287 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001288 extern_type* to, extern_type*, extern_type*& to_nxt) const
1289{
1290 frm_nxt = frm;
1291 to_nxt = to;
1292 return noconv;
1293}
1294
1295codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001296codecvt<char, char, mbstate_t>::do_in(state_type&,
1297 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001298 intern_type* to, intern_type*, intern_type*& to_nxt) const
1299{
1300 frm_nxt = frm;
1301 to_nxt = to;
1302 return noconv;
1303}
1304
1305codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001306codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001307 extern_type* to, extern_type*, extern_type*& to_nxt) const
1308{
1309 to_nxt = to;
1310 return noconv;
1311}
1312
1313int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001314codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001315{
1316 return 1;
1317}
1318
1319bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001320codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001321{
1322 return true;
1323}
1324
1325int
1326codecvt<char, char, mbstate_t>::do_length(state_type&,
1327 const extern_type* frm, const extern_type* end, size_t mx) const
1328{
1329 return static_cast<int>(min<size_t>(mx, end-frm));
1330}
1331
1332int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001333codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001334{
1335 return 1;
1336}
1337
1338// template <> class codecvt<wchar_t, char, mbstate_t>
1339
Howard Hinnantffb308e2010-08-22 00:03:27 +00001340locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001341
1342codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1343 : locale::facet(refs),
1344 __l(0)
1345{
1346}
1347
1348codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1349 : locale::facet(refs),
1350 __l(newlocale(LC_ALL_MASK, nm, 0))
1351{
Howard Hinnant72f73582010-08-11 17:04:31 +00001352#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001353 if (__l == 0)
1354 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1355 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001356#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001357}
1358
1359codecvt<wchar_t, char, mbstate_t>::~codecvt()
1360{
1361 if (__l != 0)
1362 freelocale(__l);
1363}
1364
1365codecvt<wchar_t, char, mbstate_t>::result
1366codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001367 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001368 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1369{
1370 // look for first internal null in frm
1371 const intern_type* fend = frm;
1372 for (; fend != frm_end; ++fend)
1373 if (*fend == 0)
1374 break;
1375 // loop over all null-terminated sequences in frm
1376 to_nxt = to;
1377 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1378 {
1379 // save state in case needed to reover to_nxt on error
1380 mbstate_t save_state = st;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001381 size_t n = with_locale::wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001382 if (n == size_t(-1))
1383 {
1384 // need to recover to_nxt
1385 for (to_nxt = to; frm != frm_nxt; ++frm)
1386 {
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001387 n = with_locale::wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001388 if (n == size_t(-1))
1389 break;
1390 to_nxt += n;
1391 }
1392 frm_nxt = frm;
1393 return error;
1394 }
1395 if (n == 0)
1396 return partial;
1397 to_nxt += n;
1398 if (to_nxt == to_end)
1399 break;
1400 if (fend != frm_end) // set up next null terminated sequence
1401 {
1402 // Try to write the terminating null
1403 extern_type tmp[MB_LEN_MAX];
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001404 n = with_locale::wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001405 if (n == size_t(-1)) // on error
1406 return error;
1407 if (n > to_end-to_nxt) // is there room?
1408 return partial;
1409 for (extern_type* p = tmp; n; --n) // write it
1410 *to_nxt++ = *p++;
1411 ++frm_nxt;
1412 // look for next null in frm
1413 for (fend = frm_nxt; fend != frm_end; ++fend)
1414 if (*fend == 0)
1415 break;
1416 }
1417 }
1418 return frm_nxt == frm_end ? ok : partial;
1419}
1420
1421codecvt<wchar_t, char, mbstate_t>::result
1422codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001423 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001424 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1425{
1426 // look for first internal null in frm
1427 const extern_type* fend = frm;
1428 for (; fend != frm_end; ++fend)
1429 if (*fend == 0)
1430 break;
1431 // loop over all null-terminated sequences in frm
1432 to_nxt = to;
1433 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1434 {
1435 // save state in case needed to reover to_nxt on error
1436 mbstate_t save_state = st;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001437 size_t n = with_locale::mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001438 if (n == size_t(-1))
1439 {
1440 // need to recover to_nxt
1441 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1442 {
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001443 n = with_locale::mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001444 switch (n)
1445 {
1446 case 0:
1447 ++frm;
1448 break;
1449 case -1:
1450 frm_nxt = frm;
1451 return error;
1452 case -2:
1453 frm_nxt = frm;
1454 return partial;
1455 default:
1456 frm += n;
1457 break;
1458 }
1459 }
1460 frm_nxt = frm;
1461 return frm_nxt == frm_end ? ok : partial;
1462 }
1463 if (n == 0)
1464 return error;
1465 to_nxt += n;
1466 if (to_nxt == to_end)
1467 break;
1468 if (fend != frm_end) // set up next null terminated sequence
1469 {
1470 // Try to write the terminating null
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001471 n = with_locale::mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001472 if (n != 0) // on error
1473 return error;
1474 ++to_nxt;
1475 ++frm_nxt;
1476 // look for next null in frm
1477 for (fend = frm_nxt; fend != frm_end; ++fend)
1478 if (*fend == 0)
1479 break;
1480 }
1481 }
1482 return frm_nxt == frm_end ? ok : partial;
1483}
1484
1485codecvt<wchar_t, char, mbstate_t>::result
1486codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1487 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1488{
1489 to_nxt = to;
1490 extern_type tmp[MB_LEN_MAX];
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001491 size_t n = with_locale::wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001492 if (n == size_t(-1) || n == 0) // on error
1493 return error;
1494 --n;
1495 if (n > to_end-to_nxt) // is there room?
1496 return partial;
1497 for (extern_type* p = tmp; n; --n) // write it
1498 *to_nxt++ = *p++;
1499 return ok;
1500}
1501
1502int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001503codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001504{
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001505 if (with_locale::mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001506 {
1507 // stateless encoding
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001508 if (__l == 0 || with_locale::mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Howard Hinnantc51e1022010-05-11 19:42:16 +00001509 return 1; // which take more than 1 char to form a wchar_t
1510 return 0;
1511 }
1512 return -1;
1513}
1514
1515bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001516codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001517{
1518 return false;
1519}
1520
1521int
1522codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1523 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1524{
1525 int nbytes = 0;
1526 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1527 {
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001528 size_t n = with_locale::mbrlen_l(frm, frm_end-frm, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001529 switch (n)
1530 {
1531 case 0:
1532 ++nbytes;
1533 ++frm;
1534 break;
1535 case -1:
1536 case -2:
1537 return nbytes;
1538 default:
1539 nbytes += n;
1540 frm += n;
1541 break;
1542 }
1543 }
1544 return nbytes;
1545}
1546
1547int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001548codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001549{
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00001550 return __l == 0 ? 1 : with_locale::mb_cur_max_l(__l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001551}
1552
1553// Valid UTF ranges
1554// UTF-32 UTF-16 UTF-8 # of code points
1555// first second first second third fourth
1556// 000000 - 00007F 0000 - 007F 00 - 7F 127
1557// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1558// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1559// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1560// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1561// 00D800 - 00DFFF invalid
1562// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1563// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1564// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1565// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1566
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001567static
1568codecvt_base::result
1569utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1570 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1571 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1572{
1573 frm_nxt = frm;
1574 to_nxt = to;
1575 if (mode & generate_header)
1576 {
1577 if (to_end-to_nxt < 3)
1578 return codecvt_base::partial;
1579 *to_nxt++ = static_cast<uint8_t>(0xEF);
1580 *to_nxt++ = static_cast<uint8_t>(0xBB);
1581 *to_nxt++ = static_cast<uint8_t>(0xBF);
1582 }
1583 for (; frm_nxt < frm_end; ++frm_nxt)
1584 {
1585 uint16_t wc1 = *frm_nxt;
1586 if (wc1 > Maxcode)
1587 return codecvt_base::error;
1588 if (wc1 < 0x0080)
1589 {
1590 if (to_end-to_nxt < 1)
1591 return codecvt_base::partial;
1592 *to_nxt++ = static_cast<uint8_t>(wc1);
1593 }
1594 else if (wc1 < 0x0800)
1595 {
1596 if (to_end-to_nxt < 2)
1597 return codecvt_base::partial;
1598 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1599 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1600 }
1601 else if (wc1 < 0xD800)
1602 {
1603 if (to_end-to_nxt < 3)
1604 return codecvt_base::partial;
1605 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1606 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1607 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1608 }
1609 else if (wc1 < 0xDC00)
1610 {
1611 if (frm_end-frm_nxt < 2)
1612 return codecvt_base::partial;
1613 uint16_t wc2 = frm_nxt[1];
1614 if ((wc2 & 0xFC00) != 0xDC00)
1615 return codecvt_base::error;
1616 if (to_end-to_nxt < 4)
1617 return codecvt_base::partial;
1618 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1619 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1620 return codecvt_base::error;
1621 ++frm_nxt;
1622 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1623 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1624 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1625 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1626 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1627 }
1628 else if (wc1 < 0xE000)
1629 {
1630 return codecvt_base::error;
1631 }
1632 else
1633 {
1634 if (to_end-to_nxt < 3)
1635 return codecvt_base::partial;
1636 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1637 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1638 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1639 }
1640 }
1641 return codecvt_base::ok;
1642}
1643
1644static
1645codecvt_base::result
1646utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1647 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1648 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1649{
1650 frm_nxt = frm;
1651 to_nxt = to;
1652 if (mode & generate_header)
1653 {
1654 if (to_end-to_nxt < 3)
1655 return codecvt_base::partial;
1656 *to_nxt++ = static_cast<uint8_t>(0xEF);
1657 *to_nxt++ = static_cast<uint8_t>(0xBB);
1658 *to_nxt++ = static_cast<uint8_t>(0xBF);
1659 }
1660 for (; frm_nxt < frm_end; ++frm_nxt)
1661 {
1662 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1663 if (wc1 > Maxcode)
1664 return codecvt_base::error;
1665 if (wc1 < 0x0080)
1666 {
1667 if (to_end-to_nxt < 1)
1668 return codecvt_base::partial;
1669 *to_nxt++ = static_cast<uint8_t>(wc1);
1670 }
1671 else if (wc1 < 0x0800)
1672 {
1673 if (to_end-to_nxt < 2)
1674 return codecvt_base::partial;
1675 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1676 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1677 }
1678 else if (wc1 < 0xD800)
1679 {
1680 if (to_end-to_nxt < 3)
1681 return codecvt_base::partial;
1682 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1683 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1684 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1685 }
1686 else if (wc1 < 0xDC00)
1687 {
1688 if (frm_end-frm_nxt < 2)
1689 return codecvt_base::partial;
1690 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1691 if ((wc2 & 0xFC00) != 0xDC00)
1692 return codecvt_base::error;
1693 if (to_end-to_nxt < 4)
1694 return codecvt_base::partial;
1695 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1696 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1697 return codecvt_base::error;
1698 ++frm_nxt;
1699 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1700 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1701 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1702 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1703 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1704 }
1705 else if (wc1 < 0xE000)
1706 {
1707 return codecvt_base::error;
1708 }
1709 else
1710 {
1711 if (to_end-to_nxt < 3)
1712 return codecvt_base::partial;
1713 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1714 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1715 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1716 }
1717 }
1718 return codecvt_base::ok;
1719}
1720
1721static
1722codecvt_base::result
1723utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1724 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1725 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1726{
1727 frm_nxt = frm;
1728 to_nxt = to;
1729 if (mode & consume_header)
1730 {
1731 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1732 frm_nxt[2] == 0xBF)
1733 frm_nxt += 3;
1734 }
1735 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1736 {
1737 uint8_t c1 = *frm_nxt;
1738 if (c1 > Maxcode)
1739 return codecvt_base::error;
1740 if (c1 < 0x80)
1741 {
1742 *to_nxt = static_cast<uint16_t>(c1);
1743 ++frm_nxt;
1744 }
1745 else if (c1 < 0xC2)
1746 {
1747 return codecvt_base::error;
1748 }
1749 else if (c1 < 0xE0)
1750 {
1751 if (frm_end-frm_nxt < 2)
1752 return codecvt_base::partial;
1753 uint8_t c2 = frm_nxt[1];
1754 if ((c2 & 0xC0) != 0x80)
1755 return codecvt_base::error;
1756 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1757 if (t > Maxcode)
1758 return codecvt_base::error;
1759 *to_nxt = t;
1760 frm_nxt += 2;
1761 }
1762 else if (c1 < 0xF0)
1763 {
1764 if (frm_end-frm_nxt < 3)
1765 return codecvt_base::partial;
1766 uint8_t c2 = frm_nxt[1];
1767 uint8_t c3 = frm_nxt[2];
1768 switch (c1)
1769 {
1770 case 0xE0:
1771 if ((c2 & 0xE0) != 0xA0)
1772 return codecvt_base::error;
1773 break;
1774 case 0xED:
1775 if ((c2 & 0xE0) != 0x80)
1776 return codecvt_base::error;
1777 break;
1778 default:
1779 if ((c2 & 0xC0) != 0x80)
1780 return codecvt_base::error;
1781 break;
1782 }
1783 if ((c3 & 0xC0) != 0x80)
1784 return codecvt_base::error;
1785 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1786 | ((c2 & 0x3F) << 6)
1787 | (c3 & 0x3F));
1788 if (t > Maxcode)
1789 return codecvt_base::error;
1790 *to_nxt = t;
1791 frm_nxt += 3;
1792 }
1793 else if (c1 < 0xF5)
1794 {
1795 if (frm_end-frm_nxt < 4)
1796 return codecvt_base::partial;
1797 uint8_t c2 = frm_nxt[1];
1798 uint8_t c3 = frm_nxt[2];
1799 uint8_t c4 = frm_nxt[3];
1800 switch (c1)
1801 {
1802 case 0xF0:
1803 if (!(0x90 <= c2 && c2 <= 0xBF))
1804 return codecvt_base::error;
1805 break;
1806 case 0xF4:
1807 if ((c2 & 0xF0) != 0x80)
1808 return codecvt_base::error;
1809 break;
1810 default:
1811 if ((c2 & 0xC0) != 0x80)
1812 return codecvt_base::error;
1813 break;
1814 }
1815 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1816 return codecvt_base::error;
1817 if (to_end-to_nxt < 2)
1818 return codecvt_base::partial;
1819 if (((((unsigned long)c1 & 7) << 18) +
1820 (((unsigned long)c2 & 0x3F) << 12) +
1821 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1822 return codecvt_base::error;
1823 *to_nxt = static_cast<uint16_t>(
1824 0xD800
1825 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1826 | ((c2 & 0x0F) << 2)
1827 | ((c3 & 0x30) >> 4));
1828 *++to_nxt = static_cast<uint16_t>(
1829 0xDC00
1830 | ((c3 & 0x0F) << 6)
1831 | (c4 & 0x3F));
1832 frm_nxt += 4;
1833 }
1834 else
1835 {
1836 return codecvt_base::error;
1837 }
1838 }
1839 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1840}
1841
1842static
1843codecvt_base::result
1844utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1845 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1846 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1847{
1848 frm_nxt = frm;
1849 to_nxt = to;
1850 if (mode & consume_header)
1851 {
1852 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1853 frm_nxt[2] == 0xBF)
1854 frm_nxt += 3;
1855 }
1856 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1857 {
1858 uint8_t c1 = *frm_nxt;
1859 if (c1 > Maxcode)
1860 return codecvt_base::error;
1861 if (c1 < 0x80)
1862 {
1863 *to_nxt = static_cast<uint32_t>(c1);
1864 ++frm_nxt;
1865 }
1866 else if (c1 < 0xC2)
1867 {
1868 return codecvt_base::error;
1869 }
1870 else if (c1 < 0xE0)
1871 {
1872 if (frm_end-frm_nxt < 2)
1873 return codecvt_base::partial;
1874 uint8_t c2 = frm_nxt[1];
1875 if ((c2 & 0xC0) != 0x80)
1876 return codecvt_base::error;
1877 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1878 if (t > Maxcode)
1879 return codecvt_base::error;
1880 *to_nxt = static_cast<uint32_t>(t);
1881 frm_nxt += 2;
1882 }
1883 else if (c1 < 0xF0)
1884 {
1885 if (frm_end-frm_nxt < 3)
1886 return codecvt_base::partial;
1887 uint8_t c2 = frm_nxt[1];
1888 uint8_t c3 = frm_nxt[2];
1889 switch (c1)
1890 {
1891 case 0xE0:
1892 if ((c2 & 0xE0) != 0xA0)
1893 return codecvt_base::error;
1894 break;
1895 case 0xED:
1896 if ((c2 & 0xE0) != 0x80)
1897 return codecvt_base::error;
1898 break;
1899 default:
1900 if ((c2 & 0xC0) != 0x80)
1901 return codecvt_base::error;
1902 break;
1903 }
1904 if ((c3 & 0xC0) != 0x80)
1905 return codecvt_base::error;
1906 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1907 | ((c2 & 0x3F) << 6)
1908 | (c3 & 0x3F));
1909 if (t > Maxcode)
1910 return codecvt_base::error;
1911 *to_nxt = static_cast<uint32_t>(t);
1912 frm_nxt += 3;
1913 }
1914 else if (c1 < 0xF5)
1915 {
1916 if (frm_end-frm_nxt < 4)
1917 return codecvt_base::partial;
1918 uint8_t c2 = frm_nxt[1];
1919 uint8_t c3 = frm_nxt[2];
1920 uint8_t c4 = frm_nxt[3];
1921 switch (c1)
1922 {
1923 case 0xF0:
1924 if (!(0x90 <= c2 && c2 <= 0xBF))
1925 return codecvt_base::error;
1926 break;
1927 case 0xF4:
1928 if ((c2 & 0xF0) != 0x80)
1929 return codecvt_base::error;
1930 break;
1931 default:
1932 if ((c2 & 0xC0) != 0x80)
1933 return codecvt_base::error;
1934 break;
1935 }
1936 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1937 return codecvt_base::error;
1938 if (to_end-to_nxt < 2)
1939 return codecvt_base::partial;
1940 if (((((unsigned long)c1 & 7) << 18) +
1941 (((unsigned long)c2 & 0x3F) << 12) +
1942 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1943 return codecvt_base::error;
1944 *to_nxt = static_cast<uint32_t>(
1945 0xD800
1946 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1947 | ((c2 & 0x0F) << 2)
1948 | ((c3 & 0x30) >> 4));
1949 *++to_nxt = static_cast<uint32_t>(
1950 0xDC00
1951 | ((c3 & 0x0F) << 6)
1952 | (c4 & 0x3F));
1953 frm_nxt += 4;
1954 }
1955 else
1956 {
1957 return codecvt_base::error;
1958 }
1959 }
1960 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1961}
1962
1963static
1964int
1965utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1966 size_t mx, unsigned long Maxcode = 0x10FFFF,
1967 codecvt_mode mode = codecvt_mode(0))
1968{
1969 const uint8_t* frm_nxt = frm;
1970 if (mode & consume_header)
1971 {
1972 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1973 frm_nxt[2] == 0xBF)
1974 frm_nxt += 3;
1975 }
1976 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1977 {
1978 uint8_t c1 = *frm_nxt;
1979 if (c1 > Maxcode)
1980 break;
1981 if (c1 < 0x80)
1982 {
1983 ++frm_nxt;
1984 }
1985 else if (c1 < 0xC2)
1986 {
1987 break;
1988 }
1989 else if (c1 < 0xE0)
1990 {
1991 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1992 break;
1993 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
1994 if (t > Maxcode)
1995 break;
1996 frm_nxt += 2;
1997 }
1998 else if (c1 < 0xF0)
1999 {
2000 if (frm_end-frm_nxt < 3)
2001 break;
2002 uint8_t c2 = frm_nxt[1];
2003 uint8_t c3 = frm_nxt[2];
2004 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2005 | ((c2 & 0x3F) << 6)
2006 | (c3 & 0x3F));
2007 switch (c1)
2008 {
2009 case 0xE0:
2010 if ((c2 & 0xE0) != 0xA0)
2011 return static_cast<int>(frm_nxt - frm);
2012 break;
2013 case 0xED:
2014 if ((c2 & 0xE0) != 0x80)
2015 return static_cast<int>(frm_nxt - frm);
2016 break;
2017 default:
2018 if ((c2 & 0xC0) != 0x80)
2019 return static_cast<int>(frm_nxt - frm);
2020 break;
2021 }
2022 if ((c3 & 0xC0) != 0x80)
2023 break;
2024 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2025 break;
2026 frm_nxt += 3;
2027 }
2028 else if (c1 < 0xF5)
2029 {
2030 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2031 break;
2032 uint8_t c2 = frm_nxt[1];
2033 uint8_t c3 = frm_nxt[2];
2034 uint8_t c4 = frm_nxt[3];
2035 switch (c1)
2036 {
2037 case 0xF0:
2038 if (!(0x90 <= c2 && c2 <= 0xBF))
2039 return static_cast<int>(frm_nxt - frm);
2040 break;
2041 case 0xF4:
2042 if ((c2 & 0xF0) != 0x80)
2043 return static_cast<int>(frm_nxt - frm);
2044 break;
2045 default:
2046 if ((c2 & 0xC0) != 0x80)
2047 return static_cast<int>(frm_nxt - frm);
2048 break;
2049 }
2050 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2051 break;
2052 if (((((unsigned long)c1 & 7) << 18) +
2053 (((unsigned long)c2 & 0x3F) << 12) +
2054 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2055 break;
2056 ++nchar16_t;
2057 frm_nxt += 4;
2058 }
2059 else
2060 {
2061 break;
2062 }
2063 }
2064 return static_cast<int>(frm_nxt - frm);
2065}
2066
2067static
2068codecvt_base::result
2069ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2070 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2071 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2072{
2073 frm_nxt = frm;
2074 to_nxt = to;
2075 if (mode & generate_header)
2076 {
2077 if (to_end-to_nxt < 3)
2078 return codecvt_base::partial;
2079 *to_nxt++ = static_cast<uint8_t>(0xEF);
2080 *to_nxt++ = static_cast<uint8_t>(0xBB);
2081 *to_nxt++ = static_cast<uint8_t>(0xBF);
2082 }
2083 for (; frm_nxt < frm_end; ++frm_nxt)
2084 {
2085 uint32_t wc = *frm_nxt;
2086 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2087 return codecvt_base::error;
2088 if (wc < 0x000080)
2089 {
2090 if (to_end-to_nxt < 1)
2091 return codecvt_base::partial;
2092 *to_nxt++ = static_cast<uint8_t>(wc);
2093 }
2094 else if (wc < 0x000800)
2095 {
2096 if (to_end-to_nxt < 2)
2097 return codecvt_base::partial;
2098 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2099 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2100 }
2101 else if (wc < 0x010000)
2102 {
2103 if (to_end-to_nxt < 3)
2104 return codecvt_base::partial;
2105 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2106 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2107 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2108 }
2109 else // if (wc < 0x110000)
2110 {
2111 if (to_end-to_nxt < 4)
2112 return codecvt_base::partial;
2113 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2114 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2115 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2116 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2117 }
2118 }
2119 return codecvt_base::ok;
2120}
2121
2122static
2123codecvt_base::result
2124utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2125 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2126 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2127{
2128 frm_nxt = frm;
2129 to_nxt = to;
2130 if (mode & consume_header)
2131 {
2132 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2133 frm_nxt[2] == 0xBF)
2134 frm_nxt += 3;
2135 }
2136 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2137 {
2138 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2139 if (c1 < 0x80)
2140 {
2141 if (c1 > Maxcode)
2142 return codecvt_base::error;
2143 *to_nxt = static_cast<uint32_t>(c1);
2144 ++frm_nxt;
2145 }
2146 else if (c1 < 0xC2)
2147 {
2148 return codecvt_base::error;
2149 }
2150 else if (c1 < 0xE0)
2151 {
2152 if (frm_end-frm_nxt < 2)
2153 return codecvt_base::partial;
2154 uint8_t c2 = frm_nxt[1];
2155 if ((c2 & 0xC0) != 0x80)
2156 return codecvt_base::error;
2157 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2158 | (c2 & 0x3F));
2159 if (t > Maxcode)
2160 return codecvt_base::error;
2161 *to_nxt = t;
2162 frm_nxt += 2;
2163 }
2164 else if (c1 < 0xF0)
2165 {
2166 if (frm_end-frm_nxt < 3)
2167 return codecvt_base::partial;
2168 uint8_t c2 = frm_nxt[1];
2169 uint8_t c3 = frm_nxt[2];
2170 switch (c1)
2171 {
2172 case 0xE0:
2173 if ((c2 & 0xE0) != 0xA0)
2174 return codecvt_base::error;
2175 break;
2176 case 0xED:
2177 if ((c2 & 0xE0) != 0x80)
2178 return codecvt_base::error;
2179 break;
2180 default:
2181 if ((c2 & 0xC0) != 0x80)
2182 return codecvt_base::error;
2183 break;
2184 }
2185 if ((c3 & 0xC0) != 0x80)
2186 return codecvt_base::error;
2187 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2188 | ((c2 & 0x3F) << 6)
2189 | (c3 & 0x3F));
2190 if (t > Maxcode)
2191 return codecvt_base::error;
2192 *to_nxt = t;
2193 frm_nxt += 3;
2194 }
2195 else if (c1 < 0xF5)
2196 {
2197 if (frm_end-frm_nxt < 4)
2198 return codecvt_base::partial;
2199 uint8_t c2 = frm_nxt[1];
2200 uint8_t c3 = frm_nxt[2];
2201 uint8_t c4 = frm_nxt[3];
2202 switch (c1)
2203 {
2204 case 0xF0:
2205 if (!(0x90 <= c2 && c2 <= 0xBF))
2206 return codecvt_base::error;
2207 break;
2208 case 0xF4:
2209 if ((c2 & 0xF0) != 0x80)
2210 return codecvt_base::error;
2211 break;
2212 default:
2213 if ((c2 & 0xC0) != 0x80)
2214 return codecvt_base::error;
2215 break;
2216 }
2217 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2218 return codecvt_base::error;
2219 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2220 | ((c2 & 0x3F) << 12)
2221 | ((c3 & 0x3F) << 6)
2222 | (c4 & 0x3F));
2223 if (t > Maxcode)
2224 return codecvt_base::error;
2225 *to_nxt = t;
2226 frm_nxt += 4;
2227 }
2228 else
2229 {
2230 return codecvt_base::error;
2231 }
2232 }
2233 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2234}
2235
2236static
2237int
2238utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2239 size_t mx, unsigned long Maxcode = 0x10FFFF,
2240 codecvt_mode mode = codecvt_mode(0))
2241{
2242 const uint8_t* frm_nxt = frm;
2243 if (mode & consume_header)
2244 {
2245 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2246 frm_nxt[2] == 0xBF)
2247 frm_nxt += 3;
2248 }
2249 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2250 {
2251 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2252 if (c1 < 0x80)
2253 {
2254 if (c1 > Maxcode)
2255 break;
2256 ++frm_nxt;
2257 }
2258 else if (c1 < 0xC2)
2259 {
2260 break;
2261 }
2262 else if (c1 < 0xE0)
2263 {
2264 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2265 break;
2266 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2267 break;
2268 frm_nxt += 2;
2269 }
2270 else if (c1 < 0xF0)
2271 {
2272 if (frm_end-frm_nxt < 3)
2273 break;
2274 uint8_t c2 = frm_nxt[1];
2275 uint8_t c3 = frm_nxt[2];
2276 switch (c1)
2277 {
2278 case 0xE0:
2279 if ((c2 & 0xE0) != 0xA0)
2280 return static_cast<int>(frm_nxt - frm);
2281 break;
2282 case 0xED:
2283 if ((c2 & 0xE0) != 0x80)
2284 return static_cast<int>(frm_nxt - frm);
2285 break;
2286 default:
2287 if ((c2 & 0xC0) != 0x80)
2288 return static_cast<int>(frm_nxt - frm);
2289 break;
2290 }
2291 if ((c3 & 0xC0) != 0x80)
2292 break;
2293 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2294 break;
2295 frm_nxt += 3;
2296 }
2297 else if (c1 < 0xF5)
2298 {
2299 if (frm_end-frm_nxt < 4)
2300 break;
2301 uint8_t c2 = frm_nxt[1];
2302 uint8_t c3 = frm_nxt[2];
2303 uint8_t c4 = frm_nxt[3];
2304 switch (c1)
2305 {
2306 case 0xF0:
2307 if (!(0x90 <= c2 && c2 <= 0xBF))
2308 return static_cast<int>(frm_nxt - frm);
2309 break;
2310 case 0xF4:
2311 if ((c2 & 0xF0) != 0x80)
2312 return static_cast<int>(frm_nxt - frm);
2313 break;
2314 default:
2315 if ((c2 & 0xC0) != 0x80)
2316 return static_cast<int>(frm_nxt - frm);
2317 break;
2318 }
2319 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2320 break;
2321 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2322 | ((c2 & 0x3F) << 12)
2323 | ((c3 & 0x3F) << 6)
2324 | (c4 & 0x3F));
2325 if ((((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) |
2326 ((c3 & 0x3F) << 6) | (c4 & 0x3F)) > Maxcode)
2327 break;
2328 frm_nxt += 4;
2329 }
2330 else
2331 {
2332 break;
2333 }
2334 }
2335 return static_cast<int>(frm_nxt - frm);
2336}
2337
2338static
2339codecvt_base::result
2340ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2341 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2342 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2343{
2344 frm_nxt = frm;
2345 to_nxt = to;
2346 if (mode & generate_header)
2347 {
2348 if (to_end-to_nxt < 3)
2349 return codecvt_base::partial;
2350 *to_nxt++ = static_cast<uint8_t>(0xEF);
2351 *to_nxt++ = static_cast<uint8_t>(0xBB);
2352 *to_nxt++ = static_cast<uint8_t>(0xBF);
2353 }
2354 for (; frm_nxt < frm_end; ++frm_nxt)
2355 {
2356 uint16_t wc = *frm_nxt;
2357 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2358 return codecvt_base::error;
2359 if (wc < 0x0080)
2360 {
2361 if (to_end-to_nxt < 1)
2362 return codecvt_base::partial;
2363 *to_nxt++ = static_cast<uint8_t>(wc);
2364 }
2365 else if (wc < 0x0800)
2366 {
2367 if (to_end-to_nxt < 2)
2368 return codecvt_base::partial;
2369 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2370 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2371 }
2372 else // if (wc <= 0xFFFF)
2373 {
2374 if (to_end-to_nxt < 3)
2375 return codecvt_base::partial;
2376 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2377 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2378 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2379 }
2380 }
2381 return codecvt_base::ok;
2382}
2383
2384static
2385codecvt_base::result
2386utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2387 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2388 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2389{
2390 frm_nxt = frm;
2391 to_nxt = to;
2392 if (mode & consume_header)
2393 {
2394 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2395 frm_nxt[2] == 0xBF)
2396 frm_nxt += 3;
2397 }
2398 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2399 {
2400 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2401 if (c1 < 0x80)
2402 {
2403 if (c1 > Maxcode)
2404 return codecvt_base::error;
2405 *to_nxt = static_cast<uint16_t>(c1);
2406 ++frm_nxt;
2407 }
2408 else if (c1 < 0xC2)
2409 {
2410 return codecvt_base::error;
2411 }
2412 else if (c1 < 0xE0)
2413 {
2414 if (frm_end-frm_nxt < 2)
2415 return codecvt_base::partial;
2416 uint8_t c2 = frm_nxt[1];
2417 if ((c2 & 0xC0) != 0x80)
2418 return codecvt_base::error;
2419 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2420 | (c2 & 0x3F));
2421 if (t > Maxcode)
2422 return codecvt_base::error;
2423 *to_nxt = t;
2424 frm_nxt += 2;
2425 }
2426 else if (c1 < 0xF0)
2427 {
2428 if (frm_end-frm_nxt < 3)
2429 return codecvt_base::partial;
2430 uint8_t c2 = frm_nxt[1];
2431 uint8_t c3 = frm_nxt[2];
2432 switch (c1)
2433 {
2434 case 0xE0:
2435 if ((c2 & 0xE0) != 0xA0)
2436 return codecvt_base::error;
2437 break;
2438 case 0xED:
2439 if ((c2 & 0xE0) != 0x80)
2440 return codecvt_base::error;
2441 break;
2442 default:
2443 if ((c2 & 0xC0) != 0x80)
2444 return codecvt_base::error;
2445 break;
2446 }
2447 if ((c3 & 0xC0) != 0x80)
2448 return codecvt_base::error;
2449 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2450 | ((c2 & 0x3F) << 6)
2451 | (c3 & 0x3F));
2452 if (t > Maxcode)
2453 return codecvt_base::error;
2454 *to_nxt = t;
2455 frm_nxt += 3;
2456 }
2457 else
2458 {
2459 return codecvt_base::error;
2460 }
2461 }
2462 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2463}
2464
2465static
2466int
2467utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2468 size_t mx, unsigned long Maxcode = 0x10FFFF,
2469 codecvt_mode mode = codecvt_mode(0))
2470{
2471 const uint8_t* frm_nxt = frm;
2472 if (mode & consume_header)
2473 {
2474 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2475 frm_nxt[2] == 0xBF)
2476 frm_nxt += 3;
2477 }
2478 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2479 {
2480 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2481 if (c1 < 0x80)
2482 {
2483 if (c1 > Maxcode)
2484 break;
2485 ++frm_nxt;
2486 }
2487 else if (c1 < 0xC2)
2488 {
2489 break;
2490 }
2491 else if (c1 < 0xE0)
2492 {
2493 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2494 break;
2495 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2496 break;
2497 frm_nxt += 2;
2498 }
2499 else if (c1 < 0xF0)
2500 {
2501 if (frm_end-frm_nxt < 3)
2502 break;
2503 uint8_t c2 = frm_nxt[1];
2504 uint8_t c3 = frm_nxt[2];
2505 switch (c1)
2506 {
2507 case 0xE0:
2508 if ((c2 & 0xE0) != 0xA0)
2509 return static_cast<int>(frm_nxt - frm);
2510 break;
2511 case 0xED:
2512 if ((c2 & 0xE0) != 0x80)
2513 return static_cast<int>(frm_nxt - frm);
2514 break;
2515 default:
2516 if ((c2 & 0xC0) != 0x80)
2517 return static_cast<int>(frm_nxt - frm);
2518 break;
2519 }
2520 if ((c3 & 0xC0) != 0x80)
2521 break;
2522 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2523 break;
2524 frm_nxt += 3;
2525 }
2526 else
2527 {
2528 break;
2529 }
2530 }
2531 return static_cast<int>(frm_nxt - frm);
2532}
2533
2534static
2535codecvt_base::result
2536ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2537 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2538 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2539{
2540 frm_nxt = frm;
2541 to_nxt = to;
2542 if (mode & generate_header)
2543 {
2544 if (to_end-to_nxt < 2)
2545 return codecvt_base::partial;
2546 *to_nxt++ = static_cast<uint8_t>(0xFE);
2547 *to_nxt++ = static_cast<uint8_t>(0xFF);
2548 }
2549 for (; frm_nxt < frm_end; ++frm_nxt)
2550 {
2551 uint32_t wc = *frm_nxt;
2552 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2553 return codecvt_base::error;
2554 if (wc < 0x010000)
2555 {
2556 if (to_end-to_nxt < 2)
2557 return codecvt_base::partial;
2558 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2559 *to_nxt++ = static_cast<uint8_t>(wc);
2560 }
2561 else
2562 {
2563 if (to_end-to_nxt < 4)
2564 return codecvt_base::partial;
2565 uint16_t t = static_cast<uint16_t>(
2566 0xD800
2567 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2568 | ((wc & 0x00FC00) >> 10));
2569 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2570 *to_nxt++ = static_cast<uint8_t>(t);
2571 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2572 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2573 *to_nxt++ = static_cast<uint8_t>(t);
2574 }
2575 }
2576 return codecvt_base::ok;
2577}
2578
2579static
2580codecvt_base::result
2581utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2582 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2583 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2584{
2585 frm_nxt = frm;
2586 to_nxt = to;
2587 if (mode & consume_header)
2588 {
2589 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2590 frm_nxt += 2;
2591 }
2592 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2593 {
2594 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2595 if ((c1 & 0xFC00) == 0xDC00)
2596 return codecvt_base::error;
2597 if ((c1 & 0xFC00) != 0xD800)
2598 {
2599 if (c1 > Maxcode)
2600 return codecvt_base::error;
2601 *to_nxt = static_cast<uint32_t>(c1);
2602 frm_nxt += 2;
2603 }
2604 else
2605 {
2606 if (frm_end-frm_nxt < 4)
2607 return codecvt_base::partial;
2608 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2609 if ((c2 & 0xFC00) != 0xDC00)
2610 return codecvt_base::error;
2611 uint32_t t = static_cast<uint32_t>(
2612 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2613 | ((c1 & 0x003F) << 10)
2614 | (c2 & 0x03FF));
2615 if (t > Maxcode)
2616 return codecvt_base::error;
2617 *to_nxt = t;
2618 frm_nxt += 4;
2619 }
2620 }
2621 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2622}
2623
2624static
2625int
2626utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2627 size_t mx, unsigned long Maxcode = 0x10FFFF,
2628 codecvt_mode mode = codecvt_mode(0))
2629{
2630 const uint8_t* frm_nxt = frm;
2631 frm_nxt = frm;
2632 if (mode & consume_header)
2633 {
2634 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2635 frm_nxt += 2;
2636 }
2637 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2638 {
2639 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2640 if ((c1 & 0xFC00) == 0xDC00)
2641 break;
2642 if ((c1 & 0xFC00) != 0xD800)
2643 {
2644 if (c1 > Maxcode)
2645 break;
2646 frm_nxt += 2;
2647 }
2648 else
2649 {
2650 if (frm_end-frm_nxt < 4)
2651 break;
2652 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2653 if ((c2 & 0xFC00) != 0xDC00)
2654 break;
2655 uint32_t t = static_cast<uint32_t>(
2656 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2657 | ((c1 & 0x003F) << 10)
2658 | (c2 & 0x03FF));
2659 if (t > Maxcode)
2660 break;
2661 frm_nxt += 4;
2662 }
2663 }
2664 return static_cast<int>(frm_nxt - frm);
2665}
2666
2667static
2668codecvt_base::result
2669ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2670 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2671 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2672{
2673 frm_nxt = frm;
2674 to_nxt = to;
2675 if (mode & generate_header)
2676 {
2677 if (to_end-to_nxt < 2)
2678 return codecvt_base::partial;
2679 *to_nxt++ = static_cast<uint8_t>(0xFF);
2680 *to_nxt++ = static_cast<uint8_t>(0xFE);
2681 }
2682 for (; frm_nxt < frm_end; ++frm_nxt)
2683 {
2684 uint32_t wc = *frm_nxt;
2685 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2686 return codecvt_base::error;
2687 if (wc < 0x010000)
2688 {
2689 if (to_end-to_nxt < 2)
2690 return codecvt_base::partial;
2691 *to_nxt++ = static_cast<uint8_t>(wc);
2692 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2693 }
2694 else
2695 {
2696 if (to_end-to_nxt < 4)
2697 return codecvt_base::partial;
2698 uint16_t t = static_cast<uint16_t>(
2699 0xD800
2700 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2701 | ((wc & 0x00FC00) >> 10));
2702 *to_nxt++ = static_cast<uint8_t>(t);
2703 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2704 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2705 *to_nxt++ = static_cast<uint8_t>(t);
2706 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2707 }
2708 }
2709 return codecvt_base::ok;
2710}
2711
2712static
2713codecvt_base::result
2714utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2715 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2716 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2717{
2718 frm_nxt = frm;
2719 to_nxt = to;
2720 if (mode & consume_header)
2721 {
2722 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2723 frm_nxt += 2;
2724 }
2725 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2726 {
2727 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2728 if ((c1 & 0xFC00) == 0xDC00)
2729 return codecvt_base::error;
2730 if ((c1 & 0xFC00) != 0xD800)
2731 {
2732 if (c1 > Maxcode)
2733 return codecvt_base::error;
2734 *to_nxt = static_cast<uint32_t>(c1);
2735 frm_nxt += 2;
2736 }
2737 else
2738 {
2739 if (frm_end-frm_nxt < 4)
2740 return codecvt_base::partial;
2741 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2742 if ((c2 & 0xFC00) != 0xDC00)
2743 return codecvt_base::error;
2744 uint32_t t = static_cast<uint32_t>(
2745 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2746 | ((c1 & 0x003F) << 10)
2747 | (c2 & 0x03FF));
2748 if (t > Maxcode)
2749 return codecvt_base::error;
2750 *to_nxt = t;
2751 frm_nxt += 4;
2752 }
2753 }
2754 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2755}
2756
2757static
2758int
2759utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2760 size_t mx, unsigned long Maxcode = 0x10FFFF,
2761 codecvt_mode mode = codecvt_mode(0))
2762{
2763 const uint8_t* frm_nxt = frm;
2764 frm_nxt = frm;
2765 if (mode & consume_header)
2766 {
2767 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2768 frm_nxt += 2;
2769 }
2770 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2771 {
2772 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2773 if ((c1 & 0xFC00) == 0xDC00)
2774 break;
2775 if ((c1 & 0xFC00) != 0xD800)
2776 {
2777 if (c1 > Maxcode)
2778 break;
2779 frm_nxt += 2;
2780 }
2781 else
2782 {
2783 if (frm_end-frm_nxt < 4)
2784 break;
2785 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2786 if ((c2 & 0xFC00) != 0xDC00)
2787 break;
2788 uint32_t t = static_cast<uint32_t>(
2789 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2790 | ((c1 & 0x003F) << 10)
2791 | (c2 & 0x03FF));
2792 if (t > Maxcode)
2793 break;
2794 frm_nxt += 4;
2795 }
2796 }
2797 return static_cast<int>(frm_nxt - frm);
2798}
2799
2800static
2801codecvt_base::result
2802ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2803 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2804 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2805{
2806 frm_nxt = frm;
2807 to_nxt = to;
2808 if (mode & generate_header)
2809 {
2810 if (to_end-to_nxt < 2)
2811 return codecvt_base::partial;
2812 *to_nxt++ = static_cast<uint8_t>(0xFE);
2813 *to_nxt++ = static_cast<uint8_t>(0xFF);
2814 }
2815 for (; frm_nxt < frm_end; ++frm_nxt)
2816 {
2817 uint16_t wc = *frm_nxt;
2818 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2819 return codecvt_base::error;
2820 if (to_end-to_nxt < 2)
2821 return codecvt_base::partial;
2822 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2823 *to_nxt++ = static_cast<uint8_t>(wc);
2824 }
2825 return codecvt_base::ok;
2826}
2827
2828static
2829codecvt_base::result
2830utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2831 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2832 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2833{
2834 frm_nxt = frm;
2835 to_nxt = to;
2836 if (mode & consume_header)
2837 {
2838 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2839 frm_nxt += 2;
2840 }
2841 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2842 {
2843 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2844 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2845 return codecvt_base::error;
2846 *to_nxt = c1;
2847 frm_nxt += 2;
2848 }
2849 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2850}
2851
2852static
2853int
2854utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2855 size_t mx, unsigned long Maxcode = 0x10FFFF,
2856 codecvt_mode mode = codecvt_mode(0))
2857{
2858 const uint8_t* frm_nxt = frm;
2859 frm_nxt = frm;
2860 if (mode & consume_header)
2861 {
2862 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2863 frm_nxt += 2;
2864 }
2865 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2866 {
2867 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2868 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2869 break;
2870 frm_nxt += 2;
2871 }
2872 return static_cast<int>(frm_nxt - frm);
2873}
2874
2875static
2876codecvt_base::result
2877ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2878 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2879 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2880{
2881 frm_nxt = frm;
2882 to_nxt = to;
2883 if (mode & generate_header)
2884 {
2885 if (to_end-to_nxt < 2)
2886 return codecvt_base::partial;
2887 *to_nxt++ = static_cast<uint8_t>(0xFF);
2888 *to_nxt++ = static_cast<uint8_t>(0xFE);
2889 }
2890 for (; frm_nxt < frm_end; ++frm_nxt)
2891 {
2892 uint16_t wc = *frm_nxt;
2893 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2894 return codecvt_base::error;
2895 if (to_end-to_nxt < 2)
2896 return codecvt_base::partial;
2897 *to_nxt++ = static_cast<uint8_t>(wc);
2898 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2899 }
2900 return codecvt_base::ok;
2901}
2902
2903static
2904codecvt_base::result
2905utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2906 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2907 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2908{
2909 frm_nxt = frm;
2910 to_nxt = to;
2911 if (mode & consume_header)
2912 {
2913 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2914 frm_nxt += 2;
2915 }
2916 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2917 {
2918 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2919 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2920 return codecvt_base::error;
2921 *to_nxt = c1;
2922 frm_nxt += 2;
2923 }
2924 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2925}
2926
2927static
2928int
2929utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2930 size_t mx, unsigned long Maxcode = 0x10FFFF,
2931 codecvt_mode mode = codecvt_mode(0))
2932{
2933 const uint8_t* frm_nxt = frm;
2934 frm_nxt = frm;
2935 if (mode & consume_header)
2936 {
2937 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2938 frm_nxt += 2;
2939 }
2940 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2941 {
2942 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2943 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2944 break;
2945 frm_nxt += 2;
2946 }
2947 return static_cast<int>(frm_nxt - frm);
2948}
2949
Howard Hinnantc51e1022010-05-11 19:42:16 +00002950// template <> class codecvt<char16_t, char, mbstate_t>
2951
Howard Hinnantffb308e2010-08-22 00:03:27 +00002952locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002953
2954codecvt<char16_t, char, mbstate_t>::~codecvt()
2955{
2956}
2957
2958codecvt<char16_t, char, mbstate_t>::result
2959codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00002960 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002961 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2962{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002963 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2964 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2965 const uint16_t* _frm_nxt = _frm;
2966 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2967 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2968 uint8_t* _to_nxt = _to;
2969 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2970 frm_nxt = frm + (_frm_nxt - _frm);
2971 to_nxt = to + (_to_nxt - _to);
2972 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002973}
2974
2975codecvt<char16_t, char, mbstate_t>::result
2976codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00002977 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002978 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2979{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002980 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2981 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2982 const uint8_t* _frm_nxt = _frm;
2983 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2984 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2985 uint16_t* _to_nxt = _to;
2986 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2987 frm_nxt = frm + (_frm_nxt - _frm);
2988 to_nxt = to + (_to_nxt - _to);
2989 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002990}
2991
2992codecvt<char16_t, char, mbstate_t>::result
2993codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
2994 extern_type* to, extern_type*, extern_type*& to_nxt) const
2995{
2996 to_nxt = to;
2997 return noconv;
2998}
2999
3000int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003001codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003002{
3003 return 0;
3004}
3005
3006bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003007codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003008{
3009 return false;
3010}
3011
3012int
3013codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3014 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3015{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003016 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3017 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3018 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003019}
3020
3021int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003022codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003023{
3024 return 4;
3025}
3026
3027// template <> class codecvt<char32_t, char, mbstate_t>
3028
Howard Hinnantffb308e2010-08-22 00:03:27 +00003029locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003030
3031codecvt<char32_t, char, mbstate_t>::~codecvt()
3032{
3033}
3034
3035codecvt<char32_t, char, mbstate_t>::result
3036codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003037 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003038 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3039{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003040 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3041 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3042 const uint32_t* _frm_nxt = _frm;
3043 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3044 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3045 uint8_t* _to_nxt = _to;
3046 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3047 frm_nxt = frm + (_frm_nxt - _frm);
3048 to_nxt = to + (_to_nxt - _to);
3049 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003050}
3051
3052codecvt<char32_t, char, mbstate_t>::result
3053codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003054 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003055 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3056{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003057 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3058 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3059 const uint8_t* _frm_nxt = _frm;
3060 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3061 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3062 uint32_t* _to_nxt = _to;
3063 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3064 frm_nxt = frm + (_frm_nxt - _frm);
3065 to_nxt = to + (_to_nxt - _to);
3066 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003067}
3068
3069codecvt<char32_t, char, mbstate_t>::result
3070codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3071 extern_type* to, extern_type*, extern_type*& to_nxt) const
3072{
3073 to_nxt = to;
3074 return noconv;
3075}
3076
3077int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003078codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003079{
3080 return 0;
3081}
3082
3083bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003084codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003085{
3086 return false;
3087}
3088
3089int
3090codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3091 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3092{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003093 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3094 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3095 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003096}
3097
3098int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003099codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003100{
3101 return 4;
3102}
3103
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003104// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003105
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003106__codecvt_utf8<wchar_t>::result
3107__codecvt_utf8<wchar_t>::do_out(state_type&,
3108 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003109 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3110{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003111 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3112 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3113 const uint32_t* _frm_nxt = _frm;
3114 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3115 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3116 uint8_t* _to_nxt = _to;
3117 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3118 _Maxcode_, _Mode_);
3119 frm_nxt = frm + (_frm_nxt - _frm);
3120 to_nxt = to + (_to_nxt - _to);
3121 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003122}
3123
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003124__codecvt_utf8<wchar_t>::result
3125__codecvt_utf8<wchar_t>::do_in(state_type&,
3126 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003127 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3128{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003129 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3130 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3131 const uint8_t* _frm_nxt = _frm;
3132 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3133 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3134 uint32_t* _to_nxt = _to;
3135 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3136 _Maxcode_, _Mode_);
3137 frm_nxt = frm + (_frm_nxt - _frm);
3138 to_nxt = to + (_to_nxt - _to);
3139 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003140}
3141
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003142__codecvt_utf8<wchar_t>::result
3143__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003144 extern_type* to, extern_type*, extern_type*& to_nxt) const
3145{
3146 to_nxt = to;
3147 return noconv;
3148}
3149
3150int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003151__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003152{
3153 return 0;
3154}
3155
3156bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003157__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003158{
3159 return false;
3160}
3161
3162int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003163__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003164 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3165{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003166 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3167 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3168 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003169}
3170
3171int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003172__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003173{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003174 if (_Mode_ & consume_header)
3175 return 7;
3176 return 4;
3177}
3178
3179// __codecvt_utf8<char16_t>
3180
3181__codecvt_utf8<char16_t>::result
3182__codecvt_utf8<char16_t>::do_out(state_type&,
3183 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3184 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3185{
3186 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3187 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3188 const uint16_t* _frm_nxt = _frm;
3189 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3190 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3191 uint8_t* _to_nxt = _to;
3192 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3193 _Maxcode_, _Mode_);
3194 frm_nxt = frm + (_frm_nxt - _frm);
3195 to_nxt = to + (_to_nxt - _to);
3196 return r;
3197}
3198
3199__codecvt_utf8<char16_t>::result
3200__codecvt_utf8<char16_t>::do_in(state_type&,
3201 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3202 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3203{
3204 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3205 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3206 const uint8_t* _frm_nxt = _frm;
3207 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3208 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3209 uint16_t* _to_nxt = _to;
3210 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3211 _Maxcode_, _Mode_);
3212 frm_nxt = frm + (_frm_nxt - _frm);
3213 to_nxt = to + (_to_nxt - _to);
3214 return r;
3215}
3216
3217__codecvt_utf8<char16_t>::result
3218__codecvt_utf8<char16_t>::do_unshift(state_type&,
3219 extern_type* to, extern_type*, extern_type*& to_nxt) const
3220{
3221 to_nxt = to;
3222 return noconv;
3223}
3224
3225int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003226__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003227{
3228 return 0;
3229}
3230
3231bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003232__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003233{
3234 return false;
3235}
3236
3237int
3238__codecvt_utf8<char16_t>::do_length(state_type&,
3239 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3240{
3241 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3242 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3243 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3244}
3245
3246int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003247__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003248{
3249 if (_Mode_ & consume_header)
3250 return 6;
3251 return 3;
3252}
3253
3254// __codecvt_utf8<char32_t>
3255
3256__codecvt_utf8<char32_t>::result
3257__codecvt_utf8<char32_t>::do_out(state_type&,
3258 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3259 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3260{
3261 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3262 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3263 const uint32_t* _frm_nxt = _frm;
3264 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3265 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3266 uint8_t* _to_nxt = _to;
3267 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3268 _Maxcode_, _Mode_);
3269 frm_nxt = frm + (_frm_nxt - _frm);
3270 to_nxt = to + (_to_nxt - _to);
3271 return r;
3272}
3273
3274__codecvt_utf8<char32_t>::result
3275__codecvt_utf8<char32_t>::do_in(state_type&,
3276 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3277 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3278{
3279 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3280 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3281 const uint8_t* _frm_nxt = _frm;
3282 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3283 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3284 uint32_t* _to_nxt = _to;
3285 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3286 _Maxcode_, _Mode_);
3287 frm_nxt = frm + (_frm_nxt - _frm);
3288 to_nxt = to + (_to_nxt - _to);
3289 return r;
3290}
3291
3292__codecvt_utf8<char32_t>::result
3293__codecvt_utf8<char32_t>::do_unshift(state_type&,
3294 extern_type* to, extern_type*, extern_type*& to_nxt) const
3295{
3296 to_nxt = to;
3297 return noconv;
3298}
3299
3300int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003301__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003302{
3303 return 0;
3304}
3305
3306bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003307__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003308{
3309 return false;
3310}
3311
3312int
3313__codecvt_utf8<char32_t>::do_length(state_type&,
3314 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3315{
3316 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3317 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3318 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3319}
3320
3321int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003322__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003323{
3324 if (_Mode_ & consume_header)
3325 return 7;
3326 return 4;
3327}
3328
3329// __codecvt_utf16<wchar_t, false>
3330
3331__codecvt_utf16<wchar_t, false>::result
3332__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3333 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3334 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3335{
3336 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3337 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3338 const uint32_t* _frm_nxt = _frm;
3339 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3340 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3341 uint8_t* _to_nxt = _to;
3342 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3343 _Maxcode_, _Mode_);
3344 frm_nxt = frm + (_frm_nxt - _frm);
3345 to_nxt = to + (_to_nxt - _to);
3346 return r;
3347}
3348
3349__codecvt_utf16<wchar_t, false>::result
3350__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3351 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3352 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3353{
3354 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3355 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3356 const uint8_t* _frm_nxt = _frm;
3357 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3358 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3359 uint32_t* _to_nxt = _to;
3360 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3361 _Maxcode_, _Mode_);
3362 frm_nxt = frm + (_frm_nxt - _frm);
3363 to_nxt = to + (_to_nxt - _to);
3364 return r;
3365}
3366
3367__codecvt_utf16<wchar_t, false>::result
3368__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3369 extern_type* to, extern_type*, extern_type*& to_nxt) const
3370{
3371 to_nxt = to;
3372 return noconv;
3373}
3374
3375int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003376__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003377{
3378 return 0;
3379}
3380
3381bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003382__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003383{
3384 return false;
3385}
3386
3387int
3388__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3389 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3390{
3391 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3392 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3393 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3394}
3395
3396int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003397__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003398{
3399 if (_Mode_ & consume_header)
3400 return 6;
3401 return 4;
3402}
3403
3404// __codecvt_utf16<wchar_t, true>
3405
3406__codecvt_utf16<wchar_t, true>::result
3407__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3408 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3409 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3410{
3411 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3412 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3413 const uint32_t* _frm_nxt = _frm;
3414 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3415 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3416 uint8_t* _to_nxt = _to;
3417 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3418 _Maxcode_, _Mode_);
3419 frm_nxt = frm + (_frm_nxt - _frm);
3420 to_nxt = to + (_to_nxt - _to);
3421 return r;
3422}
3423
3424__codecvt_utf16<wchar_t, true>::result
3425__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3426 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3427 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3428{
3429 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3430 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3431 const uint8_t* _frm_nxt = _frm;
3432 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3433 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3434 uint32_t* _to_nxt = _to;
3435 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3436 _Maxcode_, _Mode_);
3437 frm_nxt = frm + (_frm_nxt - _frm);
3438 to_nxt = to + (_to_nxt - _to);
3439 return r;
3440}
3441
3442__codecvt_utf16<wchar_t, true>::result
3443__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3444 extern_type* to, extern_type*, extern_type*& to_nxt) const
3445{
3446 to_nxt = to;
3447 return noconv;
3448}
3449
3450int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003451__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003452{
3453 return 0;
3454}
3455
3456bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003457__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003458{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003459 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003460}
3461
3462int
3463__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3464 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3465{
3466 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3467 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3468 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3469}
3470
3471int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003472__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003473{
3474 if (_Mode_ & consume_header)
3475 return 6;
3476 return 4;
3477}
3478
3479// __codecvt_utf16<char16_t, false>
3480
3481__codecvt_utf16<char16_t, false>::result
3482__codecvt_utf16<char16_t, false>::do_out(state_type&,
3483 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3484 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3485{
3486 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3487 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3488 const uint16_t* _frm_nxt = _frm;
3489 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3490 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3491 uint8_t* _to_nxt = _to;
3492 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3493 _Maxcode_, _Mode_);
3494 frm_nxt = frm + (_frm_nxt - _frm);
3495 to_nxt = to + (_to_nxt - _to);
3496 return r;
3497}
3498
3499__codecvt_utf16<char16_t, false>::result
3500__codecvt_utf16<char16_t, false>::do_in(state_type&,
3501 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3502 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3503{
3504 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3505 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3506 const uint8_t* _frm_nxt = _frm;
3507 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3508 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3509 uint16_t* _to_nxt = _to;
3510 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3511 _Maxcode_, _Mode_);
3512 frm_nxt = frm + (_frm_nxt - _frm);
3513 to_nxt = to + (_to_nxt - _to);
3514 return r;
3515}
3516
3517__codecvt_utf16<char16_t, false>::result
3518__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3519 extern_type* to, extern_type*, extern_type*& to_nxt) const
3520{
3521 to_nxt = to;
3522 return noconv;
3523}
3524
3525int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003526__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003527{
3528 return 0;
3529}
3530
3531bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003532__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003533{
3534 return false;
3535}
3536
3537int
3538__codecvt_utf16<char16_t, false>::do_length(state_type&,
3539 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3540{
3541 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3542 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3543 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3544}
3545
3546int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003547__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003548{
3549 if (_Mode_ & consume_header)
3550 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003551 return 2;
3552}
3553
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003554// __codecvt_utf16<char16_t, true>
3555
3556__codecvt_utf16<char16_t, true>::result
3557__codecvt_utf16<char16_t, true>::do_out(state_type&,
3558 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3559 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3560{
3561 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3562 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3563 const uint16_t* _frm_nxt = _frm;
3564 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3565 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3566 uint8_t* _to_nxt = _to;
3567 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3568 _Maxcode_, _Mode_);
3569 frm_nxt = frm + (_frm_nxt - _frm);
3570 to_nxt = to + (_to_nxt - _to);
3571 return r;
3572}
3573
3574__codecvt_utf16<char16_t, true>::result
3575__codecvt_utf16<char16_t, true>::do_in(state_type&,
3576 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3577 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3578{
3579 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3580 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3581 const uint8_t* _frm_nxt = _frm;
3582 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3583 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3584 uint16_t* _to_nxt = _to;
3585 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3586 _Maxcode_, _Mode_);
3587 frm_nxt = frm + (_frm_nxt - _frm);
3588 to_nxt = to + (_to_nxt - _to);
3589 return r;
3590}
3591
3592__codecvt_utf16<char16_t, true>::result
3593__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3594 extern_type* to, extern_type*, extern_type*& to_nxt) const
3595{
3596 to_nxt = to;
3597 return noconv;
3598}
3599
3600int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003601__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003602{
3603 return 0;
3604}
3605
3606bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003607__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003608{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003609 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003610}
3611
3612int
3613__codecvt_utf16<char16_t, true>::do_length(state_type&,
3614 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3615{
3616 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3617 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3618 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3619}
3620
3621int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003622__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003623{
3624 if (_Mode_ & consume_header)
3625 return 4;
3626 return 2;
3627}
3628
3629// __codecvt_utf16<char32_t, false>
3630
3631__codecvt_utf16<char32_t, false>::result
3632__codecvt_utf16<char32_t, false>::do_out(state_type&,
3633 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3634 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3635{
3636 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3637 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3638 const uint32_t* _frm_nxt = _frm;
3639 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3640 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3641 uint8_t* _to_nxt = _to;
3642 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3643 _Maxcode_, _Mode_);
3644 frm_nxt = frm + (_frm_nxt - _frm);
3645 to_nxt = to + (_to_nxt - _to);
3646 return r;
3647}
3648
3649__codecvt_utf16<char32_t, false>::result
3650__codecvt_utf16<char32_t, false>::do_in(state_type&,
3651 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3652 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3653{
3654 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3655 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3656 const uint8_t* _frm_nxt = _frm;
3657 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3658 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3659 uint32_t* _to_nxt = _to;
3660 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3661 _Maxcode_, _Mode_);
3662 frm_nxt = frm + (_frm_nxt - _frm);
3663 to_nxt = to + (_to_nxt - _to);
3664 return r;
3665}
3666
3667__codecvt_utf16<char32_t, false>::result
3668__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3669 extern_type* to, extern_type*, extern_type*& to_nxt) const
3670{
3671 to_nxt = to;
3672 return noconv;
3673}
3674
3675int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003676__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003677{
3678 return 0;
3679}
3680
3681bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003682__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003683{
3684 return false;
3685}
3686
3687int
3688__codecvt_utf16<char32_t, false>::do_length(state_type&,
3689 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3690{
3691 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3692 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3693 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3694}
3695
3696int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003697__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003698{
3699 if (_Mode_ & consume_header)
3700 return 6;
3701 return 4;
3702}
3703
3704// __codecvt_utf16<char32_t, true>
3705
3706__codecvt_utf16<char32_t, true>::result
3707__codecvt_utf16<char32_t, true>::do_out(state_type&,
3708 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3709 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3710{
3711 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3712 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3713 const uint32_t* _frm_nxt = _frm;
3714 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3715 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3716 uint8_t* _to_nxt = _to;
3717 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3718 _Maxcode_, _Mode_);
3719 frm_nxt = frm + (_frm_nxt - _frm);
3720 to_nxt = to + (_to_nxt - _to);
3721 return r;
3722}
3723
3724__codecvt_utf16<char32_t, true>::result
3725__codecvt_utf16<char32_t, true>::do_in(state_type&,
3726 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3727 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3728{
3729 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3730 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3731 const uint8_t* _frm_nxt = _frm;
3732 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3733 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3734 uint32_t* _to_nxt = _to;
3735 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3736 _Maxcode_, _Mode_);
3737 frm_nxt = frm + (_frm_nxt - _frm);
3738 to_nxt = to + (_to_nxt - _to);
3739 return r;
3740}
3741
3742__codecvt_utf16<char32_t, true>::result
3743__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3744 extern_type* to, extern_type*, extern_type*& to_nxt) const
3745{
3746 to_nxt = to;
3747 return noconv;
3748}
3749
3750int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003751__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003752{
3753 return 0;
3754}
3755
3756bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003757__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003758{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003759 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003760}
3761
3762int
3763__codecvt_utf16<char32_t, true>::do_length(state_type&,
3764 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3765{
3766 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3767 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3768 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3769}
3770
3771int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003772__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003773{
3774 if (_Mode_ & consume_header)
3775 return 6;
3776 return 4;
3777}
3778
3779// __codecvt_utf8_utf16<wchar_t>
3780
3781__codecvt_utf8_utf16<wchar_t>::result
3782__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3783 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3784 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3785{
3786 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3787 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3788 const uint32_t* _frm_nxt = _frm;
3789 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3790 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3791 uint8_t* _to_nxt = _to;
3792 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3793 _Maxcode_, _Mode_);
3794 frm_nxt = frm + (_frm_nxt - _frm);
3795 to_nxt = to + (_to_nxt - _to);
3796 return r;
3797}
3798
3799__codecvt_utf8_utf16<wchar_t>::result
3800__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3801 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3802 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3803{
3804 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3805 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3806 const uint8_t* _frm_nxt = _frm;
3807 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3808 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3809 uint32_t* _to_nxt = _to;
3810 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3811 _Maxcode_, _Mode_);
3812 frm_nxt = frm + (_frm_nxt - _frm);
3813 to_nxt = to + (_to_nxt - _to);
3814 return r;
3815}
3816
3817__codecvt_utf8_utf16<wchar_t>::result
3818__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3819 extern_type* to, extern_type*, extern_type*& to_nxt) const
3820{
3821 to_nxt = to;
3822 return noconv;
3823}
3824
3825int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003826__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003827{
3828 return 0;
3829}
3830
3831bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003832__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003833{
3834 return false;
3835}
3836
3837int
3838__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3839 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3840{
3841 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3842 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3843 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3844}
3845
3846int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003847__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003848{
3849 if (_Mode_ & consume_header)
3850 return 7;
3851 return 4;
3852}
3853
3854// __codecvt_utf8_utf16<char16_t>
3855
3856__codecvt_utf8_utf16<char16_t>::result
3857__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3858 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3859 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3860{
3861 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3862 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3863 const uint16_t* _frm_nxt = _frm;
3864 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3865 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3866 uint8_t* _to_nxt = _to;
3867 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3868 _Maxcode_, _Mode_);
3869 frm_nxt = frm + (_frm_nxt - _frm);
3870 to_nxt = to + (_to_nxt - _to);
3871 return r;
3872}
3873
3874__codecvt_utf8_utf16<char16_t>::result
3875__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3876 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3877 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3878{
3879 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3880 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3881 const uint8_t* _frm_nxt = _frm;
3882 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3883 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3884 uint16_t* _to_nxt = _to;
3885 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3886 _Maxcode_, _Mode_);
3887 frm_nxt = frm + (_frm_nxt - _frm);
3888 to_nxt = to + (_to_nxt - _to);
3889 return r;
3890}
3891
3892__codecvt_utf8_utf16<char16_t>::result
3893__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3894 extern_type* to, extern_type*, extern_type*& to_nxt) const
3895{
3896 to_nxt = to;
3897 return noconv;
3898}
3899
3900int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003901__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003902{
3903 return 0;
3904}
3905
3906bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003907__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003908{
3909 return false;
3910}
3911
3912int
3913__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3914 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3915{
3916 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3917 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3918 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3919}
3920
3921int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003922__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003923{
3924 if (_Mode_ & consume_header)
3925 return 7;
3926 return 4;
3927}
3928
3929// __codecvt_utf8_utf16<char32_t>
3930
3931__codecvt_utf8_utf16<char32_t>::result
3932__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3933 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3934 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3935{
3936 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3937 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3938 const uint32_t* _frm_nxt = _frm;
3939 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3940 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3941 uint8_t* _to_nxt = _to;
3942 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3943 _Maxcode_, _Mode_);
3944 frm_nxt = frm + (_frm_nxt - _frm);
3945 to_nxt = to + (_to_nxt - _to);
3946 return r;
3947}
3948
3949__codecvt_utf8_utf16<char32_t>::result
3950__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3951 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3952 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3953{
3954 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3955 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3956 const uint8_t* _frm_nxt = _frm;
3957 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3958 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3959 uint32_t* _to_nxt = _to;
3960 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3961 _Maxcode_, _Mode_);
3962 frm_nxt = frm + (_frm_nxt - _frm);
3963 to_nxt = to + (_to_nxt - _to);
3964 return r;
3965}
3966
3967__codecvt_utf8_utf16<char32_t>::result
3968__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3969 extern_type* to, extern_type*, extern_type*& to_nxt) const
3970{
3971 to_nxt = to;
3972 return noconv;
3973}
3974
3975int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003976__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003977{
3978 return 0;
3979}
3980
3981bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003982__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003983{
3984 return false;
3985}
3986
3987int
3988__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3989 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3990{
3991 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3992 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3993 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3994}
3995
3996int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003997__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003998{
3999 if (_Mode_ & consume_header)
4000 return 7;
4001 return 4;
4002}
4003
Howard Hinnantc51e1022010-05-11 19:42:16 +00004004// __narrow_to_utf8<16>
4005
4006__narrow_to_utf8<16>::~__narrow_to_utf8()
4007{
4008}
4009
4010// __narrow_to_utf8<32>
4011
4012__narrow_to_utf8<32>::~__narrow_to_utf8()
4013{
4014}
4015
4016// __widen_from_utf8<16>
4017
4018__widen_from_utf8<16>::~__widen_from_utf8()
4019{
4020}
4021
4022// __widen_from_utf8<32>
4023
4024__widen_from_utf8<32>::~__widen_from_utf8()
4025{
4026}
4027
4028// numpunct<char> && numpunct<wchar_t>
4029
4030locale::id numpunct< char >::id;
4031locale::id numpunct<wchar_t>::id;
4032
4033numpunct<char>::numpunct(size_t refs)
4034 : locale::facet(refs),
4035 __decimal_point_('.'),
4036 __thousands_sep_(',')
4037{
4038}
4039
4040numpunct<wchar_t>::numpunct(size_t refs)
4041 : locale::facet(refs),
4042 __decimal_point_(L'.'),
4043 __thousands_sep_(L',')
4044{
4045}
4046
4047numpunct<char>::~numpunct()
4048{
4049}
4050
4051numpunct<wchar_t>::~numpunct()
4052{
4053}
4054
4055 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4056wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4057
4058 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4059wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4060
4061string numpunct< char >::do_grouping() const {return __grouping_;}
4062string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4063
4064 string numpunct< char >::do_truename() const {return "true";}
4065wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4066
4067 string numpunct< char >::do_falsename() const {return "false";}
4068wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4069
4070// numpunct_byname<char>
4071
4072numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4073 : numpunct<char>(refs)
4074{
4075 __init(nm);
4076}
4077
4078numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4079 : numpunct<char>(refs)
4080{
4081 __init(nm.c_str());
4082}
4083
4084numpunct_byname<char>::~numpunct_byname()
4085{
4086}
4087
4088void
4089numpunct_byname<char>::__init(const char* nm)
4090{
4091 if (strcmp(nm, "C") != 0)
4092 {
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004093 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004094#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004095 if (loc == 0)
4096 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4097 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004098#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004099 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004100 if (*lc->decimal_point)
4101 __decimal_point_ = *lc->decimal_point;
4102 if (*lc->thousands_sep)
4103 __thousands_sep_ = *lc->thousands_sep;
4104 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004105 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004106 }
4107}
4108
4109// numpunct_byname<wchar_t>
4110
4111numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4112 : numpunct<wchar_t>(refs)
4113{
4114 __init(nm);
4115}
4116
4117numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4118 : numpunct<wchar_t>(refs)
4119{
4120 __init(nm.c_str());
4121}
4122
4123numpunct_byname<wchar_t>::~numpunct_byname()
4124{
4125}
4126
4127void
4128numpunct_byname<wchar_t>::__init(const char* nm)
4129{
4130 if (strcmp(nm, "C") != 0)
4131 {
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004132 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004133#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004134 if (loc == 0)
4135 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4136 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004137#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004138 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004139 if (*lc->decimal_point)
4140 __decimal_point_ = *lc->decimal_point;
4141 if (*lc->thousands_sep)
4142 __thousands_sep_ = *lc->thousands_sep;
4143 __grouping_ = lc->grouping;
4144 // locallization for truename and falsename is not available
4145 }
4146}
4147
4148// num_get helpers
4149
4150int
4151__num_get_base::__get_base(ios_base& iob)
4152{
4153 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4154 if (__basefield == ios_base::oct)
4155 return 8;
4156 else if (__basefield == ios_base::hex)
4157 return 16;
4158 else if (__basefield == 0)
4159 return 0;
4160 return 10;
4161}
4162
4163const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4164
4165void
4166__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4167 ios_base::iostate& __err)
4168{
4169 if (__grouping.size() != 0)
4170 {
4171 reverse(__g, __g_end);
4172 const char* __ig = __grouping.data();
4173 const char* __eg = __ig + __grouping.size();
4174 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4175 {
4176 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4177 {
4178 if (*__ig != *__r)
4179 {
4180 __err = ios_base::failbit;
4181 return;
4182 }
4183 }
4184 if (__eg - __ig > 1)
4185 ++__ig;
4186 }
4187 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4188 {
4189 if (*__ig < __g_end[-1] || __g_end[-1] == 0)
4190 __err = ios_base::failbit;
4191 }
4192 }
4193}
4194
4195void
4196__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4197 ios_base::fmtflags __flags)
4198{
4199 if (__flags & ios_base::showpos)
4200 *__fmtp++ = '+';
4201 if (__flags & ios_base::showbase)
4202 *__fmtp++ = '#';
4203 while(*__len)
4204 *__fmtp++ = *__len++;
4205 if ((__flags & ios_base::basefield) == ios_base::oct)
4206 *__fmtp = 'o';
4207 else if ((__flags & ios_base::basefield) == ios_base::hex)
4208 {
4209 if (__flags & ios_base::uppercase)
4210 *__fmtp = 'X';
4211 else
4212 *__fmtp = 'x';
4213 }
4214 else if (__signd)
4215 *__fmtp = 'd';
4216 else
4217 *__fmtp = 'u';
4218}
4219
4220bool
4221__num_put_base::__format_float(char* __fmtp, const char* __len,
4222 ios_base::fmtflags __flags)
4223{
4224 bool specify_precision = true;
4225 if (__flags & ios_base::showpos)
4226 *__fmtp++ = '+';
4227 if (__flags & ios_base::showpoint)
4228 *__fmtp++ = '#';
4229 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4230 bool uppercase = __flags & ios_base::uppercase;
4231 if (floatfield == (ios_base::fixed | ios_base::scientific))
4232 specify_precision = false;
4233 else
4234 {
4235 *__fmtp++ = '.';
4236 *__fmtp++ = '*';
4237 }
4238 while(*__len)
4239 *__fmtp++ = *__len++;
4240 if (floatfield == ios_base::fixed)
4241 {
4242 if (uppercase)
4243 *__fmtp = 'F';
4244 else
4245 *__fmtp = 'f';
4246 }
4247 else if (floatfield == ios_base::scientific)
4248 {
4249 if (uppercase)
4250 *__fmtp = 'E';
4251 else
4252 *__fmtp = 'e';
4253 }
4254 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4255 {
4256 if (uppercase)
4257 *__fmtp = 'A';
4258 else
4259 *__fmtp = 'a';
4260 }
4261 else
4262 {
4263 if (uppercase)
4264 *__fmtp = 'G';
4265 else
4266 *__fmtp = 'g';
4267 }
4268 return specify_precision;
4269}
4270
4271char*
4272__num_put_base::__identify_padding(char* __nb, char* __ne,
4273 const ios_base& __iob)
4274{
4275 switch (__iob.flags() & ios_base::adjustfield)
4276 {
4277 case ios_base::internal:
4278 if (__nb[0] == '-' || __nb[0] == '+')
4279 return __nb+1;
4280 if (__ne - __nb >= 2 && __nb[0] == '0'
4281 && (__nb[1] == 'x' || __nb[1] == 'X'))
4282 return __nb+2;
4283 break;
4284 case ios_base::left:
4285 return __ne;
4286 case ios_base::right:
4287 default:
4288 break;
4289 }
4290 return __nb;
4291}
4292
4293// time_get
4294
4295static
4296string*
4297init_weeks()
4298{
4299 static string weeks[14];
4300 weeks[0] = "Sunday";
4301 weeks[1] = "Monday";
4302 weeks[2] = "Tuesday";
4303 weeks[3] = "Wednesday";
4304 weeks[4] = "Thursday";
4305 weeks[5] = "Friday";
4306 weeks[6] = "Saturday";
4307 weeks[7] = "Sun";
4308 weeks[8] = "Mon";
4309 weeks[9] = "Tue";
4310 weeks[10] = "Wed";
4311 weeks[11] = "Thu";
4312 weeks[12] = "Fri";
4313 weeks[13] = "Sat";
4314 return weeks;
4315}
4316
4317static
4318wstring*
4319init_wweeks()
4320{
4321 static wstring weeks[14];
4322 weeks[0] = L"Sunday";
4323 weeks[1] = L"Monday";
4324 weeks[2] = L"Tuesday";
4325 weeks[3] = L"Wednesday";
4326 weeks[4] = L"Thursday";
4327 weeks[5] = L"Friday";
4328 weeks[6] = L"Saturday";
4329 weeks[7] = L"Sun";
4330 weeks[8] = L"Mon";
4331 weeks[9] = L"Tue";
4332 weeks[10] = L"Wed";
4333 weeks[11] = L"Thu";
4334 weeks[12] = L"Fri";
4335 weeks[13] = L"Sat";
4336 return weeks;
4337}
4338
4339template <>
4340const string*
4341__time_get_c_storage<char>::__weeks() const
4342{
4343 static const string* weeks = init_weeks();
4344 return weeks;
4345}
4346
4347template <>
4348const wstring*
4349__time_get_c_storage<wchar_t>::__weeks() const
4350{
4351 static const wstring* weeks = init_wweeks();
4352 return weeks;
4353}
4354
4355static
4356string*
4357init_months()
4358{
4359 static string months[24];
4360 months[0] = "January";
4361 months[1] = "February";
4362 months[2] = "March";
4363 months[3] = "April";
4364 months[4] = "May";
4365 months[5] = "June";
4366 months[6] = "July";
4367 months[7] = "August";
4368 months[8] = "September";
4369 months[9] = "October";
4370 months[10] = "November";
4371 months[11] = "December";
4372 months[12] = "Jan";
4373 months[13] = "Feb";
4374 months[14] = "Mar";
4375 months[15] = "Apr";
4376 months[16] = "May";
4377 months[17] = "Jun";
4378 months[18] = "Jul";
4379 months[19] = "Aug";
4380 months[20] = "Sep";
4381 months[21] = "Oct";
4382 months[22] = "Nov";
4383 months[23] = "Dec";
4384 return months;
4385}
4386
4387static
4388wstring*
4389init_wmonths()
4390{
4391 static wstring months[24];
4392 months[0] = L"January";
4393 months[1] = L"February";
4394 months[2] = L"March";
4395 months[3] = L"April";
4396 months[4] = L"May";
4397 months[5] = L"June";
4398 months[6] = L"July";
4399 months[7] = L"August";
4400 months[8] = L"September";
4401 months[9] = L"October";
4402 months[10] = L"November";
4403 months[11] = L"December";
4404 months[12] = L"Jan";
4405 months[13] = L"Feb";
4406 months[14] = L"Mar";
4407 months[15] = L"Apr";
4408 months[16] = L"May";
4409 months[17] = L"Jun";
4410 months[18] = L"Jul";
4411 months[19] = L"Aug";
4412 months[20] = L"Sep";
4413 months[21] = L"Oct";
4414 months[22] = L"Nov";
4415 months[23] = L"Dec";
4416 return months;
4417}
4418
4419template <>
4420const string*
4421__time_get_c_storage<char>::__months() const
4422{
4423 static const string* months = init_months();
4424 return months;
4425}
4426
4427template <>
4428const wstring*
4429__time_get_c_storage<wchar_t>::__months() const
4430{
4431 static const wstring* months = init_wmonths();
4432 return months;
4433}
4434
4435static
4436string*
4437init_am_pm()
4438{
4439 static string am_pm[24];
4440 am_pm[0] = "AM";
4441 am_pm[1] = "PM";
4442 return am_pm;
4443}
4444
4445static
4446wstring*
4447init_wam_pm()
4448{
4449 static wstring am_pm[24];
4450 am_pm[0] = L"AM";
4451 am_pm[1] = L"PM";
4452 return am_pm;
4453}
4454
4455template <>
4456const string*
4457__time_get_c_storage<char>::__am_pm() const
4458{
4459 static const string* am_pm = init_am_pm();
4460 return am_pm;
4461}
4462
4463template <>
4464const wstring*
4465__time_get_c_storage<wchar_t>::__am_pm() const
4466{
4467 static const wstring* am_pm = init_wam_pm();
4468 return am_pm;
4469}
4470
4471template <>
4472const string&
4473__time_get_c_storage<char>::__x() const
4474{
4475 static string s("%m/%d/%y");
4476 return s;
4477}
4478
4479template <>
4480const wstring&
4481__time_get_c_storage<wchar_t>::__x() const
4482{
4483 static wstring s(L"%m/%d/%y");
4484 return s;
4485}
4486
4487template <>
4488const string&
4489__time_get_c_storage<char>::__X() const
4490{
4491 static string s("%H:%M:%S");
4492 return s;
4493}
4494
4495template <>
4496const wstring&
4497__time_get_c_storage<wchar_t>::__X() const
4498{
4499 static wstring s(L"%H:%M:%S");
4500 return s;
4501}
4502
4503template <>
4504const string&
4505__time_get_c_storage<char>::__c() const
4506{
4507 static string s("%a %b %d %H:%M:%S %Y");
4508 return s;
4509}
4510
4511template <>
4512const wstring&
4513__time_get_c_storage<wchar_t>::__c() const
4514{
4515 static wstring s(L"%a %b %d %H:%M:%S %Y");
4516 return s;
4517}
4518
4519template <>
4520const string&
4521__time_get_c_storage<char>::__r() const
4522{
4523 static string s("%I:%M:%S %p");
4524 return s;
4525}
4526
4527template <>
4528const wstring&
4529__time_get_c_storage<wchar_t>::__r() const
4530{
4531 static wstring s(L"%I:%M:%S %p");
4532 return s;
4533}
4534
4535// time_get_byname
4536
4537__time_get::__time_get(const char* nm)
4538 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4539{
Howard Hinnant72f73582010-08-11 17:04:31 +00004540#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004541 if (__loc_ == 0)
4542 throw runtime_error("time_get_byname"
4543 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004544#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004545}
4546
4547__time_get::__time_get(const string& nm)
4548 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4549{
Howard Hinnant72f73582010-08-11 17:04:31 +00004550#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004551 if (__loc_ == 0)
4552 throw runtime_error("time_get_byname"
4553 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00004554#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004555}
4556
4557__time_get::~__time_get()
4558{
4559 freelocale(__loc_);
4560}
4561
4562template <>
4563string
4564__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4565{
4566 tm t;
4567 t.tm_sec = 59;
4568 t.tm_min = 55;
4569 t.tm_hour = 23;
4570 t.tm_mday = 31;
4571 t.tm_mon = 11;
4572 t.tm_year = 161;
4573 t.tm_wday = 6;
4574 t.tm_yday = 364;
4575 t.tm_isdst = -1;
4576 char buf[100];
4577 char f[3] = {0};
4578 f[0] = '%';
4579 f[1] = fmt;
4580 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4581 char* bb = buf;
4582 char* be = buf + n;
4583 string result;
4584 while (bb != be)
4585 {
4586 if (ct.is(ctype_base::space, *bb))
4587 {
4588 result.push_back(' ');
4589 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4590 ;
4591 continue;
4592 }
4593 char* w = bb;
4594 ios_base::iostate err = ios_base::goodbit;
4595 int i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4596 ct, err, false)
4597 - this->__weeks_;
4598 if (i < 14)
4599 {
4600 result.push_back('%');
4601 if (i < 7)
4602 result.push_back('A');
4603 else
4604 result.push_back('a');
4605 bb = w;
4606 continue;
4607 }
4608 w = bb;
4609 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4610 ct, err, false)
4611 - this->__months_;
4612 if (i < 24)
4613 {
4614 result.push_back('%');
4615 if (i < 12)
4616 result.push_back('B');
4617 else
4618 result.push_back('b');
4619 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4620 result.back() = 'm';
4621 bb = w;
4622 continue;
4623 }
4624 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4625 {
4626 w = bb;
4627 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4628 ct, err, false) - this->__am_pm_;
4629 if (i < 2)
4630 {
4631 result.push_back('%');
4632 result.push_back('p');
4633 bb = w;
4634 continue;
4635 }
4636 }
4637 w = bb;
4638 if (ct.is(ctype_base::digit, *bb))
4639 {
4640 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4641 {
4642 case 6:
4643 result.push_back('%');
4644 result.push_back('w');
4645 break;
4646 case 7:
4647 result.push_back('%');
4648 result.push_back('u');
4649 break;
4650 case 11:
4651 result.push_back('%');
4652 result.push_back('I');
4653 break;
4654 case 12:
4655 result.push_back('%');
4656 result.push_back('m');
4657 break;
4658 case 23:
4659 result.push_back('%');
4660 result.push_back('H');
4661 break;
4662 case 31:
4663 result.push_back('%');
4664 result.push_back('d');
4665 break;
4666 case 55:
4667 result.push_back('%');
4668 result.push_back('M');
4669 break;
4670 case 59:
4671 result.push_back('%');
4672 result.push_back('S');
4673 break;
4674 case 61:
4675 result.push_back('%');
4676 result.push_back('y');
4677 break;
4678 case 364:
4679 result.push_back('%');
4680 result.push_back('j');
4681 break;
4682 case 2061:
4683 result.push_back('%');
4684 result.push_back('Y');
4685 break;
4686 default:
4687 for (; w != bb; ++w)
4688 result.push_back(*w);
4689 break;
4690 }
4691 continue;
4692 }
4693 if (*bb == '%')
4694 {
4695 result.push_back('%');
4696 result.push_back('%');
4697 ++bb;
4698 continue;
4699 }
4700 result.push_back(*bb);
4701 ++bb;
4702 }
4703 return result;
4704}
4705
4706template <>
4707wstring
4708__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4709{
4710 tm t;
4711 t.tm_sec = 59;
4712 t.tm_min = 55;
4713 t.tm_hour = 23;
4714 t.tm_mday = 31;
4715 t.tm_mon = 11;
4716 t.tm_year = 161;
4717 t.tm_wday = 6;
4718 t.tm_yday = 364;
4719 t.tm_isdst = -1;
4720 char buf[100];
4721 char f[3] = {0};
4722 f[0] = '%';
4723 f[1] = fmt;
4724 size_t be = strftime_l(buf, 100, f, &t, __loc_);
4725 wchar_t wbuf[100];
4726 wchar_t* wbb = wbuf;
4727 mbstate_t mb = {0};
4728 const char* bb = buf;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004729 size_t i = with_locale::mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004730 if (i == -1)
4731 __throw_runtime_error("locale not supported");
4732 wchar_t* wbe = wbb + i;
4733 wstring result;
4734 while (wbb != wbe)
4735 {
4736 if (ct.is(ctype_base::space, *wbb))
4737 {
4738 result.push_back(L' ');
4739 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4740 ;
4741 continue;
4742 }
4743 wchar_t* w = wbb;
4744 ios_base::iostate err = ios_base::goodbit;
4745 int i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4746 ct, err, false)
4747 - this->__weeks_;
4748 if (i < 14)
4749 {
4750 result.push_back(L'%');
4751 if (i < 7)
4752 result.push_back(L'A');
4753 else
4754 result.push_back(L'a');
4755 wbb = w;
4756 continue;
4757 }
4758 w = wbb;
4759 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4760 ct, err, false)
4761 - this->__months_;
4762 if (i < 24)
4763 {
4764 result.push_back(L'%');
4765 if (i < 12)
4766 result.push_back(L'B');
4767 else
4768 result.push_back(L'b');
4769 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4770 result.back() = L'm';
4771 wbb = w;
4772 continue;
4773 }
4774 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4775 {
4776 w = wbb;
4777 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4778 ct, err, false) - this->__am_pm_;
4779 if (i < 2)
4780 {
4781 result.push_back(L'%');
4782 result.push_back(L'p');
4783 wbb = w;
4784 continue;
4785 }
4786 }
4787 w = wbb;
4788 if (ct.is(ctype_base::digit, *wbb))
4789 {
4790 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4791 {
4792 case 6:
4793 result.push_back(L'%');
4794 result.push_back(L'w');
4795 break;
4796 case 7:
4797 result.push_back(L'%');
4798 result.push_back(L'u');
4799 break;
4800 case 11:
4801 result.push_back(L'%');
4802 result.push_back(L'I');
4803 break;
4804 case 12:
4805 result.push_back(L'%');
4806 result.push_back(L'm');
4807 break;
4808 case 23:
4809 result.push_back(L'%');
4810 result.push_back(L'H');
4811 break;
4812 case 31:
4813 result.push_back(L'%');
4814 result.push_back(L'd');
4815 break;
4816 case 55:
4817 result.push_back(L'%');
4818 result.push_back(L'M');
4819 break;
4820 case 59:
4821 result.push_back(L'%');
4822 result.push_back(L'S');
4823 break;
4824 case 61:
4825 result.push_back(L'%');
4826 result.push_back(L'y');
4827 break;
4828 case 364:
4829 result.push_back(L'%');
4830 result.push_back(L'j');
4831 break;
4832 case 2061:
4833 result.push_back(L'%');
4834 result.push_back(L'Y');
4835 break;
4836 default:
4837 for (; w != wbb; ++w)
4838 result.push_back(*w);
4839 break;
4840 }
4841 continue;
4842 }
4843 if (ct.narrow(*wbb, 0) == '%')
4844 {
4845 result.push_back(L'%');
4846 result.push_back(L'%');
4847 ++wbb;
4848 continue;
4849 }
4850 result.push_back(*wbb);
4851 ++wbb;
4852 }
4853 return result;
4854}
4855
4856template <>
4857void
4858__time_get_storage<char>::init(const ctype<char>& ct)
4859{
4860 tm t;
4861 char buf[100];
4862 // __weeks_
4863 for (int i = 0; i < 7; ++i)
4864 {
4865 t.tm_wday = i;
4866 strftime_l(buf, 100, "%A", &t, __loc_);
4867 __weeks_[i] = buf;
4868 strftime_l(buf, 100, "%a", &t, __loc_);
4869 __weeks_[i+7] = buf;
4870 }
4871 // __months_
4872 for (int i = 0; i < 12; ++i)
4873 {
4874 t.tm_mon = i;
4875 strftime_l(buf, 100, "%B", &t, __loc_);
4876 __months_[i] = buf;
4877 strftime_l(buf, 100, "%b", &t, __loc_);
4878 __months_[i+12] = buf;
4879 }
4880 // __am_pm_
4881 t.tm_hour = 1;
4882 strftime_l(buf, 100, "%p", &t, __loc_);
4883 __am_pm_[0] = buf;
4884 t.tm_hour = 13;
4885 strftime_l(buf, 100, "%p", &t, __loc_);
4886 __am_pm_[1] = buf;
4887 __c_ = __analyze('c', ct);
4888 __r_ = __analyze('r', ct);
4889 __x_ = __analyze('x', ct);
4890 __X_ = __analyze('X', ct);
4891}
4892
4893template <>
4894void
4895__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4896{
4897 tm t = {0};
4898 char buf[100];
4899 size_t be;
4900 wchar_t wbuf[100];
4901 wchar_t* wbe;
4902 mbstate_t mb = {0};
4903 // __weeks_
4904 for (int i = 0; i < 7; ++i)
4905 {
4906 t.tm_wday = i;
4907 be = strftime_l(buf, 100, "%A", &t, __loc_);
4908 mb = mbstate_t();
4909 const char* bb = buf;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004910 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004911 if (j == -1)
4912 __throw_runtime_error("locale not supported");
4913 wbe = wbuf + j;
4914 __weeks_[i].assign(wbuf, wbe);
4915 be = strftime_l(buf, 100, "%a", &t, __loc_);
4916 mb = mbstate_t();
4917 bb = buf;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004918 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004919 if (j == -1)
4920 __throw_runtime_error("locale not supported");
4921 wbe = wbuf + j;
4922 __weeks_[i+7].assign(wbuf, wbe);
4923 }
4924 // __months_
4925 for (int i = 0; i < 12; ++i)
4926 {
4927 t.tm_mon = i;
4928 be = strftime_l(buf, 100, "%B", &t, __loc_);
4929 mb = mbstate_t();
4930 const char* bb = buf;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004931 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004932 if (j == -1)
4933 __throw_runtime_error("locale not supported");
4934 wbe = wbuf + j;
4935 __months_[i].assign(wbuf, wbe);
4936 be = strftime_l(buf, 100, "%b", &t, __loc_);
4937 mb = mbstate_t();
4938 bb = buf;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004939 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004940 if (j == -1)
4941 __throw_runtime_error("locale not supported");
4942 wbe = wbuf + j;
4943 __months_[i+12].assign(wbuf, wbe);
4944 }
4945 // __am_pm_
4946 t.tm_hour = 1;
4947 be = strftime_l(buf, 100, "%p", &t, __loc_);
4948 mb = mbstate_t();
4949 const char* bb = buf;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004950 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004951 if (j == -1)
4952 __throw_runtime_error("locale not supported");
4953 wbe = wbuf + j;
4954 __am_pm_[0].assign(wbuf, wbe);
4955 t.tm_hour = 13;
4956 be = strftime_l(buf, 100, "%p", &t, __loc_);
4957 mb = mbstate_t();
4958 bb = buf;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00004959 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004960 if (j == -1)
4961 __throw_runtime_error("locale not supported");
4962 wbe = wbuf + j;
4963 __am_pm_[1].assign(wbuf, wbe);
4964 __c_ = __analyze('c', ct);
4965 __r_ = __analyze('r', ct);
4966 __x_ = __analyze('x', ct);
4967 __X_ = __analyze('X', ct);
4968}
4969
4970template <class CharT>
4971struct _LIBCPP_HIDDEN __time_get_temp
4972 : public ctype_byname<CharT>
4973{
4974 explicit __time_get_temp(const char* nm)
4975 : ctype_byname<CharT>(nm, 1) {}
4976 explicit __time_get_temp(const string& nm)
4977 : ctype_byname<CharT>(nm, 1) {}
4978};
4979
4980template <>
4981__time_get_storage<char>::__time_get_storage(const char* __nm)
4982 : __time_get(__nm)
4983{
4984 const __time_get_temp<char> ct(__nm);
4985 init(ct);
4986}
4987
4988template <>
4989__time_get_storage<char>::__time_get_storage(const string& __nm)
4990 : __time_get(__nm)
4991{
4992 const __time_get_temp<char> ct(__nm);
4993 init(ct);
4994}
4995
4996template <>
4997__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
4998 : __time_get(__nm)
4999{
5000 const __time_get_temp<wchar_t> ct(__nm);
5001 init(ct);
5002}
5003
5004template <>
5005__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5006 : __time_get(__nm)
5007{
5008 const __time_get_temp<wchar_t> ct(__nm);
5009 init(ct);
5010}
5011
5012template <>
5013time_base::dateorder
5014__time_get_storage<char>::__do_date_order() const
5015{
5016 unsigned i;
5017 for (i = 0; i < __x_.size(); ++i)
5018 if (__x_[i] == '%')
5019 break;
5020 ++i;
5021 switch (__x_[i])
5022 {
5023 case 'y':
5024 case 'Y':
5025 for (++i; i < __x_.size(); ++i)
5026 if (__x_[i] == '%')
5027 break;
5028 if (i == __x_.size())
5029 break;
5030 ++i;
5031 switch (__x_[i])
5032 {
5033 case 'm':
5034 for (++i; i < __x_.size(); ++i)
5035 if (__x_[i] == '%')
5036 break;
5037 if (i == __x_.size())
5038 break;
5039 ++i;
5040 if (__x_[i] == 'd')
5041 return time_base::ymd;
5042 break;
5043 case 'd':
5044 for (++i; i < __x_.size(); ++i)
5045 if (__x_[i] == '%')
5046 break;
5047 if (i == __x_.size())
5048 break;
5049 ++i;
5050 if (__x_[i] == 'm')
5051 return time_base::ydm;
5052 break;
5053 }
5054 break;
5055 case 'm':
5056 for (++i; i < __x_.size(); ++i)
5057 if (__x_[i] == '%')
5058 break;
5059 if (i == __x_.size())
5060 break;
5061 ++i;
5062 if (__x_[i] == 'd')
5063 {
5064 for (++i; i < __x_.size(); ++i)
5065 if (__x_[i] == '%')
5066 break;
5067 if (i == __x_.size())
5068 break;
5069 ++i;
5070 if (__x_[i] == 'y' || __x_[i] == 'Y')
5071 return time_base::mdy;
5072 break;
5073 }
5074 break;
5075 case 'd':
5076 for (++i; i < __x_.size(); ++i)
5077 if (__x_[i] == '%')
5078 break;
5079 if (i == __x_.size())
5080 break;
5081 ++i;
5082 if (__x_[i] == 'm')
5083 {
5084 for (++i; i < __x_.size(); ++i)
5085 if (__x_[i] == '%')
5086 break;
5087 if (i == __x_.size())
5088 break;
5089 ++i;
5090 if (__x_[i] == 'y' || __x_[i] == 'Y')
5091 return time_base::dmy;
5092 break;
5093 }
5094 break;
5095 }
5096 return time_base::no_order;
5097}
5098
5099template <>
5100time_base::dateorder
5101__time_get_storage<wchar_t>::__do_date_order() const
5102{
5103 unsigned i;
5104 for (i = 0; i < __x_.size(); ++i)
5105 if (__x_[i] == L'%')
5106 break;
5107 ++i;
5108 switch (__x_[i])
5109 {
5110 case L'y':
5111 case L'Y':
5112 for (++i; i < __x_.size(); ++i)
5113 if (__x_[i] == L'%')
5114 break;
5115 if (i == __x_.size())
5116 break;
5117 ++i;
5118 switch (__x_[i])
5119 {
5120 case L'm':
5121 for (++i; i < __x_.size(); ++i)
5122 if (__x_[i] == L'%')
5123 break;
5124 if (i == __x_.size())
5125 break;
5126 ++i;
5127 if (__x_[i] == L'd')
5128 return time_base::ymd;
5129 break;
5130 case L'd':
5131 for (++i; i < __x_.size(); ++i)
5132 if (__x_[i] == L'%')
5133 break;
5134 if (i == __x_.size())
5135 break;
5136 ++i;
5137 if (__x_[i] == L'm')
5138 return time_base::ydm;
5139 break;
5140 }
5141 break;
5142 case L'm':
5143 for (++i; i < __x_.size(); ++i)
5144 if (__x_[i] == L'%')
5145 break;
5146 if (i == __x_.size())
5147 break;
5148 ++i;
5149 if (__x_[i] == L'd')
5150 {
5151 for (++i; i < __x_.size(); ++i)
5152 if (__x_[i] == L'%')
5153 break;
5154 if (i == __x_.size())
5155 break;
5156 ++i;
5157 if (__x_[i] == L'y' || __x_[i] == L'Y')
5158 return time_base::mdy;
5159 break;
5160 }
5161 break;
5162 case L'd':
5163 for (++i; i < __x_.size(); ++i)
5164 if (__x_[i] == L'%')
5165 break;
5166 if (i == __x_.size())
5167 break;
5168 ++i;
5169 if (__x_[i] == L'm')
5170 {
5171 for (++i; i < __x_.size(); ++i)
5172 if (__x_[i] == L'%')
5173 break;
5174 if (i == __x_.size())
5175 break;
5176 ++i;
5177 if (__x_[i] == L'y' || __x_[i] == L'Y')
5178 return time_base::dmy;
5179 break;
5180 }
5181 break;
5182 }
5183 return time_base::no_order;
5184}
5185
5186// time_put
5187
5188__time_put::__time_put(const char* nm)
5189 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5190{
Howard Hinnant72f73582010-08-11 17:04:31 +00005191#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005192 if (__loc_ == 0)
5193 throw runtime_error("time_put_byname"
5194 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005195#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005196}
5197
5198__time_put::__time_put(const string& nm)
5199 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5200{
Howard Hinnant72f73582010-08-11 17:04:31 +00005201#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005202 if (__loc_ == 0)
5203 throw runtime_error("time_put_byname"
5204 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00005205#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005206}
5207
5208__time_put::~__time_put()
5209{
5210 if (__loc_)
5211 freelocale(__loc_);
5212}
5213
5214void
5215__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5216 char __fmt, char __mod) const
5217{
5218 char fmt[] = {'%', __fmt, __mod, 0};
5219 if (__mod != 0)
5220 swap(fmt[1], fmt[2]);
5221 size_t n = strftime_l(__nb, __ne-__nb, fmt, __tm, __loc_);
5222 __ne = __nb + n;
5223}
5224
5225void
5226__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5227 char __fmt, char __mod) const
5228{
5229 char __nar[100];
5230 char* __ne = __nar + 100;
5231 __do_put(__nar, __ne, __tm, __fmt, __mod);
5232 mbstate_t mb = {0};
5233 const char* __nb = __nar;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005234 size_t j = with_locale::mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005235 if (j == -1)
5236 __throw_runtime_error("locale not supported");
5237 __we = __wb + j;
5238}
5239
5240// moneypunct_byname
5241
5242static
5243void
5244__init_pat(money_base::pattern& pat, char cs_precedes, char sep_by_space, char sign_posn)
5245{
5246 const char sign = static_cast<char>(money_base::sign);
5247 const char space = static_cast<char>(money_base::space);
5248 const char none = static_cast<char>(money_base::none);
5249 const char symbol = static_cast<char>(money_base::symbol);
5250 const char value = static_cast<char>(money_base::value);
5251 switch (cs_precedes)
5252 {
5253 case 0:
5254 switch (sign_posn)
5255 {
5256 case 0:
5257 pat.field[0] = sign;
5258 pat.field[1] = value;
5259 pat.field[3] = symbol;
5260 switch (sep_by_space)
5261 {
5262 case 0:
5263 pat.field[2] = none;
5264 return;
5265 case 1:
5266 case 2:
5267 pat.field[2] = space;
5268 return;
5269 default:
5270 break;
5271 }
5272 break;
5273 case 1:
5274 pat.field[0] = sign;
5275 pat.field[3] = symbol;
5276 switch (sep_by_space)
5277 {
5278 case 0:
5279 pat.field[1] = value;
5280 pat.field[2] = none;
5281 return;
5282 case 1:
5283 pat.field[1] = value;
5284 pat.field[2] = space;
5285 return;
5286 case 2:
5287 pat.field[1] = space;
5288 pat.field[2] = value;
5289 return;
5290 default:
5291 break;
5292 }
5293 break;
5294 case 2:
5295 pat.field[0] = value;
5296 pat.field[3] = sign;
5297 switch (sep_by_space)
5298 {
5299 case 0:
5300 pat.field[1] = none;
5301 pat.field[2] = symbol;
5302 return;
5303 case 1:
5304 pat.field[1] = space;
5305 pat.field[2] = symbol;
5306 return;
5307 case 2:
5308 pat.field[1] = symbol;
5309 pat.field[2] = space;
5310 return;
5311 default:
5312 break;
5313 }
5314 break;
5315 case 3:
5316 pat.field[0] = value;
5317 pat.field[3] = symbol;
5318 switch (sep_by_space)
5319 {
5320 case 0:
5321 pat.field[1] = none;
5322 pat.field[2] = sign;
5323 return;
5324 case 1:
5325 pat.field[1] = space;
5326 pat.field[2] = sign;
5327 return;
5328 case 2:
5329 pat.field[1] = sign;
5330 pat.field[2] = space;
5331 return;
5332 default:
5333 break;
5334 }
5335 break;
5336 case 4:
5337 pat.field[0] = value;
5338 pat.field[3] = sign;
5339 switch (sep_by_space)
5340 {
5341 case 0:
5342 pat.field[1] = none;
5343 pat.field[2] = symbol;
5344 return;
5345 case 1:
5346 pat.field[1] = space;
5347 pat.field[2] = symbol;
5348 return;
5349 case 2:
5350 pat.field[1] = symbol;
5351 pat.field[2] = space;
5352 return;
5353 default:
5354 break;
5355 }
5356 break;
5357 default:
5358 break;
5359 }
5360 break;
5361 case 1:
5362 switch (sign_posn)
5363 {
5364 case 0:
5365 pat.field[0] = sign;
5366 pat.field[1] = symbol;
5367 pat.field[3] = value;
5368 switch (sep_by_space)
5369 {
5370 case 0:
5371 pat.field[2] = none;
5372 return;
5373 case 1:
5374 case 2:
5375 pat.field[2] = space;
5376 return;
5377 default:
5378 break;
5379 }
5380 break;
5381 case 1:
5382 pat.field[0] = sign;
5383 pat.field[3] = value;
5384 switch (sep_by_space)
5385 {
5386 case 0:
5387 pat.field[1] = symbol;
5388 pat.field[2] = none;
5389 return;
5390 case 1:
5391 pat.field[1] = symbol;
5392 pat.field[2] = space;
5393 return;
5394 case 2:
5395 pat.field[1] = space;
5396 pat.field[2] = symbol;
5397 return;
5398 default:
5399 break;
5400 }
5401 break;
5402 case 2:
5403 pat.field[0] = symbol;
5404 pat.field[3] = sign;
5405 switch (sep_by_space)
5406 {
5407 case 0:
5408 pat.field[1] = none;
5409 pat.field[2] = value;
5410 return;
5411 case 1:
5412 pat.field[1] = space;
5413 pat.field[2] = value;
5414 return;
5415 case 2:
5416 pat.field[1] = value;
5417 pat.field[2] = space;
5418 return;
5419 default:
5420 break;
5421 }
5422 break;
5423 case 3:
5424 pat.field[0] = sign;
5425 pat.field[3] = value;
5426 switch (sep_by_space)
5427 {
5428 case 0:
5429 pat.field[1] = symbol;
5430 pat.field[2] = none;
5431 return;
5432 case 1:
5433 pat.field[1] = symbol;
5434 pat.field[2] = space;
5435 return;
5436 case 2:
5437 pat.field[1] = space;
5438 pat.field[2] = symbol;
5439 return;
5440 default:
5441 break;
5442 }
5443 break;
5444 case 4:
5445 pat.field[0] = symbol;
5446 pat.field[3] = value;
5447 switch (sep_by_space)
5448 {
5449 case 0:
5450 pat.field[1] = sign;
5451 pat.field[2] = none;
5452 return;
5453 case 1:
5454 pat.field[1] = sign;
5455 pat.field[2] = space;
5456 return;
5457 case 2:
5458 pat.field[1] = space;
5459 pat.field[2] = sign;
5460 return;
5461 default:
5462 break;
5463 }
5464 break;
5465 default:
5466 break;
5467 }
5468 break;
5469 default:
5470 break;
5471 }
5472 pat.field[0] = symbol;
5473 pat.field[1] = sign;
5474 pat.field[2] = none;
5475 pat.field[3] = value;
5476}
5477
5478template<>
5479void
5480moneypunct_byname<char, false>::init(const char* nm)
5481{
5482 typedef moneypunct<char, false> base;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005483 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005484#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005485 if (loc == 0)
5486 throw runtime_error("moneypunct_byname"
5487 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005488#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005489 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005490 if (*lc->mon_decimal_point)
5491 __decimal_point_ = *lc->mon_decimal_point;
5492 else
5493 __decimal_point_ = base::do_decimal_point();
5494 if (*lc->mon_thousands_sep)
5495 __thousands_sep_ = *lc->mon_thousands_sep;
5496 else
5497 __thousands_sep_ = base::do_thousands_sep();
5498 __grouping_ = lc->mon_grouping;
5499 __curr_symbol_ = lc->currency_symbol;
5500 if (lc->frac_digits != CHAR_MAX)
5501 __frac_digits_ = lc->frac_digits;
5502 else
5503 __frac_digits_ = base::do_frac_digits();
5504 if (lc->p_sign_posn == 0)
5505 __positive_sign_ = "()";
5506 else
5507 __positive_sign_ = lc->positive_sign;
5508 if (lc->n_sign_posn == 0)
5509 __negative_sign_ = "()";
5510 else
5511 __negative_sign_ = lc->negative_sign;
5512 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5513 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5514}
5515
5516template<>
5517void
5518moneypunct_byname<char, true>::init(const char* nm)
5519{
5520 typedef moneypunct<char, true> base;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005521 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005522#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005523 if (loc == 0)
5524 throw runtime_error("moneypunct_byname"
5525 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005526#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005527 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005528 if (*lc->mon_decimal_point)
5529 __decimal_point_ = *lc->mon_decimal_point;
5530 else
5531 __decimal_point_ = base::do_decimal_point();
5532 if (*lc->mon_thousands_sep)
5533 __thousands_sep_ = *lc->mon_thousands_sep;
5534 else
5535 __thousands_sep_ = base::do_thousands_sep();
5536 __grouping_ = lc->mon_grouping;
5537 __curr_symbol_ = lc->int_curr_symbol;
5538 if (lc->int_frac_digits != CHAR_MAX)
5539 __frac_digits_ = lc->int_frac_digits;
5540 else
5541 __frac_digits_ = base::do_frac_digits();
5542 if (lc->int_p_sign_posn == 0)
5543 __positive_sign_ = "()";
5544 else
5545 __positive_sign_ = lc->positive_sign;
5546 if (lc->int_n_sign_posn == 0)
5547 __negative_sign_ = "()";
5548 else
5549 __negative_sign_ = lc->negative_sign;
5550 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5551 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
5552}
5553
5554template<>
5555void
5556moneypunct_byname<wchar_t, false>::init(const char* nm)
5557{
5558 typedef moneypunct<wchar_t, false> base;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005559 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005560#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005561 if (loc == 0)
5562 throw runtime_error("moneypunct_byname"
5563 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005564#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005565 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005566 if (*lc->mon_decimal_point)
5567 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5568 else
5569 __decimal_point_ = base::do_decimal_point();
5570 if (*lc->mon_thousands_sep)
5571 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5572 else
5573 __thousands_sep_ = base::do_thousands_sep();
5574 __grouping_ = lc->mon_grouping;
5575 wchar_t wbuf[100];
5576 mbstate_t mb = {0};
5577 const char* bb = lc->currency_symbol;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005578 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005579 if (j == -1)
5580 __throw_runtime_error("locale not supported");
5581 wchar_t* wbe = wbuf + j;
5582 __curr_symbol_.assign(wbuf, wbe);
5583 if (lc->frac_digits != CHAR_MAX)
5584 __frac_digits_ = lc->frac_digits;
5585 else
5586 __frac_digits_ = base::do_frac_digits();
5587 if (lc->p_sign_posn == 0)
5588 __positive_sign_ = L"()";
5589 else
5590 {
5591 mb = mbstate_t();
5592 bb = lc->positive_sign;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005593 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005594 if (j == -1)
5595 __throw_runtime_error("locale not supported");
5596 wbe = wbuf + j;
5597 __positive_sign_.assign(wbuf, wbe);
5598 }
5599 if (lc->n_sign_posn == 0)
5600 __negative_sign_ = L"()";
5601 else
5602 {
5603 mb = mbstate_t();
5604 bb = lc->negative_sign;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005605 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005606 if (j == -1)
5607 __throw_runtime_error("locale not supported");
5608 wbe = wbuf + j;
5609 __negative_sign_.assign(wbuf, wbe);
5610 }
5611 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5612 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5613}
5614
5615template<>
5616void
5617moneypunct_byname<wchar_t, true>::init(const char* nm)
5618{
5619 typedef moneypunct<wchar_t, true> base;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005620 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005621#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005622 if (loc == 0)
5623 throw runtime_error("moneypunct_byname"
5624 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005625#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005626 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005627 if (*lc->mon_decimal_point)
5628 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5629 else
5630 __decimal_point_ = base::do_decimal_point();
5631 if (*lc->mon_thousands_sep)
5632 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5633 else
5634 __thousands_sep_ = base::do_thousands_sep();
5635 __grouping_ = lc->mon_grouping;
5636 wchar_t wbuf[100];
5637 mbstate_t mb = {0};
5638 const char* bb = lc->int_curr_symbol;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005639 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005640 if (j == -1)
5641 __throw_runtime_error("locale not supported");
5642 wchar_t* wbe = wbuf + j;
5643 __curr_symbol_.assign(wbuf, wbe);
5644 if (lc->int_frac_digits != CHAR_MAX)
5645 __frac_digits_ = lc->int_frac_digits;
5646 else
5647 __frac_digits_ = base::do_frac_digits();
5648 if (lc->int_p_sign_posn == 0)
5649 __positive_sign_ = L"()";
5650 else
5651 {
5652 mb = mbstate_t();
5653 bb = lc->positive_sign;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005654 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005655 if (j == -1)
5656 __throw_runtime_error("locale not supported");
5657 wbe = wbuf + j;
5658 __positive_sign_.assign(wbuf, wbe);
5659 }
5660 if (lc->int_n_sign_posn == 0)
5661 __negative_sign_ = L"()";
5662 else
5663 {
5664 mb = mbstate_t();
5665 bb = lc->negative_sign;
Howard Hinnantbf6c0b42011-06-30 14:21:55 +00005666 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005667 if (j == -1)
5668 __throw_runtime_error("locale not supported");
5669 wbe = wbuf + j;
5670 __negative_sign_.assign(wbuf, wbe);
5671 }
5672 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5673 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
5674}
5675
5676void __do_nothing(void*) {}
5677
5678void __throw_runtime_error(const char* msg)
5679{
Howard Hinnant72f73582010-08-11 17:04:31 +00005680#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005681 throw runtime_error(msg);
Howard Hinnant72f73582010-08-11 17:04:31 +00005682#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005683}
5684
5685template class collate<char>;
5686template class collate<wchar_t>;
5687
5688template class num_get<char>;
5689template class num_get<wchar_t>;
5690
5691template class __num_get<char>;
5692template class __num_get<wchar_t>;
5693
5694template class num_put<char>;
5695template class num_put<wchar_t>;
5696
5697template class __num_put<char>;
5698template class __num_put<wchar_t>;
5699
5700template class time_get<char>;
5701template class time_get<wchar_t>;
5702
5703template class time_get_byname<char>;
5704template class time_get_byname<wchar_t>;
5705
5706template class time_put<char>;
5707template class time_put<wchar_t>;
5708
5709template class time_put_byname<char>;
5710template class time_put_byname<wchar_t>;
5711
5712template class moneypunct<char, false>;
5713template class moneypunct<char, true>;
5714template class moneypunct<wchar_t, false>;
5715template class moneypunct<wchar_t, true>;
5716
5717template class moneypunct_byname<char, false>;
5718template class moneypunct_byname<char, true>;
5719template class moneypunct_byname<wchar_t, false>;
5720template class moneypunct_byname<wchar_t, true>;
5721
5722template class money_get<char>;
5723template class money_get<wchar_t>;
5724
5725template class __money_get<char>;
5726template class __money_get<wchar_t>;
5727
5728template class money_put<char>;
5729template class money_put<wchar_t>;
5730
5731template class __money_put<char>;
5732template class __money_put<wchar_t>;
5733
5734template class messages<char>;
5735template class messages<wchar_t>;
5736
5737template class messages_byname<char>;
5738template class messages_byname<wchar_t>;
5739
5740template class codecvt_byname<char, char, mbstate_t>;
5741template class codecvt_byname<wchar_t, char, mbstate_t>;
5742template class codecvt_byname<char16_t, char, mbstate_t>;
5743template class codecvt_byname<char32_t, char, mbstate_t>;
5744
5745template class __vector_base_common<true>;
5746
5747_LIBCPP_END_NAMESPACE_STD