blob: 542c0d7a20ffc5650e0332c6551dd189d0093db9 [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 Hinnantef793f22012-08-02 18:35:07 +00001055 bool result = false;
1056 if (m & space) result |= (iswspace_l(c, __l) != 0);
1057 if (m & print) result |= (iswprint_l(c, __l) != 0);
1058 if (m & cntrl) result |= (iswcntrl_l(c, __l) != 0);
1059 if (m & upper) result |= (iswupper_l(c, __l) != 0);
1060 if (m & lower) result |= (iswlower_l(c, __l) != 0);
1061 if (m & alpha) result |= (iswalpha_l(c, __l) != 0);
1062 if (m & digit) result |= (iswdigit_l(c, __l) != 0);
1063 if (m & punct) result |= (iswpunct_l(c, __l) != 0);
1064 if (m & xdigit) result |= (iswxdigit_l(c, __l) != 0);
1065 if (m & blank) result |= (iswblank_l(c, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001066 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
Howard Hinnantef793f22012-08-02 18:35:07 +00001112 if (m & space && iswspace_l(*low, __l)) break;
1113 if (m & print && iswprint_l(*low, __l)) break;
1114 if (m & cntrl && iswcntrl_l(*low, __l)) break;
1115 if (m & upper && iswupper_l(*low, __l)) break;
1116 if (m & lower && iswlower_l(*low, __l)) break;
1117 if (m & alpha && iswalpha_l(*low, __l)) break;
1118 if (m & digit && iswdigit_l(*low, __l)) break;
1119 if (m & punct && iswpunct_l(*low, __l)) break;
1120 if (m & xdigit && iswxdigit_l(*low, __l)) break;
1121 if (m & blank && iswblank_l(*low, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001122#endif
1123 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001124 return low;
1125}
1126
1127const wchar_t*
1128ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1129{
1130 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001131 {
1132#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001133 if (!iswctype_l(*low, m, __l))
1134 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001135#else
1136 if (m & space && iswspace_l(*low, __l)) continue;
1137 if (m & print && iswprint_l(*low, __l)) continue;
1138 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1139 if (m & upper && iswupper_l(*low, __l)) continue;
1140 if (m & lower && iswlower_l(*low, __l)) continue;
1141 if (m & alpha && iswalpha_l(*low, __l)) continue;
1142 if (m & digit && iswdigit_l(*low, __l)) continue;
1143 if (m & punct && iswpunct_l(*low, __l)) continue;
1144 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1145 if (m & blank && iswblank_l(*low, __l)) continue;
1146 break;
1147#endif
1148 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001149 return low;
1150}
1151
1152wchar_t
1153ctype_byname<wchar_t>::do_toupper(char_type c) const
1154{
1155 return towupper_l(c, __l);
1156}
1157
1158const wchar_t*
1159ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1160{
1161 for (; low != high; ++low)
1162 *low = towupper_l(*low, __l);
1163 return low;
1164}
1165
1166wchar_t
1167ctype_byname<wchar_t>::do_tolower(char_type c) const
1168{
1169 return towlower_l(c, __l);
1170}
1171
1172const wchar_t*
1173ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1174{
1175 for (; low != high; ++low)
1176 *low = towlower_l(*low, __l);
1177 return low;
1178}
1179
1180wchar_t
1181ctype_byname<wchar_t>::do_widen(char c) const
1182{
Howard Hinnant866569b2011-09-28 23:39:33 +00001183#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001184 return btowc_l(c, __l);
1185#else
1186 return __btowc_l(c, __l);
1187#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001188}
1189
1190const char*
1191ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1192{
1193 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001194#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001195 *dest = btowc_l(*low, __l);
1196#else
1197 *dest = __btowc_l(*low, __l);
1198#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001199 return low;
1200}
1201
1202char
1203ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1204{
Howard Hinnant866569b2011-09-28 23:39:33 +00001205#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001206 int r = wctob_l(c, __l);
1207#else
1208 int r = __wctob_l(c, __l);
1209#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001210 return r != WEOF ? static_cast<char>(r) : dfault;
1211}
1212
1213const wchar_t*
1214ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1215{
1216 for (; low != high; ++low, ++dest)
1217 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001218#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001219 int r = wctob_l(*low, __l);
1220#else
1221 int r = __wctob_l(*low, __l);
1222#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001223 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1224 }
1225 return low;
1226}
1227
1228// template <> class codecvt<char, char, mbstate_t>
1229
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001230locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001231
1232codecvt<char, char, mbstate_t>::~codecvt()
1233{
1234}
1235
1236codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001237codecvt<char, char, mbstate_t>::do_out(state_type&,
1238 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001239 extern_type* to, extern_type*, extern_type*& to_nxt) const
1240{
1241 frm_nxt = frm;
1242 to_nxt = to;
1243 return noconv;
1244}
1245
1246codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001247codecvt<char, char, mbstate_t>::do_in(state_type&,
1248 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001249 intern_type* to, intern_type*, intern_type*& to_nxt) const
1250{
1251 frm_nxt = frm;
1252 to_nxt = to;
1253 return noconv;
1254}
1255
1256codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001257codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001258 extern_type* to, extern_type*, extern_type*& to_nxt) const
1259{
1260 to_nxt = to;
1261 return noconv;
1262}
1263
1264int
Howard Hinnantc9834542011-05-31 15:34:58 +00001265codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001266{
1267 return 1;
1268}
1269
1270bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001271codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001272{
1273 return true;
1274}
1275
1276int
1277codecvt<char, char, mbstate_t>::do_length(state_type&,
1278 const extern_type* frm, const extern_type* end, size_t mx) const
1279{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001280 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001281}
1282
1283int
Howard Hinnantc9834542011-05-31 15:34:58 +00001284codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001285{
1286 return 1;
1287}
1288
1289// template <> class codecvt<wchar_t, char, mbstate_t>
1290
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001291locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001292
1293codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1294 : locale::facet(refs),
1295 __l(0)
1296{
1297}
1298
1299codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1300 : locale::facet(refs),
1301 __l(newlocale(LC_ALL_MASK, nm, 0))
1302{
Howard Hinnantd4444702010-08-11 17:04:31 +00001303#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001304 if (__l == 0)
1305 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1306 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001307#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001308}
1309
1310codecvt<wchar_t, char, mbstate_t>::~codecvt()
1311{
1312 if (__l != 0)
1313 freelocale(__l);
1314}
1315
1316codecvt<wchar_t, char, mbstate_t>::result
1317codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001318 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001319 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1320{
1321 // look for first internal null in frm
1322 const intern_type* fend = frm;
1323 for (; fend != frm_end; ++fend)
1324 if (*fend == 0)
1325 break;
1326 // loop over all null-terminated sequences in frm
1327 to_nxt = to;
1328 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1329 {
1330 // save state in case needed to reover to_nxt on error
1331 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001332#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001333 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1334 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001335#else
1336 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1337#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001338 if (n == size_t(-1))
1339 {
1340 // need to recover to_nxt
1341 for (to_nxt = to; frm != frm_nxt; ++frm)
1342 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001343#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001344 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1345#else
1346 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1347#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001348 if (n == size_t(-1))
1349 break;
1350 to_nxt += n;
1351 }
1352 frm_nxt = frm;
1353 return error;
1354 }
1355 if (n == 0)
1356 return partial;
1357 to_nxt += n;
1358 if (to_nxt == to_end)
1359 break;
1360 if (fend != frm_end) // set up next null terminated sequence
1361 {
1362 // Try to write the terminating null
1363 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001364#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001365 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1366#else
1367 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1368#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001369 if (n == size_t(-1)) // on error
1370 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001371 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001372 return partial;
1373 for (extern_type* p = tmp; n; --n) // write it
1374 *to_nxt++ = *p++;
1375 ++frm_nxt;
1376 // look for next null in frm
1377 for (fend = frm_nxt; fend != frm_end; ++fend)
1378 if (*fend == 0)
1379 break;
1380 }
1381 }
1382 return frm_nxt == frm_end ? ok : partial;
1383}
1384
1385codecvt<wchar_t, char, mbstate_t>::result
1386codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001387 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001388 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1389{
1390 // look for first internal null in frm
1391 const extern_type* fend = frm;
1392 for (; fend != frm_end; ++fend)
1393 if (*fend == 0)
1394 break;
1395 // loop over all null-terminated sequences in frm
1396 to_nxt = to;
1397 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1398 {
1399 // save state in case needed to reover to_nxt on error
1400 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001401#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001402 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1403 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001404#else
1405 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1406#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001407 if (n == size_t(-1))
1408 {
1409 // need to recover to_nxt
1410 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1411 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001412#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001413 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1414 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001415#else
1416 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1417#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001418 switch (n)
1419 {
1420 case 0:
1421 ++frm;
1422 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001423 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001424 frm_nxt = frm;
1425 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001426 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001427 frm_nxt = frm;
1428 return partial;
1429 default:
1430 frm += n;
1431 break;
1432 }
1433 }
1434 frm_nxt = frm;
1435 return frm_nxt == frm_end ? ok : partial;
1436 }
1437 if (n == 0)
1438 return error;
1439 to_nxt += n;
1440 if (to_nxt == to_end)
1441 break;
1442 if (fend != frm_end) // set up next null terminated sequence
1443 {
1444 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001445#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001446 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1447#else
1448 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1449#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001450 if (n != 0) // on error
1451 return error;
1452 ++to_nxt;
1453 ++frm_nxt;
1454 // look for next null in frm
1455 for (fend = frm_nxt; fend != frm_end; ++fend)
1456 if (*fend == 0)
1457 break;
1458 }
1459 }
1460 return frm_nxt == frm_end ? ok : partial;
1461}
1462
1463codecvt<wchar_t, char, mbstate_t>::result
1464codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1465 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1466{
1467 to_nxt = to;
1468 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001469#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001470 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1471#else
1472 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1473#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001474 if (n == size_t(-1) || n == 0) // on error
1475 return error;
1476 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001477 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001478 return partial;
1479 for (extern_type* p = tmp; n; --n) // write it
1480 *to_nxt++ = *p++;
1481 return ok;
1482}
1483
1484int
Howard Hinnantc9834542011-05-31 15:34:58 +00001485codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001486{
Howard Hinnant866569b2011-09-28 23:39:33 +00001487#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001488 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1489#else
1490 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1491#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001492 {
1493 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001494#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001495 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1496#else
1497 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1498#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001499 return 1; // which take more than 1 char to form a wchar_t
1500 return 0;
1501 }
1502 return -1;
1503}
1504
1505bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001506codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001507{
1508 return false;
1509}
1510
1511int
1512codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1513 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1514{
1515 int nbytes = 0;
1516 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1517 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001518#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001519 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001520#else
1521 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1522#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001523 switch (n)
1524 {
1525 case 0:
1526 ++nbytes;
1527 ++frm;
1528 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001529 case size_t(-1):
1530 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001531 return nbytes;
1532 default:
1533 nbytes += n;
1534 frm += n;
1535 break;
1536 }
1537 }
1538 return nbytes;
1539}
1540
1541int
Howard Hinnantc9834542011-05-31 15:34:58 +00001542codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001543{
Howard Hinnant866569b2011-09-28 23:39:33 +00001544#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001545 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1546#else
1547 return __l == 0 ? 1 : __mb_cur_max_l(__l);
1548#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001549}
1550
1551// Valid UTF ranges
1552// UTF-32 UTF-16 UTF-8 # of code points
1553// first second first second third fourth
1554// 000000 - 00007F 0000 - 007F 00 - 7F 127
1555// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1556// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1557// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1558// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1559// 00D800 - 00DFFF invalid
1560// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1561// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1562// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1563// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1564
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001565static
1566codecvt_base::result
1567utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1568 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1569 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1570{
1571 frm_nxt = frm;
1572 to_nxt = to;
1573 if (mode & generate_header)
1574 {
1575 if (to_end-to_nxt < 3)
1576 return codecvt_base::partial;
1577 *to_nxt++ = static_cast<uint8_t>(0xEF);
1578 *to_nxt++ = static_cast<uint8_t>(0xBB);
1579 *to_nxt++ = static_cast<uint8_t>(0xBF);
1580 }
1581 for (; frm_nxt < frm_end; ++frm_nxt)
1582 {
1583 uint16_t wc1 = *frm_nxt;
1584 if (wc1 > Maxcode)
1585 return codecvt_base::error;
1586 if (wc1 < 0x0080)
1587 {
1588 if (to_end-to_nxt < 1)
1589 return codecvt_base::partial;
1590 *to_nxt++ = static_cast<uint8_t>(wc1);
1591 }
1592 else if (wc1 < 0x0800)
1593 {
1594 if (to_end-to_nxt < 2)
1595 return codecvt_base::partial;
1596 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1597 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1598 }
1599 else if (wc1 < 0xD800)
1600 {
1601 if (to_end-to_nxt < 3)
1602 return codecvt_base::partial;
1603 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1604 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1605 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1606 }
1607 else if (wc1 < 0xDC00)
1608 {
1609 if (frm_end-frm_nxt < 2)
1610 return codecvt_base::partial;
1611 uint16_t wc2 = frm_nxt[1];
1612 if ((wc2 & 0xFC00) != 0xDC00)
1613 return codecvt_base::error;
1614 if (to_end-to_nxt < 4)
1615 return codecvt_base::partial;
1616 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1617 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1618 return codecvt_base::error;
1619 ++frm_nxt;
1620 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1621 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1622 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1623 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1624 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1625 }
1626 else if (wc1 < 0xE000)
1627 {
1628 return codecvt_base::error;
1629 }
1630 else
1631 {
1632 if (to_end-to_nxt < 3)
1633 return codecvt_base::partial;
1634 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1635 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1636 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1637 }
1638 }
1639 return codecvt_base::ok;
1640}
1641
1642static
1643codecvt_base::result
1644utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1645 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1646 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1647{
1648 frm_nxt = frm;
1649 to_nxt = to;
1650 if (mode & generate_header)
1651 {
1652 if (to_end-to_nxt < 3)
1653 return codecvt_base::partial;
1654 *to_nxt++ = static_cast<uint8_t>(0xEF);
1655 *to_nxt++ = static_cast<uint8_t>(0xBB);
1656 *to_nxt++ = static_cast<uint8_t>(0xBF);
1657 }
1658 for (; frm_nxt < frm_end; ++frm_nxt)
1659 {
1660 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1661 if (wc1 > Maxcode)
1662 return codecvt_base::error;
1663 if (wc1 < 0x0080)
1664 {
1665 if (to_end-to_nxt < 1)
1666 return codecvt_base::partial;
1667 *to_nxt++ = static_cast<uint8_t>(wc1);
1668 }
1669 else if (wc1 < 0x0800)
1670 {
1671 if (to_end-to_nxt < 2)
1672 return codecvt_base::partial;
1673 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1674 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1675 }
1676 else if (wc1 < 0xD800)
1677 {
1678 if (to_end-to_nxt < 3)
1679 return codecvt_base::partial;
1680 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1681 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1682 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1683 }
1684 else if (wc1 < 0xDC00)
1685 {
1686 if (frm_end-frm_nxt < 2)
1687 return codecvt_base::partial;
1688 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1689 if ((wc2 & 0xFC00) != 0xDC00)
1690 return codecvt_base::error;
1691 if (to_end-to_nxt < 4)
1692 return codecvt_base::partial;
1693 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1694 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1695 return codecvt_base::error;
1696 ++frm_nxt;
1697 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1698 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1699 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1700 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1701 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1702 }
1703 else if (wc1 < 0xE000)
1704 {
1705 return codecvt_base::error;
1706 }
1707 else
1708 {
1709 if (to_end-to_nxt < 3)
1710 return codecvt_base::partial;
1711 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1712 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1713 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1714 }
1715 }
1716 return codecvt_base::ok;
1717}
1718
1719static
1720codecvt_base::result
1721utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1722 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1723 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1724{
1725 frm_nxt = frm;
1726 to_nxt = to;
1727 if (mode & consume_header)
1728 {
1729 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1730 frm_nxt[2] == 0xBF)
1731 frm_nxt += 3;
1732 }
1733 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1734 {
1735 uint8_t c1 = *frm_nxt;
1736 if (c1 > Maxcode)
1737 return codecvt_base::error;
1738 if (c1 < 0x80)
1739 {
1740 *to_nxt = static_cast<uint16_t>(c1);
1741 ++frm_nxt;
1742 }
1743 else if (c1 < 0xC2)
1744 {
1745 return codecvt_base::error;
1746 }
1747 else if (c1 < 0xE0)
1748 {
1749 if (frm_end-frm_nxt < 2)
1750 return codecvt_base::partial;
1751 uint8_t c2 = frm_nxt[1];
1752 if ((c2 & 0xC0) != 0x80)
1753 return codecvt_base::error;
1754 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1755 if (t > Maxcode)
1756 return codecvt_base::error;
1757 *to_nxt = t;
1758 frm_nxt += 2;
1759 }
1760 else if (c1 < 0xF0)
1761 {
1762 if (frm_end-frm_nxt < 3)
1763 return codecvt_base::partial;
1764 uint8_t c2 = frm_nxt[1];
1765 uint8_t c3 = frm_nxt[2];
1766 switch (c1)
1767 {
1768 case 0xE0:
1769 if ((c2 & 0xE0) != 0xA0)
1770 return codecvt_base::error;
1771 break;
1772 case 0xED:
1773 if ((c2 & 0xE0) != 0x80)
1774 return codecvt_base::error;
1775 break;
1776 default:
1777 if ((c2 & 0xC0) != 0x80)
1778 return codecvt_base::error;
1779 break;
1780 }
1781 if ((c3 & 0xC0) != 0x80)
1782 return codecvt_base::error;
1783 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1784 | ((c2 & 0x3F) << 6)
1785 | (c3 & 0x3F));
1786 if (t > Maxcode)
1787 return codecvt_base::error;
1788 *to_nxt = t;
1789 frm_nxt += 3;
1790 }
1791 else if (c1 < 0xF5)
1792 {
1793 if (frm_end-frm_nxt < 4)
1794 return codecvt_base::partial;
1795 uint8_t c2 = frm_nxt[1];
1796 uint8_t c3 = frm_nxt[2];
1797 uint8_t c4 = frm_nxt[3];
1798 switch (c1)
1799 {
1800 case 0xF0:
1801 if (!(0x90 <= c2 && c2 <= 0xBF))
1802 return codecvt_base::error;
1803 break;
1804 case 0xF4:
1805 if ((c2 & 0xF0) != 0x80)
1806 return codecvt_base::error;
1807 break;
1808 default:
1809 if ((c2 & 0xC0) != 0x80)
1810 return codecvt_base::error;
1811 break;
1812 }
1813 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1814 return codecvt_base::error;
1815 if (to_end-to_nxt < 2)
1816 return codecvt_base::partial;
1817 if (((((unsigned long)c1 & 7) << 18) +
1818 (((unsigned long)c2 & 0x3F) << 12) +
1819 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1820 return codecvt_base::error;
1821 *to_nxt = static_cast<uint16_t>(
1822 0xD800
1823 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1824 | ((c2 & 0x0F) << 2)
1825 | ((c3 & 0x30) >> 4));
1826 *++to_nxt = static_cast<uint16_t>(
1827 0xDC00
1828 | ((c3 & 0x0F) << 6)
1829 | (c4 & 0x3F));
1830 frm_nxt += 4;
1831 }
1832 else
1833 {
1834 return codecvt_base::error;
1835 }
1836 }
1837 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1838}
1839
1840static
1841codecvt_base::result
1842utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1843 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1844 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1845{
1846 frm_nxt = frm;
1847 to_nxt = to;
1848 if (mode & consume_header)
1849 {
1850 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1851 frm_nxt[2] == 0xBF)
1852 frm_nxt += 3;
1853 }
1854 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1855 {
1856 uint8_t c1 = *frm_nxt;
1857 if (c1 > Maxcode)
1858 return codecvt_base::error;
1859 if (c1 < 0x80)
1860 {
1861 *to_nxt = static_cast<uint32_t>(c1);
1862 ++frm_nxt;
1863 }
1864 else if (c1 < 0xC2)
1865 {
1866 return codecvt_base::error;
1867 }
1868 else if (c1 < 0xE0)
1869 {
1870 if (frm_end-frm_nxt < 2)
1871 return codecvt_base::partial;
1872 uint8_t c2 = frm_nxt[1];
1873 if ((c2 & 0xC0) != 0x80)
1874 return codecvt_base::error;
1875 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1876 if (t > Maxcode)
1877 return codecvt_base::error;
1878 *to_nxt = static_cast<uint32_t>(t);
1879 frm_nxt += 2;
1880 }
1881 else if (c1 < 0xF0)
1882 {
1883 if (frm_end-frm_nxt < 3)
1884 return codecvt_base::partial;
1885 uint8_t c2 = frm_nxt[1];
1886 uint8_t c3 = frm_nxt[2];
1887 switch (c1)
1888 {
1889 case 0xE0:
1890 if ((c2 & 0xE0) != 0xA0)
1891 return codecvt_base::error;
1892 break;
1893 case 0xED:
1894 if ((c2 & 0xE0) != 0x80)
1895 return codecvt_base::error;
1896 break;
1897 default:
1898 if ((c2 & 0xC0) != 0x80)
1899 return codecvt_base::error;
1900 break;
1901 }
1902 if ((c3 & 0xC0) != 0x80)
1903 return codecvt_base::error;
1904 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1905 | ((c2 & 0x3F) << 6)
1906 | (c3 & 0x3F));
1907 if (t > Maxcode)
1908 return codecvt_base::error;
1909 *to_nxt = static_cast<uint32_t>(t);
1910 frm_nxt += 3;
1911 }
1912 else if (c1 < 0xF5)
1913 {
1914 if (frm_end-frm_nxt < 4)
1915 return codecvt_base::partial;
1916 uint8_t c2 = frm_nxt[1];
1917 uint8_t c3 = frm_nxt[2];
1918 uint8_t c4 = frm_nxt[3];
1919 switch (c1)
1920 {
1921 case 0xF0:
1922 if (!(0x90 <= c2 && c2 <= 0xBF))
1923 return codecvt_base::error;
1924 break;
1925 case 0xF4:
1926 if ((c2 & 0xF0) != 0x80)
1927 return codecvt_base::error;
1928 break;
1929 default:
1930 if ((c2 & 0xC0) != 0x80)
1931 return codecvt_base::error;
1932 break;
1933 }
1934 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1935 return codecvt_base::error;
1936 if (to_end-to_nxt < 2)
1937 return codecvt_base::partial;
1938 if (((((unsigned long)c1 & 7) << 18) +
1939 (((unsigned long)c2 & 0x3F) << 12) +
1940 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1941 return codecvt_base::error;
1942 *to_nxt = static_cast<uint32_t>(
1943 0xD800
1944 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1945 | ((c2 & 0x0F) << 2)
1946 | ((c3 & 0x30) >> 4));
1947 *++to_nxt = static_cast<uint32_t>(
1948 0xDC00
1949 | ((c3 & 0x0F) << 6)
1950 | (c4 & 0x3F));
1951 frm_nxt += 4;
1952 }
1953 else
1954 {
1955 return codecvt_base::error;
1956 }
1957 }
1958 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1959}
1960
1961static
1962int
1963utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1964 size_t mx, unsigned long Maxcode = 0x10FFFF,
1965 codecvt_mode mode = codecvt_mode(0))
1966{
1967 const uint8_t* frm_nxt = frm;
1968 if (mode & consume_header)
1969 {
1970 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1971 frm_nxt[2] == 0xBF)
1972 frm_nxt += 3;
1973 }
1974 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1975 {
1976 uint8_t c1 = *frm_nxt;
1977 if (c1 > Maxcode)
1978 break;
1979 if (c1 < 0x80)
1980 {
1981 ++frm_nxt;
1982 }
1983 else if (c1 < 0xC2)
1984 {
1985 break;
1986 }
1987 else if (c1 < 0xE0)
1988 {
1989 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1990 break;
1991 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
1992 if (t > Maxcode)
1993 break;
1994 frm_nxt += 2;
1995 }
1996 else if (c1 < 0xF0)
1997 {
1998 if (frm_end-frm_nxt < 3)
1999 break;
2000 uint8_t c2 = frm_nxt[1];
2001 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002002 switch (c1)
2003 {
2004 case 0xE0:
2005 if ((c2 & 0xE0) != 0xA0)
2006 return static_cast<int>(frm_nxt - frm);
2007 break;
2008 case 0xED:
2009 if ((c2 & 0xE0) != 0x80)
2010 return static_cast<int>(frm_nxt - frm);
2011 break;
2012 default:
2013 if ((c2 & 0xC0) != 0x80)
2014 return static_cast<int>(frm_nxt - frm);
2015 break;
2016 }
2017 if ((c3 & 0xC0) != 0x80)
2018 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002019 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002020 break;
2021 frm_nxt += 3;
2022 }
2023 else if (c1 < 0xF5)
2024 {
2025 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2026 break;
2027 uint8_t c2 = frm_nxt[1];
2028 uint8_t c3 = frm_nxt[2];
2029 uint8_t c4 = frm_nxt[3];
2030 switch (c1)
2031 {
2032 case 0xF0:
2033 if (!(0x90 <= c2 && c2 <= 0xBF))
2034 return static_cast<int>(frm_nxt - frm);
2035 break;
2036 case 0xF4:
2037 if ((c2 & 0xF0) != 0x80)
2038 return static_cast<int>(frm_nxt - frm);
2039 break;
2040 default:
2041 if ((c2 & 0xC0) != 0x80)
2042 return static_cast<int>(frm_nxt - frm);
2043 break;
2044 }
2045 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2046 break;
2047 if (((((unsigned long)c1 & 7) << 18) +
2048 (((unsigned long)c2 & 0x3F) << 12) +
2049 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2050 break;
2051 ++nchar16_t;
2052 frm_nxt += 4;
2053 }
2054 else
2055 {
2056 break;
2057 }
2058 }
2059 return static_cast<int>(frm_nxt - frm);
2060}
2061
2062static
2063codecvt_base::result
2064ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2065 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2066 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2067{
2068 frm_nxt = frm;
2069 to_nxt = to;
2070 if (mode & generate_header)
2071 {
2072 if (to_end-to_nxt < 3)
2073 return codecvt_base::partial;
2074 *to_nxt++ = static_cast<uint8_t>(0xEF);
2075 *to_nxt++ = static_cast<uint8_t>(0xBB);
2076 *to_nxt++ = static_cast<uint8_t>(0xBF);
2077 }
2078 for (; frm_nxt < frm_end; ++frm_nxt)
2079 {
2080 uint32_t wc = *frm_nxt;
2081 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2082 return codecvt_base::error;
2083 if (wc < 0x000080)
2084 {
2085 if (to_end-to_nxt < 1)
2086 return codecvt_base::partial;
2087 *to_nxt++ = static_cast<uint8_t>(wc);
2088 }
2089 else if (wc < 0x000800)
2090 {
2091 if (to_end-to_nxt < 2)
2092 return codecvt_base::partial;
2093 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2094 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2095 }
2096 else if (wc < 0x010000)
2097 {
2098 if (to_end-to_nxt < 3)
2099 return codecvt_base::partial;
2100 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2101 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2102 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2103 }
2104 else // if (wc < 0x110000)
2105 {
2106 if (to_end-to_nxt < 4)
2107 return codecvt_base::partial;
2108 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2109 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2110 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2111 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2112 }
2113 }
2114 return codecvt_base::ok;
2115}
2116
2117static
2118codecvt_base::result
2119utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2120 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2121 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2122{
2123 frm_nxt = frm;
2124 to_nxt = to;
2125 if (mode & consume_header)
2126 {
2127 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2128 frm_nxt[2] == 0xBF)
2129 frm_nxt += 3;
2130 }
2131 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2132 {
2133 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2134 if (c1 < 0x80)
2135 {
2136 if (c1 > Maxcode)
2137 return codecvt_base::error;
2138 *to_nxt = static_cast<uint32_t>(c1);
2139 ++frm_nxt;
2140 }
2141 else if (c1 < 0xC2)
2142 {
2143 return codecvt_base::error;
2144 }
2145 else if (c1 < 0xE0)
2146 {
2147 if (frm_end-frm_nxt < 2)
2148 return codecvt_base::partial;
2149 uint8_t c2 = frm_nxt[1];
2150 if ((c2 & 0xC0) != 0x80)
2151 return codecvt_base::error;
2152 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2153 | (c2 & 0x3F));
2154 if (t > Maxcode)
2155 return codecvt_base::error;
2156 *to_nxt = t;
2157 frm_nxt += 2;
2158 }
2159 else if (c1 < 0xF0)
2160 {
2161 if (frm_end-frm_nxt < 3)
2162 return codecvt_base::partial;
2163 uint8_t c2 = frm_nxt[1];
2164 uint8_t c3 = frm_nxt[2];
2165 switch (c1)
2166 {
2167 case 0xE0:
2168 if ((c2 & 0xE0) != 0xA0)
2169 return codecvt_base::error;
2170 break;
2171 case 0xED:
2172 if ((c2 & 0xE0) != 0x80)
2173 return codecvt_base::error;
2174 break;
2175 default:
2176 if ((c2 & 0xC0) != 0x80)
2177 return codecvt_base::error;
2178 break;
2179 }
2180 if ((c3 & 0xC0) != 0x80)
2181 return codecvt_base::error;
2182 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2183 | ((c2 & 0x3F) << 6)
2184 | (c3 & 0x3F));
2185 if (t > Maxcode)
2186 return codecvt_base::error;
2187 *to_nxt = t;
2188 frm_nxt += 3;
2189 }
2190 else if (c1 < 0xF5)
2191 {
2192 if (frm_end-frm_nxt < 4)
2193 return codecvt_base::partial;
2194 uint8_t c2 = frm_nxt[1];
2195 uint8_t c3 = frm_nxt[2];
2196 uint8_t c4 = frm_nxt[3];
2197 switch (c1)
2198 {
2199 case 0xF0:
2200 if (!(0x90 <= c2 && c2 <= 0xBF))
2201 return codecvt_base::error;
2202 break;
2203 case 0xF4:
2204 if ((c2 & 0xF0) != 0x80)
2205 return codecvt_base::error;
2206 break;
2207 default:
2208 if ((c2 & 0xC0) != 0x80)
2209 return codecvt_base::error;
2210 break;
2211 }
2212 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2213 return codecvt_base::error;
2214 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2215 | ((c2 & 0x3F) << 12)
2216 | ((c3 & 0x3F) << 6)
2217 | (c4 & 0x3F));
2218 if (t > Maxcode)
2219 return codecvt_base::error;
2220 *to_nxt = t;
2221 frm_nxt += 4;
2222 }
2223 else
2224 {
2225 return codecvt_base::error;
2226 }
2227 }
2228 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2229}
2230
2231static
2232int
2233utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2234 size_t mx, unsigned long Maxcode = 0x10FFFF,
2235 codecvt_mode mode = codecvt_mode(0))
2236{
2237 const uint8_t* frm_nxt = frm;
2238 if (mode & consume_header)
2239 {
2240 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2241 frm_nxt[2] == 0xBF)
2242 frm_nxt += 3;
2243 }
2244 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2245 {
2246 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2247 if (c1 < 0x80)
2248 {
2249 if (c1 > Maxcode)
2250 break;
2251 ++frm_nxt;
2252 }
2253 else if (c1 < 0xC2)
2254 {
2255 break;
2256 }
2257 else if (c1 < 0xE0)
2258 {
2259 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2260 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002261 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002262 break;
2263 frm_nxt += 2;
2264 }
2265 else if (c1 < 0xF0)
2266 {
2267 if (frm_end-frm_nxt < 3)
2268 break;
2269 uint8_t c2 = frm_nxt[1];
2270 uint8_t c3 = frm_nxt[2];
2271 switch (c1)
2272 {
2273 case 0xE0:
2274 if ((c2 & 0xE0) != 0xA0)
2275 return static_cast<int>(frm_nxt - frm);
2276 break;
2277 case 0xED:
2278 if ((c2 & 0xE0) != 0x80)
2279 return static_cast<int>(frm_nxt - frm);
2280 break;
2281 default:
2282 if ((c2 & 0xC0) != 0x80)
2283 return static_cast<int>(frm_nxt - frm);
2284 break;
2285 }
2286 if ((c3 & 0xC0) != 0x80)
2287 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002288 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002289 break;
2290 frm_nxt += 3;
2291 }
2292 else if (c1 < 0xF5)
2293 {
2294 if (frm_end-frm_nxt < 4)
2295 break;
2296 uint8_t c2 = frm_nxt[1];
2297 uint8_t c3 = frm_nxt[2];
2298 uint8_t c4 = frm_nxt[3];
2299 switch (c1)
2300 {
2301 case 0xF0:
2302 if (!(0x90 <= c2 && c2 <= 0xBF))
2303 return static_cast<int>(frm_nxt - frm);
2304 break;
2305 case 0xF4:
2306 if ((c2 & 0xF0) != 0x80)
2307 return static_cast<int>(frm_nxt - frm);
2308 break;
2309 default:
2310 if ((c2 & 0xC0) != 0x80)
2311 return static_cast<int>(frm_nxt - frm);
2312 break;
2313 }
2314 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2315 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002316 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2317 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002318 break;
2319 frm_nxt += 4;
2320 }
2321 else
2322 {
2323 break;
2324 }
2325 }
2326 return static_cast<int>(frm_nxt - frm);
2327}
2328
2329static
2330codecvt_base::result
2331ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2332 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2333 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2334{
2335 frm_nxt = frm;
2336 to_nxt = to;
2337 if (mode & generate_header)
2338 {
2339 if (to_end-to_nxt < 3)
2340 return codecvt_base::partial;
2341 *to_nxt++ = static_cast<uint8_t>(0xEF);
2342 *to_nxt++ = static_cast<uint8_t>(0xBB);
2343 *to_nxt++ = static_cast<uint8_t>(0xBF);
2344 }
2345 for (; frm_nxt < frm_end; ++frm_nxt)
2346 {
2347 uint16_t wc = *frm_nxt;
2348 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2349 return codecvt_base::error;
2350 if (wc < 0x0080)
2351 {
2352 if (to_end-to_nxt < 1)
2353 return codecvt_base::partial;
2354 *to_nxt++ = static_cast<uint8_t>(wc);
2355 }
2356 else if (wc < 0x0800)
2357 {
2358 if (to_end-to_nxt < 2)
2359 return codecvt_base::partial;
2360 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2361 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2362 }
2363 else // if (wc <= 0xFFFF)
2364 {
2365 if (to_end-to_nxt < 3)
2366 return codecvt_base::partial;
2367 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2368 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2369 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2370 }
2371 }
2372 return codecvt_base::ok;
2373}
2374
2375static
2376codecvt_base::result
2377utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2378 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2379 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2380{
2381 frm_nxt = frm;
2382 to_nxt = to;
2383 if (mode & consume_header)
2384 {
2385 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2386 frm_nxt[2] == 0xBF)
2387 frm_nxt += 3;
2388 }
2389 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2390 {
2391 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2392 if (c1 < 0x80)
2393 {
2394 if (c1 > Maxcode)
2395 return codecvt_base::error;
2396 *to_nxt = static_cast<uint16_t>(c1);
2397 ++frm_nxt;
2398 }
2399 else if (c1 < 0xC2)
2400 {
2401 return codecvt_base::error;
2402 }
2403 else if (c1 < 0xE0)
2404 {
2405 if (frm_end-frm_nxt < 2)
2406 return codecvt_base::partial;
2407 uint8_t c2 = frm_nxt[1];
2408 if ((c2 & 0xC0) != 0x80)
2409 return codecvt_base::error;
2410 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2411 | (c2 & 0x3F));
2412 if (t > Maxcode)
2413 return codecvt_base::error;
2414 *to_nxt = t;
2415 frm_nxt += 2;
2416 }
2417 else if (c1 < 0xF0)
2418 {
2419 if (frm_end-frm_nxt < 3)
2420 return codecvt_base::partial;
2421 uint8_t c2 = frm_nxt[1];
2422 uint8_t c3 = frm_nxt[2];
2423 switch (c1)
2424 {
2425 case 0xE0:
2426 if ((c2 & 0xE0) != 0xA0)
2427 return codecvt_base::error;
2428 break;
2429 case 0xED:
2430 if ((c2 & 0xE0) != 0x80)
2431 return codecvt_base::error;
2432 break;
2433 default:
2434 if ((c2 & 0xC0) != 0x80)
2435 return codecvt_base::error;
2436 break;
2437 }
2438 if ((c3 & 0xC0) != 0x80)
2439 return codecvt_base::error;
2440 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2441 | ((c2 & 0x3F) << 6)
2442 | (c3 & 0x3F));
2443 if (t > Maxcode)
2444 return codecvt_base::error;
2445 *to_nxt = t;
2446 frm_nxt += 3;
2447 }
2448 else
2449 {
2450 return codecvt_base::error;
2451 }
2452 }
2453 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2454}
2455
2456static
2457int
2458utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2459 size_t mx, unsigned long Maxcode = 0x10FFFF,
2460 codecvt_mode mode = codecvt_mode(0))
2461{
2462 const uint8_t* frm_nxt = frm;
2463 if (mode & consume_header)
2464 {
2465 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2466 frm_nxt[2] == 0xBF)
2467 frm_nxt += 3;
2468 }
2469 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2470 {
2471 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2472 if (c1 < 0x80)
2473 {
2474 if (c1 > Maxcode)
2475 break;
2476 ++frm_nxt;
2477 }
2478 else if (c1 < 0xC2)
2479 {
2480 break;
2481 }
2482 else if (c1 < 0xE0)
2483 {
2484 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2485 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002486 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002487 break;
2488 frm_nxt += 2;
2489 }
2490 else if (c1 < 0xF0)
2491 {
2492 if (frm_end-frm_nxt < 3)
2493 break;
2494 uint8_t c2 = frm_nxt[1];
2495 uint8_t c3 = frm_nxt[2];
2496 switch (c1)
2497 {
2498 case 0xE0:
2499 if ((c2 & 0xE0) != 0xA0)
2500 return static_cast<int>(frm_nxt - frm);
2501 break;
2502 case 0xED:
2503 if ((c2 & 0xE0) != 0x80)
2504 return static_cast<int>(frm_nxt - frm);
2505 break;
2506 default:
2507 if ((c2 & 0xC0) != 0x80)
2508 return static_cast<int>(frm_nxt - frm);
2509 break;
2510 }
2511 if ((c3 & 0xC0) != 0x80)
2512 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002513 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002514 break;
2515 frm_nxt += 3;
2516 }
2517 else
2518 {
2519 break;
2520 }
2521 }
2522 return static_cast<int>(frm_nxt - frm);
2523}
2524
2525static
2526codecvt_base::result
2527ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2528 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2529 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2530{
2531 frm_nxt = frm;
2532 to_nxt = to;
2533 if (mode & generate_header)
2534 {
2535 if (to_end-to_nxt < 2)
2536 return codecvt_base::partial;
2537 *to_nxt++ = static_cast<uint8_t>(0xFE);
2538 *to_nxt++ = static_cast<uint8_t>(0xFF);
2539 }
2540 for (; frm_nxt < frm_end; ++frm_nxt)
2541 {
2542 uint32_t wc = *frm_nxt;
2543 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2544 return codecvt_base::error;
2545 if (wc < 0x010000)
2546 {
2547 if (to_end-to_nxt < 2)
2548 return codecvt_base::partial;
2549 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2550 *to_nxt++ = static_cast<uint8_t>(wc);
2551 }
2552 else
2553 {
2554 if (to_end-to_nxt < 4)
2555 return codecvt_base::partial;
2556 uint16_t t = static_cast<uint16_t>(
2557 0xD800
2558 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2559 | ((wc & 0x00FC00) >> 10));
2560 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2561 *to_nxt++ = static_cast<uint8_t>(t);
2562 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2563 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2564 *to_nxt++ = static_cast<uint8_t>(t);
2565 }
2566 }
2567 return codecvt_base::ok;
2568}
2569
2570static
2571codecvt_base::result
2572utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2573 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2574 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2575{
2576 frm_nxt = frm;
2577 to_nxt = to;
2578 if (mode & consume_header)
2579 {
2580 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2581 frm_nxt += 2;
2582 }
2583 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2584 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002585 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002586 if ((c1 & 0xFC00) == 0xDC00)
2587 return codecvt_base::error;
2588 if ((c1 & 0xFC00) != 0xD800)
2589 {
2590 if (c1 > Maxcode)
2591 return codecvt_base::error;
2592 *to_nxt = static_cast<uint32_t>(c1);
2593 frm_nxt += 2;
2594 }
2595 else
2596 {
2597 if (frm_end-frm_nxt < 4)
2598 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002599 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002600 if ((c2 & 0xFC00) != 0xDC00)
2601 return codecvt_base::error;
2602 uint32_t t = static_cast<uint32_t>(
2603 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2604 | ((c1 & 0x003F) << 10)
2605 | (c2 & 0x03FF));
2606 if (t > Maxcode)
2607 return codecvt_base::error;
2608 *to_nxt = t;
2609 frm_nxt += 4;
2610 }
2611 }
2612 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2613}
2614
2615static
2616int
2617utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2618 size_t mx, unsigned long Maxcode = 0x10FFFF,
2619 codecvt_mode mode = codecvt_mode(0))
2620{
2621 const uint8_t* frm_nxt = frm;
2622 frm_nxt = frm;
2623 if (mode & consume_header)
2624 {
2625 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2626 frm_nxt += 2;
2627 }
2628 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2629 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002630 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002631 if ((c1 & 0xFC00) == 0xDC00)
2632 break;
2633 if ((c1 & 0xFC00) != 0xD800)
2634 {
2635 if (c1 > Maxcode)
2636 break;
2637 frm_nxt += 2;
2638 }
2639 else
2640 {
2641 if (frm_end-frm_nxt < 4)
2642 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002643 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002644 if ((c2 & 0xFC00) != 0xDC00)
2645 break;
2646 uint32_t t = static_cast<uint32_t>(
2647 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2648 | ((c1 & 0x003F) << 10)
2649 | (c2 & 0x03FF));
2650 if (t > Maxcode)
2651 break;
2652 frm_nxt += 4;
2653 }
2654 }
2655 return static_cast<int>(frm_nxt - frm);
2656}
2657
2658static
2659codecvt_base::result
2660ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2661 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2662 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2663{
2664 frm_nxt = frm;
2665 to_nxt = to;
2666 if (mode & generate_header)
2667 {
2668 if (to_end-to_nxt < 2)
2669 return codecvt_base::partial;
2670 *to_nxt++ = static_cast<uint8_t>(0xFF);
2671 *to_nxt++ = static_cast<uint8_t>(0xFE);
2672 }
2673 for (; frm_nxt < frm_end; ++frm_nxt)
2674 {
2675 uint32_t wc = *frm_nxt;
2676 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2677 return codecvt_base::error;
2678 if (wc < 0x010000)
2679 {
2680 if (to_end-to_nxt < 2)
2681 return codecvt_base::partial;
2682 *to_nxt++ = static_cast<uint8_t>(wc);
2683 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2684 }
2685 else
2686 {
2687 if (to_end-to_nxt < 4)
2688 return codecvt_base::partial;
2689 uint16_t t = static_cast<uint16_t>(
2690 0xD800
2691 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2692 | ((wc & 0x00FC00) >> 10));
2693 *to_nxt++ = static_cast<uint8_t>(t);
2694 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2695 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2696 *to_nxt++ = static_cast<uint8_t>(t);
2697 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2698 }
2699 }
2700 return codecvt_base::ok;
2701}
2702
2703static
2704codecvt_base::result
2705utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2706 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2707 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2708{
2709 frm_nxt = frm;
2710 to_nxt = to;
2711 if (mode & consume_header)
2712 {
2713 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2714 frm_nxt += 2;
2715 }
2716 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2717 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002718 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002719 if ((c1 & 0xFC00) == 0xDC00)
2720 return codecvt_base::error;
2721 if ((c1 & 0xFC00) != 0xD800)
2722 {
2723 if (c1 > Maxcode)
2724 return codecvt_base::error;
2725 *to_nxt = static_cast<uint32_t>(c1);
2726 frm_nxt += 2;
2727 }
2728 else
2729 {
2730 if (frm_end-frm_nxt < 4)
2731 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002732 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002733 if ((c2 & 0xFC00) != 0xDC00)
2734 return codecvt_base::error;
2735 uint32_t t = static_cast<uint32_t>(
2736 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2737 | ((c1 & 0x003F) << 10)
2738 | (c2 & 0x03FF));
2739 if (t > Maxcode)
2740 return codecvt_base::error;
2741 *to_nxt = t;
2742 frm_nxt += 4;
2743 }
2744 }
2745 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2746}
2747
2748static
2749int
2750utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2751 size_t mx, unsigned long Maxcode = 0x10FFFF,
2752 codecvt_mode mode = codecvt_mode(0))
2753{
2754 const uint8_t* frm_nxt = frm;
2755 frm_nxt = frm;
2756 if (mode & consume_header)
2757 {
2758 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2759 frm_nxt += 2;
2760 }
2761 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2762 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002763 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002764 if ((c1 & 0xFC00) == 0xDC00)
2765 break;
2766 if ((c1 & 0xFC00) != 0xD800)
2767 {
2768 if (c1 > Maxcode)
2769 break;
2770 frm_nxt += 2;
2771 }
2772 else
2773 {
2774 if (frm_end-frm_nxt < 4)
2775 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002776 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002777 if ((c2 & 0xFC00) != 0xDC00)
2778 break;
2779 uint32_t t = static_cast<uint32_t>(
2780 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2781 | ((c1 & 0x003F) << 10)
2782 | (c2 & 0x03FF));
2783 if (t > Maxcode)
2784 break;
2785 frm_nxt += 4;
2786 }
2787 }
2788 return static_cast<int>(frm_nxt - frm);
2789}
2790
2791static
2792codecvt_base::result
2793ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2794 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2795 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2796{
2797 frm_nxt = frm;
2798 to_nxt = to;
2799 if (mode & generate_header)
2800 {
2801 if (to_end-to_nxt < 2)
2802 return codecvt_base::partial;
2803 *to_nxt++ = static_cast<uint8_t>(0xFE);
2804 *to_nxt++ = static_cast<uint8_t>(0xFF);
2805 }
2806 for (; frm_nxt < frm_end; ++frm_nxt)
2807 {
2808 uint16_t wc = *frm_nxt;
2809 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2810 return codecvt_base::error;
2811 if (to_end-to_nxt < 2)
2812 return codecvt_base::partial;
2813 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2814 *to_nxt++ = static_cast<uint8_t>(wc);
2815 }
2816 return codecvt_base::ok;
2817}
2818
2819static
2820codecvt_base::result
2821utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2822 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2823 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2824{
2825 frm_nxt = frm;
2826 to_nxt = to;
2827 if (mode & consume_header)
2828 {
2829 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2830 frm_nxt += 2;
2831 }
2832 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2833 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002834 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002835 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2836 return codecvt_base::error;
2837 *to_nxt = c1;
2838 frm_nxt += 2;
2839 }
2840 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2841}
2842
2843static
2844int
2845utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2846 size_t mx, unsigned long Maxcode = 0x10FFFF,
2847 codecvt_mode mode = codecvt_mode(0))
2848{
2849 const uint8_t* frm_nxt = frm;
2850 frm_nxt = frm;
2851 if (mode & consume_header)
2852 {
2853 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2854 frm_nxt += 2;
2855 }
2856 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2857 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002858 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002859 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2860 break;
2861 frm_nxt += 2;
2862 }
2863 return static_cast<int>(frm_nxt - frm);
2864}
2865
2866static
2867codecvt_base::result
2868ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2869 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2870 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2871{
2872 frm_nxt = frm;
2873 to_nxt = to;
2874 if (mode & generate_header)
2875 {
2876 if (to_end-to_nxt < 2)
2877 return codecvt_base::partial;
2878 *to_nxt++ = static_cast<uint8_t>(0xFF);
2879 *to_nxt++ = static_cast<uint8_t>(0xFE);
2880 }
2881 for (; frm_nxt < frm_end; ++frm_nxt)
2882 {
2883 uint16_t wc = *frm_nxt;
2884 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2885 return codecvt_base::error;
2886 if (to_end-to_nxt < 2)
2887 return codecvt_base::partial;
2888 *to_nxt++ = static_cast<uint8_t>(wc);
2889 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2890 }
2891 return codecvt_base::ok;
2892}
2893
2894static
2895codecvt_base::result
2896utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2897 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2898 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2899{
2900 frm_nxt = frm;
2901 to_nxt = to;
2902 if (mode & consume_header)
2903 {
2904 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2905 frm_nxt += 2;
2906 }
2907 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2908 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002909 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002910 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2911 return codecvt_base::error;
2912 *to_nxt = c1;
2913 frm_nxt += 2;
2914 }
2915 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2916}
2917
2918static
2919int
2920utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2921 size_t mx, unsigned long Maxcode = 0x10FFFF,
2922 codecvt_mode mode = codecvt_mode(0))
2923{
2924 const uint8_t* frm_nxt = frm;
2925 frm_nxt = frm;
2926 if (mode & consume_header)
2927 {
2928 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2929 frm_nxt += 2;
2930 }
2931 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2932 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002933 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002934 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2935 break;
2936 frm_nxt += 2;
2937 }
2938 return static_cast<int>(frm_nxt - frm);
2939}
2940
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002941// template <> class codecvt<char16_t, char, mbstate_t>
2942
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002943locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002944
2945codecvt<char16_t, char, mbstate_t>::~codecvt()
2946{
2947}
2948
2949codecvt<char16_t, char, mbstate_t>::result
2950codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002951 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002952 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2953{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002954 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2955 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2956 const uint16_t* _frm_nxt = _frm;
2957 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2958 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2959 uint8_t* _to_nxt = _to;
2960 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2961 frm_nxt = frm + (_frm_nxt - _frm);
2962 to_nxt = to + (_to_nxt - _to);
2963 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002964}
2965
2966codecvt<char16_t, char, mbstate_t>::result
2967codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002968 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002969 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2970{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002971 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2972 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2973 const uint8_t* _frm_nxt = _frm;
2974 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2975 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2976 uint16_t* _to_nxt = _to;
2977 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2978 frm_nxt = frm + (_frm_nxt - _frm);
2979 to_nxt = to + (_to_nxt - _to);
2980 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002981}
2982
2983codecvt<char16_t, char, mbstate_t>::result
2984codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
2985 extern_type* to, extern_type*, extern_type*& to_nxt) const
2986{
2987 to_nxt = to;
2988 return noconv;
2989}
2990
2991int
Howard Hinnantc9834542011-05-31 15:34:58 +00002992codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002993{
2994 return 0;
2995}
2996
2997bool
Howard Hinnantc9834542011-05-31 15:34:58 +00002998codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002999{
3000 return false;
3001}
3002
3003int
3004codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3005 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3006{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003007 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3008 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3009 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003010}
3011
3012int
Howard Hinnantc9834542011-05-31 15:34:58 +00003013codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003014{
3015 return 4;
3016}
3017
3018// template <> class codecvt<char32_t, char, mbstate_t>
3019
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003020locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003021
3022codecvt<char32_t, char, mbstate_t>::~codecvt()
3023{
3024}
3025
3026codecvt<char32_t, char, mbstate_t>::result
3027codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003028 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003029 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3030{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003031 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3032 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3033 const uint32_t* _frm_nxt = _frm;
3034 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3035 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3036 uint8_t* _to_nxt = _to;
3037 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3038 frm_nxt = frm + (_frm_nxt - _frm);
3039 to_nxt = to + (_to_nxt - _to);
3040 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003041}
3042
3043codecvt<char32_t, char, mbstate_t>::result
3044codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003045 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003046 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3047{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003048 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3049 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3050 const uint8_t* _frm_nxt = _frm;
3051 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3052 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3053 uint32_t* _to_nxt = _to;
3054 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3055 frm_nxt = frm + (_frm_nxt - _frm);
3056 to_nxt = to + (_to_nxt - _to);
3057 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003058}
3059
3060codecvt<char32_t, char, mbstate_t>::result
3061codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3062 extern_type* to, extern_type*, extern_type*& to_nxt) const
3063{
3064 to_nxt = to;
3065 return noconv;
3066}
3067
3068int
Howard Hinnantc9834542011-05-31 15:34:58 +00003069codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003070{
3071 return 0;
3072}
3073
3074bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003075codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003076{
3077 return false;
3078}
3079
3080int
3081codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3082 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3083{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003084 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3085 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3086 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003087}
3088
3089int
Howard Hinnantc9834542011-05-31 15:34:58 +00003090codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003091{
3092 return 4;
3093}
3094
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003095// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003096
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003097__codecvt_utf8<wchar_t>::result
3098__codecvt_utf8<wchar_t>::do_out(state_type&,
3099 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003100 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3101{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003102 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3103 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3104 const uint32_t* _frm_nxt = _frm;
3105 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3106 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3107 uint8_t* _to_nxt = _to;
3108 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3109 _Maxcode_, _Mode_);
3110 frm_nxt = frm + (_frm_nxt - _frm);
3111 to_nxt = to + (_to_nxt - _to);
3112 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003113}
3114
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003115__codecvt_utf8<wchar_t>::result
3116__codecvt_utf8<wchar_t>::do_in(state_type&,
3117 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003118 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3119{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003120 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3121 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3122 const uint8_t* _frm_nxt = _frm;
3123 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3124 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3125 uint32_t* _to_nxt = _to;
3126 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3127 _Maxcode_, _Mode_);
3128 frm_nxt = frm + (_frm_nxt - _frm);
3129 to_nxt = to + (_to_nxt - _to);
3130 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003131}
3132
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003133__codecvt_utf8<wchar_t>::result
3134__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003135 extern_type* to, extern_type*, extern_type*& to_nxt) const
3136{
3137 to_nxt = to;
3138 return noconv;
3139}
3140
3141int
Howard Hinnantc9834542011-05-31 15:34:58 +00003142__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003143{
3144 return 0;
3145}
3146
3147bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003148__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003149{
3150 return false;
3151}
3152
3153int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003154__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003155 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3156{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003157 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3158 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3159 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003160}
3161
3162int
Howard Hinnantc9834542011-05-31 15:34:58 +00003163__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003164{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003165 if (_Mode_ & consume_header)
3166 return 7;
3167 return 4;
3168}
3169
3170// __codecvt_utf8<char16_t>
3171
3172__codecvt_utf8<char16_t>::result
3173__codecvt_utf8<char16_t>::do_out(state_type&,
3174 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3175 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3176{
3177 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3178 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3179 const uint16_t* _frm_nxt = _frm;
3180 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3181 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3182 uint8_t* _to_nxt = _to;
3183 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3184 _Maxcode_, _Mode_);
3185 frm_nxt = frm + (_frm_nxt - _frm);
3186 to_nxt = to + (_to_nxt - _to);
3187 return r;
3188}
3189
3190__codecvt_utf8<char16_t>::result
3191__codecvt_utf8<char16_t>::do_in(state_type&,
3192 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3193 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3194{
3195 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3196 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3197 const uint8_t* _frm_nxt = _frm;
3198 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3199 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3200 uint16_t* _to_nxt = _to;
3201 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3202 _Maxcode_, _Mode_);
3203 frm_nxt = frm + (_frm_nxt - _frm);
3204 to_nxt = to + (_to_nxt - _to);
3205 return r;
3206}
3207
3208__codecvt_utf8<char16_t>::result
3209__codecvt_utf8<char16_t>::do_unshift(state_type&,
3210 extern_type* to, extern_type*, extern_type*& to_nxt) const
3211{
3212 to_nxt = to;
3213 return noconv;
3214}
3215
3216int
Howard Hinnantc9834542011-05-31 15:34:58 +00003217__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003218{
3219 return 0;
3220}
3221
3222bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003223__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003224{
3225 return false;
3226}
3227
3228int
3229__codecvt_utf8<char16_t>::do_length(state_type&,
3230 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3231{
3232 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3233 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3234 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3235}
3236
3237int
Howard Hinnantc9834542011-05-31 15:34:58 +00003238__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003239{
3240 if (_Mode_ & consume_header)
3241 return 6;
3242 return 3;
3243}
3244
3245// __codecvt_utf8<char32_t>
3246
3247__codecvt_utf8<char32_t>::result
3248__codecvt_utf8<char32_t>::do_out(state_type&,
3249 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3250 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3251{
3252 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3253 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3254 const uint32_t* _frm_nxt = _frm;
3255 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3256 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3257 uint8_t* _to_nxt = _to;
3258 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3259 _Maxcode_, _Mode_);
3260 frm_nxt = frm + (_frm_nxt - _frm);
3261 to_nxt = to + (_to_nxt - _to);
3262 return r;
3263}
3264
3265__codecvt_utf8<char32_t>::result
3266__codecvt_utf8<char32_t>::do_in(state_type&,
3267 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3268 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3269{
3270 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3271 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3272 const uint8_t* _frm_nxt = _frm;
3273 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3274 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3275 uint32_t* _to_nxt = _to;
3276 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3277 _Maxcode_, _Mode_);
3278 frm_nxt = frm + (_frm_nxt - _frm);
3279 to_nxt = to + (_to_nxt - _to);
3280 return r;
3281}
3282
3283__codecvt_utf8<char32_t>::result
3284__codecvt_utf8<char32_t>::do_unshift(state_type&,
3285 extern_type* to, extern_type*, extern_type*& to_nxt) const
3286{
3287 to_nxt = to;
3288 return noconv;
3289}
3290
3291int
Howard Hinnantc9834542011-05-31 15:34:58 +00003292__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003293{
3294 return 0;
3295}
3296
3297bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003298__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003299{
3300 return false;
3301}
3302
3303int
3304__codecvt_utf8<char32_t>::do_length(state_type&,
3305 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3306{
3307 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3308 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3309 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3310}
3311
3312int
Howard Hinnantc9834542011-05-31 15:34:58 +00003313__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003314{
3315 if (_Mode_ & consume_header)
3316 return 7;
3317 return 4;
3318}
3319
3320// __codecvt_utf16<wchar_t, false>
3321
3322__codecvt_utf16<wchar_t, false>::result
3323__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3324 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3325 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3326{
3327 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3328 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3329 const uint32_t* _frm_nxt = _frm;
3330 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3331 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3332 uint8_t* _to_nxt = _to;
3333 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3334 _Maxcode_, _Mode_);
3335 frm_nxt = frm + (_frm_nxt - _frm);
3336 to_nxt = to + (_to_nxt - _to);
3337 return r;
3338}
3339
3340__codecvt_utf16<wchar_t, false>::result
3341__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3342 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3343 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3344{
3345 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3346 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3347 const uint8_t* _frm_nxt = _frm;
3348 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3349 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3350 uint32_t* _to_nxt = _to;
3351 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3352 _Maxcode_, _Mode_);
3353 frm_nxt = frm + (_frm_nxt - _frm);
3354 to_nxt = to + (_to_nxt - _to);
3355 return r;
3356}
3357
3358__codecvt_utf16<wchar_t, false>::result
3359__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3360 extern_type* to, extern_type*, extern_type*& to_nxt) const
3361{
3362 to_nxt = to;
3363 return noconv;
3364}
3365
3366int
Howard Hinnantc9834542011-05-31 15:34:58 +00003367__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003368{
3369 return 0;
3370}
3371
3372bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003373__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003374{
3375 return false;
3376}
3377
3378int
3379__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3380 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3381{
3382 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3383 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3384 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3385}
3386
3387int
Howard Hinnantc9834542011-05-31 15:34:58 +00003388__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003389{
3390 if (_Mode_ & consume_header)
3391 return 6;
3392 return 4;
3393}
3394
3395// __codecvt_utf16<wchar_t, true>
3396
3397__codecvt_utf16<wchar_t, true>::result
3398__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3399 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3400 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3401{
3402 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3403 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3404 const uint32_t* _frm_nxt = _frm;
3405 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3406 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3407 uint8_t* _to_nxt = _to;
3408 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3409 _Maxcode_, _Mode_);
3410 frm_nxt = frm + (_frm_nxt - _frm);
3411 to_nxt = to + (_to_nxt - _to);
3412 return r;
3413}
3414
3415__codecvt_utf16<wchar_t, true>::result
3416__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3417 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3418 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3419{
3420 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3421 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3422 const uint8_t* _frm_nxt = _frm;
3423 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3424 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3425 uint32_t* _to_nxt = _to;
3426 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3427 _Maxcode_, _Mode_);
3428 frm_nxt = frm + (_frm_nxt - _frm);
3429 to_nxt = to + (_to_nxt - _to);
3430 return r;
3431}
3432
3433__codecvt_utf16<wchar_t, true>::result
3434__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3435 extern_type* to, extern_type*, extern_type*& to_nxt) const
3436{
3437 to_nxt = to;
3438 return noconv;
3439}
3440
3441int
Howard Hinnantc9834542011-05-31 15:34:58 +00003442__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003443{
3444 return 0;
3445}
3446
3447bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003448__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003449{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003450 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003451}
3452
3453int
3454__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3455 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3456{
3457 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3458 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3459 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3460}
3461
3462int
Howard Hinnantc9834542011-05-31 15:34:58 +00003463__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003464{
3465 if (_Mode_ & consume_header)
3466 return 6;
3467 return 4;
3468}
3469
3470// __codecvt_utf16<char16_t, false>
3471
3472__codecvt_utf16<char16_t, false>::result
3473__codecvt_utf16<char16_t, false>::do_out(state_type&,
3474 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3475 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3476{
3477 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3478 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3479 const uint16_t* _frm_nxt = _frm;
3480 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3481 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3482 uint8_t* _to_nxt = _to;
3483 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3484 _Maxcode_, _Mode_);
3485 frm_nxt = frm + (_frm_nxt - _frm);
3486 to_nxt = to + (_to_nxt - _to);
3487 return r;
3488}
3489
3490__codecvt_utf16<char16_t, false>::result
3491__codecvt_utf16<char16_t, false>::do_in(state_type&,
3492 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3493 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3494{
3495 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3496 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3497 const uint8_t* _frm_nxt = _frm;
3498 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3499 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3500 uint16_t* _to_nxt = _to;
3501 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3502 _Maxcode_, _Mode_);
3503 frm_nxt = frm + (_frm_nxt - _frm);
3504 to_nxt = to + (_to_nxt - _to);
3505 return r;
3506}
3507
3508__codecvt_utf16<char16_t, false>::result
3509__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3510 extern_type* to, extern_type*, extern_type*& to_nxt) const
3511{
3512 to_nxt = to;
3513 return noconv;
3514}
3515
3516int
Howard Hinnantc9834542011-05-31 15:34:58 +00003517__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003518{
3519 return 0;
3520}
3521
3522bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003523__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003524{
3525 return false;
3526}
3527
3528int
3529__codecvt_utf16<char16_t, false>::do_length(state_type&,
3530 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3531{
3532 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3533 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3534 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3535}
3536
3537int
Howard Hinnantc9834542011-05-31 15:34:58 +00003538__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003539{
3540 if (_Mode_ & consume_header)
3541 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003542 return 2;
3543}
3544
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003545// __codecvt_utf16<char16_t, true>
3546
3547__codecvt_utf16<char16_t, true>::result
3548__codecvt_utf16<char16_t, true>::do_out(state_type&,
3549 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3550 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3551{
3552 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3553 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3554 const uint16_t* _frm_nxt = _frm;
3555 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3556 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3557 uint8_t* _to_nxt = _to;
3558 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3559 _Maxcode_, _Mode_);
3560 frm_nxt = frm + (_frm_nxt - _frm);
3561 to_nxt = to + (_to_nxt - _to);
3562 return r;
3563}
3564
3565__codecvt_utf16<char16_t, true>::result
3566__codecvt_utf16<char16_t, true>::do_in(state_type&,
3567 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3568 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3569{
3570 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3571 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3572 const uint8_t* _frm_nxt = _frm;
3573 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3574 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3575 uint16_t* _to_nxt = _to;
3576 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3577 _Maxcode_, _Mode_);
3578 frm_nxt = frm + (_frm_nxt - _frm);
3579 to_nxt = to + (_to_nxt - _to);
3580 return r;
3581}
3582
3583__codecvt_utf16<char16_t, true>::result
3584__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3585 extern_type* to, extern_type*, extern_type*& to_nxt) const
3586{
3587 to_nxt = to;
3588 return noconv;
3589}
3590
3591int
Howard Hinnantc9834542011-05-31 15:34:58 +00003592__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003593{
3594 return 0;
3595}
3596
3597bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003598__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003599{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003600 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003601}
3602
3603int
3604__codecvt_utf16<char16_t, true>::do_length(state_type&,
3605 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3606{
3607 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3608 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3609 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3610}
3611
3612int
Howard Hinnantc9834542011-05-31 15:34:58 +00003613__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003614{
3615 if (_Mode_ & consume_header)
3616 return 4;
3617 return 2;
3618}
3619
3620// __codecvt_utf16<char32_t, false>
3621
3622__codecvt_utf16<char32_t, false>::result
3623__codecvt_utf16<char32_t, false>::do_out(state_type&,
3624 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3625 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3626{
3627 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3628 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3629 const uint32_t* _frm_nxt = _frm;
3630 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3631 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3632 uint8_t* _to_nxt = _to;
3633 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3634 _Maxcode_, _Mode_);
3635 frm_nxt = frm + (_frm_nxt - _frm);
3636 to_nxt = to + (_to_nxt - _to);
3637 return r;
3638}
3639
3640__codecvt_utf16<char32_t, false>::result
3641__codecvt_utf16<char32_t, false>::do_in(state_type&,
3642 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3643 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3644{
3645 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3646 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3647 const uint8_t* _frm_nxt = _frm;
3648 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3649 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3650 uint32_t* _to_nxt = _to;
3651 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3652 _Maxcode_, _Mode_);
3653 frm_nxt = frm + (_frm_nxt - _frm);
3654 to_nxt = to + (_to_nxt - _to);
3655 return r;
3656}
3657
3658__codecvt_utf16<char32_t, false>::result
3659__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3660 extern_type* to, extern_type*, extern_type*& to_nxt) const
3661{
3662 to_nxt = to;
3663 return noconv;
3664}
3665
3666int
Howard Hinnantc9834542011-05-31 15:34:58 +00003667__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003668{
3669 return 0;
3670}
3671
3672bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003673__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003674{
3675 return false;
3676}
3677
3678int
3679__codecvt_utf16<char32_t, false>::do_length(state_type&,
3680 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3681{
3682 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3683 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3684 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3685}
3686
3687int
Howard Hinnantc9834542011-05-31 15:34:58 +00003688__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003689{
3690 if (_Mode_ & consume_header)
3691 return 6;
3692 return 4;
3693}
3694
3695// __codecvt_utf16<char32_t, true>
3696
3697__codecvt_utf16<char32_t, true>::result
3698__codecvt_utf16<char32_t, true>::do_out(state_type&,
3699 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3700 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3701{
3702 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3703 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3704 const uint32_t* _frm_nxt = _frm;
3705 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3706 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3707 uint8_t* _to_nxt = _to;
3708 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3709 _Maxcode_, _Mode_);
3710 frm_nxt = frm + (_frm_nxt - _frm);
3711 to_nxt = to + (_to_nxt - _to);
3712 return r;
3713}
3714
3715__codecvt_utf16<char32_t, true>::result
3716__codecvt_utf16<char32_t, true>::do_in(state_type&,
3717 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3718 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3719{
3720 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3721 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3722 const uint8_t* _frm_nxt = _frm;
3723 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3724 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3725 uint32_t* _to_nxt = _to;
3726 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3727 _Maxcode_, _Mode_);
3728 frm_nxt = frm + (_frm_nxt - _frm);
3729 to_nxt = to + (_to_nxt - _to);
3730 return r;
3731}
3732
3733__codecvt_utf16<char32_t, true>::result
3734__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3735 extern_type* to, extern_type*, extern_type*& to_nxt) const
3736{
3737 to_nxt = to;
3738 return noconv;
3739}
3740
3741int
Howard Hinnantc9834542011-05-31 15:34:58 +00003742__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003743{
3744 return 0;
3745}
3746
3747bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003748__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003749{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003750 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003751}
3752
3753int
3754__codecvt_utf16<char32_t, true>::do_length(state_type&,
3755 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3756{
3757 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3758 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3759 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3760}
3761
3762int
Howard Hinnantc9834542011-05-31 15:34:58 +00003763__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003764{
3765 if (_Mode_ & consume_header)
3766 return 6;
3767 return 4;
3768}
3769
3770// __codecvt_utf8_utf16<wchar_t>
3771
3772__codecvt_utf8_utf16<wchar_t>::result
3773__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3774 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3775 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3776{
3777 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3778 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3779 const uint32_t* _frm_nxt = _frm;
3780 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3781 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3782 uint8_t* _to_nxt = _to;
3783 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3784 _Maxcode_, _Mode_);
3785 frm_nxt = frm + (_frm_nxt - _frm);
3786 to_nxt = to + (_to_nxt - _to);
3787 return r;
3788}
3789
3790__codecvt_utf8_utf16<wchar_t>::result
3791__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3792 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3793 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3794{
3795 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3796 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3797 const uint8_t* _frm_nxt = _frm;
3798 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3799 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3800 uint32_t* _to_nxt = _to;
3801 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3802 _Maxcode_, _Mode_);
3803 frm_nxt = frm + (_frm_nxt - _frm);
3804 to_nxt = to + (_to_nxt - _to);
3805 return r;
3806}
3807
3808__codecvt_utf8_utf16<wchar_t>::result
3809__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3810 extern_type* to, extern_type*, extern_type*& to_nxt) const
3811{
3812 to_nxt = to;
3813 return noconv;
3814}
3815
3816int
Howard Hinnantc9834542011-05-31 15:34:58 +00003817__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003818{
3819 return 0;
3820}
3821
3822bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003823__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003824{
3825 return false;
3826}
3827
3828int
3829__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3830 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3831{
3832 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3833 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3834 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3835}
3836
3837int
Howard Hinnantc9834542011-05-31 15:34:58 +00003838__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003839{
3840 if (_Mode_ & consume_header)
3841 return 7;
3842 return 4;
3843}
3844
3845// __codecvt_utf8_utf16<char16_t>
3846
3847__codecvt_utf8_utf16<char16_t>::result
3848__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3849 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3850 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3851{
3852 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3853 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3854 const uint16_t* _frm_nxt = _frm;
3855 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3856 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3857 uint8_t* _to_nxt = _to;
3858 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3859 _Maxcode_, _Mode_);
3860 frm_nxt = frm + (_frm_nxt - _frm);
3861 to_nxt = to + (_to_nxt - _to);
3862 return r;
3863}
3864
3865__codecvt_utf8_utf16<char16_t>::result
3866__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3867 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3868 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3869{
3870 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3871 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3872 const uint8_t* _frm_nxt = _frm;
3873 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3874 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3875 uint16_t* _to_nxt = _to;
3876 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3877 _Maxcode_, _Mode_);
3878 frm_nxt = frm + (_frm_nxt - _frm);
3879 to_nxt = to + (_to_nxt - _to);
3880 return r;
3881}
3882
3883__codecvt_utf8_utf16<char16_t>::result
3884__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3885 extern_type* to, extern_type*, extern_type*& to_nxt) const
3886{
3887 to_nxt = to;
3888 return noconv;
3889}
3890
3891int
Howard Hinnantc9834542011-05-31 15:34:58 +00003892__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003893{
3894 return 0;
3895}
3896
3897bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003898__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003899{
3900 return false;
3901}
3902
3903int
3904__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3905 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3906{
3907 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3908 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3909 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3910}
3911
3912int
Howard Hinnantc9834542011-05-31 15:34:58 +00003913__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003914{
3915 if (_Mode_ & consume_header)
3916 return 7;
3917 return 4;
3918}
3919
3920// __codecvt_utf8_utf16<char32_t>
3921
3922__codecvt_utf8_utf16<char32_t>::result
3923__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3924 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3925 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3926{
3927 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3928 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3929 const uint32_t* _frm_nxt = _frm;
3930 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3931 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3932 uint8_t* _to_nxt = _to;
3933 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3934 _Maxcode_, _Mode_);
3935 frm_nxt = frm + (_frm_nxt - _frm);
3936 to_nxt = to + (_to_nxt - _to);
3937 return r;
3938}
3939
3940__codecvt_utf8_utf16<char32_t>::result
3941__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3942 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3943 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3944{
3945 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3946 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3947 const uint8_t* _frm_nxt = _frm;
3948 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3949 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3950 uint32_t* _to_nxt = _to;
3951 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3952 _Maxcode_, _Mode_);
3953 frm_nxt = frm + (_frm_nxt - _frm);
3954 to_nxt = to + (_to_nxt - _to);
3955 return r;
3956}
3957
3958__codecvt_utf8_utf16<char32_t>::result
3959__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3960 extern_type* to, extern_type*, extern_type*& to_nxt) const
3961{
3962 to_nxt = to;
3963 return noconv;
3964}
3965
3966int
Howard Hinnantc9834542011-05-31 15:34:58 +00003967__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003968{
3969 return 0;
3970}
3971
3972bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003973__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003974{
3975 return false;
3976}
3977
3978int
3979__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3980 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3981{
3982 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3983 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3984 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3985}
3986
3987int
Howard Hinnantc9834542011-05-31 15:34:58 +00003988__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003989{
3990 if (_Mode_ & consume_header)
3991 return 7;
3992 return 4;
3993}
3994
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003995// __narrow_to_utf8<16>
3996
3997__narrow_to_utf8<16>::~__narrow_to_utf8()
3998{
3999}
4000
4001// __narrow_to_utf8<32>
4002
4003__narrow_to_utf8<32>::~__narrow_to_utf8()
4004{
4005}
4006
4007// __widen_from_utf8<16>
4008
4009__widen_from_utf8<16>::~__widen_from_utf8()
4010{
4011}
4012
4013// __widen_from_utf8<32>
4014
4015__widen_from_utf8<32>::~__widen_from_utf8()
4016{
4017}
4018
4019// numpunct<char> && numpunct<wchar_t>
4020
4021locale::id numpunct< char >::id;
4022locale::id numpunct<wchar_t>::id;
4023
4024numpunct<char>::numpunct(size_t refs)
4025 : locale::facet(refs),
4026 __decimal_point_('.'),
4027 __thousands_sep_(',')
4028{
4029}
4030
4031numpunct<wchar_t>::numpunct(size_t refs)
4032 : locale::facet(refs),
4033 __decimal_point_(L'.'),
4034 __thousands_sep_(L',')
4035{
4036}
4037
4038numpunct<char>::~numpunct()
4039{
4040}
4041
4042numpunct<wchar_t>::~numpunct()
4043{
4044}
4045
4046 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4047wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4048
4049 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4050wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4051
4052string numpunct< char >::do_grouping() const {return __grouping_;}
4053string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4054
4055 string numpunct< char >::do_truename() const {return "true";}
4056wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4057
4058 string numpunct< char >::do_falsename() const {return "false";}
4059wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4060
4061// numpunct_byname<char>
4062
4063numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4064 : numpunct<char>(refs)
4065{
4066 __init(nm);
4067}
4068
4069numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4070 : numpunct<char>(refs)
4071{
4072 __init(nm.c_str());
4073}
4074
4075numpunct_byname<char>::~numpunct_byname()
4076{
4077}
4078
4079void
4080numpunct_byname<char>::__init(const char* nm)
4081{
4082 if (strcmp(nm, "C") != 0)
4083 {
Sean Huntf3907e62011-07-15 05:40:33 +00004084 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004085#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004086 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004087 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4088 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004089#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004090#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004091 lconv* lc = localeconv_l(loc.get());
4092#else
4093 lconv* lc = __localeconv_l(loc.get());
4094#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004095 if (*lc->decimal_point)
4096 __decimal_point_ = *lc->decimal_point;
4097 if (*lc->thousands_sep)
4098 __thousands_sep_ = *lc->thousands_sep;
4099 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004100 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004101 }
4102}
4103
4104// numpunct_byname<wchar_t>
4105
4106numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4107 : numpunct<wchar_t>(refs)
4108{
4109 __init(nm);
4110}
4111
4112numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4113 : numpunct<wchar_t>(refs)
4114{
4115 __init(nm.c_str());
4116}
4117
4118numpunct_byname<wchar_t>::~numpunct_byname()
4119{
4120}
4121
4122void
4123numpunct_byname<wchar_t>::__init(const char* nm)
4124{
4125 if (strcmp(nm, "C") != 0)
4126 {
Sean Huntf3907e62011-07-15 05:40:33 +00004127 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004128#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004129 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004130 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4131 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004132#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004133#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004134 lconv* lc = localeconv_l(loc.get());
4135#else
4136 lconv* lc = __localeconv_l(loc.get());
4137#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004138 if (*lc->decimal_point)
4139 __decimal_point_ = *lc->decimal_point;
4140 if (*lc->thousands_sep)
4141 __thousands_sep_ = *lc->thousands_sep;
4142 __grouping_ = lc->grouping;
4143 // locallization for truename and falsename is not available
4144 }
4145}
4146
4147// num_get helpers
4148
4149int
4150__num_get_base::__get_base(ios_base& iob)
4151{
4152 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4153 if (__basefield == ios_base::oct)
4154 return 8;
4155 else if (__basefield == ios_base::hex)
4156 return 16;
4157 else if (__basefield == 0)
4158 return 0;
4159 return 10;
4160}
4161
4162const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4163
4164void
4165__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4166 ios_base::iostate& __err)
4167{
4168 if (__grouping.size() != 0)
4169 {
4170 reverse(__g, __g_end);
4171 const char* __ig = __grouping.data();
4172 const char* __eg = __ig + __grouping.size();
4173 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4174 {
4175 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4176 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004177 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004178 {
4179 __err = ios_base::failbit;
4180 return;
4181 }
4182 }
4183 if (__eg - __ig > 1)
4184 ++__ig;
4185 }
4186 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4187 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004188 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004189 __err = ios_base::failbit;
4190 }
4191 }
4192}
4193
4194void
4195__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4196 ios_base::fmtflags __flags)
4197{
4198 if (__flags & ios_base::showpos)
4199 *__fmtp++ = '+';
4200 if (__flags & ios_base::showbase)
4201 *__fmtp++ = '#';
4202 while(*__len)
4203 *__fmtp++ = *__len++;
4204 if ((__flags & ios_base::basefield) == ios_base::oct)
4205 *__fmtp = 'o';
4206 else if ((__flags & ios_base::basefield) == ios_base::hex)
4207 {
4208 if (__flags & ios_base::uppercase)
4209 *__fmtp = 'X';
4210 else
4211 *__fmtp = 'x';
4212 }
4213 else if (__signd)
4214 *__fmtp = 'd';
4215 else
4216 *__fmtp = 'u';
4217}
4218
4219bool
4220__num_put_base::__format_float(char* __fmtp, const char* __len,
4221 ios_base::fmtflags __flags)
4222{
4223 bool specify_precision = true;
4224 if (__flags & ios_base::showpos)
4225 *__fmtp++ = '+';
4226 if (__flags & ios_base::showpoint)
4227 *__fmtp++ = '#';
4228 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4229 bool uppercase = __flags & ios_base::uppercase;
4230 if (floatfield == (ios_base::fixed | ios_base::scientific))
4231 specify_precision = false;
4232 else
4233 {
4234 *__fmtp++ = '.';
4235 *__fmtp++ = '*';
4236 }
4237 while(*__len)
4238 *__fmtp++ = *__len++;
4239 if (floatfield == ios_base::fixed)
4240 {
4241 if (uppercase)
4242 *__fmtp = 'F';
4243 else
4244 *__fmtp = 'f';
4245 }
4246 else if (floatfield == ios_base::scientific)
4247 {
4248 if (uppercase)
4249 *__fmtp = 'E';
4250 else
4251 *__fmtp = 'e';
4252 }
4253 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4254 {
4255 if (uppercase)
4256 *__fmtp = 'A';
4257 else
4258 *__fmtp = 'a';
4259 }
4260 else
4261 {
4262 if (uppercase)
4263 *__fmtp = 'G';
4264 else
4265 *__fmtp = 'g';
4266 }
4267 return specify_precision;
4268}
4269
4270char*
4271__num_put_base::__identify_padding(char* __nb, char* __ne,
4272 const ios_base& __iob)
4273{
4274 switch (__iob.flags() & ios_base::adjustfield)
4275 {
4276 case ios_base::internal:
4277 if (__nb[0] == '-' || __nb[0] == '+')
4278 return __nb+1;
4279 if (__ne - __nb >= 2 && __nb[0] == '0'
4280 && (__nb[1] == 'x' || __nb[1] == 'X'))
4281 return __nb+2;
4282 break;
4283 case ios_base::left:
4284 return __ne;
4285 case ios_base::right:
4286 default:
4287 break;
4288 }
4289 return __nb;
4290}
4291
4292// time_get
4293
4294static
4295string*
4296init_weeks()
4297{
4298 static string weeks[14];
4299 weeks[0] = "Sunday";
4300 weeks[1] = "Monday";
4301 weeks[2] = "Tuesday";
4302 weeks[3] = "Wednesday";
4303 weeks[4] = "Thursday";
4304 weeks[5] = "Friday";
4305 weeks[6] = "Saturday";
4306 weeks[7] = "Sun";
4307 weeks[8] = "Mon";
4308 weeks[9] = "Tue";
4309 weeks[10] = "Wed";
4310 weeks[11] = "Thu";
4311 weeks[12] = "Fri";
4312 weeks[13] = "Sat";
4313 return weeks;
4314}
4315
4316static
4317wstring*
4318init_wweeks()
4319{
4320 static wstring weeks[14];
4321 weeks[0] = L"Sunday";
4322 weeks[1] = L"Monday";
4323 weeks[2] = L"Tuesday";
4324 weeks[3] = L"Wednesday";
4325 weeks[4] = L"Thursday";
4326 weeks[5] = L"Friday";
4327 weeks[6] = L"Saturday";
4328 weeks[7] = L"Sun";
4329 weeks[8] = L"Mon";
4330 weeks[9] = L"Tue";
4331 weeks[10] = L"Wed";
4332 weeks[11] = L"Thu";
4333 weeks[12] = L"Fri";
4334 weeks[13] = L"Sat";
4335 return weeks;
4336}
4337
4338template <>
4339const string*
4340__time_get_c_storage<char>::__weeks() const
4341{
4342 static const string* weeks = init_weeks();
4343 return weeks;
4344}
4345
4346template <>
4347const wstring*
4348__time_get_c_storage<wchar_t>::__weeks() const
4349{
4350 static const wstring* weeks = init_wweeks();
4351 return weeks;
4352}
4353
4354static
4355string*
4356init_months()
4357{
4358 static string months[24];
4359 months[0] = "January";
4360 months[1] = "February";
4361 months[2] = "March";
4362 months[3] = "April";
4363 months[4] = "May";
4364 months[5] = "June";
4365 months[6] = "July";
4366 months[7] = "August";
4367 months[8] = "September";
4368 months[9] = "October";
4369 months[10] = "November";
4370 months[11] = "December";
4371 months[12] = "Jan";
4372 months[13] = "Feb";
4373 months[14] = "Mar";
4374 months[15] = "Apr";
4375 months[16] = "May";
4376 months[17] = "Jun";
4377 months[18] = "Jul";
4378 months[19] = "Aug";
4379 months[20] = "Sep";
4380 months[21] = "Oct";
4381 months[22] = "Nov";
4382 months[23] = "Dec";
4383 return months;
4384}
4385
4386static
4387wstring*
4388init_wmonths()
4389{
4390 static wstring months[24];
4391 months[0] = L"January";
4392 months[1] = L"February";
4393 months[2] = L"March";
4394 months[3] = L"April";
4395 months[4] = L"May";
4396 months[5] = L"June";
4397 months[6] = L"July";
4398 months[7] = L"August";
4399 months[8] = L"September";
4400 months[9] = L"October";
4401 months[10] = L"November";
4402 months[11] = L"December";
4403 months[12] = L"Jan";
4404 months[13] = L"Feb";
4405 months[14] = L"Mar";
4406 months[15] = L"Apr";
4407 months[16] = L"May";
4408 months[17] = L"Jun";
4409 months[18] = L"Jul";
4410 months[19] = L"Aug";
4411 months[20] = L"Sep";
4412 months[21] = L"Oct";
4413 months[22] = L"Nov";
4414 months[23] = L"Dec";
4415 return months;
4416}
4417
4418template <>
4419const string*
4420__time_get_c_storage<char>::__months() const
4421{
4422 static const string* months = init_months();
4423 return months;
4424}
4425
4426template <>
4427const wstring*
4428__time_get_c_storage<wchar_t>::__months() const
4429{
4430 static const wstring* months = init_wmonths();
4431 return months;
4432}
4433
4434static
4435string*
4436init_am_pm()
4437{
4438 static string am_pm[24];
4439 am_pm[0] = "AM";
4440 am_pm[1] = "PM";
4441 return am_pm;
4442}
4443
4444static
4445wstring*
4446init_wam_pm()
4447{
4448 static wstring am_pm[24];
4449 am_pm[0] = L"AM";
4450 am_pm[1] = L"PM";
4451 return am_pm;
4452}
4453
4454template <>
4455const string*
4456__time_get_c_storage<char>::__am_pm() const
4457{
4458 static const string* am_pm = init_am_pm();
4459 return am_pm;
4460}
4461
4462template <>
4463const wstring*
4464__time_get_c_storage<wchar_t>::__am_pm() const
4465{
4466 static const wstring* am_pm = init_wam_pm();
4467 return am_pm;
4468}
4469
4470template <>
4471const string&
4472__time_get_c_storage<char>::__x() const
4473{
4474 static string s("%m/%d/%y");
4475 return s;
4476}
4477
4478template <>
4479const wstring&
4480__time_get_c_storage<wchar_t>::__x() const
4481{
4482 static wstring s(L"%m/%d/%y");
4483 return s;
4484}
4485
4486template <>
4487const string&
4488__time_get_c_storage<char>::__X() const
4489{
4490 static string s("%H:%M:%S");
4491 return s;
4492}
4493
4494template <>
4495const wstring&
4496__time_get_c_storage<wchar_t>::__X() const
4497{
4498 static wstring s(L"%H:%M:%S");
4499 return s;
4500}
4501
4502template <>
4503const string&
4504__time_get_c_storage<char>::__c() const
4505{
4506 static string s("%a %b %d %H:%M:%S %Y");
4507 return s;
4508}
4509
4510template <>
4511const wstring&
4512__time_get_c_storage<wchar_t>::__c() const
4513{
4514 static wstring s(L"%a %b %d %H:%M:%S %Y");
4515 return s;
4516}
4517
4518template <>
4519const string&
4520__time_get_c_storage<char>::__r() const
4521{
4522 static string s("%I:%M:%S %p");
4523 return s;
4524}
4525
4526template <>
4527const wstring&
4528__time_get_c_storage<wchar_t>::__r() const
4529{
4530 static wstring s(L"%I:%M:%S %p");
4531 return s;
4532}
4533
4534// time_get_byname
4535
4536__time_get::__time_get(const char* nm)
4537 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4538{
Howard Hinnantd4444702010-08-11 17:04:31 +00004539#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004540 if (__loc_ == 0)
4541 throw runtime_error("time_get_byname"
4542 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004543#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004544}
4545
4546__time_get::__time_get(const string& nm)
4547 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4548{
Howard Hinnantd4444702010-08-11 17:04:31 +00004549#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004550 if (__loc_ == 0)
4551 throw runtime_error("time_get_byname"
4552 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004553#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004554}
4555
4556__time_get::~__time_get()
4557{
4558 freelocale(__loc_);
4559}
4560
Howard Hinnant335b1512012-02-20 16:51:43 +00004561#pragma clang diagnostic ignored "-Wmissing-field-initializers"
4562
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004563template <>
4564string
4565__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4566{
Howard Hinnant3074a052012-02-19 14:55:32 +00004567 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004568 t.tm_sec = 59;
4569 t.tm_min = 55;
4570 t.tm_hour = 23;
4571 t.tm_mday = 31;
4572 t.tm_mon = 11;
4573 t.tm_year = 161;
4574 t.tm_wday = 6;
4575 t.tm_yday = 364;
4576 t.tm_isdst = -1;
4577 char buf[100];
4578 char f[3] = {0};
4579 f[0] = '%';
4580 f[1] = fmt;
4581 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4582 char* bb = buf;
4583 char* be = buf + n;
4584 string result;
4585 while (bb != be)
4586 {
4587 if (ct.is(ctype_base::space, *bb))
4588 {
4589 result.push_back(' ');
4590 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4591 ;
4592 continue;
4593 }
4594 char* w = bb;
4595 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004596 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004597 ct, err, false)
4598 - this->__weeks_;
4599 if (i < 14)
4600 {
4601 result.push_back('%');
4602 if (i < 7)
4603 result.push_back('A');
4604 else
4605 result.push_back('a');
4606 bb = w;
4607 continue;
4608 }
4609 w = bb;
4610 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4611 ct, err, false)
4612 - this->__months_;
4613 if (i < 24)
4614 {
4615 result.push_back('%');
4616 if (i < 12)
4617 result.push_back('B');
4618 else
4619 result.push_back('b');
4620 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4621 result.back() = 'm';
4622 bb = w;
4623 continue;
4624 }
4625 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4626 {
4627 w = bb;
4628 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4629 ct, err, false) - this->__am_pm_;
4630 if (i < 2)
4631 {
4632 result.push_back('%');
4633 result.push_back('p');
4634 bb = w;
4635 continue;
4636 }
4637 }
4638 w = bb;
4639 if (ct.is(ctype_base::digit, *bb))
4640 {
4641 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4642 {
4643 case 6:
4644 result.push_back('%');
4645 result.push_back('w');
4646 break;
4647 case 7:
4648 result.push_back('%');
4649 result.push_back('u');
4650 break;
4651 case 11:
4652 result.push_back('%');
4653 result.push_back('I');
4654 break;
4655 case 12:
4656 result.push_back('%');
4657 result.push_back('m');
4658 break;
4659 case 23:
4660 result.push_back('%');
4661 result.push_back('H');
4662 break;
4663 case 31:
4664 result.push_back('%');
4665 result.push_back('d');
4666 break;
4667 case 55:
4668 result.push_back('%');
4669 result.push_back('M');
4670 break;
4671 case 59:
4672 result.push_back('%');
4673 result.push_back('S');
4674 break;
4675 case 61:
4676 result.push_back('%');
4677 result.push_back('y');
4678 break;
4679 case 364:
4680 result.push_back('%');
4681 result.push_back('j');
4682 break;
4683 case 2061:
4684 result.push_back('%');
4685 result.push_back('Y');
4686 break;
4687 default:
4688 for (; w != bb; ++w)
4689 result.push_back(*w);
4690 break;
4691 }
4692 continue;
4693 }
4694 if (*bb == '%')
4695 {
4696 result.push_back('%');
4697 result.push_back('%');
4698 ++bb;
4699 continue;
4700 }
4701 result.push_back(*bb);
4702 ++bb;
4703 }
4704 return result;
4705}
4706
Howard Hinnantec3773c2011-12-01 20:21:04 +00004707#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004708
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004709template <>
4710wstring
4711__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4712{
Howard Hinnant3074a052012-02-19 14:55:32 +00004713 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004714 t.tm_sec = 59;
4715 t.tm_min = 55;
4716 t.tm_hour = 23;
4717 t.tm_mday = 31;
4718 t.tm_mon = 11;
4719 t.tm_year = 161;
4720 t.tm_wday = 6;
4721 t.tm_yday = 364;
4722 t.tm_isdst = -1;
4723 char buf[100];
4724 char f[3] = {0};
4725 f[0] = '%';
4726 f[1] = fmt;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004727 strftime_l(buf, 100, f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004728 wchar_t wbuf[100];
4729 wchar_t* wbb = wbuf;
4730 mbstate_t mb = {0};
4731 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004732#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00004733 size_t j = mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004734#else
Howard Hinnantec3773c2011-12-01 20:21:04 +00004735 size_t j = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004736#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004737 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004738 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004739 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004740 wstring result;
4741 while (wbb != wbe)
4742 {
4743 if (ct.is(ctype_base::space, *wbb))
4744 {
4745 result.push_back(L' ');
4746 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4747 ;
4748 continue;
4749 }
4750 wchar_t* w = wbb;
4751 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004752 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004753 ct, err, false)
4754 - this->__weeks_;
4755 if (i < 14)
4756 {
4757 result.push_back(L'%');
4758 if (i < 7)
4759 result.push_back(L'A');
4760 else
4761 result.push_back(L'a');
4762 wbb = w;
4763 continue;
4764 }
4765 w = wbb;
4766 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4767 ct, err, false)
4768 - this->__months_;
4769 if (i < 24)
4770 {
4771 result.push_back(L'%');
4772 if (i < 12)
4773 result.push_back(L'B');
4774 else
4775 result.push_back(L'b');
4776 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4777 result.back() = L'm';
4778 wbb = w;
4779 continue;
4780 }
4781 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4782 {
4783 w = wbb;
4784 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4785 ct, err, false) - this->__am_pm_;
4786 if (i < 2)
4787 {
4788 result.push_back(L'%');
4789 result.push_back(L'p');
4790 wbb = w;
4791 continue;
4792 }
4793 }
4794 w = wbb;
4795 if (ct.is(ctype_base::digit, *wbb))
4796 {
4797 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4798 {
4799 case 6:
4800 result.push_back(L'%');
4801 result.push_back(L'w');
4802 break;
4803 case 7:
4804 result.push_back(L'%');
4805 result.push_back(L'u');
4806 break;
4807 case 11:
4808 result.push_back(L'%');
4809 result.push_back(L'I');
4810 break;
4811 case 12:
4812 result.push_back(L'%');
4813 result.push_back(L'm');
4814 break;
4815 case 23:
4816 result.push_back(L'%');
4817 result.push_back(L'H');
4818 break;
4819 case 31:
4820 result.push_back(L'%');
4821 result.push_back(L'd');
4822 break;
4823 case 55:
4824 result.push_back(L'%');
4825 result.push_back(L'M');
4826 break;
4827 case 59:
4828 result.push_back(L'%');
4829 result.push_back(L'S');
4830 break;
4831 case 61:
4832 result.push_back(L'%');
4833 result.push_back(L'y');
4834 break;
4835 case 364:
4836 result.push_back(L'%');
4837 result.push_back(L'j');
4838 break;
4839 case 2061:
4840 result.push_back(L'%');
4841 result.push_back(L'Y');
4842 break;
4843 default:
4844 for (; w != wbb; ++w)
4845 result.push_back(*w);
4846 break;
4847 }
4848 continue;
4849 }
4850 if (ct.narrow(*wbb, 0) == '%')
4851 {
4852 result.push_back(L'%');
4853 result.push_back(L'%');
4854 ++wbb;
4855 continue;
4856 }
4857 result.push_back(*wbb);
4858 ++wbb;
4859 }
4860 return result;
4861}
4862
4863template <>
4864void
4865__time_get_storage<char>::init(const ctype<char>& ct)
4866{
Howard Hinnantcd992362012-08-02 18:44:17 +00004867 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004868 char buf[100];
4869 // __weeks_
4870 for (int i = 0; i < 7; ++i)
4871 {
4872 t.tm_wday = i;
4873 strftime_l(buf, 100, "%A", &t, __loc_);
4874 __weeks_[i] = buf;
4875 strftime_l(buf, 100, "%a", &t, __loc_);
4876 __weeks_[i+7] = buf;
4877 }
4878 // __months_
4879 for (int i = 0; i < 12; ++i)
4880 {
4881 t.tm_mon = i;
4882 strftime_l(buf, 100, "%B", &t, __loc_);
4883 __months_[i] = buf;
4884 strftime_l(buf, 100, "%b", &t, __loc_);
4885 __months_[i+12] = buf;
4886 }
4887 // __am_pm_
4888 t.tm_hour = 1;
4889 strftime_l(buf, 100, "%p", &t, __loc_);
4890 __am_pm_[0] = buf;
4891 t.tm_hour = 13;
4892 strftime_l(buf, 100, "%p", &t, __loc_);
4893 __am_pm_[1] = buf;
4894 __c_ = __analyze('c', ct);
4895 __r_ = __analyze('r', ct);
4896 __x_ = __analyze('x', ct);
4897 __X_ = __analyze('X', ct);
4898}
4899
4900template <>
4901void
4902__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4903{
4904 tm t = {0};
4905 char buf[100];
4906 size_t be;
4907 wchar_t wbuf[100];
4908 wchar_t* wbe;
4909 mbstate_t mb = {0};
4910 // __weeks_
4911 for (int i = 0; i < 7; ++i)
4912 {
4913 t.tm_wday = i;
4914 be = strftime_l(buf, 100, "%A", &t, __loc_);
4915 mb = mbstate_t();
4916 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004917#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004918 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4919#else
4920 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4921#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004922 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004923 __throw_runtime_error("locale not supported");
4924 wbe = wbuf + j;
4925 __weeks_[i].assign(wbuf, wbe);
4926 be = strftime_l(buf, 100, "%a", &t, __loc_);
4927 mb = mbstate_t();
4928 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004929#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004930 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4931#else
4932 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4933#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004934 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004935 __throw_runtime_error("locale not supported");
4936 wbe = wbuf + j;
4937 __weeks_[i+7].assign(wbuf, wbe);
4938 }
4939 // __months_
4940 for (int i = 0; i < 12; ++i)
4941 {
4942 t.tm_mon = i;
4943 be = strftime_l(buf, 100, "%B", &t, __loc_);
4944 mb = mbstate_t();
4945 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004946#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004947 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4948#else
4949 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4950#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004951 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004952 __throw_runtime_error("locale not supported");
4953 wbe = wbuf + j;
4954 __months_[i].assign(wbuf, wbe);
4955 be = strftime_l(buf, 100, "%b", &t, __loc_);
4956 mb = mbstate_t();
4957 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004958#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004959 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4960#else
4961 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4962#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004963 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004964 __throw_runtime_error("locale not supported");
4965 wbe = wbuf + j;
4966 __months_[i+12].assign(wbuf, wbe);
4967 }
4968 // __am_pm_
4969 t.tm_hour = 1;
4970 be = strftime_l(buf, 100, "%p", &t, __loc_);
4971 mb = mbstate_t();
4972 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004973#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004974 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4975#else
4976 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4977#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004978 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004979 __throw_runtime_error("locale not supported");
4980 wbe = wbuf + j;
4981 __am_pm_[0].assign(wbuf, wbe);
4982 t.tm_hour = 13;
4983 be = strftime_l(buf, 100, "%p", &t, __loc_);
4984 mb = mbstate_t();
4985 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004986#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004987 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4988#else
4989 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4990#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004991 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004992 __throw_runtime_error("locale not supported");
4993 wbe = wbuf + j;
4994 __am_pm_[1].assign(wbuf, wbe);
4995 __c_ = __analyze('c', ct);
4996 __r_ = __analyze('r', ct);
4997 __x_ = __analyze('x', ct);
4998 __X_ = __analyze('X', ct);
4999}
5000
5001template <class CharT>
5002struct _LIBCPP_HIDDEN __time_get_temp
5003 : public ctype_byname<CharT>
5004{
5005 explicit __time_get_temp(const char* nm)
5006 : ctype_byname<CharT>(nm, 1) {}
5007 explicit __time_get_temp(const string& nm)
5008 : ctype_byname<CharT>(nm, 1) {}
5009};
5010
5011template <>
5012__time_get_storage<char>::__time_get_storage(const char* __nm)
5013 : __time_get(__nm)
5014{
5015 const __time_get_temp<char> ct(__nm);
5016 init(ct);
5017}
5018
5019template <>
5020__time_get_storage<char>::__time_get_storage(const string& __nm)
5021 : __time_get(__nm)
5022{
5023 const __time_get_temp<char> ct(__nm);
5024 init(ct);
5025}
5026
5027template <>
5028__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5029 : __time_get(__nm)
5030{
5031 const __time_get_temp<wchar_t> ct(__nm);
5032 init(ct);
5033}
5034
5035template <>
5036__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5037 : __time_get(__nm)
5038{
5039 const __time_get_temp<wchar_t> ct(__nm);
5040 init(ct);
5041}
5042
5043template <>
5044time_base::dateorder
5045__time_get_storage<char>::__do_date_order() const
5046{
5047 unsigned i;
5048 for (i = 0; i < __x_.size(); ++i)
5049 if (__x_[i] == '%')
5050 break;
5051 ++i;
5052 switch (__x_[i])
5053 {
5054 case 'y':
5055 case 'Y':
5056 for (++i; i < __x_.size(); ++i)
5057 if (__x_[i] == '%')
5058 break;
5059 if (i == __x_.size())
5060 break;
5061 ++i;
5062 switch (__x_[i])
5063 {
5064 case 'm':
5065 for (++i; i < __x_.size(); ++i)
5066 if (__x_[i] == '%')
5067 break;
5068 if (i == __x_.size())
5069 break;
5070 ++i;
5071 if (__x_[i] == 'd')
5072 return time_base::ymd;
5073 break;
5074 case 'd':
5075 for (++i; i < __x_.size(); ++i)
5076 if (__x_[i] == '%')
5077 break;
5078 if (i == __x_.size())
5079 break;
5080 ++i;
5081 if (__x_[i] == 'm')
5082 return time_base::ydm;
5083 break;
5084 }
5085 break;
5086 case 'm':
5087 for (++i; i < __x_.size(); ++i)
5088 if (__x_[i] == '%')
5089 break;
5090 if (i == __x_.size())
5091 break;
5092 ++i;
5093 if (__x_[i] == 'd')
5094 {
5095 for (++i; i < __x_.size(); ++i)
5096 if (__x_[i] == '%')
5097 break;
5098 if (i == __x_.size())
5099 break;
5100 ++i;
5101 if (__x_[i] == 'y' || __x_[i] == 'Y')
5102 return time_base::mdy;
5103 break;
5104 }
5105 break;
5106 case 'd':
5107 for (++i; i < __x_.size(); ++i)
5108 if (__x_[i] == '%')
5109 break;
5110 if (i == __x_.size())
5111 break;
5112 ++i;
5113 if (__x_[i] == 'm')
5114 {
5115 for (++i; i < __x_.size(); ++i)
5116 if (__x_[i] == '%')
5117 break;
5118 if (i == __x_.size())
5119 break;
5120 ++i;
5121 if (__x_[i] == 'y' || __x_[i] == 'Y')
5122 return time_base::dmy;
5123 break;
5124 }
5125 break;
5126 }
5127 return time_base::no_order;
5128}
5129
5130template <>
5131time_base::dateorder
5132__time_get_storage<wchar_t>::__do_date_order() const
5133{
5134 unsigned i;
5135 for (i = 0; i < __x_.size(); ++i)
5136 if (__x_[i] == L'%')
5137 break;
5138 ++i;
5139 switch (__x_[i])
5140 {
5141 case L'y':
5142 case L'Y':
5143 for (++i; i < __x_.size(); ++i)
5144 if (__x_[i] == L'%')
5145 break;
5146 if (i == __x_.size())
5147 break;
5148 ++i;
5149 switch (__x_[i])
5150 {
5151 case L'm':
5152 for (++i; i < __x_.size(); ++i)
5153 if (__x_[i] == L'%')
5154 break;
5155 if (i == __x_.size())
5156 break;
5157 ++i;
5158 if (__x_[i] == L'd')
5159 return time_base::ymd;
5160 break;
5161 case L'd':
5162 for (++i; i < __x_.size(); ++i)
5163 if (__x_[i] == L'%')
5164 break;
5165 if (i == __x_.size())
5166 break;
5167 ++i;
5168 if (__x_[i] == L'm')
5169 return time_base::ydm;
5170 break;
5171 }
5172 break;
5173 case L'm':
5174 for (++i; i < __x_.size(); ++i)
5175 if (__x_[i] == L'%')
5176 break;
5177 if (i == __x_.size())
5178 break;
5179 ++i;
5180 if (__x_[i] == L'd')
5181 {
5182 for (++i; i < __x_.size(); ++i)
5183 if (__x_[i] == L'%')
5184 break;
5185 if (i == __x_.size())
5186 break;
5187 ++i;
5188 if (__x_[i] == L'y' || __x_[i] == L'Y')
5189 return time_base::mdy;
5190 break;
5191 }
5192 break;
5193 case L'd':
5194 for (++i; i < __x_.size(); ++i)
5195 if (__x_[i] == L'%')
5196 break;
5197 if (i == __x_.size())
5198 break;
5199 ++i;
5200 if (__x_[i] == L'm')
5201 {
5202 for (++i; i < __x_.size(); ++i)
5203 if (__x_[i] == L'%')
5204 break;
5205 if (i == __x_.size())
5206 break;
5207 ++i;
5208 if (__x_[i] == L'y' || __x_[i] == L'Y')
5209 return time_base::dmy;
5210 break;
5211 }
5212 break;
5213 }
5214 return time_base::no_order;
5215}
5216
5217// time_put
5218
5219__time_put::__time_put(const char* nm)
5220 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5221{
Howard Hinnantd4444702010-08-11 17:04:31 +00005222#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005223 if (__loc_ == 0)
5224 throw runtime_error("time_put_byname"
5225 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005226#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005227}
5228
5229__time_put::__time_put(const string& nm)
5230 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5231{
Howard Hinnantd4444702010-08-11 17:04:31 +00005232#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005233 if (__loc_ == 0)
5234 throw runtime_error("time_put_byname"
5235 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005236#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005237}
5238
5239__time_put::~__time_put()
5240{
5241 if (__loc_)
5242 freelocale(__loc_);
5243}
5244
5245void
5246__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5247 char __fmt, char __mod) const
5248{
5249 char fmt[] = {'%', __fmt, __mod, 0};
5250 if (__mod != 0)
5251 swap(fmt[1], fmt[2]);
Howard Hinnantec3773c2011-12-01 20:21:04 +00005252 size_t n = strftime_l(__nb, static_cast<size_t>(__ne-__nb), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005253 __ne = __nb + n;
5254}
5255
5256void
5257__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5258 char __fmt, char __mod) const
5259{
5260 char __nar[100];
5261 char* __ne = __nar + 100;
5262 __do_put(__nar, __ne, __tm, __fmt, __mod);
5263 mbstate_t mb = {0};
5264 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005265#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005266 size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5267#else
5268 size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5269#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005270 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005271 __throw_runtime_error("locale not supported");
5272 __we = __wb + j;
5273}
5274
5275// moneypunct_byname
5276
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005277template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005278static
5279void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005280__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5281 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5282 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005283{
5284 const char sign = static_cast<char>(money_base::sign);
5285 const char space = static_cast<char>(money_base::space);
5286 const char none = static_cast<char>(money_base::none);
5287 const char symbol = static_cast<char>(money_base::symbol);
5288 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005289 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5290
5291 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5292 // function'. "Space between sign and symbol or value" means that
5293 // if the sign is adjacent to the symbol, there's a space between
5294 // them, and otherwise there's a space between the sign and value.
5295 //
5296 // C11's localeconv specifies that the fourth character of an
5297 // international curr_symbol is used to separate the sign and
5298 // value when sep_by_space says to do so. C++ can't represent
5299 // that, so we just use a space. When sep_by_space says to
5300 // separate the symbol and value-or-sign with a space, we rearrange the
5301 // curr_symbol to put its spacing character on the correct side of
5302 // the symbol.
5303 //
5304 // We also need to avoid adding an extra space between the sign
5305 // and value when the currency symbol is suppressed (by not
5306 // setting showbase). We match glibc's strfmon by interpreting
5307 // sep_by_space==1 as "omit the space when the currency symbol is
5308 // absent".
5309 //
5310 // Users who want to get this right should use ICU instead.
5311
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005312 switch (cs_precedes)
5313 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005314 case 0: // value before curr_symbol
5315 if (symbol_contains_sep) {
5316 // Move the separator to before the symbol, to place it
5317 // between the value and symbol.
5318 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5319 __curr_symbol_.end());
5320 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005321 switch (sign_posn)
5322 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005323 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005324 pat.field[0] = sign;
5325 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005326 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005327 pat.field[3] = symbol;
5328 switch (sep_by_space)
5329 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005330 case 0: // No space separates the currency symbol and value.
5331 // This case may have changed between C99 and C11;
5332 // assume the currency symbol matches the intention.
5333 case 2: // Space between sign and currency or value.
5334 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005335 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005336 case 1: // Space between currency-and-sign or currency and value.
5337 if (!symbol_contains_sep) {
5338 // We insert the space into the symbol instead of
5339 // setting pat.field[2]=space so that when
5340 // showbase is not set, the space goes away too.
5341 __curr_symbol_.insert(0, 1, space_char);
5342 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005343 return;
5344 default:
5345 break;
5346 }
5347 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005348 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005349 pat.field[0] = sign;
5350 pat.field[3] = symbol;
5351 switch (sep_by_space)
5352 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005353 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005354 pat.field[1] = value;
5355 pat.field[2] = none;
5356 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005357 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005358 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005359 pat.field[2] = none;
5360 if (!symbol_contains_sep) {
5361 // We insert the space into the symbol instead of
5362 // setting pat.field[2]=space so that when
5363 // showbase is not set, the space goes away too.
5364 __curr_symbol_.insert(0, 1, space_char);
5365 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005366 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005367 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005368 pat.field[1] = space;
5369 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005370 if (symbol_contains_sep) {
5371 // Remove the separator from the symbol, since it
5372 // has already appeared after the sign.
5373 __curr_symbol_.erase(__curr_symbol_.begin());
5374 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005375 return;
5376 default:
5377 break;
5378 }
5379 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005380 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005381 pat.field[0] = value;
5382 pat.field[3] = sign;
5383 switch (sep_by_space)
5384 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005385 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005386 pat.field[1] = none;
5387 pat.field[2] = symbol;
5388 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005389 case 1: // Space between currency-and-sign or currency and value.
5390 if (!symbol_contains_sep) {
5391 // We insert the space into the symbol instead of
5392 // setting pat.field[1]=space so that when
5393 // showbase is not set, the space goes away too.
5394 __curr_symbol_.insert(0, 1, space_char);
5395 }
5396 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005397 pat.field[2] = symbol;
5398 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005399 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005400 pat.field[1] = symbol;
5401 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005402 if (symbol_contains_sep) {
5403 // Remove the separator from the symbol, since it
5404 // should not be removed if showbase is absent.
5405 __curr_symbol_.erase(__curr_symbol_.begin());
5406 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005407 return;
5408 default:
5409 break;
5410 }
5411 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005412 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005413 pat.field[0] = value;
5414 pat.field[3] = symbol;
5415 switch (sep_by_space)
5416 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005417 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005418 pat.field[1] = none;
5419 pat.field[2] = sign;
5420 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005421 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005422 pat.field[1] = space;
5423 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005424 if (symbol_contains_sep) {
5425 // Remove the separator from the symbol, since it
5426 // has already appeared before the sign.
5427 __curr_symbol_.erase(__curr_symbol_.begin());
5428 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005429 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005430 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005431 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005432 pat.field[2] = none;
5433 if (!symbol_contains_sep) {
5434 // We insert the space into the symbol instead of
5435 // setting pat.field[2]=space so that when
5436 // showbase is not set, the space goes away too.
5437 __curr_symbol_.insert(0, 1, space_char);
5438 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005439 return;
5440 default:
5441 break;
5442 }
5443 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005444 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005445 pat.field[0] = value;
5446 pat.field[3] = sign;
5447 switch (sep_by_space)
5448 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005449 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005450 pat.field[1] = none;
5451 pat.field[2] = symbol;
5452 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005453 case 1: // Space between currency-and-sign or currency and value.
5454 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005455 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005456 if (!symbol_contains_sep) {
5457 // We insert the space into the symbol instead of
5458 // setting pat.field[1]=space so that when
5459 // showbase is not set, the space goes away too.
5460 __curr_symbol_.insert(0, 1, space_char);
5461 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005462 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005463 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005464 pat.field[1] = symbol;
5465 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005466 if (symbol_contains_sep) {
5467 // Remove the separator from the symbol, since it
5468 // should not disappear when showbase is absent.
5469 __curr_symbol_.erase(__curr_symbol_.begin());
5470 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005471 return;
5472 default:
5473 break;
5474 }
5475 break;
5476 default:
5477 break;
5478 }
5479 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005480 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005481 switch (sign_posn)
5482 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005483 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005484 pat.field[0] = sign;
5485 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005486 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005487 pat.field[3] = value;
5488 switch (sep_by_space)
5489 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005490 case 0: // No space separates the currency symbol and value.
5491 // This case may have changed between C99 and C11;
5492 // assume the currency symbol matches the intention.
5493 case 2: // Space between sign and currency or value.
5494 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005495 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005496 case 1: // Space between currency-and-sign or currency and value.
5497 if (!symbol_contains_sep) {
5498 // We insert the space into the symbol instead of
5499 // setting pat.field[2]=space so that when
5500 // showbase is not set, the space goes away too.
5501 __curr_symbol_.insert(0, 1, space_char);
5502 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005503 return;
5504 default:
5505 break;
5506 }
5507 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005508 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005509 pat.field[0] = sign;
5510 pat.field[3] = value;
5511 switch (sep_by_space)
5512 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005513 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005514 pat.field[1] = symbol;
5515 pat.field[2] = none;
5516 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005517 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005518 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005519 pat.field[2] = none;
5520 if (!symbol_contains_sep) {
5521 // We insert the space into the symbol instead of
5522 // setting pat.field[2]=space so that when
5523 // showbase is not set, the space goes away too.
5524 __curr_symbol_.push_back(space_char);
5525 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005526 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005527 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005528 pat.field[1] = space;
5529 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005530 if (symbol_contains_sep) {
5531 // Remove the separator from the symbol, since it
5532 // has already appeared after the sign.
5533 __curr_symbol_.pop_back();
5534 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005535 return;
5536 default:
5537 break;
5538 }
5539 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005540 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005541 pat.field[0] = symbol;
5542 pat.field[3] = sign;
5543 switch (sep_by_space)
5544 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005545 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005546 pat.field[1] = none;
5547 pat.field[2] = value;
5548 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005549 case 1: // Space between currency-and-sign or currency and value.
5550 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005551 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005552 if (!symbol_contains_sep) {
5553 // We insert the space into the symbol instead of
5554 // setting pat.field[1]=space so that when
5555 // showbase is not set, the space goes away too.
5556 __curr_symbol_.push_back(space_char);
5557 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005558 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005559 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005560 pat.field[1] = value;
5561 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005562 if (symbol_contains_sep) {
5563 // Remove the separator from the symbol, since it
5564 // will appear before the sign.
5565 __curr_symbol_.pop_back();
5566 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005567 return;
5568 default:
5569 break;
5570 }
5571 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005572 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005573 pat.field[0] = sign;
5574 pat.field[3] = value;
5575 switch (sep_by_space)
5576 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005577 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005578 pat.field[1] = symbol;
5579 pat.field[2] = none;
5580 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005581 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005582 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005583 pat.field[2] = none;
5584 if (!symbol_contains_sep) {
5585 // We insert the space into the symbol instead of
5586 // setting pat.field[2]=space so that when
5587 // showbase is not set, the space goes away too.
5588 __curr_symbol_.push_back(space_char);
5589 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005590 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005591 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005592 pat.field[1] = space;
5593 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005594 if (symbol_contains_sep) {
5595 // Remove the separator from the symbol, since it
5596 // has already appeared after the sign.
5597 __curr_symbol_.pop_back();
5598 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005599 return;
5600 default:
5601 break;
5602 }
5603 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005604 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005605 pat.field[0] = symbol;
5606 pat.field[3] = value;
5607 switch (sep_by_space)
5608 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005609 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005610 pat.field[1] = sign;
5611 pat.field[2] = none;
5612 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005613 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005614 pat.field[1] = sign;
5615 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005616 if (symbol_contains_sep) {
5617 // Remove the separator from the symbol, since it
5618 // should not disappear when showbase is absent.
5619 __curr_symbol_.pop_back();
5620 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005621 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005622 case 2: // Space between sign and currency or value.
5623 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005624 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005625 if (!symbol_contains_sep) {
5626 // We insert the space into the symbol instead of
5627 // setting pat.field[1]=space so that when
5628 // showbase is not set, the space goes away too.
5629 __curr_symbol_.push_back(space_char);
5630 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005631 return;
5632 default:
5633 break;
5634 }
5635 break;
5636 default:
5637 break;
5638 }
5639 break;
5640 default:
5641 break;
5642 }
5643 pat.field[0] = symbol;
5644 pat.field[1] = sign;
5645 pat.field[2] = none;
5646 pat.field[3] = value;
5647}
5648
5649template<>
5650void
5651moneypunct_byname<char, false>::init(const char* nm)
5652{
5653 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005654 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005655#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005656 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005657 throw runtime_error("moneypunct_byname"
5658 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005659#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005660#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005661 lconv* lc = localeconv_l(loc.get());
5662#else
5663 lconv* lc = __localeconv_l(loc.get());
5664#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005665 if (*lc->mon_decimal_point)
5666 __decimal_point_ = *lc->mon_decimal_point;
5667 else
5668 __decimal_point_ = base::do_decimal_point();
5669 if (*lc->mon_thousands_sep)
5670 __thousands_sep_ = *lc->mon_thousands_sep;
5671 else
5672 __thousands_sep_ = base::do_thousands_sep();
5673 __grouping_ = lc->mon_grouping;
5674 __curr_symbol_ = lc->currency_symbol;
5675 if (lc->frac_digits != CHAR_MAX)
5676 __frac_digits_ = lc->frac_digits;
5677 else
5678 __frac_digits_ = base::do_frac_digits();
5679 if (lc->p_sign_posn == 0)
5680 __positive_sign_ = "()";
5681 else
5682 __positive_sign_ = lc->positive_sign;
5683 if (lc->n_sign_posn == 0)
5684 __negative_sign_ = "()";
5685 else
5686 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005687 // Assume the positive and negative formats will want spaces in
5688 // the same places in curr_symbol since there's no way to
5689 // represent anything else.
5690 string_type __dummy_curr_symbol = __curr_symbol_;
5691 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5692 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5693 __init_pat(__neg_format_, __curr_symbol_, false,
5694 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005695}
5696
5697template<>
5698void
5699moneypunct_byname<char, true>::init(const char* nm)
5700{
5701 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005702 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005703#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005704 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005705 throw runtime_error("moneypunct_byname"
5706 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005707#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005708#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005709 lconv* lc = localeconv_l(loc.get());
5710#else
5711 lconv* lc = __localeconv_l(loc.get());
5712#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005713 if (*lc->mon_decimal_point)
5714 __decimal_point_ = *lc->mon_decimal_point;
5715 else
5716 __decimal_point_ = base::do_decimal_point();
5717 if (*lc->mon_thousands_sep)
5718 __thousands_sep_ = *lc->mon_thousands_sep;
5719 else
5720 __thousands_sep_ = base::do_thousands_sep();
5721 __grouping_ = lc->mon_grouping;
5722 __curr_symbol_ = lc->int_curr_symbol;
5723 if (lc->int_frac_digits != CHAR_MAX)
5724 __frac_digits_ = lc->int_frac_digits;
5725 else
5726 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005727#if _WIN32
5728 if (lc->p_sign_posn == 0)
5729#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005730 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005731#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005732 __positive_sign_ = "()";
5733 else
5734 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005735#if _WIN32
5736 if(lc->n_sign_posn == 0)
5737#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005738 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005739#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005740 __negative_sign_ = "()";
5741 else
5742 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005743 // Assume the positive and negative formats will want spaces in
5744 // the same places in curr_symbol since there's no way to
5745 // represent anything else.
5746 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005747#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005748 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5749 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5750 __init_pat(__neg_format_, __curr_symbol_, true,
5751 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005752#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005753 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5754 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5755 lc->int_p_sign_posn, ' ');
5756 __init_pat(__neg_format_, __curr_symbol_, true,
5757 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5758 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005759#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005760}
5761
5762template<>
5763void
5764moneypunct_byname<wchar_t, false>::init(const char* nm)
5765{
5766 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005767 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005768#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005769 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005770 throw runtime_error("moneypunct_byname"
5771 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005772#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005773#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005774 lconv* lc = localeconv_l(loc.get());
5775#else
5776 lconv* lc = __localeconv_l(loc.get());
5777#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005778 if (*lc->mon_decimal_point)
5779 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5780 else
5781 __decimal_point_ = base::do_decimal_point();
5782 if (*lc->mon_thousands_sep)
5783 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5784 else
5785 __thousands_sep_ = base::do_thousands_sep();
5786 __grouping_ = lc->mon_grouping;
5787 wchar_t wbuf[100];
5788 mbstate_t mb = {0};
5789 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005790#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005791 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5792#else
5793 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5794#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005795 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005796 __throw_runtime_error("locale not supported");
5797 wchar_t* wbe = wbuf + j;
5798 __curr_symbol_.assign(wbuf, wbe);
5799 if (lc->frac_digits != CHAR_MAX)
5800 __frac_digits_ = lc->frac_digits;
5801 else
5802 __frac_digits_ = base::do_frac_digits();
5803 if (lc->p_sign_posn == 0)
5804 __positive_sign_ = L"()";
5805 else
5806 {
5807 mb = mbstate_t();
5808 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005809#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005810 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5811#else
5812 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5813#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005814 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005815 __throw_runtime_error("locale not supported");
5816 wbe = wbuf + j;
5817 __positive_sign_.assign(wbuf, wbe);
5818 }
5819 if (lc->n_sign_posn == 0)
5820 __negative_sign_ = L"()";
5821 else
5822 {
5823 mb = mbstate_t();
5824 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005825#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005826 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5827#else
5828 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5829#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005830 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005831 __throw_runtime_error("locale not supported");
5832 wbe = wbuf + j;
5833 __negative_sign_.assign(wbuf, wbe);
5834 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005835 // Assume the positive and negative formats will want spaces in
5836 // the same places in curr_symbol since there's no way to
5837 // represent anything else.
5838 string_type __dummy_curr_symbol = __curr_symbol_;
5839 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5840 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5841 __init_pat(__neg_format_, __curr_symbol_, false,
5842 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005843}
5844
5845template<>
5846void
5847moneypunct_byname<wchar_t, true>::init(const char* nm)
5848{
5849 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005850 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005851#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005852 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005853 throw runtime_error("moneypunct_byname"
5854 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005855#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005856#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005857 lconv* lc = localeconv_l(loc.get());
5858#else
5859 lconv* lc = __localeconv_l(loc.get());
5860#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005861 if (*lc->mon_decimal_point)
5862 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5863 else
5864 __decimal_point_ = base::do_decimal_point();
5865 if (*lc->mon_thousands_sep)
5866 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5867 else
5868 __thousands_sep_ = base::do_thousands_sep();
5869 __grouping_ = lc->mon_grouping;
5870 wchar_t wbuf[100];
5871 mbstate_t mb = {0};
5872 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005873#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005874 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5875#else
5876 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5877#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005878 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005879 __throw_runtime_error("locale not supported");
5880 wchar_t* wbe = wbuf + j;
5881 __curr_symbol_.assign(wbuf, wbe);
5882 if (lc->int_frac_digits != CHAR_MAX)
5883 __frac_digits_ = lc->int_frac_digits;
5884 else
5885 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005886#if _WIN32
5887 if (lc->p_sign_posn == 0)
5888#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005889 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005890#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005891 __positive_sign_ = L"()";
5892 else
5893 {
5894 mb = mbstate_t();
5895 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005896#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005897 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5898#else
5899 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5900#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005901 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005902 __throw_runtime_error("locale not supported");
5903 wbe = wbuf + j;
5904 __positive_sign_.assign(wbuf, wbe);
5905 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005906#if _WIN32
5907 if (lc->n_sign_posn == 0)
5908#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005909 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005910#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005911 __negative_sign_ = L"()";
5912 else
5913 {
5914 mb = mbstate_t();
5915 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005916#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005917 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5918#else
5919 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5920#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005921 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005922 __throw_runtime_error("locale not supported");
5923 wbe = wbuf + j;
5924 __negative_sign_.assign(wbuf, wbe);
5925 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005926 // Assume the positive and negative formats will want spaces in
5927 // the same places in curr_symbol since there's no way to
5928 // represent anything else.
5929 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005930#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005931 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5932 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5933 __init_pat(__neg_format_, __curr_symbol_, true,
5934 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005935#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005936 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5937 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5938 lc->int_p_sign_posn, L' ');
5939 __init_pat(__neg_format_, __curr_symbol_, true,
5940 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5941 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005942#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005943}
5944
5945void __do_nothing(void*) {}
5946
5947void __throw_runtime_error(const char* msg)
5948{
Howard Hinnantd4444702010-08-11 17:04:31 +00005949#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005950 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00005951#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005952}
5953
5954template class collate<char>;
5955template class collate<wchar_t>;
5956
5957template class num_get<char>;
5958template class num_get<wchar_t>;
5959
Howard Hinnantec3773c2011-12-01 20:21:04 +00005960template struct __num_get<char>;
5961template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005962
5963template class num_put<char>;
5964template class num_put<wchar_t>;
5965
Howard Hinnantec3773c2011-12-01 20:21:04 +00005966template struct __num_put<char>;
5967template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005968
5969template class time_get<char>;
5970template class time_get<wchar_t>;
5971
5972template class time_get_byname<char>;
5973template class time_get_byname<wchar_t>;
5974
5975template class time_put<char>;
5976template class time_put<wchar_t>;
5977
5978template class time_put_byname<char>;
5979template class time_put_byname<wchar_t>;
5980
5981template class moneypunct<char, false>;
5982template class moneypunct<char, true>;
5983template class moneypunct<wchar_t, false>;
5984template class moneypunct<wchar_t, true>;
5985
5986template class moneypunct_byname<char, false>;
5987template class moneypunct_byname<char, true>;
5988template class moneypunct_byname<wchar_t, false>;
5989template class moneypunct_byname<wchar_t, true>;
5990
5991template class money_get<char>;
5992template class money_get<wchar_t>;
5993
5994template class __money_get<char>;
5995template class __money_get<wchar_t>;
5996
5997template class money_put<char>;
5998template class money_put<wchar_t>;
5999
6000template class __money_put<char>;
6001template class __money_put<wchar_t>;
6002
6003template class messages<char>;
6004template class messages<wchar_t>;
6005
6006template class messages_byname<char>;
6007template class messages_byname<wchar_t>;
6008
6009template class codecvt_byname<char, char, mbstate_t>;
6010template class codecvt_byname<wchar_t, char, mbstate_t>;
6011template class codecvt_byname<char16_t, char, mbstate_t>;
6012template class codecvt_byname<char32_t, char, mbstate_t>;
6013
6014template class __vector_base_common<true>;
6015
6016_LIBCPP_END_NAMESPACE_STD