blob: 97c2102c1b50e2f5925bca2914625a748d7b0b26 [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"
Marshall Clowa22d2ad2013-03-18 17:04:29 +000028#ifdef _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
Marshall Clow9ae96d02013-02-07 17:20:56 +000035// On Linux, wint_t and wchar_t have different signed-ness, and this causes
36// lots of noise in the build log, but no bugs that I know of.
37#pragma clang diagnostic ignored "-Wsign-conversion"
38
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000039_LIBCPP_BEGIN_NAMESPACE_STD
40
Howard Hinnant866569b2011-09-28 23:39:33 +000041#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000042locale_t __cloc() {
43 // In theory this could create a race condition. In practice
44 // the race condition is non-fatal since it will just create
45 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000046 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
47 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000048}
Howard Hinnant866569b2011-09-28 23:39:33 +000049#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000050
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051namespace {
52
53struct release
54{
55 void operator()(locale::facet* p) {p->__release_shared();}
56};
57
58template <class T, class A0>
59inline
60T&
61make(A0 a0)
62{
63 static typename aligned_storage<sizeof(T)>::type buf;
64 ::new (&buf) T(a0);
65 return *(T*)&buf;
66}
67
68template <class T, class A0, class A1>
69inline
70T&
71make(A0 a0, A1 a1)
72{
73 static typename aligned_storage<sizeof(T)>::type buf;
74 ::new (&buf) T(a0, a1);
75 return *(T*)&buf;
76}
77
78template <class T, class A0, class A1, class A2>
79inline
80T&
81make(A0 a0, A1 a1, A2 a2)
82{
83 static typename aligned_storage<sizeof(T)>::type buf;
84 ::new (&buf) T(a0, a1, a2);
85 return *(T*)&buf;
86}
87
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000088template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000089inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000090_LIBCPP_CONSTEXPR
91size_t
92countof(const T (&)[N])
93{
94 return N;
95}
96
97template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +000098inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000099_LIBCPP_CONSTEXPR
100size_t
101countof(const T * const begin, const T * const end)
102{
103 return static_cast<size_t>(end - begin);
104}
105
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000106}
107
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000108const locale::category locale::none;
109const locale::category locale::collate;
110const locale::category locale::ctype;
111const locale::category locale::monetary;
112const locale::category locale::numeric;
113const locale::category locale::time;
114const locale::category locale::messages;
115const locale::category locale::all;
116
Howard Hinnantec3773c2011-12-01 20:21:04 +0000117#pragma clang diagnostic push
118#pragma clang diagnostic ignored "-Wpadded"
119
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120class _LIBCPP_HIDDEN locale::__imp
121 : public facet
122{
123 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000124 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000125 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000126public:
127 explicit __imp(size_t refs = 0);
128 explicit __imp(const string& name, size_t refs = 0);
129 __imp(const __imp&);
130 __imp(const __imp&, const string&, locale::category c);
131 __imp(const __imp& other, const __imp& one, locale::category c);
132 __imp(const __imp&, facet* f, long id);
133 ~__imp();
134
135 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000136 bool has_facet(long id) const
137 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000138 const locale::facet* use_facet(long id) const;
139
140 static const locale& make_classic();
141 static locale& make_global();
142private:
143 void install(facet* f, long id);
144 template <class F> void install(F* f) {install(f, f->id.__get());}
145 template <class F> void install_from(const __imp& other);
146};
147
Howard Hinnantec3773c2011-12-01 20:21:04 +0000148#pragma clang diagnostic pop
149
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000150locale::__imp::__imp(size_t refs)
151 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000152 facets_(N),
153 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000154{
155 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000156 install(&make<_VSTD::collate<char> >(1u));
157 install(&make<_VSTD::collate<wchar_t> >(1u));
158 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
159 install(&make<_VSTD::ctype<wchar_t> >(1u));
160 install(&make<codecvt<char, char, mbstate_t> >(1u));
161 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
162 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
163 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
164 install(&make<numpunct<char> >(1u));
165 install(&make<numpunct<wchar_t> >(1u));
166 install(&make<num_get<char> >(1u));
167 install(&make<num_get<wchar_t> >(1u));
168 install(&make<num_put<char> >(1u));
169 install(&make<num_put<wchar_t> >(1u));
170 install(&make<moneypunct<char, false> >(1u));
171 install(&make<moneypunct<char, true> >(1u));
172 install(&make<moneypunct<wchar_t, false> >(1u));
173 install(&make<moneypunct<wchar_t, true> >(1u));
174 install(&make<money_get<char> >(1u));
175 install(&make<money_get<wchar_t> >(1u));
176 install(&make<money_put<char> >(1u));
177 install(&make<money_put<wchar_t> >(1u));
178 install(&make<time_get<char> >(1u));
179 install(&make<time_get<wchar_t> >(1u));
180 install(&make<time_put<char> >(1u));
181 install(&make<time_put<wchar_t> >(1u));
182 install(&make<_VSTD::messages<char> >(1u));
183 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000184}
185
186locale::__imp::__imp(const string& name, size_t refs)
187 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000188 facets_(N),
189 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000190{
Howard Hinnantd4444702010-08-11 17:04:31 +0000191#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192 try
193 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000194#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000195 facets_ = locale::classic().__locale_->facets_;
196 for (unsigned i = 0; i < facets_.size(); ++i)
197 if (facets_[i])
198 facets_[i]->__add_shared();
199 install(new collate_byname<char>(name_));
200 install(new collate_byname<wchar_t>(name_));
201 install(new ctype_byname<char>(name_));
202 install(new ctype_byname<wchar_t>(name_));
203 install(new codecvt_byname<char, char, mbstate_t>(name_));
204 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
205 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
206 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
207 install(new numpunct_byname<char>(name_));
208 install(new numpunct_byname<wchar_t>(name_));
209 install(new moneypunct_byname<char, false>(name_));
210 install(new moneypunct_byname<char, true>(name_));
211 install(new moneypunct_byname<wchar_t, false>(name_));
212 install(new moneypunct_byname<wchar_t, true>(name_));
213 install(new time_get_byname<char>(name_));
214 install(new time_get_byname<wchar_t>(name_));
215 install(new time_put_byname<char>(name_));
216 install(new time_put_byname<wchar_t>(name_));
217 install(new messages_byname<char>(name_));
218 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000219#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000220 }
221 catch (...)
222 {
223 for (unsigned i = 0; i < facets_.size(); ++i)
224 if (facets_[i])
225 facets_[i]->__release_shared();
226 throw;
227 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000228#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000229}
230
Howard Hinnant21772ec2012-12-28 18:15:01 +0000231// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000232// copy constructor` warning emitted by GCC
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000233#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000234#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000235#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000236#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000237
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000238locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000239 : facets_(max<size_t>(N, other.facets_.size())),
240 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000241{
242 facets_ = other.facets_;
243 for (unsigned i = 0; i < facets_.size(); ++i)
244 if (facets_[i])
245 facets_[i]->__add_shared();
246}
247
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000248#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000249#pragma GCC diagnostic pop
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000250#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000251
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000252locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000253 : facets_(N),
254 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000255{
256 facets_ = other.facets_;
257 for (unsigned i = 0; i < facets_.size(); ++i)
258 if (facets_[i])
259 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000260#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000261 try
262 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000263#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000264 if (c & locale::collate)
265 {
266 install(new collate_byname<char>(name));
267 install(new collate_byname<wchar_t>(name));
268 }
269 if (c & locale::ctype)
270 {
271 install(new ctype_byname<char>(name));
272 install(new ctype_byname<wchar_t>(name));
273 install(new codecvt_byname<char, char, mbstate_t>(name));
274 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
275 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
276 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
277 }
278 if (c & locale::monetary)
279 {
280 install(new moneypunct_byname<char, false>(name));
281 install(new moneypunct_byname<char, true>(name));
282 install(new moneypunct_byname<wchar_t, false>(name));
283 install(new moneypunct_byname<wchar_t, true>(name));
284 }
285 if (c & locale::numeric)
286 {
287 install(new numpunct_byname<char>(name));
288 install(new numpunct_byname<wchar_t>(name));
289 }
290 if (c & locale::time)
291 {
292 install(new time_get_byname<char>(name));
293 install(new time_get_byname<wchar_t>(name));
294 install(new time_put_byname<char>(name));
295 install(new time_put_byname<wchar_t>(name));
296 }
297 if (c & locale::messages)
298 {
299 install(new messages_byname<char>(name));
300 install(new messages_byname<wchar_t>(name));
301 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000302#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000303 }
304 catch (...)
305 {
306 for (unsigned i = 0; i < facets_.size(); ++i)
307 if (facets_[i])
308 facets_[i]->__release_shared();
309 throw;
310 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000311#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000312}
313
314template<class F>
315inline
316void
317locale::__imp::install_from(const locale::__imp& one)
318{
319 long id = F::id.__get();
320 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
321}
322
323locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000324 : facets_(N),
325 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000326{
327 facets_ = other.facets_;
328 for (unsigned i = 0; i < facets_.size(); ++i)
329 if (facets_[i])
330 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000331#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000332 try
333 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000334#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000335 if (c & locale::collate)
336 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000337 install_from<_VSTD::collate<char> >(one);
338 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000339 }
340 if (c & locale::ctype)
341 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000342 install_from<_VSTD::ctype<char> >(one);
343 install_from<_VSTD::ctype<wchar_t> >(one);
344 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
345 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
346 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
347 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000348 }
349 if (c & locale::monetary)
350 {
351 install_from<moneypunct<char, false> >(one);
352 install_from<moneypunct<char, true> >(one);
353 install_from<moneypunct<wchar_t, false> >(one);
354 install_from<moneypunct<wchar_t, true> >(one);
355 install_from<money_get<char> >(one);
356 install_from<money_get<wchar_t> >(one);
357 install_from<money_put<char> >(one);
358 install_from<money_put<wchar_t> >(one);
359 }
360 if (c & locale::numeric)
361 {
362 install_from<numpunct<char> >(one);
363 install_from<numpunct<wchar_t> >(one);
364 install_from<num_get<char> >(one);
365 install_from<num_get<wchar_t> >(one);
366 install_from<num_put<char> >(one);
367 install_from<num_put<wchar_t> >(one);
368 }
369 if (c & locale::time)
370 {
371 install_from<time_get<char> >(one);
372 install_from<time_get<wchar_t> >(one);
373 install_from<time_put<char> >(one);
374 install_from<time_put<wchar_t> >(one);
375 }
376 if (c & locale::messages)
377 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000378 install_from<_VSTD::messages<char> >(one);
379 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000380 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000381#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000382 }
383 catch (...)
384 {
385 for (unsigned i = 0; i < facets_.size(); ++i)
386 if (facets_[i])
387 facets_[i]->__release_shared();
388 throw;
389 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000390#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000391}
392
393locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000394 : facets_(max<size_t>(N, other.facets_.size()+1)),
395 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000396{
397 f->__add_shared();
398 unique_ptr<facet, release> hold(f);
399 facets_ = other.facets_;
400 for (unsigned i = 0; i < other.facets_.size(); ++i)
401 if (facets_[i])
402 facets_[i]->__add_shared();
403 install(hold.get(), id);
404}
405
406locale::__imp::~__imp()
407{
408 for (unsigned i = 0; i < facets_.size(); ++i)
409 if (facets_[i])
410 facets_[i]->__release_shared();
411}
412
413void
414locale::__imp::install(facet* f, long id)
415{
416 f->__add_shared();
417 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000418 if (static_cast<size_t>(id) >= facets_.size())
419 facets_.resize(static_cast<size_t>(id+1));
420 if (facets_[static_cast<size_t>(id)])
421 facets_[static_cast<size_t>(id)]->__release_shared();
422 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000423}
424
425const locale::facet*
426locale::__imp::use_facet(long id) const
427{
Howard Hinnantd4444702010-08-11 17:04:31 +0000428#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000429 if (!has_facet(id))
430 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000431#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000432 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000433}
434
435// locale
436
437const locale&
438locale::__imp::make_classic()
439{
440 // only one thread can get in here and it only gets in once
441 static aligned_storage<sizeof(locale)>::type buf;
442 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000443 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000444 return *c;
445}
446
447const locale&
448locale::classic()
449{
450 static const locale& c = __imp::make_classic();
451 return c;
452}
453
454locale&
455locale::__imp::make_global()
456{
457 // only one thread can get in here and it only gets in once
458 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000459 ::new (&buf) locale(locale::classic());
460 return *(locale*)&buf;
461}
462
463locale&
464locale::__global()
465{
466 static locale& g = __imp::make_global();
467 return g;
468}
469
Howard Hinnantc9834542011-05-31 15:34:58 +0000470locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000471 : __locale_(__global().__locale_)
472{
473 __locale_->__add_shared();
474}
475
Howard Hinnantc9834542011-05-31 15:34:58 +0000476locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000477 : __locale_(l.__locale_)
478{
479 __locale_->__add_shared();
480}
481
Howard Hinnantc9834542011-05-31 15:34:58 +0000482locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000483{
484 __locale_->__release_shared();
485}
486
487const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000488locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000489{
490 other.__locale_->__add_shared();
491 __locale_->__release_shared();
492 __locale_ = other.__locale_;
493 return *this;
494}
495
496locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000497#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000498 : __locale_(name ? new __imp(name)
499 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000500#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000501 : __locale_(new __imp(name))
502#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000503{
504 __locale_->__add_shared();
505}
506
507locale::locale(const string& name)
508 : __locale_(new __imp(name))
509{
510 __locale_->__add_shared();
511}
512
513locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000514#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000515 : __locale_(name ? new __imp(*other.__locale_, name, c)
516 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000517#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000518 : __locale_(new __imp(*other.__locale_, name, c))
519#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000520{
521 __locale_->__add_shared();
522}
523
524locale::locale(const locale& other, const string& name, category c)
525 : __locale_(new __imp(*other.__locale_, name, c))
526{
527 __locale_->__add_shared();
528}
529
530locale::locale(const locale& other, const locale& one, category c)
531 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
532{
533 __locale_->__add_shared();
534}
535
536string
537locale::name() const
538{
539 return __locale_->name();
540}
541
542void
543locale::__install_ctor(const locale& other, facet* f, long id)
544{
545 if (f)
546 __locale_ = new __imp(*other.__locale_, f, id);
547 else
548 __locale_ = other.__locale_;
549 __locale_->__add_shared();
550}
551
552locale
553locale::global(const locale& loc)
554{
555 locale& g = __global();
556 locale r = g;
557 g = loc;
558 if (g.name() != "*")
559 setlocale(LC_ALL, g.name().c_str());
560 return r;
561}
562
563bool
564locale::has_facet(id& x) const
565{
566 return __locale_->has_facet(x.__get());
567}
568
569const locale::facet*
570locale::use_facet(id& x) const
571{
572 return __locale_->use_facet(x.__get());
573}
574
575bool
576locale::operator==(const locale& y) const
577{
578 return (__locale_ == y.__locale_)
579 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
580}
581
582// locale::facet
583
584locale::facet::~facet()
585{
586}
587
588void
Howard Hinnant1694d232011-05-28 14:41:13 +0000589locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000590{
591 delete this;
592}
593
594// locale::id
595
596int32_t locale::id::__next_id = 0;
597
598namespace
599{
600
601class __fake_bind
602{
603 locale::id* id_;
604 void (locale::id::* pmf_)();
605public:
606 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
607 : id_(id), pmf_(pmf) {}
608
609 void operator()() const
610 {
611 (id_->*pmf_)();
612 }
613};
614
615}
616
617long
618locale::id::__get()
619{
620 call_once(__flag_, __fake_bind(&locale::id::__init, this));
621 return __id_ - 1;
622}
623
624void
625locale::id::__init()
626{
Howard Hinnantadff4892010-05-24 17:49:41 +0000627 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000628}
629
630// template <> class collate_byname<char>
631
632collate_byname<char>::collate_byname(const char* n, size_t refs)
633 : collate<char>(refs),
634 __l(newlocale(LC_ALL_MASK, n, 0))
635{
Howard Hinnantd4444702010-08-11 17:04:31 +0000636#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000637 if (__l == 0)
638 throw runtime_error("collate_byname<char>::collate_byname"
639 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000640#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000641}
642
643collate_byname<char>::collate_byname(const string& name, size_t refs)
644 : collate<char>(refs),
645 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
646{
Howard Hinnantd4444702010-08-11 17:04:31 +0000647#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000648 if (__l == 0)
649 throw runtime_error("collate_byname<char>::collate_byname"
650 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000651#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000652}
653
654collate_byname<char>::~collate_byname()
655{
656 freelocale(__l);
657}
658
659int
660collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
661 const char_type* __lo2, const char_type* __hi2) const
662{
663 string_type lhs(__lo1, __hi1);
664 string_type rhs(__lo2, __hi2);
665 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
666 if (r < 0)
667 return -1;
668 if (r > 0)
669 return 1;
670 return r;
671}
672
673collate_byname<char>::string_type
674collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
675{
676 const string_type in(lo, hi);
677 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
678 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
679 return out;
680}
681
682// template <> class collate_byname<wchar_t>
683
684collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
685 : collate<wchar_t>(refs),
686 __l(newlocale(LC_ALL_MASK, n, 0))
687{
Howard Hinnantd4444702010-08-11 17:04:31 +0000688#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000689 if (__l == 0)
690 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
691 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000692#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000693}
694
695collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
696 : collate<wchar_t>(refs),
697 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
698{
Howard Hinnantd4444702010-08-11 17:04:31 +0000699#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000700 if (__l == 0)
701 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
702 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000703#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000704}
705
706collate_byname<wchar_t>::~collate_byname()
707{
708 freelocale(__l);
709}
710
711int
712collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
713 const char_type* __lo2, const char_type* __hi2) const
714{
715 string_type lhs(__lo1, __hi1);
716 string_type rhs(__lo2, __hi2);
717 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
718 if (r < 0)
719 return -1;
720 if (r > 0)
721 return 1;
722 return r;
723}
724
725collate_byname<wchar_t>::string_type
726collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
727{
728 const string_type in(lo, hi);
729 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
730 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
731 return out;
732}
733
734// template <> class ctype<wchar_t>;
735
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000736const ctype_base::mask ctype_base::space;
737const ctype_base::mask ctype_base::print;
738const ctype_base::mask ctype_base::cntrl;
739const ctype_base::mask ctype_base::upper;
740const ctype_base::mask ctype_base::lower;
741const ctype_base::mask ctype_base::alpha;
742const ctype_base::mask ctype_base::digit;
743const ctype_base::mask ctype_base::punct;
744const ctype_base::mask ctype_base::xdigit;
745const ctype_base::mask ctype_base::blank;
746const ctype_base::mask ctype_base::alnum;
747const ctype_base::mask ctype_base::graph;
748
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000749locale::id ctype<wchar_t>::id;
750
751ctype<wchar_t>::~ctype()
752{
753}
754
755bool
756ctype<wchar_t>::do_is(mask m, char_type c) const
757{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000758 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000759}
760
761const wchar_t*
762ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
763{
764 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000765 *vec = static_cast<mask>(isascii(*low) ?
766 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000767 return low;
768}
769
770const wchar_t*
771ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
772{
773 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000774 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000775 break;
776 return low;
777}
778
779const wchar_t*
780ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
781{
782 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000783 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000784 break;
785 return low;
786}
787
788wchar_t
789ctype<wchar_t>::do_toupper(char_type c) const
790{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000791#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
792 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000793#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000794 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000795#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000796 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000797#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000798}
799
800const wchar_t*
801ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
802{
803 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000804#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
805 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000806#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000807 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
808 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000809#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000810 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000811#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000812 return low;
813}
814
815wchar_t
816ctype<wchar_t>::do_tolower(char_type c) const
817{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000818#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
819 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000820#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000821 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000822#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000823 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000824#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000825}
826
827const wchar_t*
828ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
829{
830 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000831#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
832 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000833#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000834 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
835 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000836#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000837 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000838#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000839 return low;
840}
841
842wchar_t
843ctype<wchar_t>::do_widen(char c) const
844{
845 return c;
846}
847
848const char*
849ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
850{
851 for (; low != high; ++low, ++dest)
852 *dest = *low;
853 return low;
854}
855
856char
857ctype<wchar_t>::do_narrow(char_type c, char dfault) const
858{
859 if (isascii(c))
860 return static_cast<char>(c);
861 return dfault;
862}
863
864const wchar_t*
865ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
866{
867 for (; low != high; ++low, ++dest)
868 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000869 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000870 else
871 *dest = dfault;
872 return low;
873}
874
875// template <> class ctype<char>;
876
877locale::id ctype<char>::id;
878
879ctype<char>::ctype(const mask* tab, bool del, size_t refs)
880 : locale::facet(refs),
881 __tab_(tab),
882 __del_(del)
883{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000884 if (__tab_ == 0)
885 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000886}
887
888ctype<char>::~ctype()
889{
890 if (__tab_ && __del_)
891 delete [] __tab_;
892}
893
894char
895ctype<char>::do_toupper(char_type c) const
896{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000897#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000898 return isascii(c) ?
899 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000900#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000901 return isascii(c) ?
902 static_cast<char>(__classic_upper_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000903#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000904 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000905#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000906}
907
908const char*
909ctype<char>::do_toupper(char_type* low, const char_type* high) const
910{
911 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000912#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000913 *low = isascii(*low) ?
914 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000915#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000916 *low = isascii(*low) ?
917 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000918#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000919 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000920#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000921 return low;
922}
923
924char
925ctype<char>::do_tolower(char_type c) const
926{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000927#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000928 return isascii(c) ?
929 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000930#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000931 return isascii(c) ?
932 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000933#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000934 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000935#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000936}
937
938const char*
939ctype<char>::do_tolower(char_type* low, const char_type* high) const
940{
941 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000942#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000943 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000944#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000945 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000946#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000947 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000948#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000949 return low;
950}
951
952char
953ctype<char>::do_widen(char c) const
954{
955 return c;
956}
957
958const char*
959ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
960{
961 for (; low != high; ++low, ++dest)
962 *dest = *low;
963 return low;
964}
965
966char
967ctype<char>::do_narrow(char_type c, char dfault) const
968{
969 if (isascii(c))
970 return static_cast<char>(c);
971 return dfault;
972}
973
974const char*
975ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
976{
977 for (; low != high; ++low, ++dest)
978 if (isascii(*low))
979 *dest = *low;
980 else
981 *dest = dfault;
982 return low;
983}
984
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000985#ifdef EMSCRIPTEN
986extern "C" const unsigned short ** __ctype_b_loc();
987extern "C" const int ** __ctype_tolower_loc();
988extern "C" const int ** __ctype_toupper_loc();
989#endif
990
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000991const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000992ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000993{
David Chisnallc512df12011-09-21 08:39:44 +0000994#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000995 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000996#elif defined(__GLIBC__)
997 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +0000998#elif __sun__
999 return __ctype_mask;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00001000#elif defined(_WIN32)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001001 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001002// This is assumed to be safe, which is a nonsense assumption because we're
1003// going to end up dereferencing it later...
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001004#elif defined(EMSCRIPTEN)
1005 return *__ctype_b_loc();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001006#else
David Chisnall997e4542012-02-29 13:05:08 +00001007 // Platform not supported: abort so the person doing the port knows what to
1008 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001009# warning ctype<char>::classic_table() is not implemented
David Chisnall997e4542012-02-29 13:05:08 +00001010 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001011 return NULL;
1012#endif
1013}
1014
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001015#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001016const int*
1017ctype<char>::__classic_lower_table() _NOEXCEPT
1018{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001019 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001020}
1021
1022const int*
1023ctype<char>::__classic_upper_table() _NOEXCEPT
1024{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001025 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001026}
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001027#endif // __GLIBC__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001028
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001029#if defined(EMSCRIPTEN)
1030const int*
1031ctype<char>::__classic_lower_table() _NOEXCEPT
1032{
1033 return *__ctype_tolower_loc();
1034}
1035
1036const int*
1037ctype<char>::__classic_upper_table() _NOEXCEPT
1038{
1039 return *__ctype_toupper_loc();
1040}
1041#endif // EMSCRIPTEN
1042
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043// template <> class ctype_byname<char>
1044
1045ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1046 : ctype<char>(0, false, refs),
1047 __l(newlocale(LC_ALL_MASK, name, 0))
1048{
Howard Hinnantd4444702010-08-11 17:04:31 +00001049#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001050 if (__l == 0)
1051 throw runtime_error("ctype_byname<char>::ctype_byname"
1052 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001053#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001054}
1055
1056ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1057 : ctype<char>(0, false, refs),
1058 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1059{
Howard Hinnantd4444702010-08-11 17:04:31 +00001060#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001061 if (__l == 0)
1062 throw runtime_error("ctype_byname<char>::ctype_byname"
1063 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001064#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001065}
1066
1067ctype_byname<char>::~ctype_byname()
1068{
1069 freelocale(__l);
1070}
1071
1072char
1073ctype_byname<char>::do_toupper(char_type c) const
1074{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001075 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001076}
1077
1078const char*
1079ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1080{
1081 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001082 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001083 return low;
1084}
1085
1086char
1087ctype_byname<char>::do_tolower(char_type c) const
1088{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001089 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001090}
1091
1092const char*
1093ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1094{
1095 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001096 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001097 return low;
1098}
1099
1100// template <> class ctype_byname<wchar_t>
1101
1102ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1103 : ctype<wchar_t>(refs),
1104 __l(newlocale(LC_ALL_MASK, name, 0))
1105{
Howard Hinnantd4444702010-08-11 17:04:31 +00001106#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001107 if (__l == 0)
1108 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1109 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001110#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001111}
1112
1113ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1114 : ctype<wchar_t>(refs),
1115 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1116{
Howard Hinnantd4444702010-08-11 17:04:31 +00001117#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001118 if (__l == 0)
1119 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1120 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001121#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001122}
1123
1124ctype_byname<wchar_t>::~ctype_byname()
1125{
1126 freelocale(__l);
1127}
1128
1129bool
1130ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1131{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001132#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001133 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001134#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001135 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001136 wint_t ch = static_cast<wint_t>(c);
1137 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1138 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1139 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1140 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1141 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1142 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1143 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1144 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1145 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1146 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001147 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001148#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001149}
1150
1151const wchar_t*
1152ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1153{
1154 for (; low != high; ++low, ++vec)
1155 {
1156 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001157 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001158 else
1159 {
1160 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001161 wint_t ch = static_cast<wint_t>(*low);
1162 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001163 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001164 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001165 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001166 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001167 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001168 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001169 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001170 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001171 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001172 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001173 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001174 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001175 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001176 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001177 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001178 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001179 *vec |= xdigit;
1180 }
1181 }
1182 return low;
1183}
1184
1185const wchar_t*
1186ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1187{
1188 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001189 {
1190#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001191 if (iswctype_l(*low, m, __l))
1192 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001193#else
Marshall Clow88c31902013-02-07 14:22:51 +00001194 wint_t ch = static_cast<wint_t>(*low);
1195 if (m & space && iswspace_l(ch, __l)) break;
1196 if (m & print && iswprint_l(ch, __l)) break;
1197 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1198 if (m & upper && iswupper_l(ch, __l)) break;
1199 if (m & lower && iswlower_l(ch, __l)) break;
1200 if (m & alpha && iswalpha_l(ch, __l)) break;
1201 if (m & digit && iswdigit_l(ch, __l)) break;
1202 if (m & punct && iswpunct_l(ch, __l)) break;
1203 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1204 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001205#endif
1206 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001207 return low;
1208}
1209
1210const wchar_t*
1211ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1212{
1213 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001214 {
1215#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001216 if (!iswctype_l(*low, m, __l))
1217 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001218#else
Marshall Clow88c31902013-02-07 14:22:51 +00001219 wint_t ch = static_cast<wint_t>(*low);
1220 if (m & space && iswspace_l(ch, __l)) continue;
1221 if (m & print && iswprint_l(ch, __l)) continue;
1222 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1223 if (m & upper && iswupper_l(ch, __l)) continue;
1224 if (m & lower && iswlower_l(ch, __l)) continue;
1225 if (m & alpha && iswalpha_l(ch, __l)) continue;
1226 if (m & digit && iswdigit_l(ch, __l)) continue;
1227 if (m & punct && iswpunct_l(ch, __l)) continue;
1228 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1229 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001230 break;
1231#endif
1232 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001233 return low;
1234}
1235
1236wchar_t
1237ctype_byname<wchar_t>::do_toupper(char_type c) const
1238{
1239 return towupper_l(c, __l);
1240}
1241
1242const wchar_t*
1243ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1244{
1245 for (; low != high; ++low)
1246 *low = towupper_l(*low, __l);
1247 return low;
1248}
1249
1250wchar_t
1251ctype_byname<wchar_t>::do_tolower(char_type c) const
1252{
1253 return towlower_l(c, __l);
1254}
1255
1256const wchar_t*
1257ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1258{
1259 for (; low != high; ++low)
1260 *low = towlower_l(*low, __l);
1261 return low;
1262}
1263
1264wchar_t
1265ctype_byname<wchar_t>::do_widen(char c) const
1266{
Howard Hinnant866569b2011-09-28 23:39:33 +00001267#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001268 return btowc_l(c, __l);
1269#else
1270 return __btowc_l(c, __l);
1271#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001272}
1273
1274const char*
1275ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1276{
1277 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001278#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001279 *dest = btowc_l(*low, __l);
1280#else
1281 *dest = __btowc_l(*low, __l);
1282#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001283 return low;
1284}
1285
1286char
1287ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1288{
Howard Hinnant866569b2011-09-28 23:39:33 +00001289#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001290 int r = wctob_l(c, __l);
1291#else
1292 int r = __wctob_l(c, __l);
1293#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001294 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001295}
1296
1297const wchar_t*
1298ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1299{
1300 for (; low != high; ++low, ++dest)
1301 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001302#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001303 int r = wctob_l(*low, __l);
1304#else
1305 int r = __wctob_l(*low, __l);
1306#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001307 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001308 }
1309 return low;
1310}
1311
1312// template <> class codecvt<char, char, mbstate_t>
1313
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001314locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001315
1316codecvt<char, char, mbstate_t>::~codecvt()
1317{
1318}
1319
1320codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001321codecvt<char, char, mbstate_t>::do_out(state_type&,
1322 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001323 extern_type* to, extern_type*, extern_type*& to_nxt) const
1324{
1325 frm_nxt = frm;
1326 to_nxt = to;
1327 return noconv;
1328}
1329
1330codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001331codecvt<char, char, mbstate_t>::do_in(state_type&,
1332 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001333 intern_type* to, intern_type*, intern_type*& to_nxt) const
1334{
1335 frm_nxt = frm;
1336 to_nxt = to;
1337 return noconv;
1338}
1339
1340codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001341codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001342 extern_type* to, extern_type*, extern_type*& to_nxt) const
1343{
1344 to_nxt = to;
1345 return noconv;
1346}
1347
1348int
Howard Hinnantc9834542011-05-31 15:34:58 +00001349codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001350{
1351 return 1;
1352}
1353
1354bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001355codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001356{
1357 return true;
1358}
1359
1360int
1361codecvt<char, char, mbstate_t>::do_length(state_type&,
1362 const extern_type* frm, const extern_type* end, size_t mx) const
1363{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001364 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001365}
1366
1367int
Howard Hinnantc9834542011-05-31 15:34:58 +00001368codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001369{
1370 return 1;
1371}
1372
1373// template <> class codecvt<wchar_t, char, mbstate_t>
1374
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001375locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001376
1377codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1378 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001379 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001380{
1381}
1382
1383codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1384 : locale::facet(refs),
1385 __l(newlocale(LC_ALL_MASK, nm, 0))
1386{
Howard Hinnantd4444702010-08-11 17:04:31 +00001387#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001388 if (__l == 0)
1389 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1390 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001391#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001392}
1393
1394codecvt<wchar_t, char, mbstate_t>::~codecvt()
1395{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001396 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001397 freelocale(__l);
1398}
1399
1400codecvt<wchar_t, char, mbstate_t>::result
1401codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001402 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001403 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1404{
1405 // look for first internal null in frm
1406 const intern_type* fend = frm;
1407 for (; fend != frm_end; ++fend)
1408 if (*fend == 0)
1409 break;
1410 // loop over all null-terminated sequences in frm
1411 to_nxt = to;
1412 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1413 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001414 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001415 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001416#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001417 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1418 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001419#else
1420 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1421#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001422 if (n == size_t(-1))
1423 {
1424 // need to recover to_nxt
1425 for (to_nxt = to; frm != frm_nxt; ++frm)
1426 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001427#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001428 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1429#else
1430 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1431#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001432 if (n == size_t(-1))
1433 break;
1434 to_nxt += n;
1435 }
1436 frm_nxt = frm;
1437 return error;
1438 }
1439 if (n == 0)
1440 return partial;
1441 to_nxt += n;
1442 if (to_nxt == to_end)
1443 break;
1444 if (fend != frm_end) // set up next null terminated sequence
1445 {
1446 // Try to write the terminating null
1447 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001448#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001449 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1450#else
1451 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1452#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001453 if (n == size_t(-1)) // on error
1454 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001455 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001456 return partial;
1457 for (extern_type* p = tmp; n; --n) // write it
1458 *to_nxt++ = *p++;
1459 ++frm_nxt;
1460 // look for next null in frm
1461 for (fend = frm_nxt; fend != frm_end; ++fend)
1462 if (*fend == 0)
1463 break;
1464 }
1465 }
1466 return frm_nxt == frm_end ? ok : partial;
1467}
1468
1469codecvt<wchar_t, char, mbstate_t>::result
1470codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001471 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001472 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1473{
1474 // look for first internal null in frm
1475 const extern_type* fend = frm;
1476 for (; fend != frm_end; ++fend)
1477 if (*fend == 0)
1478 break;
1479 // loop over all null-terminated sequences in frm
1480 to_nxt = to;
1481 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1482 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001483 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001484 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001485#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001486 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1487 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001488#else
1489 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1490#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001491 if (n == size_t(-1))
1492 {
1493 // need to recover to_nxt
1494 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1495 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001496#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001497 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1498 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001499#else
1500 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1501#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001502 switch (n)
1503 {
1504 case 0:
1505 ++frm;
1506 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001507 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001508 frm_nxt = frm;
1509 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001510 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001511 frm_nxt = frm;
1512 return partial;
1513 default:
1514 frm += n;
1515 break;
1516 }
1517 }
1518 frm_nxt = frm;
1519 return frm_nxt == frm_end ? ok : partial;
1520 }
1521 if (n == 0)
1522 return error;
1523 to_nxt += n;
1524 if (to_nxt == to_end)
1525 break;
1526 if (fend != frm_end) // set up next null terminated sequence
1527 {
1528 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001529#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001530 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1531#else
1532 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1533#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001534 if (n != 0) // on error
1535 return error;
1536 ++to_nxt;
1537 ++frm_nxt;
1538 // look for next null in frm
1539 for (fend = frm_nxt; fend != frm_end; ++fend)
1540 if (*fend == 0)
1541 break;
1542 }
1543 }
1544 return frm_nxt == frm_end ? ok : partial;
1545}
1546
1547codecvt<wchar_t, char, mbstate_t>::result
1548codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1549 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1550{
1551 to_nxt = to;
1552 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001553#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001554 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1555#else
1556 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1557#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001558 if (n == size_t(-1) || n == 0) // on error
1559 return error;
1560 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001561 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001562 return partial;
1563 for (extern_type* p = tmp; n; --n) // write it
1564 *to_nxt++ = *p++;
1565 return ok;
1566}
1567
1568int
Howard Hinnantc9834542011-05-31 15:34:58 +00001569codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001570{
Howard Hinnant866569b2011-09-28 23:39:33 +00001571#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001572 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1573#else
1574 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1575#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001576 {
1577 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001578#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001579 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1580#else
1581 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1582#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001583 return 1; // which take more than 1 char to form a wchar_t
1584 return 0;
1585 }
1586 return -1;
1587}
1588
1589bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001590codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001591{
1592 return false;
1593}
1594
1595int
1596codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1597 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1598{
1599 int nbytes = 0;
1600 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1601 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001602#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001603 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001604#else
1605 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1606#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001607 switch (n)
1608 {
1609 case 0:
1610 ++nbytes;
1611 ++frm;
1612 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001613 case size_t(-1):
1614 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001615 return nbytes;
1616 default:
1617 nbytes += n;
1618 frm += n;
1619 break;
1620 }
1621 }
1622 return nbytes;
1623}
1624
1625int
Howard Hinnantc9834542011-05-31 15:34:58 +00001626codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001627{
Howard Hinnant866569b2011-09-28 23:39:33 +00001628#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001629 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001630#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001631 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001632#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001633}
1634
1635// Valid UTF ranges
1636// UTF-32 UTF-16 UTF-8 # of code points
1637// first second first second third fourth
1638// 000000 - 00007F 0000 - 007F 00 - 7F 127
1639// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1640// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1641// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1642// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1643// 00D800 - 00DFFF invalid
1644// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1645// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1646// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1647// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1648
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001649static
1650codecvt_base::result
1651utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1652 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1653 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1654{
1655 frm_nxt = frm;
1656 to_nxt = to;
1657 if (mode & generate_header)
1658 {
1659 if (to_end-to_nxt < 3)
1660 return codecvt_base::partial;
1661 *to_nxt++ = static_cast<uint8_t>(0xEF);
1662 *to_nxt++ = static_cast<uint8_t>(0xBB);
1663 *to_nxt++ = static_cast<uint8_t>(0xBF);
1664 }
1665 for (; frm_nxt < frm_end; ++frm_nxt)
1666 {
1667 uint16_t wc1 = *frm_nxt;
1668 if (wc1 > Maxcode)
1669 return codecvt_base::error;
1670 if (wc1 < 0x0080)
1671 {
1672 if (to_end-to_nxt < 1)
1673 return codecvt_base::partial;
1674 *to_nxt++ = static_cast<uint8_t>(wc1);
1675 }
1676 else if (wc1 < 0x0800)
1677 {
1678 if (to_end-to_nxt < 2)
1679 return codecvt_base::partial;
1680 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1681 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1682 }
1683 else if (wc1 < 0xD800)
1684 {
1685 if (to_end-to_nxt < 3)
1686 return codecvt_base::partial;
1687 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1688 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1689 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1690 }
1691 else if (wc1 < 0xDC00)
1692 {
1693 if (frm_end-frm_nxt < 2)
1694 return codecvt_base::partial;
1695 uint16_t wc2 = frm_nxt[1];
1696 if ((wc2 & 0xFC00) != 0xDC00)
1697 return codecvt_base::error;
1698 if (to_end-to_nxt < 4)
1699 return codecvt_base::partial;
1700 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1701 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1702 return codecvt_base::error;
1703 ++frm_nxt;
1704 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1705 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1706 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1707 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1708 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1709 }
1710 else if (wc1 < 0xE000)
1711 {
1712 return codecvt_base::error;
1713 }
1714 else
1715 {
1716 if (to_end-to_nxt < 3)
1717 return codecvt_base::partial;
1718 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1719 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1720 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1721 }
1722 }
1723 return codecvt_base::ok;
1724}
1725
1726static
1727codecvt_base::result
1728utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1729 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1730 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1731{
1732 frm_nxt = frm;
1733 to_nxt = to;
1734 if (mode & generate_header)
1735 {
1736 if (to_end-to_nxt < 3)
1737 return codecvt_base::partial;
1738 *to_nxt++ = static_cast<uint8_t>(0xEF);
1739 *to_nxt++ = static_cast<uint8_t>(0xBB);
1740 *to_nxt++ = static_cast<uint8_t>(0xBF);
1741 }
1742 for (; frm_nxt < frm_end; ++frm_nxt)
1743 {
1744 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1745 if (wc1 > Maxcode)
1746 return codecvt_base::error;
1747 if (wc1 < 0x0080)
1748 {
1749 if (to_end-to_nxt < 1)
1750 return codecvt_base::partial;
1751 *to_nxt++ = static_cast<uint8_t>(wc1);
1752 }
1753 else if (wc1 < 0x0800)
1754 {
1755 if (to_end-to_nxt < 2)
1756 return codecvt_base::partial;
1757 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1758 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1759 }
1760 else if (wc1 < 0xD800)
1761 {
1762 if (to_end-to_nxt < 3)
1763 return codecvt_base::partial;
1764 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1765 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1766 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1767 }
1768 else if (wc1 < 0xDC00)
1769 {
1770 if (frm_end-frm_nxt < 2)
1771 return codecvt_base::partial;
1772 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1773 if ((wc2 & 0xFC00) != 0xDC00)
1774 return codecvt_base::error;
1775 if (to_end-to_nxt < 4)
1776 return codecvt_base::partial;
1777 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1778 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1779 return codecvt_base::error;
1780 ++frm_nxt;
1781 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1782 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1783 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1784 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1785 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1786 }
1787 else if (wc1 < 0xE000)
1788 {
1789 return codecvt_base::error;
1790 }
1791 else
1792 {
1793 if (to_end-to_nxt < 3)
1794 return codecvt_base::partial;
1795 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1796 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1797 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1798 }
1799 }
1800 return codecvt_base::ok;
1801}
1802
1803static
1804codecvt_base::result
1805utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1806 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1807 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1808{
1809 frm_nxt = frm;
1810 to_nxt = to;
1811 if (mode & consume_header)
1812 {
1813 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1814 frm_nxt[2] == 0xBF)
1815 frm_nxt += 3;
1816 }
1817 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1818 {
1819 uint8_t c1 = *frm_nxt;
1820 if (c1 > Maxcode)
1821 return codecvt_base::error;
1822 if (c1 < 0x80)
1823 {
1824 *to_nxt = static_cast<uint16_t>(c1);
1825 ++frm_nxt;
1826 }
1827 else if (c1 < 0xC2)
1828 {
1829 return codecvt_base::error;
1830 }
1831 else if (c1 < 0xE0)
1832 {
1833 if (frm_end-frm_nxt < 2)
1834 return codecvt_base::partial;
1835 uint8_t c2 = frm_nxt[1];
1836 if ((c2 & 0xC0) != 0x80)
1837 return codecvt_base::error;
1838 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1839 if (t > Maxcode)
1840 return codecvt_base::error;
1841 *to_nxt = t;
1842 frm_nxt += 2;
1843 }
1844 else if (c1 < 0xF0)
1845 {
1846 if (frm_end-frm_nxt < 3)
1847 return codecvt_base::partial;
1848 uint8_t c2 = frm_nxt[1];
1849 uint8_t c3 = frm_nxt[2];
1850 switch (c1)
1851 {
1852 case 0xE0:
1853 if ((c2 & 0xE0) != 0xA0)
1854 return codecvt_base::error;
1855 break;
1856 case 0xED:
1857 if ((c2 & 0xE0) != 0x80)
1858 return codecvt_base::error;
1859 break;
1860 default:
1861 if ((c2 & 0xC0) != 0x80)
1862 return codecvt_base::error;
1863 break;
1864 }
1865 if ((c3 & 0xC0) != 0x80)
1866 return codecvt_base::error;
1867 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1868 | ((c2 & 0x3F) << 6)
1869 | (c3 & 0x3F));
1870 if (t > Maxcode)
1871 return codecvt_base::error;
1872 *to_nxt = t;
1873 frm_nxt += 3;
1874 }
1875 else if (c1 < 0xF5)
1876 {
1877 if (frm_end-frm_nxt < 4)
1878 return codecvt_base::partial;
1879 uint8_t c2 = frm_nxt[1];
1880 uint8_t c3 = frm_nxt[2];
1881 uint8_t c4 = frm_nxt[3];
1882 switch (c1)
1883 {
1884 case 0xF0:
1885 if (!(0x90 <= c2 && c2 <= 0xBF))
1886 return codecvt_base::error;
1887 break;
1888 case 0xF4:
1889 if ((c2 & 0xF0) != 0x80)
1890 return codecvt_base::error;
1891 break;
1892 default:
1893 if ((c2 & 0xC0) != 0x80)
1894 return codecvt_base::error;
1895 break;
1896 }
1897 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1898 return codecvt_base::error;
1899 if (to_end-to_nxt < 2)
1900 return codecvt_base::partial;
1901 if (((((unsigned long)c1 & 7) << 18) +
1902 (((unsigned long)c2 & 0x3F) << 12) +
1903 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1904 return codecvt_base::error;
1905 *to_nxt = static_cast<uint16_t>(
1906 0xD800
1907 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1908 | ((c2 & 0x0F) << 2)
1909 | ((c3 & 0x30) >> 4));
1910 *++to_nxt = static_cast<uint16_t>(
1911 0xDC00
1912 | ((c3 & 0x0F) << 6)
1913 | (c4 & 0x3F));
1914 frm_nxt += 4;
1915 }
1916 else
1917 {
1918 return codecvt_base::error;
1919 }
1920 }
1921 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1922}
1923
1924static
1925codecvt_base::result
1926utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1927 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1928 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1929{
1930 frm_nxt = frm;
1931 to_nxt = to;
1932 if (mode & consume_header)
1933 {
1934 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1935 frm_nxt[2] == 0xBF)
1936 frm_nxt += 3;
1937 }
1938 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1939 {
1940 uint8_t c1 = *frm_nxt;
1941 if (c1 > Maxcode)
1942 return codecvt_base::error;
1943 if (c1 < 0x80)
1944 {
1945 *to_nxt = static_cast<uint32_t>(c1);
1946 ++frm_nxt;
1947 }
1948 else if (c1 < 0xC2)
1949 {
1950 return codecvt_base::error;
1951 }
1952 else if (c1 < 0xE0)
1953 {
1954 if (frm_end-frm_nxt < 2)
1955 return codecvt_base::partial;
1956 uint8_t c2 = frm_nxt[1];
1957 if ((c2 & 0xC0) != 0x80)
1958 return codecvt_base::error;
1959 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1960 if (t > Maxcode)
1961 return codecvt_base::error;
1962 *to_nxt = static_cast<uint32_t>(t);
1963 frm_nxt += 2;
1964 }
1965 else if (c1 < 0xF0)
1966 {
1967 if (frm_end-frm_nxt < 3)
1968 return codecvt_base::partial;
1969 uint8_t c2 = frm_nxt[1];
1970 uint8_t c3 = frm_nxt[2];
1971 switch (c1)
1972 {
1973 case 0xE0:
1974 if ((c2 & 0xE0) != 0xA0)
1975 return codecvt_base::error;
1976 break;
1977 case 0xED:
1978 if ((c2 & 0xE0) != 0x80)
1979 return codecvt_base::error;
1980 break;
1981 default:
1982 if ((c2 & 0xC0) != 0x80)
1983 return codecvt_base::error;
1984 break;
1985 }
1986 if ((c3 & 0xC0) != 0x80)
1987 return codecvt_base::error;
1988 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1989 | ((c2 & 0x3F) << 6)
1990 | (c3 & 0x3F));
1991 if (t > Maxcode)
1992 return codecvt_base::error;
1993 *to_nxt = static_cast<uint32_t>(t);
1994 frm_nxt += 3;
1995 }
1996 else if (c1 < 0xF5)
1997 {
1998 if (frm_end-frm_nxt < 4)
1999 return codecvt_base::partial;
2000 uint8_t c2 = frm_nxt[1];
2001 uint8_t c3 = frm_nxt[2];
2002 uint8_t c4 = frm_nxt[3];
2003 switch (c1)
2004 {
2005 case 0xF0:
2006 if (!(0x90 <= c2 && c2 <= 0xBF))
2007 return codecvt_base::error;
2008 break;
2009 case 0xF4:
2010 if ((c2 & 0xF0) != 0x80)
2011 return codecvt_base::error;
2012 break;
2013 default:
2014 if ((c2 & 0xC0) != 0x80)
2015 return codecvt_base::error;
2016 break;
2017 }
2018 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2019 return codecvt_base::error;
2020 if (to_end-to_nxt < 2)
2021 return codecvt_base::partial;
2022 if (((((unsigned long)c1 & 7) << 18) +
2023 (((unsigned long)c2 & 0x3F) << 12) +
2024 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2025 return codecvt_base::error;
2026 *to_nxt = static_cast<uint32_t>(
2027 0xD800
2028 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2029 | ((c2 & 0x0F) << 2)
2030 | ((c3 & 0x30) >> 4));
2031 *++to_nxt = static_cast<uint32_t>(
2032 0xDC00
2033 | ((c3 & 0x0F) << 6)
2034 | (c4 & 0x3F));
2035 frm_nxt += 4;
2036 }
2037 else
2038 {
2039 return codecvt_base::error;
2040 }
2041 }
2042 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2043}
2044
2045static
2046int
2047utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2048 size_t mx, unsigned long Maxcode = 0x10FFFF,
2049 codecvt_mode mode = codecvt_mode(0))
2050{
2051 const uint8_t* frm_nxt = frm;
2052 if (mode & consume_header)
2053 {
2054 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2055 frm_nxt[2] == 0xBF)
2056 frm_nxt += 3;
2057 }
2058 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2059 {
2060 uint8_t c1 = *frm_nxt;
2061 if (c1 > Maxcode)
2062 break;
2063 if (c1 < 0x80)
2064 {
2065 ++frm_nxt;
2066 }
2067 else if (c1 < 0xC2)
2068 {
2069 break;
2070 }
2071 else if (c1 < 0xE0)
2072 {
2073 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2074 break;
2075 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2076 if (t > Maxcode)
2077 break;
2078 frm_nxt += 2;
2079 }
2080 else if (c1 < 0xF0)
2081 {
2082 if (frm_end-frm_nxt < 3)
2083 break;
2084 uint8_t c2 = frm_nxt[1];
2085 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002086 switch (c1)
2087 {
2088 case 0xE0:
2089 if ((c2 & 0xE0) != 0xA0)
2090 return static_cast<int>(frm_nxt - frm);
2091 break;
2092 case 0xED:
2093 if ((c2 & 0xE0) != 0x80)
2094 return static_cast<int>(frm_nxt - frm);
2095 break;
2096 default:
2097 if ((c2 & 0xC0) != 0x80)
2098 return static_cast<int>(frm_nxt - frm);
2099 break;
2100 }
2101 if ((c3 & 0xC0) != 0x80)
2102 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002103 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002104 break;
2105 frm_nxt += 3;
2106 }
2107 else if (c1 < 0xF5)
2108 {
2109 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2110 break;
2111 uint8_t c2 = frm_nxt[1];
2112 uint8_t c3 = frm_nxt[2];
2113 uint8_t c4 = frm_nxt[3];
2114 switch (c1)
2115 {
2116 case 0xF0:
2117 if (!(0x90 <= c2 && c2 <= 0xBF))
2118 return static_cast<int>(frm_nxt - frm);
2119 break;
2120 case 0xF4:
2121 if ((c2 & 0xF0) != 0x80)
2122 return static_cast<int>(frm_nxt - frm);
2123 break;
2124 default:
2125 if ((c2 & 0xC0) != 0x80)
2126 return static_cast<int>(frm_nxt - frm);
2127 break;
2128 }
2129 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2130 break;
2131 if (((((unsigned long)c1 & 7) << 18) +
2132 (((unsigned long)c2 & 0x3F) << 12) +
2133 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2134 break;
2135 ++nchar16_t;
2136 frm_nxt += 4;
2137 }
2138 else
2139 {
2140 break;
2141 }
2142 }
2143 return static_cast<int>(frm_nxt - frm);
2144}
2145
2146static
2147codecvt_base::result
2148ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2149 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2150 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2151{
2152 frm_nxt = frm;
2153 to_nxt = to;
2154 if (mode & generate_header)
2155 {
2156 if (to_end-to_nxt < 3)
2157 return codecvt_base::partial;
2158 *to_nxt++ = static_cast<uint8_t>(0xEF);
2159 *to_nxt++ = static_cast<uint8_t>(0xBB);
2160 *to_nxt++ = static_cast<uint8_t>(0xBF);
2161 }
2162 for (; frm_nxt < frm_end; ++frm_nxt)
2163 {
2164 uint32_t wc = *frm_nxt;
2165 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2166 return codecvt_base::error;
2167 if (wc < 0x000080)
2168 {
2169 if (to_end-to_nxt < 1)
2170 return codecvt_base::partial;
2171 *to_nxt++ = static_cast<uint8_t>(wc);
2172 }
2173 else if (wc < 0x000800)
2174 {
2175 if (to_end-to_nxt < 2)
2176 return codecvt_base::partial;
2177 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2178 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2179 }
2180 else if (wc < 0x010000)
2181 {
2182 if (to_end-to_nxt < 3)
2183 return codecvt_base::partial;
2184 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2185 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2186 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2187 }
2188 else // if (wc < 0x110000)
2189 {
2190 if (to_end-to_nxt < 4)
2191 return codecvt_base::partial;
2192 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2193 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2194 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2195 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2196 }
2197 }
2198 return codecvt_base::ok;
2199}
2200
2201static
2202codecvt_base::result
2203utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2204 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2205 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2206{
2207 frm_nxt = frm;
2208 to_nxt = to;
2209 if (mode & consume_header)
2210 {
2211 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2212 frm_nxt[2] == 0xBF)
2213 frm_nxt += 3;
2214 }
2215 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2216 {
2217 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2218 if (c1 < 0x80)
2219 {
2220 if (c1 > Maxcode)
2221 return codecvt_base::error;
2222 *to_nxt = static_cast<uint32_t>(c1);
2223 ++frm_nxt;
2224 }
2225 else if (c1 < 0xC2)
2226 {
2227 return codecvt_base::error;
2228 }
2229 else if (c1 < 0xE0)
2230 {
2231 if (frm_end-frm_nxt < 2)
2232 return codecvt_base::partial;
2233 uint8_t c2 = frm_nxt[1];
2234 if ((c2 & 0xC0) != 0x80)
2235 return codecvt_base::error;
2236 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2237 | (c2 & 0x3F));
2238 if (t > Maxcode)
2239 return codecvt_base::error;
2240 *to_nxt = t;
2241 frm_nxt += 2;
2242 }
2243 else if (c1 < 0xF0)
2244 {
2245 if (frm_end-frm_nxt < 3)
2246 return codecvt_base::partial;
2247 uint8_t c2 = frm_nxt[1];
2248 uint8_t c3 = frm_nxt[2];
2249 switch (c1)
2250 {
2251 case 0xE0:
2252 if ((c2 & 0xE0) != 0xA0)
2253 return codecvt_base::error;
2254 break;
2255 case 0xED:
2256 if ((c2 & 0xE0) != 0x80)
2257 return codecvt_base::error;
2258 break;
2259 default:
2260 if ((c2 & 0xC0) != 0x80)
2261 return codecvt_base::error;
2262 break;
2263 }
2264 if ((c3 & 0xC0) != 0x80)
2265 return codecvt_base::error;
2266 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2267 | ((c2 & 0x3F) << 6)
2268 | (c3 & 0x3F));
2269 if (t > Maxcode)
2270 return codecvt_base::error;
2271 *to_nxt = t;
2272 frm_nxt += 3;
2273 }
2274 else if (c1 < 0xF5)
2275 {
2276 if (frm_end-frm_nxt < 4)
2277 return codecvt_base::partial;
2278 uint8_t c2 = frm_nxt[1];
2279 uint8_t c3 = frm_nxt[2];
2280 uint8_t c4 = frm_nxt[3];
2281 switch (c1)
2282 {
2283 case 0xF0:
2284 if (!(0x90 <= c2 && c2 <= 0xBF))
2285 return codecvt_base::error;
2286 break;
2287 case 0xF4:
2288 if ((c2 & 0xF0) != 0x80)
2289 return codecvt_base::error;
2290 break;
2291 default:
2292 if ((c2 & 0xC0) != 0x80)
2293 return codecvt_base::error;
2294 break;
2295 }
2296 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2297 return codecvt_base::error;
2298 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2299 | ((c2 & 0x3F) << 12)
2300 | ((c3 & 0x3F) << 6)
2301 | (c4 & 0x3F));
2302 if (t > Maxcode)
2303 return codecvt_base::error;
2304 *to_nxt = t;
2305 frm_nxt += 4;
2306 }
2307 else
2308 {
2309 return codecvt_base::error;
2310 }
2311 }
2312 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2313}
2314
2315static
2316int
2317utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2318 size_t mx, unsigned long Maxcode = 0x10FFFF,
2319 codecvt_mode mode = codecvt_mode(0))
2320{
2321 const uint8_t* frm_nxt = frm;
2322 if (mode & consume_header)
2323 {
2324 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2325 frm_nxt[2] == 0xBF)
2326 frm_nxt += 3;
2327 }
2328 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2329 {
2330 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2331 if (c1 < 0x80)
2332 {
2333 if (c1 > Maxcode)
2334 break;
2335 ++frm_nxt;
2336 }
2337 else if (c1 < 0xC2)
2338 {
2339 break;
2340 }
2341 else if (c1 < 0xE0)
2342 {
2343 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2344 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002345 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002346 break;
2347 frm_nxt += 2;
2348 }
2349 else if (c1 < 0xF0)
2350 {
2351 if (frm_end-frm_nxt < 3)
2352 break;
2353 uint8_t c2 = frm_nxt[1];
2354 uint8_t c3 = frm_nxt[2];
2355 switch (c1)
2356 {
2357 case 0xE0:
2358 if ((c2 & 0xE0) != 0xA0)
2359 return static_cast<int>(frm_nxt - frm);
2360 break;
2361 case 0xED:
2362 if ((c2 & 0xE0) != 0x80)
2363 return static_cast<int>(frm_nxt - frm);
2364 break;
2365 default:
2366 if ((c2 & 0xC0) != 0x80)
2367 return static_cast<int>(frm_nxt - frm);
2368 break;
2369 }
2370 if ((c3 & 0xC0) != 0x80)
2371 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002372 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002373 break;
2374 frm_nxt += 3;
2375 }
2376 else if (c1 < 0xF5)
2377 {
2378 if (frm_end-frm_nxt < 4)
2379 break;
2380 uint8_t c2 = frm_nxt[1];
2381 uint8_t c3 = frm_nxt[2];
2382 uint8_t c4 = frm_nxt[3];
2383 switch (c1)
2384 {
2385 case 0xF0:
2386 if (!(0x90 <= c2 && c2 <= 0xBF))
2387 return static_cast<int>(frm_nxt - frm);
2388 break;
2389 case 0xF4:
2390 if ((c2 & 0xF0) != 0x80)
2391 return static_cast<int>(frm_nxt - frm);
2392 break;
2393 default:
2394 if ((c2 & 0xC0) != 0x80)
2395 return static_cast<int>(frm_nxt - frm);
2396 break;
2397 }
2398 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2399 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002400 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2401 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002402 break;
2403 frm_nxt += 4;
2404 }
2405 else
2406 {
2407 break;
2408 }
2409 }
2410 return static_cast<int>(frm_nxt - frm);
2411}
2412
2413static
2414codecvt_base::result
2415ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2416 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2417 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2418{
2419 frm_nxt = frm;
2420 to_nxt = to;
2421 if (mode & generate_header)
2422 {
2423 if (to_end-to_nxt < 3)
2424 return codecvt_base::partial;
2425 *to_nxt++ = static_cast<uint8_t>(0xEF);
2426 *to_nxt++ = static_cast<uint8_t>(0xBB);
2427 *to_nxt++ = static_cast<uint8_t>(0xBF);
2428 }
2429 for (; frm_nxt < frm_end; ++frm_nxt)
2430 {
2431 uint16_t wc = *frm_nxt;
2432 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2433 return codecvt_base::error;
2434 if (wc < 0x0080)
2435 {
2436 if (to_end-to_nxt < 1)
2437 return codecvt_base::partial;
2438 *to_nxt++ = static_cast<uint8_t>(wc);
2439 }
2440 else if (wc < 0x0800)
2441 {
2442 if (to_end-to_nxt < 2)
2443 return codecvt_base::partial;
2444 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2445 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2446 }
2447 else // if (wc <= 0xFFFF)
2448 {
2449 if (to_end-to_nxt < 3)
2450 return codecvt_base::partial;
2451 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2452 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2453 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2454 }
2455 }
2456 return codecvt_base::ok;
2457}
2458
2459static
2460codecvt_base::result
2461utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2462 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2463 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2464{
2465 frm_nxt = frm;
2466 to_nxt = to;
2467 if (mode & consume_header)
2468 {
2469 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2470 frm_nxt[2] == 0xBF)
2471 frm_nxt += 3;
2472 }
2473 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2474 {
2475 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2476 if (c1 < 0x80)
2477 {
2478 if (c1 > Maxcode)
2479 return codecvt_base::error;
2480 *to_nxt = static_cast<uint16_t>(c1);
2481 ++frm_nxt;
2482 }
2483 else if (c1 < 0xC2)
2484 {
2485 return codecvt_base::error;
2486 }
2487 else if (c1 < 0xE0)
2488 {
2489 if (frm_end-frm_nxt < 2)
2490 return codecvt_base::partial;
2491 uint8_t c2 = frm_nxt[1];
2492 if ((c2 & 0xC0) != 0x80)
2493 return codecvt_base::error;
2494 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2495 | (c2 & 0x3F));
2496 if (t > Maxcode)
2497 return codecvt_base::error;
2498 *to_nxt = t;
2499 frm_nxt += 2;
2500 }
2501 else if (c1 < 0xF0)
2502 {
2503 if (frm_end-frm_nxt < 3)
2504 return codecvt_base::partial;
2505 uint8_t c2 = frm_nxt[1];
2506 uint8_t c3 = frm_nxt[2];
2507 switch (c1)
2508 {
2509 case 0xE0:
2510 if ((c2 & 0xE0) != 0xA0)
2511 return codecvt_base::error;
2512 break;
2513 case 0xED:
2514 if ((c2 & 0xE0) != 0x80)
2515 return codecvt_base::error;
2516 break;
2517 default:
2518 if ((c2 & 0xC0) != 0x80)
2519 return codecvt_base::error;
2520 break;
2521 }
2522 if ((c3 & 0xC0) != 0x80)
2523 return codecvt_base::error;
2524 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2525 | ((c2 & 0x3F) << 6)
2526 | (c3 & 0x3F));
2527 if (t > Maxcode)
2528 return codecvt_base::error;
2529 *to_nxt = t;
2530 frm_nxt += 3;
2531 }
2532 else
2533 {
2534 return codecvt_base::error;
2535 }
2536 }
2537 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2538}
2539
2540static
2541int
2542utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2543 size_t mx, unsigned long Maxcode = 0x10FFFF,
2544 codecvt_mode mode = codecvt_mode(0))
2545{
2546 const uint8_t* frm_nxt = frm;
2547 if (mode & consume_header)
2548 {
2549 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2550 frm_nxt[2] == 0xBF)
2551 frm_nxt += 3;
2552 }
2553 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2554 {
2555 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2556 if (c1 < 0x80)
2557 {
2558 if (c1 > Maxcode)
2559 break;
2560 ++frm_nxt;
2561 }
2562 else if (c1 < 0xC2)
2563 {
2564 break;
2565 }
2566 else if (c1 < 0xE0)
2567 {
2568 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2569 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002570 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002571 break;
2572 frm_nxt += 2;
2573 }
2574 else if (c1 < 0xF0)
2575 {
2576 if (frm_end-frm_nxt < 3)
2577 break;
2578 uint8_t c2 = frm_nxt[1];
2579 uint8_t c3 = frm_nxt[2];
2580 switch (c1)
2581 {
2582 case 0xE0:
2583 if ((c2 & 0xE0) != 0xA0)
2584 return static_cast<int>(frm_nxt - frm);
2585 break;
2586 case 0xED:
2587 if ((c2 & 0xE0) != 0x80)
2588 return static_cast<int>(frm_nxt - frm);
2589 break;
2590 default:
2591 if ((c2 & 0xC0) != 0x80)
2592 return static_cast<int>(frm_nxt - frm);
2593 break;
2594 }
2595 if ((c3 & 0xC0) != 0x80)
2596 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002597 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002598 break;
2599 frm_nxt += 3;
2600 }
2601 else
2602 {
2603 break;
2604 }
2605 }
2606 return static_cast<int>(frm_nxt - frm);
2607}
2608
2609static
2610codecvt_base::result
2611ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2612 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2613 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2614{
2615 frm_nxt = frm;
2616 to_nxt = to;
2617 if (mode & generate_header)
2618 {
2619 if (to_end-to_nxt < 2)
2620 return codecvt_base::partial;
2621 *to_nxt++ = static_cast<uint8_t>(0xFE);
2622 *to_nxt++ = static_cast<uint8_t>(0xFF);
2623 }
2624 for (; frm_nxt < frm_end; ++frm_nxt)
2625 {
2626 uint32_t wc = *frm_nxt;
2627 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2628 return codecvt_base::error;
2629 if (wc < 0x010000)
2630 {
2631 if (to_end-to_nxt < 2)
2632 return codecvt_base::partial;
2633 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2634 *to_nxt++ = static_cast<uint8_t>(wc);
2635 }
2636 else
2637 {
2638 if (to_end-to_nxt < 4)
2639 return codecvt_base::partial;
2640 uint16_t t = static_cast<uint16_t>(
2641 0xD800
2642 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2643 | ((wc & 0x00FC00) >> 10));
2644 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2645 *to_nxt++ = static_cast<uint8_t>(t);
2646 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2647 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2648 *to_nxt++ = static_cast<uint8_t>(t);
2649 }
2650 }
2651 return codecvt_base::ok;
2652}
2653
2654static
2655codecvt_base::result
2656utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2657 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2658 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2659{
2660 frm_nxt = frm;
2661 to_nxt = to;
2662 if (mode & consume_header)
2663 {
2664 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2665 frm_nxt += 2;
2666 }
2667 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2668 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002669 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002670 if ((c1 & 0xFC00) == 0xDC00)
2671 return codecvt_base::error;
2672 if ((c1 & 0xFC00) != 0xD800)
2673 {
2674 if (c1 > Maxcode)
2675 return codecvt_base::error;
2676 *to_nxt = static_cast<uint32_t>(c1);
2677 frm_nxt += 2;
2678 }
2679 else
2680 {
2681 if (frm_end-frm_nxt < 4)
2682 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002683 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002684 if ((c2 & 0xFC00) != 0xDC00)
2685 return codecvt_base::error;
2686 uint32_t t = static_cast<uint32_t>(
2687 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2688 | ((c1 & 0x003F) << 10)
2689 | (c2 & 0x03FF));
2690 if (t > Maxcode)
2691 return codecvt_base::error;
2692 *to_nxt = t;
2693 frm_nxt += 4;
2694 }
2695 }
2696 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2697}
2698
2699static
2700int
2701utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2702 size_t mx, unsigned long Maxcode = 0x10FFFF,
2703 codecvt_mode mode = codecvt_mode(0))
2704{
2705 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002706 if (mode & consume_header)
2707 {
2708 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2709 frm_nxt += 2;
2710 }
2711 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2712 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002713 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002714 if ((c1 & 0xFC00) == 0xDC00)
2715 break;
2716 if ((c1 & 0xFC00) != 0xD800)
2717 {
2718 if (c1 > Maxcode)
2719 break;
2720 frm_nxt += 2;
2721 }
2722 else
2723 {
2724 if (frm_end-frm_nxt < 4)
2725 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002726 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002727 if ((c2 & 0xFC00) != 0xDC00)
2728 break;
2729 uint32_t t = static_cast<uint32_t>(
2730 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2731 | ((c1 & 0x003F) << 10)
2732 | (c2 & 0x03FF));
2733 if (t > Maxcode)
2734 break;
2735 frm_nxt += 4;
2736 }
2737 }
2738 return static_cast<int>(frm_nxt - frm);
2739}
2740
2741static
2742codecvt_base::result
2743ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2744 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2745 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2746{
2747 frm_nxt = frm;
2748 to_nxt = to;
2749 if (mode & generate_header)
2750 {
2751 if (to_end-to_nxt < 2)
2752 return codecvt_base::partial;
2753 *to_nxt++ = static_cast<uint8_t>(0xFF);
2754 *to_nxt++ = static_cast<uint8_t>(0xFE);
2755 }
2756 for (; frm_nxt < frm_end; ++frm_nxt)
2757 {
2758 uint32_t wc = *frm_nxt;
2759 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2760 return codecvt_base::error;
2761 if (wc < 0x010000)
2762 {
2763 if (to_end-to_nxt < 2)
2764 return codecvt_base::partial;
2765 *to_nxt++ = static_cast<uint8_t>(wc);
2766 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2767 }
2768 else
2769 {
2770 if (to_end-to_nxt < 4)
2771 return codecvt_base::partial;
2772 uint16_t t = static_cast<uint16_t>(
2773 0xD800
2774 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2775 | ((wc & 0x00FC00) >> 10));
2776 *to_nxt++ = static_cast<uint8_t>(t);
2777 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2778 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2779 *to_nxt++ = static_cast<uint8_t>(t);
2780 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2781 }
2782 }
2783 return codecvt_base::ok;
2784}
2785
2786static
2787codecvt_base::result
2788utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2789 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2790 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2791{
2792 frm_nxt = frm;
2793 to_nxt = to;
2794 if (mode & consume_header)
2795 {
2796 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2797 frm_nxt += 2;
2798 }
2799 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2800 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002801 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002802 if ((c1 & 0xFC00) == 0xDC00)
2803 return codecvt_base::error;
2804 if ((c1 & 0xFC00) != 0xD800)
2805 {
2806 if (c1 > Maxcode)
2807 return codecvt_base::error;
2808 *to_nxt = static_cast<uint32_t>(c1);
2809 frm_nxt += 2;
2810 }
2811 else
2812 {
2813 if (frm_end-frm_nxt < 4)
2814 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002815 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002816 if ((c2 & 0xFC00) != 0xDC00)
2817 return codecvt_base::error;
2818 uint32_t t = static_cast<uint32_t>(
2819 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2820 | ((c1 & 0x003F) << 10)
2821 | (c2 & 0x03FF));
2822 if (t > Maxcode)
2823 return codecvt_base::error;
2824 *to_nxt = t;
2825 frm_nxt += 4;
2826 }
2827 }
2828 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2829}
2830
2831static
2832int
2833utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2834 size_t mx, unsigned long Maxcode = 0x10FFFF,
2835 codecvt_mode mode = codecvt_mode(0))
2836{
2837 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002838 if (mode & consume_header)
2839 {
2840 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2841 frm_nxt += 2;
2842 }
2843 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2844 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002845 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002846 if ((c1 & 0xFC00) == 0xDC00)
2847 break;
2848 if ((c1 & 0xFC00) != 0xD800)
2849 {
2850 if (c1 > Maxcode)
2851 break;
2852 frm_nxt += 2;
2853 }
2854 else
2855 {
2856 if (frm_end-frm_nxt < 4)
2857 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002858 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002859 if ((c2 & 0xFC00) != 0xDC00)
2860 break;
2861 uint32_t t = static_cast<uint32_t>(
2862 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2863 | ((c1 & 0x003F) << 10)
2864 | (c2 & 0x03FF));
2865 if (t > Maxcode)
2866 break;
2867 frm_nxt += 4;
2868 }
2869 }
2870 return static_cast<int>(frm_nxt - frm);
2871}
2872
2873static
2874codecvt_base::result
2875ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2876 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2877 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2878{
2879 frm_nxt = frm;
2880 to_nxt = to;
2881 if (mode & generate_header)
2882 {
2883 if (to_end-to_nxt < 2)
2884 return codecvt_base::partial;
2885 *to_nxt++ = static_cast<uint8_t>(0xFE);
2886 *to_nxt++ = static_cast<uint8_t>(0xFF);
2887 }
2888 for (; frm_nxt < frm_end; ++frm_nxt)
2889 {
2890 uint16_t wc = *frm_nxt;
2891 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2892 return codecvt_base::error;
2893 if (to_end-to_nxt < 2)
2894 return codecvt_base::partial;
2895 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2896 *to_nxt++ = static_cast<uint8_t>(wc);
2897 }
2898 return codecvt_base::ok;
2899}
2900
2901static
2902codecvt_base::result
2903utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2904 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2905 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2906{
2907 frm_nxt = frm;
2908 to_nxt = to;
2909 if (mode & consume_header)
2910 {
2911 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2912 frm_nxt += 2;
2913 }
2914 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2915 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002916 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002917 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2918 return codecvt_base::error;
2919 *to_nxt = c1;
2920 frm_nxt += 2;
2921 }
2922 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2923}
2924
2925static
2926int
2927utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2928 size_t mx, unsigned long Maxcode = 0x10FFFF,
2929 codecvt_mode mode = codecvt_mode(0))
2930{
2931 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002932 if (mode & consume_header)
2933 {
2934 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2935 frm_nxt += 2;
2936 }
2937 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2938 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002939 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002940 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2941 break;
2942 frm_nxt += 2;
2943 }
2944 return static_cast<int>(frm_nxt - frm);
2945}
2946
2947static
2948codecvt_base::result
2949ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2950 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2951 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2952{
2953 frm_nxt = frm;
2954 to_nxt = to;
2955 if (mode & generate_header)
2956 {
2957 if (to_end-to_nxt < 2)
2958 return codecvt_base::partial;
2959 *to_nxt++ = static_cast<uint8_t>(0xFF);
2960 *to_nxt++ = static_cast<uint8_t>(0xFE);
2961 }
2962 for (; frm_nxt < frm_end; ++frm_nxt)
2963 {
2964 uint16_t wc = *frm_nxt;
2965 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2966 return codecvt_base::error;
2967 if (to_end-to_nxt < 2)
2968 return codecvt_base::partial;
2969 *to_nxt++ = static_cast<uint8_t>(wc);
2970 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2971 }
2972 return codecvt_base::ok;
2973}
2974
2975static
2976codecvt_base::result
2977utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2978 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2979 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2980{
2981 frm_nxt = frm;
2982 to_nxt = to;
2983 if (mode & consume_header)
2984 {
2985 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2986 frm_nxt += 2;
2987 }
2988 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2989 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002990 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002991 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2992 return codecvt_base::error;
2993 *to_nxt = c1;
2994 frm_nxt += 2;
2995 }
2996 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2997}
2998
2999static
3000int
3001utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3002 size_t mx, unsigned long Maxcode = 0x10FFFF,
3003 codecvt_mode mode = codecvt_mode(0))
3004{
3005 const uint8_t* frm_nxt = frm;
3006 frm_nxt = frm;
3007 if (mode & consume_header)
3008 {
3009 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3010 frm_nxt += 2;
3011 }
3012 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3013 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003014 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003015 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3016 break;
3017 frm_nxt += 2;
3018 }
3019 return static_cast<int>(frm_nxt - frm);
3020}
3021
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003022// template <> class codecvt<char16_t, char, mbstate_t>
3023
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003024locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003025
3026codecvt<char16_t, char, mbstate_t>::~codecvt()
3027{
3028}
3029
3030codecvt<char16_t, char, mbstate_t>::result
3031codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003032 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003033 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3034{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003035 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3036 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3037 const uint16_t* _frm_nxt = _frm;
3038 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3039 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3040 uint8_t* _to_nxt = _to;
3041 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3042 frm_nxt = frm + (_frm_nxt - _frm);
3043 to_nxt = to + (_to_nxt - _to);
3044 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003045}
3046
3047codecvt<char16_t, char, mbstate_t>::result
3048codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003049 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003050 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3051{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003052 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3053 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3054 const uint8_t* _frm_nxt = _frm;
3055 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3056 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3057 uint16_t* _to_nxt = _to;
3058 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3059 frm_nxt = frm + (_frm_nxt - _frm);
3060 to_nxt = to + (_to_nxt - _to);
3061 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003062}
3063
3064codecvt<char16_t, char, mbstate_t>::result
3065codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3066 extern_type* to, extern_type*, extern_type*& to_nxt) const
3067{
3068 to_nxt = to;
3069 return noconv;
3070}
3071
3072int
Howard Hinnantc9834542011-05-31 15:34:58 +00003073codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003074{
3075 return 0;
3076}
3077
3078bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003079codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003080{
3081 return false;
3082}
3083
3084int
3085codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3086 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3087{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003088 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3089 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3090 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003091}
3092
3093int
Howard Hinnantc9834542011-05-31 15:34:58 +00003094codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003095{
3096 return 4;
3097}
3098
3099// template <> class codecvt<char32_t, char, mbstate_t>
3100
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003101locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003102
3103codecvt<char32_t, char, mbstate_t>::~codecvt()
3104{
3105}
3106
3107codecvt<char32_t, char, mbstate_t>::result
3108codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003109 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003110 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3111{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003112 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3113 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3114 const uint32_t* _frm_nxt = _frm;
3115 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3116 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3117 uint8_t* _to_nxt = _to;
3118 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3119 frm_nxt = frm + (_frm_nxt - _frm);
3120 to_nxt = to + (_to_nxt - _to);
3121 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003122}
3123
3124codecvt<char32_t, char, mbstate_t>::result
3125codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003126 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003127 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3128{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003129 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3130 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3131 const uint8_t* _frm_nxt = _frm;
3132 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3133 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3134 uint32_t* _to_nxt = _to;
3135 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3136 frm_nxt = frm + (_frm_nxt - _frm);
3137 to_nxt = to + (_to_nxt - _to);
3138 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003139}
3140
3141codecvt<char32_t, char, mbstate_t>::result
3142codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3143 extern_type* to, extern_type*, extern_type*& to_nxt) const
3144{
3145 to_nxt = to;
3146 return noconv;
3147}
3148
3149int
Howard Hinnantc9834542011-05-31 15:34:58 +00003150codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003151{
3152 return 0;
3153}
3154
3155bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003156codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003157{
3158 return false;
3159}
3160
3161int
3162codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3163 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3164{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003165 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3166 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3167 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003168}
3169
3170int
Howard Hinnantc9834542011-05-31 15:34:58 +00003171codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003172{
3173 return 4;
3174}
3175
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003176// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003177
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003178__codecvt_utf8<wchar_t>::result
3179__codecvt_utf8<wchar_t>::do_out(state_type&,
3180 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003181 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3182{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003183 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3184 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3185 const uint32_t* _frm_nxt = _frm;
3186 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3187 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3188 uint8_t* _to_nxt = _to;
3189 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3190 _Maxcode_, _Mode_);
3191 frm_nxt = frm + (_frm_nxt - _frm);
3192 to_nxt = to + (_to_nxt - _to);
3193 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003194}
3195
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003196__codecvt_utf8<wchar_t>::result
3197__codecvt_utf8<wchar_t>::do_in(state_type&,
3198 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003199 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3200{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003201 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3202 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3203 const uint8_t* _frm_nxt = _frm;
3204 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3205 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3206 uint32_t* _to_nxt = _to;
3207 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3208 _Maxcode_, _Mode_);
3209 frm_nxt = frm + (_frm_nxt - _frm);
3210 to_nxt = to + (_to_nxt - _to);
3211 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003212}
3213
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003214__codecvt_utf8<wchar_t>::result
3215__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003216 extern_type* to, extern_type*, extern_type*& to_nxt) const
3217{
3218 to_nxt = to;
3219 return noconv;
3220}
3221
3222int
Howard Hinnantc9834542011-05-31 15:34:58 +00003223__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003224{
3225 return 0;
3226}
3227
3228bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003229__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003230{
3231 return false;
3232}
3233
3234int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003235__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003236 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3237{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003238 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3239 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3240 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003241}
3242
3243int
Howard Hinnantc9834542011-05-31 15:34:58 +00003244__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003245{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003246 if (_Mode_ & consume_header)
3247 return 7;
3248 return 4;
3249}
3250
3251// __codecvt_utf8<char16_t>
3252
3253__codecvt_utf8<char16_t>::result
3254__codecvt_utf8<char16_t>::do_out(state_type&,
3255 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3256 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3257{
3258 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3259 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3260 const uint16_t* _frm_nxt = _frm;
3261 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3262 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3263 uint8_t* _to_nxt = _to;
3264 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3265 _Maxcode_, _Mode_);
3266 frm_nxt = frm + (_frm_nxt - _frm);
3267 to_nxt = to + (_to_nxt - _to);
3268 return r;
3269}
3270
3271__codecvt_utf8<char16_t>::result
3272__codecvt_utf8<char16_t>::do_in(state_type&,
3273 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3274 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3275{
3276 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3277 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3278 const uint8_t* _frm_nxt = _frm;
3279 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3280 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3281 uint16_t* _to_nxt = _to;
3282 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3283 _Maxcode_, _Mode_);
3284 frm_nxt = frm + (_frm_nxt - _frm);
3285 to_nxt = to + (_to_nxt - _to);
3286 return r;
3287}
3288
3289__codecvt_utf8<char16_t>::result
3290__codecvt_utf8<char16_t>::do_unshift(state_type&,
3291 extern_type* to, extern_type*, extern_type*& to_nxt) const
3292{
3293 to_nxt = to;
3294 return noconv;
3295}
3296
3297int
Howard Hinnantc9834542011-05-31 15:34:58 +00003298__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003299{
3300 return 0;
3301}
3302
3303bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003304__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003305{
3306 return false;
3307}
3308
3309int
3310__codecvt_utf8<char16_t>::do_length(state_type&,
3311 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3312{
3313 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3314 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3315 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3316}
3317
3318int
Howard Hinnantc9834542011-05-31 15:34:58 +00003319__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003320{
3321 if (_Mode_ & consume_header)
3322 return 6;
3323 return 3;
3324}
3325
3326// __codecvt_utf8<char32_t>
3327
3328__codecvt_utf8<char32_t>::result
3329__codecvt_utf8<char32_t>::do_out(state_type&,
3330 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3331 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3332{
3333 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3334 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3335 const uint32_t* _frm_nxt = _frm;
3336 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3337 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3338 uint8_t* _to_nxt = _to;
3339 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3340 _Maxcode_, _Mode_);
3341 frm_nxt = frm + (_frm_nxt - _frm);
3342 to_nxt = to + (_to_nxt - _to);
3343 return r;
3344}
3345
3346__codecvt_utf8<char32_t>::result
3347__codecvt_utf8<char32_t>::do_in(state_type&,
3348 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3349 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3350{
3351 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3352 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3353 const uint8_t* _frm_nxt = _frm;
3354 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3355 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3356 uint32_t* _to_nxt = _to;
3357 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3358 _Maxcode_, _Mode_);
3359 frm_nxt = frm + (_frm_nxt - _frm);
3360 to_nxt = to + (_to_nxt - _to);
3361 return r;
3362}
3363
3364__codecvt_utf8<char32_t>::result
3365__codecvt_utf8<char32_t>::do_unshift(state_type&,
3366 extern_type* to, extern_type*, extern_type*& to_nxt) const
3367{
3368 to_nxt = to;
3369 return noconv;
3370}
3371
3372int
Howard Hinnantc9834542011-05-31 15:34:58 +00003373__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003374{
3375 return 0;
3376}
3377
3378bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003379__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003380{
3381 return false;
3382}
3383
3384int
3385__codecvt_utf8<char32_t>::do_length(state_type&,
3386 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3387{
3388 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3389 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3390 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3391}
3392
3393int
Howard Hinnantc9834542011-05-31 15:34:58 +00003394__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003395{
3396 if (_Mode_ & consume_header)
3397 return 7;
3398 return 4;
3399}
3400
3401// __codecvt_utf16<wchar_t, false>
3402
3403__codecvt_utf16<wchar_t, false>::result
3404__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3405 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3406 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3407{
3408 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3409 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3410 const uint32_t* _frm_nxt = _frm;
3411 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3412 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3413 uint8_t* _to_nxt = _to;
3414 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3415 _Maxcode_, _Mode_);
3416 frm_nxt = frm + (_frm_nxt - _frm);
3417 to_nxt = to + (_to_nxt - _to);
3418 return r;
3419}
3420
3421__codecvt_utf16<wchar_t, false>::result
3422__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3423 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3424 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3425{
3426 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3427 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3428 const uint8_t* _frm_nxt = _frm;
3429 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3430 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3431 uint32_t* _to_nxt = _to;
3432 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3433 _Maxcode_, _Mode_);
3434 frm_nxt = frm + (_frm_nxt - _frm);
3435 to_nxt = to + (_to_nxt - _to);
3436 return r;
3437}
3438
3439__codecvt_utf16<wchar_t, false>::result
3440__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3441 extern_type* to, extern_type*, extern_type*& to_nxt) const
3442{
3443 to_nxt = to;
3444 return noconv;
3445}
3446
3447int
Howard Hinnantc9834542011-05-31 15:34:58 +00003448__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003449{
3450 return 0;
3451}
3452
3453bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003454__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003455{
3456 return false;
3457}
3458
3459int
3460__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3461 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3462{
3463 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3464 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3465 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3466}
3467
3468int
Howard Hinnantc9834542011-05-31 15:34:58 +00003469__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003470{
3471 if (_Mode_ & consume_header)
3472 return 6;
3473 return 4;
3474}
3475
3476// __codecvt_utf16<wchar_t, true>
3477
3478__codecvt_utf16<wchar_t, true>::result
3479__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3480 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3481 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3482{
3483 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3484 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3485 const uint32_t* _frm_nxt = _frm;
3486 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3487 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3488 uint8_t* _to_nxt = _to;
3489 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3490 _Maxcode_, _Mode_);
3491 frm_nxt = frm + (_frm_nxt - _frm);
3492 to_nxt = to + (_to_nxt - _to);
3493 return r;
3494}
3495
3496__codecvt_utf16<wchar_t, true>::result
3497__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3498 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3499 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3500{
3501 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3502 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3503 const uint8_t* _frm_nxt = _frm;
3504 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3505 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3506 uint32_t* _to_nxt = _to;
3507 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3508 _Maxcode_, _Mode_);
3509 frm_nxt = frm + (_frm_nxt - _frm);
3510 to_nxt = to + (_to_nxt - _to);
3511 return r;
3512}
3513
3514__codecvt_utf16<wchar_t, true>::result
3515__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3516 extern_type* to, extern_type*, extern_type*& to_nxt) const
3517{
3518 to_nxt = to;
3519 return noconv;
3520}
3521
3522int
Howard Hinnantc9834542011-05-31 15:34:58 +00003523__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003524{
3525 return 0;
3526}
3527
3528bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003529__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003530{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003531 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003532}
3533
3534int
3535__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3536 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3537{
3538 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3539 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3540 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3541}
3542
3543int
Howard Hinnantc9834542011-05-31 15:34:58 +00003544__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003545{
3546 if (_Mode_ & consume_header)
3547 return 6;
3548 return 4;
3549}
3550
3551// __codecvt_utf16<char16_t, false>
3552
3553__codecvt_utf16<char16_t, false>::result
3554__codecvt_utf16<char16_t, false>::do_out(state_type&,
3555 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3556 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3557{
3558 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3559 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3560 const uint16_t* _frm_nxt = _frm;
3561 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3562 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3563 uint8_t* _to_nxt = _to;
3564 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3565 _Maxcode_, _Mode_);
3566 frm_nxt = frm + (_frm_nxt - _frm);
3567 to_nxt = to + (_to_nxt - _to);
3568 return r;
3569}
3570
3571__codecvt_utf16<char16_t, false>::result
3572__codecvt_utf16<char16_t, false>::do_in(state_type&,
3573 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3574 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3575{
3576 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3577 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3578 const uint8_t* _frm_nxt = _frm;
3579 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3580 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3581 uint16_t* _to_nxt = _to;
3582 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3583 _Maxcode_, _Mode_);
3584 frm_nxt = frm + (_frm_nxt - _frm);
3585 to_nxt = to + (_to_nxt - _to);
3586 return r;
3587}
3588
3589__codecvt_utf16<char16_t, false>::result
3590__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3591 extern_type* to, extern_type*, extern_type*& to_nxt) const
3592{
3593 to_nxt = to;
3594 return noconv;
3595}
3596
3597int
Howard Hinnantc9834542011-05-31 15:34:58 +00003598__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003599{
3600 return 0;
3601}
3602
3603bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003604__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003605{
3606 return false;
3607}
3608
3609int
3610__codecvt_utf16<char16_t, false>::do_length(state_type&,
3611 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3612{
3613 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3614 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3615 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3616}
3617
3618int
Howard Hinnantc9834542011-05-31 15:34:58 +00003619__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003620{
3621 if (_Mode_ & consume_header)
3622 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003623 return 2;
3624}
3625
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003626// __codecvt_utf16<char16_t, true>
3627
3628__codecvt_utf16<char16_t, true>::result
3629__codecvt_utf16<char16_t, true>::do_out(state_type&,
3630 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3631 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3632{
3633 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3634 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3635 const uint16_t* _frm_nxt = _frm;
3636 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3637 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3638 uint8_t* _to_nxt = _to;
3639 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3640 _Maxcode_, _Mode_);
3641 frm_nxt = frm + (_frm_nxt - _frm);
3642 to_nxt = to + (_to_nxt - _to);
3643 return r;
3644}
3645
3646__codecvt_utf16<char16_t, true>::result
3647__codecvt_utf16<char16_t, true>::do_in(state_type&,
3648 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3649 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3650{
3651 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3652 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3653 const uint8_t* _frm_nxt = _frm;
3654 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3655 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3656 uint16_t* _to_nxt = _to;
3657 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3658 _Maxcode_, _Mode_);
3659 frm_nxt = frm + (_frm_nxt - _frm);
3660 to_nxt = to + (_to_nxt - _to);
3661 return r;
3662}
3663
3664__codecvt_utf16<char16_t, true>::result
3665__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3666 extern_type* to, extern_type*, extern_type*& to_nxt) const
3667{
3668 to_nxt = to;
3669 return noconv;
3670}
3671
3672int
Howard Hinnantc9834542011-05-31 15:34:58 +00003673__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003674{
3675 return 0;
3676}
3677
3678bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003679__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003680{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003681 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003682}
3683
3684int
3685__codecvt_utf16<char16_t, true>::do_length(state_type&,
3686 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3687{
3688 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3689 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3690 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3691}
3692
3693int
Howard Hinnantc9834542011-05-31 15:34:58 +00003694__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003695{
3696 if (_Mode_ & consume_header)
3697 return 4;
3698 return 2;
3699}
3700
3701// __codecvt_utf16<char32_t, false>
3702
3703__codecvt_utf16<char32_t, false>::result
3704__codecvt_utf16<char32_t, false>::do_out(state_type&,
3705 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3706 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3707{
3708 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3709 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3710 const uint32_t* _frm_nxt = _frm;
3711 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3712 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3713 uint8_t* _to_nxt = _to;
3714 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3715 _Maxcode_, _Mode_);
3716 frm_nxt = frm + (_frm_nxt - _frm);
3717 to_nxt = to + (_to_nxt - _to);
3718 return r;
3719}
3720
3721__codecvt_utf16<char32_t, false>::result
3722__codecvt_utf16<char32_t, false>::do_in(state_type&,
3723 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3724 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3725{
3726 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3727 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3728 const uint8_t* _frm_nxt = _frm;
3729 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3730 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3731 uint32_t* _to_nxt = _to;
3732 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3733 _Maxcode_, _Mode_);
3734 frm_nxt = frm + (_frm_nxt - _frm);
3735 to_nxt = to + (_to_nxt - _to);
3736 return r;
3737}
3738
3739__codecvt_utf16<char32_t, false>::result
3740__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3741 extern_type* to, extern_type*, extern_type*& to_nxt) const
3742{
3743 to_nxt = to;
3744 return noconv;
3745}
3746
3747int
Howard Hinnantc9834542011-05-31 15:34:58 +00003748__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003749{
3750 return 0;
3751}
3752
3753bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003754__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003755{
3756 return false;
3757}
3758
3759int
3760__codecvt_utf16<char32_t, false>::do_length(state_type&,
3761 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3762{
3763 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3764 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3765 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3766}
3767
3768int
Howard Hinnantc9834542011-05-31 15:34:58 +00003769__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003770{
3771 if (_Mode_ & consume_header)
3772 return 6;
3773 return 4;
3774}
3775
3776// __codecvt_utf16<char32_t, true>
3777
3778__codecvt_utf16<char32_t, true>::result
3779__codecvt_utf16<char32_t, true>::do_out(state_type&,
3780 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3781 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3782{
3783 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3784 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3785 const uint32_t* _frm_nxt = _frm;
3786 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3787 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3788 uint8_t* _to_nxt = _to;
3789 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3790 _Maxcode_, _Mode_);
3791 frm_nxt = frm + (_frm_nxt - _frm);
3792 to_nxt = to + (_to_nxt - _to);
3793 return r;
3794}
3795
3796__codecvt_utf16<char32_t, true>::result
3797__codecvt_utf16<char32_t, true>::do_in(state_type&,
3798 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3799 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3800{
3801 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3802 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3803 const uint8_t* _frm_nxt = _frm;
3804 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3805 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3806 uint32_t* _to_nxt = _to;
3807 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3808 _Maxcode_, _Mode_);
3809 frm_nxt = frm + (_frm_nxt - _frm);
3810 to_nxt = to + (_to_nxt - _to);
3811 return r;
3812}
3813
3814__codecvt_utf16<char32_t, true>::result
3815__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3816 extern_type* to, extern_type*, extern_type*& to_nxt) const
3817{
3818 to_nxt = to;
3819 return noconv;
3820}
3821
3822int
Howard Hinnantc9834542011-05-31 15:34:58 +00003823__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003824{
3825 return 0;
3826}
3827
3828bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003829__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003830{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003831 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003832}
3833
3834int
3835__codecvt_utf16<char32_t, true>::do_length(state_type&,
3836 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3837{
3838 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3839 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3840 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3841}
3842
3843int
Howard Hinnantc9834542011-05-31 15:34:58 +00003844__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003845{
3846 if (_Mode_ & consume_header)
3847 return 6;
3848 return 4;
3849}
3850
3851// __codecvt_utf8_utf16<wchar_t>
3852
3853__codecvt_utf8_utf16<wchar_t>::result
3854__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3855 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3856 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3857{
3858 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3859 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3860 const uint32_t* _frm_nxt = _frm;
3861 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3862 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3863 uint8_t* _to_nxt = _to;
3864 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3865 _Maxcode_, _Mode_);
3866 frm_nxt = frm + (_frm_nxt - _frm);
3867 to_nxt = to + (_to_nxt - _to);
3868 return r;
3869}
3870
3871__codecvt_utf8_utf16<wchar_t>::result
3872__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3873 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3874 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3875{
3876 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3877 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3878 const uint8_t* _frm_nxt = _frm;
3879 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3880 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3881 uint32_t* _to_nxt = _to;
3882 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3883 _Maxcode_, _Mode_);
3884 frm_nxt = frm + (_frm_nxt - _frm);
3885 to_nxt = to + (_to_nxt - _to);
3886 return r;
3887}
3888
3889__codecvt_utf8_utf16<wchar_t>::result
3890__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3891 extern_type* to, extern_type*, extern_type*& to_nxt) const
3892{
3893 to_nxt = to;
3894 return noconv;
3895}
3896
3897int
Howard Hinnantc9834542011-05-31 15:34:58 +00003898__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003899{
3900 return 0;
3901}
3902
3903bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003904__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003905{
3906 return false;
3907}
3908
3909int
3910__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3911 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3912{
3913 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3914 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3915 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3916}
3917
3918int
Howard Hinnantc9834542011-05-31 15:34:58 +00003919__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003920{
3921 if (_Mode_ & consume_header)
3922 return 7;
3923 return 4;
3924}
3925
3926// __codecvt_utf8_utf16<char16_t>
3927
3928__codecvt_utf8_utf16<char16_t>::result
3929__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3930 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3931 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3932{
3933 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3934 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3935 const uint16_t* _frm_nxt = _frm;
3936 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3937 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3938 uint8_t* _to_nxt = _to;
3939 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3940 _Maxcode_, _Mode_);
3941 frm_nxt = frm + (_frm_nxt - _frm);
3942 to_nxt = to + (_to_nxt - _to);
3943 return r;
3944}
3945
3946__codecvt_utf8_utf16<char16_t>::result
3947__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3948 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3949 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3950{
3951 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3952 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3953 const uint8_t* _frm_nxt = _frm;
3954 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3955 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3956 uint16_t* _to_nxt = _to;
3957 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3958 _Maxcode_, _Mode_);
3959 frm_nxt = frm + (_frm_nxt - _frm);
3960 to_nxt = to + (_to_nxt - _to);
3961 return r;
3962}
3963
3964__codecvt_utf8_utf16<char16_t>::result
3965__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3966 extern_type* to, extern_type*, extern_type*& to_nxt) const
3967{
3968 to_nxt = to;
3969 return noconv;
3970}
3971
3972int
Howard Hinnantc9834542011-05-31 15:34:58 +00003973__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003974{
3975 return 0;
3976}
3977
3978bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003979__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003980{
3981 return false;
3982}
3983
3984int
3985__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3986 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3987{
3988 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3989 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3990 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3991}
3992
3993int
Howard Hinnantc9834542011-05-31 15:34:58 +00003994__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003995{
3996 if (_Mode_ & consume_header)
3997 return 7;
3998 return 4;
3999}
4000
4001// __codecvt_utf8_utf16<char32_t>
4002
4003__codecvt_utf8_utf16<char32_t>::result
4004__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4005 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4006 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4007{
4008 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4009 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4010 const uint32_t* _frm_nxt = _frm;
4011 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4012 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4013 uint8_t* _to_nxt = _to;
4014 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4015 _Maxcode_, _Mode_);
4016 frm_nxt = frm + (_frm_nxt - _frm);
4017 to_nxt = to + (_to_nxt - _to);
4018 return r;
4019}
4020
4021__codecvt_utf8_utf16<char32_t>::result
4022__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4023 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4024 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4025{
4026 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4027 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4028 const uint8_t* _frm_nxt = _frm;
4029 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4030 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4031 uint32_t* _to_nxt = _to;
4032 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4033 _Maxcode_, _Mode_);
4034 frm_nxt = frm + (_frm_nxt - _frm);
4035 to_nxt = to + (_to_nxt - _to);
4036 return r;
4037}
4038
4039__codecvt_utf8_utf16<char32_t>::result
4040__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4041 extern_type* to, extern_type*, extern_type*& to_nxt) const
4042{
4043 to_nxt = to;
4044 return noconv;
4045}
4046
4047int
Howard Hinnantc9834542011-05-31 15:34:58 +00004048__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004049{
4050 return 0;
4051}
4052
4053bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004054__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004055{
4056 return false;
4057}
4058
4059int
4060__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4061 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4062{
4063 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4064 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4065 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4066}
4067
4068int
Howard Hinnantc9834542011-05-31 15:34:58 +00004069__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004070{
4071 if (_Mode_ & consume_header)
4072 return 7;
4073 return 4;
4074}
4075
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004076// __narrow_to_utf8<16>
4077
4078__narrow_to_utf8<16>::~__narrow_to_utf8()
4079{
4080}
4081
4082// __narrow_to_utf8<32>
4083
4084__narrow_to_utf8<32>::~__narrow_to_utf8()
4085{
4086}
4087
4088// __widen_from_utf8<16>
4089
4090__widen_from_utf8<16>::~__widen_from_utf8()
4091{
4092}
4093
4094// __widen_from_utf8<32>
4095
4096__widen_from_utf8<32>::~__widen_from_utf8()
4097{
4098}
4099
4100// numpunct<char> && numpunct<wchar_t>
4101
4102locale::id numpunct< char >::id;
4103locale::id numpunct<wchar_t>::id;
4104
4105numpunct<char>::numpunct(size_t refs)
4106 : locale::facet(refs),
4107 __decimal_point_('.'),
4108 __thousands_sep_(',')
4109{
4110}
4111
4112numpunct<wchar_t>::numpunct(size_t refs)
4113 : locale::facet(refs),
4114 __decimal_point_(L'.'),
4115 __thousands_sep_(L',')
4116{
4117}
4118
4119numpunct<char>::~numpunct()
4120{
4121}
4122
4123numpunct<wchar_t>::~numpunct()
4124{
4125}
4126
4127 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4128wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4129
4130 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4131wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4132
4133string numpunct< char >::do_grouping() const {return __grouping_;}
4134string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4135
4136 string numpunct< char >::do_truename() const {return "true";}
4137wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4138
4139 string numpunct< char >::do_falsename() const {return "false";}
4140wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4141
4142// numpunct_byname<char>
4143
4144numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4145 : numpunct<char>(refs)
4146{
4147 __init(nm);
4148}
4149
4150numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4151 : numpunct<char>(refs)
4152{
4153 __init(nm.c_str());
4154}
4155
4156numpunct_byname<char>::~numpunct_byname()
4157{
4158}
4159
4160void
4161numpunct_byname<char>::__init(const char* nm)
4162{
4163 if (strcmp(nm, "C") != 0)
4164 {
Sean Huntf3907e62011-07-15 05:40:33 +00004165 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004166#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004167 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004168 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4169 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004170#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004171#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004172 lconv* lc = localeconv_l(loc.get());
4173#else
4174 lconv* lc = __localeconv_l(loc.get());
4175#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004176 if (*lc->decimal_point)
4177 __decimal_point_ = *lc->decimal_point;
4178 if (*lc->thousands_sep)
4179 __thousands_sep_ = *lc->thousands_sep;
4180 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004181 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004182 }
4183}
4184
4185// numpunct_byname<wchar_t>
4186
4187numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4188 : numpunct<wchar_t>(refs)
4189{
4190 __init(nm);
4191}
4192
4193numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4194 : numpunct<wchar_t>(refs)
4195{
4196 __init(nm.c_str());
4197}
4198
4199numpunct_byname<wchar_t>::~numpunct_byname()
4200{
4201}
4202
4203void
4204numpunct_byname<wchar_t>::__init(const char* nm)
4205{
4206 if (strcmp(nm, "C") != 0)
4207 {
Sean Huntf3907e62011-07-15 05:40:33 +00004208 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004209#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004210 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004211 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4212 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004213#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004214#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004215 lconv* lc = localeconv_l(loc.get());
4216#else
4217 lconv* lc = __localeconv_l(loc.get());
4218#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004219 if (*lc->decimal_point)
4220 __decimal_point_ = *lc->decimal_point;
4221 if (*lc->thousands_sep)
4222 __thousands_sep_ = *lc->thousands_sep;
4223 __grouping_ = lc->grouping;
4224 // locallization for truename and falsename is not available
4225 }
4226}
4227
4228// num_get helpers
4229
4230int
4231__num_get_base::__get_base(ios_base& iob)
4232{
4233 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4234 if (__basefield == ios_base::oct)
4235 return 8;
4236 else if (__basefield == ios_base::hex)
4237 return 16;
4238 else if (__basefield == 0)
4239 return 0;
4240 return 10;
4241}
4242
4243const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4244
4245void
4246__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4247 ios_base::iostate& __err)
4248{
4249 if (__grouping.size() != 0)
4250 {
4251 reverse(__g, __g_end);
4252 const char* __ig = __grouping.data();
4253 const char* __eg = __ig + __grouping.size();
4254 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4255 {
4256 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4257 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004258 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004259 {
4260 __err = ios_base::failbit;
4261 return;
4262 }
4263 }
4264 if (__eg - __ig > 1)
4265 ++__ig;
4266 }
4267 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4268 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004269 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004270 __err = ios_base::failbit;
4271 }
4272 }
4273}
4274
4275void
4276__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4277 ios_base::fmtflags __flags)
4278{
4279 if (__flags & ios_base::showpos)
4280 *__fmtp++ = '+';
4281 if (__flags & ios_base::showbase)
4282 *__fmtp++ = '#';
4283 while(*__len)
4284 *__fmtp++ = *__len++;
4285 if ((__flags & ios_base::basefield) == ios_base::oct)
4286 *__fmtp = 'o';
4287 else if ((__flags & ios_base::basefield) == ios_base::hex)
4288 {
4289 if (__flags & ios_base::uppercase)
4290 *__fmtp = 'X';
4291 else
4292 *__fmtp = 'x';
4293 }
4294 else if (__signd)
4295 *__fmtp = 'd';
4296 else
4297 *__fmtp = 'u';
4298}
4299
4300bool
4301__num_put_base::__format_float(char* __fmtp, const char* __len,
4302 ios_base::fmtflags __flags)
4303{
4304 bool specify_precision = true;
4305 if (__flags & ios_base::showpos)
4306 *__fmtp++ = '+';
4307 if (__flags & ios_base::showpoint)
4308 *__fmtp++ = '#';
4309 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4310 bool uppercase = __flags & ios_base::uppercase;
4311 if (floatfield == (ios_base::fixed | ios_base::scientific))
4312 specify_precision = false;
4313 else
4314 {
4315 *__fmtp++ = '.';
4316 *__fmtp++ = '*';
4317 }
4318 while(*__len)
4319 *__fmtp++ = *__len++;
4320 if (floatfield == ios_base::fixed)
4321 {
4322 if (uppercase)
4323 *__fmtp = 'F';
4324 else
4325 *__fmtp = 'f';
4326 }
4327 else if (floatfield == ios_base::scientific)
4328 {
4329 if (uppercase)
4330 *__fmtp = 'E';
4331 else
4332 *__fmtp = 'e';
4333 }
4334 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4335 {
4336 if (uppercase)
4337 *__fmtp = 'A';
4338 else
4339 *__fmtp = 'a';
4340 }
4341 else
4342 {
4343 if (uppercase)
4344 *__fmtp = 'G';
4345 else
4346 *__fmtp = 'g';
4347 }
4348 return specify_precision;
4349}
4350
4351char*
4352__num_put_base::__identify_padding(char* __nb, char* __ne,
4353 const ios_base& __iob)
4354{
4355 switch (__iob.flags() & ios_base::adjustfield)
4356 {
4357 case ios_base::internal:
4358 if (__nb[0] == '-' || __nb[0] == '+')
4359 return __nb+1;
4360 if (__ne - __nb >= 2 && __nb[0] == '0'
4361 && (__nb[1] == 'x' || __nb[1] == 'X'))
4362 return __nb+2;
4363 break;
4364 case ios_base::left:
4365 return __ne;
4366 case ios_base::right:
4367 default:
4368 break;
4369 }
4370 return __nb;
4371}
4372
4373// time_get
4374
4375static
4376string*
4377init_weeks()
4378{
4379 static string weeks[14];
4380 weeks[0] = "Sunday";
4381 weeks[1] = "Monday";
4382 weeks[2] = "Tuesday";
4383 weeks[3] = "Wednesday";
4384 weeks[4] = "Thursday";
4385 weeks[5] = "Friday";
4386 weeks[6] = "Saturday";
4387 weeks[7] = "Sun";
4388 weeks[8] = "Mon";
4389 weeks[9] = "Tue";
4390 weeks[10] = "Wed";
4391 weeks[11] = "Thu";
4392 weeks[12] = "Fri";
4393 weeks[13] = "Sat";
4394 return weeks;
4395}
4396
4397static
4398wstring*
4399init_wweeks()
4400{
4401 static wstring weeks[14];
4402 weeks[0] = L"Sunday";
4403 weeks[1] = L"Monday";
4404 weeks[2] = L"Tuesday";
4405 weeks[3] = L"Wednesday";
4406 weeks[4] = L"Thursday";
4407 weeks[5] = L"Friday";
4408 weeks[6] = L"Saturday";
4409 weeks[7] = L"Sun";
4410 weeks[8] = L"Mon";
4411 weeks[9] = L"Tue";
4412 weeks[10] = L"Wed";
4413 weeks[11] = L"Thu";
4414 weeks[12] = L"Fri";
4415 weeks[13] = L"Sat";
4416 return weeks;
4417}
4418
4419template <>
4420const string*
4421__time_get_c_storage<char>::__weeks() const
4422{
4423 static const string* weeks = init_weeks();
4424 return weeks;
4425}
4426
4427template <>
4428const wstring*
4429__time_get_c_storage<wchar_t>::__weeks() const
4430{
4431 static const wstring* weeks = init_wweeks();
4432 return weeks;
4433}
4434
4435static
4436string*
4437init_months()
4438{
4439 static string months[24];
4440 months[0] = "January";
4441 months[1] = "February";
4442 months[2] = "March";
4443 months[3] = "April";
4444 months[4] = "May";
4445 months[5] = "June";
4446 months[6] = "July";
4447 months[7] = "August";
4448 months[8] = "September";
4449 months[9] = "October";
4450 months[10] = "November";
4451 months[11] = "December";
4452 months[12] = "Jan";
4453 months[13] = "Feb";
4454 months[14] = "Mar";
4455 months[15] = "Apr";
4456 months[16] = "May";
4457 months[17] = "Jun";
4458 months[18] = "Jul";
4459 months[19] = "Aug";
4460 months[20] = "Sep";
4461 months[21] = "Oct";
4462 months[22] = "Nov";
4463 months[23] = "Dec";
4464 return months;
4465}
4466
4467static
4468wstring*
4469init_wmonths()
4470{
4471 static wstring months[24];
4472 months[0] = L"January";
4473 months[1] = L"February";
4474 months[2] = L"March";
4475 months[3] = L"April";
4476 months[4] = L"May";
4477 months[5] = L"June";
4478 months[6] = L"July";
4479 months[7] = L"August";
4480 months[8] = L"September";
4481 months[9] = L"October";
4482 months[10] = L"November";
4483 months[11] = L"December";
4484 months[12] = L"Jan";
4485 months[13] = L"Feb";
4486 months[14] = L"Mar";
4487 months[15] = L"Apr";
4488 months[16] = L"May";
4489 months[17] = L"Jun";
4490 months[18] = L"Jul";
4491 months[19] = L"Aug";
4492 months[20] = L"Sep";
4493 months[21] = L"Oct";
4494 months[22] = L"Nov";
4495 months[23] = L"Dec";
4496 return months;
4497}
4498
4499template <>
4500const string*
4501__time_get_c_storage<char>::__months() const
4502{
4503 static const string* months = init_months();
4504 return months;
4505}
4506
4507template <>
4508const wstring*
4509__time_get_c_storage<wchar_t>::__months() const
4510{
4511 static const wstring* months = init_wmonths();
4512 return months;
4513}
4514
4515static
4516string*
4517init_am_pm()
4518{
4519 static string am_pm[24];
4520 am_pm[0] = "AM";
4521 am_pm[1] = "PM";
4522 return am_pm;
4523}
4524
4525static
4526wstring*
4527init_wam_pm()
4528{
4529 static wstring am_pm[24];
4530 am_pm[0] = L"AM";
4531 am_pm[1] = L"PM";
4532 return am_pm;
4533}
4534
4535template <>
4536const string*
4537__time_get_c_storage<char>::__am_pm() const
4538{
4539 static const string* am_pm = init_am_pm();
4540 return am_pm;
4541}
4542
4543template <>
4544const wstring*
4545__time_get_c_storage<wchar_t>::__am_pm() const
4546{
4547 static const wstring* am_pm = init_wam_pm();
4548 return am_pm;
4549}
4550
4551template <>
4552const string&
4553__time_get_c_storage<char>::__x() const
4554{
4555 static string s("%m/%d/%y");
4556 return s;
4557}
4558
4559template <>
4560const wstring&
4561__time_get_c_storage<wchar_t>::__x() const
4562{
4563 static wstring s(L"%m/%d/%y");
4564 return s;
4565}
4566
4567template <>
4568const string&
4569__time_get_c_storage<char>::__X() const
4570{
4571 static string s("%H:%M:%S");
4572 return s;
4573}
4574
4575template <>
4576const wstring&
4577__time_get_c_storage<wchar_t>::__X() const
4578{
4579 static wstring s(L"%H:%M:%S");
4580 return s;
4581}
4582
4583template <>
4584const string&
4585__time_get_c_storage<char>::__c() const
4586{
4587 static string s("%a %b %d %H:%M:%S %Y");
4588 return s;
4589}
4590
4591template <>
4592const wstring&
4593__time_get_c_storage<wchar_t>::__c() const
4594{
4595 static wstring s(L"%a %b %d %H:%M:%S %Y");
4596 return s;
4597}
4598
4599template <>
4600const string&
4601__time_get_c_storage<char>::__r() const
4602{
4603 static string s("%I:%M:%S %p");
4604 return s;
4605}
4606
4607template <>
4608const wstring&
4609__time_get_c_storage<wchar_t>::__r() const
4610{
4611 static wstring s(L"%I:%M:%S %p");
4612 return s;
4613}
4614
4615// time_get_byname
4616
4617__time_get::__time_get(const char* nm)
4618 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4619{
Howard Hinnantd4444702010-08-11 17:04:31 +00004620#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004621 if (__loc_ == 0)
4622 throw runtime_error("time_get_byname"
4623 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004624#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004625}
4626
4627__time_get::__time_get(const string& nm)
4628 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4629{
Howard Hinnantd4444702010-08-11 17:04:31 +00004630#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004631 if (__loc_ == 0)
4632 throw runtime_error("time_get_byname"
4633 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004634#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004635}
4636
4637__time_get::~__time_get()
4638{
4639 freelocale(__loc_);
4640}
4641
Howard Hinnant335b1512012-02-20 16:51:43 +00004642#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant21772ec2012-12-28 18:15:01 +00004643#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant335b1512012-02-20 16:51:43 +00004644
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004645template <>
4646string
4647__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4648{
Howard Hinnant3074a052012-02-19 14:55:32 +00004649 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004650 t.tm_sec = 59;
4651 t.tm_min = 55;
4652 t.tm_hour = 23;
4653 t.tm_mday = 31;
4654 t.tm_mon = 11;
4655 t.tm_year = 161;
4656 t.tm_wday = 6;
4657 t.tm_yday = 364;
4658 t.tm_isdst = -1;
4659 char buf[100];
4660 char f[3] = {0};
4661 f[0] = '%';
4662 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004663 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004664 char* bb = buf;
4665 char* be = buf + n;
4666 string result;
4667 while (bb != be)
4668 {
4669 if (ct.is(ctype_base::space, *bb))
4670 {
4671 result.push_back(' ');
4672 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4673 ;
4674 continue;
4675 }
4676 char* w = bb;
4677 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004678 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004679 ct, err, false)
4680 - this->__weeks_;
4681 if (i < 14)
4682 {
4683 result.push_back('%');
4684 if (i < 7)
4685 result.push_back('A');
4686 else
4687 result.push_back('a');
4688 bb = w;
4689 continue;
4690 }
4691 w = bb;
4692 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4693 ct, err, false)
4694 - this->__months_;
4695 if (i < 24)
4696 {
4697 result.push_back('%');
4698 if (i < 12)
4699 result.push_back('B');
4700 else
4701 result.push_back('b');
4702 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4703 result.back() = 'm';
4704 bb = w;
4705 continue;
4706 }
4707 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4708 {
4709 w = bb;
4710 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4711 ct, err, false) - this->__am_pm_;
4712 if (i < 2)
4713 {
4714 result.push_back('%');
4715 result.push_back('p');
4716 bb = w;
4717 continue;
4718 }
4719 }
4720 w = bb;
4721 if (ct.is(ctype_base::digit, *bb))
4722 {
4723 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4724 {
4725 case 6:
4726 result.push_back('%');
4727 result.push_back('w');
4728 break;
4729 case 7:
4730 result.push_back('%');
4731 result.push_back('u');
4732 break;
4733 case 11:
4734 result.push_back('%');
4735 result.push_back('I');
4736 break;
4737 case 12:
4738 result.push_back('%');
4739 result.push_back('m');
4740 break;
4741 case 23:
4742 result.push_back('%');
4743 result.push_back('H');
4744 break;
4745 case 31:
4746 result.push_back('%');
4747 result.push_back('d');
4748 break;
4749 case 55:
4750 result.push_back('%');
4751 result.push_back('M');
4752 break;
4753 case 59:
4754 result.push_back('%');
4755 result.push_back('S');
4756 break;
4757 case 61:
4758 result.push_back('%');
4759 result.push_back('y');
4760 break;
4761 case 364:
4762 result.push_back('%');
4763 result.push_back('j');
4764 break;
4765 case 2061:
4766 result.push_back('%');
4767 result.push_back('Y');
4768 break;
4769 default:
4770 for (; w != bb; ++w)
4771 result.push_back(*w);
4772 break;
4773 }
4774 continue;
4775 }
4776 if (*bb == '%')
4777 {
4778 result.push_back('%');
4779 result.push_back('%');
4780 ++bb;
4781 continue;
4782 }
4783 result.push_back(*bb);
4784 ++bb;
4785 }
4786 return result;
4787}
4788
Howard Hinnantec3773c2011-12-01 20:21:04 +00004789#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004790
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004791template <>
4792wstring
4793__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4794{
Howard Hinnant3074a052012-02-19 14:55:32 +00004795 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004796 t.tm_sec = 59;
4797 t.tm_min = 55;
4798 t.tm_hour = 23;
4799 t.tm_mday = 31;
4800 t.tm_mon = 11;
4801 t.tm_year = 161;
4802 t.tm_wday = 6;
4803 t.tm_yday = 364;
4804 t.tm_isdst = -1;
4805 char buf[100];
4806 char f[3] = {0};
4807 f[0] = '%';
4808 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004809 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004810 wchar_t wbuf[100];
4811 wchar_t* wbb = wbuf;
4812 mbstate_t mb = {0};
4813 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004814#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004815 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004816#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004817 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004818#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004819 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004820 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004821 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004822 wstring result;
4823 while (wbb != wbe)
4824 {
4825 if (ct.is(ctype_base::space, *wbb))
4826 {
4827 result.push_back(L' ');
4828 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4829 ;
4830 continue;
4831 }
4832 wchar_t* w = wbb;
4833 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004834 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004835 ct, err, false)
4836 - this->__weeks_;
4837 if (i < 14)
4838 {
4839 result.push_back(L'%');
4840 if (i < 7)
4841 result.push_back(L'A');
4842 else
4843 result.push_back(L'a');
4844 wbb = w;
4845 continue;
4846 }
4847 w = wbb;
4848 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4849 ct, err, false)
4850 - this->__months_;
4851 if (i < 24)
4852 {
4853 result.push_back(L'%');
4854 if (i < 12)
4855 result.push_back(L'B');
4856 else
4857 result.push_back(L'b');
4858 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4859 result.back() = L'm';
4860 wbb = w;
4861 continue;
4862 }
4863 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4864 {
4865 w = wbb;
4866 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4867 ct, err, false) - this->__am_pm_;
4868 if (i < 2)
4869 {
4870 result.push_back(L'%');
4871 result.push_back(L'p');
4872 wbb = w;
4873 continue;
4874 }
4875 }
4876 w = wbb;
4877 if (ct.is(ctype_base::digit, *wbb))
4878 {
4879 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4880 {
4881 case 6:
4882 result.push_back(L'%');
4883 result.push_back(L'w');
4884 break;
4885 case 7:
4886 result.push_back(L'%');
4887 result.push_back(L'u');
4888 break;
4889 case 11:
4890 result.push_back(L'%');
4891 result.push_back(L'I');
4892 break;
4893 case 12:
4894 result.push_back(L'%');
4895 result.push_back(L'm');
4896 break;
4897 case 23:
4898 result.push_back(L'%');
4899 result.push_back(L'H');
4900 break;
4901 case 31:
4902 result.push_back(L'%');
4903 result.push_back(L'd');
4904 break;
4905 case 55:
4906 result.push_back(L'%');
4907 result.push_back(L'M');
4908 break;
4909 case 59:
4910 result.push_back(L'%');
4911 result.push_back(L'S');
4912 break;
4913 case 61:
4914 result.push_back(L'%');
4915 result.push_back(L'y');
4916 break;
4917 case 364:
4918 result.push_back(L'%');
4919 result.push_back(L'j');
4920 break;
4921 case 2061:
4922 result.push_back(L'%');
4923 result.push_back(L'Y');
4924 break;
4925 default:
4926 for (; w != wbb; ++w)
4927 result.push_back(*w);
4928 break;
4929 }
4930 continue;
4931 }
4932 if (ct.narrow(*wbb, 0) == '%')
4933 {
4934 result.push_back(L'%');
4935 result.push_back(L'%');
4936 ++wbb;
4937 continue;
4938 }
4939 result.push_back(*wbb);
4940 ++wbb;
4941 }
4942 return result;
4943}
4944
4945template <>
4946void
4947__time_get_storage<char>::init(const ctype<char>& ct)
4948{
Howard Hinnantcd992362012-08-02 18:44:17 +00004949 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004950 char buf[100];
4951 // __weeks_
4952 for (int i = 0; i < 7; ++i)
4953 {
4954 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004955 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004956 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004957 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004958 __weeks_[i+7] = buf;
4959 }
4960 // __months_
4961 for (int i = 0; i < 12; ++i)
4962 {
4963 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004964 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004965 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004966 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004967 __months_[i+12] = buf;
4968 }
4969 // __am_pm_
4970 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004971 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004972 __am_pm_[0] = buf;
4973 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004974 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004975 __am_pm_[1] = buf;
4976 __c_ = __analyze('c', ct);
4977 __r_ = __analyze('r', ct);
4978 __x_ = __analyze('x', ct);
4979 __X_ = __analyze('X', ct);
4980}
4981
4982template <>
4983void
4984__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4985{
4986 tm t = {0};
4987 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004988 wchar_t wbuf[100];
4989 wchar_t* wbe;
4990 mbstate_t mb = {0};
4991 // __weeks_
4992 for (int i = 0; i < 7; ++i)
4993 {
4994 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004995 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004996 mb = mbstate_t();
4997 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004998#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004999 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005000#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005001 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005002#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005003 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005004 __throw_runtime_error("locale not supported");
5005 wbe = wbuf + j;
5006 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005007 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005008 mb = mbstate_t();
5009 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005010#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005011 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005012#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005013 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005014#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005015 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005016 __throw_runtime_error("locale not supported");
5017 wbe = wbuf + j;
5018 __weeks_[i+7].assign(wbuf, wbe);
5019 }
5020 // __months_
5021 for (int i = 0; i < 12; ++i)
5022 {
5023 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005024 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005025 mb = mbstate_t();
5026 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005027#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005028 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005029#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005030 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005031#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005032 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005033 __throw_runtime_error("locale not supported");
5034 wbe = wbuf + j;
5035 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005036 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005037 mb = mbstate_t();
5038 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005039#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005040 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005041#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005042 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005043#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005044 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005045 __throw_runtime_error("locale not supported");
5046 wbe = wbuf + j;
5047 __months_[i+12].assign(wbuf, wbe);
5048 }
5049 // __am_pm_
5050 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005051 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005052 mb = mbstate_t();
5053 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005054#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005055 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005056#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005057 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005058#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005059 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005060 __throw_runtime_error("locale not supported");
5061 wbe = wbuf + j;
5062 __am_pm_[0].assign(wbuf, wbe);
5063 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005064 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005065 mb = mbstate_t();
5066 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005067#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005068 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005069#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005070 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005071#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005072 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005073 __throw_runtime_error("locale not supported");
5074 wbe = wbuf + j;
5075 __am_pm_[1].assign(wbuf, wbe);
5076 __c_ = __analyze('c', ct);
5077 __r_ = __analyze('r', ct);
5078 __x_ = __analyze('x', ct);
5079 __X_ = __analyze('X', ct);
5080}
5081
5082template <class CharT>
5083struct _LIBCPP_HIDDEN __time_get_temp
5084 : public ctype_byname<CharT>
5085{
5086 explicit __time_get_temp(const char* nm)
5087 : ctype_byname<CharT>(nm, 1) {}
5088 explicit __time_get_temp(const string& nm)
5089 : ctype_byname<CharT>(nm, 1) {}
5090};
5091
5092template <>
5093__time_get_storage<char>::__time_get_storage(const char* __nm)
5094 : __time_get(__nm)
5095{
5096 const __time_get_temp<char> ct(__nm);
5097 init(ct);
5098}
5099
5100template <>
5101__time_get_storage<char>::__time_get_storage(const string& __nm)
5102 : __time_get(__nm)
5103{
5104 const __time_get_temp<char> ct(__nm);
5105 init(ct);
5106}
5107
5108template <>
5109__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5110 : __time_get(__nm)
5111{
5112 const __time_get_temp<wchar_t> ct(__nm);
5113 init(ct);
5114}
5115
5116template <>
5117__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5118 : __time_get(__nm)
5119{
5120 const __time_get_temp<wchar_t> ct(__nm);
5121 init(ct);
5122}
5123
5124template <>
5125time_base::dateorder
5126__time_get_storage<char>::__do_date_order() const
5127{
5128 unsigned i;
5129 for (i = 0; i < __x_.size(); ++i)
5130 if (__x_[i] == '%')
5131 break;
5132 ++i;
5133 switch (__x_[i])
5134 {
5135 case 'y':
5136 case 'Y':
5137 for (++i; i < __x_.size(); ++i)
5138 if (__x_[i] == '%')
5139 break;
5140 if (i == __x_.size())
5141 break;
5142 ++i;
5143 switch (__x_[i])
5144 {
5145 case 'm':
5146 for (++i; i < __x_.size(); ++i)
5147 if (__x_[i] == '%')
5148 break;
5149 if (i == __x_.size())
5150 break;
5151 ++i;
5152 if (__x_[i] == 'd')
5153 return time_base::ymd;
5154 break;
5155 case 'd':
5156 for (++i; i < __x_.size(); ++i)
5157 if (__x_[i] == '%')
5158 break;
5159 if (i == __x_.size())
5160 break;
5161 ++i;
5162 if (__x_[i] == 'm')
5163 return time_base::ydm;
5164 break;
5165 }
5166 break;
5167 case 'm':
5168 for (++i; i < __x_.size(); ++i)
5169 if (__x_[i] == '%')
5170 break;
5171 if (i == __x_.size())
5172 break;
5173 ++i;
5174 if (__x_[i] == 'd')
5175 {
5176 for (++i; i < __x_.size(); ++i)
5177 if (__x_[i] == '%')
5178 break;
5179 if (i == __x_.size())
5180 break;
5181 ++i;
5182 if (__x_[i] == 'y' || __x_[i] == 'Y')
5183 return time_base::mdy;
5184 break;
5185 }
5186 break;
5187 case 'd':
5188 for (++i; i < __x_.size(); ++i)
5189 if (__x_[i] == '%')
5190 break;
5191 if (i == __x_.size())
5192 break;
5193 ++i;
5194 if (__x_[i] == 'm')
5195 {
5196 for (++i; i < __x_.size(); ++i)
5197 if (__x_[i] == '%')
5198 break;
5199 if (i == __x_.size())
5200 break;
5201 ++i;
5202 if (__x_[i] == 'y' || __x_[i] == 'Y')
5203 return time_base::dmy;
5204 break;
5205 }
5206 break;
5207 }
5208 return time_base::no_order;
5209}
5210
5211template <>
5212time_base::dateorder
5213__time_get_storage<wchar_t>::__do_date_order() const
5214{
5215 unsigned i;
5216 for (i = 0; i < __x_.size(); ++i)
5217 if (__x_[i] == L'%')
5218 break;
5219 ++i;
5220 switch (__x_[i])
5221 {
5222 case L'y':
5223 case L'Y':
5224 for (++i; i < __x_.size(); ++i)
5225 if (__x_[i] == L'%')
5226 break;
5227 if (i == __x_.size())
5228 break;
5229 ++i;
5230 switch (__x_[i])
5231 {
5232 case L'm':
5233 for (++i; i < __x_.size(); ++i)
5234 if (__x_[i] == L'%')
5235 break;
5236 if (i == __x_.size())
5237 break;
5238 ++i;
5239 if (__x_[i] == L'd')
5240 return time_base::ymd;
5241 break;
5242 case L'd':
5243 for (++i; i < __x_.size(); ++i)
5244 if (__x_[i] == L'%')
5245 break;
5246 if (i == __x_.size())
5247 break;
5248 ++i;
5249 if (__x_[i] == L'm')
5250 return time_base::ydm;
5251 break;
5252 }
5253 break;
5254 case L'm':
5255 for (++i; i < __x_.size(); ++i)
5256 if (__x_[i] == L'%')
5257 break;
5258 if (i == __x_.size())
5259 break;
5260 ++i;
5261 if (__x_[i] == L'd')
5262 {
5263 for (++i; i < __x_.size(); ++i)
5264 if (__x_[i] == L'%')
5265 break;
5266 if (i == __x_.size())
5267 break;
5268 ++i;
5269 if (__x_[i] == L'y' || __x_[i] == L'Y')
5270 return time_base::mdy;
5271 break;
5272 }
5273 break;
5274 case L'd':
5275 for (++i; i < __x_.size(); ++i)
5276 if (__x_[i] == L'%')
5277 break;
5278 if (i == __x_.size())
5279 break;
5280 ++i;
5281 if (__x_[i] == L'm')
5282 {
5283 for (++i; i < __x_.size(); ++i)
5284 if (__x_[i] == L'%')
5285 break;
5286 if (i == __x_.size())
5287 break;
5288 ++i;
5289 if (__x_[i] == L'y' || __x_[i] == L'Y')
5290 return time_base::dmy;
5291 break;
5292 }
5293 break;
5294 }
5295 return time_base::no_order;
5296}
5297
5298// time_put
5299
5300__time_put::__time_put(const char* nm)
5301 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5302{
Howard Hinnantd4444702010-08-11 17:04:31 +00005303#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005304 if (__loc_ == 0)
5305 throw runtime_error("time_put_byname"
5306 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005307#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005308}
5309
5310__time_put::__time_put(const string& nm)
5311 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5312{
Howard Hinnantd4444702010-08-11 17:04:31 +00005313#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005314 if (__loc_ == 0)
5315 throw runtime_error("time_put_byname"
5316 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005317#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005318}
5319
5320__time_put::~__time_put()
5321{
5322 if (__loc_)
5323 freelocale(__loc_);
5324}
5325
5326void
5327__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5328 char __fmt, char __mod) const
5329{
5330 char fmt[] = {'%', __fmt, __mod, 0};
5331 if (__mod != 0)
5332 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005333 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005334 __ne = __nb + n;
5335}
5336
5337void
5338__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5339 char __fmt, char __mod) const
5340{
5341 char __nar[100];
5342 char* __ne = __nar + 100;
5343 __do_put(__nar, __ne, __tm, __fmt, __mod);
5344 mbstate_t mb = {0};
5345 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005346#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005347 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005348#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005349 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005350#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005351 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005352 __throw_runtime_error("locale not supported");
5353 __we = __wb + j;
5354}
5355
5356// moneypunct_byname
5357
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005358template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005359static
5360void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005361__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5362 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5363 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005364{
5365 const char sign = static_cast<char>(money_base::sign);
5366 const char space = static_cast<char>(money_base::space);
5367 const char none = static_cast<char>(money_base::none);
5368 const char symbol = static_cast<char>(money_base::symbol);
5369 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005370 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5371
5372 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5373 // function'. "Space between sign and symbol or value" means that
5374 // if the sign is adjacent to the symbol, there's a space between
5375 // them, and otherwise there's a space between the sign and value.
5376 //
5377 // C11's localeconv specifies that the fourth character of an
5378 // international curr_symbol is used to separate the sign and
5379 // value when sep_by_space says to do so. C++ can't represent
5380 // that, so we just use a space. When sep_by_space says to
5381 // separate the symbol and value-or-sign with a space, we rearrange the
5382 // curr_symbol to put its spacing character on the correct side of
5383 // the symbol.
5384 //
5385 // We also need to avoid adding an extra space between the sign
5386 // and value when the currency symbol is suppressed (by not
5387 // setting showbase). We match glibc's strfmon by interpreting
5388 // sep_by_space==1 as "omit the space when the currency symbol is
5389 // absent".
5390 //
5391 // Users who want to get this right should use ICU instead.
5392
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005393 switch (cs_precedes)
5394 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005395 case 0: // value before curr_symbol
5396 if (symbol_contains_sep) {
5397 // Move the separator to before the symbol, to place it
5398 // between the value and symbol.
5399 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5400 __curr_symbol_.end());
5401 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005402 switch (sign_posn)
5403 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005404 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005405 pat.field[0] = sign;
5406 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005407 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005408 pat.field[3] = symbol;
5409 switch (sep_by_space)
5410 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005411 case 0: // No space separates the currency symbol and value.
5412 // This case may have changed between C99 and C11;
5413 // assume the currency symbol matches the intention.
5414 case 2: // Space between sign and currency or value.
5415 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005416 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005417 case 1: // Space between currency-and-sign or currency and value.
5418 if (!symbol_contains_sep) {
5419 // We insert the space into the symbol instead of
5420 // setting pat.field[2]=space so that when
5421 // showbase is not set, the space goes away too.
5422 __curr_symbol_.insert(0, 1, space_char);
5423 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005424 return;
5425 default:
5426 break;
5427 }
5428 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005429 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005430 pat.field[0] = sign;
5431 pat.field[3] = symbol;
5432 switch (sep_by_space)
5433 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005434 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005435 pat.field[1] = value;
5436 pat.field[2] = none;
5437 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005438 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005439 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005440 pat.field[2] = none;
5441 if (!symbol_contains_sep) {
5442 // We insert the space into the symbol instead of
5443 // setting pat.field[2]=space so that when
5444 // showbase is not set, the space goes away too.
5445 __curr_symbol_.insert(0, 1, space_char);
5446 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005447 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005448 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005449 pat.field[1] = space;
5450 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005451 if (symbol_contains_sep) {
5452 // Remove the separator from the symbol, since it
5453 // has already appeared after the sign.
5454 __curr_symbol_.erase(__curr_symbol_.begin());
5455 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005456 return;
5457 default:
5458 break;
5459 }
5460 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005461 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005462 pat.field[0] = value;
5463 pat.field[3] = sign;
5464 switch (sep_by_space)
5465 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005466 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005467 pat.field[1] = none;
5468 pat.field[2] = symbol;
5469 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005470 case 1: // Space between currency-and-sign or currency and value.
5471 if (!symbol_contains_sep) {
5472 // We insert the space into the symbol instead of
5473 // setting pat.field[1]=space so that when
5474 // showbase is not set, the space goes away too.
5475 __curr_symbol_.insert(0, 1, space_char);
5476 }
5477 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005478 pat.field[2] = symbol;
5479 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005480 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005481 pat.field[1] = symbol;
5482 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005483 if (symbol_contains_sep) {
5484 // Remove the separator from the symbol, since it
5485 // should not be removed if showbase is absent.
5486 __curr_symbol_.erase(__curr_symbol_.begin());
5487 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005488 return;
5489 default:
5490 break;
5491 }
5492 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005493 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005494 pat.field[0] = value;
5495 pat.field[3] = symbol;
5496 switch (sep_by_space)
5497 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005498 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005499 pat.field[1] = none;
5500 pat.field[2] = sign;
5501 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005502 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005503 pat.field[1] = space;
5504 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005505 if (symbol_contains_sep) {
5506 // Remove the separator from the symbol, since it
5507 // has already appeared before the sign.
5508 __curr_symbol_.erase(__curr_symbol_.begin());
5509 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005510 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005511 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005512 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005513 pat.field[2] = none;
5514 if (!symbol_contains_sep) {
5515 // We insert the space into the symbol instead of
5516 // setting pat.field[2]=space so that when
5517 // showbase is not set, the space goes away too.
5518 __curr_symbol_.insert(0, 1, space_char);
5519 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005520 return;
5521 default:
5522 break;
5523 }
5524 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005525 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005526 pat.field[0] = value;
5527 pat.field[3] = sign;
5528 switch (sep_by_space)
5529 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005530 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005531 pat.field[1] = none;
5532 pat.field[2] = symbol;
5533 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005534 case 1: // Space between currency-and-sign or currency and value.
5535 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005536 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005537 if (!symbol_contains_sep) {
5538 // We insert the space into the symbol instead of
5539 // setting pat.field[1]=space so that when
5540 // showbase is not set, the space goes away too.
5541 __curr_symbol_.insert(0, 1, space_char);
5542 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005543 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005544 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005545 pat.field[1] = symbol;
5546 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005547 if (symbol_contains_sep) {
5548 // Remove the separator from the symbol, since it
5549 // should not disappear when showbase is absent.
5550 __curr_symbol_.erase(__curr_symbol_.begin());
5551 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005552 return;
5553 default:
5554 break;
5555 }
5556 break;
5557 default:
5558 break;
5559 }
5560 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005561 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005562 switch (sign_posn)
5563 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005564 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005565 pat.field[0] = sign;
5566 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005567 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005568 pat.field[3] = value;
5569 switch (sep_by_space)
5570 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005571 case 0: // No space separates the currency symbol and value.
5572 // This case may have changed between C99 and C11;
5573 // assume the currency symbol matches the intention.
5574 case 2: // Space between sign and currency or value.
5575 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005576 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005577 case 1: // Space between currency-and-sign or currency and value.
5578 if (!symbol_contains_sep) {
5579 // We insert the space into the symbol instead of
5580 // setting pat.field[2]=space so that when
5581 // showbase is not set, the space goes away too.
5582 __curr_symbol_.insert(0, 1, space_char);
5583 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005584 return;
5585 default:
5586 break;
5587 }
5588 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005589 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005590 pat.field[0] = sign;
5591 pat.field[3] = value;
5592 switch (sep_by_space)
5593 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005594 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005595 pat.field[1] = symbol;
5596 pat.field[2] = none;
5597 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005598 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005599 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005600 pat.field[2] = none;
5601 if (!symbol_contains_sep) {
5602 // We insert the space into the symbol instead of
5603 // setting pat.field[2]=space so that when
5604 // showbase is not set, the space goes away too.
5605 __curr_symbol_.push_back(space_char);
5606 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005607 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005608 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005609 pat.field[1] = space;
5610 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005611 if (symbol_contains_sep) {
5612 // Remove the separator from the symbol, since it
5613 // has already appeared after the sign.
5614 __curr_symbol_.pop_back();
5615 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005616 return;
5617 default:
5618 break;
5619 }
5620 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005621 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005622 pat.field[0] = symbol;
5623 pat.field[3] = sign;
5624 switch (sep_by_space)
5625 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005626 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005627 pat.field[1] = none;
5628 pat.field[2] = value;
5629 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005630 case 1: // Space between currency-and-sign or currency and value.
5631 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005632 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005633 if (!symbol_contains_sep) {
5634 // We insert the space into the symbol instead of
5635 // setting pat.field[1]=space so that when
5636 // showbase is not set, the space goes away too.
5637 __curr_symbol_.push_back(space_char);
5638 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005639 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005640 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005641 pat.field[1] = value;
5642 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005643 if (symbol_contains_sep) {
5644 // Remove the separator from the symbol, since it
5645 // will appear before the sign.
5646 __curr_symbol_.pop_back();
5647 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005648 return;
5649 default:
5650 break;
5651 }
5652 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005653 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005654 pat.field[0] = sign;
5655 pat.field[3] = value;
5656 switch (sep_by_space)
5657 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005658 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005659 pat.field[1] = symbol;
5660 pat.field[2] = none;
5661 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005662 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005663 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005664 pat.field[2] = none;
5665 if (!symbol_contains_sep) {
5666 // We insert the space into the symbol instead of
5667 // setting pat.field[2]=space so that when
5668 // showbase is not set, the space goes away too.
5669 __curr_symbol_.push_back(space_char);
5670 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005671 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005672 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005673 pat.field[1] = space;
5674 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005675 if (symbol_contains_sep) {
5676 // Remove the separator from the symbol, since it
5677 // has already appeared after the sign.
5678 __curr_symbol_.pop_back();
5679 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005680 return;
5681 default:
5682 break;
5683 }
5684 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005685 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005686 pat.field[0] = symbol;
5687 pat.field[3] = value;
5688 switch (sep_by_space)
5689 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005690 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005691 pat.field[1] = sign;
5692 pat.field[2] = none;
5693 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005694 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005695 pat.field[1] = sign;
5696 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005697 if (symbol_contains_sep) {
5698 // Remove the separator from the symbol, since it
5699 // should not disappear when showbase is absent.
5700 __curr_symbol_.pop_back();
5701 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005702 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005703 case 2: // Space between sign and currency or value.
5704 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005705 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005706 if (!symbol_contains_sep) {
5707 // We insert the space into the symbol instead of
5708 // setting pat.field[1]=space so that when
5709 // showbase is not set, the space goes away too.
5710 __curr_symbol_.push_back(space_char);
5711 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005712 return;
5713 default:
5714 break;
5715 }
5716 break;
5717 default:
5718 break;
5719 }
5720 break;
5721 default:
5722 break;
5723 }
5724 pat.field[0] = symbol;
5725 pat.field[1] = sign;
5726 pat.field[2] = none;
5727 pat.field[3] = value;
5728}
5729
5730template<>
5731void
5732moneypunct_byname<char, false>::init(const char* nm)
5733{
5734 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005735 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005736#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005737 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005738 throw runtime_error("moneypunct_byname"
5739 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005740#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005741#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005742 lconv* lc = localeconv_l(loc.get());
5743#else
5744 lconv* lc = __localeconv_l(loc.get());
5745#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005746 if (*lc->mon_decimal_point)
5747 __decimal_point_ = *lc->mon_decimal_point;
5748 else
5749 __decimal_point_ = base::do_decimal_point();
5750 if (*lc->mon_thousands_sep)
5751 __thousands_sep_ = *lc->mon_thousands_sep;
5752 else
5753 __thousands_sep_ = base::do_thousands_sep();
5754 __grouping_ = lc->mon_grouping;
5755 __curr_symbol_ = lc->currency_symbol;
5756 if (lc->frac_digits != CHAR_MAX)
5757 __frac_digits_ = lc->frac_digits;
5758 else
5759 __frac_digits_ = base::do_frac_digits();
5760 if (lc->p_sign_posn == 0)
5761 __positive_sign_ = "()";
5762 else
5763 __positive_sign_ = lc->positive_sign;
5764 if (lc->n_sign_posn == 0)
5765 __negative_sign_ = "()";
5766 else
5767 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005768 // Assume the positive and negative formats will want spaces in
5769 // the same places in curr_symbol since there's no way to
5770 // represent anything else.
5771 string_type __dummy_curr_symbol = __curr_symbol_;
5772 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5773 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5774 __init_pat(__neg_format_, __curr_symbol_, false,
5775 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005776}
5777
5778template<>
5779void
5780moneypunct_byname<char, true>::init(const char* nm)
5781{
5782 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005783 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005784#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005785 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005786 throw runtime_error("moneypunct_byname"
5787 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005788#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005789#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005790 lconv* lc = localeconv_l(loc.get());
5791#else
5792 lconv* lc = __localeconv_l(loc.get());
5793#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005794 if (*lc->mon_decimal_point)
5795 __decimal_point_ = *lc->mon_decimal_point;
5796 else
5797 __decimal_point_ = base::do_decimal_point();
5798 if (*lc->mon_thousands_sep)
5799 __thousands_sep_ = *lc->mon_thousands_sep;
5800 else
5801 __thousands_sep_ = base::do_thousands_sep();
5802 __grouping_ = lc->mon_grouping;
5803 __curr_symbol_ = lc->int_curr_symbol;
5804 if (lc->int_frac_digits != CHAR_MAX)
5805 __frac_digits_ = lc->int_frac_digits;
5806 else
5807 __frac_digits_ = base::do_frac_digits();
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005808#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005809 if (lc->p_sign_posn == 0)
5810#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005811 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005812#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005813 __positive_sign_ = "()";
5814 else
5815 __positive_sign_ = lc->positive_sign;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005816#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005817 if(lc->n_sign_posn == 0)
5818#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005819 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005820#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005821 __negative_sign_ = "()";
5822 else
5823 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005824 // Assume the positive and negative formats will want spaces in
5825 // the same places in curr_symbol since there's no way to
5826 // represent anything else.
5827 string_type __dummy_curr_symbol = __curr_symbol_;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005828#ifdef _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005829 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5830 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5831 __init_pat(__neg_format_, __curr_symbol_, true,
5832 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005833#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005834 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5835 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5836 lc->int_p_sign_posn, ' ');
5837 __init_pat(__neg_format_, __curr_symbol_, true,
5838 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5839 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005840#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005841}
5842
5843template<>
5844void
5845moneypunct_byname<wchar_t, false>::init(const char* nm)
5846{
5847 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005848 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005849#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005850 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005851 throw runtime_error("moneypunct_byname"
5852 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005853#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005854#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005855 lconv* lc = localeconv_l(loc.get());
5856#else
5857 lconv* lc = __localeconv_l(loc.get());
5858#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005859 if (*lc->mon_decimal_point)
5860 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5861 else
5862 __decimal_point_ = base::do_decimal_point();
5863 if (*lc->mon_thousands_sep)
5864 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5865 else
5866 __thousands_sep_ = base::do_thousands_sep();
5867 __grouping_ = lc->mon_grouping;
5868 wchar_t wbuf[100];
5869 mbstate_t mb = {0};
5870 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005871#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005872 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005873#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005874 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005875#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005876 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005877 __throw_runtime_error("locale not supported");
5878 wchar_t* wbe = wbuf + j;
5879 __curr_symbol_.assign(wbuf, wbe);
5880 if (lc->frac_digits != CHAR_MAX)
5881 __frac_digits_ = lc->frac_digits;
5882 else
5883 __frac_digits_ = base::do_frac_digits();
5884 if (lc->p_sign_posn == 0)
5885 __positive_sign_ = L"()";
5886 else
5887 {
5888 mb = mbstate_t();
5889 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005890#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005891 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005892#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005893 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005894#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005895 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005896 __throw_runtime_error("locale not supported");
5897 wbe = wbuf + j;
5898 __positive_sign_.assign(wbuf, wbe);
5899 }
5900 if (lc->n_sign_posn == 0)
5901 __negative_sign_ = L"()";
5902 else
5903 {
5904 mb = mbstate_t();
5905 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005906#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005907 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005908#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005909 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005910#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005911 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005912 __throw_runtime_error("locale not supported");
5913 wbe = wbuf + j;
5914 __negative_sign_.assign(wbuf, wbe);
5915 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005916 // Assume the positive and negative formats will want spaces in
5917 // the same places in curr_symbol since there's no way to
5918 // represent anything else.
5919 string_type __dummy_curr_symbol = __curr_symbol_;
5920 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5921 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5922 __init_pat(__neg_format_, __curr_symbol_, false,
5923 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005924}
5925
5926template<>
5927void
5928moneypunct_byname<wchar_t, true>::init(const char* nm)
5929{
5930 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005931 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005932#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005933 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005934 throw runtime_error("moneypunct_byname"
5935 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005936#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005937#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005938 lconv* lc = localeconv_l(loc.get());
5939#else
5940 lconv* lc = __localeconv_l(loc.get());
5941#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005942 if (*lc->mon_decimal_point)
5943 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5944 else
5945 __decimal_point_ = base::do_decimal_point();
5946 if (*lc->mon_thousands_sep)
5947 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5948 else
5949 __thousands_sep_ = base::do_thousands_sep();
5950 __grouping_ = lc->mon_grouping;
5951 wchar_t wbuf[100];
5952 mbstate_t mb = {0};
5953 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005954#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005955 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005956#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005957 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005958#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005959 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005960 __throw_runtime_error("locale not supported");
5961 wchar_t* wbe = wbuf + j;
5962 __curr_symbol_.assign(wbuf, wbe);
5963 if (lc->int_frac_digits != CHAR_MAX)
5964 __frac_digits_ = lc->int_frac_digits;
5965 else
5966 __frac_digits_ = base::do_frac_digits();
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005967#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005968 if (lc->p_sign_posn == 0)
5969#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005970 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005971#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005972 __positive_sign_ = L"()";
5973 else
5974 {
5975 mb = mbstate_t();
5976 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005977#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005978 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005979#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005980 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005981#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005982 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005983 __throw_runtime_error("locale not supported");
5984 wbe = wbuf + j;
5985 __positive_sign_.assign(wbuf, wbe);
5986 }
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005987#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005988 if (lc->n_sign_posn == 0)
5989#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005990 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005991#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005992 __negative_sign_ = L"()";
5993 else
5994 {
5995 mb = mbstate_t();
5996 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005997#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005998 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005999#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006000 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006001#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006002 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006003 __throw_runtime_error("locale not supported");
6004 wbe = wbuf + j;
6005 __negative_sign_.assign(wbuf, wbe);
6006 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006007 // Assume the positive and negative formats will want spaces in
6008 // the same places in curr_symbol since there's no way to
6009 // represent anything else.
6010 string_type __dummy_curr_symbol = __curr_symbol_;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00006011#ifdef _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006012 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6013 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6014 __init_pat(__neg_format_, __curr_symbol_, true,
6015 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006016#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006017 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6018 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6019 lc->int_p_sign_posn, L' ');
6020 __init_pat(__neg_format_, __curr_symbol_, true,
6021 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6022 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006023#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006024}
6025
6026void __do_nothing(void*) {}
6027
6028void __throw_runtime_error(const char* msg)
6029{
Howard Hinnantd4444702010-08-11 17:04:31 +00006030#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006031 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006032#else
6033 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006034#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006035}
6036
6037template class collate<char>;
6038template class collate<wchar_t>;
6039
6040template class num_get<char>;
6041template class num_get<wchar_t>;
6042
Howard Hinnantec3773c2011-12-01 20:21:04 +00006043template struct __num_get<char>;
6044template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006045
6046template class num_put<char>;
6047template class num_put<wchar_t>;
6048
Howard Hinnantec3773c2011-12-01 20:21:04 +00006049template struct __num_put<char>;
6050template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006051
6052template class time_get<char>;
6053template class time_get<wchar_t>;
6054
6055template class time_get_byname<char>;
6056template class time_get_byname<wchar_t>;
6057
6058template class time_put<char>;
6059template class time_put<wchar_t>;
6060
6061template class time_put_byname<char>;
6062template class time_put_byname<wchar_t>;
6063
6064template class moneypunct<char, false>;
6065template class moneypunct<char, true>;
6066template class moneypunct<wchar_t, false>;
6067template class moneypunct<wchar_t, true>;
6068
6069template class moneypunct_byname<char, false>;
6070template class moneypunct_byname<char, true>;
6071template class moneypunct_byname<wchar_t, false>;
6072template class moneypunct_byname<wchar_t, true>;
6073
6074template class money_get<char>;
6075template class money_get<wchar_t>;
6076
6077template class __money_get<char>;
6078template class __money_get<wchar_t>;
6079
6080template class money_put<char>;
6081template class money_put<wchar_t>;
6082
6083template class __money_put<char>;
6084template class __money_put<wchar_t>;
6085
6086template class messages<char>;
6087template class messages<wchar_t>;
6088
6089template class messages_byname<char>;
6090template class messages_byname<wchar_t>;
6091
6092template class codecvt_byname<char, char, mbstate_t>;
6093template class codecvt_byname<wchar_t, char, mbstate_t>;
6094template class codecvt_byname<char16_t, char, mbstate_t>;
6095template class codecvt_byname<char32_t, char, mbstate_t>;
6096
6097template class __vector_base_common<true>;
6098
6099_LIBCPP_END_NAMESPACE_STD