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