blob: 63f54294a466320723d0ebef535f5892317e2d2f [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
10#include "string"
11#include "locale"
Howard Hinnant87d1a8a2010-05-30 21:39:41 +000012#include "codecvt"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000013#include "vector"
14#include "algorithm"
15#include "algorithm"
16#include "typeinfo"
Howard Hinnantd318d492011-06-30 14:21:55 +000017#include "type_traits"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000018#include "clocale"
19#include "cstring"
20#include "cwctype"
21#include "__sso_allocator"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000022#include <langinfo.h>
23#include <stdlib.h>
24
Howard Hinnantd318d492011-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 Hinnant0949eed2011-06-30 21:18:19 +000044 decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnantd318d492011-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000117_LIBCPP_BEGIN_NAMESPACE_STD
118
Sean Hunte59f7242011-07-09 01:09:31 +0000119#ifndef _LIBCPP_APPLE_STABLE_ABI
Sean Hunt62a6ac32011-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}
Sean Hunte59f7242011-07-09 01:09:31 +0000131#endif // _LIBCPP_APPLE_STABLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000132
Howard Hinnantbc8d3f92010-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 Hinnant0949eed2011-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 Hinnantbc8d3f92010-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 Hinnant0949eed2011-06-30 21:18:19 +0000231 install(&make<_VSTD::messages<char> >(1));
232 install(&make<_VSTD::messages<wchar_t> >(1));
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000240#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000241 try
242 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000243#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000268#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000277#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000298#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000299 try
300 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000301#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000340#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000349#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000369#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000370 try
371 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000372#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000373 if (c & locale::collate)
374 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000375 install_from<_VSTD::collate<char> >(one);
376 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000377 }
378 if (c & locale::ctype)
379 {
Howard Hinnant0949eed2011-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 Hinnantbc8d3f92010-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 Hinnant0949eed2011-06-30 21:18:19 +0000416 install_from<_VSTD::messages<char> >(one);
417 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000418 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000419#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000428#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000466#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000467 if (!has_facet(id))
468 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000469#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantc9834542011-05-31 15:34:58 +0000509locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000510 : __locale_(__global().__locale_)
511{
512 __locale_->__add_shared();
513}
514
Howard Hinnantc9834542011-05-31 15:34:58 +0000515locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000516 : __locale_(l.__locale_)
517{
518 __locale_->__add_shared();
519}
520
Howard Hinnantc9834542011-05-31 15:34:58 +0000521locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000522{
523 __locale_->__release_shared();
524}
525
526const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000527locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000536#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000537 : __locale_(name ? new __imp(name)
538 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000539#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000540 : __locale_(new __imp(name))
541#endif
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000553#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000554 : __locale_(name ? new __imp(*other.__locale_, name, c)
555 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000556#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000557 : __locale_(new __imp(*other.__locale_, name, c))
558#endif
Howard Hinnantbc8d3f92010-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 Hinnant1694d232011-05-28 14:41:13 +0000628locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnantadff4892010-05-24 17:49:41 +0000666 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000675#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000679#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000686#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000690#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000727#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000731#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000738#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000742#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000784 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-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)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000791 *vec = static_cast<mask>(isascii(*low) ?
792 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-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)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000800 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-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)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000809 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000810 break;
811 return low;
812}
813
814wchar_t
815ctype<wchar_t>::do_toupper(char_type c) const
816{
Sean Hunte59f7242011-07-09 01:09:31 +0000817#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000818 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000819#else
820 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
821#endif
Howard Hinnantbc8d3f92010-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)
Sean Hunte59f7242011-07-09 01:09:31 +0000828#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000829 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
830 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000831#else
832 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
833#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000834 return low;
835}
836
837wchar_t
838ctype<wchar_t>::do_tolower(char_type c) const
839{
Sean Hunte59f7242011-07-09 01:09:31 +0000840#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000841 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000842#else
843 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
844#endif
Howard Hinnantbc8d3f92010-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)
Sean Hunte59f7242011-07-09 01:09:31 +0000851#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000852 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
853 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000854#else
855 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
856#endif
Howard Hinnantbc8d3f92010-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{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000902 if (__tab_ == 0)
903 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-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{
Sean Hunte59f7242011-07-09 01:09:31 +0000915#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000916 return isascii(c) ? __classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000917#else
918 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
919#endif
Howard Hinnantbc8d3f92010-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)
Sean Hunte59f7242011-07-09 01:09:31 +0000926#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000927 *low = isascii(*low) ? __classic_upper_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000928#else
929 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[c] : c;
930#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000931 return low;
932}
933
934char
935ctype<char>::do_tolower(char_type c) const
936{
Sean Hunte59f7242011-07-09 01:09:31 +0000937#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000938 return isascii(c) ? __classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000939#else
940 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
941#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000942}
943
944const char*
945ctype<char>::do_tolower(char_type* low, const char_type* high) const
946{
947 for (; low != high; ++low)
Sean Hunte59f7242011-07-09 01:09:31 +0000948#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000949 *low = isascii(*low) ? __classic_lower_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000950#else
951 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[c] : c;
952#endif
Howard Hinnantbc8d3f92010-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 Hinnantc9834542011-05-31 15:34:58 +0000990ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000991{
Michael J. Spencer626916f2010-12-10 19:47:54 +0000992#ifdef __APPLE__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000993 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-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
Sean Hunte59f7242011-07-09 01:09:31 +00001002#ifndef _LIBCPP_APPLE_STABLE_ABI
Sean Hunt62a6ac32011-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. Spencer626916f2010-12-10 19:47:54 +00001022#else
1023 return NULL;
1024#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025}
Sean Hunte59f7242011-07-09 01:09:31 +00001026#endif // _LIBCPP_APPLE_STABLE_ABI
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +00001034#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +00001038#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +00001045#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +00001049#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +00001091#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +00001095#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +00001102#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +00001106#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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{
1117 return static_cast<bool>(iswctype_l(c, m, __l));
1118}
1119
1120const wchar_t*
1121ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1122{
1123 for (; low != high; ++low, ++vec)
1124 {
1125 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001126 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001127 else
1128 {
1129 *vec = 0;
1130 if (iswspace_l(*low, __l))
1131 *vec |= space;
1132 if (iswprint_l(*low, __l))
1133 *vec |= print;
1134 if (iswcntrl_l(*low, __l))
1135 *vec |= cntrl;
1136 if (iswupper_l(*low, __l))
1137 *vec |= upper;
1138 if (iswlower_l(*low, __l))
1139 *vec |= lower;
1140 if (iswalpha_l(*low, __l))
1141 *vec |= alpha;
1142 if (iswdigit_l(*low, __l))
1143 *vec |= digit;
1144 if (iswpunct_l(*low, __l))
1145 *vec |= punct;
1146 if (iswxdigit_l(*low, __l))
1147 *vec |= xdigit;
1148 }
1149 }
1150 return low;
1151}
1152
1153const wchar_t*
1154ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1155{
1156 for (; low != high; ++low)
1157 if (iswctype_l(*low, m, __l))
1158 break;
1159 return low;
1160}
1161
1162const wchar_t*
1163ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1164{
1165 for (; low != high; ++low)
1166 if (!iswctype_l(*low, m, __l))
1167 break;
1168 return low;
1169}
1170
1171wchar_t
1172ctype_byname<wchar_t>::do_toupper(char_type c) const
1173{
1174 return towupper_l(c, __l);
1175}
1176
1177const wchar_t*
1178ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1179{
1180 for (; low != high; ++low)
1181 *low = towupper_l(*low, __l);
1182 return low;
1183}
1184
1185wchar_t
1186ctype_byname<wchar_t>::do_tolower(char_type c) const
1187{
1188 return towlower_l(c, __l);
1189}
1190
1191const wchar_t*
1192ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1193{
1194 for (; low != high; ++low)
1195 *low = towlower_l(*low, __l);
1196 return low;
1197}
1198
1199wchar_t
1200ctype_byname<wchar_t>::do_widen(char c) const
1201{
Howard Hinnantd318d492011-06-30 14:21:55 +00001202 return with_locale::btowc_l(c, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001203}
1204
1205const char*
1206ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1207{
1208 for (; low != high; ++low, ++dest)
Howard Hinnantd318d492011-06-30 14:21:55 +00001209 *dest = with_locale::btowc_l(*low, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001210 return low;
1211}
1212
1213char
1214ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1215{
Howard Hinnantd318d492011-06-30 14:21:55 +00001216 int r = with_locale::wctob_l(c, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001217 return r != WEOF ? static_cast<char>(r) : dfault;
1218}
1219
1220const wchar_t*
1221ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1222{
1223 for (; low != high; ++low, ++dest)
1224 {
Howard Hinnantd318d492011-06-30 14:21:55 +00001225 int r = with_locale::wctob_l(*low, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001226 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1227 }
1228 return low;
1229}
1230
1231// template <> class codecvt<char, char, mbstate_t>
1232
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001233locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001234
1235codecvt<char, char, mbstate_t>::~codecvt()
1236{
1237}
1238
1239codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001240codecvt<char, char, mbstate_t>::do_out(state_type&,
1241 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001242 extern_type* to, extern_type*, extern_type*& to_nxt) const
1243{
1244 frm_nxt = frm;
1245 to_nxt = to;
1246 return noconv;
1247}
1248
1249codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001250codecvt<char, char, mbstate_t>::do_in(state_type&,
1251 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001252 intern_type* to, intern_type*, intern_type*& to_nxt) const
1253{
1254 frm_nxt = frm;
1255 to_nxt = to;
1256 return noconv;
1257}
1258
1259codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001260codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001261 extern_type* to, extern_type*, extern_type*& to_nxt) const
1262{
1263 to_nxt = to;
1264 return noconv;
1265}
1266
1267int
Howard Hinnantc9834542011-05-31 15:34:58 +00001268codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001269{
1270 return 1;
1271}
1272
1273bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001274codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001275{
1276 return true;
1277}
1278
1279int
1280codecvt<char, char, mbstate_t>::do_length(state_type&,
1281 const extern_type* frm, const extern_type* end, size_t mx) const
1282{
1283 return static_cast<int>(min<size_t>(mx, end-frm));
1284}
1285
1286int
Howard Hinnantc9834542011-05-31 15:34:58 +00001287codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001288{
1289 return 1;
1290}
1291
1292// template <> class codecvt<wchar_t, char, mbstate_t>
1293
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001294locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001295
1296codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1297 : locale::facet(refs),
1298 __l(0)
1299{
1300}
1301
1302codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1303 : locale::facet(refs),
1304 __l(newlocale(LC_ALL_MASK, nm, 0))
1305{
Howard Hinnantd4444702010-08-11 17:04:31 +00001306#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001307 if (__l == 0)
1308 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1309 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001310#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001311}
1312
1313codecvt<wchar_t, char, mbstate_t>::~codecvt()
1314{
1315 if (__l != 0)
1316 freelocale(__l);
1317}
1318
1319codecvt<wchar_t, char, mbstate_t>::result
1320codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001321 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001322 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1323{
1324 // look for first internal null in frm
1325 const intern_type* fend = frm;
1326 for (; fend != frm_end; ++fend)
1327 if (*fend == 0)
1328 break;
1329 // loop over all null-terminated sequences in frm
1330 to_nxt = to;
1331 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1332 {
1333 // save state in case needed to reover to_nxt on error
1334 mbstate_t save_state = st;
Howard Hinnantd318d492011-06-30 14:21:55 +00001335 size_t n = with_locale::wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001336 if (n == size_t(-1))
1337 {
1338 // need to recover to_nxt
1339 for (to_nxt = to; frm != frm_nxt; ++frm)
1340 {
Howard Hinnantd318d492011-06-30 14:21:55 +00001341 n = with_locale::wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001342 if (n == size_t(-1))
1343 break;
1344 to_nxt += n;
1345 }
1346 frm_nxt = frm;
1347 return error;
1348 }
1349 if (n == 0)
1350 return partial;
1351 to_nxt += n;
1352 if (to_nxt == to_end)
1353 break;
1354 if (fend != frm_end) // set up next null terminated sequence
1355 {
1356 // Try to write the terminating null
1357 extern_type tmp[MB_LEN_MAX];
Howard Hinnantd318d492011-06-30 14:21:55 +00001358 n = with_locale::wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001359 if (n == size_t(-1)) // on error
1360 return error;
1361 if (n > to_end-to_nxt) // is there room?
1362 return partial;
1363 for (extern_type* p = tmp; n; --n) // write it
1364 *to_nxt++ = *p++;
1365 ++frm_nxt;
1366 // look for next null in frm
1367 for (fend = frm_nxt; fend != frm_end; ++fend)
1368 if (*fend == 0)
1369 break;
1370 }
1371 }
1372 return frm_nxt == frm_end ? ok : partial;
1373}
1374
1375codecvt<wchar_t, char, mbstate_t>::result
1376codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001377 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001378 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1379{
1380 // look for first internal null in frm
1381 const extern_type* fend = frm;
1382 for (; fend != frm_end; ++fend)
1383 if (*fend == 0)
1384 break;
1385 // loop over all null-terminated sequences in frm
1386 to_nxt = to;
1387 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1388 {
1389 // save state in case needed to reover to_nxt on error
1390 mbstate_t save_state = st;
Howard Hinnantd318d492011-06-30 14:21:55 +00001391 size_t n = with_locale::mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001392 if (n == size_t(-1))
1393 {
1394 // need to recover to_nxt
1395 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1396 {
Howard Hinnantd318d492011-06-30 14:21:55 +00001397 n = with_locale::mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001398 switch (n)
1399 {
1400 case 0:
1401 ++frm;
1402 break;
1403 case -1:
1404 frm_nxt = frm;
1405 return error;
1406 case -2:
1407 frm_nxt = frm;
1408 return partial;
1409 default:
1410 frm += n;
1411 break;
1412 }
1413 }
1414 frm_nxt = frm;
1415 return frm_nxt == frm_end ? ok : partial;
1416 }
1417 if (n == 0)
1418 return error;
1419 to_nxt += n;
1420 if (to_nxt == to_end)
1421 break;
1422 if (fend != frm_end) // set up next null terminated sequence
1423 {
1424 // Try to write the terminating null
Howard Hinnantd318d492011-06-30 14:21:55 +00001425 n = with_locale::mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001426 if (n != 0) // on error
1427 return error;
1428 ++to_nxt;
1429 ++frm_nxt;
1430 // look for next null in frm
1431 for (fend = frm_nxt; fend != frm_end; ++fend)
1432 if (*fend == 0)
1433 break;
1434 }
1435 }
1436 return frm_nxt == frm_end ? ok : partial;
1437}
1438
1439codecvt<wchar_t, char, mbstate_t>::result
1440codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1441 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1442{
1443 to_nxt = to;
1444 extern_type tmp[MB_LEN_MAX];
Howard Hinnantd318d492011-06-30 14:21:55 +00001445 size_t n = with_locale::wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001446 if (n == size_t(-1) || n == 0) // on error
1447 return error;
1448 --n;
1449 if (n > to_end-to_nxt) // is there room?
1450 return partial;
1451 for (extern_type* p = tmp; n; --n) // write it
1452 *to_nxt++ = *p++;
1453 return ok;
1454}
1455
1456int
Howard Hinnantc9834542011-05-31 15:34:58 +00001457codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458{
Howard Hinnantd318d492011-06-30 14:21:55 +00001459 if (with_locale::mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001460 {
1461 // stateless encoding
Howard Hinnantd318d492011-06-30 14:21:55 +00001462 if (__l == 0 || with_locale::mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001463 return 1; // which take more than 1 char to form a wchar_t
1464 return 0;
1465 }
1466 return -1;
1467}
1468
1469bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001470codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001471{
1472 return false;
1473}
1474
1475int
1476codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1477 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1478{
1479 int nbytes = 0;
1480 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1481 {
Howard Hinnantd318d492011-06-30 14:21:55 +00001482 size_t n = with_locale::mbrlen_l(frm, frm_end-frm, &st, __l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001483 switch (n)
1484 {
1485 case 0:
1486 ++nbytes;
1487 ++frm;
1488 break;
1489 case -1:
1490 case -2:
1491 return nbytes;
1492 default:
1493 nbytes += n;
1494 frm += n;
1495 break;
1496 }
1497 }
1498 return nbytes;
1499}
1500
1501int
Howard Hinnantc9834542011-05-31 15:34:58 +00001502codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001503{
Howard Hinnantd318d492011-06-30 14:21:55 +00001504 return __l == 0 ? 1 : with_locale::mb_cur_max_l(__l);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001505}
1506
1507// Valid UTF ranges
1508// UTF-32 UTF-16 UTF-8 # of code points
1509// first second first second third fourth
1510// 000000 - 00007F 0000 - 007F 00 - 7F 127
1511// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1512// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1513// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1514// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1515// 00D800 - 00DFFF invalid
1516// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1517// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1518// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1519// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1520
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001521static
1522codecvt_base::result
1523utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1524 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1525 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1526{
1527 frm_nxt = frm;
1528 to_nxt = to;
1529 if (mode & generate_header)
1530 {
1531 if (to_end-to_nxt < 3)
1532 return codecvt_base::partial;
1533 *to_nxt++ = static_cast<uint8_t>(0xEF);
1534 *to_nxt++ = static_cast<uint8_t>(0xBB);
1535 *to_nxt++ = static_cast<uint8_t>(0xBF);
1536 }
1537 for (; frm_nxt < frm_end; ++frm_nxt)
1538 {
1539 uint16_t wc1 = *frm_nxt;
1540 if (wc1 > Maxcode)
1541 return codecvt_base::error;
1542 if (wc1 < 0x0080)
1543 {
1544 if (to_end-to_nxt < 1)
1545 return codecvt_base::partial;
1546 *to_nxt++ = static_cast<uint8_t>(wc1);
1547 }
1548 else if (wc1 < 0x0800)
1549 {
1550 if (to_end-to_nxt < 2)
1551 return codecvt_base::partial;
1552 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1553 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1554 }
1555 else if (wc1 < 0xD800)
1556 {
1557 if (to_end-to_nxt < 3)
1558 return codecvt_base::partial;
1559 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1560 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1561 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1562 }
1563 else if (wc1 < 0xDC00)
1564 {
1565 if (frm_end-frm_nxt < 2)
1566 return codecvt_base::partial;
1567 uint16_t wc2 = frm_nxt[1];
1568 if ((wc2 & 0xFC00) != 0xDC00)
1569 return codecvt_base::error;
1570 if (to_end-to_nxt < 4)
1571 return codecvt_base::partial;
1572 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1573 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1574 return codecvt_base::error;
1575 ++frm_nxt;
1576 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1577 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1578 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1579 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1580 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1581 }
1582 else if (wc1 < 0xE000)
1583 {
1584 return codecvt_base::error;
1585 }
1586 else
1587 {
1588 if (to_end-to_nxt < 3)
1589 return codecvt_base::partial;
1590 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1591 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1592 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1593 }
1594 }
1595 return codecvt_base::ok;
1596}
1597
1598static
1599codecvt_base::result
1600utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1601 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1602 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1603{
1604 frm_nxt = frm;
1605 to_nxt = to;
1606 if (mode & generate_header)
1607 {
1608 if (to_end-to_nxt < 3)
1609 return codecvt_base::partial;
1610 *to_nxt++ = static_cast<uint8_t>(0xEF);
1611 *to_nxt++ = static_cast<uint8_t>(0xBB);
1612 *to_nxt++ = static_cast<uint8_t>(0xBF);
1613 }
1614 for (; frm_nxt < frm_end; ++frm_nxt)
1615 {
1616 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1617 if (wc1 > Maxcode)
1618 return codecvt_base::error;
1619 if (wc1 < 0x0080)
1620 {
1621 if (to_end-to_nxt < 1)
1622 return codecvt_base::partial;
1623 *to_nxt++ = static_cast<uint8_t>(wc1);
1624 }
1625 else if (wc1 < 0x0800)
1626 {
1627 if (to_end-to_nxt < 2)
1628 return codecvt_base::partial;
1629 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1630 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1631 }
1632 else if (wc1 < 0xD800)
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 else if (wc1 < 0xDC00)
1641 {
1642 if (frm_end-frm_nxt < 2)
1643 return codecvt_base::partial;
1644 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1645 if ((wc2 & 0xFC00) != 0xDC00)
1646 return codecvt_base::error;
1647 if (to_end-to_nxt < 4)
1648 return codecvt_base::partial;
1649 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1650 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1651 return codecvt_base::error;
1652 ++frm_nxt;
1653 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1654 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1655 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1656 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1657 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1658 }
1659 else if (wc1 < 0xE000)
1660 {
1661 return codecvt_base::error;
1662 }
1663 else
1664 {
1665 if (to_end-to_nxt < 3)
1666 return codecvt_base::partial;
1667 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1668 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1669 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1670 }
1671 }
1672 return codecvt_base::ok;
1673}
1674
1675static
1676codecvt_base::result
1677utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1678 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1679 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1680{
1681 frm_nxt = frm;
1682 to_nxt = to;
1683 if (mode & consume_header)
1684 {
1685 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1686 frm_nxt[2] == 0xBF)
1687 frm_nxt += 3;
1688 }
1689 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1690 {
1691 uint8_t c1 = *frm_nxt;
1692 if (c1 > Maxcode)
1693 return codecvt_base::error;
1694 if (c1 < 0x80)
1695 {
1696 *to_nxt = static_cast<uint16_t>(c1);
1697 ++frm_nxt;
1698 }
1699 else if (c1 < 0xC2)
1700 {
1701 return codecvt_base::error;
1702 }
1703 else if (c1 < 0xE0)
1704 {
1705 if (frm_end-frm_nxt < 2)
1706 return codecvt_base::partial;
1707 uint8_t c2 = frm_nxt[1];
1708 if ((c2 & 0xC0) != 0x80)
1709 return codecvt_base::error;
1710 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1711 if (t > Maxcode)
1712 return codecvt_base::error;
1713 *to_nxt = t;
1714 frm_nxt += 2;
1715 }
1716 else if (c1 < 0xF0)
1717 {
1718 if (frm_end-frm_nxt < 3)
1719 return codecvt_base::partial;
1720 uint8_t c2 = frm_nxt[1];
1721 uint8_t c3 = frm_nxt[2];
1722 switch (c1)
1723 {
1724 case 0xE0:
1725 if ((c2 & 0xE0) != 0xA0)
1726 return codecvt_base::error;
1727 break;
1728 case 0xED:
1729 if ((c2 & 0xE0) != 0x80)
1730 return codecvt_base::error;
1731 break;
1732 default:
1733 if ((c2 & 0xC0) != 0x80)
1734 return codecvt_base::error;
1735 break;
1736 }
1737 if ((c3 & 0xC0) != 0x80)
1738 return codecvt_base::error;
1739 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1740 | ((c2 & 0x3F) << 6)
1741 | (c3 & 0x3F));
1742 if (t > Maxcode)
1743 return codecvt_base::error;
1744 *to_nxt = t;
1745 frm_nxt += 3;
1746 }
1747 else if (c1 < 0xF5)
1748 {
1749 if (frm_end-frm_nxt < 4)
1750 return codecvt_base::partial;
1751 uint8_t c2 = frm_nxt[1];
1752 uint8_t c3 = frm_nxt[2];
1753 uint8_t c4 = frm_nxt[3];
1754 switch (c1)
1755 {
1756 case 0xF0:
1757 if (!(0x90 <= c2 && c2 <= 0xBF))
1758 return codecvt_base::error;
1759 break;
1760 case 0xF4:
1761 if ((c2 & 0xF0) != 0x80)
1762 return codecvt_base::error;
1763 break;
1764 default:
1765 if ((c2 & 0xC0) != 0x80)
1766 return codecvt_base::error;
1767 break;
1768 }
1769 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1770 return codecvt_base::error;
1771 if (to_end-to_nxt < 2)
1772 return codecvt_base::partial;
1773 if (((((unsigned long)c1 & 7) << 18) +
1774 (((unsigned long)c2 & 0x3F) << 12) +
1775 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1776 return codecvt_base::error;
1777 *to_nxt = static_cast<uint16_t>(
1778 0xD800
1779 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1780 | ((c2 & 0x0F) << 2)
1781 | ((c3 & 0x30) >> 4));
1782 *++to_nxt = static_cast<uint16_t>(
1783 0xDC00
1784 | ((c3 & 0x0F) << 6)
1785 | (c4 & 0x3F));
1786 frm_nxt += 4;
1787 }
1788 else
1789 {
1790 return codecvt_base::error;
1791 }
1792 }
1793 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1794}
1795
1796static
1797codecvt_base::result
1798utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1799 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1800 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1801{
1802 frm_nxt = frm;
1803 to_nxt = to;
1804 if (mode & consume_header)
1805 {
1806 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1807 frm_nxt[2] == 0xBF)
1808 frm_nxt += 3;
1809 }
1810 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1811 {
1812 uint8_t c1 = *frm_nxt;
1813 if (c1 > Maxcode)
1814 return codecvt_base::error;
1815 if (c1 < 0x80)
1816 {
1817 *to_nxt = static_cast<uint32_t>(c1);
1818 ++frm_nxt;
1819 }
1820 else if (c1 < 0xC2)
1821 {
1822 return codecvt_base::error;
1823 }
1824 else if (c1 < 0xE0)
1825 {
1826 if (frm_end-frm_nxt < 2)
1827 return codecvt_base::partial;
1828 uint8_t c2 = frm_nxt[1];
1829 if ((c2 & 0xC0) != 0x80)
1830 return codecvt_base::error;
1831 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1832 if (t > Maxcode)
1833 return codecvt_base::error;
1834 *to_nxt = static_cast<uint32_t>(t);
1835 frm_nxt += 2;
1836 }
1837 else if (c1 < 0xF0)
1838 {
1839 if (frm_end-frm_nxt < 3)
1840 return codecvt_base::partial;
1841 uint8_t c2 = frm_nxt[1];
1842 uint8_t c3 = frm_nxt[2];
1843 switch (c1)
1844 {
1845 case 0xE0:
1846 if ((c2 & 0xE0) != 0xA0)
1847 return codecvt_base::error;
1848 break;
1849 case 0xED:
1850 if ((c2 & 0xE0) != 0x80)
1851 return codecvt_base::error;
1852 break;
1853 default:
1854 if ((c2 & 0xC0) != 0x80)
1855 return codecvt_base::error;
1856 break;
1857 }
1858 if ((c3 & 0xC0) != 0x80)
1859 return codecvt_base::error;
1860 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1861 | ((c2 & 0x3F) << 6)
1862 | (c3 & 0x3F));
1863 if (t > Maxcode)
1864 return codecvt_base::error;
1865 *to_nxt = static_cast<uint32_t>(t);
1866 frm_nxt += 3;
1867 }
1868 else if (c1 < 0xF5)
1869 {
1870 if (frm_end-frm_nxt < 4)
1871 return codecvt_base::partial;
1872 uint8_t c2 = frm_nxt[1];
1873 uint8_t c3 = frm_nxt[2];
1874 uint8_t c4 = frm_nxt[3];
1875 switch (c1)
1876 {
1877 case 0xF0:
1878 if (!(0x90 <= c2 && c2 <= 0xBF))
1879 return codecvt_base::error;
1880 break;
1881 case 0xF4:
1882 if ((c2 & 0xF0) != 0x80)
1883 return codecvt_base::error;
1884 break;
1885 default:
1886 if ((c2 & 0xC0) != 0x80)
1887 return codecvt_base::error;
1888 break;
1889 }
1890 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1891 return codecvt_base::error;
1892 if (to_end-to_nxt < 2)
1893 return codecvt_base::partial;
1894 if (((((unsigned long)c1 & 7) << 18) +
1895 (((unsigned long)c2 & 0x3F) << 12) +
1896 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1897 return codecvt_base::error;
1898 *to_nxt = static_cast<uint32_t>(
1899 0xD800
1900 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1901 | ((c2 & 0x0F) << 2)
1902 | ((c3 & 0x30) >> 4));
1903 *++to_nxt = static_cast<uint32_t>(
1904 0xDC00
1905 | ((c3 & 0x0F) << 6)
1906 | (c4 & 0x3F));
1907 frm_nxt += 4;
1908 }
1909 else
1910 {
1911 return codecvt_base::error;
1912 }
1913 }
1914 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1915}
1916
1917static
1918int
1919utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1920 size_t mx, unsigned long Maxcode = 0x10FFFF,
1921 codecvt_mode mode = codecvt_mode(0))
1922{
1923 const uint8_t* frm_nxt = frm;
1924 if (mode & consume_header)
1925 {
1926 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1927 frm_nxt[2] == 0xBF)
1928 frm_nxt += 3;
1929 }
1930 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1931 {
1932 uint8_t c1 = *frm_nxt;
1933 if (c1 > Maxcode)
1934 break;
1935 if (c1 < 0x80)
1936 {
1937 ++frm_nxt;
1938 }
1939 else if (c1 < 0xC2)
1940 {
1941 break;
1942 }
1943 else if (c1 < 0xE0)
1944 {
1945 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1946 break;
1947 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
1948 if (t > Maxcode)
1949 break;
1950 frm_nxt += 2;
1951 }
1952 else if (c1 < 0xF0)
1953 {
1954 if (frm_end-frm_nxt < 3)
1955 break;
1956 uint8_t c2 = frm_nxt[1];
1957 uint8_t c3 = frm_nxt[2];
1958 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1959 | ((c2 & 0x3F) << 6)
1960 | (c3 & 0x3F));
1961 switch (c1)
1962 {
1963 case 0xE0:
1964 if ((c2 & 0xE0) != 0xA0)
1965 return static_cast<int>(frm_nxt - frm);
1966 break;
1967 case 0xED:
1968 if ((c2 & 0xE0) != 0x80)
1969 return static_cast<int>(frm_nxt - frm);
1970 break;
1971 default:
1972 if ((c2 & 0xC0) != 0x80)
1973 return static_cast<int>(frm_nxt - frm);
1974 break;
1975 }
1976 if ((c3 & 0xC0) != 0x80)
1977 break;
1978 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
1979 break;
1980 frm_nxt += 3;
1981 }
1982 else if (c1 < 0xF5)
1983 {
1984 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
1985 break;
1986 uint8_t c2 = frm_nxt[1];
1987 uint8_t c3 = frm_nxt[2];
1988 uint8_t c4 = frm_nxt[3];
1989 switch (c1)
1990 {
1991 case 0xF0:
1992 if (!(0x90 <= c2 && c2 <= 0xBF))
1993 return static_cast<int>(frm_nxt - frm);
1994 break;
1995 case 0xF4:
1996 if ((c2 & 0xF0) != 0x80)
1997 return static_cast<int>(frm_nxt - frm);
1998 break;
1999 default:
2000 if ((c2 & 0xC0) != 0x80)
2001 return static_cast<int>(frm_nxt - frm);
2002 break;
2003 }
2004 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2005 break;
2006 if (((((unsigned long)c1 & 7) << 18) +
2007 (((unsigned long)c2 & 0x3F) << 12) +
2008 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2009 break;
2010 ++nchar16_t;
2011 frm_nxt += 4;
2012 }
2013 else
2014 {
2015 break;
2016 }
2017 }
2018 return static_cast<int>(frm_nxt - frm);
2019}
2020
2021static
2022codecvt_base::result
2023ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2024 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2025 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2026{
2027 frm_nxt = frm;
2028 to_nxt = to;
2029 if (mode & generate_header)
2030 {
2031 if (to_end-to_nxt < 3)
2032 return codecvt_base::partial;
2033 *to_nxt++ = static_cast<uint8_t>(0xEF);
2034 *to_nxt++ = static_cast<uint8_t>(0xBB);
2035 *to_nxt++ = static_cast<uint8_t>(0xBF);
2036 }
2037 for (; frm_nxt < frm_end; ++frm_nxt)
2038 {
2039 uint32_t wc = *frm_nxt;
2040 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2041 return codecvt_base::error;
2042 if (wc < 0x000080)
2043 {
2044 if (to_end-to_nxt < 1)
2045 return codecvt_base::partial;
2046 *to_nxt++ = static_cast<uint8_t>(wc);
2047 }
2048 else if (wc < 0x000800)
2049 {
2050 if (to_end-to_nxt < 2)
2051 return codecvt_base::partial;
2052 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2053 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2054 }
2055 else if (wc < 0x010000)
2056 {
2057 if (to_end-to_nxt < 3)
2058 return codecvt_base::partial;
2059 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2060 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2061 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2062 }
2063 else // if (wc < 0x110000)
2064 {
2065 if (to_end-to_nxt < 4)
2066 return codecvt_base::partial;
2067 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2068 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2069 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2070 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2071 }
2072 }
2073 return codecvt_base::ok;
2074}
2075
2076static
2077codecvt_base::result
2078utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2079 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2080 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2081{
2082 frm_nxt = frm;
2083 to_nxt = to;
2084 if (mode & consume_header)
2085 {
2086 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2087 frm_nxt[2] == 0xBF)
2088 frm_nxt += 3;
2089 }
2090 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2091 {
2092 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2093 if (c1 < 0x80)
2094 {
2095 if (c1 > Maxcode)
2096 return codecvt_base::error;
2097 *to_nxt = static_cast<uint32_t>(c1);
2098 ++frm_nxt;
2099 }
2100 else if (c1 < 0xC2)
2101 {
2102 return codecvt_base::error;
2103 }
2104 else if (c1 < 0xE0)
2105 {
2106 if (frm_end-frm_nxt < 2)
2107 return codecvt_base::partial;
2108 uint8_t c2 = frm_nxt[1];
2109 if ((c2 & 0xC0) != 0x80)
2110 return codecvt_base::error;
2111 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2112 | (c2 & 0x3F));
2113 if (t > Maxcode)
2114 return codecvt_base::error;
2115 *to_nxt = t;
2116 frm_nxt += 2;
2117 }
2118 else if (c1 < 0xF0)
2119 {
2120 if (frm_end-frm_nxt < 3)
2121 return codecvt_base::partial;
2122 uint8_t c2 = frm_nxt[1];
2123 uint8_t c3 = frm_nxt[2];
2124 switch (c1)
2125 {
2126 case 0xE0:
2127 if ((c2 & 0xE0) != 0xA0)
2128 return codecvt_base::error;
2129 break;
2130 case 0xED:
2131 if ((c2 & 0xE0) != 0x80)
2132 return codecvt_base::error;
2133 break;
2134 default:
2135 if ((c2 & 0xC0) != 0x80)
2136 return codecvt_base::error;
2137 break;
2138 }
2139 if ((c3 & 0xC0) != 0x80)
2140 return codecvt_base::error;
2141 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2142 | ((c2 & 0x3F) << 6)
2143 | (c3 & 0x3F));
2144 if (t > Maxcode)
2145 return codecvt_base::error;
2146 *to_nxt = t;
2147 frm_nxt += 3;
2148 }
2149 else if (c1 < 0xF5)
2150 {
2151 if (frm_end-frm_nxt < 4)
2152 return codecvt_base::partial;
2153 uint8_t c2 = frm_nxt[1];
2154 uint8_t c3 = frm_nxt[2];
2155 uint8_t c4 = frm_nxt[3];
2156 switch (c1)
2157 {
2158 case 0xF0:
2159 if (!(0x90 <= c2 && c2 <= 0xBF))
2160 return codecvt_base::error;
2161 break;
2162 case 0xF4:
2163 if ((c2 & 0xF0) != 0x80)
2164 return codecvt_base::error;
2165 break;
2166 default:
2167 if ((c2 & 0xC0) != 0x80)
2168 return codecvt_base::error;
2169 break;
2170 }
2171 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2172 return codecvt_base::error;
2173 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2174 | ((c2 & 0x3F) << 12)
2175 | ((c3 & 0x3F) << 6)
2176 | (c4 & 0x3F));
2177 if (t > Maxcode)
2178 return codecvt_base::error;
2179 *to_nxt = t;
2180 frm_nxt += 4;
2181 }
2182 else
2183 {
2184 return codecvt_base::error;
2185 }
2186 }
2187 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2188}
2189
2190static
2191int
2192utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2193 size_t mx, unsigned long Maxcode = 0x10FFFF,
2194 codecvt_mode mode = codecvt_mode(0))
2195{
2196 const uint8_t* frm_nxt = frm;
2197 if (mode & consume_header)
2198 {
2199 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2200 frm_nxt[2] == 0xBF)
2201 frm_nxt += 3;
2202 }
2203 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2204 {
2205 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2206 if (c1 < 0x80)
2207 {
2208 if (c1 > Maxcode)
2209 break;
2210 ++frm_nxt;
2211 }
2212 else if (c1 < 0xC2)
2213 {
2214 break;
2215 }
2216 else if (c1 < 0xE0)
2217 {
2218 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2219 break;
2220 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2221 break;
2222 frm_nxt += 2;
2223 }
2224 else if (c1 < 0xF0)
2225 {
2226 if (frm_end-frm_nxt < 3)
2227 break;
2228 uint8_t c2 = frm_nxt[1];
2229 uint8_t c3 = frm_nxt[2];
2230 switch (c1)
2231 {
2232 case 0xE0:
2233 if ((c2 & 0xE0) != 0xA0)
2234 return static_cast<int>(frm_nxt - frm);
2235 break;
2236 case 0xED:
2237 if ((c2 & 0xE0) != 0x80)
2238 return static_cast<int>(frm_nxt - frm);
2239 break;
2240 default:
2241 if ((c2 & 0xC0) != 0x80)
2242 return static_cast<int>(frm_nxt - frm);
2243 break;
2244 }
2245 if ((c3 & 0xC0) != 0x80)
2246 break;
2247 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2248 break;
2249 frm_nxt += 3;
2250 }
2251 else if (c1 < 0xF5)
2252 {
2253 if (frm_end-frm_nxt < 4)
2254 break;
2255 uint8_t c2 = frm_nxt[1];
2256 uint8_t c3 = frm_nxt[2];
2257 uint8_t c4 = frm_nxt[3];
2258 switch (c1)
2259 {
2260 case 0xF0:
2261 if (!(0x90 <= c2 && c2 <= 0xBF))
2262 return static_cast<int>(frm_nxt - frm);
2263 break;
2264 case 0xF4:
2265 if ((c2 & 0xF0) != 0x80)
2266 return static_cast<int>(frm_nxt - frm);
2267 break;
2268 default:
2269 if ((c2 & 0xC0) != 0x80)
2270 return static_cast<int>(frm_nxt - frm);
2271 break;
2272 }
2273 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2274 break;
2275 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2276 | ((c2 & 0x3F) << 12)
2277 | ((c3 & 0x3F) << 6)
2278 | (c4 & 0x3F));
2279 if ((((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) |
2280 ((c3 & 0x3F) << 6) | (c4 & 0x3F)) > Maxcode)
2281 break;
2282 frm_nxt += 4;
2283 }
2284 else
2285 {
2286 break;
2287 }
2288 }
2289 return static_cast<int>(frm_nxt - frm);
2290}
2291
2292static
2293codecvt_base::result
2294ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2295 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2296 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2297{
2298 frm_nxt = frm;
2299 to_nxt = to;
2300 if (mode & generate_header)
2301 {
2302 if (to_end-to_nxt < 3)
2303 return codecvt_base::partial;
2304 *to_nxt++ = static_cast<uint8_t>(0xEF);
2305 *to_nxt++ = static_cast<uint8_t>(0xBB);
2306 *to_nxt++ = static_cast<uint8_t>(0xBF);
2307 }
2308 for (; frm_nxt < frm_end; ++frm_nxt)
2309 {
2310 uint16_t wc = *frm_nxt;
2311 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2312 return codecvt_base::error;
2313 if (wc < 0x0080)
2314 {
2315 if (to_end-to_nxt < 1)
2316 return codecvt_base::partial;
2317 *to_nxt++ = static_cast<uint8_t>(wc);
2318 }
2319 else if (wc < 0x0800)
2320 {
2321 if (to_end-to_nxt < 2)
2322 return codecvt_base::partial;
2323 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2324 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2325 }
2326 else // if (wc <= 0xFFFF)
2327 {
2328 if (to_end-to_nxt < 3)
2329 return codecvt_base::partial;
2330 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2331 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2332 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2333 }
2334 }
2335 return codecvt_base::ok;
2336}
2337
2338static
2339codecvt_base::result
2340utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2341 uint16_t* to, uint16_t* to_end, uint16_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 & consume_header)
2347 {
2348 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2349 frm_nxt[2] == 0xBF)
2350 frm_nxt += 3;
2351 }
2352 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2353 {
2354 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2355 if (c1 < 0x80)
2356 {
2357 if (c1 > Maxcode)
2358 return codecvt_base::error;
2359 *to_nxt = static_cast<uint16_t>(c1);
2360 ++frm_nxt;
2361 }
2362 else if (c1 < 0xC2)
2363 {
2364 return codecvt_base::error;
2365 }
2366 else if (c1 < 0xE0)
2367 {
2368 if (frm_end-frm_nxt < 2)
2369 return codecvt_base::partial;
2370 uint8_t c2 = frm_nxt[1];
2371 if ((c2 & 0xC0) != 0x80)
2372 return codecvt_base::error;
2373 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2374 | (c2 & 0x3F));
2375 if (t > Maxcode)
2376 return codecvt_base::error;
2377 *to_nxt = t;
2378 frm_nxt += 2;
2379 }
2380 else if (c1 < 0xF0)
2381 {
2382 if (frm_end-frm_nxt < 3)
2383 return codecvt_base::partial;
2384 uint8_t c2 = frm_nxt[1];
2385 uint8_t c3 = frm_nxt[2];
2386 switch (c1)
2387 {
2388 case 0xE0:
2389 if ((c2 & 0xE0) != 0xA0)
2390 return codecvt_base::error;
2391 break;
2392 case 0xED:
2393 if ((c2 & 0xE0) != 0x80)
2394 return codecvt_base::error;
2395 break;
2396 default:
2397 if ((c2 & 0xC0) != 0x80)
2398 return codecvt_base::error;
2399 break;
2400 }
2401 if ((c3 & 0xC0) != 0x80)
2402 return codecvt_base::error;
2403 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2404 | ((c2 & 0x3F) << 6)
2405 | (c3 & 0x3F));
2406 if (t > Maxcode)
2407 return codecvt_base::error;
2408 *to_nxt = t;
2409 frm_nxt += 3;
2410 }
2411 else
2412 {
2413 return codecvt_base::error;
2414 }
2415 }
2416 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2417}
2418
2419static
2420int
2421utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2422 size_t mx, unsigned long Maxcode = 0x10FFFF,
2423 codecvt_mode mode = codecvt_mode(0))
2424{
2425 const uint8_t* frm_nxt = frm;
2426 if (mode & consume_header)
2427 {
2428 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2429 frm_nxt[2] == 0xBF)
2430 frm_nxt += 3;
2431 }
2432 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2433 {
2434 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2435 if (c1 < 0x80)
2436 {
2437 if (c1 > Maxcode)
2438 break;
2439 ++frm_nxt;
2440 }
2441 else if (c1 < 0xC2)
2442 {
2443 break;
2444 }
2445 else if (c1 < 0xE0)
2446 {
2447 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2448 break;
2449 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2450 break;
2451 frm_nxt += 2;
2452 }
2453 else if (c1 < 0xF0)
2454 {
2455 if (frm_end-frm_nxt < 3)
2456 break;
2457 uint8_t c2 = frm_nxt[1];
2458 uint8_t c3 = frm_nxt[2];
2459 switch (c1)
2460 {
2461 case 0xE0:
2462 if ((c2 & 0xE0) != 0xA0)
2463 return static_cast<int>(frm_nxt - frm);
2464 break;
2465 case 0xED:
2466 if ((c2 & 0xE0) != 0x80)
2467 return static_cast<int>(frm_nxt - frm);
2468 break;
2469 default:
2470 if ((c2 & 0xC0) != 0x80)
2471 return static_cast<int>(frm_nxt - frm);
2472 break;
2473 }
2474 if ((c3 & 0xC0) != 0x80)
2475 break;
2476 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2477 break;
2478 frm_nxt += 3;
2479 }
2480 else
2481 {
2482 break;
2483 }
2484 }
2485 return static_cast<int>(frm_nxt - frm);
2486}
2487
2488static
2489codecvt_base::result
2490ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2491 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2492 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2493{
2494 frm_nxt = frm;
2495 to_nxt = to;
2496 if (mode & generate_header)
2497 {
2498 if (to_end-to_nxt < 2)
2499 return codecvt_base::partial;
2500 *to_nxt++ = static_cast<uint8_t>(0xFE);
2501 *to_nxt++ = static_cast<uint8_t>(0xFF);
2502 }
2503 for (; frm_nxt < frm_end; ++frm_nxt)
2504 {
2505 uint32_t wc = *frm_nxt;
2506 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2507 return codecvt_base::error;
2508 if (wc < 0x010000)
2509 {
2510 if (to_end-to_nxt < 2)
2511 return codecvt_base::partial;
2512 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2513 *to_nxt++ = static_cast<uint8_t>(wc);
2514 }
2515 else
2516 {
2517 if (to_end-to_nxt < 4)
2518 return codecvt_base::partial;
2519 uint16_t t = static_cast<uint16_t>(
2520 0xD800
2521 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2522 | ((wc & 0x00FC00) >> 10));
2523 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2524 *to_nxt++ = static_cast<uint8_t>(t);
2525 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2526 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2527 *to_nxt++ = static_cast<uint8_t>(t);
2528 }
2529 }
2530 return codecvt_base::ok;
2531}
2532
2533static
2534codecvt_base::result
2535utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2536 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2537 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2538{
2539 frm_nxt = frm;
2540 to_nxt = to;
2541 if (mode & consume_header)
2542 {
2543 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2544 frm_nxt += 2;
2545 }
2546 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2547 {
2548 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2549 if ((c1 & 0xFC00) == 0xDC00)
2550 return codecvt_base::error;
2551 if ((c1 & 0xFC00) != 0xD800)
2552 {
2553 if (c1 > Maxcode)
2554 return codecvt_base::error;
2555 *to_nxt = static_cast<uint32_t>(c1);
2556 frm_nxt += 2;
2557 }
2558 else
2559 {
2560 if (frm_end-frm_nxt < 4)
2561 return codecvt_base::partial;
2562 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2563 if ((c2 & 0xFC00) != 0xDC00)
2564 return codecvt_base::error;
2565 uint32_t t = static_cast<uint32_t>(
2566 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2567 | ((c1 & 0x003F) << 10)
2568 | (c2 & 0x03FF));
2569 if (t > Maxcode)
2570 return codecvt_base::error;
2571 *to_nxt = t;
2572 frm_nxt += 4;
2573 }
2574 }
2575 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2576}
2577
2578static
2579int
2580utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2581 size_t mx, unsigned long Maxcode = 0x10FFFF,
2582 codecvt_mode mode = codecvt_mode(0))
2583{
2584 const uint8_t* frm_nxt = frm;
2585 frm_nxt = frm;
2586 if (mode & consume_header)
2587 {
2588 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2589 frm_nxt += 2;
2590 }
2591 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2592 {
2593 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2594 if ((c1 & 0xFC00) == 0xDC00)
2595 break;
2596 if ((c1 & 0xFC00) != 0xD800)
2597 {
2598 if (c1 > Maxcode)
2599 break;
2600 frm_nxt += 2;
2601 }
2602 else
2603 {
2604 if (frm_end-frm_nxt < 4)
2605 break;
2606 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2607 if ((c2 & 0xFC00) != 0xDC00)
2608 break;
2609 uint32_t t = static_cast<uint32_t>(
2610 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2611 | ((c1 & 0x003F) << 10)
2612 | (c2 & 0x03FF));
2613 if (t > Maxcode)
2614 break;
2615 frm_nxt += 4;
2616 }
2617 }
2618 return static_cast<int>(frm_nxt - frm);
2619}
2620
2621static
2622codecvt_base::result
2623ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2624 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2625 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2626{
2627 frm_nxt = frm;
2628 to_nxt = to;
2629 if (mode & generate_header)
2630 {
2631 if (to_end-to_nxt < 2)
2632 return codecvt_base::partial;
2633 *to_nxt++ = static_cast<uint8_t>(0xFF);
2634 *to_nxt++ = static_cast<uint8_t>(0xFE);
2635 }
2636 for (; frm_nxt < frm_end; ++frm_nxt)
2637 {
2638 uint32_t wc = *frm_nxt;
2639 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2640 return codecvt_base::error;
2641 if (wc < 0x010000)
2642 {
2643 if (to_end-to_nxt < 2)
2644 return codecvt_base::partial;
2645 *to_nxt++ = static_cast<uint8_t>(wc);
2646 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2647 }
2648 else
2649 {
2650 if (to_end-to_nxt < 4)
2651 return codecvt_base::partial;
2652 uint16_t t = static_cast<uint16_t>(
2653 0xD800
2654 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2655 | ((wc & 0x00FC00) >> 10));
2656 *to_nxt++ = static_cast<uint8_t>(t);
2657 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2658 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2659 *to_nxt++ = static_cast<uint8_t>(t);
2660 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2661 }
2662 }
2663 return codecvt_base::ok;
2664}
2665
2666static
2667codecvt_base::result
2668utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2669 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2670 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2671{
2672 frm_nxt = frm;
2673 to_nxt = to;
2674 if (mode & consume_header)
2675 {
2676 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2677 frm_nxt += 2;
2678 }
2679 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2680 {
2681 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2682 if ((c1 & 0xFC00) == 0xDC00)
2683 return codecvt_base::error;
2684 if ((c1 & 0xFC00) != 0xD800)
2685 {
2686 if (c1 > Maxcode)
2687 return codecvt_base::error;
2688 *to_nxt = static_cast<uint32_t>(c1);
2689 frm_nxt += 2;
2690 }
2691 else
2692 {
2693 if (frm_end-frm_nxt < 4)
2694 return codecvt_base::partial;
2695 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2696 if ((c2 & 0xFC00) != 0xDC00)
2697 return codecvt_base::error;
2698 uint32_t t = static_cast<uint32_t>(
2699 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2700 | ((c1 & 0x003F) << 10)
2701 | (c2 & 0x03FF));
2702 if (t > Maxcode)
2703 return codecvt_base::error;
2704 *to_nxt = t;
2705 frm_nxt += 4;
2706 }
2707 }
2708 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2709}
2710
2711static
2712int
2713utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2714 size_t mx, unsigned long Maxcode = 0x10FFFF,
2715 codecvt_mode mode = codecvt_mode(0))
2716{
2717 const uint8_t* frm_nxt = frm;
2718 frm_nxt = frm;
2719 if (mode & consume_header)
2720 {
2721 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2722 frm_nxt += 2;
2723 }
2724 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2725 {
2726 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2727 if ((c1 & 0xFC00) == 0xDC00)
2728 break;
2729 if ((c1 & 0xFC00) != 0xD800)
2730 {
2731 if (c1 > Maxcode)
2732 break;
2733 frm_nxt += 2;
2734 }
2735 else
2736 {
2737 if (frm_end-frm_nxt < 4)
2738 break;
2739 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2740 if ((c2 & 0xFC00) != 0xDC00)
2741 break;
2742 uint32_t t = static_cast<uint32_t>(
2743 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2744 | ((c1 & 0x003F) << 10)
2745 | (c2 & 0x03FF));
2746 if (t > Maxcode)
2747 break;
2748 frm_nxt += 4;
2749 }
2750 }
2751 return static_cast<int>(frm_nxt - frm);
2752}
2753
2754static
2755codecvt_base::result
2756ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2757 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2758 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2759{
2760 frm_nxt = frm;
2761 to_nxt = to;
2762 if (mode & generate_header)
2763 {
2764 if (to_end-to_nxt < 2)
2765 return codecvt_base::partial;
2766 *to_nxt++ = static_cast<uint8_t>(0xFE);
2767 *to_nxt++ = static_cast<uint8_t>(0xFF);
2768 }
2769 for (; frm_nxt < frm_end; ++frm_nxt)
2770 {
2771 uint16_t wc = *frm_nxt;
2772 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2773 return codecvt_base::error;
2774 if (to_end-to_nxt < 2)
2775 return codecvt_base::partial;
2776 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2777 *to_nxt++ = static_cast<uint8_t>(wc);
2778 }
2779 return codecvt_base::ok;
2780}
2781
2782static
2783codecvt_base::result
2784utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2785 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2786 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2787{
2788 frm_nxt = frm;
2789 to_nxt = to;
2790 if (mode & consume_header)
2791 {
2792 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2793 frm_nxt += 2;
2794 }
2795 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2796 {
2797 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2798 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2799 return codecvt_base::error;
2800 *to_nxt = c1;
2801 frm_nxt += 2;
2802 }
2803 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2804}
2805
2806static
2807int
2808utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2809 size_t mx, unsigned long Maxcode = 0x10FFFF,
2810 codecvt_mode mode = codecvt_mode(0))
2811{
2812 const uint8_t* frm_nxt = frm;
2813 frm_nxt = frm;
2814 if (mode & consume_header)
2815 {
2816 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2817 frm_nxt += 2;
2818 }
2819 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2820 {
2821 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2822 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2823 break;
2824 frm_nxt += 2;
2825 }
2826 return static_cast<int>(frm_nxt - frm);
2827}
2828
2829static
2830codecvt_base::result
2831ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2832 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2833 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2834{
2835 frm_nxt = frm;
2836 to_nxt = to;
2837 if (mode & generate_header)
2838 {
2839 if (to_end-to_nxt < 2)
2840 return codecvt_base::partial;
2841 *to_nxt++ = static_cast<uint8_t>(0xFF);
2842 *to_nxt++ = static_cast<uint8_t>(0xFE);
2843 }
2844 for (; frm_nxt < frm_end; ++frm_nxt)
2845 {
2846 uint16_t wc = *frm_nxt;
2847 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2848 return codecvt_base::error;
2849 if (to_end-to_nxt < 2)
2850 return codecvt_base::partial;
2851 *to_nxt++ = static_cast<uint8_t>(wc);
2852 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2853 }
2854 return codecvt_base::ok;
2855}
2856
2857static
2858codecvt_base::result
2859utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2860 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2861 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2862{
2863 frm_nxt = frm;
2864 to_nxt = to;
2865 if (mode & consume_header)
2866 {
2867 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2868 frm_nxt += 2;
2869 }
2870 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2871 {
2872 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2873 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2874 return codecvt_base::error;
2875 *to_nxt = c1;
2876 frm_nxt += 2;
2877 }
2878 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2879}
2880
2881static
2882int
2883utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2884 size_t mx, unsigned long Maxcode = 0x10FFFF,
2885 codecvt_mode mode = codecvt_mode(0))
2886{
2887 const uint8_t* frm_nxt = frm;
2888 frm_nxt = frm;
2889 if (mode & consume_header)
2890 {
2891 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2892 frm_nxt += 2;
2893 }
2894 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2895 {
2896 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2897 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2898 break;
2899 frm_nxt += 2;
2900 }
2901 return static_cast<int>(frm_nxt - frm);
2902}
2903
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002904// template <> class codecvt<char16_t, char, mbstate_t>
2905
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002906locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002907
2908codecvt<char16_t, char, mbstate_t>::~codecvt()
2909{
2910}
2911
2912codecvt<char16_t, char, mbstate_t>::result
2913codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002914 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002915 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2916{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002917 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2918 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2919 const uint16_t* _frm_nxt = _frm;
2920 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2921 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2922 uint8_t* _to_nxt = _to;
2923 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2924 frm_nxt = frm + (_frm_nxt - _frm);
2925 to_nxt = to + (_to_nxt - _to);
2926 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002927}
2928
2929codecvt<char16_t, char, mbstate_t>::result
2930codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002931 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002932 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2933{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002934 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2935 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2936 const uint8_t* _frm_nxt = _frm;
2937 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2938 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2939 uint16_t* _to_nxt = _to;
2940 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2941 frm_nxt = frm + (_frm_nxt - _frm);
2942 to_nxt = to + (_to_nxt - _to);
2943 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002944}
2945
2946codecvt<char16_t, char, mbstate_t>::result
2947codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
2948 extern_type* to, extern_type*, extern_type*& to_nxt) const
2949{
2950 to_nxt = to;
2951 return noconv;
2952}
2953
2954int
Howard Hinnantc9834542011-05-31 15:34:58 +00002955codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002956{
2957 return 0;
2958}
2959
2960bool
Howard Hinnantc9834542011-05-31 15:34:58 +00002961codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002962{
2963 return false;
2964}
2965
2966int
2967codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
2968 const extern_type* frm, const extern_type* frm_end, size_t mx) const
2969{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002970 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2971 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2972 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002973}
2974
2975int
Howard Hinnantc9834542011-05-31 15:34:58 +00002976codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002977{
2978 return 4;
2979}
2980
2981// template <> class codecvt<char32_t, char, mbstate_t>
2982
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002983locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002984
2985codecvt<char32_t, char, mbstate_t>::~codecvt()
2986{
2987}
2988
2989codecvt<char32_t, char, mbstate_t>::result
2990codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002991 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002992 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2993{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002994 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
2995 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
2996 const uint32_t* _frm_nxt = _frm;
2997 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2998 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2999 uint8_t* _to_nxt = _to;
3000 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3001 frm_nxt = frm + (_frm_nxt - _frm);
3002 to_nxt = to + (_to_nxt - _to);
3003 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003004}
3005
3006codecvt<char32_t, char, mbstate_t>::result
3007codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003008 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003009 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3010{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003011 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3012 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3013 const uint8_t* _frm_nxt = _frm;
3014 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3015 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3016 uint32_t* _to_nxt = _to;
3017 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3018 frm_nxt = frm + (_frm_nxt - _frm);
3019 to_nxt = to + (_to_nxt - _to);
3020 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003021}
3022
3023codecvt<char32_t, char, mbstate_t>::result
3024codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3025 extern_type* to, extern_type*, extern_type*& to_nxt) const
3026{
3027 to_nxt = to;
3028 return noconv;
3029}
3030
3031int
Howard Hinnantc9834542011-05-31 15:34:58 +00003032codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003033{
3034 return 0;
3035}
3036
3037bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003038codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003039{
3040 return false;
3041}
3042
3043int
3044codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3045 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3046{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003047 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3048 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3049 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003050}
3051
3052int
Howard Hinnantc9834542011-05-31 15:34:58 +00003053codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003054{
3055 return 4;
3056}
3057
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003058// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003059
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003060__codecvt_utf8<wchar_t>::result
3061__codecvt_utf8<wchar_t>::do_out(state_type&,
3062 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003063 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3064{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003065 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3066 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3067 const uint32_t* _frm_nxt = _frm;
3068 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3069 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3070 uint8_t* _to_nxt = _to;
3071 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3072 _Maxcode_, _Mode_);
3073 frm_nxt = frm + (_frm_nxt - _frm);
3074 to_nxt = to + (_to_nxt - _to);
3075 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003076}
3077
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003078__codecvt_utf8<wchar_t>::result
3079__codecvt_utf8<wchar_t>::do_in(state_type&,
3080 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003081 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3082{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003083 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3084 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3085 const uint8_t* _frm_nxt = _frm;
3086 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3087 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3088 uint32_t* _to_nxt = _to;
3089 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3090 _Maxcode_, _Mode_);
3091 frm_nxt = frm + (_frm_nxt - _frm);
3092 to_nxt = to + (_to_nxt - _to);
3093 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003094}
3095
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003096__codecvt_utf8<wchar_t>::result
3097__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003098 extern_type* to, extern_type*, extern_type*& to_nxt) const
3099{
3100 to_nxt = to;
3101 return noconv;
3102}
3103
3104int
Howard Hinnantc9834542011-05-31 15:34:58 +00003105__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003106{
3107 return 0;
3108}
3109
3110bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003111__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003112{
3113 return false;
3114}
3115
3116int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003117__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003118 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3119{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003120 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3121 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3122 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003123}
3124
3125int
Howard Hinnantc9834542011-05-31 15:34:58 +00003126__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003127{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003128 if (_Mode_ & consume_header)
3129 return 7;
3130 return 4;
3131}
3132
3133// __codecvt_utf8<char16_t>
3134
3135__codecvt_utf8<char16_t>::result
3136__codecvt_utf8<char16_t>::do_out(state_type&,
3137 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3138 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3139{
3140 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3141 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3142 const uint16_t* _frm_nxt = _frm;
3143 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3144 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3145 uint8_t* _to_nxt = _to;
3146 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3147 _Maxcode_, _Mode_);
3148 frm_nxt = frm + (_frm_nxt - _frm);
3149 to_nxt = to + (_to_nxt - _to);
3150 return r;
3151}
3152
3153__codecvt_utf8<char16_t>::result
3154__codecvt_utf8<char16_t>::do_in(state_type&,
3155 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3156 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3157{
3158 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3159 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3160 const uint8_t* _frm_nxt = _frm;
3161 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3162 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3163 uint16_t* _to_nxt = _to;
3164 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3165 _Maxcode_, _Mode_);
3166 frm_nxt = frm + (_frm_nxt - _frm);
3167 to_nxt = to + (_to_nxt - _to);
3168 return r;
3169}
3170
3171__codecvt_utf8<char16_t>::result
3172__codecvt_utf8<char16_t>::do_unshift(state_type&,
3173 extern_type* to, extern_type*, extern_type*& to_nxt) const
3174{
3175 to_nxt = to;
3176 return noconv;
3177}
3178
3179int
Howard Hinnantc9834542011-05-31 15:34:58 +00003180__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003181{
3182 return 0;
3183}
3184
3185bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003186__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003187{
3188 return false;
3189}
3190
3191int
3192__codecvt_utf8<char16_t>::do_length(state_type&,
3193 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3194{
3195 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3196 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3197 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3198}
3199
3200int
Howard Hinnantc9834542011-05-31 15:34:58 +00003201__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003202{
3203 if (_Mode_ & consume_header)
3204 return 6;
3205 return 3;
3206}
3207
3208// __codecvt_utf8<char32_t>
3209
3210__codecvt_utf8<char32_t>::result
3211__codecvt_utf8<char32_t>::do_out(state_type&,
3212 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3213 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3214{
3215 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3216 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3217 const uint32_t* _frm_nxt = _frm;
3218 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3219 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3220 uint8_t* _to_nxt = _to;
3221 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3222 _Maxcode_, _Mode_);
3223 frm_nxt = frm + (_frm_nxt - _frm);
3224 to_nxt = to + (_to_nxt - _to);
3225 return r;
3226}
3227
3228__codecvt_utf8<char32_t>::result
3229__codecvt_utf8<char32_t>::do_in(state_type&,
3230 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3231 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3232{
3233 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3234 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3235 const uint8_t* _frm_nxt = _frm;
3236 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3237 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3238 uint32_t* _to_nxt = _to;
3239 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3240 _Maxcode_, _Mode_);
3241 frm_nxt = frm + (_frm_nxt - _frm);
3242 to_nxt = to + (_to_nxt - _to);
3243 return r;
3244}
3245
3246__codecvt_utf8<char32_t>::result
3247__codecvt_utf8<char32_t>::do_unshift(state_type&,
3248 extern_type* to, extern_type*, extern_type*& to_nxt) const
3249{
3250 to_nxt = to;
3251 return noconv;
3252}
3253
3254int
Howard Hinnantc9834542011-05-31 15:34:58 +00003255__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003256{
3257 return 0;
3258}
3259
3260bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003261__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003262{
3263 return false;
3264}
3265
3266int
3267__codecvt_utf8<char32_t>::do_length(state_type&,
3268 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3269{
3270 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3271 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3272 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3273}
3274
3275int
Howard Hinnantc9834542011-05-31 15:34:58 +00003276__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003277{
3278 if (_Mode_ & consume_header)
3279 return 7;
3280 return 4;
3281}
3282
3283// __codecvt_utf16<wchar_t, false>
3284
3285__codecvt_utf16<wchar_t, false>::result
3286__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3287 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3288 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3289{
3290 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3291 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3292 const uint32_t* _frm_nxt = _frm;
3293 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3294 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3295 uint8_t* _to_nxt = _to;
3296 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3297 _Maxcode_, _Mode_);
3298 frm_nxt = frm + (_frm_nxt - _frm);
3299 to_nxt = to + (_to_nxt - _to);
3300 return r;
3301}
3302
3303__codecvt_utf16<wchar_t, false>::result
3304__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3305 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3306 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3307{
3308 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3309 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3310 const uint8_t* _frm_nxt = _frm;
3311 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3312 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3313 uint32_t* _to_nxt = _to;
3314 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3315 _Maxcode_, _Mode_);
3316 frm_nxt = frm + (_frm_nxt - _frm);
3317 to_nxt = to + (_to_nxt - _to);
3318 return r;
3319}
3320
3321__codecvt_utf16<wchar_t, false>::result
3322__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3323 extern_type* to, extern_type*, extern_type*& to_nxt) const
3324{
3325 to_nxt = to;
3326 return noconv;
3327}
3328
3329int
Howard Hinnantc9834542011-05-31 15:34:58 +00003330__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003331{
3332 return 0;
3333}
3334
3335bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003336__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003337{
3338 return false;
3339}
3340
3341int
3342__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3343 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3344{
3345 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3346 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3347 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3348}
3349
3350int
Howard Hinnantc9834542011-05-31 15:34:58 +00003351__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003352{
3353 if (_Mode_ & consume_header)
3354 return 6;
3355 return 4;
3356}
3357
3358// __codecvt_utf16<wchar_t, true>
3359
3360__codecvt_utf16<wchar_t, true>::result
3361__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3362 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3363 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3364{
3365 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3366 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3367 const uint32_t* _frm_nxt = _frm;
3368 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3369 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3370 uint8_t* _to_nxt = _to;
3371 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3372 _Maxcode_, _Mode_);
3373 frm_nxt = frm + (_frm_nxt - _frm);
3374 to_nxt = to + (_to_nxt - _to);
3375 return r;
3376}
3377
3378__codecvt_utf16<wchar_t, true>::result
3379__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3380 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3381 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3382{
3383 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3384 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3385 const uint8_t* _frm_nxt = _frm;
3386 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3387 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3388 uint32_t* _to_nxt = _to;
3389 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3390 _Maxcode_, _Mode_);
3391 frm_nxt = frm + (_frm_nxt - _frm);
3392 to_nxt = to + (_to_nxt - _to);
3393 return r;
3394}
3395
3396__codecvt_utf16<wchar_t, true>::result
3397__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3398 extern_type* to, extern_type*, extern_type*& to_nxt) const
3399{
3400 to_nxt = to;
3401 return noconv;
3402}
3403
3404int
Howard Hinnantc9834542011-05-31 15:34:58 +00003405__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003406{
3407 return 0;
3408}
3409
3410bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003411__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003412{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003413 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003414}
3415
3416int
3417__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3418 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3419{
3420 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3421 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3422 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3423}
3424
3425int
Howard Hinnantc9834542011-05-31 15:34:58 +00003426__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003427{
3428 if (_Mode_ & consume_header)
3429 return 6;
3430 return 4;
3431}
3432
3433// __codecvt_utf16<char16_t, false>
3434
3435__codecvt_utf16<char16_t, false>::result
3436__codecvt_utf16<char16_t, false>::do_out(state_type&,
3437 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3438 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3439{
3440 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3441 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3442 const uint16_t* _frm_nxt = _frm;
3443 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3444 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3445 uint8_t* _to_nxt = _to;
3446 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3447 _Maxcode_, _Mode_);
3448 frm_nxt = frm + (_frm_nxt - _frm);
3449 to_nxt = to + (_to_nxt - _to);
3450 return r;
3451}
3452
3453__codecvt_utf16<char16_t, false>::result
3454__codecvt_utf16<char16_t, false>::do_in(state_type&,
3455 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3456 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3457{
3458 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3459 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3460 const uint8_t* _frm_nxt = _frm;
3461 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3462 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3463 uint16_t* _to_nxt = _to;
3464 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3465 _Maxcode_, _Mode_);
3466 frm_nxt = frm + (_frm_nxt - _frm);
3467 to_nxt = to + (_to_nxt - _to);
3468 return r;
3469}
3470
3471__codecvt_utf16<char16_t, false>::result
3472__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3473 extern_type* to, extern_type*, extern_type*& to_nxt) const
3474{
3475 to_nxt = to;
3476 return noconv;
3477}
3478
3479int
Howard Hinnantc9834542011-05-31 15:34:58 +00003480__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003481{
3482 return 0;
3483}
3484
3485bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003486__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003487{
3488 return false;
3489}
3490
3491int
3492__codecvt_utf16<char16_t, false>::do_length(state_type&,
3493 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3494{
3495 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3496 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3497 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3498}
3499
3500int
Howard Hinnantc9834542011-05-31 15:34:58 +00003501__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003502{
3503 if (_Mode_ & consume_header)
3504 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003505 return 2;
3506}
3507
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003508// __codecvt_utf16<char16_t, true>
3509
3510__codecvt_utf16<char16_t, true>::result
3511__codecvt_utf16<char16_t, true>::do_out(state_type&,
3512 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3513 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3514{
3515 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3516 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3517 const uint16_t* _frm_nxt = _frm;
3518 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3519 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3520 uint8_t* _to_nxt = _to;
3521 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3522 _Maxcode_, _Mode_);
3523 frm_nxt = frm + (_frm_nxt - _frm);
3524 to_nxt = to + (_to_nxt - _to);
3525 return r;
3526}
3527
3528__codecvt_utf16<char16_t, true>::result
3529__codecvt_utf16<char16_t, true>::do_in(state_type&,
3530 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3531 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3532{
3533 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3534 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3535 const uint8_t* _frm_nxt = _frm;
3536 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3537 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3538 uint16_t* _to_nxt = _to;
3539 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3540 _Maxcode_, _Mode_);
3541 frm_nxt = frm + (_frm_nxt - _frm);
3542 to_nxt = to + (_to_nxt - _to);
3543 return r;
3544}
3545
3546__codecvt_utf16<char16_t, true>::result
3547__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3548 extern_type* to, extern_type*, extern_type*& to_nxt) const
3549{
3550 to_nxt = to;
3551 return noconv;
3552}
3553
3554int
Howard Hinnantc9834542011-05-31 15:34:58 +00003555__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003556{
3557 return 0;
3558}
3559
3560bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003561__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003562{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003563 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003564}
3565
3566int
3567__codecvt_utf16<char16_t, true>::do_length(state_type&,
3568 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3569{
3570 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3571 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3572 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3573}
3574
3575int
Howard Hinnantc9834542011-05-31 15:34:58 +00003576__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003577{
3578 if (_Mode_ & consume_header)
3579 return 4;
3580 return 2;
3581}
3582
3583// __codecvt_utf16<char32_t, false>
3584
3585__codecvt_utf16<char32_t, false>::result
3586__codecvt_utf16<char32_t, false>::do_out(state_type&,
3587 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3588 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3589{
3590 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3591 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3592 const uint32_t* _frm_nxt = _frm;
3593 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3594 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3595 uint8_t* _to_nxt = _to;
3596 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3597 _Maxcode_, _Mode_);
3598 frm_nxt = frm + (_frm_nxt - _frm);
3599 to_nxt = to + (_to_nxt - _to);
3600 return r;
3601}
3602
3603__codecvt_utf16<char32_t, false>::result
3604__codecvt_utf16<char32_t, false>::do_in(state_type&,
3605 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3606 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3607{
3608 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3609 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3610 const uint8_t* _frm_nxt = _frm;
3611 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3612 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3613 uint32_t* _to_nxt = _to;
3614 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3615 _Maxcode_, _Mode_);
3616 frm_nxt = frm + (_frm_nxt - _frm);
3617 to_nxt = to + (_to_nxt - _to);
3618 return r;
3619}
3620
3621__codecvt_utf16<char32_t, false>::result
3622__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3623 extern_type* to, extern_type*, extern_type*& to_nxt) const
3624{
3625 to_nxt = to;
3626 return noconv;
3627}
3628
3629int
Howard Hinnantc9834542011-05-31 15:34:58 +00003630__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003631{
3632 return 0;
3633}
3634
3635bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003636__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003637{
3638 return false;
3639}
3640
3641int
3642__codecvt_utf16<char32_t, false>::do_length(state_type&,
3643 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3644{
3645 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3646 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3647 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3648}
3649
3650int
Howard Hinnantc9834542011-05-31 15:34:58 +00003651__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003652{
3653 if (_Mode_ & consume_header)
3654 return 6;
3655 return 4;
3656}
3657
3658// __codecvt_utf16<char32_t, true>
3659
3660__codecvt_utf16<char32_t, true>::result
3661__codecvt_utf16<char32_t, true>::do_out(state_type&,
3662 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3663 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3664{
3665 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3666 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3667 const uint32_t* _frm_nxt = _frm;
3668 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3669 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3670 uint8_t* _to_nxt = _to;
3671 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3672 _Maxcode_, _Mode_);
3673 frm_nxt = frm + (_frm_nxt - _frm);
3674 to_nxt = to + (_to_nxt - _to);
3675 return r;
3676}
3677
3678__codecvt_utf16<char32_t, true>::result
3679__codecvt_utf16<char32_t, true>::do_in(state_type&,
3680 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3681 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3682{
3683 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3684 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3685 const uint8_t* _frm_nxt = _frm;
3686 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3687 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3688 uint32_t* _to_nxt = _to;
3689 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3690 _Maxcode_, _Mode_);
3691 frm_nxt = frm + (_frm_nxt - _frm);
3692 to_nxt = to + (_to_nxt - _to);
3693 return r;
3694}
3695
3696__codecvt_utf16<char32_t, true>::result
3697__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3698 extern_type* to, extern_type*, extern_type*& to_nxt) const
3699{
3700 to_nxt = to;
3701 return noconv;
3702}
3703
3704int
Howard Hinnantc9834542011-05-31 15:34:58 +00003705__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003706{
3707 return 0;
3708}
3709
3710bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003711__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003712{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003713 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003714}
3715
3716int
3717__codecvt_utf16<char32_t, true>::do_length(state_type&,
3718 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3719{
3720 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3721 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3722 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3723}
3724
3725int
Howard Hinnantc9834542011-05-31 15:34:58 +00003726__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003727{
3728 if (_Mode_ & consume_header)
3729 return 6;
3730 return 4;
3731}
3732
3733// __codecvt_utf8_utf16<wchar_t>
3734
3735__codecvt_utf8_utf16<wchar_t>::result
3736__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3737 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3738 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3739{
3740 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3741 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3742 const uint32_t* _frm_nxt = _frm;
3743 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3744 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3745 uint8_t* _to_nxt = _to;
3746 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3747 _Maxcode_, _Mode_);
3748 frm_nxt = frm + (_frm_nxt - _frm);
3749 to_nxt = to + (_to_nxt - _to);
3750 return r;
3751}
3752
3753__codecvt_utf8_utf16<wchar_t>::result
3754__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3755 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3756 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3757{
3758 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3759 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3760 const uint8_t* _frm_nxt = _frm;
3761 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3762 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3763 uint32_t* _to_nxt = _to;
3764 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3765 _Maxcode_, _Mode_);
3766 frm_nxt = frm + (_frm_nxt - _frm);
3767 to_nxt = to + (_to_nxt - _to);
3768 return r;
3769}
3770
3771__codecvt_utf8_utf16<wchar_t>::result
3772__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3773 extern_type* to, extern_type*, extern_type*& to_nxt) const
3774{
3775 to_nxt = to;
3776 return noconv;
3777}
3778
3779int
Howard Hinnantc9834542011-05-31 15:34:58 +00003780__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003781{
3782 return 0;
3783}
3784
3785bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003786__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003787{
3788 return false;
3789}
3790
3791int
3792__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3793 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3794{
3795 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3796 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3797 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3798}
3799
3800int
Howard Hinnantc9834542011-05-31 15:34:58 +00003801__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003802{
3803 if (_Mode_ & consume_header)
3804 return 7;
3805 return 4;
3806}
3807
3808// __codecvt_utf8_utf16<char16_t>
3809
3810__codecvt_utf8_utf16<char16_t>::result
3811__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3812 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3813 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3814{
3815 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3816 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3817 const uint16_t* _frm_nxt = _frm;
3818 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3819 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3820 uint8_t* _to_nxt = _to;
3821 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3822 _Maxcode_, _Mode_);
3823 frm_nxt = frm + (_frm_nxt - _frm);
3824 to_nxt = to + (_to_nxt - _to);
3825 return r;
3826}
3827
3828__codecvt_utf8_utf16<char16_t>::result
3829__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3830 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3831 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3832{
3833 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3834 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3835 const uint8_t* _frm_nxt = _frm;
3836 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3837 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3838 uint16_t* _to_nxt = _to;
3839 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3840 _Maxcode_, _Mode_);
3841 frm_nxt = frm + (_frm_nxt - _frm);
3842 to_nxt = to + (_to_nxt - _to);
3843 return r;
3844}
3845
3846__codecvt_utf8_utf16<char16_t>::result
3847__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3848 extern_type* to, extern_type*, extern_type*& to_nxt) const
3849{
3850 to_nxt = to;
3851 return noconv;
3852}
3853
3854int
Howard Hinnantc9834542011-05-31 15:34:58 +00003855__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003856{
3857 return 0;
3858}
3859
3860bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003861__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003862{
3863 return false;
3864}
3865
3866int
3867__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3868 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3869{
3870 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3871 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3872 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3873}
3874
3875int
Howard Hinnantc9834542011-05-31 15:34:58 +00003876__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003877{
3878 if (_Mode_ & consume_header)
3879 return 7;
3880 return 4;
3881}
3882
3883// __codecvt_utf8_utf16<char32_t>
3884
3885__codecvt_utf8_utf16<char32_t>::result
3886__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3887 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3888 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3889{
3890 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3891 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3892 const uint32_t* _frm_nxt = _frm;
3893 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3894 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3895 uint8_t* _to_nxt = _to;
3896 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3897 _Maxcode_, _Mode_);
3898 frm_nxt = frm + (_frm_nxt - _frm);
3899 to_nxt = to + (_to_nxt - _to);
3900 return r;
3901}
3902
3903__codecvt_utf8_utf16<char32_t>::result
3904__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3905 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3906 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3907{
3908 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3909 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3910 const uint8_t* _frm_nxt = _frm;
3911 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3912 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3913 uint32_t* _to_nxt = _to;
3914 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3915 _Maxcode_, _Mode_);
3916 frm_nxt = frm + (_frm_nxt - _frm);
3917 to_nxt = to + (_to_nxt - _to);
3918 return r;
3919}
3920
3921__codecvt_utf8_utf16<char32_t>::result
3922__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3923 extern_type* to, extern_type*, extern_type*& to_nxt) const
3924{
3925 to_nxt = to;
3926 return noconv;
3927}
3928
3929int
Howard Hinnantc9834542011-05-31 15:34:58 +00003930__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003931{
3932 return 0;
3933}
3934
3935bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003936__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003937{
3938 return false;
3939}
3940
3941int
3942__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3943 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3944{
3945 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3946 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3947 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3948}
3949
3950int
Howard Hinnantc9834542011-05-31 15:34:58 +00003951__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003952{
3953 if (_Mode_ & consume_header)
3954 return 7;
3955 return 4;
3956}
3957
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003958// __narrow_to_utf8<16>
3959
3960__narrow_to_utf8<16>::~__narrow_to_utf8()
3961{
3962}
3963
3964// __narrow_to_utf8<32>
3965
3966__narrow_to_utf8<32>::~__narrow_to_utf8()
3967{
3968}
3969
3970// __widen_from_utf8<16>
3971
3972__widen_from_utf8<16>::~__widen_from_utf8()
3973{
3974}
3975
3976// __widen_from_utf8<32>
3977
3978__widen_from_utf8<32>::~__widen_from_utf8()
3979{
3980}
3981
3982// numpunct<char> && numpunct<wchar_t>
3983
3984locale::id numpunct< char >::id;
3985locale::id numpunct<wchar_t>::id;
3986
3987numpunct<char>::numpunct(size_t refs)
3988 : locale::facet(refs),
3989 __decimal_point_('.'),
3990 __thousands_sep_(',')
3991{
3992}
3993
3994numpunct<wchar_t>::numpunct(size_t refs)
3995 : locale::facet(refs),
3996 __decimal_point_(L'.'),
3997 __thousands_sep_(L',')
3998{
3999}
4000
4001numpunct<char>::~numpunct()
4002{
4003}
4004
4005numpunct<wchar_t>::~numpunct()
4006{
4007}
4008
4009 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4010wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4011
4012 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4013wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4014
4015string numpunct< char >::do_grouping() const {return __grouping_;}
4016string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4017
4018 string numpunct< char >::do_truename() const {return "true";}
4019wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4020
4021 string numpunct< char >::do_falsename() const {return "false";}
4022wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4023
4024// numpunct_byname<char>
4025
4026numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4027 : numpunct<char>(refs)
4028{
4029 __init(nm);
4030}
4031
4032numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4033 : numpunct<char>(refs)
4034{
4035 __init(nm.c_str());
4036}
4037
4038numpunct_byname<char>::~numpunct_byname()
4039{
4040}
4041
4042void
4043numpunct_byname<char>::__init(const char* nm)
4044{
4045 if (strcmp(nm, "C") != 0)
4046 {
Howard Hinnantd318d492011-06-30 14:21:55 +00004047 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004048#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004049 if (loc == 0)
4050 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4051 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004052#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd318d492011-06-30 14:21:55 +00004053 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004054 if (*lc->decimal_point)
4055 __decimal_point_ = *lc->decimal_point;
4056 if (*lc->thousands_sep)
4057 __thousands_sep_ = *lc->thousands_sep;
4058 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004059 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004060 }
4061}
4062
4063// numpunct_byname<wchar_t>
4064
4065numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4066 : numpunct<wchar_t>(refs)
4067{
4068 __init(nm);
4069}
4070
4071numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4072 : numpunct<wchar_t>(refs)
4073{
4074 __init(nm.c_str());
4075}
4076
4077numpunct_byname<wchar_t>::~numpunct_byname()
4078{
4079}
4080
4081void
4082numpunct_byname<wchar_t>::__init(const char* nm)
4083{
4084 if (strcmp(nm, "C") != 0)
4085 {
Howard Hinnantd318d492011-06-30 14:21:55 +00004086 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004087#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004088 if (loc == 0)
4089 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4090 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004091#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd318d492011-06-30 14:21:55 +00004092 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004093 if (*lc->decimal_point)
4094 __decimal_point_ = *lc->decimal_point;
4095 if (*lc->thousands_sep)
4096 __thousands_sep_ = *lc->thousands_sep;
4097 __grouping_ = lc->grouping;
4098 // locallization for truename and falsename is not available
4099 }
4100}
4101
4102// num_get helpers
4103
4104int
4105__num_get_base::__get_base(ios_base& iob)
4106{
4107 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4108 if (__basefield == ios_base::oct)
4109 return 8;
4110 else if (__basefield == ios_base::hex)
4111 return 16;
4112 else if (__basefield == 0)
4113 return 0;
4114 return 10;
4115}
4116
4117const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4118
4119void
4120__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4121 ios_base::iostate& __err)
4122{
4123 if (__grouping.size() != 0)
4124 {
4125 reverse(__g, __g_end);
4126 const char* __ig = __grouping.data();
4127 const char* __eg = __ig + __grouping.size();
4128 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4129 {
4130 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4131 {
4132 if (*__ig != *__r)
4133 {
4134 __err = ios_base::failbit;
4135 return;
4136 }
4137 }
4138 if (__eg - __ig > 1)
4139 ++__ig;
4140 }
4141 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4142 {
4143 if (*__ig < __g_end[-1] || __g_end[-1] == 0)
4144 __err = ios_base::failbit;
4145 }
4146 }
4147}
4148
4149void
4150__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4151 ios_base::fmtflags __flags)
4152{
4153 if (__flags & ios_base::showpos)
4154 *__fmtp++ = '+';
4155 if (__flags & ios_base::showbase)
4156 *__fmtp++ = '#';
4157 while(*__len)
4158 *__fmtp++ = *__len++;
4159 if ((__flags & ios_base::basefield) == ios_base::oct)
4160 *__fmtp = 'o';
4161 else if ((__flags & ios_base::basefield) == ios_base::hex)
4162 {
4163 if (__flags & ios_base::uppercase)
4164 *__fmtp = 'X';
4165 else
4166 *__fmtp = 'x';
4167 }
4168 else if (__signd)
4169 *__fmtp = 'd';
4170 else
4171 *__fmtp = 'u';
4172}
4173
4174bool
4175__num_put_base::__format_float(char* __fmtp, const char* __len,
4176 ios_base::fmtflags __flags)
4177{
4178 bool specify_precision = true;
4179 if (__flags & ios_base::showpos)
4180 *__fmtp++ = '+';
4181 if (__flags & ios_base::showpoint)
4182 *__fmtp++ = '#';
4183 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4184 bool uppercase = __flags & ios_base::uppercase;
4185 if (floatfield == (ios_base::fixed | ios_base::scientific))
4186 specify_precision = false;
4187 else
4188 {
4189 *__fmtp++ = '.';
4190 *__fmtp++ = '*';
4191 }
4192 while(*__len)
4193 *__fmtp++ = *__len++;
4194 if (floatfield == ios_base::fixed)
4195 {
4196 if (uppercase)
4197 *__fmtp = 'F';
4198 else
4199 *__fmtp = 'f';
4200 }
4201 else if (floatfield == ios_base::scientific)
4202 {
4203 if (uppercase)
4204 *__fmtp = 'E';
4205 else
4206 *__fmtp = 'e';
4207 }
4208 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4209 {
4210 if (uppercase)
4211 *__fmtp = 'A';
4212 else
4213 *__fmtp = 'a';
4214 }
4215 else
4216 {
4217 if (uppercase)
4218 *__fmtp = 'G';
4219 else
4220 *__fmtp = 'g';
4221 }
4222 return specify_precision;
4223}
4224
4225char*
4226__num_put_base::__identify_padding(char* __nb, char* __ne,
4227 const ios_base& __iob)
4228{
4229 switch (__iob.flags() & ios_base::adjustfield)
4230 {
4231 case ios_base::internal:
4232 if (__nb[0] == '-' || __nb[0] == '+')
4233 return __nb+1;
4234 if (__ne - __nb >= 2 && __nb[0] == '0'
4235 && (__nb[1] == 'x' || __nb[1] == 'X'))
4236 return __nb+2;
4237 break;
4238 case ios_base::left:
4239 return __ne;
4240 case ios_base::right:
4241 default:
4242 break;
4243 }
4244 return __nb;
4245}
4246
4247// time_get
4248
4249static
4250string*
4251init_weeks()
4252{
4253 static string weeks[14];
4254 weeks[0] = "Sunday";
4255 weeks[1] = "Monday";
4256 weeks[2] = "Tuesday";
4257 weeks[3] = "Wednesday";
4258 weeks[4] = "Thursday";
4259 weeks[5] = "Friday";
4260 weeks[6] = "Saturday";
4261 weeks[7] = "Sun";
4262 weeks[8] = "Mon";
4263 weeks[9] = "Tue";
4264 weeks[10] = "Wed";
4265 weeks[11] = "Thu";
4266 weeks[12] = "Fri";
4267 weeks[13] = "Sat";
4268 return weeks;
4269}
4270
4271static
4272wstring*
4273init_wweeks()
4274{
4275 static wstring weeks[14];
4276 weeks[0] = L"Sunday";
4277 weeks[1] = L"Monday";
4278 weeks[2] = L"Tuesday";
4279 weeks[3] = L"Wednesday";
4280 weeks[4] = L"Thursday";
4281 weeks[5] = L"Friday";
4282 weeks[6] = L"Saturday";
4283 weeks[7] = L"Sun";
4284 weeks[8] = L"Mon";
4285 weeks[9] = L"Tue";
4286 weeks[10] = L"Wed";
4287 weeks[11] = L"Thu";
4288 weeks[12] = L"Fri";
4289 weeks[13] = L"Sat";
4290 return weeks;
4291}
4292
4293template <>
4294const string*
4295__time_get_c_storage<char>::__weeks() const
4296{
4297 static const string* weeks = init_weeks();
4298 return weeks;
4299}
4300
4301template <>
4302const wstring*
4303__time_get_c_storage<wchar_t>::__weeks() const
4304{
4305 static const wstring* weeks = init_wweeks();
4306 return weeks;
4307}
4308
4309static
4310string*
4311init_months()
4312{
4313 static string months[24];
4314 months[0] = "January";
4315 months[1] = "February";
4316 months[2] = "March";
4317 months[3] = "April";
4318 months[4] = "May";
4319 months[5] = "June";
4320 months[6] = "July";
4321 months[7] = "August";
4322 months[8] = "September";
4323 months[9] = "October";
4324 months[10] = "November";
4325 months[11] = "December";
4326 months[12] = "Jan";
4327 months[13] = "Feb";
4328 months[14] = "Mar";
4329 months[15] = "Apr";
4330 months[16] = "May";
4331 months[17] = "Jun";
4332 months[18] = "Jul";
4333 months[19] = "Aug";
4334 months[20] = "Sep";
4335 months[21] = "Oct";
4336 months[22] = "Nov";
4337 months[23] = "Dec";
4338 return months;
4339}
4340
4341static
4342wstring*
4343init_wmonths()
4344{
4345 static wstring months[24];
4346 months[0] = L"January";
4347 months[1] = L"February";
4348 months[2] = L"March";
4349 months[3] = L"April";
4350 months[4] = L"May";
4351 months[5] = L"June";
4352 months[6] = L"July";
4353 months[7] = L"August";
4354 months[8] = L"September";
4355 months[9] = L"October";
4356 months[10] = L"November";
4357 months[11] = L"December";
4358 months[12] = L"Jan";
4359 months[13] = L"Feb";
4360 months[14] = L"Mar";
4361 months[15] = L"Apr";
4362 months[16] = L"May";
4363 months[17] = L"Jun";
4364 months[18] = L"Jul";
4365 months[19] = L"Aug";
4366 months[20] = L"Sep";
4367 months[21] = L"Oct";
4368 months[22] = L"Nov";
4369 months[23] = L"Dec";
4370 return months;
4371}
4372
4373template <>
4374const string*
4375__time_get_c_storage<char>::__months() const
4376{
4377 static const string* months = init_months();
4378 return months;
4379}
4380
4381template <>
4382const wstring*
4383__time_get_c_storage<wchar_t>::__months() const
4384{
4385 static const wstring* months = init_wmonths();
4386 return months;
4387}
4388
4389static
4390string*
4391init_am_pm()
4392{
4393 static string am_pm[24];
4394 am_pm[0] = "AM";
4395 am_pm[1] = "PM";
4396 return am_pm;
4397}
4398
4399static
4400wstring*
4401init_wam_pm()
4402{
4403 static wstring am_pm[24];
4404 am_pm[0] = L"AM";
4405 am_pm[1] = L"PM";
4406 return am_pm;
4407}
4408
4409template <>
4410const string*
4411__time_get_c_storage<char>::__am_pm() const
4412{
4413 static const string* am_pm = init_am_pm();
4414 return am_pm;
4415}
4416
4417template <>
4418const wstring*
4419__time_get_c_storage<wchar_t>::__am_pm() const
4420{
4421 static const wstring* am_pm = init_wam_pm();
4422 return am_pm;
4423}
4424
4425template <>
4426const string&
4427__time_get_c_storage<char>::__x() const
4428{
4429 static string s("%m/%d/%y");
4430 return s;
4431}
4432
4433template <>
4434const wstring&
4435__time_get_c_storage<wchar_t>::__x() const
4436{
4437 static wstring s(L"%m/%d/%y");
4438 return s;
4439}
4440
4441template <>
4442const string&
4443__time_get_c_storage<char>::__X() const
4444{
4445 static string s("%H:%M:%S");
4446 return s;
4447}
4448
4449template <>
4450const wstring&
4451__time_get_c_storage<wchar_t>::__X() const
4452{
4453 static wstring s(L"%H:%M:%S");
4454 return s;
4455}
4456
4457template <>
4458const string&
4459__time_get_c_storage<char>::__c() const
4460{
4461 static string s("%a %b %d %H:%M:%S %Y");
4462 return s;
4463}
4464
4465template <>
4466const wstring&
4467__time_get_c_storage<wchar_t>::__c() const
4468{
4469 static wstring s(L"%a %b %d %H:%M:%S %Y");
4470 return s;
4471}
4472
4473template <>
4474const string&
4475__time_get_c_storage<char>::__r() const
4476{
4477 static string s("%I:%M:%S %p");
4478 return s;
4479}
4480
4481template <>
4482const wstring&
4483__time_get_c_storage<wchar_t>::__r() const
4484{
4485 static wstring s(L"%I:%M:%S %p");
4486 return s;
4487}
4488
4489// time_get_byname
4490
4491__time_get::__time_get(const char* nm)
4492 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4493{
Howard Hinnantd4444702010-08-11 17:04:31 +00004494#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004495 if (__loc_ == 0)
4496 throw runtime_error("time_get_byname"
4497 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004498#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004499}
4500
4501__time_get::__time_get(const string& nm)
4502 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4503{
Howard Hinnantd4444702010-08-11 17:04:31 +00004504#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004505 if (__loc_ == 0)
4506 throw runtime_error("time_get_byname"
4507 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004508#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004509}
4510
4511__time_get::~__time_get()
4512{
4513 freelocale(__loc_);
4514}
4515
4516template <>
4517string
4518__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4519{
4520 tm t;
4521 t.tm_sec = 59;
4522 t.tm_min = 55;
4523 t.tm_hour = 23;
4524 t.tm_mday = 31;
4525 t.tm_mon = 11;
4526 t.tm_year = 161;
4527 t.tm_wday = 6;
4528 t.tm_yday = 364;
4529 t.tm_isdst = -1;
4530 char buf[100];
4531 char f[3] = {0};
4532 f[0] = '%';
4533 f[1] = fmt;
4534 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4535 char* bb = buf;
4536 char* be = buf + n;
4537 string result;
4538 while (bb != be)
4539 {
4540 if (ct.is(ctype_base::space, *bb))
4541 {
4542 result.push_back(' ');
4543 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4544 ;
4545 continue;
4546 }
4547 char* w = bb;
4548 ios_base::iostate err = ios_base::goodbit;
4549 int i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4550 ct, err, false)
4551 - this->__weeks_;
4552 if (i < 14)
4553 {
4554 result.push_back('%');
4555 if (i < 7)
4556 result.push_back('A');
4557 else
4558 result.push_back('a');
4559 bb = w;
4560 continue;
4561 }
4562 w = bb;
4563 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4564 ct, err, false)
4565 - this->__months_;
4566 if (i < 24)
4567 {
4568 result.push_back('%');
4569 if (i < 12)
4570 result.push_back('B');
4571 else
4572 result.push_back('b');
4573 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4574 result.back() = 'm';
4575 bb = w;
4576 continue;
4577 }
4578 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4579 {
4580 w = bb;
4581 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4582 ct, err, false) - this->__am_pm_;
4583 if (i < 2)
4584 {
4585 result.push_back('%');
4586 result.push_back('p');
4587 bb = w;
4588 continue;
4589 }
4590 }
4591 w = bb;
4592 if (ct.is(ctype_base::digit, *bb))
4593 {
4594 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4595 {
4596 case 6:
4597 result.push_back('%');
4598 result.push_back('w');
4599 break;
4600 case 7:
4601 result.push_back('%');
4602 result.push_back('u');
4603 break;
4604 case 11:
4605 result.push_back('%');
4606 result.push_back('I');
4607 break;
4608 case 12:
4609 result.push_back('%');
4610 result.push_back('m');
4611 break;
4612 case 23:
4613 result.push_back('%');
4614 result.push_back('H');
4615 break;
4616 case 31:
4617 result.push_back('%');
4618 result.push_back('d');
4619 break;
4620 case 55:
4621 result.push_back('%');
4622 result.push_back('M');
4623 break;
4624 case 59:
4625 result.push_back('%');
4626 result.push_back('S');
4627 break;
4628 case 61:
4629 result.push_back('%');
4630 result.push_back('y');
4631 break;
4632 case 364:
4633 result.push_back('%');
4634 result.push_back('j');
4635 break;
4636 case 2061:
4637 result.push_back('%');
4638 result.push_back('Y');
4639 break;
4640 default:
4641 for (; w != bb; ++w)
4642 result.push_back(*w);
4643 break;
4644 }
4645 continue;
4646 }
4647 if (*bb == '%')
4648 {
4649 result.push_back('%');
4650 result.push_back('%');
4651 ++bb;
4652 continue;
4653 }
4654 result.push_back(*bb);
4655 ++bb;
4656 }
4657 return result;
4658}
4659
4660template <>
4661wstring
4662__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4663{
4664 tm t;
4665 t.tm_sec = 59;
4666 t.tm_min = 55;
4667 t.tm_hour = 23;
4668 t.tm_mday = 31;
4669 t.tm_mon = 11;
4670 t.tm_year = 161;
4671 t.tm_wday = 6;
4672 t.tm_yday = 364;
4673 t.tm_isdst = -1;
4674 char buf[100];
4675 char f[3] = {0};
4676 f[0] = '%';
4677 f[1] = fmt;
4678 size_t be = strftime_l(buf, 100, f, &t, __loc_);
4679 wchar_t wbuf[100];
4680 wchar_t* wbb = wbuf;
4681 mbstate_t mb = {0};
4682 const char* bb = buf;
Howard Hinnantd318d492011-06-30 14:21:55 +00004683 size_t i = with_locale::mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004684 if (i == -1)
4685 __throw_runtime_error("locale not supported");
4686 wchar_t* wbe = wbb + i;
4687 wstring result;
4688 while (wbb != wbe)
4689 {
4690 if (ct.is(ctype_base::space, *wbb))
4691 {
4692 result.push_back(L' ');
4693 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4694 ;
4695 continue;
4696 }
4697 wchar_t* w = wbb;
4698 ios_base::iostate err = ios_base::goodbit;
4699 int i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4700 ct, err, false)
4701 - this->__weeks_;
4702 if (i < 14)
4703 {
4704 result.push_back(L'%');
4705 if (i < 7)
4706 result.push_back(L'A');
4707 else
4708 result.push_back(L'a');
4709 wbb = w;
4710 continue;
4711 }
4712 w = wbb;
4713 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4714 ct, err, false)
4715 - this->__months_;
4716 if (i < 24)
4717 {
4718 result.push_back(L'%');
4719 if (i < 12)
4720 result.push_back(L'B');
4721 else
4722 result.push_back(L'b');
4723 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4724 result.back() = L'm';
4725 wbb = w;
4726 continue;
4727 }
4728 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4729 {
4730 w = wbb;
4731 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4732 ct, err, false) - this->__am_pm_;
4733 if (i < 2)
4734 {
4735 result.push_back(L'%');
4736 result.push_back(L'p');
4737 wbb = w;
4738 continue;
4739 }
4740 }
4741 w = wbb;
4742 if (ct.is(ctype_base::digit, *wbb))
4743 {
4744 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4745 {
4746 case 6:
4747 result.push_back(L'%');
4748 result.push_back(L'w');
4749 break;
4750 case 7:
4751 result.push_back(L'%');
4752 result.push_back(L'u');
4753 break;
4754 case 11:
4755 result.push_back(L'%');
4756 result.push_back(L'I');
4757 break;
4758 case 12:
4759 result.push_back(L'%');
4760 result.push_back(L'm');
4761 break;
4762 case 23:
4763 result.push_back(L'%');
4764 result.push_back(L'H');
4765 break;
4766 case 31:
4767 result.push_back(L'%');
4768 result.push_back(L'd');
4769 break;
4770 case 55:
4771 result.push_back(L'%');
4772 result.push_back(L'M');
4773 break;
4774 case 59:
4775 result.push_back(L'%');
4776 result.push_back(L'S');
4777 break;
4778 case 61:
4779 result.push_back(L'%');
4780 result.push_back(L'y');
4781 break;
4782 case 364:
4783 result.push_back(L'%');
4784 result.push_back(L'j');
4785 break;
4786 case 2061:
4787 result.push_back(L'%');
4788 result.push_back(L'Y');
4789 break;
4790 default:
4791 for (; w != wbb; ++w)
4792 result.push_back(*w);
4793 break;
4794 }
4795 continue;
4796 }
4797 if (ct.narrow(*wbb, 0) == '%')
4798 {
4799 result.push_back(L'%');
4800 result.push_back(L'%');
4801 ++wbb;
4802 continue;
4803 }
4804 result.push_back(*wbb);
4805 ++wbb;
4806 }
4807 return result;
4808}
4809
4810template <>
4811void
4812__time_get_storage<char>::init(const ctype<char>& ct)
4813{
4814 tm t;
4815 char buf[100];
4816 // __weeks_
4817 for (int i = 0; i < 7; ++i)
4818 {
4819 t.tm_wday = i;
4820 strftime_l(buf, 100, "%A", &t, __loc_);
4821 __weeks_[i] = buf;
4822 strftime_l(buf, 100, "%a", &t, __loc_);
4823 __weeks_[i+7] = buf;
4824 }
4825 // __months_
4826 for (int i = 0; i < 12; ++i)
4827 {
4828 t.tm_mon = i;
4829 strftime_l(buf, 100, "%B", &t, __loc_);
4830 __months_[i] = buf;
4831 strftime_l(buf, 100, "%b", &t, __loc_);
4832 __months_[i+12] = buf;
4833 }
4834 // __am_pm_
4835 t.tm_hour = 1;
4836 strftime_l(buf, 100, "%p", &t, __loc_);
4837 __am_pm_[0] = buf;
4838 t.tm_hour = 13;
4839 strftime_l(buf, 100, "%p", &t, __loc_);
4840 __am_pm_[1] = buf;
4841 __c_ = __analyze('c', ct);
4842 __r_ = __analyze('r', ct);
4843 __x_ = __analyze('x', ct);
4844 __X_ = __analyze('X', ct);
4845}
4846
4847template <>
4848void
4849__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4850{
4851 tm t = {0};
4852 char buf[100];
4853 size_t be;
4854 wchar_t wbuf[100];
4855 wchar_t* wbe;
4856 mbstate_t mb = {0};
4857 // __weeks_
4858 for (int i = 0; i < 7; ++i)
4859 {
4860 t.tm_wday = i;
4861 be = strftime_l(buf, 100, "%A", &t, __loc_);
4862 mb = mbstate_t();
4863 const char* bb = buf;
Howard Hinnantd318d492011-06-30 14:21:55 +00004864 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004865 if (j == -1)
4866 __throw_runtime_error("locale not supported");
4867 wbe = wbuf + j;
4868 __weeks_[i].assign(wbuf, wbe);
4869 be = strftime_l(buf, 100, "%a", &t, __loc_);
4870 mb = mbstate_t();
4871 bb = buf;
Howard Hinnantd318d492011-06-30 14:21:55 +00004872 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004873 if (j == -1)
4874 __throw_runtime_error("locale not supported");
4875 wbe = wbuf + j;
4876 __weeks_[i+7].assign(wbuf, wbe);
4877 }
4878 // __months_
4879 for (int i = 0; i < 12; ++i)
4880 {
4881 t.tm_mon = i;
4882 be = strftime_l(buf, 100, "%B", &t, __loc_);
4883 mb = mbstate_t();
4884 const char* bb = buf;
Howard Hinnantd318d492011-06-30 14:21:55 +00004885 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004886 if (j == -1)
4887 __throw_runtime_error("locale not supported");
4888 wbe = wbuf + j;
4889 __months_[i].assign(wbuf, wbe);
4890 be = strftime_l(buf, 100, "%b", &t, __loc_);
4891 mb = mbstate_t();
4892 bb = buf;
Howard Hinnantd318d492011-06-30 14:21:55 +00004893 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004894 if (j == -1)
4895 __throw_runtime_error("locale not supported");
4896 wbe = wbuf + j;
4897 __months_[i+12].assign(wbuf, wbe);
4898 }
4899 // __am_pm_
4900 t.tm_hour = 1;
4901 be = strftime_l(buf, 100, "%p", &t, __loc_);
4902 mb = mbstate_t();
4903 const char* bb = buf;
Howard Hinnantd318d492011-06-30 14:21:55 +00004904 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004905 if (j == -1)
4906 __throw_runtime_error("locale not supported");
4907 wbe = wbuf + j;
4908 __am_pm_[0].assign(wbuf, wbe);
4909 t.tm_hour = 13;
4910 be = strftime_l(buf, 100, "%p", &t, __loc_);
4911 mb = mbstate_t();
4912 bb = buf;
Howard Hinnantd318d492011-06-30 14:21:55 +00004913 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004914 if (j == -1)
4915 __throw_runtime_error("locale not supported");
4916 wbe = wbuf + j;
4917 __am_pm_[1].assign(wbuf, wbe);
4918 __c_ = __analyze('c', ct);
4919 __r_ = __analyze('r', ct);
4920 __x_ = __analyze('x', ct);
4921 __X_ = __analyze('X', ct);
4922}
4923
4924template <class CharT>
4925struct _LIBCPP_HIDDEN __time_get_temp
4926 : public ctype_byname<CharT>
4927{
4928 explicit __time_get_temp(const char* nm)
4929 : ctype_byname<CharT>(nm, 1) {}
4930 explicit __time_get_temp(const string& nm)
4931 : ctype_byname<CharT>(nm, 1) {}
4932};
4933
4934template <>
4935__time_get_storage<char>::__time_get_storage(const char* __nm)
4936 : __time_get(__nm)
4937{
4938 const __time_get_temp<char> ct(__nm);
4939 init(ct);
4940}
4941
4942template <>
4943__time_get_storage<char>::__time_get_storage(const string& __nm)
4944 : __time_get(__nm)
4945{
4946 const __time_get_temp<char> ct(__nm);
4947 init(ct);
4948}
4949
4950template <>
4951__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
4952 : __time_get(__nm)
4953{
4954 const __time_get_temp<wchar_t> ct(__nm);
4955 init(ct);
4956}
4957
4958template <>
4959__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
4960 : __time_get(__nm)
4961{
4962 const __time_get_temp<wchar_t> ct(__nm);
4963 init(ct);
4964}
4965
4966template <>
4967time_base::dateorder
4968__time_get_storage<char>::__do_date_order() const
4969{
4970 unsigned i;
4971 for (i = 0; i < __x_.size(); ++i)
4972 if (__x_[i] == '%')
4973 break;
4974 ++i;
4975 switch (__x_[i])
4976 {
4977 case 'y':
4978 case 'Y':
4979 for (++i; i < __x_.size(); ++i)
4980 if (__x_[i] == '%')
4981 break;
4982 if (i == __x_.size())
4983 break;
4984 ++i;
4985 switch (__x_[i])
4986 {
4987 case 'm':
4988 for (++i; i < __x_.size(); ++i)
4989 if (__x_[i] == '%')
4990 break;
4991 if (i == __x_.size())
4992 break;
4993 ++i;
4994 if (__x_[i] == 'd')
4995 return time_base::ymd;
4996 break;
4997 case 'd':
4998 for (++i; i < __x_.size(); ++i)
4999 if (__x_[i] == '%')
5000 break;
5001 if (i == __x_.size())
5002 break;
5003 ++i;
5004 if (__x_[i] == 'm')
5005 return time_base::ydm;
5006 break;
5007 }
5008 break;
5009 case 'm':
5010 for (++i; i < __x_.size(); ++i)
5011 if (__x_[i] == '%')
5012 break;
5013 if (i == __x_.size())
5014 break;
5015 ++i;
5016 if (__x_[i] == 'd')
5017 {
5018 for (++i; i < __x_.size(); ++i)
5019 if (__x_[i] == '%')
5020 break;
5021 if (i == __x_.size())
5022 break;
5023 ++i;
5024 if (__x_[i] == 'y' || __x_[i] == 'Y')
5025 return time_base::mdy;
5026 break;
5027 }
5028 break;
5029 case 'd':
5030 for (++i; i < __x_.size(); ++i)
5031 if (__x_[i] == '%')
5032 break;
5033 if (i == __x_.size())
5034 break;
5035 ++i;
5036 if (__x_[i] == 'm')
5037 {
5038 for (++i; i < __x_.size(); ++i)
5039 if (__x_[i] == '%')
5040 break;
5041 if (i == __x_.size())
5042 break;
5043 ++i;
5044 if (__x_[i] == 'y' || __x_[i] == 'Y')
5045 return time_base::dmy;
5046 break;
5047 }
5048 break;
5049 }
5050 return time_base::no_order;
5051}
5052
5053template <>
5054time_base::dateorder
5055__time_get_storage<wchar_t>::__do_date_order() const
5056{
5057 unsigned i;
5058 for (i = 0; i < __x_.size(); ++i)
5059 if (__x_[i] == L'%')
5060 break;
5061 ++i;
5062 switch (__x_[i])
5063 {
5064 case L'y':
5065 case L'Y':
5066 for (++i; i < __x_.size(); ++i)
5067 if (__x_[i] == L'%')
5068 break;
5069 if (i == __x_.size())
5070 break;
5071 ++i;
5072 switch (__x_[i])
5073 {
5074 case L'm':
5075 for (++i; i < __x_.size(); ++i)
5076 if (__x_[i] == L'%')
5077 break;
5078 if (i == __x_.size())
5079 break;
5080 ++i;
5081 if (__x_[i] == L'd')
5082 return time_base::ymd;
5083 break;
5084 case L'd':
5085 for (++i; i < __x_.size(); ++i)
5086 if (__x_[i] == L'%')
5087 break;
5088 if (i == __x_.size())
5089 break;
5090 ++i;
5091 if (__x_[i] == L'm')
5092 return time_base::ydm;
5093 break;
5094 }
5095 break;
5096 case L'm':
5097 for (++i; i < __x_.size(); ++i)
5098 if (__x_[i] == L'%')
5099 break;
5100 if (i == __x_.size())
5101 break;
5102 ++i;
5103 if (__x_[i] == L'd')
5104 {
5105 for (++i; i < __x_.size(); ++i)
5106 if (__x_[i] == L'%')
5107 break;
5108 if (i == __x_.size())
5109 break;
5110 ++i;
5111 if (__x_[i] == L'y' || __x_[i] == L'Y')
5112 return time_base::mdy;
5113 break;
5114 }
5115 break;
5116 case L'd':
5117 for (++i; i < __x_.size(); ++i)
5118 if (__x_[i] == L'%')
5119 break;
5120 if (i == __x_.size())
5121 break;
5122 ++i;
5123 if (__x_[i] == L'm')
5124 {
5125 for (++i; i < __x_.size(); ++i)
5126 if (__x_[i] == L'%')
5127 break;
5128 if (i == __x_.size())
5129 break;
5130 ++i;
5131 if (__x_[i] == L'y' || __x_[i] == L'Y')
5132 return time_base::dmy;
5133 break;
5134 }
5135 break;
5136 }
5137 return time_base::no_order;
5138}
5139
5140// time_put
5141
5142__time_put::__time_put(const char* nm)
5143 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5144{
Howard Hinnantd4444702010-08-11 17:04:31 +00005145#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005146 if (__loc_ == 0)
5147 throw runtime_error("time_put_byname"
5148 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005149#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005150}
5151
5152__time_put::__time_put(const string& nm)
5153 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5154{
Howard Hinnantd4444702010-08-11 17:04:31 +00005155#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005156 if (__loc_ == 0)
5157 throw runtime_error("time_put_byname"
5158 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005159#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005160}
5161
5162__time_put::~__time_put()
5163{
5164 if (__loc_)
5165 freelocale(__loc_);
5166}
5167
5168void
5169__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5170 char __fmt, char __mod) const
5171{
5172 char fmt[] = {'%', __fmt, __mod, 0};
5173 if (__mod != 0)
5174 swap(fmt[1], fmt[2]);
5175 size_t n = strftime_l(__nb, __ne-__nb, fmt, __tm, __loc_);
5176 __ne = __nb + n;
5177}
5178
5179void
5180__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5181 char __fmt, char __mod) const
5182{
5183 char __nar[100];
5184 char* __ne = __nar + 100;
5185 __do_put(__nar, __ne, __tm, __fmt, __mod);
5186 mbstate_t mb = {0};
5187 const char* __nb = __nar;
Howard Hinnantd318d492011-06-30 14:21:55 +00005188 size_t j = with_locale::mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005189 if (j == -1)
5190 __throw_runtime_error("locale not supported");
5191 __we = __wb + j;
5192}
5193
5194// moneypunct_byname
5195
5196static
5197void
5198__init_pat(money_base::pattern& pat, char cs_precedes, char sep_by_space, char sign_posn)
5199{
5200 const char sign = static_cast<char>(money_base::sign);
5201 const char space = static_cast<char>(money_base::space);
5202 const char none = static_cast<char>(money_base::none);
5203 const char symbol = static_cast<char>(money_base::symbol);
5204 const char value = static_cast<char>(money_base::value);
5205 switch (cs_precedes)
5206 {
5207 case 0:
5208 switch (sign_posn)
5209 {
5210 case 0:
5211 pat.field[0] = sign;
5212 pat.field[1] = value;
5213 pat.field[3] = symbol;
5214 switch (sep_by_space)
5215 {
5216 case 0:
5217 pat.field[2] = none;
5218 return;
5219 case 1:
5220 case 2:
5221 pat.field[2] = space;
5222 return;
5223 default:
5224 break;
5225 }
5226 break;
5227 case 1:
5228 pat.field[0] = sign;
5229 pat.field[3] = symbol;
5230 switch (sep_by_space)
5231 {
5232 case 0:
5233 pat.field[1] = value;
5234 pat.field[2] = none;
5235 return;
5236 case 1:
5237 pat.field[1] = value;
5238 pat.field[2] = space;
5239 return;
5240 case 2:
5241 pat.field[1] = space;
5242 pat.field[2] = value;
5243 return;
5244 default:
5245 break;
5246 }
5247 break;
5248 case 2:
5249 pat.field[0] = value;
5250 pat.field[3] = sign;
5251 switch (sep_by_space)
5252 {
5253 case 0:
5254 pat.field[1] = none;
5255 pat.field[2] = symbol;
5256 return;
5257 case 1:
5258 pat.field[1] = space;
5259 pat.field[2] = symbol;
5260 return;
5261 case 2:
5262 pat.field[1] = symbol;
5263 pat.field[2] = space;
5264 return;
5265 default:
5266 break;
5267 }
5268 break;
5269 case 3:
5270 pat.field[0] = value;
5271 pat.field[3] = symbol;
5272 switch (sep_by_space)
5273 {
5274 case 0:
5275 pat.field[1] = none;
5276 pat.field[2] = sign;
5277 return;
5278 case 1:
5279 pat.field[1] = space;
5280 pat.field[2] = sign;
5281 return;
5282 case 2:
5283 pat.field[1] = sign;
5284 pat.field[2] = space;
5285 return;
5286 default:
5287 break;
5288 }
5289 break;
5290 case 4:
5291 pat.field[0] = value;
5292 pat.field[3] = sign;
5293 switch (sep_by_space)
5294 {
5295 case 0:
5296 pat.field[1] = none;
5297 pat.field[2] = symbol;
5298 return;
5299 case 1:
5300 pat.field[1] = space;
5301 pat.field[2] = symbol;
5302 return;
5303 case 2:
5304 pat.field[1] = symbol;
5305 pat.field[2] = space;
5306 return;
5307 default:
5308 break;
5309 }
5310 break;
5311 default:
5312 break;
5313 }
5314 break;
5315 case 1:
5316 switch (sign_posn)
5317 {
5318 case 0:
5319 pat.field[0] = sign;
5320 pat.field[1] = symbol;
5321 pat.field[3] = value;
5322 switch (sep_by_space)
5323 {
5324 case 0:
5325 pat.field[2] = none;
5326 return;
5327 case 1:
5328 case 2:
5329 pat.field[2] = space;
5330 return;
5331 default:
5332 break;
5333 }
5334 break;
5335 case 1:
5336 pat.field[0] = sign;
5337 pat.field[3] = value;
5338 switch (sep_by_space)
5339 {
5340 case 0:
5341 pat.field[1] = symbol;
5342 pat.field[2] = none;
5343 return;
5344 case 1:
5345 pat.field[1] = symbol;
5346 pat.field[2] = space;
5347 return;
5348 case 2:
5349 pat.field[1] = space;
5350 pat.field[2] = symbol;
5351 return;
5352 default:
5353 break;
5354 }
5355 break;
5356 case 2:
5357 pat.field[0] = symbol;
5358 pat.field[3] = sign;
5359 switch (sep_by_space)
5360 {
5361 case 0:
5362 pat.field[1] = none;
5363 pat.field[2] = value;
5364 return;
5365 case 1:
5366 pat.field[1] = space;
5367 pat.field[2] = value;
5368 return;
5369 case 2:
5370 pat.field[1] = value;
5371 pat.field[2] = space;
5372 return;
5373 default:
5374 break;
5375 }
5376 break;
5377 case 3:
5378 pat.field[0] = sign;
5379 pat.field[3] = value;
5380 switch (sep_by_space)
5381 {
5382 case 0:
5383 pat.field[1] = symbol;
5384 pat.field[2] = none;
5385 return;
5386 case 1:
5387 pat.field[1] = symbol;
5388 pat.field[2] = space;
5389 return;
5390 case 2:
5391 pat.field[1] = space;
5392 pat.field[2] = symbol;
5393 return;
5394 default:
5395 break;
5396 }
5397 break;
5398 case 4:
5399 pat.field[0] = symbol;
5400 pat.field[3] = value;
5401 switch (sep_by_space)
5402 {
5403 case 0:
5404 pat.field[1] = sign;
5405 pat.field[2] = none;
5406 return;
5407 case 1:
5408 pat.field[1] = sign;
5409 pat.field[2] = space;
5410 return;
5411 case 2:
5412 pat.field[1] = space;
5413 pat.field[2] = sign;
5414 return;
5415 default:
5416 break;
5417 }
5418 break;
5419 default:
5420 break;
5421 }
5422 break;
5423 default:
5424 break;
5425 }
5426 pat.field[0] = symbol;
5427 pat.field[1] = sign;
5428 pat.field[2] = none;
5429 pat.field[3] = value;
5430}
5431
5432template<>
5433void
5434moneypunct_byname<char, false>::init(const char* nm)
5435{
5436 typedef moneypunct<char, false> base;
Howard Hinnantd318d492011-06-30 14:21:55 +00005437 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005438#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005439 if (loc == 0)
5440 throw runtime_error("moneypunct_byname"
5441 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005442#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd318d492011-06-30 14:21:55 +00005443 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005444 if (*lc->mon_decimal_point)
5445 __decimal_point_ = *lc->mon_decimal_point;
5446 else
5447 __decimal_point_ = base::do_decimal_point();
5448 if (*lc->mon_thousands_sep)
5449 __thousands_sep_ = *lc->mon_thousands_sep;
5450 else
5451 __thousands_sep_ = base::do_thousands_sep();
5452 __grouping_ = lc->mon_grouping;
5453 __curr_symbol_ = lc->currency_symbol;
5454 if (lc->frac_digits != CHAR_MAX)
5455 __frac_digits_ = lc->frac_digits;
5456 else
5457 __frac_digits_ = base::do_frac_digits();
5458 if (lc->p_sign_posn == 0)
5459 __positive_sign_ = "()";
5460 else
5461 __positive_sign_ = lc->positive_sign;
5462 if (lc->n_sign_posn == 0)
5463 __negative_sign_ = "()";
5464 else
5465 __negative_sign_ = lc->negative_sign;
5466 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5467 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5468}
5469
5470template<>
5471void
5472moneypunct_byname<char, true>::init(const char* nm)
5473{
5474 typedef moneypunct<char, true> base;
Howard Hinnantd318d492011-06-30 14:21:55 +00005475 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005476#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005477 if (loc == 0)
5478 throw runtime_error("moneypunct_byname"
5479 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005480#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd318d492011-06-30 14:21:55 +00005481 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005482 if (*lc->mon_decimal_point)
5483 __decimal_point_ = *lc->mon_decimal_point;
5484 else
5485 __decimal_point_ = base::do_decimal_point();
5486 if (*lc->mon_thousands_sep)
5487 __thousands_sep_ = *lc->mon_thousands_sep;
5488 else
5489 __thousands_sep_ = base::do_thousands_sep();
5490 __grouping_ = lc->mon_grouping;
5491 __curr_symbol_ = lc->int_curr_symbol;
5492 if (lc->int_frac_digits != CHAR_MAX)
5493 __frac_digits_ = lc->int_frac_digits;
5494 else
5495 __frac_digits_ = base::do_frac_digits();
5496 if (lc->int_p_sign_posn == 0)
5497 __positive_sign_ = "()";
5498 else
5499 __positive_sign_ = lc->positive_sign;
5500 if (lc->int_n_sign_posn == 0)
5501 __negative_sign_ = "()";
5502 else
5503 __negative_sign_ = lc->negative_sign;
5504 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5505 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
5506}
5507
5508template<>
5509void
5510moneypunct_byname<wchar_t, false>::init(const char* nm)
5511{
5512 typedef moneypunct<wchar_t, false> base;
Howard Hinnantd318d492011-06-30 14:21:55 +00005513 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005514#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005515 if (loc == 0)
5516 throw runtime_error("moneypunct_byname"
5517 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005518#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd318d492011-06-30 14:21:55 +00005519 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005520 if (*lc->mon_decimal_point)
5521 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5522 else
5523 __decimal_point_ = base::do_decimal_point();
5524 if (*lc->mon_thousands_sep)
5525 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5526 else
5527 __thousands_sep_ = base::do_thousands_sep();
5528 __grouping_ = lc->mon_grouping;
5529 wchar_t wbuf[100];
5530 mbstate_t mb = {0};
5531 const char* bb = lc->currency_symbol;
Howard Hinnantd318d492011-06-30 14:21:55 +00005532 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005533 if (j == -1)
5534 __throw_runtime_error("locale not supported");
5535 wchar_t* wbe = wbuf + j;
5536 __curr_symbol_.assign(wbuf, wbe);
5537 if (lc->frac_digits != CHAR_MAX)
5538 __frac_digits_ = lc->frac_digits;
5539 else
5540 __frac_digits_ = base::do_frac_digits();
5541 if (lc->p_sign_posn == 0)
5542 __positive_sign_ = L"()";
5543 else
5544 {
5545 mb = mbstate_t();
5546 bb = lc->positive_sign;
Howard Hinnantd318d492011-06-30 14:21:55 +00005547 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005548 if (j == -1)
5549 __throw_runtime_error("locale not supported");
5550 wbe = wbuf + j;
5551 __positive_sign_.assign(wbuf, wbe);
5552 }
5553 if (lc->n_sign_posn == 0)
5554 __negative_sign_ = L"()";
5555 else
5556 {
5557 mb = mbstate_t();
5558 bb = lc->negative_sign;
Howard Hinnantd318d492011-06-30 14:21:55 +00005559 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005560 if (j == -1)
5561 __throw_runtime_error("locale not supported");
5562 wbe = wbuf + j;
5563 __negative_sign_.assign(wbuf, wbe);
5564 }
5565 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5566 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5567}
5568
5569template<>
5570void
5571moneypunct_byname<wchar_t, true>::init(const char* nm)
5572{
5573 typedef moneypunct<wchar_t, true> base;
Howard Hinnantd318d492011-06-30 14:21:55 +00005574 locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005575#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005576 if (loc == 0)
5577 throw runtime_error("moneypunct_byname"
5578 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005579#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd318d492011-06-30 14:21:55 +00005580 lconv* lc = with_locale::localeconv_l(loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005581 if (*lc->mon_decimal_point)
5582 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5583 else
5584 __decimal_point_ = base::do_decimal_point();
5585 if (*lc->mon_thousands_sep)
5586 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5587 else
5588 __thousands_sep_ = base::do_thousands_sep();
5589 __grouping_ = lc->mon_grouping;
5590 wchar_t wbuf[100];
5591 mbstate_t mb = {0};
5592 const char* bb = lc->int_curr_symbol;
Howard Hinnantd318d492011-06-30 14:21:55 +00005593 size_t j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005594 if (j == -1)
5595 __throw_runtime_error("locale not supported");
5596 wchar_t* wbe = wbuf + j;
5597 __curr_symbol_.assign(wbuf, wbe);
5598 if (lc->int_frac_digits != CHAR_MAX)
5599 __frac_digits_ = lc->int_frac_digits;
5600 else
5601 __frac_digits_ = base::do_frac_digits();
5602 if (lc->int_p_sign_posn == 0)
5603 __positive_sign_ = L"()";
5604 else
5605 {
5606 mb = mbstate_t();
5607 bb = lc->positive_sign;
Howard Hinnantd318d492011-06-30 14:21:55 +00005608 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005609 if (j == -1)
5610 __throw_runtime_error("locale not supported");
5611 wbe = wbuf + j;
5612 __positive_sign_.assign(wbuf, wbe);
5613 }
5614 if (lc->int_n_sign_posn == 0)
5615 __negative_sign_ = L"()";
5616 else
5617 {
5618 mb = mbstate_t();
5619 bb = lc->negative_sign;
Howard Hinnantd318d492011-06-30 14:21:55 +00005620 j = with_locale::mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005621 if (j == -1)
5622 __throw_runtime_error("locale not supported");
5623 wbe = wbuf + j;
5624 __negative_sign_.assign(wbuf, wbe);
5625 }
5626 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5627 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
5628}
5629
5630void __do_nothing(void*) {}
5631
5632void __throw_runtime_error(const char* msg)
5633{
Howard Hinnantd4444702010-08-11 17:04:31 +00005634#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005635 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00005636#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005637}
5638
5639template class collate<char>;
5640template class collate<wchar_t>;
5641
5642template class num_get<char>;
5643template class num_get<wchar_t>;
5644
5645template class __num_get<char>;
5646template class __num_get<wchar_t>;
5647
5648template class num_put<char>;
5649template class num_put<wchar_t>;
5650
5651template class __num_put<char>;
5652template class __num_put<wchar_t>;
5653
5654template class time_get<char>;
5655template class time_get<wchar_t>;
5656
5657template class time_get_byname<char>;
5658template class time_get_byname<wchar_t>;
5659
5660template class time_put<char>;
5661template class time_put<wchar_t>;
5662
5663template class time_put_byname<char>;
5664template class time_put_byname<wchar_t>;
5665
5666template class moneypunct<char, false>;
5667template class moneypunct<char, true>;
5668template class moneypunct<wchar_t, false>;
5669template class moneypunct<wchar_t, true>;
5670
5671template class moneypunct_byname<char, false>;
5672template class moneypunct_byname<char, true>;
5673template class moneypunct_byname<wchar_t, false>;
5674template class moneypunct_byname<wchar_t, true>;
5675
5676template class money_get<char>;
5677template class money_get<wchar_t>;
5678
5679template class __money_get<char>;
5680template class __money_get<wchar_t>;
5681
5682template class money_put<char>;
5683template class money_put<wchar_t>;
5684
5685template class __money_put<char>;
5686template class __money_put<wchar_t>;
5687
5688template class messages<char>;
5689template class messages<wchar_t>;
5690
5691template class messages_byname<char>;
5692template class messages_byname<wchar_t>;
5693
5694template class codecvt_byname<char, char, mbstate_t>;
5695template class codecvt_byname<wchar_t, char, mbstate_t>;
5696template class codecvt_byname<char16_t, char, mbstate_t>;
5697template class codecvt_byname<char32_t, char, mbstate_t>;
5698
5699template class __vector_base_common<true>;
5700
5701_LIBCPP_END_NAMESPACE_STD