blob: fe994881d4624ab7008c980ea58828031c0c73f0 [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
David Chisnall997e4542012-02-29 13:05:08 +000010// On Solaris, we need to define something to make the C99 parts of localeconv
11// visible.
12#ifdef __sun__
13#define _LCONV_C99
14#endif
15
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000016#include "string"
17#include "locale"
Howard Hinnant87d1a8a2010-05-30 21:39:41 +000018#include "codecvt"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000019#include "vector"
20#include "algorithm"
21#include "algorithm"
22#include "typeinfo"
Howard Hinnantd318d492011-06-30 14:21:55 +000023#include "type_traits"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024#include "clocale"
25#include "cstring"
26#include "cwctype"
27#include "__sso_allocator"
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000028#if _WIN32
Howard Hinnant14fa9f92011-09-29 20:33:10 +000029#include <support/win32/locale_win32.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000030#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031#include <langinfo.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000032#endif // _!WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000033#include <stdlib.h>
34
35_LIBCPP_BEGIN_NAMESPACE_STD
36
Howard Hinnant866569b2011-09-28 23:39:33 +000037#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000038locale_t __cloc() {
39 // In theory this could create a race condition. In practice
40 // the race condition is non-fatal since it will just create
41 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000042 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
43 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000044}
Howard Hinnant866569b2011-09-28 23:39:33 +000045#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000046
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000047namespace {
48
49struct release
50{
51 void operator()(locale::facet* p) {p->__release_shared();}
52};
53
54template <class T, class A0>
55inline
56T&
57make(A0 a0)
58{
59 static typename aligned_storage<sizeof(T)>::type buf;
60 ::new (&buf) T(a0);
61 return *(T*)&buf;
62}
63
64template <class T, class A0, class A1>
65inline
66T&
67make(A0 a0, A1 a1)
68{
69 static typename aligned_storage<sizeof(T)>::type buf;
70 ::new (&buf) T(a0, a1);
71 return *(T*)&buf;
72}
73
74template <class T, class A0, class A1, class A2>
75inline
76T&
77make(A0 a0, A1 a1, A2 a2)
78{
79 static typename aligned_storage<sizeof(T)>::type buf;
80 ::new (&buf) T(a0, a1, a2);
81 return *(T*)&buf;
82}
83
84}
85
Howard Hinnantec3773c2011-12-01 20:21:04 +000086#pragma clang diagnostic push
87#pragma clang diagnostic ignored "-Wpadded"
88
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000089class _LIBCPP_HIDDEN locale::__imp
90 : public facet
91{
92 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000093 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +000094 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000095public:
96 explicit __imp(size_t refs = 0);
97 explicit __imp(const string& name, size_t refs = 0);
98 __imp(const __imp&);
99 __imp(const __imp&, const string&, locale::category c);
100 __imp(const __imp& other, const __imp& one, locale::category c);
101 __imp(const __imp&, facet* f, long id);
102 ~__imp();
103
104 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000105 bool has_facet(long id) const
106 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000107 const locale::facet* use_facet(long id) const;
108
109 static const locale& make_classic();
110 static locale& make_global();
111private:
112 void install(facet* f, long id);
113 template <class F> void install(F* f) {install(f, f->id.__get());}
114 template <class F> void install_from(const __imp& other);
115};
116
Howard Hinnantec3773c2011-12-01 20:21:04 +0000117#pragma clang diagnostic pop
118
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000119locale::__imp::__imp(size_t refs)
120 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000121 facets_(N),
122 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000123{
124 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000125 install(&make<_VSTD::collate<char> >(1u));
126 install(&make<_VSTD::collate<wchar_t> >(1u));
127 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
128 install(&make<_VSTD::ctype<wchar_t> >(1u));
129 install(&make<codecvt<char, char, mbstate_t> >(1u));
130 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
131 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
132 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
133 install(&make<numpunct<char> >(1u));
134 install(&make<numpunct<wchar_t> >(1u));
135 install(&make<num_get<char> >(1u));
136 install(&make<num_get<wchar_t> >(1u));
137 install(&make<num_put<char> >(1u));
138 install(&make<num_put<wchar_t> >(1u));
139 install(&make<moneypunct<char, false> >(1u));
140 install(&make<moneypunct<char, true> >(1u));
141 install(&make<moneypunct<wchar_t, false> >(1u));
142 install(&make<moneypunct<wchar_t, true> >(1u));
143 install(&make<money_get<char> >(1u));
144 install(&make<money_get<wchar_t> >(1u));
145 install(&make<money_put<char> >(1u));
146 install(&make<money_put<wchar_t> >(1u));
147 install(&make<time_get<char> >(1u));
148 install(&make<time_get<wchar_t> >(1u));
149 install(&make<time_put<char> >(1u));
150 install(&make<time_put<wchar_t> >(1u));
151 install(&make<_VSTD::messages<char> >(1u));
152 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000153}
154
155locale::__imp::__imp(const string& name, size_t refs)
156 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000157 facets_(N),
158 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000159{
Howard Hinnantd4444702010-08-11 17:04:31 +0000160#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000161 try
162 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000163#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000164 facets_ = locale::classic().__locale_->facets_;
165 for (unsigned i = 0; i < facets_.size(); ++i)
166 if (facets_[i])
167 facets_[i]->__add_shared();
168 install(new collate_byname<char>(name_));
169 install(new collate_byname<wchar_t>(name_));
170 install(new ctype_byname<char>(name_));
171 install(new ctype_byname<wchar_t>(name_));
172 install(new codecvt_byname<char, char, mbstate_t>(name_));
173 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
174 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
175 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
176 install(new numpunct_byname<char>(name_));
177 install(new numpunct_byname<wchar_t>(name_));
178 install(new moneypunct_byname<char, false>(name_));
179 install(new moneypunct_byname<char, true>(name_));
180 install(new moneypunct_byname<wchar_t, false>(name_));
181 install(new moneypunct_byname<wchar_t, true>(name_));
182 install(new time_get_byname<char>(name_));
183 install(new time_get_byname<wchar_t>(name_));
184 install(new time_put_byname<char>(name_));
185 install(new time_put_byname<wchar_t>(name_));
186 install(new messages_byname<char>(name_));
187 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000188#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000189 }
190 catch (...)
191 {
192 for (unsigned i = 0; i < facets_.size(); ++i)
193 if (facets_[i])
194 facets_[i]->__release_shared();
195 throw;
196 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000197#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000198}
199
200locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000201 : facets_(max<size_t>(N, other.facets_.size())),
202 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000203{
204 facets_ = other.facets_;
205 for (unsigned i = 0; i < facets_.size(); ++i)
206 if (facets_[i])
207 facets_[i]->__add_shared();
208}
209
210locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000211 : facets_(N),
212 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000213{
214 facets_ = other.facets_;
215 for (unsigned i = 0; i < facets_.size(); ++i)
216 if (facets_[i])
217 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000218#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000219 try
220 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000221#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000222 if (c & locale::collate)
223 {
224 install(new collate_byname<char>(name));
225 install(new collate_byname<wchar_t>(name));
226 }
227 if (c & locale::ctype)
228 {
229 install(new ctype_byname<char>(name));
230 install(new ctype_byname<wchar_t>(name));
231 install(new codecvt_byname<char, char, mbstate_t>(name));
232 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
233 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
234 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
235 }
236 if (c & locale::monetary)
237 {
238 install(new moneypunct_byname<char, false>(name));
239 install(new moneypunct_byname<char, true>(name));
240 install(new moneypunct_byname<wchar_t, false>(name));
241 install(new moneypunct_byname<wchar_t, true>(name));
242 }
243 if (c & locale::numeric)
244 {
245 install(new numpunct_byname<char>(name));
246 install(new numpunct_byname<wchar_t>(name));
247 }
248 if (c & locale::time)
249 {
250 install(new time_get_byname<char>(name));
251 install(new time_get_byname<wchar_t>(name));
252 install(new time_put_byname<char>(name));
253 install(new time_put_byname<wchar_t>(name));
254 }
255 if (c & locale::messages)
256 {
257 install(new messages_byname<char>(name));
258 install(new messages_byname<wchar_t>(name));
259 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000260#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000261 }
262 catch (...)
263 {
264 for (unsigned i = 0; i < facets_.size(); ++i)
265 if (facets_[i])
266 facets_[i]->__release_shared();
267 throw;
268 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000269#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000270}
271
272template<class F>
273inline
274void
275locale::__imp::install_from(const locale::__imp& one)
276{
277 long id = F::id.__get();
278 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
279}
280
281locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000282 : facets_(N),
283 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000284{
285 facets_ = other.facets_;
286 for (unsigned i = 0; i < facets_.size(); ++i)
287 if (facets_[i])
288 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000289#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000290 try
291 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000292#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000293 if (c & locale::collate)
294 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000295 install_from<_VSTD::collate<char> >(one);
296 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000297 }
298 if (c & locale::ctype)
299 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000300 install_from<_VSTD::ctype<char> >(one);
301 install_from<_VSTD::ctype<wchar_t> >(one);
302 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
303 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
304 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
305 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000306 }
307 if (c & locale::monetary)
308 {
309 install_from<moneypunct<char, false> >(one);
310 install_from<moneypunct<char, true> >(one);
311 install_from<moneypunct<wchar_t, false> >(one);
312 install_from<moneypunct<wchar_t, true> >(one);
313 install_from<money_get<char> >(one);
314 install_from<money_get<wchar_t> >(one);
315 install_from<money_put<char> >(one);
316 install_from<money_put<wchar_t> >(one);
317 }
318 if (c & locale::numeric)
319 {
320 install_from<numpunct<char> >(one);
321 install_from<numpunct<wchar_t> >(one);
322 install_from<num_get<char> >(one);
323 install_from<num_get<wchar_t> >(one);
324 install_from<num_put<char> >(one);
325 install_from<num_put<wchar_t> >(one);
326 }
327 if (c & locale::time)
328 {
329 install_from<time_get<char> >(one);
330 install_from<time_get<wchar_t> >(one);
331 install_from<time_put<char> >(one);
332 install_from<time_put<wchar_t> >(one);
333 }
334 if (c & locale::messages)
335 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000336 install_from<_VSTD::messages<char> >(one);
337 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000338 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000339#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000340 }
341 catch (...)
342 {
343 for (unsigned i = 0; i < facets_.size(); ++i)
344 if (facets_[i])
345 facets_[i]->__release_shared();
346 throw;
347 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000348#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000349}
350
351locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000352 : facets_(max<size_t>(N, other.facets_.size()+1)),
353 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000354{
355 f->__add_shared();
356 unique_ptr<facet, release> hold(f);
357 facets_ = other.facets_;
358 for (unsigned i = 0; i < other.facets_.size(); ++i)
359 if (facets_[i])
360 facets_[i]->__add_shared();
361 install(hold.get(), id);
362}
363
364locale::__imp::~__imp()
365{
366 for (unsigned i = 0; i < facets_.size(); ++i)
367 if (facets_[i])
368 facets_[i]->__release_shared();
369}
370
371void
372locale::__imp::install(facet* f, long id)
373{
374 f->__add_shared();
375 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000376 if (static_cast<size_t>(id) >= facets_.size())
377 facets_.resize(static_cast<size_t>(id+1));
378 if (facets_[static_cast<size_t>(id)])
379 facets_[static_cast<size_t>(id)]->__release_shared();
380 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000381}
382
383const locale::facet*
384locale::__imp::use_facet(long id) const
385{
Howard Hinnantd4444702010-08-11 17:04:31 +0000386#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000387 if (!has_facet(id))
388 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000389#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000390 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000391}
392
393// locale
394
395const locale&
396locale::__imp::make_classic()
397{
398 // only one thread can get in here and it only gets in once
399 static aligned_storage<sizeof(locale)>::type buf;
400 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000401 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000402 return *c;
403}
404
405const locale&
406locale::classic()
407{
408 static const locale& c = __imp::make_classic();
409 return c;
410}
411
412locale&
413locale::__imp::make_global()
414{
415 // only one thread can get in here and it only gets in once
416 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000417 ::new (&buf) locale(locale::classic());
418 return *(locale*)&buf;
419}
420
421locale&
422locale::__global()
423{
424 static locale& g = __imp::make_global();
425 return g;
426}
427
Howard Hinnantc9834542011-05-31 15:34:58 +0000428locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000429 : __locale_(__global().__locale_)
430{
431 __locale_->__add_shared();
432}
433
Howard Hinnantc9834542011-05-31 15:34:58 +0000434locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000435 : __locale_(l.__locale_)
436{
437 __locale_->__add_shared();
438}
439
Howard Hinnantc9834542011-05-31 15:34:58 +0000440locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000441{
442 __locale_->__release_shared();
443}
444
445const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000446locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000447{
448 other.__locale_->__add_shared();
449 __locale_->__release_shared();
450 __locale_ = other.__locale_;
451 return *this;
452}
453
454locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000455#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000456 : __locale_(name ? new __imp(name)
457 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000458#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000459 : __locale_(new __imp(name))
460#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000461{
462 __locale_->__add_shared();
463}
464
465locale::locale(const string& name)
466 : __locale_(new __imp(name))
467{
468 __locale_->__add_shared();
469}
470
471locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000472#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000473 : __locale_(name ? new __imp(*other.__locale_, name, c)
474 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000475#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000476 : __locale_(new __imp(*other.__locale_, name, c))
477#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000478{
479 __locale_->__add_shared();
480}
481
482locale::locale(const locale& other, const string& name, category c)
483 : __locale_(new __imp(*other.__locale_, name, c))
484{
485 __locale_->__add_shared();
486}
487
488locale::locale(const locale& other, const locale& one, category c)
489 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
490{
491 __locale_->__add_shared();
492}
493
494string
495locale::name() const
496{
497 return __locale_->name();
498}
499
500void
501locale::__install_ctor(const locale& other, facet* f, long id)
502{
503 if (f)
504 __locale_ = new __imp(*other.__locale_, f, id);
505 else
506 __locale_ = other.__locale_;
507 __locale_->__add_shared();
508}
509
510locale
511locale::global(const locale& loc)
512{
513 locale& g = __global();
514 locale r = g;
515 g = loc;
516 if (g.name() != "*")
517 setlocale(LC_ALL, g.name().c_str());
518 return r;
519}
520
521bool
522locale::has_facet(id& x) const
523{
524 return __locale_->has_facet(x.__get());
525}
526
527const locale::facet*
528locale::use_facet(id& x) const
529{
530 return __locale_->use_facet(x.__get());
531}
532
533bool
534locale::operator==(const locale& y) const
535{
536 return (__locale_ == y.__locale_)
537 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
538}
539
540// locale::facet
541
542locale::facet::~facet()
543{
544}
545
546void
Howard Hinnant1694d232011-05-28 14:41:13 +0000547locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000548{
549 delete this;
550}
551
552// locale::id
553
554int32_t locale::id::__next_id = 0;
555
556namespace
557{
558
559class __fake_bind
560{
561 locale::id* id_;
562 void (locale::id::* pmf_)();
563public:
564 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
565 : id_(id), pmf_(pmf) {}
566
567 void operator()() const
568 {
569 (id_->*pmf_)();
570 }
571};
572
573}
574
575long
576locale::id::__get()
577{
578 call_once(__flag_, __fake_bind(&locale::id::__init, this));
579 return __id_ - 1;
580}
581
582void
583locale::id::__init()
584{
Howard Hinnantadff4892010-05-24 17:49:41 +0000585 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000586}
587
588// template <> class collate_byname<char>
589
590collate_byname<char>::collate_byname(const char* n, size_t refs)
591 : collate<char>(refs),
592 __l(newlocale(LC_ALL_MASK, n, 0))
593{
Howard Hinnantd4444702010-08-11 17:04:31 +0000594#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000595 if (__l == 0)
596 throw runtime_error("collate_byname<char>::collate_byname"
597 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000598#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000599}
600
601collate_byname<char>::collate_byname(const string& name, size_t refs)
602 : collate<char>(refs),
603 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
604{
Howard Hinnantd4444702010-08-11 17:04:31 +0000605#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000606 if (__l == 0)
607 throw runtime_error("collate_byname<char>::collate_byname"
608 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000609#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000610}
611
612collate_byname<char>::~collate_byname()
613{
614 freelocale(__l);
615}
616
617int
618collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
619 const char_type* __lo2, const char_type* __hi2) const
620{
621 string_type lhs(__lo1, __hi1);
622 string_type rhs(__lo2, __hi2);
623 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
624 if (r < 0)
625 return -1;
626 if (r > 0)
627 return 1;
628 return r;
629}
630
631collate_byname<char>::string_type
632collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
633{
634 const string_type in(lo, hi);
635 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
636 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
637 return out;
638}
639
640// template <> class collate_byname<wchar_t>
641
642collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
643 : collate<wchar_t>(refs),
644 __l(newlocale(LC_ALL_MASK, n, 0))
645{
Howard Hinnantd4444702010-08-11 17:04:31 +0000646#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000647 if (__l == 0)
648 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
649 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000650#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000651}
652
653collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
654 : collate<wchar_t>(refs),
655 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
656{
Howard Hinnantd4444702010-08-11 17:04:31 +0000657#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000658 if (__l == 0)
659 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
660 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000661#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000662}
663
664collate_byname<wchar_t>::~collate_byname()
665{
666 freelocale(__l);
667}
668
669int
670collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
671 const char_type* __lo2, const char_type* __hi2) const
672{
673 string_type lhs(__lo1, __hi1);
674 string_type rhs(__lo2, __hi2);
675 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
676 if (r < 0)
677 return -1;
678 if (r > 0)
679 return 1;
680 return r;
681}
682
683collate_byname<wchar_t>::string_type
684collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
685{
686 const string_type in(lo, hi);
687 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
688 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
689 return out;
690}
691
692// template <> class ctype<wchar_t>;
693
694locale::id ctype<wchar_t>::id;
695
696ctype<wchar_t>::~ctype()
697{
698}
699
700bool
701ctype<wchar_t>::do_is(mask m, char_type c) const
702{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000703 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000704}
705
706const wchar_t*
707ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
708{
709 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000710 *vec = static_cast<mask>(isascii(*low) ?
711 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000712 return low;
713}
714
715const wchar_t*
716ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
717{
718 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000719 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000720 break;
721 return low;
722}
723
724const wchar_t*
725ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
726{
727 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000728 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000729 break;
730 return low;
731}
732
733wchar_t
734ctype<wchar_t>::do_toupper(char_type c) const
735{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000736#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
737 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
738#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000739 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000740#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000741 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000742#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000743}
744
745const wchar_t*
746ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
747{
748 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000749#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
750 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
751#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000752 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
753 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000754#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000755 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000756#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000757 return low;
758}
759
760wchar_t
761ctype<wchar_t>::do_tolower(char_type c) const
762{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000763#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
764 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
765#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000766 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000767#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000768 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000769#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000770}
771
772const wchar_t*
773ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
774{
775 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000776#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
777 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
778#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000779 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
780 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000781#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000782 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000783#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000784 return low;
785}
786
787wchar_t
788ctype<wchar_t>::do_widen(char c) const
789{
790 return c;
791}
792
793const char*
794ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
795{
796 for (; low != high; ++low, ++dest)
797 *dest = *low;
798 return low;
799}
800
801char
802ctype<wchar_t>::do_narrow(char_type c, char dfault) const
803{
804 if (isascii(c))
805 return static_cast<char>(c);
806 return dfault;
807}
808
809const wchar_t*
810ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
811{
812 for (; low != high; ++low, ++dest)
813 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000814 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000815 else
816 *dest = dfault;
817 return low;
818}
819
820// template <> class ctype<char>;
821
822locale::id ctype<char>::id;
823
824ctype<char>::ctype(const mask* tab, bool del, size_t refs)
825 : locale::facet(refs),
826 __tab_(tab),
827 __del_(del)
828{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000829 if (__tab_ == 0)
830 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000831}
832
833ctype<char>::~ctype()
834{
835 if (__tab_ && __del_)
836 delete [] __tab_;
837}
838
839char
840ctype<char>::do_toupper(char_type c) const
841{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000842#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000843 return isascii(c) ?
844 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000845#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000846 return isascii(c) ? __classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000847#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000848 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000849#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000850}
851
852const char*
853ctype<char>::do_toupper(char_type* low, const char_type* high) const
854{
855 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000856#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000857 *low = isascii(*low) ?
858 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000859#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000860 *low = isascii(*low) ? __classic_upper_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000861#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000862 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000863#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000864 return low;
865}
866
867char
868ctype<char>::do_tolower(char_type c) const
869{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000870#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000871 return isascii(c) ?
872 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000873#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000874 return isascii(c) ? __classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000875#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000876 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000877#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000878}
879
880const char*
881ctype<char>::do_tolower(char_type* low, const char_type* high) const
882{
883 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000884#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000885 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000886#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000887 *low = isascii(*low) ? __classic_lower_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000888#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000889 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000890#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000891 return low;
892}
893
894char
895ctype<char>::do_widen(char c) const
896{
897 return c;
898}
899
900const char*
901ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
902{
903 for (; low != high; ++low, ++dest)
904 *dest = *low;
905 return low;
906}
907
908char
909ctype<char>::do_narrow(char_type c, char dfault) const
910{
911 if (isascii(c))
912 return static_cast<char>(c);
913 return dfault;
914}
915
916const char*
917ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
918{
919 for (; low != high; ++low, ++dest)
920 if (isascii(*low))
921 *dest = *low;
922 else
923 *dest = dfault;
924 return low;
925}
926
927const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000928ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000929{
David Chisnallc512df12011-09-21 08:39:44 +0000930#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000931 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000932#elif defined(__GLIBC__)
933 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +0000934#elif __sun__
935 return __ctype_mask;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000936#elif _WIN32
937 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +0000938// This is assumed to be safe, which is a nonsense assumption because we're
939// going to end up dereferencing it later...
Sean Hunt62a6ac32011-07-09 00:56:23 +0000940#else
David Chisnall997e4542012-02-29 13:05:08 +0000941 // Platform not supported: abort so the person doing the port knows what to
942 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +0000943# warning ctype<char>::classic_table() is not implemented
David Chisnall997e4542012-02-29 13:05:08 +0000944 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +0000945 return NULL;
946#endif
947}
948
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000949#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000950const int*
951ctype<char>::__classic_lower_table() _NOEXCEPT
952{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000953 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000954}
955
956const int*
957ctype<char>::__classic_upper_table() _NOEXCEPT
958{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000959 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000960}
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000961#endif // __GLIBC__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000962
963// template <> class ctype_byname<char>
964
965ctype_byname<char>::ctype_byname(const char* name, size_t refs)
966 : ctype<char>(0, false, refs),
967 __l(newlocale(LC_ALL_MASK, name, 0))
968{
Howard Hinnantd4444702010-08-11 17:04:31 +0000969#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000970 if (__l == 0)
971 throw runtime_error("ctype_byname<char>::ctype_byname"
972 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000973#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000974}
975
976ctype_byname<char>::ctype_byname(const string& name, size_t refs)
977 : ctype<char>(0, false, refs),
978 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
979{
Howard Hinnantd4444702010-08-11 17:04:31 +0000980#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000981 if (__l == 0)
982 throw runtime_error("ctype_byname<char>::ctype_byname"
983 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000984#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000985}
986
987ctype_byname<char>::~ctype_byname()
988{
989 freelocale(__l);
990}
991
992char
993ctype_byname<char>::do_toupper(char_type c) const
994{
Howard Hinnantec3773c2011-12-01 20:21:04 +0000995 return static_cast<char>(toupper_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000996}
997
998const char*
999ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1000{
1001 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001002 *low = static_cast<char>(toupper_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001003 return low;
1004}
1005
1006char
1007ctype_byname<char>::do_tolower(char_type c) const
1008{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001009 return static_cast<char>(tolower_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001010}
1011
1012const char*
1013ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1014{
1015 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001016 *low = static_cast<char>(tolower_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001017 return low;
1018}
1019
1020// template <> class ctype_byname<wchar_t>
1021
1022ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1023 : ctype<wchar_t>(refs),
1024 __l(newlocale(LC_ALL_MASK, name, 0))
1025{
Howard Hinnantd4444702010-08-11 17:04:31 +00001026#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001027 if (__l == 0)
1028 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1029 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001030#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001031}
1032
1033ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1034 : ctype<wchar_t>(refs),
1035 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1036{
Howard Hinnantd4444702010-08-11 17:04:31 +00001037#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001038 if (__l == 0)
1039 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1040 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001041#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001042}
1043
1044ctype_byname<wchar_t>::~ctype_byname()
1045{
1046 freelocale(__l);
1047}
1048
1049bool
1050ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1051{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001052#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001053 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001054#else
Howard Hinnant8db4aca2011-10-17 20:08:59 +00001055 bool result = true;
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001056 if (m & space && !iswspace_l(c, __l)) result = false;
1057 if (m & print && !iswprint_l(c, __l)) result = false;
1058 if (m & cntrl && !iswcntrl_l(c, __l)) result = false;
1059 if (m & upper && !iswupper_l(c, __l)) result = false;
1060 if (m & lower && !iswlower_l(c, __l)) result = false;
1061 if (m & alpha && !iswalpha_l(c, __l)) result = false;
1062 if (m & digit && !iswdigit_l(c, __l)) result = false;
1063 if (m & punct && !iswpunct_l(c, __l)) result = false;
1064 if (m & xdigit && !iswxdigit_l(c, __l)) result = false;
1065 if (m & blank && !iswblank_l(c, __l)) result = false;
1066 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001067#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001068}
1069
1070const wchar_t*
1071ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1072{
1073 for (; low != high; ++low, ++vec)
1074 {
1075 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001076 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001077 else
1078 {
1079 *vec = 0;
1080 if (iswspace_l(*low, __l))
1081 *vec |= space;
1082 if (iswprint_l(*low, __l))
1083 *vec |= print;
1084 if (iswcntrl_l(*low, __l))
1085 *vec |= cntrl;
1086 if (iswupper_l(*low, __l))
1087 *vec |= upper;
1088 if (iswlower_l(*low, __l))
1089 *vec |= lower;
1090 if (iswalpha_l(*low, __l))
1091 *vec |= alpha;
1092 if (iswdigit_l(*low, __l))
1093 *vec |= digit;
1094 if (iswpunct_l(*low, __l))
1095 *vec |= punct;
1096 if (iswxdigit_l(*low, __l))
1097 *vec |= xdigit;
1098 }
1099 }
1100 return low;
1101}
1102
1103const wchar_t*
1104ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1105{
1106 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001107 {
1108#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001109 if (iswctype_l(*low, m, __l))
1110 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001111#else
1112 if (m & space && !iswspace_l(*low, __l)) continue;
1113 if (m & print && !iswprint_l(*low, __l)) continue;
1114 if (m & cntrl && !iswcntrl_l(*low, __l)) continue;
1115 if (m & upper && !iswupper_l(*low, __l)) continue;
1116 if (m & lower && !iswlower_l(*low, __l)) continue;
1117 if (m & alpha && !iswalpha_l(*low, __l)) continue;
1118 if (m & digit && !iswdigit_l(*low, __l)) continue;
1119 if (m & punct && !iswpunct_l(*low, __l)) continue;
1120 if (m & xdigit && !iswxdigit_l(*low, __l)) continue;
1121 if (m & blank && !iswblank_l(*low, __l)) continue;
1122 break;
1123#endif
1124 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001125 return low;
1126}
1127
1128const wchar_t*
1129ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1130{
1131 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001132 {
1133#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001134 if (!iswctype_l(*low, m, __l))
1135 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001136#else
1137 if (m & space && iswspace_l(*low, __l)) continue;
1138 if (m & print && iswprint_l(*low, __l)) continue;
1139 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1140 if (m & upper && iswupper_l(*low, __l)) continue;
1141 if (m & lower && iswlower_l(*low, __l)) continue;
1142 if (m & alpha && iswalpha_l(*low, __l)) continue;
1143 if (m & digit && iswdigit_l(*low, __l)) continue;
1144 if (m & punct && iswpunct_l(*low, __l)) continue;
1145 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1146 if (m & blank && iswblank_l(*low, __l)) continue;
1147 break;
1148#endif
1149 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001150 return low;
1151}
1152
1153wchar_t
1154ctype_byname<wchar_t>::do_toupper(char_type c) const
1155{
1156 return towupper_l(c, __l);
1157}
1158
1159const wchar_t*
1160ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1161{
1162 for (; low != high; ++low)
1163 *low = towupper_l(*low, __l);
1164 return low;
1165}
1166
1167wchar_t
1168ctype_byname<wchar_t>::do_tolower(char_type c) const
1169{
1170 return towlower_l(c, __l);
1171}
1172
1173const wchar_t*
1174ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1175{
1176 for (; low != high; ++low)
1177 *low = towlower_l(*low, __l);
1178 return low;
1179}
1180
1181wchar_t
1182ctype_byname<wchar_t>::do_widen(char c) const
1183{
Howard Hinnant866569b2011-09-28 23:39:33 +00001184#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001185 return btowc_l(c, __l);
1186#else
1187 return __btowc_l(c, __l);
1188#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001189}
1190
1191const char*
1192ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1193{
1194 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001195#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001196 *dest = btowc_l(*low, __l);
1197#else
1198 *dest = __btowc_l(*low, __l);
1199#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200 return low;
1201}
1202
1203char
1204ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1205{
Howard Hinnant866569b2011-09-28 23:39:33 +00001206#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001207 int r = wctob_l(c, __l);
1208#else
1209 int r = __wctob_l(c, __l);
1210#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001211 return r != WEOF ? static_cast<char>(r) : dfault;
1212}
1213
1214const wchar_t*
1215ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1216{
1217 for (; low != high; ++low, ++dest)
1218 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001219#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001220 int r = wctob_l(*low, __l);
1221#else
1222 int r = __wctob_l(*low, __l);
1223#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001224 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1225 }
1226 return low;
1227}
1228
1229// template <> class codecvt<char, char, mbstate_t>
1230
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001231locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001232
1233codecvt<char, char, mbstate_t>::~codecvt()
1234{
1235}
1236
1237codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001238codecvt<char, char, mbstate_t>::do_out(state_type&,
1239 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 extern_type* to, extern_type*, extern_type*& to_nxt) const
1241{
1242 frm_nxt = frm;
1243 to_nxt = to;
1244 return noconv;
1245}
1246
1247codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001248codecvt<char, char, mbstate_t>::do_in(state_type&,
1249 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001250 intern_type* to, intern_type*, intern_type*& to_nxt) const
1251{
1252 frm_nxt = frm;
1253 to_nxt = to;
1254 return noconv;
1255}
1256
1257codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001258codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001259 extern_type* to, extern_type*, extern_type*& to_nxt) const
1260{
1261 to_nxt = to;
1262 return noconv;
1263}
1264
1265int
Howard Hinnantc9834542011-05-31 15:34:58 +00001266codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001267{
1268 return 1;
1269}
1270
1271bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001272codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001273{
1274 return true;
1275}
1276
1277int
1278codecvt<char, char, mbstate_t>::do_length(state_type&,
1279 const extern_type* frm, const extern_type* end, size_t mx) const
1280{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001281 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001282}
1283
1284int
Howard Hinnantc9834542011-05-31 15:34:58 +00001285codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001286{
1287 return 1;
1288}
1289
1290// template <> class codecvt<wchar_t, char, mbstate_t>
1291
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001292locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001293
1294codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1295 : locale::facet(refs),
1296 __l(0)
1297{
1298}
1299
1300codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1301 : locale::facet(refs),
1302 __l(newlocale(LC_ALL_MASK, nm, 0))
1303{
Howard Hinnantd4444702010-08-11 17:04:31 +00001304#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001305 if (__l == 0)
1306 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1307 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001308#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001309}
1310
1311codecvt<wchar_t, char, mbstate_t>::~codecvt()
1312{
1313 if (__l != 0)
1314 freelocale(__l);
1315}
1316
1317codecvt<wchar_t, char, mbstate_t>::result
1318codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001319 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001320 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1321{
1322 // look for first internal null in frm
1323 const intern_type* fend = frm;
1324 for (; fend != frm_end; ++fend)
1325 if (*fend == 0)
1326 break;
1327 // loop over all null-terminated sequences in frm
1328 to_nxt = to;
1329 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1330 {
1331 // save state in case needed to reover to_nxt on error
1332 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001333#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001334 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1335 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001336#else
1337 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1338#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001339 if (n == size_t(-1))
1340 {
1341 // need to recover to_nxt
1342 for (to_nxt = to; frm != frm_nxt; ++frm)
1343 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001344#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001345 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1346#else
1347 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1348#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001349 if (n == size_t(-1))
1350 break;
1351 to_nxt += n;
1352 }
1353 frm_nxt = frm;
1354 return error;
1355 }
1356 if (n == 0)
1357 return partial;
1358 to_nxt += n;
1359 if (to_nxt == to_end)
1360 break;
1361 if (fend != frm_end) // set up next null terminated sequence
1362 {
1363 // Try to write the terminating null
1364 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001365#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001366 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1367#else
1368 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1369#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001370 if (n == size_t(-1)) // on error
1371 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001372 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001373 return partial;
1374 for (extern_type* p = tmp; n; --n) // write it
1375 *to_nxt++ = *p++;
1376 ++frm_nxt;
1377 // look for next null in frm
1378 for (fend = frm_nxt; fend != frm_end; ++fend)
1379 if (*fend == 0)
1380 break;
1381 }
1382 }
1383 return frm_nxt == frm_end ? ok : partial;
1384}
1385
1386codecvt<wchar_t, char, mbstate_t>::result
1387codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001388 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001389 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1390{
1391 // look for first internal null in frm
1392 const extern_type* fend = frm;
1393 for (; fend != frm_end; ++fend)
1394 if (*fend == 0)
1395 break;
1396 // loop over all null-terminated sequences in frm
1397 to_nxt = to;
1398 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1399 {
1400 // save state in case needed to reover to_nxt on error
1401 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001402#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001403 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1404 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001405#else
1406 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1407#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001408 if (n == size_t(-1))
1409 {
1410 // need to recover to_nxt
1411 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1412 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001413#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001414 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1415 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001416#else
1417 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1418#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001419 switch (n)
1420 {
1421 case 0:
1422 ++frm;
1423 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001424 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001425 frm_nxt = frm;
1426 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001427 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001428 frm_nxt = frm;
1429 return partial;
1430 default:
1431 frm += n;
1432 break;
1433 }
1434 }
1435 frm_nxt = frm;
1436 return frm_nxt == frm_end ? ok : partial;
1437 }
1438 if (n == 0)
1439 return error;
1440 to_nxt += n;
1441 if (to_nxt == to_end)
1442 break;
1443 if (fend != frm_end) // set up next null terminated sequence
1444 {
1445 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001446#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001447 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1448#else
1449 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1450#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001451 if (n != 0) // on error
1452 return error;
1453 ++to_nxt;
1454 ++frm_nxt;
1455 // look for next null in frm
1456 for (fend = frm_nxt; fend != frm_end; ++fend)
1457 if (*fend == 0)
1458 break;
1459 }
1460 }
1461 return frm_nxt == frm_end ? ok : partial;
1462}
1463
1464codecvt<wchar_t, char, mbstate_t>::result
1465codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1466 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1467{
1468 to_nxt = to;
1469 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001470#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001471 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1472#else
1473 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1474#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001475 if (n == size_t(-1) || n == 0) // on error
1476 return error;
1477 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001478 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001479 return partial;
1480 for (extern_type* p = tmp; n; --n) // write it
1481 *to_nxt++ = *p++;
1482 return ok;
1483}
1484
1485int
Howard Hinnantc9834542011-05-31 15:34:58 +00001486codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001487{
Howard Hinnant866569b2011-09-28 23:39:33 +00001488#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001489 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1490#else
1491 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1492#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001493 {
1494 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001495#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001496 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1497#else
1498 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1499#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001500 return 1; // which take more than 1 char to form a wchar_t
1501 return 0;
1502 }
1503 return -1;
1504}
1505
1506bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001507codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001508{
1509 return false;
1510}
1511
1512int
1513codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1514 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1515{
1516 int nbytes = 0;
1517 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1518 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001519#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001520 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001521#else
1522 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1523#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001524 switch (n)
1525 {
1526 case 0:
1527 ++nbytes;
1528 ++frm;
1529 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001530 case size_t(-1):
1531 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 return nbytes;
1533 default:
1534 nbytes += n;
1535 frm += n;
1536 break;
1537 }
1538 }
1539 return nbytes;
1540}
1541
1542int
Howard Hinnantc9834542011-05-31 15:34:58 +00001543codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001544{
Howard Hinnant866569b2011-09-28 23:39:33 +00001545#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001546 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1547#else
1548 return __l == 0 ? 1 : __mb_cur_max_l(__l);
1549#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001550}
1551
1552// Valid UTF ranges
1553// UTF-32 UTF-16 UTF-8 # of code points
1554// first second first second third fourth
1555// 000000 - 00007F 0000 - 007F 00 - 7F 127
1556// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1557// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1558// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1559// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1560// 00D800 - 00DFFF invalid
1561// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1562// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1563// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1564// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1565
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001566static
1567codecvt_base::result
1568utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1569 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1570 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1571{
1572 frm_nxt = frm;
1573 to_nxt = to;
1574 if (mode & generate_header)
1575 {
1576 if (to_end-to_nxt < 3)
1577 return codecvt_base::partial;
1578 *to_nxt++ = static_cast<uint8_t>(0xEF);
1579 *to_nxt++ = static_cast<uint8_t>(0xBB);
1580 *to_nxt++ = static_cast<uint8_t>(0xBF);
1581 }
1582 for (; frm_nxt < frm_end; ++frm_nxt)
1583 {
1584 uint16_t wc1 = *frm_nxt;
1585 if (wc1 > Maxcode)
1586 return codecvt_base::error;
1587 if (wc1 < 0x0080)
1588 {
1589 if (to_end-to_nxt < 1)
1590 return codecvt_base::partial;
1591 *to_nxt++ = static_cast<uint8_t>(wc1);
1592 }
1593 else if (wc1 < 0x0800)
1594 {
1595 if (to_end-to_nxt < 2)
1596 return codecvt_base::partial;
1597 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1598 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1599 }
1600 else if (wc1 < 0xD800)
1601 {
1602 if (to_end-to_nxt < 3)
1603 return codecvt_base::partial;
1604 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1605 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1606 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1607 }
1608 else if (wc1 < 0xDC00)
1609 {
1610 if (frm_end-frm_nxt < 2)
1611 return codecvt_base::partial;
1612 uint16_t wc2 = frm_nxt[1];
1613 if ((wc2 & 0xFC00) != 0xDC00)
1614 return codecvt_base::error;
1615 if (to_end-to_nxt < 4)
1616 return codecvt_base::partial;
1617 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1618 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1619 return codecvt_base::error;
1620 ++frm_nxt;
1621 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1622 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1623 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1624 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1625 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1626 }
1627 else if (wc1 < 0xE000)
1628 {
1629 return codecvt_base::error;
1630 }
1631 else
1632 {
1633 if (to_end-to_nxt < 3)
1634 return codecvt_base::partial;
1635 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1636 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1637 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1638 }
1639 }
1640 return codecvt_base::ok;
1641}
1642
1643static
1644codecvt_base::result
1645utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1646 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1647 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1648{
1649 frm_nxt = frm;
1650 to_nxt = to;
1651 if (mode & generate_header)
1652 {
1653 if (to_end-to_nxt < 3)
1654 return codecvt_base::partial;
1655 *to_nxt++ = static_cast<uint8_t>(0xEF);
1656 *to_nxt++ = static_cast<uint8_t>(0xBB);
1657 *to_nxt++ = static_cast<uint8_t>(0xBF);
1658 }
1659 for (; frm_nxt < frm_end; ++frm_nxt)
1660 {
1661 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1662 if (wc1 > Maxcode)
1663 return codecvt_base::error;
1664 if (wc1 < 0x0080)
1665 {
1666 if (to_end-to_nxt < 1)
1667 return codecvt_base::partial;
1668 *to_nxt++ = static_cast<uint8_t>(wc1);
1669 }
1670 else if (wc1 < 0x0800)
1671 {
1672 if (to_end-to_nxt < 2)
1673 return codecvt_base::partial;
1674 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1675 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1676 }
1677 else if (wc1 < 0xD800)
1678 {
1679 if (to_end-to_nxt < 3)
1680 return codecvt_base::partial;
1681 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1682 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1683 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1684 }
1685 else if (wc1 < 0xDC00)
1686 {
1687 if (frm_end-frm_nxt < 2)
1688 return codecvt_base::partial;
1689 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1690 if ((wc2 & 0xFC00) != 0xDC00)
1691 return codecvt_base::error;
1692 if (to_end-to_nxt < 4)
1693 return codecvt_base::partial;
1694 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1695 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1696 return codecvt_base::error;
1697 ++frm_nxt;
1698 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1699 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1700 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1701 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1702 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1703 }
1704 else if (wc1 < 0xE000)
1705 {
1706 return codecvt_base::error;
1707 }
1708 else
1709 {
1710 if (to_end-to_nxt < 3)
1711 return codecvt_base::partial;
1712 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1713 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1714 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1715 }
1716 }
1717 return codecvt_base::ok;
1718}
1719
1720static
1721codecvt_base::result
1722utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1723 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1724 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1725{
1726 frm_nxt = frm;
1727 to_nxt = to;
1728 if (mode & consume_header)
1729 {
1730 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1731 frm_nxt[2] == 0xBF)
1732 frm_nxt += 3;
1733 }
1734 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1735 {
1736 uint8_t c1 = *frm_nxt;
1737 if (c1 > Maxcode)
1738 return codecvt_base::error;
1739 if (c1 < 0x80)
1740 {
1741 *to_nxt = static_cast<uint16_t>(c1);
1742 ++frm_nxt;
1743 }
1744 else if (c1 < 0xC2)
1745 {
1746 return codecvt_base::error;
1747 }
1748 else if (c1 < 0xE0)
1749 {
1750 if (frm_end-frm_nxt < 2)
1751 return codecvt_base::partial;
1752 uint8_t c2 = frm_nxt[1];
1753 if ((c2 & 0xC0) != 0x80)
1754 return codecvt_base::error;
1755 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1756 if (t > Maxcode)
1757 return codecvt_base::error;
1758 *to_nxt = t;
1759 frm_nxt += 2;
1760 }
1761 else if (c1 < 0xF0)
1762 {
1763 if (frm_end-frm_nxt < 3)
1764 return codecvt_base::partial;
1765 uint8_t c2 = frm_nxt[1];
1766 uint8_t c3 = frm_nxt[2];
1767 switch (c1)
1768 {
1769 case 0xE0:
1770 if ((c2 & 0xE0) != 0xA0)
1771 return codecvt_base::error;
1772 break;
1773 case 0xED:
1774 if ((c2 & 0xE0) != 0x80)
1775 return codecvt_base::error;
1776 break;
1777 default:
1778 if ((c2 & 0xC0) != 0x80)
1779 return codecvt_base::error;
1780 break;
1781 }
1782 if ((c3 & 0xC0) != 0x80)
1783 return codecvt_base::error;
1784 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1785 | ((c2 & 0x3F) << 6)
1786 | (c3 & 0x3F));
1787 if (t > Maxcode)
1788 return codecvt_base::error;
1789 *to_nxt = t;
1790 frm_nxt += 3;
1791 }
1792 else if (c1 < 0xF5)
1793 {
1794 if (frm_end-frm_nxt < 4)
1795 return codecvt_base::partial;
1796 uint8_t c2 = frm_nxt[1];
1797 uint8_t c3 = frm_nxt[2];
1798 uint8_t c4 = frm_nxt[3];
1799 switch (c1)
1800 {
1801 case 0xF0:
1802 if (!(0x90 <= c2 && c2 <= 0xBF))
1803 return codecvt_base::error;
1804 break;
1805 case 0xF4:
1806 if ((c2 & 0xF0) != 0x80)
1807 return codecvt_base::error;
1808 break;
1809 default:
1810 if ((c2 & 0xC0) != 0x80)
1811 return codecvt_base::error;
1812 break;
1813 }
1814 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1815 return codecvt_base::error;
1816 if (to_end-to_nxt < 2)
1817 return codecvt_base::partial;
1818 if (((((unsigned long)c1 & 7) << 18) +
1819 (((unsigned long)c2 & 0x3F) << 12) +
1820 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1821 return codecvt_base::error;
1822 *to_nxt = static_cast<uint16_t>(
1823 0xD800
1824 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1825 | ((c2 & 0x0F) << 2)
1826 | ((c3 & 0x30) >> 4));
1827 *++to_nxt = static_cast<uint16_t>(
1828 0xDC00
1829 | ((c3 & 0x0F) << 6)
1830 | (c4 & 0x3F));
1831 frm_nxt += 4;
1832 }
1833 else
1834 {
1835 return codecvt_base::error;
1836 }
1837 }
1838 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1839}
1840
1841static
1842codecvt_base::result
1843utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1844 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1845 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1846{
1847 frm_nxt = frm;
1848 to_nxt = to;
1849 if (mode & consume_header)
1850 {
1851 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1852 frm_nxt[2] == 0xBF)
1853 frm_nxt += 3;
1854 }
1855 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1856 {
1857 uint8_t c1 = *frm_nxt;
1858 if (c1 > Maxcode)
1859 return codecvt_base::error;
1860 if (c1 < 0x80)
1861 {
1862 *to_nxt = static_cast<uint32_t>(c1);
1863 ++frm_nxt;
1864 }
1865 else if (c1 < 0xC2)
1866 {
1867 return codecvt_base::error;
1868 }
1869 else if (c1 < 0xE0)
1870 {
1871 if (frm_end-frm_nxt < 2)
1872 return codecvt_base::partial;
1873 uint8_t c2 = frm_nxt[1];
1874 if ((c2 & 0xC0) != 0x80)
1875 return codecvt_base::error;
1876 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1877 if (t > Maxcode)
1878 return codecvt_base::error;
1879 *to_nxt = static_cast<uint32_t>(t);
1880 frm_nxt += 2;
1881 }
1882 else if (c1 < 0xF0)
1883 {
1884 if (frm_end-frm_nxt < 3)
1885 return codecvt_base::partial;
1886 uint8_t c2 = frm_nxt[1];
1887 uint8_t c3 = frm_nxt[2];
1888 switch (c1)
1889 {
1890 case 0xE0:
1891 if ((c2 & 0xE0) != 0xA0)
1892 return codecvt_base::error;
1893 break;
1894 case 0xED:
1895 if ((c2 & 0xE0) != 0x80)
1896 return codecvt_base::error;
1897 break;
1898 default:
1899 if ((c2 & 0xC0) != 0x80)
1900 return codecvt_base::error;
1901 break;
1902 }
1903 if ((c3 & 0xC0) != 0x80)
1904 return codecvt_base::error;
1905 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1906 | ((c2 & 0x3F) << 6)
1907 | (c3 & 0x3F));
1908 if (t > Maxcode)
1909 return codecvt_base::error;
1910 *to_nxt = static_cast<uint32_t>(t);
1911 frm_nxt += 3;
1912 }
1913 else if (c1 < 0xF5)
1914 {
1915 if (frm_end-frm_nxt < 4)
1916 return codecvt_base::partial;
1917 uint8_t c2 = frm_nxt[1];
1918 uint8_t c3 = frm_nxt[2];
1919 uint8_t c4 = frm_nxt[3];
1920 switch (c1)
1921 {
1922 case 0xF0:
1923 if (!(0x90 <= c2 && c2 <= 0xBF))
1924 return codecvt_base::error;
1925 break;
1926 case 0xF4:
1927 if ((c2 & 0xF0) != 0x80)
1928 return codecvt_base::error;
1929 break;
1930 default:
1931 if ((c2 & 0xC0) != 0x80)
1932 return codecvt_base::error;
1933 break;
1934 }
1935 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1936 return codecvt_base::error;
1937 if (to_end-to_nxt < 2)
1938 return codecvt_base::partial;
1939 if (((((unsigned long)c1 & 7) << 18) +
1940 (((unsigned long)c2 & 0x3F) << 12) +
1941 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1942 return codecvt_base::error;
1943 *to_nxt = static_cast<uint32_t>(
1944 0xD800
1945 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1946 | ((c2 & 0x0F) << 2)
1947 | ((c3 & 0x30) >> 4));
1948 *++to_nxt = static_cast<uint32_t>(
1949 0xDC00
1950 | ((c3 & 0x0F) << 6)
1951 | (c4 & 0x3F));
1952 frm_nxt += 4;
1953 }
1954 else
1955 {
1956 return codecvt_base::error;
1957 }
1958 }
1959 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1960}
1961
1962static
1963int
1964utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1965 size_t mx, unsigned long Maxcode = 0x10FFFF,
1966 codecvt_mode mode = codecvt_mode(0))
1967{
1968 const uint8_t* frm_nxt = frm;
1969 if (mode & consume_header)
1970 {
1971 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1972 frm_nxt[2] == 0xBF)
1973 frm_nxt += 3;
1974 }
1975 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1976 {
1977 uint8_t c1 = *frm_nxt;
1978 if (c1 > Maxcode)
1979 break;
1980 if (c1 < 0x80)
1981 {
1982 ++frm_nxt;
1983 }
1984 else if (c1 < 0xC2)
1985 {
1986 break;
1987 }
1988 else if (c1 < 0xE0)
1989 {
1990 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1991 break;
1992 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
1993 if (t > Maxcode)
1994 break;
1995 frm_nxt += 2;
1996 }
1997 else if (c1 < 0xF0)
1998 {
1999 if (frm_end-frm_nxt < 3)
2000 break;
2001 uint8_t c2 = frm_nxt[1];
2002 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002003 switch (c1)
2004 {
2005 case 0xE0:
2006 if ((c2 & 0xE0) != 0xA0)
2007 return static_cast<int>(frm_nxt - frm);
2008 break;
2009 case 0xED:
2010 if ((c2 & 0xE0) != 0x80)
2011 return static_cast<int>(frm_nxt - frm);
2012 break;
2013 default:
2014 if ((c2 & 0xC0) != 0x80)
2015 return static_cast<int>(frm_nxt - frm);
2016 break;
2017 }
2018 if ((c3 & 0xC0) != 0x80)
2019 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002020 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002021 break;
2022 frm_nxt += 3;
2023 }
2024 else if (c1 < 0xF5)
2025 {
2026 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2027 break;
2028 uint8_t c2 = frm_nxt[1];
2029 uint8_t c3 = frm_nxt[2];
2030 uint8_t c4 = frm_nxt[3];
2031 switch (c1)
2032 {
2033 case 0xF0:
2034 if (!(0x90 <= c2 && c2 <= 0xBF))
2035 return static_cast<int>(frm_nxt - frm);
2036 break;
2037 case 0xF4:
2038 if ((c2 & 0xF0) != 0x80)
2039 return static_cast<int>(frm_nxt - frm);
2040 break;
2041 default:
2042 if ((c2 & 0xC0) != 0x80)
2043 return static_cast<int>(frm_nxt - frm);
2044 break;
2045 }
2046 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2047 break;
2048 if (((((unsigned long)c1 & 7) << 18) +
2049 (((unsigned long)c2 & 0x3F) << 12) +
2050 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2051 break;
2052 ++nchar16_t;
2053 frm_nxt += 4;
2054 }
2055 else
2056 {
2057 break;
2058 }
2059 }
2060 return static_cast<int>(frm_nxt - frm);
2061}
2062
2063static
2064codecvt_base::result
2065ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2066 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2067 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2068{
2069 frm_nxt = frm;
2070 to_nxt = to;
2071 if (mode & generate_header)
2072 {
2073 if (to_end-to_nxt < 3)
2074 return codecvt_base::partial;
2075 *to_nxt++ = static_cast<uint8_t>(0xEF);
2076 *to_nxt++ = static_cast<uint8_t>(0xBB);
2077 *to_nxt++ = static_cast<uint8_t>(0xBF);
2078 }
2079 for (; frm_nxt < frm_end; ++frm_nxt)
2080 {
2081 uint32_t wc = *frm_nxt;
2082 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2083 return codecvt_base::error;
2084 if (wc < 0x000080)
2085 {
2086 if (to_end-to_nxt < 1)
2087 return codecvt_base::partial;
2088 *to_nxt++ = static_cast<uint8_t>(wc);
2089 }
2090 else if (wc < 0x000800)
2091 {
2092 if (to_end-to_nxt < 2)
2093 return codecvt_base::partial;
2094 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2095 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2096 }
2097 else if (wc < 0x010000)
2098 {
2099 if (to_end-to_nxt < 3)
2100 return codecvt_base::partial;
2101 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2102 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2103 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2104 }
2105 else // if (wc < 0x110000)
2106 {
2107 if (to_end-to_nxt < 4)
2108 return codecvt_base::partial;
2109 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2110 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2111 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2112 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2113 }
2114 }
2115 return codecvt_base::ok;
2116}
2117
2118static
2119codecvt_base::result
2120utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2121 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2122 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2123{
2124 frm_nxt = frm;
2125 to_nxt = to;
2126 if (mode & consume_header)
2127 {
2128 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2129 frm_nxt[2] == 0xBF)
2130 frm_nxt += 3;
2131 }
2132 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2133 {
2134 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2135 if (c1 < 0x80)
2136 {
2137 if (c1 > Maxcode)
2138 return codecvt_base::error;
2139 *to_nxt = static_cast<uint32_t>(c1);
2140 ++frm_nxt;
2141 }
2142 else if (c1 < 0xC2)
2143 {
2144 return codecvt_base::error;
2145 }
2146 else if (c1 < 0xE0)
2147 {
2148 if (frm_end-frm_nxt < 2)
2149 return codecvt_base::partial;
2150 uint8_t c2 = frm_nxt[1];
2151 if ((c2 & 0xC0) != 0x80)
2152 return codecvt_base::error;
2153 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2154 | (c2 & 0x3F));
2155 if (t > Maxcode)
2156 return codecvt_base::error;
2157 *to_nxt = t;
2158 frm_nxt += 2;
2159 }
2160 else if (c1 < 0xF0)
2161 {
2162 if (frm_end-frm_nxt < 3)
2163 return codecvt_base::partial;
2164 uint8_t c2 = frm_nxt[1];
2165 uint8_t c3 = frm_nxt[2];
2166 switch (c1)
2167 {
2168 case 0xE0:
2169 if ((c2 & 0xE0) != 0xA0)
2170 return codecvt_base::error;
2171 break;
2172 case 0xED:
2173 if ((c2 & 0xE0) != 0x80)
2174 return codecvt_base::error;
2175 break;
2176 default:
2177 if ((c2 & 0xC0) != 0x80)
2178 return codecvt_base::error;
2179 break;
2180 }
2181 if ((c3 & 0xC0) != 0x80)
2182 return codecvt_base::error;
2183 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2184 | ((c2 & 0x3F) << 6)
2185 | (c3 & 0x3F));
2186 if (t > Maxcode)
2187 return codecvt_base::error;
2188 *to_nxt = t;
2189 frm_nxt += 3;
2190 }
2191 else if (c1 < 0xF5)
2192 {
2193 if (frm_end-frm_nxt < 4)
2194 return codecvt_base::partial;
2195 uint8_t c2 = frm_nxt[1];
2196 uint8_t c3 = frm_nxt[2];
2197 uint8_t c4 = frm_nxt[3];
2198 switch (c1)
2199 {
2200 case 0xF0:
2201 if (!(0x90 <= c2 && c2 <= 0xBF))
2202 return codecvt_base::error;
2203 break;
2204 case 0xF4:
2205 if ((c2 & 0xF0) != 0x80)
2206 return codecvt_base::error;
2207 break;
2208 default:
2209 if ((c2 & 0xC0) != 0x80)
2210 return codecvt_base::error;
2211 break;
2212 }
2213 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2214 return codecvt_base::error;
2215 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2216 | ((c2 & 0x3F) << 12)
2217 | ((c3 & 0x3F) << 6)
2218 | (c4 & 0x3F));
2219 if (t > Maxcode)
2220 return codecvt_base::error;
2221 *to_nxt = t;
2222 frm_nxt += 4;
2223 }
2224 else
2225 {
2226 return codecvt_base::error;
2227 }
2228 }
2229 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2230}
2231
2232static
2233int
2234utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2235 size_t mx, unsigned long Maxcode = 0x10FFFF,
2236 codecvt_mode mode = codecvt_mode(0))
2237{
2238 const uint8_t* frm_nxt = frm;
2239 if (mode & consume_header)
2240 {
2241 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2242 frm_nxt[2] == 0xBF)
2243 frm_nxt += 3;
2244 }
2245 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2246 {
2247 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2248 if (c1 < 0x80)
2249 {
2250 if (c1 > Maxcode)
2251 break;
2252 ++frm_nxt;
2253 }
2254 else if (c1 < 0xC2)
2255 {
2256 break;
2257 }
2258 else if (c1 < 0xE0)
2259 {
2260 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2261 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002262 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002263 break;
2264 frm_nxt += 2;
2265 }
2266 else if (c1 < 0xF0)
2267 {
2268 if (frm_end-frm_nxt < 3)
2269 break;
2270 uint8_t c2 = frm_nxt[1];
2271 uint8_t c3 = frm_nxt[2];
2272 switch (c1)
2273 {
2274 case 0xE0:
2275 if ((c2 & 0xE0) != 0xA0)
2276 return static_cast<int>(frm_nxt - frm);
2277 break;
2278 case 0xED:
2279 if ((c2 & 0xE0) != 0x80)
2280 return static_cast<int>(frm_nxt - frm);
2281 break;
2282 default:
2283 if ((c2 & 0xC0) != 0x80)
2284 return static_cast<int>(frm_nxt - frm);
2285 break;
2286 }
2287 if ((c3 & 0xC0) != 0x80)
2288 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002289 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002290 break;
2291 frm_nxt += 3;
2292 }
2293 else if (c1 < 0xF5)
2294 {
2295 if (frm_end-frm_nxt < 4)
2296 break;
2297 uint8_t c2 = frm_nxt[1];
2298 uint8_t c3 = frm_nxt[2];
2299 uint8_t c4 = frm_nxt[3];
2300 switch (c1)
2301 {
2302 case 0xF0:
2303 if (!(0x90 <= c2 && c2 <= 0xBF))
2304 return static_cast<int>(frm_nxt - frm);
2305 break;
2306 case 0xF4:
2307 if ((c2 & 0xF0) != 0x80)
2308 return static_cast<int>(frm_nxt - frm);
2309 break;
2310 default:
2311 if ((c2 & 0xC0) != 0x80)
2312 return static_cast<int>(frm_nxt - frm);
2313 break;
2314 }
2315 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2316 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002317 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2318 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002319 break;
2320 frm_nxt += 4;
2321 }
2322 else
2323 {
2324 break;
2325 }
2326 }
2327 return static_cast<int>(frm_nxt - frm);
2328}
2329
2330static
2331codecvt_base::result
2332ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2333 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2334 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2335{
2336 frm_nxt = frm;
2337 to_nxt = to;
2338 if (mode & generate_header)
2339 {
2340 if (to_end-to_nxt < 3)
2341 return codecvt_base::partial;
2342 *to_nxt++ = static_cast<uint8_t>(0xEF);
2343 *to_nxt++ = static_cast<uint8_t>(0xBB);
2344 *to_nxt++ = static_cast<uint8_t>(0xBF);
2345 }
2346 for (; frm_nxt < frm_end; ++frm_nxt)
2347 {
2348 uint16_t wc = *frm_nxt;
2349 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2350 return codecvt_base::error;
2351 if (wc < 0x0080)
2352 {
2353 if (to_end-to_nxt < 1)
2354 return codecvt_base::partial;
2355 *to_nxt++ = static_cast<uint8_t>(wc);
2356 }
2357 else if (wc < 0x0800)
2358 {
2359 if (to_end-to_nxt < 2)
2360 return codecvt_base::partial;
2361 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2362 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2363 }
2364 else // if (wc <= 0xFFFF)
2365 {
2366 if (to_end-to_nxt < 3)
2367 return codecvt_base::partial;
2368 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2369 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2370 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2371 }
2372 }
2373 return codecvt_base::ok;
2374}
2375
2376static
2377codecvt_base::result
2378utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2379 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2380 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2381{
2382 frm_nxt = frm;
2383 to_nxt = to;
2384 if (mode & consume_header)
2385 {
2386 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2387 frm_nxt[2] == 0xBF)
2388 frm_nxt += 3;
2389 }
2390 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2391 {
2392 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2393 if (c1 < 0x80)
2394 {
2395 if (c1 > Maxcode)
2396 return codecvt_base::error;
2397 *to_nxt = static_cast<uint16_t>(c1);
2398 ++frm_nxt;
2399 }
2400 else if (c1 < 0xC2)
2401 {
2402 return codecvt_base::error;
2403 }
2404 else if (c1 < 0xE0)
2405 {
2406 if (frm_end-frm_nxt < 2)
2407 return codecvt_base::partial;
2408 uint8_t c2 = frm_nxt[1];
2409 if ((c2 & 0xC0) != 0x80)
2410 return codecvt_base::error;
2411 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2412 | (c2 & 0x3F));
2413 if (t > Maxcode)
2414 return codecvt_base::error;
2415 *to_nxt = t;
2416 frm_nxt += 2;
2417 }
2418 else if (c1 < 0xF0)
2419 {
2420 if (frm_end-frm_nxt < 3)
2421 return codecvt_base::partial;
2422 uint8_t c2 = frm_nxt[1];
2423 uint8_t c3 = frm_nxt[2];
2424 switch (c1)
2425 {
2426 case 0xE0:
2427 if ((c2 & 0xE0) != 0xA0)
2428 return codecvt_base::error;
2429 break;
2430 case 0xED:
2431 if ((c2 & 0xE0) != 0x80)
2432 return codecvt_base::error;
2433 break;
2434 default:
2435 if ((c2 & 0xC0) != 0x80)
2436 return codecvt_base::error;
2437 break;
2438 }
2439 if ((c3 & 0xC0) != 0x80)
2440 return codecvt_base::error;
2441 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2442 | ((c2 & 0x3F) << 6)
2443 | (c3 & 0x3F));
2444 if (t > Maxcode)
2445 return codecvt_base::error;
2446 *to_nxt = t;
2447 frm_nxt += 3;
2448 }
2449 else
2450 {
2451 return codecvt_base::error;
2452 }
2453 }
2454 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2455}
2456
2457static
2458int
2459utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2460 size_t mx, unsigned long Maxcode = 0x10FFFF,
2461 codecvt_mode mode = codecvt_mode(0))
2462{
2463 const uint8_t* frm_nxt = frm;
2464 if (mode & consume_header)
2465 {
2466 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2467 frm_nxt[2] == 0xBF)
2468 frm_nxt += 3;
2469 }
2470 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2471 {
2472 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2473 if (c1 < 0x80)
2474 {
2475 if (c1 > Maxcode)
2476 break;
2477 ++frm_nxt;
2478 }
2479 else if (c1 < 0xC2)
2480 {
2481 break;
2482 }
2483 else if (c1 < 0xE0)
2484 {
2485 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2486 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002487 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002488 break;
2489 frm_nxt += 2;
2490 }
2491 else if (c1 < 0xF0)
2492 {
2493 if (frm_end-frm_nxt < 3)
2494 break;
2495 uint8_t c2 = frm_nxt[1];
2496 uint8_t c3 = frm_nxt[2];
2497 switch (c1)
2498 {
2499 case 0xE0:
2500 if ((c2 & 0xE0) != 0xA0)
2501 return static_cast<int>(frm_nxt - frm);
2502 break;
2503 case 0xED:
2504 if ((c2 & 0xE0) != 0x80)
2505 return static_cast<int>(frm_nxt - frm);
2506 break;
2507 default:
2508 if ((c2 & 0xC0) != 0x80)
2509 return static_cast<int>(frm_nxt - frm);
2510 break;
2511 }
2512 if ((c3 & 0xC0) != 0x80)
2513 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002514 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002515 break;
2516 frm_nxt += 3;
2517 }
2518 else
2519 {
2520 break;
2521 }
2522 }
2523 return static_cast<int>(frm_nxt - frm);
2524}
2525
2526static
2527codecvt_base::result
2528ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2529 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2530 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2531{
2532 frm_nxt = frm;
2533 to_nxt = to;
2534 if (mode & generate_header)
2535 {
2536 if (to_end-to_nxt < 2)
2537 return codecvt_base::partial;
2538 *to_nxt++ = static_cast<uint8_t>(0xFE);
2539 *to_nxt++ = static_cast<uint8_t>(0xFF);
2540 }
2541 for (; frm_nxt < frm_end; ++frm_nxt)
2542 {
2543 uint32_t wc = *frm_nxt;
2544 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2545 return codecvt_base::error;
2546 if (wc < 0x010000)
2547 {
2548 if (to_end-to_nxt < 2)
2549 return codecvt_base::partial;
2550 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2551 *to_nxt++ = static_cast<uint8_t>(wc);
2552 }
2553 else
2554 {
2555 if (to_end-to_nxt < 4)
2556 return codecvt_base::partial;
2557 uint16_t t = static_cast<uint16_t>(
2558 0xD800
2559 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2560 | ((wc & 0x00FC00) >> 10));
2561 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2562 *to_nxt++ = static_cast<uint8_t>(t);
2563 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2564 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2565 *to_nxt++ = static_cast<uint8_t>(t);
2566 }
2567 }
2568 return codecvt_base::ok;
2569}
2570
2571static
2572codecvt_base::result
2573utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2574 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2575 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2576{
2577 frm_nxt = frm;
2578 to_nxt = to;
2579 if (mode & consume_header)
2580 {
2581 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2582 frm_nxt += 2;
2583 }
2584 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2585 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002586 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002587 if ((c1 & 0xFC00) == 0xDC00)
2588 return codecvt_base::error;
2589 if ((c1 & 0xFC00) != 0xD800)
2590 {
2591 if (c1 > Maxcode)
2592 return codecvt_base::error;
2593 *to_nxt = static_cast<uint32_t>(c1);
2594 frm_nxt += 2;
2595 }
2596 else
2597 {
2598 if (frm_end-frm_nxt < 4)
2599 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002600 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002601 if ((c2 & 0xFC00) != 0xDC00)
2602 return codecvt_base::error;
2603 uint32_t t = static_cast<uint32_t>(
2604 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2605 | ((c1 & 0x003F) << 10)
2606 | (c2 & 0x03FF));
2607 if (t > Maxcode)
2608 return codecvt_base::error;
2609 *to_nxt = t;
2610 frm_nxt += 4;
2611 }
2612 }
2613 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2614}
2615
2616static
2617int
2618utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2619 size_t mx, unsigned long Maxcode = 0x10FFFF,
2620 codecvt_mode mode = codecvt_mode(0))
2621{
2622 const uint8_t* frm_nxt = frm;
2623 frm_nxt = frm;
2624 if (mode & consume_header)
2625 {
2626 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2627 frm_nxt += 2;
2628 }
2629 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2630 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002631 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002632 if ((c1 & 0xFC00) == 0xDC00)
2633 break;
2634 if ((c1 & 0xFC00) != 0xD800)
2635 {
2636 if (c1 > Maxcode)
2637 break;
2638 frm_nxt += 2;
2639 }
2640 else
2641 {
2642 if (frm_end-frm_nxt < 4)
2643 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002644 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002645 if ((c2 & 0xFC00) != 0xDC00)
2646 break;
2647 uint32_t t = static_cast<uint32_t>(
2648 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2649 | ((c1 & 0x003F) << 10)
2650 | (c2 & 0x03FF));
2651 if (t > Maxcode)
2652 break;
2653 frm_nxt += 4;
2654 }
2655 }
2656 return static_cast<int>(frm_nxt - frm);
2657}
2658
2659static
2660codecvt_base::result
2661ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2662 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2663 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2664{
2665 frm_nxt = frm;
2666 to_nxt = to;
2667 if (mode & generate_header)
2668 {
2669 if (to_end-to_nxt < 2)
2670 return codecvt_base::partial;
2671 *to_nxt++ = static_cast<uint8_t>(0xFF);
2672 *to_nxt++ = static_cast<uint8_t>(0xFE);
2673 }
2674 for (; frm_nxt < frm_end; ++frm_nxt)
2675 {
2676 uint32_t wc = *frm_nxt;
2677 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2678 return codecvt_base::error;
2679 if (wc < 0x010000)
2680 {
2681 if (to_end-to_nxt < 2)
2682 return codecvt_base::partial;
2683 *to_nxt++ = static_cast<uint8_t>(wc);
2684 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2685 }
2686 else
2687 {
2688 if (to_end-to_nxt < 4)
2689 return codecvt_base::partial;
2690 uint16_t t = static_cast<uint16_t>(
2691 0xD800
2692 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2693 | ((wc & 0x00FC00) >> 10));
2694 *to_nxt++ = static_cast<uint8_t>(t);
2695 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2696 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2697 *to_nxt++ = static_cast<uint8_t>(t);
2698 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2699 }
2700 }
2701 return codecvt_base::ok;
2702}
2703
2704static
2705codecvt_base::result
2706utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2707 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2708 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2709{
2710 frm_nxt = frm;
2711 to_nxt = to;
2712 if (mode & consume_header)
2713 {
2714 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2715 frm_nxt += 2;
2716 }
2717 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2718 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002719 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002720 if ((c1 & 0xFC00) == 0xDC00)
2721 return codecvt_base::error;
2722 if ((c1 & 0xFC00) != 0xD800)
2723 {
2724 if (c1 > Maxcode)
2725 return codecvt_base::error;
2726 *to_nxt = static_cast<uint32_t>(c1);
2727 frm_nxt += 2;
2728 }
2729 else
2730 {
2731 if (frm_end-frm_nxt < 4)
2732 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002733 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002734 if ((c2 & 0xFC00) != 0xDC00)
2735 return codecvt_base::error;
2736 uint32_t t = static_cast<uint32_t>(
2737 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2738 | ((c1 & 0x003F) << 10)
2739 | (c2 & 0x03FF));
2740 if (t > Maxcode)
2741 return codecvt_base::error;
2742 *to_nxt = t;
2743 frm_nxt += 4;
2744 }
2745 }
2746 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2747}
2748
2749static
2750int
2751utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2752 size_t mx, unsigned long Maxcode = 0x10FFFF,
2753 codecvt_mode mode = codecvt_mode(0))
2754{
2755 const uint8_t* frm_nxt = frm;
2756 frm_nxt = frm;
2757 if (mode & consume_header)
2758 {
2759 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2760 frm_nxt += 2;
2761 }
2762 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2763 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002764 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002765 if ((c1 & 0xFC00) == 0xDC00)
2766 break;
2767 if ((c1 & 0xFC00) != 0xD800)
2768 {
2769 if (c1 > Maxcode)
2770 break;
2771 frm_nxt += 2;
2772 }
2773 else
2774 {
2775 if (frm_end-frm_nxt < 4)
2776 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002777 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002778 if ((c2 & 0xFC00) != 0xDC00)
2779 break;
2780 uint32_t t = static_cast<uint32_t>(
2781 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2782 | ((c1 & 0x003F) << 10)
2783 | (c2 & 0x03FF));
2784 if (t > Maxcode)
2785 break;
2786 frm_nxt += 4;
2787 }
2788 }
2789 return static_cast<int>(frm_nxt - frm);
2790}
2791
2792static
2793codecvt_base::result
2794ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2795 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2796 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2797{
2798 frm_nxt = frm;
2799 to_nxt = to;
2800 if (mode & generate_header)
2801 {
2802 if (to_end-to_nxt < 2)
2803 return codecvt_base::partial;
2804 *to_nxt++ = static_cast<uint8_t>(0xFE);
2805 *to_nxt++ = static_cast<uint8_t>(0xFF);
2806 }
2807 for (; frm_nxt < frm_end; ++frm_nxt)
2808 {
2809 uint16_t wc = *frm_nxt;
2810 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2811 return codecvt_base::error;
2812 if (to_end-to_nxt < 2)
2813 return codecvt_base::partial;
2814 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2815 *to_nxt++ = static_cast<uint8_t>(wc);
2816 }
2817 return codecvt_base::ok;
2818}
2819
2820static
2821codecvt_base::result
2822utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2823 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2824 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2825{
2826 frm_nxt = frm;
2827 to_nxt = to;
2828 if (mode & consume_header)
2829 {
2830 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2831 frm_nxt += 2;
2832 }
2833 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2834 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002835 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002836 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2837 return codecvt_base::error;
2838 *to_nxt = c1;
2839 frm_nxt += 2;
2840 }
2841 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2842}
2843
2844static
2845int
2846utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2847 size_t mx, unsigned long Maxcode = 0x10FFFF,
2848 codecvt_mode mode = codecvt_mode(0))
2849{
2850 const uint8_t* frm_nxt = frm;
2851 frm_nxt = frm;
2852 if (mode & consume_header)
2853 {
2854 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2855 frm_nxt += 2;
2856 }
2857 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2858 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002859 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002860 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2861 break;
2862 frm_nxt += 2;
2863 }
2864 return static_cast<int>(frm_nxt - frm);
2865}
2866
2867static
2868codecvt_base::result
2869ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2870 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2871 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2872{
2873 frm_nxt = frm;
2874 to_nxt = to;
2875 if (mode & generate_header)
2876 {
2877 if (to_end-to_nxt < 2)
2878 return codecvt_base::partial;
2879 *to_nxt++ = static_cast<uint8_t>(0xFF);
2880 *to_nxt++ = static_cast<uint8_t>(0xFE);
2881 }
2882 for (; frm_nxt < frm_end; ++frm_nxt)
2883 {
2884 uint16_t wc = *frm_nxt;
2885 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2886 return codecvt_base::error;
2887 if (to_end-to_nxt < 2)
2888 return codecvt_base::partial;
2889 *to_nxt++ = static_cast<uint8_t>(wc);
2890 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2891 }
2892 return codecvt_base::ok;
2893}
2894
2895static
2896codecvt_base::result
2897utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2898 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2899 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2900{
2901 frm_nxt = frm;
2902 to_nxt = to;
2903 if (mode & consume_header)
2904 {
2905 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2906 frm_nxt += 2;
2907 }
2908 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2909 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002910 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002911 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2912 return codecvt_base::error;
2913 *to_nxt = c1;
2914 frm_nxt += 2;
2915 }
2916 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2917}
2918
2919static
2920int
2921utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2922 size_t mx, unsigned long Maxcode = 0x10FFFF,
2923 codecvt_mode mode = codecvt_mode(0))
2924{
2925 const uint8_t* frm_nxt = frm;
2926 frm_nxt = frm;
2927 if (mode & consume_header)
2928 {
2929 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2930 frm_nxt += 2;
2931 }
2932 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2933 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002934 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002935 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2936 break;
2937 frm_nxt += 2;
2938 }
2939 return static_cast<int>(frm_nxt - frm);
2940}
2941
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002942// template <> class codecvt<char16_t, char, mbstate_t>
2943
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002944locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002945
2946codecvt<char16_t, char, mbstate_t>::~codecvt()
2947{
2948}
2949
2950codecvt<char16_t, char, mbstate_t>::result
2951codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002952 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002953 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2954{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002955 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2956 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2957 const uint16_t* _frm_nxt = _frm;
2958 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2959 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2960 uint8_t* _to_nxt = _to;
2961 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2962 frm_nxt = frm + (_frm_nxt - _frm);
2963 to_nxt = to + (_to_nxt - _to);
2964 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002965}
2966
2967codecvt<char16_t, char, mbstate_t>::result
2968codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002969 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002970 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2971{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002972 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2973 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2974 const uint8_t* _frm_nxt = _frm;
2975 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2976 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2977 uint16_t* _to_nxt = _to;
2978 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2979 frm_nxt = frm + (_frm_nxt - _frm);
2980 to_nxt = to + (_to_nxt - _to);
2981 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002982}
2983
2984codecvt<char16_t, char, mbstate_t>::result
2985codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
2986 extern_type* to, extern_type*, extern_type*& to_nxt) const
2987{
2988 to_nxt = to;
2989 return noconv;
2990}
2991
2992int
Howard Hinnantc9834542011-05-31 15:34:58 +00002993codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002994{
2995 return 0;
2996}
2997
2998bool
Howard Hinnantc9834542011-05-31 15:34:58 +00002999codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003000{
3001 return false;
3002}
3003
3004int
3005codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3006 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3007{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003008 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3009 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3010 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003011}
3012
3013int
Howard Hinnantc9834542011-05-31 15:34:58 +00003014codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003015{
3016 return 4;
3017}
3018
3019// template <> class codecvt<char32_t, char, mbstate_t>
3020
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003021locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003022
3023codecvt<char32_t, char, mbstate_t>::~codecvt()
3024{
3025}
3026
3027codecvt<char32_t, char, mbstate_t>::result
3028codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003029 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003030 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3031{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003032 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3033 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3034 const uint32_t* _frm_nxt = _frm;
3035 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3036 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3037 uint8_t* _to_nxt = _to;
3038 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3039 frm_nxt = frm + (_frm_nxt - _frm);
3040 to_nxt = to + (_to_nxt - _to);
3041 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003042}
3043
3044codecvt<char32_t, char, mbstate_t>::result
3045codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003046 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003047 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3048{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003049 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3050 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3051 const uint8_t* _frm_nxt = _frm;
3052 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3053 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3054 uint32_t* _to_nxt = _to;
3055 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3056 frm_nxt = frm + (_frm_nxt - _frm);
3057 to_nxt = to + (_to_nxt - _to);
3058 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003059}
3060
3061codecvt<char32_t, char, mbstate_t>::result
3062codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3063 extern_type* to, extern_type*, extern_type*& to_nxt) const
3064{
3065 to_nxt = to;
3066 return noconv;
3067}
3068
3069int
Howard Hinnantc9834542011-05-31 15:34:58 +00003070codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003071{
3072 return 0;
3073}
3074
3075bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003076codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003077{
3078 return false;
3079}
3080
3081int
3082codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3083 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3084{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003085 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3086 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3087 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003088}
3089
3090int
Howard Hinnantc9834542011-05-31 15:34:58 +00003091codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003092{
3093 return 4;
3094}
3095
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003096// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003097
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003098__codecvt_utf8<wchar_t>::result
3099__codecvt_utf8<wchar_t>::do_out(state_type&,
3100 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003101 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3102{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003103 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3104 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3105 const uint32_t* _frm_nxt = _frm;
3106 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3107 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3108 uint8_t* _to_nxt = _to;
3109 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3110 _Maxcode_, _Mode_);
3111 frm_nxt = frm + (_frm_nxt - _frm);
3112 to_nxt = to + (_to_nxt - _to);
3113 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003114}
3115
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003116__codecvt_utf8<wchar_t>::result
3117__codecvt_utf8<wchar_t>::do_in(state_type&,
3118 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003119 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3120{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003121 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3122 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3123 const uint8_t* _frm_nxt = _frm;
3124 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3125 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3126 uint32_t* _to_nxt = _to;
3127 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3128 _Maxcode_, _Mode_);
3129 frm_nxt = frm + (_frm_nxt - _frm);
3130 to_nxt = to + (_to_nxt - _to);
3131 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003132}
3133
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003134__codecvt_utf8<wchar_t>::result
3135__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003136 extern_type* to, extern_type*, extern_type*& to_nxt) const
3137{
3138 to_nxt = to;
3139 return noconv;
3140}
3141
3142int
Howard Hinnantc9834542011-05-31 15:34:58 +00003143__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003144{
3145 return 0;
3146}
3147
3148bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003149__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003150{
3151 return false;
3152}
3153
3154int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003155__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003156 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3157{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003158 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3159 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3160 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003161}
3162
3163int
Howard Hinnantc9834542011-05-31 15:34:58 +00003164__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003165{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003166 if (_Mode_ & consume_header)
3167 return 7;
3168 return 4;
3169}
3170
3171// __codecvt_utf8<char16_t>
3172
3173__codecvt_utf8<char16_t>::result
3174__codecvt_utf8<char16_t>::do_out(state_type&,
3175 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3176 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3177{
3178 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3179 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3180 const uint16_t* _frm_nxt = _frm;
3181 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3182 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3183 uint8_t* _to_nxt = _to;
3184 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3185 _Maxcode_, _Mode_);
3186 frm_nxt = frm + (_frm_nxt - _frm);
3187 to_nxt = to + (_to_nxt - _to);
3188 return r;
3189}
3190
3191__codecvt_utf8<char16_t>::result
3192__codecvt_utf8<char16_t>::do_in(state_type&,
3193 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3194 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3195{
3196 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3197 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3198 const uint8_t* _frm_nxt = _frm;
3199 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3200 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3201 uint16_t* _to_nxt = _to;
3202 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3203 _Maxcode_, _Mode_);
3204 frm_nxt = frm + (_frm_nxt - _frm);
3205 to_nxt = to + (_to_nxt - _to);
3206 return r;
3207}
3208
3209__codecvt_utf8<char16_t>::result
3210__codecvt_utf8<char16_t>::do_unshift(state_type&,
3211 extern_type* to, extern_type*, extern_type*& to_nxt) const
3212{
3213 to_nxt = to;
3214 return noconv;
3215}
3216
3217int
Howard Hinnantc9834542011-05-31 15:34:58 +00003218__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003219{
3220 return 0;
3221}
3222
3223bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003224__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003225{
3226 return false;
3227}
3228
3229int
3230__codecvt_utf8<char16_t>::do_length(state_type&,
3231 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3232{
3233 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3234 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3235 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3236}
3237
3238int
Howard Hinnantc9834542011-05-31 15:34:58 +00003239__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003240{
3241 if (_Mode_ & consume_header)
3242 return 6;
3243 return 3;
3244}
3245
3246// __codecvt_utf8<char32_t>
3247
3248__codecvt_utf8<char32_t>::result
3249__codecvt_utf8<char32_t>::do_out(state_type&,
3250 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3251 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3252{
3253 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3254 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3255 const uint32_t* _frm_nxt = _frm;
3256 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3257 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3258 uint8_t* _to_nxt = _to;
3259 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3260 _Maxcode_, _Mode_);
3261 frm_nxt = frm + (_frm_nxt - _frm);
3262 to_nxt = to + (_to_nxt - _to);
3263 return r;
3264}
3265
3266__codecvt_utf8<char32_t>::result
3267__codecvt_utf8<char32_t>::do_in(state_type&,
3268 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3269 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3270{
3271 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3272 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3273 const uint8_t* _frm_nxt = _frm;
3274 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3275 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3276 uint32_t* _to_nxt = _to;
3277 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3278 _Maxcode_, _Mode_);
3279 frm_nxt = frm + (_frm_nxt - _frm);
3280 to_nxt = to + (_to_nxt - _to);
3281 return r;
3282}
3283
3284__codecvt_utf8<char32_t>::result
3285__codecvt_utf8<char32_t>::do_unshift(state_type&,
3286 extern_type* to, extern_type*, extern_type*& to_nxt) const
3287{
3288 to_nxt = to;
3289 return noconv;
3290}
3291
3292int
Howard Hinnantc9834542011-05-31 15:34:58 +00003293__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003294{
3295 return 0;
3296}
3297
3298bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003299__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003300{
3301 return false;
3302}
3303
3304int
3305__codecvt_utf8<char32_t>::do_length(state_type&,
3306 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3307{
3308 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3309 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3310 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3311}
3312
3313int
Howard Hinnantc9834542011-05-31 15:34:58 +00003314__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003315{
3316 if (_Mode_ & consume_header)
3317 return 7;
3318 return 4;
3319}
3320
3321// __codecvt_utf16<wchar_t, false>
3322
3323__codecvt_utf16<wchar_t, false>::result
3324__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3325 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3326 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3327{
3328 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3329 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3330 const uint32_t* _frm_nxt = _frm;
3331 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3332 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3333 uint8_t* _to_nxt = _to;
3334 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3335 _Maxcode_, _Mode_);
3336 frm_nxt = frm + (_frm_nxt - _frm);
3337 to_nxt = to + (_to_nxt - _to);
3338 return r;
3339}
3340
3341__codecvt_utf16<wchar_t, false>::result
3342__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3343 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3344 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3345{
3346 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3347 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3348 const uint8_t* _frm_nxt = _frm;
3349 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3350 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3351 uint32_t* _to_nxt = _to;
3352 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3353 _Maxcode_, _Mode_);
3354 frm_nxt = frm + (_frm_nxt - _frm);
3355 to_nxt = to + (_to_nxt - _to);
3356 return r;
3357}
3358
3359__codecvt_utf16<wchar_t, false>::result
3360__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3361 extern_type* to, extern_type*, extern_type*& to_nxt) const
3362{
3363 to_nxt = to;
3364 return noconv;
3365}
3366
3367int
Howard Hinnantc9834542011-05-31 15:34:58 +00003368__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003369{
3370 return 0;
3371}
3372
3373bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003374__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003375{
3376 return false;
3377}
3378
3379int
3380__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3381 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3382{
3383 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3384 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3385 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3386}
3387
3388int
Howard Hinnantc9834542011-05-31 15:34:58 +00003389__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003390{
3391 if (_Mode_ & consume_header)
3392 return 6;
3393 return 4;
3394}
3395
3396// __codecvt_utf16<wchar_t, true>
3397
3398__codecvt_utf16<wchar_t, true>::result
3399__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3400 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3401 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3402{
3403 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3404 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3405 const uint32_t* _frm_nxt = _frm;
3406 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3407 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3408 uint8_t* _to_nxt = _to;
3409 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3410 _Maxcode_, _Mode_);
3411 frm_nxt = frm + (_frm_nxt - _frm);
3412 to_nxt = to + (_to_nxt - _to);
3413 return r;
3414}
3415
3416__codecvt_utf16<wchar_t, true>::result
3417__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3418 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3419 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3420{
3421 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3422 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3423 const uint8_t* _frm_nxt = _frm;
3424 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3425 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3426 uint32_t* _to_nxt = _to;
3427 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3428 _Maxcode_, _Mode_);
3429 frm_nxt = frm + (_frm_nxt - _frm);
3430 to_nxt = to + (_to_nxt - _to);
3431 return r;
3432}
3433
3434__codecvt_utf16<wchar_t, true>::result
3435__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3436 extern_type* to, extern_type*, extern_type*& to_nxt) const
3437{
3438 to_nxt = to;
3439 return noconv;
3440}
3441
3442int
Howard Hinnantc9834542011-05-31 15:34:58 +00003443__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003444{
3445 return 0;
3446}
3447
3448bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003449__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003450{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003451 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003452}
3453
3454int
3455__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3456 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3457{
3458 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3459 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3460 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3461}
3462
3463int
Howard Hinnantc9834542011-05-31 15:34:58 +00003464__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003465{
3466 if (_Mode_ & consume_header)
3467 return 6;
3468 return 4;
3469}
3470
3471// __codecvt_utf16<char16_t, false>
3472
3473__codecvt_utf16<char16_t, false>::result
3474__codecvt_utf16<char16_t, false>::do_out(state_type&,
3475 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3476 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3477{
3478 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3479 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3480 const uint16_t* _frm_nxt = _frm;
3481 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3482 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3483 uint8_t* _to_nxt = _to;
3484 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3485 _Maxcode_, _Mode_);
3486 frm_nxt = frm + (_frm_nxt - _frm);
3487 to_nxt = to + (_to_nxt - _to);
3488 return r;
3489}
3490
3491__codecvt_utf16<char16_t, false>::result
3492__codecvt_utf16<char16_t, false>::do_in(state_type&,
3493 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3494 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3495{
3496 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3497 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3498 const uint8_t* _frm_nxt = _frm;
3499 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3500 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3501 uint16_t* _to_nxt = _to;
3502 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3503 _Maxcode_, _Mode_);
3504 frm_nxt = frm + (_frm_nxt - _frm);
3505 to_nxt = to + (_to_nxt - _to);
3506 return r;
3507}
3508
3509__codecvt_utf16<char16_t, false>::result
3510__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3511 extern_type* to, extern_type*, extern_type*& to_nxt) const
3512{
3513 to_nxt = to;
3514 return noconv;
3515}
3516
3517int
Howard Hinnantc9834542011-05-31 15:34:58 +00003518__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003519{
3520 return 0;
3521}
3522
3523bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003524__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003525{
3526 return false;
3527}
3528
3529int
3530__codecvt_utf16<char16_t, false>::do_length(state_type&,
3531 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3532{
3533 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3534 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3535 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3536}
3537
3538int
Howard Hinnantc9834542011-05-31 15:34:58 +00003539__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003540{
3541 if (_Mode_ & consume_header)
3542 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003543 return 2;
3544}
3545
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003546// __codecvt_utf16<char16_t, true>
3547
3548__codecvt_utf16<char16_t, true>::result
3549__codecvt_utf16<char16_t, true>::do_out(state_type&,
3550 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3551 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3552{
3553 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3554 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3555 const uint16_t* _frm_nxt = _frm;
3556 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3557 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3558 uint8_t* _to_nxt = _to;
3559 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3560 _Maxcode_, _Mode_);
3561 frm_nxt = frm + (_frm_nxt - _frm);
3562 to_nxt = to + (_to_nxt - _to);
3563 return r;
3564}
3565
3566__codecvt_utf16<char16_t, true>::result
3567__codecvt_utf16<char16_t, true>::do_in(state_type&,
3568 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3569 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3570{
3571 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3572 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3573 const uint8_t* _frm_nxt = _frm;
3574 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3575 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3576 uint16_t* _to_nxt = _to;
3577 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3578 _Maxcode_, _Mode_);
3579 frm_nxt = frm + (_frm_nxt - _frm);
3580 to_nxt = to + (_to_nxt - _to);
3581 return r;
3582}
3583
3584__codecvt_utf16<char16_t, true>::result
3585__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3586 extern_type* to, extern_type*, extern_type*& to_nxt) const
3587{
3588 to_nxt = to;
3589 return noconv;
3590}
3591
3592int
Howard Hinnantc9834542011-05-31 15:34:58 +00003593__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003594{
3595 return 0;
3596}
3597
3598bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003599__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003600{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003601 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003602}
3603
3604int
3605__codecvt_utf16<char16_t, true>::do_length(state_type&,
3606 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3607{
3608 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3609 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3610 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3611}
3612
3613int
Howard Hinnantc9834542011-05-31 15:34:58 +00003614__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003615{
3616 if (_Mode_ & consume_header)
3617 return 4;
3618 return 2;
3619}
3620
3621// __codecvt_utf16<char32_t, false>
3622
3623__codecvt_utf16<char32_t, false>::result
3624__codecvt_utf16<char32_t, false>::do_out(state_type&,
3625 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3626 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3627{
3628 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3629 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3630 const uint32_t* _frm_nxt = _frm;
3631 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3632 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3633 uint8_t* _to_nxt = _to;
3634 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3635 _Maxcode_, _Mode_);
3636 frm_nxt = frm + (_frm_nxt - _frm);
3637 to_nxt = to + (_to_nxt - _to);
3638 return r;
3639}
3640
3641__codecvt_utf16<char32_t, false>::result
3642__codecvt_utf16<char32_t, false>::do_in(state_type&,
3643 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3644 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3645{
3646 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3647 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3648 const uint8_t* _frm_nxt = _frm;
3649 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3650 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3651 uint32_t* _to_nxt = _to;
3652 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3653 _Maxcode_, _Mode_);
3654 frm_nxt = frm + (_frm_nxt - _frm);
3655 to_nxt = to + (_to_nxt - _to);
3656 return r;
3657}
3658
3659__codecvt_utf16<char32_t, false>::result
3660__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3661 extern_type* to, extern_type*, extern_type*& to_nxt) const
3662{
3663 to_nxt = to;
3664 return noconv;
3665}
3666
3667int
Howard Hinnantc9834542011-05-31 15:34:58 +00003668__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003669{
3670 return 0;
3671}
3672
3673bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003674__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003675{
3676 return false;
3677}
3678
3679int
3680__codecvt_utf16<char32_t, false>::do_length(state_type&,
3681 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3682{
3683 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3684 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3685 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3686}
3687
3688int
Howard Hinnantc9834542011-05-31 15:34:58 +00003689__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003690{
3691 if (_Mode_ & consume_header)
3692 return 6;
3693 return 4;
3694}
3695
3696// __codecvt_utf16<char32_t, true>
3697
3698__codecvt_utf16<char32_t, true>::result
3699__codecvt_utf16<char32_t, true>::do_out(state_type&,
3700 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3701 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3702{
3703 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3704 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3705 const uint32_t* _frm_nxt = _frm;
3706 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3707 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3708 uint8_t* _to_nxt = _to;
3709 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3710 _Maxcode_, _Mode_);
3711 frm_nxt = frm + (_frm_nxt - _frm);
3712 to_nxt = to + (_to_nxt - _to);
3713 return r;
3714}
3715
3716__codecvt_utf16<char32_t, true>::result
3717__codecvt_utf16<char32_t, true>::do_in(state_type&,
3718 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3719 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3720{
3721 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3722 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3723 const uint8_t* _frm_nxt = _frm;
3724 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3725 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3726 uint32_t* _to_nxt = _to;
3727 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3728 _Maxcode_, _Mode_);
3729 frm_nxt = frm + (_frm_nxt - _frm);
3730 to_nxt = to + (_to_nxt - _to);
3731 return r;
3732}
3733
3734__codecvt_utf16<char32_t, true>::result
3735__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3736 extern_type* to, extern_type*, extern_type*& to_nxt) const
3737{
3738 to_nxt = to;
3739 return noconv;
3740}
3741
3742int
Howard Hinnantc9834542011-05-31 15:34:58 +00003743__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003744{
3745 return 0;
3746}
3747
3748bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003749__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003750{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003751 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003752}
3753
3754int
3755__codecvt_utf16<char32_t, true>::do_length(state_type&,
3756 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3757{
3758 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3759 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3760 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3761}
3762
3763int
Howard Hinnantc9834542011-05-31 15:34:58 +00003764__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003765{
3766 if (_Mode_ & consume_header)
3767 return 6;
3768 return 4;
3769}
3770
3771// __codecvt_utf8_utf16<wchar_t>
3772
3773__codecvt_utf8_utf16<wchar_t>::result
3774__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3775 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3776 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3777{
3778 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3779 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3780 const uint32_t* _frm_nxt = _frm;
3781 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3782 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3783 uint8_t* _to_nxt = _to;
3784 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3785 _Maxcode_, _Mode_);
3786 frm_nxt = frm + (_frm_nxt - _frm);
3787 to_nxt = to + (_to_nxt - _to);
3788 return r;
3789}
3790
3791__codecvt_utf8_utf16<wchar_t>::result
3792__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3793 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3794 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3795{
3796 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3797 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3798 const uint8_t* _frm_nxt = _frm;
3799 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3800 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3801 uint32_t* _to_nxt = _to;
3802 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3803 _Maxcode_, _Mode_);
3804 frm_nxt = frm + (_frm_nxt - _frm);
3805 to_nxt = to + (_to_nxt - _to);
3806 return r;
3807}
3808
3809__codecvt_utf8_utf16<wchar_t>::result
3810__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3811 extern_type* to, extern_type*, extern_type*& to_nxt) const
3812{
3813 to_nxt = to;
3814 return noconv;
3815}
3816
3817int
Howard Hinnantc9834542011-05-31 15:34:58 +00003818__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003819{
3820 return 0;
3821}
3822
3823bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003824__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003825{
3826 return false;
3827}
3828
3829int
3830__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3831 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3832{
3833 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3834 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3835 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3836}
3837
3838int
Howard Hinnantc9834542011-05-31 15:34:58 +00003839__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003840{
3841 if (_Mode_ & consume_header)
3842 return 7;
3843 return 4;
3844}
3845
3846// __codecvt_utf8_utf16<char16_t>
3847
3848__codecvt_utf8_utf16<char16_t>::result
3849__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3850 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3851 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3852{
3853 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3854 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3855 const uint16_t* _frm_nxt = _frm;
3856 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3857 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3858 uint8_t* _to_nxt = _to;
3859 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3860 _Maxcode_, _Mode_);
3861 frm_nxt = frm + (_frm_nxt - _frm);
3862 to_nxt = to + (_to_nxt - _to);
3863 return r;
3864}
3865
3866__codecvt_utf8_utf16<char16_t>::result
3867__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3868 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3869 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3870{
3871 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3872 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3873 const uint8_t* _frm_nxt = _frm;
3874 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3875 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3876 uint16_t* _to_nxt = _to;
3877 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3878 _Maxcode_, _Mode_);
3879 frm_nxt = frm + (_frm_nxt - _frm);
3880 to_nxt = to + (_to_nxt - _to);
3881 return r;
3882}
3883
3884__codecvt_utf8_utf16<char16_t>::result
3885__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3886 extern_type* to, extern_type*, extern_type*& to_nxt) const
3887{
3888 to_nxt = to;
3889 return noconv;
3890}
3891
3892int
Howard Hinnantc9834542011-05-31 15:34:58 +00003893__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003894{
3895 return 0;
3896}
3897
3898bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003899__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003900{
3901 return false;
3902}
3903
3904int
3905__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3906 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3907{
3908 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3909 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3910 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3911}
3912
3913int
Howard Hinnantc9834542011-05-31 15:34:58 +00003914__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003915{
3916 if (_Mode_ & consume_header)
3917 return 7;
3918 return 4;
3919}
3920
3921// __codecvt_utf8_utf16<char32_t>
3922
3923__codecvt_utf8_utf16<char32_t>::result
3924__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3925 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3926 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3927{
3928 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3929 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3930 const uint32_t* _frm_nxt = _frm;
3931 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3932 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3933 uint8_t* _to_nxt = _to;
3934 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3935 _Maxcode_, _Mode_);
3936 frm_nxt = frm + (_frm_nxt - _frm);
3937 to_nxt = to + (_to_nxt - _to);
3938 return r;
3939}
3940
3941__codecvt_utf8_utf16<char32_t>::result
3942__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3943 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3944 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3945{
3946 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3947 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3948 const uint8_t* _frm_nxt = _frm;
3949 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3950 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3951 uint32_t* _to_nxt = _to;
3952 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3953 _Maxcode_, _Mode_);
3954 frm_nxt = frm + (_frm_nxt - _frm);
3955 to_nxt = to + (_to_nxt - _to);
3956 return r;
3957}
3958
3959__codecvt_utf8_utf16<char32_t>::result
3960__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3961 extern_type* to, extern_type*, extern_type*& to_nxt) const
3962{
3963 to_nxt = to;
3964 return noconv;
3965}
3966
3967int
Howard Hinnantc9834542011-05-31 15:34:58 +00003968__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003969{
3970 return 0;
3971}
3972
3973bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003974__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003975{
3976 return false;
3977}
3978
3979int
3980__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3981 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3982{
3983 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3984 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3985 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3986}
3987
3988int
Howard Hinnantc9834542011-05-31 15:34:58 +00003989__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003990{
3991 if (_Mode_ & consume_header)
3992 return 7;
3993 return 4;
3994}
3995
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003996// __narrow_to_utf8<16>
3997
3998__narrow_to_utf8<16>::~__narrow_to_utf8()
3999{
4000}
4001
4002// __narrow_to_utf8<32>
4003
4004__narrow_to_utf8<32>::~__narrow_to_utf8()
4005{
4006}
4007
4008// __widen_from_utf8<16>
4009
4010__widen_from_utf8<16>::~__widen_from_utf8()
4011{
4012}
4013
4014// __widen_from_utf8<32>
4015
4016__widen_from_utf8<32>::~__widen_from_utf8()
4017{
4018}
4019
4020// numpunct<char> && numpunct<wchar_t>
4021
4022locale::id numpunct< char >::id;
4023locale::id numpunct<wchar_t>::id;
4024
4025numpunct<char>::numpunct(size_t refs)
4026 : locale::facet(refs),
4027 __decimal_point_('.'),
4028 __thousands_sep_(',')
4029{
4030}
4031
4032numpunct<wchar_t>::numpunct(size_t refs)
4033 : locale::facet(refs),
4034 __decimal_point_(L'.'),
4035 __thousands_sep_(L',')
4036{
4037}
4038
4039numpunct<char>::~numpunct()
4040{
4041}
4042
4043numpunct<wchar_t>::~numpunct()
4044{
4045}
4046
4047 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4048wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4049
4050 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4051wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4052
4053string numpunct< char >::do_grouping() const {return __grouping_;}
4054string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4055
4056 string numpunct< char >::do_truename() const {return "true";}
4057wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4058
4059 string numpunct< char >::do_falsename() const {return "false";}
4060wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4061
4062// numpunct_byname<char>
4063
4064numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4065 : numpunct<char>(refs)
4066{
4067 __init(nm);
4068}
4069
4070numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4071 : numpunct<char>(refs)
4072{
4073 __init(nm.c_str());
4074}
4075
4076numpunct_byname<char>::~numpunct_byname()
4077{
4078}
4079
4080void
4081numpunct_byname<char>::__init(const char* nm)
4082{
4083 if (strcmp(nm, "C") != 0)
4084 {
Sean Huntf3907e62011-07-15 05:40:33 +00004085 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004086#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004087 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004088 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4089 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004090#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004091#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004092 lconv* lc = localeconv_l(loc.get());
4093#else
4094 lconv* lc = __localeconv_l(loc.get());
4095#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004096 if (*lc->decimal_point)
4097 __decimal_point_ = *lc->decimal_point;
4098 if (*lc->thousands_sep)
4099 __thousands_sep_ = *lc->thousands_sep;
4100 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004101 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004102 }
4103}
4104
4105// numpunct_byname<wchar_t>
4106
4107numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4108 : numpunct<wchar_t>(refs)
4109{
4110 __init(nm);
4111}
4112
4113numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4114 : numpunct<wchar_t>(refs)
4115{
4116 __init(nm.c_str());
4117}
4118
4119numpunct_byname<wchar_t>::~numpunct_byname()
4120{
4121}
4122
4123void
4124numpunct_byname<wchar_t>::__init(const char* nm)
4125{
4126 if (strcmp(nm, "C") != 0)
4127 {
Sean Huntf3907e62011-07-15 05:40:33 +00004128 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004129#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004130 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004131 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4132 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004133#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004134#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004135 lconv* lc = localeconv_l(loc.get());
4136#else
4137 lconv* lc = __localeconv_l(loc.get());
4138#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004139 if (*lc->decimal_point)
4140 __decimal_point_ = *lc->decimal_point;
4141 if (*lc->thousands_sep)
4142 __thousands_sep_ = *lc->thousands_sep;
4143 __grouping_ = lc->grouping;
4144 // locallization for truename and falsename is not available
4145 }
4146}
4147
4148// num_get helpers
4149
4150int
4151__num_get_base::__get_base(ios_base& iob)
4152{
4153 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4154 if (__basefield == ios_base::oct)
4155 return 8;
4156 else if (__basefield == ios_base::hex)
4157 return 16;
4158 else if (__basefield == 0)
4159 return 0;
4160 return 10;
4161}
4162
4163const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4164
4165void
4166__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4167 ios_base::iostate& __err)
4168{
4169 if (__grouping.size() != 0)
4170 {
4171 reverse(__g, __g_end);
4172 const char* __ig = __grouping.data();
4173 const char* __eg = __ig + __grouping.size();
4174 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4175 {
4176 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4177 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004178 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004179 {
4180 __err = ios_base::failbit;
4181 return;
4182 }
4183 }
4184 if (__eg - __ig > 1)
4185 ++__ig;
4186 }
4187 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4188 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004189 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004190 __err = ios_base::failbit;
4191 }
4192 }
4193}
4194
4195void
4196__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4197 ios_base::fmtflags __flags)
4198{
4199 if (__flags & ios_base::showpos)
4200 *__fmtp++ = '+';
4201 if (__flags & ios_base::showbase)
4202 *__fmtp++ = '#';
4203 while(*__len)
4204 *__fmtp++ = *__len++;
4205 if ((__flags & ios_base::basefield) == ios_base::oct)
4206 *__fmtp = 'o';
4207 else if ((__flags & ios_base::basefield) == ios_base::hex)
4208 {
4209 if (__flags & ios_base::uppercase)
4210 *__fmtp = 'X';
4211 else
4212 *__fmtp = 'x';
4213 }
4214 else if (__signd)
4215 *__fmtp = 'd';
4216 else
4217 *__fmtp = 'u';
4218}
4219
4220bool
4221__num_put_base::__format_float(char* __fmtp, const char* __len,
4222 ios_base::fmtflags __flags)
4223{
4224 bool specify_precision = true;
4225 if (__flags & ios_base::showpos)
4226 *__fmtp++ = '+';
4227 if (__flags & ios_base::showpoint)
4228 *__fmtp++ = '#';
4229 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4230 bool uppercase = __flags & ios_base::uppercase;
4231 if (floatfield == (ios_base::fixed | ios_base::scientific))
4232 specify_precision = false;
4233 else
4234 {
4235 *__fmtp++ = '.';
4236 *__fmtp++ = '*';
4237 }
4238 while(*__len)
4239 *__fmtp++ = *__len++;
4240 if (floatfield == ios_base::fixed)
4241 {
4242 if (uppercase)
4243 *__fmtp = 'F';
4244 else
4245 *__fmtp = 'f';
4246 }
4247 else if (floatfield == ios_base::scientific)
4248 {
4249 if (uppercase)
4250 *__fmtp = 'E';
4251 else
4252 *__fmtp = 'e';
4253 }
4254 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4255 {
4256 if (uppercase)
4257 *__fmtp = 'A';
4258 else
4259 *__fmtp = 'a';
4260 }
4261 else
4262 {
4263 if (uppercase)
4264 *__fmtp = 'G';
4265 else
4266 *__fmtp = 'g';
4267 }
4268 return specify_precision;
4269}
4270
4271char*
4272__num_put_base::__identify_padding(char* __nb, char* __ne,
4273 const ios_base& __iob)
4274{
4275 switch (__iob.flags() & ios_base::adjustfield)
4276 {
4277 case ios_base::internal:
4278 if (__nb[0] == '-' || __nb[0] == '+')
4279 return __nb+1;
4280 if (__ne - __nb >= 2 && __nb[0] == '0'
4281 && (__nb[1] == 'x' || __nb[1] == 'X'))
4282 return __nb+2;
4283 break;
4284 case ios_base::left:
4285 return __ne;
4286 case ios_base::right:
4287 default:
4288 break;
4289 }
4290 return __nb;
4291}
4292
4293// time_get
4294
4295static
4296string*
4297init_weeks()
4298{
4299 static string weeks[14];
4300 weeks[0] = "Sunday";
4301 weeks[1] = "Monday";
4302 weeks[2] = "Tuesday";
4303 weeks[3] = "Wednesday";
4304 weeks[4] = "Thursday";
4305 weeks[5] = "Friday";
4306 weeks[6] = "Saturday";
4307 weeks[7] = "Sun";
4308 weeks[8] = "Mon";
4309 weeks[9] = "Tue";
4310 weeks[10] = "Wed";
4311 weeks[11] = "Thu";
4312 weeks[12] = "Fri";
4313 weeks[13] = "Sat";
4314 return weeks;
4315}
4316
4317static
4318wstring*
4319init_wweeks()
4320{
4321 static wstring weeks[14];
4322 weeks[0] = L"Sunday";
4323 weeks[1] = L"Monday";
4324 weeks[2] = L"Tuesday";
4325 weeks[3] = L"Wednesday";
4326 weeks[4] = L"Thursday";
4327 weeks[5] = L"Friday";
4328 weeks[6] = L"Saturday";
4329 weeks[7] = L"Sun";
4330 weeks[8] = L"Mon";
4331 weeks[9] = L"Tue";
4332 weeks[10] = L"Wed";
4333 weeks[11] = L"Thu";
4334 weeks[12] = L"Fri";
4335 weeks[13] = L"Sat";
4336 return weeks;
4337}
4338
4339template <>
4340const string*
4341__time_get_c_storage<char>::__weeks() const
4342{
4343 static const string* weeks = init_weeks();
4344 return weeks;
4345}
4346
4347template <>
4348const wstring*
4349__time_get_c_storage<wchar_t>::__weeks() const
4350{
4351 static const wstring* weeks = init_wweeks();
4352 return weeks;
4353}
4354
4355static
4356string*
4357init_months()
4358{
4359 static string months[24];
4360 months[0] = "January";
4361 months[1] = "February";
4362 months[2] = "March";
4363 months[3] = "April";
4364 months[4] = "May";
4365 months[5] = "June";
4366 months[6] = "July";
4367 months[7] = "August";
4368 months[8] = "September";
4369 months[9] = "October";
4370 months[10] = "November";
4371 months[11] = "December";
4372 months[12] = "Jan";
4373 months[13] = "Feb";
4374 months[14] = "Mar";
4375 months[15] = "Apr";
4376 months[16] = "May";
4377 months[17] = "Jun";
4378 months[18] = "Jul";
4379 months[19] = "Aug";
4380 months[20] = "Sep";
4381 months[21] = "Oct";
4382 months[22] = "Nov";
4383 months[23] = "Dec";
4384 return months;
4385}
4386
4387static
4388wstring*
4389init_wmonths()
4390{
4391 static wstring months[24];
4392 months[0] = L"January";
4393 months[1] = L"February";
4394 months[2] = L"March";
4395 months[3] = L"April";
4396 months[4] = L"May";
4397 months[5] = L"June";
4398 months[6] = L"July";
4399 months[7] = L"August";
4400 months[8] = L"September";
4401 months[9] = L"October";
4402 months[10] = L"November";
4403 months[11] = L"December";
4404 months[12] = L"Jan";
4405 months[13] = L"Feb";
4406 months[14] = L"Mar";
4407 months[15] = L"Apr";
4408 months[16] = L"May";
4409 months[17] = L"Jun";
4410 months[18] = L"Jul";
4411 months[19] = L"Aug";
4412 months[20] = L"Sep";
4413 months[21] = L"Oct";
4414 months[22] = L"Nov";
4415 months[23] = L"Dec";
4416 return months;
4417}
4418
4419template <>
4420const string*
4421__time_get_c_storage<char>::__months() const
4422{
4423 static const string* months = init_months();
4424 return months;
4425}
4426
4427template <>
4428const wstring*
4429__time_get_c_storage<wchar_t>::__months() const
4430{
4431 static const wstring* months = init_wmonths();
4432 return months;
4433}
4434
4435static
4436string*
4437init_am_pm()
4438{
4439 static string am_pm[24];
4440 am_pm[0] = "AM";
4441 am_pm[1] = "PM";
4442 return am_pm;
4443}
4444
4445static
4446wstring*
4447init_wam_pm()
4448{
4449 static wstring am_pm[24];
4450 am_pm[0] = L"AM";
4451 am_pm[1] = L"PM";
4452 return am_pm;
4453}
4454
4455template <>
4456const string*
4457__time_get_c_storage<char>::__am_pm() const
4458{
4459 static const string* am_pm = init_am_pm();
4460 return am_pm;
4461}
4462
4463template <>
4464const wstring*
4465__time_get_c_storage<wchar_t>::__am_pm() const
4466{
4467 static const wstring* am_pm = init_wam_pm();
4468 return am_pm;
4469}
4470
4471template <>
4472const string&
4473__time_get_c_storage<char>::__x() const
4474{
4475 static string s("%m/%d/%y");
4476 return s;
4477}
4478
4479template <>
4480const wstring&
4481__time_get_c_storage<wchar_t>::__x() const
4482{
4483 static wstring s(L"%m/%d/%y");
4484 return s;
4485}
4486
4487template <>
4488const string&
4489__time_get_c_storage<char>::__X() const
4490{
4491 static string s("%H:%M:%S");
4492 return s;
4493}
4494
4495template <>
4496const wstring&
4497__time_get_c_storage<wchar_t>::__X() const
4498{
4499 static wstring s(L"%H:%M:%S");
4500 return s;
4501}
4502
4503template <>
4504const string&
4505__time_get_c_storage<char>::__c() const
4506{
4507 static string s("%a %b %d %H:%M:%S %Y");
4508 return s;
4509}
4510
4511template <>
4512const wstring&
4513__time_get_c_storage<wchar_t>::__c() const
4514{
4515 static wstring s(L"%a %b %d %H:%M:%S %Y");
4516 return s;
4517}
4518
4519template <>
4520const string&
4521__time_get_c_storage<char>::__r() const
4522{
4523 static string s("%I:%M:%S %p");
4524 return s;
4525}
4526
4527template <>
4528const wstring&
4529__time_get_c_storage<wchar_t>::__r() const
4530{
4531 static wstring s(L"%I:%M:%S %p");
4532 return s;
4533}
4534
4535// time_get_byname
4536
4537__time_get::__time_get(const char* nm)
4538 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4539{
Howard Hinnantd4444702010-08-11 17:04:31 +00004540#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004541 if (__loc_ == 0)
4542 throw runtime_error("time_get_byname"
4543 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004544#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004545}
4546
4547__time_get::__time_get(const string& nm)
4548 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4549{
Howard Hinnantd4444702010-08-11 17:04:31 +00004550#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004551 if (__loc_ == 0)
4552 throw runtime_error("time_get_byname"
4553 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004554#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004555}
4556
4557__time_get::~__time_get()
4558{
4559 freelocale(__loc_);
4560}
4561
Howard Hinnant335b1512012-02-20 16:51:43 +00004562#pragma clang diagnostic ignored "-Wmissing-field-initializers"
4563
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004564template <>
4565string
4566__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4567{
Howard Hinnant3074a052012-02-19 14:55:32 +00004568 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004569 t.tm_sec = 59;
4570 t.tm_min = 55;
4571 t.tm_hour = 23;
4572 t.tm_mday = 31;
4573 t.tm_mon = 11;
4574 t.tm_year = 161;
4575 t.tm_wday = 6;
4576 t.tm_yday = 364;
4577 t.tm_isdst = -1;
4578 char buf[100];
4579 char f[3] = {0};
4580 f[0] = '%';
4581 f[1] = fmt;
4582 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4583 char* bb = buf;
4584 char* be = buf + n;
4585 string result;
4586 while (bb != be)
4587 {
4588 if (ct.is(ctype_base::space, *bb))
4589 {
4590 result.push_back(' ');
4591 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4592 ;
4593 continue;
4594 }
4595 char* w = bb;
4596 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004597 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004598 ct, err, false)
4599 - this->__weeks_;
4600 if (i < 14)
4601 {
4602 result.push_back('%');
4603 if (i < 7)
4604 result.push_back('A');
4605 else
4606 result.push_back('a');
4607 bb = w;
4608 continue;
4609 }
4610 w = bb;
4611 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4612 ct, err, false)
4613 - this->__months_;
4614 if (i < 24)
4615 {
4616 result.push_back('%');
4617 if (i < 12)
4618 result.push_back('B');
4619 else
4620 result.push_back('b');
4621 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4622 result.back() = 'm';
4623 bb = w;
4624 continue;
4625 }
4626 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4627 {
4628 w = bb;
4629 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4630 ct, err, false) - this->__am_pm_;
4631 if (i < 2)
4632 {
4633 result.push_back('%');
4634 result.push_back('p');
4635 bb = w;
4636 continue;
4637 }
4638 }
4639 w = bb;
4640 if (ct.is(ctype_base::digit, *bb))
4641 {
4642 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4643 {
4644 case 6:
4645 result.push_back('%');
4646 result.push_back('w');
4647 break;
4648 case 7:
4649 result.push_back('%');
4650 result.push_back('u');
4651 break;
4652 case 11:
4653 result.push_back('%');
4654 result.push_back('I');
4655 break;
4656 case 12:
4657 result.push_back('%');
4658 result.push_back('m');
4659 break;
4660 case 23:
4661 result.push_back('%');
4662 result.push_back('H');
4663 break;
4664 case 31:
4665 result.push_back('%');
4666 result.push_back('d');
4667 break;
4668 case 55:
4669 result.push_back('%');
4670 result.push_back('M');
4671 break;
4672 case 59:
4673 result.push_back('%');
4674 result.push_back('S');
4675 break;
4676 case 61:
4677 result.push_back('%');
4678 result.push_back('y');
4679 break;
4680 case 364:
4681 result.push_back('%');
4682 result.push_back('j');
4683 break;
4684 case 2061:
4685 result.push_back('%');
4686 result.push_back('Y');
4687 break;
4688 default:
4689 for (; w != bb; ++w)
4690 result.push_back(*w);
4691 break;
4692 }
4693 continue;
4694 }
4695 if (*bb == '%')
4696 {
4697 result.push_back('%');
4698 result.push_back('%');
4699 ++bb;
4700 continue;
4701 }
4702 result.push_back(*bb);
4703 ++bb;
4704 }
4705 return result;
4706}
4707
Howard Hinnantec3773c2011-12-01 20:21:04 +00004708#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004709
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004710template <>
4711wstring
4712__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4713{
Howard Hinnant3074a052012-02-19 14:55:32 +00004714 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004715 t.tm_sec = 59;
4716 t.tm_min = 55;
4717 t.tm_hour = 23;
4718 t.tm_mday = 31;
4719 t.tm_mon = 11;
4720 t.tm_year = 161;
4721 t.tm_wday = 6;
4722 t.tm_yday = 364;
4723 t.tm_isdst = -1;
4724 char buf[100];
4725 char f[3] = {0};
4726 f[0] = '%';
4727 f[1] = fmt;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004728 strftime_l(buf, 100, f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004729 wchar_t wbuf[100];
4730 wchar_t* wbb = wbuf;
4731 mbstate_t mb = {0};
4732 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004733#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00004734 size_t j = mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004735#else
Howard Hinnantec3773c2011-12-01 20:21:04 +00004736 size_t j = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004737#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004738 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004739 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004740 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004741 wstring result;
4742 while (wbb != wbe)
4743 {
4744 if (ct.is(ctype_base::space, *wbb))
4745 {
4746 result.push_back(L' ');
4747 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4748 ;
4749 continue;
4750 }
4751 wchar_t* w = wbb;
4752 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004753 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004754 ct, err, false)
4755 - this->__weeks_;
4756 if (i < 14)
4757 {
4758 result.push_back(L'%');
4759 if (i < 7)
4760 result.push_back(L'A');
4761 else
4762 result.push_back(L'a');
4763 wbb = w;
4764 continue;
4765 }
4766 w = wbb;
4767 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4768 ct, err, false)
4769 - this->__months_;
4770 if (i < 24)
4771 {
4772 result.push_back(L'%');
4773 if (i < 12)
4774 result.push_back(L'B');
4775 else
4776 result.push_back(L'b');
4777 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4778 result.back() = L'm';
4779 wbb = w;
4780 continue;
4781 }
4782 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4783 {
4784 w = wbb;
4785 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4786 ct, err, false) - this->__am_pm_;
4787 if (i < 2)
4788 {
4789 result.push_back(L'%');
4790 result.push_back(L'p');
4791 wbb = w;
4792 continue;
4793 }
4794 }
4795 w = wbb;
4796 if (ct.is(ctype_base::digit, *wbb))
4797 {
4798 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4799 {
4800 case 6:
4801 result.push_back(L'%');
4802 result.push_back(L'w');
4803 break;
4804 case 7:
4805 result.push_back(L'%');
4806 result.push_back(L'u');
4807 break;
4808 case 11:
4809 result.push_back(L'%');
4810 result.push_back(L'I');
4811 break;
4812 case 12:
4813 result.push_back(L'%');
4814 result.push_back(L'm');
4815 break;
4816 case 23:
4817 result.push_back(L'%');
4818 result.push_back(L'H');
4819 break;
4820 case 31:
4821 result.push_back(L'%');
4822 result.push_back(L'd');
4823 break;
4824 case 55:
4825 result.push_back(L'%');
4826 result.push_back(L'M');
4827 break;
4828 case 59:
4829 result.push_back(L'%');
4830 result.push_back(L'S');
4831 break;
4832 case 61:
4833 result.push_back(L'%');
4834 result.push_back(L'y');
4835 break;
4836 case 364:
4837 result.push_back(L'%');
4838 result.push_back(L'j');
4839 break;
4840 case 2061:
4841 result.push_back(L'%');
4842 result.push_back(L'Y');
4843 break;
4844 default:
4845 for (; w != wbb; ++w)
4846 result.push_back(*w);
4847 break;
4848 }
4849 continue;
4850 }
4851 if (ct.narrow(*wbb, 0) == '%')
4852 {
4853 result.push_back(L'%');
4854 result.push_back(L'%');
4855 ++wbb;
4856 continue;
4857 }
4858 result.push_back(*wbb);
4859 ++wbb;
4860 }
4861 return result;
4862}
4863
4864template <>
4865void
4866__time_get_storage<char>::init(const ctype<char>& ct)
4867{
4868 tm t;
4869 char buf[100];
4870 // __weeks_
4871 for (int i = 0; i < 7; ++i)
4872 {
4873 t.tm_wday = i;
4874 strftime_l(buf, 100, "%A", &t, __loc_);
4875 __weeks_[i] = buf;
4876 strftime_l(buf, 100, "%a", &t, __loc_);
4877 __weeks_[i+7] = buf;
4878 }
4879 // __months_
4880 for (int i = 0; i < 12; ++i)
4881 {
4882 t.tm_mon = i;
4883 strftime_l(buf, 100, "%B", &t, __loc_);
4884 __months_[i] = buf;
4885 strftime_l(buf, 100, "%b", &t, __loc_);
4886 __months_[i+12] = buf;
4887 }
4888 // __am_pm_
4889 t.tm_hour = 1;
4890 strftime_l(buf, 100, "%p", &t, __loc_);
4891 __am_pm_[0] = buf;
4892 t.tm_hour = 13;
4893 strftime_l(buf, 100, "%p", &t, __loc_);
4894 __am_pm_[1] = buf;
4895 __c_ = __analyze('c', ct);
4896 __r_ = __analyze('r', ct);
4897 __x_ = __analyze('x', ct);
4898 __X_ = __analyze('X', ct);
4899}
4900
4901template <>
4902void
4903__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4904{
4905 tm t = {0};
4906 char buf[100];
4907 size_t be;
4908 wchar_t wbuf[100];
4909 wchar_t* wbe;
4910 mbstate_t mb = {0};
4911 // __weeks_
4912 for (int i = 0; i < 7; ++i)
4913 {
4914 t.tm_wday = i;
4915 be = strftime_l(buf, 100, "%A", &t, __loc_);
4916 mb = mbstate_t();
4917 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004918#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004919 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4920#else
4921 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4922#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004923 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004924 __throw_runtime_error("locale not supported");
4925 wbe = wbuf + j;
4926 __weeks_[i].assign(wbuf, wbe);
4927 be = strftime_l(buf, 100, "%a", &t, __loc_);
4928 mb = mbstate_t();
4929 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004930#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004931 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4932#else
4933 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4934#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004935 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004936 __throw_runtime_error("locale not supported");
4937 wbe = wbuf + j;
4938 __weeks_[i+7].assign(wbuf, wbe);
4939 }
4940 // __months_
4941 for (int i = 0; i < 12; ++i)
4942 {
4943 t.tm_mon = i;
4944 be = strftime_l(buf, 100, "%B", &t, __loc_);
4945 mb = mbstate_t();
4946 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004947#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004948 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4949#else
4950 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4951#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004952 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004953 __throw_runtime_error("locale not supported");
4954 wbe = wbuf + j;
4955 __months_[i].assign(wbuf, wbe);
4956 be = strftime_l(buf, 100, "%b", &t, __loc_);
4957 mb = mbstate_t();
4958 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004959#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004960 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4961#else
4962 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4963#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004964 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004965 __throw_runtime_error("locale not supported");
4966 wbe = wbuf + j;
4967 __months_[i+12].assign(wbuf, wbe);
4968 }
4969 // __am_pm_
4970 t.tm_hour = 1;
4971 be = strftime_l(buf, 100, "%p", &t, __loc_);
4972 mb = mbstate_t();
4973 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004974#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004975 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4976#else
4977 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4978#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004979 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004980 __throw_runtime_error("locale not supported");
4981 wbe = wbuf + j;
4982 __am_pm_[0].assign(wbuf, wbe);
4983 t.tm_hour = 13;
4984 be = strftime_l(buf, 100, "%p", &t, __loc_);
4985 mb = mbstate_t();
4986 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004987#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004988 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4989#else
4990 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4991#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004992 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004993 __throw_runtime_error("locale not supported");
4994 wbe = wbuf + j;
4995 __am_pm_[1].assign(wbuf, wbe);
4996 __c_ = __analyze('c', ct);
4997 __r_ = __analyze('r', ct);
4998 __x_ = __analyze('x', ct);
4999 __X_ = __analyze('X', ct);
5000}
5001
5002template <class CharT>
5003struct _LIBCPP_HIDDEN __time_get_temp
5004 : public ctype_byname<CharT>
5005{
5006 explicit __time_get_temp(const char* nm)
5007 : ctype_byname<CharT>(nm, 1) {}
5008 explicit __time_get_temp(const string& nm)
5009 : ctype_byname<CharT>(nm, 1) {}
5010};
5011
5012template <>
5013__time_get_storage<char>::__time_get_storage(const char* __nm)
5014 : __time_get(__nm)
5015{
5016 const __time_get_temp<char> ct(__nm);
5017 init(ct);
5018}
5019
5020template <>
5021__time_get_storage<char>::__time_get_storage(const string& __nm)
5022 : __time_get(__nm)
5023{
5024 const __time_get_temp<char> ct(__nm);
5025 init(ct);
5026}
5027
5028template <>
5029__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5030 : __time_get(__nm)
5031{
5032 const __time_get_temp<wchar_t> ct(__nm);
5033 init(ct);
5034}
5035
5036template <>
5037__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5038 : __time_get(__nm)
5039{
5040 const __time_get_temp<wchar_t> ct(__nm);
5041 init(ct);
5042}
5043
5044template <>
5045time_base::dateorder
5046__time_get_storage<char>::__do_date_order() const
5047{
5048 unsigned i;
5049 for (i = 0; i < __x_.size(); ++i)
5050 if (__x_[i] == '%')
5051 break;
5052 ++i;
5053 switch (__x_[i])
5054 {
5055 case 'y':
5056 case 'Y':
5057 for (++i; i < __x_.size(); ++i)
5058 if (__x_[i] == '%')
5059 break;
5060 if (i == __x_.size())
5061 break;
5062 ++i;
5063 switch (__x_[i])
5064 {
5065 case 'm':
5066 for (++i; i < __x_.size(); ++i)
5067 if (__x_[i] == '%')
5068 break;
5069 if (i == __x_.size())
5070 break;
5071 ++i;
5072 if (__x_[i] == 'd')
5073 return time_base::ymd;
5074 break;
5075 case 'd':
5076 for (++i; i < __x_.size(); ++i)
5077 if (__x_[i] == '%')
5078 break;
5079 if (i == __x_.size())
5080 break;
5081 ++i;
5082 if (__x_[i] == 'm')
5083 return time_base::ydm;
5084 break;
5085 }
5086 break;
5087 case 'm':
5088 for (++i; i < __x_.size(); ++i)
5089 if (__x_[i] == '%')
5090 break;
5091 if (i == __x_.size())
5092 break;
5093 ++i;
5094 if (__x_[i] == 'd')
5095 {
5096 for (++i; i < __x_.size(); ++i)
5097 if (__x_[i] == '%')
5098 break;
5099 if (i == __x_.size())
5100 break;
5101 ++i;
5102 if (__x_[i] == 'y' || __x_[i] == 'Y')
5103 return time_base::mdy;
5104 break;
5105 }
5106 break;
5107 case 'd':
5108 for (++i; i < __x_.size(); ++i)
5109 if (__x_[i] == '%')
5110 break;
5111 if (i == __x_.size())
5112 break;
5113 ++i;
5114 if (__x_[i] == 'm')
5115 {
5116 for (++i; i < __x_.size(); ++i)
5117 if (__x_[i] == '%')
5118 break;
5119 if (i == __x_.size())
5120 break;
5121 ++i;
5122 if (__x_[i] == 'y' || __x_[i] == 'Y')
5123 return time_base::dmy;
5124 break;
5125 }
5126 break;
5127 }
5128 return time_base::no_order;
5129}
5130
5131template <>
5132time_base::dateorder
5133__time_get_storage<wchar_t>::__do_date_order() const
5134{
5135 unsigned i;
5136 for (i = 0; i < __x_.size(); ++i)
5137 if (__x_[i] == L'%')
5138 break;
5139 ++i;
5140 switch (__x_[i])
5141 {
5142 case L'y':
5143 case L'Y':
5144 for (++i; i < __x_.size(); ++i)
5145 if (__x_[i] == L'%')
5146 break;
5147 if (i == __x_.size())
5148 break;
5149 ++i;
5150 switch (__x_[i])
5151 {
5152 case L'm':
5153 for (++i; i < __x_.size(); ++i)
5154 if (__x_[i] == L'%')
5155 break;
5156 if (i == __x_.size())
5157 break;
5158 ++i;
5159 if (__x_[i] == L'd')
5160 return time_base::ymd;
5161 break;
5162 case L'd':
5163 for (++i; i < __x_.size(); ++i)
5164 if (__x_[i] == L'%')
5165 break;
5166 if (i == __x_.size())
5167 break;
5168 ++i;
5169 if (__x_[i] == L'm')
5170 return time_base::ydm;
5171 break;
5172 }
5173 break;
5174 case L'm':
5175 for (++i; i < __x_.size(); ++i)
5176 if (__x_[i] == L'%')
5177 break;
5178 if (i == __x_.size())
5179 break;
5180 ++i;
5181 if (__x_[i] == L'd')
5182 {
5183 for (++i; i < __x_.size(); ++i)
5184 if (__x_[i] == L'%')
5185 break;
5186 if (i == __x_.size())
5187 break;
5188 ++i;
5189 if (__x_[i] == L'y' || __x_[i] == L'Y')
5190 return time_base::mdy;
5191 break;
5192 }
5193 break;
5194 case L'd':
5195 for (++i; i < __x_.size(); ++i)
5196 if (__x_[i] == L'%')
5197 break;
5198 if (i == __x_.size())
5199 break;
5200 ++i;
5201 if (__x_[i] == L'm')
5202 {
5203 for (++i; i < __x_.size(); ++i)
5204 if (__x_[i] == L'%')
5205 break;
5206 if (i == __x_.size())
5207 break;
5208 ++i;
5209 if (__x_[i] == L'y' || __x_[i] == L'Y')
5210 return time_base::dmy;
5211 break;
5212 }
5213 break;
5214 }
5215 return time_base::no_order;
5216}
5217
5218// time_put
5219
5220__time_put::__time_put(const char* nm)
5221 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5222{
Howard Hinnantd4444702010-08-11 17:04:31 +00005223#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005224 if (__loc_ == 0)
5225 throw runtime_error("time_put_byname"
5226 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005227#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005228}
5229
5230__time_put::__time_put(const string& nm)
5231 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5232{
Howard Hinnantd4444702010-08-11 17:04:31 +00005233#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005234 if (__loc_ == 0)
5235 throw runtime_error("time_put_byname"
5236 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005237#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005238}
5239
5240__time_put::~__time_put()
5241{
5242 if (__loc_)
5243 freelocale(__loc_);
5244}
5245
5246void
5247__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5248 char __fmt, char __mod) const
5249{
5250 char fmt[] = {'%', __fmt, __mod, 0};
5251 if (__mod != 0)
5252 swap(fmt[1], fmt[2]);
Howard Hinnantec3773c2011-12-01 20:21:04 +00005253 size_t n = strftime_l(__nb, static_cast<size_t>(__ne-__nb), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005254 __ne = __nb + n;
5255}
5256
5257void
5258__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5259 char __fmt, char __mod) const
5260{
5261 char __nar[100];
5262 char* __ne = __nar + 100;
5263 __do_put(__nar, __ne, __tm, __fmt, __mod);
5264 mbstate_t mb = {0};
5265 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005266#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005267 size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5268#else
5269 size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5270#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005271 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005272 __throw_runtime_error("locale not supported");
5273 __we = __wb + j;
5274}
5275
5276// moneypunct_byname
5277
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005278template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005279static
5280void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005281__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5282 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5283 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005284{
5285 const char sign = static_cast<char>(money_base::sign);
5286 const char space = static_cast<char>(money_base::space);
5287 const char none = static_cast<char>(money_base::none);
5288 const char symbol = static_cast<char>(money_base::symbol);
5289 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005290 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5291
5292 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5293 // function'. "Space between sign and symbol or value" means that
5294 // if the sign is adjacent to the symbol, there's a space between
5295 // them, and otherwise there's a space between the sign and value.
5296 //
5297 // C11's localeconv specifies that the fourth character of an
5298 // international curr_symbol is used to separate the sign and
5299 // value when sep_by_space says to do so. C++ can't represent
5300 // that, so we just use a space. When sep_by_space says to
5301 // separate the symbol and value-or-sign with a space, we rearrange the
5302 // curr_symbol to put its spacing character on the correct side of
5303 // the symbol.
5304 //
5305 // We also need to avoid adding an extra space between the sign
5306 // and value when the currency symbol is suppressed (by not
5307 // setting showbase). We match glibc's strfmon by interpreting
5308 // sep_by_space==1 as "omit the space when the currency symbol is
5309 // absent".
5310 //
5311 // Users who want to get this right should use ICU instead.
5312
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005313 switch (cs_precedes)
5314 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005315 case 0: // value before curr_symbol
5316 if (symbol_contains_sep) {
5317 // Move the separator to before the symbol, to place it
5318 // between the value and symbol.
5319 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5320 __curr_symbol_.end());
5321 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005322 switch (sign_posn)
5323 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005324 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005325 pat.field[0] = sign;
5326 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005327 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005328 pat.field[3] = symbol;
5329 switch (sep_by_space)
5330 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005331 case 0: // No space separates the currency symbol and value.
5332 // This case may have changed between C99 and C11;
5333 // assume the currency symbol matches the intention.
5334 case 2: // Space between sign and currency or value.
5335 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005336 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005337 case 1: // Space between currency-and-sign or currency and value.
5338 if (!symbol_contains_sep) {
5339 // We insert the space into the symbol instead of
5340 // setting pat.field[2]=space so that when
5341 // showbase is not set, the space goes away too.
5342 __curr_symbol_.insert(0, 1, space_char);
5343 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005344 return;
5345 default:
5346 break;
5347 }
5348 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005349 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005350 pat.field[0] = sign;
5351 pat.field[3] = symbol;
5352 switch (sep_by_space)
5353 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005354 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005355 pat.field[1] = value;
5356 pat.field[2] = none;
5357 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005358 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005359 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005360 pat.field[2] = none;
5361 if (!symbol_contains_sep) {
5362 // We insert the space into the symbol instead of
5363 // setting pat.field[2]=space so that when
5364 // showbase is not set, the space goes away too.
5365 __curr_symbol_.insert(0, 1, space_char);
5366 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005367 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005368 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005369 pat.field[1] = space;
5370 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005371 if (symbol_contains_sep) {
5372 // Remove the separator from the symbol, since it
5373 // has already appeared after the sign.
5374 __curr_symbol_.erase(__curr_symbol_.begin());
5375 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005376 return;
5377 default:
5378 break;
5379 }
5380 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005381 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005382 pat.field[0] = value;
5383 pat.field[3] = sign;
5384 switch (sep_by_space)
5385 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005386 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005387 pat.field[1] = none;
5388 pat.field[2] = symbol;
5389 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005390 case 1: // Space between currency-and-sign or currency and value.
5391 if (!symbol_contains_sep) {
5392 // We insert the space into the symbol instead of
5393 // setting pat.field[1]=space so that when
5394 // showbase is not set, the space goes away too.
5395 __curr_symbol_.insert(0, 1, space_char);
5396 }
5397 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005398 pat.field[2] = symbol;
5399 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005400 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005401 pat.field[1] = symbol;
5402 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005403 if (symbol_contains_sep) {
5404 // Remove the separator from the symbol, since it
5405 // should not be removed if showbase is absent.
5406 __curr_symbol_.erase(__curr_symbol_.begin());
5407 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005408 return;
5409 default:
5410 break;
5411 }
5412 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005413 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005414 pat.field[0] = value;
5415 pat.field[3] = symbol;
5416 switch (sep_by_space)
5417 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005418 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005419 pat.field[1] = none;
5420 pat.field[2] = sign;
5421 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005422 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005423 pat.field[1] = space;
5424 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005425 if (symbol_contains_sep) {
5426 // Remove the separator from the symbol, since it
5427 // has already appeared before the sign.
5428 __curr_symbol_.erase(__curr_symbol_.begin());
5429 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005430 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005431 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005432 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005433 pat.field[2] = none;
5434 if (!symbol_contains_sep) {
5435 // We insert the space into the symbol instead of
5436 // setting pat.field[2]=space so that when
5437 // showbase is not set, the space goes away too.
5438 __curr_symbol_.insert(0, 1, space_char);
5439 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005440 return;
5441 default:
5442 break;
5443 }
5444 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005445 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005446 pat.field[0] = value;
5447 pat.field[3] = sign;
5448 switch (sep_by_space)
5449 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005450 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005451 pat.field[1] = none;
5452 pat.field[2] = symbol;
5453 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005454 case 1: // Space between currency-and-sign or currency and value.
5455 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005456 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005457 if (!symbol_contains_sep) {
5458 // We insert the space into the symbol instead of
5459 // setting pat.field[1]=space so that when
5460 // showbase is not set, the space goes away too.
5461 __curr_symbol_.insert(0, 1, space_char);
5462 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005463 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005464 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005465 pat.field[1] = symbol;
5466 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005467 if (symbol_contains_sep) {
5468 // Remove the separator from the symbol, since it
5469 // should not disappear when showbase is absent.
5470 __curr_symbol_.erase(__curr_symbol_.begin());
5471 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005472 return;
5473 default:
5474 break;
5475 }
5476 break;
5477 default:
5478 break;
5479 }
5480 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005481 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005482 switch (sign_posn)
5483 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005484 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005485 pat.field[0] = sign;
5486 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005487 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005488 pat.field[3] = value;
5489 switch (sep_by_space)
5490 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005491 case 0: // No space separates the currency symbol and value.
5492 // This case may have changed between C99 and C11;
5493 // assume the currency symbol matches the intention.
5494 case 2: // Space between sign and currency or value.
5495 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005496 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005497 case 1: // Space between currency-and-sign or currency and value.
5498 if (!symbol_contains_sep) {
5499 // We insert the space into the symbol instead of
5500 // setting pat.field[2]=space so that when
5501 // showbase is not set, the space goes away too.
5502 __curr_symbol_.insert(0, 1, space_char);
5503 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005504 return;
5505 default:
5506 break;
5507 }
5508 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005509 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005510 pat.field[0] = sign;
5511 pat.field[3] = value;
5512 switch (sep_by_space)
5513 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005514 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005515 pat.field[1] = symbol;
5516 pat.field[2] = none;
5517 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005518 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005519 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005520 pat.field[2] = none;
5521 if (!symbol_contains_sep) {
5522 // We insert the space into the symbol instead of
5523 // setting pat.field[2]=space so that when
5524 // showbase is not set, the space goes away too.
5525 __curr_symbol_.push_back(space_char);
5526 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005527 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005528 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005529 pat.field[1] = space;
5530 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005531 if (symbol_contains_sep) {
5532 // Remove the separator from the symbol, since it
5533 // has already appeared after the sign.
5534 __curr_symbol_.pop_back();
5535 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005536 return;
5537 default:
5538 break;
5539 }
5540 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005541 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005542 pat.field[0] = symbol;
5543 pat.field[3] = sign;
5544 switch (sep_by_space)
5545 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005546 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005547 pat.field[1] = none;
5548 pat.field[2] = value;
5549 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005550 case 1: // Space between currency-and-sign or currency and value.
5551 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005552 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005553 if (!symbol_contains_sep) {
5554 // We insert the space into the symbol instead of
5555 // setting pat.field[1]=space so that when
5556 // showbase is not set, the space goes away too.
5557 __curr_symbol_.push_back(space_char);
5558 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005559 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005560 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005561 pat.field[1] = value;
5562 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005563 if (symbol_contains_sep) {
5564 // Remove the separator from the symbol, since it
5565 // will appear before the sign.
5566 __curr_symbol_.pop_back();
5567 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005568 return;
5569 default:
5570 break;
5571 }
5572 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005573 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005574 pat.field[0] = sign;
5575 pat.field[3] = value;
5576 switch (sep_by_space)
5577 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005578 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005579 pat.field[1] = symbol;
5580 pat.field[2] = none;
5581 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005582 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005583 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005584 pat.field[2] = none;
5585 if (!symbol_contains_sep) {
5586 // We insert the space into the symbol instead of
5587 // setting pat.field[2]=space so that when
5588 // showbase is not set, the space goes away too.
5589 __curr_symbol_.push_back(space_char);
5590 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005591 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005592 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005593 pat.field[1] = space;
5594 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005595 if (symbol_contains_sep) {
5596 // Remove the separator from the symbol, since it
5597 // has already appeared after the sign.
5598 __curr_symbol_.pop_back();
5599 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005600 return;
5601 default:
5602 break;
5603 }
5604 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005605 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005606 pat.field[0] = symbol;
5607 pat.field[3] = value;
5608 switch (sep_by_space)
5609 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005610 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005611 pat.field[1] = sign;
5612 pat.field[2] = none;
5613 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005614 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005615 pat.field[1] = sign;
5616 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005617 if (symbol_contains_sep) {
5618 // Remove the separator from the symbol, since it
5619 // should not disappear when showbase is absent.
5620 __curr_symbol_.pop_back();
5621 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005622 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005623 case 2: // Space between sign and currency or value.
5624 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005625 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005626 if (!symbol_contains_sep) {
5627 // We insert the space into the symbol instead of
5628 // setting pat.field[1]=space so that when
5629 // showbase is not set, the space goes away too.
5630 __curr_symbol_.push_back(space_char);
5631 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005632 return;
5633 default:
5634 break;
5635 }
5636 break;
5637 default:
5638 break;
5639 }
5640 break;
5641 default:
5642 break;
5643 }
5644 pat.field[0] = symbol;
5645 pat.field[1] = sign;
5646 pat.field[2] = none;
5647 pat.field[3] = value;
5648}
5649
5650template<>
5651void
5652moneypunct_byname<char, false>::init(const char* nm)
5653{
5654 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005655 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005656#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005657 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005658 throw runtime_error("moneypunct_byname"
5659 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005660#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005661#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005662 lconv* lc = localeconv_l(loc.get());
5663#else
5664 lconv* lc = __localeconv_l(loc.get());
5665#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005666 if (*lc->mon_decimal_point)
5667 __decimal_point_ = *lc->mon_decimal_point;
5668 else
5669 __decimal_point_ = base::do_decimal_point();
5670 if (*lc->mon_thousands_sep)
5671 __thousands_sep_ = *lc->mon_thousands_sep;
5672 else
5673 __thousands_sep_ = base::do_thousands_sep();
5674 __grouping_ = lc->mon_grouping;
5675 __curr_symbol_ = lc->currency_symbol;
5676 if (lc->frac_digits != CHAR_MAX)
5677 __frac_digits_ = lc->frac_digits;
5678 else
5679 __frac_digits_ = base::do_frac_digits();
5680 if (lc->p_sign_posn == 0)
5681 __positive_sign_ = "()";
5682 else
5683 __positive_sign_ = lc->positive_sign;
5684 if (lc->n_sign_posn == 0)
5685 __negative_sign_ = "()";
5686 else
5687 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005688 // Assume the positive and negative formats will want spaces in
5689 // the same places in curr_symbol since there's no way to
5690 // represent anything else.
5691 string_type __dummy_curr_symbol = __curr_symbol_;
5692 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5693 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5694 __init_pat(__neg_format_, __curr_symbol_, false,
5695 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005696}
5697
5698template<>
5699void
5700moneypunct_byname<char, true>::init(const char* nm)
5701{
5702 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005703 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005704#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005705 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005706 throw runtime_error("moneypunct_byname"
5707 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005708#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005709#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005710 lconv* lc = localeconv_l(loc.get());
5711#else
5712 lconv* lc = __localeconv_l(loc.get());
5713#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005714 if (*lc->mon_decimal_point)
5715 __decimal_point_ = *lc->mon_decimal_point;
5716 else
5717 __decimal_point_ = base::do_decimal_point();
5718 if (*lc->mon_thousands_sep)
5719 __thousands_sep_ = *lc->mon_thousands_sep;
5720 else
5721 __thousands_sep_ = base::do_thousands_sep();
5722 __grouping_ = lc->mon_grouping;
5723 __curr_symbol_ = lc->int_curr_symbol;
5724 if (lc->int_frac_digits != CHAR_MAX)
5725 __frac_digits_ = lc->int_frac_digits;
5726 else
5727 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005728#if _WIN32
5729 if (lc->p_sign_posn == 0)
5730#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005731 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005732#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005733 __positive_sign_ = "()";
5734 else
5735 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005736#if _WIN32
5737 if(lc->n_sign_posn == 0)
5738#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005739 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005740#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005741 __negative_sign_ = "()";
5742 else
5743 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005744 // Assume the positive and negative formats will want spaces in
5745 // the same places in curr_symbol since there's no way to
5746 // represent anything else.
5747 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005748#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005749 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5750 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5751 __init_pat(__neg_format_, __curr_symbol_, true,
5752 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005753#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005754 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5755 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5756 lc->int_p_sign_posn, ' ');
5757 __init_pat(__neg_format_, __curr_symbol_, true,
5758 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5759 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005760#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005761}
5762
5763template<>
5764void
5765moneypunct_byname<wchar_t, false>::init(const char* nm)
5766{
5767 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005768 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005769#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005770 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005771 throw runtime_error("moneypunct_byname"
5772 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005773#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005774#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005775 lconv* lc = localeconv_l(loc.get());
5776#else
5777 lconv* lc = __localeconv_l(loc.get());
5778#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005779 if (*lc->mon_decimal_point)
5780 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5781 else
5782 __decimal_point_ = base::do_decimal_point();
5783 if (*lc->mon_thousands_sep)
5784 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5785 else
5786 __thousands_sep_ = base::do_thousands_sep();
5787 __grouping_ = lc->mon_grouping;
5788 wchar_t wbuf[100];
5789 mbstate_t mb = {0};
5790 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005791#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005792 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5793#else
5794 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5795#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005796 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005797 __throw_runtime_error("locale not supported");
5798 wchar_t* wbe = wbuf + j;
5799 __curr_symbol_.assign(wbuf, wbe);
5800 if (lc->frac_digits != CHAR_MAX)
5801 __frac_digits_ = lc->frac_digits;
5802 else
5803 __frac_digits_ = base::do_frac_digits();
5804 if (lc->p_sign_posn == 0)
5805 __positive_sign_ = L"()";
5806 else
5807 {
5808 mb = mbstate_t();
5809 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005810#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005811 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5812#else
5813 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5814#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005815 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005816 __throw_runtime_error("locale not supported");
5817 wbe = wbuf + j;
5818 __positive_sign_.assign(wbuf, wbe);
5819 }
5820 if (lc->n_sign_posn == 0)
5821 __negative_sign_ = L"()";
5822 else
5823 {
5824 mb = mbstate_t();
5825 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005826#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005827 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5828#else
5829 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5830#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005831 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005832 __throw_runtime_error("locale not supported");
5833 wbe = wbuf + j;
5834 __negative_sign_.assign(wbuf, wbe);
5835 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005836 // Assume the positive and negative formats will want spaces in
5837 // the same places in curr_symbol since there's no way to
5838 // represent anything else.
5839 string_type __dummy_curr_symbol = __curr_symbol_;
5840 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5841 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5842 __init_pat(__neg_format_, __curr_symbol_, false,
5843 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005844}
5845
5846template<>
5847void
5848moneypunct_byname<wchar_t, true>::init(const char* nm)
5849{
5850 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005851 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005852#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005853 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005854 throw runtime_error("moneypunct_byname"
5855 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005856#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005857#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005858 lconv* lc = localeconv_l(loc.get());
5859#else
5860 lconv* lc = __localeconv_l(loc.get());
5861#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005862 if (*lc->mon_decimal_point)
5863 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5864 else
5865 __decimal_point_ = base::do_decimal_point();
5866 if (*lc->mon_thousands_sep)
5867 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5868 else
5869 __thousands_sep_ = base::do_thousands_sep();
5870 __grouping_ = lc->mon_grouping;
5871 wchar_t wbuf[100];
5872 mbstate_t mb = {0};
5873 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005874#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005875 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5876#else
5877 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5878#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005879 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005880 __throw_runtime_error("locale not supported");
5881 wchar_t* wbe = wbuf + j;
5882 __curr_symbol_.assign(wbuf, wbe);
5883 if (lc->int_frac_digits != CHAR_MAX)
5884 __frac_digits_ = lc->int_frac_digits;
5885 else
5886 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005887#if _WIN32
5888 if (lc->p_sign_posn == 0)
5889#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005890 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005891#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005892 __positive_sign_ = L"()";
5893 else
5894 {
5895 mb = mbstate_t();
5896 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005897#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005898 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5899#else
5900 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5901#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005902 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005903 __throw_runtime_error("locale not supported");
5904 wbe = wbuf + j;
5905 __positive_sign_.assign(wbuf, wbe);
5906 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005907#if _WIN32
5908 if (lc->n_sign_posn == 0)
5909#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005910 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005911#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005912 __negative_sign_ = L"()";
5913 else
5914 {
5915 mb = mbstate_t();
5916 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005917#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005918 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5919#else
5920 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5921#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005922 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005923 __throw_runtime_error("locale not supported");
5924 wbe = wbuf + j;
5925 __negative_sign_.assign(wbuf, wbe);
5926 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005927 // Assume the positive and negative formats will want spaces in
5928 // the same places in curr_symbol since there's no way to
5929 // represent anything else.
5930 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005931#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005932 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5933 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5934 __init_pat(__neg_format_, __curr_symbol_, true,
5935 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005936#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005937 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5938 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5939 lc->int_p_sign_posn, L' ');
5940 __init_pat(__neg_format_, __curr_symbol_, true,
5941 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5942 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005943#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005944}
5945
5946void __do_nothing(void*) {}
5947
5948void __throw_runtime_error(const char* msg)
5949{
Howard Hinnantd4444702010-08-11 17:04:31 +00005950#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005951 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00005952#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005953}
5954
5955template class collate<char>;
5956template class collate<wchar_t>;
5957
5958template class num_get<char>;
5959template class num_get<wchar_t>;
5960
Howard Hinnantec3773c2011-12-01 20:21:04 +00005961template struct __num_get<char>;
5962template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005963
5964template class num_put<char>;
5965template class num_put<wchar_t>;
5966
Howard Hinnantec3773c2011-12-01 20:21:04 +00005967template struct __num_put<char>;
5968template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005969
5970template class time_get<char>;
5971template class time_get<wchar_t>;
5972
5973template class time_get_byname<char>;
5974template class time_get_byname<wchar_t>;
5975
5976template class time_put<char>;
5977template class time_put<wchar_t>;
5978
5979template class time_put_byname<char>;
5980template class time_put_byname<wchar_t>;
5981
5982template class moneypunct<char, false>;
5983template class moneypunct<char, true>;
5984template class moneypunct<wchar_t, false>;
5985template class moneypunct<wchar_t, true>;
5986
5987template class moneypunct_byname<char, false>;
5988template class moneypunct_byname<char, true>;
5989template class moneypunct_byname<wchar_t, false>;
5990template class moneypunct_byname<wchar_t, true>;
5991
5992template class money_get<char>;
5993template class money_get<wchar_t>;
5994
5995template class __money_get<char>;
5996template class __money_get<wchar_t>;
5997
5998template class money_put<char>;
5999template class money_put<wchar_t>;
6000
6001template class __money_put<char>;
6002template class __money_put<wchar_t>;
6003
6004template class messages<char>;
6005template class messages<wchar_t>;
6006
6007template class messages_byname<char>;
6008template class messages_byname<wchar_t>;
6009
6010template class codecvt_byname<char, char, mbstate_t>;
6011template class codecvt_byname<wchar_t, char, mbstate_t>;
6012template class codecvt_byname<char16_t, char, mbstate_t>;
6013template class codecvt_byname<char32_t, char, mbstate_t>;
6014
6015template class __vector_base_common<true>;
6016
6017_LIBCPP_END_NAMESPACE_STD