blob: ac1952151a03a0b4f16fb3ddb1771ed04a6fddaf [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"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000021#include "typeinfo"
Howard Hinnantb87922c2013-07-28 18:20:00 +000022#ifndef _LIBCPP_NO_EXCEPTIONS
23# include "type_traits"
24#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000025#include "clocale"
26#include "cstring"
27#include "cwctype"
28#include "__sso_allocator"
Howard Hinnante9df0a52013-08-01 18:17:34 +000029#ifdef _LIBCPP_MSVCRT
Howard Hinnant14fa9f92011-09-29 20:33:10 +000030#include <support/win32/locale_win32.h>
Howard Hinnante9df0a52013-08-01 18:17:34 +000031#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000032#include <langinfo.h>
Howard Hinnante9df0a52013-08-01 18:17:34 +000033#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000034#include <stdlib.h>
Howard Hinnanted14a762013-07-23 16:05:56 +000035#include <stdio.h>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000036
Marshall Clow9ae96d02013-02-07 17:20:56 +000037// On Linux, wint_t and wchar_t have different signed-ness, and this causes
38// lots of noise in the build log, but no bugs that I know of.
39#pragma clang diagnostic ignored "-Wsign-conversion"
40
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041_LIBCPP_BEGIN_NAMESPACE_STD
42
Howard Hinnant866569b2011-09-28 23:39:33 +000043#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000044locale_t __cloc() {
45 // In theory this could create a race condition. In practice
46 // the race condition is non-fatal since it will just create
47 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000048 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
49 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000050}
Howard Hinnant866569b2011-09-28 23:39:33 +000051#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000052
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000053namespace {
54
55struct release
56{
57 void operator()(locale::facet* p) {p->__release_shared();}
58};
59
60template <class T, class A0>
61inline
62T&
63make(A0 a0)
64{
65 static typename aligned_storage<sizeof(T)>::type buf;
66 ::new (&buf) T(a0);
67 return *(T*)&buf;
68}
69
70template <class T, class A0, class A1>
71inline
72T&
73make(A0 a0, A1 a1)
74{
75 static typename aligned_storage<sizeof(T)>::type buf;
76 ::new (&buf) T(a0, a1);
77 return *(T*)&buf;
78}
79
80template <class T, class A0, class A1, class A2>
81inline
82T&
83make(A0 a0, A1 a1, A2 a2)
84{
85 static typename aligned_storage<sizeof(T)>::type buf;
86 ::new (&buf) T(a0, a1, a2);
87 return *(T*)&buf;
88}
89
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000090template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000091inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000092_LIBCPP_CONSTEXPR
93size_t
94countof(const T (&)[N])
95{
96 return N;
97}
98
99template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +0000100inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +0000101_LIBCPP_CONSTEXPR
102size_t
103countof(const T * const begin, const T * const end)
104{
105 return static_cast<size_t>(end - begin);
106}
107
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000108}
109
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000110const locale::category locale::none;
111const locale::category locale::collate;
112const locale::category locale::ctype;
113const locale::category locale::monetary;
114const locale::category locale::numeric;
115const locale::category locale::time;
116const locale::category locale::messages;
117const locale::category locale::all;
118
Howard Hinnantec3773c2011-12-01 20:21:04 +0000119#pragma clang diagnostic push
120#pragma clang diagnostic ignored "-Wpadded"
121
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000122class _LIBCPP_HIDDEN locale::__imp
123 : public facet
124{
125 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000126 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000127 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000128public:
129 explicit __imp(size_t refs = 0);
130 explicit __imp(const string& name, size_t refs = 0);
131 __imp(const __imp&);
132 __imp(const __imp&, const string&, locale::category c);
133 __imp(const __imp& other, const __imp& one, locale::category c);
134 __imp(const __imp&, facet* f, long id);
135 ~__imp();
136
137 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000138 bool has_facet(long id) const
139 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000140 const locale::facet* use_facet(long id) const;
141
142 static const locale& make_classic();
143 static locale& make_global();
144private:
145 void install(facet* f, long id);
146 template <class F> void install(F* f) {install(f, f->id.__get());}
147 template <class F> void install_from(const __imp& other);
148};
149
Howard Hinnantec3773c2011-12-01 20:21:04 +0000150#pragma clang diagnostic pop
151
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000152locale::__imp::__imp(size_t refs)
153 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000154 facets_(N),
155 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000156{
157 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000158 install(&make<_VSTD::collate<char> >(1u));
159 install(&make<_VSTD::collate<wchar_t> >(1u));
160 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
161 install(&make<_VSTD::ctype<wchar_t> >(1u));
162 install(&make<codecvt<char, char, mbstate_t> >(1u));
163 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
164 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
165 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
166 install(&make<numpunct<char> >(1u));
167 install(&make<numpunct<wchar_t> >(1u));
168 install(&make<num_get<char> >(1u));
169 install(&make<num_get<wchar_t> >(1u));
170 install(&make<num_put<char> >(1u));
171 install(&make<num_put<wchar_t> >(1u));
172 install(&make<moneypunct<char, false> >(1u));
173 install(&make<moneypunct<char, true> >(1u));
174 install(&make<moneypunct<wchar_t, false> >(1u));
175 install(&make<moneypunct<wchar_t, true> >(1u));
176 install(&make<money_get<char> >(1u));
177 install(&make<money_get<wchar_t> >(1u));
178 install(&make<money_put<char> >(1u));
179 install(&make<money_put<wchar_t> >(1u));
180 install(&make<time_get<char> >(1u));
181 install(&make<time_get<wchar_t> >(1u));
182 install(&make<time_put<char> >(1u));
183 install(&make<time_put<wchar_t> >(1u));
184 install(&make<_VSTD::messages<char> >(1u));
185 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000186}
187
188locale::__imp::__imp(const string& name, size_t refs)
189 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000190 facets_(N),
191 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192{
Howard Hinnantd4444702010-08-11 17:04:31 +0000193#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000194 try
195 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000196#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000197 facets_ = locale::classic().__locale_->facets_;
198 for (unsigned i = 0; i < facets_.size(); ++i)
199 if (facets_[i])
200 facets_[i]->__add_shared();
201 install(new collate_byname<char>(name_));
202 install(new collate_byname<wchar_t>(name_));
203 install(new ctype_byname<char>(name_));
204 install(new ctype_byname<wchar_t>(name_));
205 install(new codecvt_byname<char, char, mbstate_t>(name_));
206 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
207 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
208 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
209 install(new numpunct_byname<char>(name_));
210 install(new numpunct_byname<wchar_t>(name_));
211 install(new moneypunct_byname<char, false>(name_));
212 install(new moneypunct_byname<char, true>(name_));
213 install(new moneypunct_byname<wchar_t, false>(name_));
214 install(new moneypunct_byname<wchar_t, true>(name_));
215 install(new time_get_byname<char>(name_));
216 install(new time_get_byname<wchar_t>(name_));
217 install(new time_put_byname<char>(name_));
218 install(new time_put_byname<wchar_t>(name_));
219 install(new messages_byname<char>(name_));
220 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000221#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000222 }
223 catch (...)
224 {
225 for (unsigned i = 0; i < facets_.size(); ++i)
226 if (facets_[i])
227 facets_[i]->__release_shared();
228 throw;
229 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000230#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000231}
232
Howard Hinnant21772ec2012-12-28 18:15:01 +0000233// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000234// copy constructor` warning emitted by GCC
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000235#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000236#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000237#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000238#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000239
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000240locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000241 : facets_(max<size_t>(N, other.facets_.size())),
242 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000243{
244 facets_ = other.facets_;
245 for (unsigned i = 0; i < facets_.size(); ++i)
246 if (facets_[i])
247 facets_[i]->__add_shared();
248}
249
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000250#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000251#pragma GCC diagnostic pop
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000252#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000253
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000254locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000255 : facets_(N),
256 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000257{
258 facets_ = other.facets_;
259 for (unsigned i = 0; i < facets_.size(); ++i)
260 if (facets_[i])
261 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000262#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000263 try
264 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000265#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000266 if (c & locale::collate)
267 {
268 install(new collate_byname<char>(name));
269 install(new collate_byname<wchar_t>(name));
270 }
271 if (c & locale::ctype)
272 {
273 install(new ctype_byname<char>(name));
274 install(new ctype_byname<wchar_t>(name));
275 install(new codecvt_byname<char, char, mbstate_t>(name));
276 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
277 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
278 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
279 }
280 if (c & locale::monetary)
281 {
282 install(new moneypunct_byname<char, false>(name));
283 install(new moneypunct_byname<char, true>(name));
284 install(new moneypunct_byname<wchar_t, false>(name));
285 install(new moneypunct_byname<wchar_t, true>(name));
286 }
287 if (c & locale::numeric)
288 {
289 install(new numpunct_byname<char>(name));
290 install(new numpunct_byname<wchar_t>(name));
291 }
292 if (c & locale::time)
293 {
294 install(new time_get_byname<char>(name));
295 install(new time_get_byname<wchar_t>(name));
296 install(new time_put_byname<char>(name));
297 install(new time_put_byname<wchar_t>(name));
298 }
299 if (c & locale::messages)
300 {
301 install(new messages_byname<char>(name));
302 install(new messages_byname<wchar_t>(name));
303 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000304#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000305 }
306 catch (...)
307 {
308 for (unsigned i = 0; i < facets_.size(); ++i)
309 if (facets_[i])
310 facets_[i]->__release_shared();
311 throw;
312 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000313#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000314}
315
316template<class F>
317inline
318void
319locale::__imp::install_from(const locale::__imp& one)
320{
321 long id = F::id.__get();
322 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
323}
324
325locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000326 : facets_(N),
327 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000328{
329 facets_ = other.facets_;
330 for (unsigned i = 0; i < facets_.size(); ++i)
331 if (facets_[i])
332 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000333#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000334 try
335 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000336#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000337 if (c & locale::collate)
338 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000339 install_from<_VSTD::collate<char> >(one);
340 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000341 }
342 if (c & locale::ctype)
343 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000344 install_from<_VSTD::ctype<char> >(one);
345 install_from<_VSTD::ctype<wchar_t> >(one);
346 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
347 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
348 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
349 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000350 }
351 if (c & locale::monetary)
352 {
353 install_from<moneypunct<char, false> >(one);
354 install_from<moneypunct<char, true> >(one);
355 install_from<moneypunct<wchar_t, false> >(one);
356 install_from<moneypunct<wchar_t, true> >(one);
357 install_from<money_get<char> >(one);
358 install_from<money_get<wchar_t> >(one);
359 install_from<money_put<char> >(one);
360 install_from<money_put<wchar_t> >(one);
361 }
362 if (c & locale::numeric)
363 {
364 install_from<numpunct<char> >(one);
365 install_from<numpunct<wchar_t> >(one);
366 install_from<num_get<char> >(one);
367 install_from<num_get<wchar_t> >(one);
368 install_from<num_put<char> >(one);
369 install_from<num_put<wchar_t> >(one);
370 }
371 if (c & locale::time)
372 {
373 install_from<time_get<char> >(one);
374 install_from<time_get<wchar_t> >(one);
375 install_from<time_put<char> >(one);
376 install_from<time_put<wchar_t> >(one);
377 }
378 if (c & locale::messages)
379 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000380 install_from<_VSTD::messages<char> >(one);
381 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000382 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000383#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000384 }
385 catch (...)
386 {
387 for (unsigned i = 0; i < facets_.size(); ++i)
388 if (facets_[i])
389 facets_[i]->__release_shared();
390 throw;
391 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000392#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000393}
394
395locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000396 : facets_(max<size_t>(N, other.facets_.size()+1)),
397 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000398{
399 f->__add_shared();
400 unique_ptr<facet, release> hold(f);
401 facets_ = other.facets_;
402 for (unsigned i = 0; i < other.facets_.size(); ++i)
403 if (facets_[i])
404 facets_[i]->__add_shared();
405 install(hold.get(), id);
406}
407
408locale::__imp::~__imp()
409{
410 for (unsigned i = 0; i < facets_.size(); ++i)
411 if (facets_[i])
412 facets_[i]->__release_shared();
413}
414
415void
416locale::__imp::install(facet* f, long id)
417{
418 f->__add_shared();
419 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000420 if (static_cast<size_t>(id) >= facets_.size())
421 facets_.resize(static_cast<size_t>(id+1));
422 if (facets_[static_cast<size_t>(id)])
423 facets_[static_cast<size_t>(id)]->__release_shared();
424 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000425}
426
427const locale::facet*
428locale::__imp::use_facet(long id) const
429{
Howard Hinnantd4444702010-08-11 17:04:31 +0000430#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000431 if (!has_facet(id))
432 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000433#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000434 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000435}
436
437// locale
438
439const locale&
440locale::__imp::make_classic()
441{
442 // only one thread can get in here and it only gets in once
443 static aligned_storage<sizeof(locale)>::type buf;
444 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000445 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000446 return *c;
447}
448
449const locale&
450locale::classic()
451{
452 static const locale& c = __imp::make_classic();
453 return c;
454}
455
456locale&
457locale::__imp::make_global()
458{
459 // only one thread can get in here and it only gets in once
460 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000461 ::new (&buf) locale(locale::classic());
462 return *(locale*)&buf;
463}
464
465locale&
466locale::__global()
467{
468 static locale& g = __imp::make_global();
469 return g;
470}
471
Howard Hinnantc9834542011-05-31 15:34:58 +0000472locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000473 : __locale_(__global().__locale_)
474{
475 __locale_->__add_shared();
476}
477
Howard Hinnantc9834542011-05-31 15:34:58 +0000478locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000479 : __locale_(l.__locale_)
480{
481 __locale_->__add_shared();
482}
483
Howard Hinnantc9834542011-05-31 15:34:58 +0000484locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000485{
486 __locale_->__release_shared();
487}
488
489const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000490locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000491{
492 other.__locale_->__add_shared();
493 __locale_->__release_shared();
494 __locale_ = other.__locale_;
495 return *this;
496}
497
498locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000499#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000500 : __locale_(name ? new __imp(name)
501 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000502#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000503 : __locale_(new __imp(name))
504#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000505{
506 __locale_->__add_shared();
507}
508
509locale::locale(const string& name)
510 : __locale_(new __imp(name))
511{
512 __locale_->__add_shared();
513}
514
515locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000516#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000517 : __locale_(name ? new __imp(*other.__locale_, name, c)
518 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000519#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000520 : __locale_(new __imp(*other.__locale_, name, c))
521#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000522{
523 __locale_->__add_shared();
524}
525
526locale::locale(const locale& other, const string& name, category c)
527 : __locale_(new __imp(*other.__locale_, name, c))
528{
529 __locale_->__add_shared();
530}
531
532locale::locale(const locale& other, const locale& one, category c)
533 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
534{
535 __locale_->__add_shared();
536}
537
538string
539locale::name() const
540{
541 return __locale_->name();
542}
543
544void
545locale::__install_ctor(const locale& other, facet* f, long id)
546{
547 if (f)
548 __locale_ = new __imp(*other.__locale_, f, id);
549 else
550 __locale_ = other.__locale_;
551 __locale_->__add_shared();
552}
553
554locale
555locale::global(const locale& loc)
556{
557 locale& g = __global();
558 locale r = g;
559 g = loc;
560 if (g.name() != "*")
561 setlocale(LC_ALL, g.name().c_str());
562 return r;
563}
564
565bool
566locale::has_facet(id& x) const
567{
568 return __locale_->has_facet(x.__get());
569}
570
571const locale::facet*
572locale::use_facet(id& x) const
573{
574 return __locale_->use_facet(x.__get());
575}
576
577bool
578locale::operator==(const locale& y) const
579{
580 return (__locale_ == y.__locale_)
581 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
582}
583
584// locale::facet
585
586locale::facet::~facet()
587{
588}
589
590void
Howard Hinnant1694d232011-05-28 14:41:13 +0000591locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000592{
593 delete this;
594}
595
596// locale::id
597
598int32_t locale::id::__next_id = 0;
599
600namespace
601{
602
603class __fake_bind
604{
605 locale::id* id_;
606 void (locale::id::* pmf_)();
607public:
608 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
609 : id_(id), pmf_(pmf) {}
610
611 void operator()() const
612 {
613 (id_->*pmf_)();
614 }
615};
616
617}
618
619long
620locale::id::__get()
621{
622 call_once(__flag_, __fake_bind(&locale::id::__init, this));
623 return __id_ - 1;
624}
625
626void
627locale::id::__init()
628{
Howard Hinnantadff4892010-05-24 17:49:41 +0000629 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000630}
631
632// template <> class collate_byname<char>
633
634collate_byname<char>::collate_byname(const char* n, size_t refs)
635 : collate<char>(refs),
636 __l(newlocale(LC_ALL_MASK, n, 0))
637{
Howard Hinnantd4444702010-08-11 17:04:31 +0000638#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000639 if (__l == 0)
640 throw runtime_error("collate_byname<char>::collate_byname"
641 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000642#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000643}
644
645collate_byname<char>::collate_byname(const string& name, size_t refs)
646 : collate<char>(refs),
647 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
648{
Howard Hinnantd4444702010-08-11 17:04:31 +0000649#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000650 if (__l == 0)
651 throw runtime_error("collate_byname<char>::collate_byname"
652 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000653#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000654}
655
656collate_byname<char>::~collate_byname()
657{
658 freelocale(__l);
659}
660
661int
662collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
663 const char_type* __lo2, const char_type* __hi2) const
664{
665 string_type lhs(__lo1, __hi1);
666 string_type rhs(__lo2, __hi2);
667 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
668 if (r < 0)
669 return -1;
670 if (r > 0)
671 return 1;
672 return r;
673}
674
675collate_byname<char>::string_type
676collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
677{
678 const string_type in(lo, hi);
679 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
680 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
681 return out;
682}
683
684// template <> class collate_byname<wchar_t>
685
686collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
687 : collate<wchar_t>(refs),
688 __l(newlocale(LC_ALL_MASK, n, 0))
689{
Howard Hinnantd4444702010-08-11 17:04:31 +0000690#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000691 if (__l == 0)
692 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
693 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000694#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000695}
696
697collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
698 : collate<wchar_t>(refs),
699 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
700{
Howard Hinnantd4444702010-08-11 17:04:31 +0000701#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000702 if (__l == 0)
703 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
704 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000705#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000706}
707
708collate_byname<wchar_t>::~collate_byname()
709{
710 freelocale(__l);
711}
712
713int
714collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
715 const char_type* __lo2, const char_type* __hi2) const
716{
717 string_type lhs(__lo1, __hi1);
718 string_type rhs(__lo2, __hi2);
719 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
720 if (r < 0)
721 return -1;
722 if (r > 0)
723 return 1;
724 return r;
725}
726
727collate_byname<wchar_t>::string_type
728collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
729{
730 const string_type in(lo, hi);
731 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
732 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
733 return out;
734}
735
736// template <> class ctype<wchar_t>;
737
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000738const ctype_base::mask ctype_base::space;
739const ctype_base::mask ctype_base::print;
740const ctype_base::mask ctype_base::cntrl;
741const ctype_base::mask ctype_base::upper;
742const ctype_base::mask ctype_base::lower;
743const ctype_base::mask ctype_base::alpha;
744const ctype_base::mask ctype_base::digit;
745const ctype_base::mask ctype_base::punct;
746const ctype_base::mask ctype_base::xdigit;
747const ctype_base::mask ctype_base::blank;
748const ctype_base::mask ctype_base::alnum;
749const ctype_base::mask ctype_base::graph;
750
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000751locale::id ctype<wchar_t>::id;
752
753ctype<wchar_t>::~ctype()
754{
755}
756
757bool
758ctype<wchar_t>::do_is(mask m, char_type c) const
759{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000760 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000761}
762
763const wchar_t*
764ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
765{
766 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000767 *vec = static_cast<mask>(isascii(*low) ?
768 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000769 return low;
770}
771
772const wchar_t*
773ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
774{
775 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000776 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000777 break;
778 return low;
779}
780
781const wchar_t*
782ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
783{
784 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000785 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000786 break;
787 return low;
788}
789
790wchar_t
791ctype<wchar_t>::do_toupper(char_type c) const
792{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000793#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
794 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000795#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000796 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000797#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000798 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000799#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000800}
801
802const wchar_t*
803ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
804{
805 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000806#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
807 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000808#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000809 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
810 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000811#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000812 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000813#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000814 return low;
815}
816
817wchar_t
818ctype<wchar_t>::do_tolower(char_type c) const
819{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000820#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
821 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000822#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000823 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000824#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000825 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000826#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000827}
828
829const wchar_t*
830ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
831{
832 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000833#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
834 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000835#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000836 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
837 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000838#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000839 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000840#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000841 return low;
842}
843
844wchar_t
845ctype<wchar_t>::do_widen(char c) const
846{
847 return c;
848}
849
850const char*
851ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
852{
853 for (; low != high; ++low, ++dest)
854 *dest = *low;
855 return low;
856}
857
858char
859ctype<wchar_t>::do_narrow(char_type c, char dfault) const
860{
861 if (isascii(c))
862 return static_cast<char>(c);
863 return dfault;
864}
865
866const wchar_t*
867ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
868{
869 for (; low != high; ++low, ++dest)
870 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000871 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000872 else
873 *dest = dfault;
874 return low;
875}
876
877// template <> class ctype<char>;
878
879locale::id ctype<char>::id;
880
881ctype<char>::ctype(const mask* tab, bool del, size_t refs)
882 : locale::facet(refs),
883 __tab_(tab),
884 __del_(del)
885{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000886 if (__tab_ == 0)
887 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000888}
889
890ctype<char>::~ctype()
891{
892 if (__tab_ && __del_)
893 delete [] __tab_;
894}
895
896char
897ctype<char>::do_toupper(char_type c) const
898{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000899#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000900 return isascii(c) ?
901 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000902#elif defined(__NetBSD__)
903 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000904#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000905 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000906 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000907#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000908 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000909#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000910}
911
912const char*
913ctype<char>::do_toupper(char_type* low, const char_type* high) const
914{
915 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000916#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000917 *low = isascii(*low) ?
918 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000919#elif defined(__NetBSD__)
920 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000921#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000922 *low = isascii(*low) ?
923 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000924#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000925 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000926#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000927 return low;
928}
929
930char
931ctype<char>::do_tolower(char_type c) const
932{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000933#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000934 return isascii(c) ?
935 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000936#elif defined(__NetBSD__)
937 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
938#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Marshall Clow88c31902013-02-07 14:22:51 +0000939 return isascii(c) ?
940 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000941#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000942 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000943#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000944}
945
946const char*
947ctype<char>::do_tolower(char_type* low, const char_type* high) const
948{
949 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000950#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000951 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000952#elif defined(__NetBSD__)
953 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000954#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000955 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000956#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000957 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000958#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000959 return low;
960}
961
962char
963ctype<char>::do_widen(char c) const
964{
965 return c;
966}
967
968const char*
969ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
970{
971 for (; low != high; ++low, ++dest)
972 *dest = *low;
973 return low;
974}
975
976char
977ctype<char>::do_narrow(char_type c, char dfault) const
978{
979 if (isascii(c))
980 return static_cast<char>(c);
981 return dfault;
982}
983
984const char*
985ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
986{
987 for (; low != high; ++low, ++dest)
988 if (isascii(*low))
989 *dest = *low;
990 else
991 *dest = dfault;
992 return low;
993}
994
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000995#ifdef EMSCRIPTEN
996extern "C" const unsigned short ** __ctype_b_loc();
997extern "C" const int ** __ctype_tolower_loc();
998extern "C" const int ** __ctype_toupper_loc();
999#endif
1000
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001001const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001002ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001003{
David Chisnallc512df12011-09-21 08:39:44 +00001004#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001005 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001006#elif defined(__NetBSD__)
1007 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001008#elif defined(__GLIBC__)
1009 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001010#elif __sun__
1011 return __ctype_mask;
Howard Hinnante9df0a52013-08-01 18:17:34 +00001012#elif defined(_LIBCPP_MSVCRT)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001013 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001014// This is assumed to be safe, which is a nonsense assumption because we're
1015// going to end up dereferencing it later...
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001016#elif defined(EMSCRIPTEN)
1017 return *__ctype_b_loc();
Howard Hinnant7f764502013-08-14 18:00:20 +00001018#elif defined(_AIX)
1019 return (const unsigned long *)__lc_ctype_ptr->obj->mask;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001020#else
David Chisnall997e4542012-02-29 13:05:08 +00001021 // Platform not supported: abort so the person doing the port knows what to
1022 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001023# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001024 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001025 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001026 return NULL;
1027#endif
1028}
1029
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001030#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001031const int*
1032ctype<char>::__classic_lower_table() _NOEXCEPT
1033{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001034 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001035}
1036
1037const int*
1038ctype<char>::__classic_upper_table() _NOEXCEPT
1039{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001040 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001041}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001042#elif __NetBSD__
1043const short*
1044ctype<char>::__classic_lower_table() _NOEXCEPT
1045{
1046 return _C_tolower_tab_ + 1;
1047}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001048
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001049const short*
1050ctype<char>::__classic_upper_table() _NOEXCEPT
1051{
1052 return _C_toupper_tab_ + 1;
1053}
1054
1055#elif defined(EMSCRIPTEN)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001056const int*
1057ctype<char>::__classic_lower_table() _NOEXCEPT
1058{
1059 return *__ctype_tolower_loc();
1060}
1061
1062const int*
1063ctype<char>::__classic_upper_table() _NOEXCEPT
1064{
1065 return *__ctype_toupper_loc();
1066}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001067#endif // __GLIBC__ || EMSCRIPTEN || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001068
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001069// template <> class ctype_byname<char>
1070
1071ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1072 : ctype<char>(0, false, refs),
1073 __l(newlocale(LC_ALL_MASK, name, 0))
1074{
Howard Hinnantd4444702010-08-11 17:04:31 +00001075#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001076 if (__l == 0)
1077 throw runtime_error("ctype_byname<char>::ctype_byname"
1078 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001079#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001080}
1081
1082ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1083 : ctype<char>(0, false, refs),
1084 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1085{
Howard Hinnantd4444702010-08-11 17:04:31 +00001086#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001087 if (__l == 0)
1088 throw runtime_error("ctype_byname<char>::ctype_byname"
1089 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001090#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001091}
1092
1093ctype_byname<char>::~ctype_byname()
1094{
1095 freelocale(__l);
1096}
1097
1098char
1099ctype_byname<char>::do_toupper(char_type c) const
1100{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001101 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001102}
1103
1104const char*
1105ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1106{
1107 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001108 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001109 return low;
1110}
1111
1112char
1113ctype_byname<char>::do_tolower(char_type c) const
1114{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001115 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001116}
1117
1118const char*
1119ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1120{
1121 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001122 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001123 return low;
1124}
1125
1126// template <> class ctype_byname<wchar_t>
1127
1128ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1129 : ctype<wchar_t>(refs),
1130 __l(newlocale(LC_ALL_MASK, name, 0))
1131{
Howard Hinnantd4444702010-08-11 17:04:31 +00001132#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001133 if (__l == 0)
1134 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1135 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001136#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001137}
1138
1139ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1140 : ctype<wchar_t>(refs),
1141 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1142{
Howard Hinnantd4444702010-08-11 17:04:31 +00001143#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001144 if (__l == 0)
1145 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1146 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001147#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001148}
1149
1150ctype_byname<wchar_t>::~ctype_byname()
1151{
1152 freelocale(__l);
1153}
1154
1155bool
1156ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1157{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001158#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001159 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001160#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001161 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001162 wint_t ch = static_cast<wint_t>(c);
1163 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1164 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1165 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1166 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1167 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1168 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1169 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1170 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1171 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1172 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001173 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001174#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001175}
1176
1177const wchar_t*
1178ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1179{
1180 for (; low != high; ++low, ++vec)
1181 {
1182 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001183 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001184 else
1185 {
1186 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001187 wint_t ch = static_cast<wint_t>(*low);
1188 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001189 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001190 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001191 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001192 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001193 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001194 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001195 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001196 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001197 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001198 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001199 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001200 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001201 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001202 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001203 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001204 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001205 *vec |= xdigit;
1206 }
1207 }
1208 return low;
1209}
1210
1211const wchar_t*
1212ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1213{
1214 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001215 {
1216#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001217 if (iswctype_l(*low, m, __l))
1218 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001219#else
Marshall Clow88c31902013-02-07 14:22:51 +00001220 wint_t ch = static_cast<wint_t>(*low);
1221 if (m & space && iswspace_l(ch, __l)) break;
1222 if (m & print && iswprint_l(ch, __l)) break;
1223 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1224 if (m & upper && iswupper_l(ch, __l)) break;
1225 if (m & lower && iswlower_l(ch, __l)) break;
1226 if (m & alpha && iswalpha_l(ch, __l)) break;
1227 if (m & digit && iswdigit_l(ch, __l)) break;
1228 if (m & punct && iswpunct_l(ch, __l)) break;
1229 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1230 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001231#endif
1232 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001233 return low;
1234}
1235
1236const wchar_t*
1237ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1238{
1239 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001240 {
1241#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001242 if (!iswctype_l(*low, m, __l))
1243 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001244#else
Marshall Clow88c31902013-02-07 14:22:51 +00001245 wint_t ch = static_cast<wint_t>(*low);
1246 if (m & space && iswspace_l(ch, __l)) continue;
1247 if (m & print && iswprint_l(ch, __l)) continue;
1248 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1249 if (m & upper && iswupper_l(ch, __l)) continue;
1250 if (m & lower && iswlower_l(ch, __l)) continue;
1251 if (m & alpha && iswalpha_l(ch, __l)) continue;
1252 if (m & digit && iswdigit_l(ch, __l)) continue;
1253 if (m & punct && iswpunct_l(ch, __l)) continue;
1254 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1255 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001256 break;
1257#endif
1258 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001259 return low;
1260}
1261
1262wchar_t
1263ctype_byname<wchar_t>::do_toupper(char_type c) const
1264{
1265 return towupper_l(c, __l);
1266}
1267
1268const wchar_t*
1269ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1270{
1271 for (; low != high; ++low)
1272 *low = towupper_l(*low, __l);
1273 return low;
1274}
1275
1276wchar_t
1277ctype_byname<wchar_t>::do_tolower(char_type c) const
1278{
1279 return towlower_l(c, __l);
1280}
1281
1282const wchar_t*
1283ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1284{
1285 for (; low != high; ++low)
1286 *low = towlower_l(*low, __l);
1287 return low;
1288}
1289
1290wchar_t
1291ctype_byname<wchar_t>::do_widen(char c) const
1292{
Howard Hinnant866569b2011-09-28 23:39:33 +00001293#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001294 return btowc_l(c, __l);
1295#else
1296 return __btowc_l(c, __l);
1297#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001298}
1299
1300const char*
1301ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1302{
1303 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001304#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001305 *dest = btowc_l(*low, __l);
1306#else
1307 *dest = __btowc_l(*low, __l);
1308#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001309 return low;
1310}
1311
1312char
1313ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1314{
Howard Hinnant866569b2011-09-28 23:39:33 +00001315#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001316 int r = wctob_l(c, __l);
1317#else
1318 int r = __wctob_l(c, __l);
1319#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001320 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001321}
1322
1323const wchar_t*
1324ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1325{
1326 for (; low != high; ++low, ++dest)
1327 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001328#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001329 int r = wctob_l(*low, __l);
1330#else
1331 int r = __wctob_l(*low, __l);
1332#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001333 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001334 }
1335 return low;
1336}
1337
1338// template <> class codecvt<char, char, mbstate_t>
1339
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001340locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001341
1342codecvt<char, char, mbstate_t>::~codecvt()
1343{
1344}
1345
1346codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001347codecvt<char, char, mbstate_t>::do_out(state_type&,
1348 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001349 extern_type* to, extern_type*, extern_type*& to_nxt) const
1350{
1351 frm_nxt = frm;
1352 to_nxt = to;
1353 return noconv;
1354}
1355
1356codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001357codecvt<char, char, mbstate_t>::do_in(state_type&,
1358 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001359 intern_type* to, intern_type*, intern_type*& to_nxt) const
1360{
1361 frm_nxt = frm;
1362 to_nxt = to;
1363 return noconv;
1364}
1365
1366codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001367codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001368 extern_type* to, extern_type*, extern_type*& to_nxt) const
1369{
1370 to_nxt = to;
1371 return noconv;
1372}
1373
1374int
Howard Hinnantc9834542011-05-31 15:34:58 +00001375codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001376{
1377 return 1;
1378}
1379
1380bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001381codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001382{
1383 return true;
1384}
1385
1386int
1387codecvt<char, char, mbstate_t>::do_length(state_type&,
1388 const extern_type* frm, const extern_type* end, size_t mx) const
1389{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001390 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001391}
1392
1393int
Howard Hinnantc9834542011-05-31 15:34:58 +00001394codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001395{
1396 return 1;
1397}
1398
1399// template <> class codecvt<wchar_t, char, mbstate_t>
1400
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001401locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001402
1403codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1404 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001405 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001406{
1407}
1408
1409codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1410 : locale::facet(refs),
1411 __l(newlocale(LC_ALL_MASK, nm, 0))
1412{
Howard Hinnantd4444702010-08-11 17:04:31 +00001413#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001414 if (__l == 0)
1415 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1416 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001417#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001418}
1419
1420codecvt<wchar_t, char, mbstate_t>::~codecvt()
1421{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001422 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001423 freelocale(__l);
1424}
1425
1426codecvt<wchar_t, char, mbstate_t>::result
1427codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001428 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001429 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1430{
1431 // look for first internal null in frm
1432 const intern_type* fend = frm;
1433 for (; fend != frm_end; ++fend)
1434 if (*fend == 0)
1435 break;
1436 // loop over all null-terminated sequences in frm
1437 to_nxt = to;
1438 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1439 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001440 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001441 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001442#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001443 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1444 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001445#else
1446 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1447#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001448 if (n == size_t(-1))
1449 {
1450 // need to recover to_nxt
1451 for (to_nxt = to; frm != frm_nxt; ++frm)
1452 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001453#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001454 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1455#else
1456 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1457#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458 if (n == size_t(-1))
1459 break;
1460 to_nxt += n;
1461 }
1462 frm_nxt = frm;
1463 return error;
1464 }
1465 if (n == 0)
1466 return partial;
1467 to_nxt += n;
1468 if (to_nxt == to_end)
1469 break;
1470 if (fend != frm_end) // set up next null terminated sequence
1471 {
1472 // Try to write the terminating null
1473 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001474#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001475 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1476#else
1477 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1478#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001479 if (n == size_t(-1)) // on error
1480 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001481 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001482 return partial;
1483 for (extern_type* p = tmp; n; --n) // write it
1484 *to_nxt++ = *p++;
1485 ++frm_nxt;
1486 // look for next null in frm
1487 for (fend = frm_nxt; fend != frm_end; ++fend)
1488 if (*fend == 0)
1489 break;
1490 }
1491 }
1492 return frm_nxt == frm_end ? ok : partial;
1493}
1494
1495codecvt<wchar_t, char, mbstate_t>::result
1496codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001497 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001498 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1499{
1500 // look for first internal null in frm
1501 const extern_type* fend = frm;
1502 for (; fend != frm_end; ++fend)
1503 if (*fend == 0)
1504 break;
1505 // loop over all null-terminated sequences in frm
1506 to_nxt = to;
1507 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1508 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001509 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001510 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001511#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001512 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1513 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001514#else
1515 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1516#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001517 if (n == size_t(-1))
1518 {
1519 // need to recover to_nxt
1520 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1521 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001522#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001523 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1524 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001525#else
1526 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1527#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001528 switch (n)
1529 {
1530 case 0:
1531 ++frm;
1532 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001533 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001534 frm_nxt = frm;
1535 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001536 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001537 frm_nxt = frm;
1538 return partial;
1539 default:
1540 frm += n;
1541 break;
1542 }
1543 }
1544 frm_nxt = frm;
1545 return frm_nxt == frm_end ? ok : partial;
1546 }
1547 if (n == 0)
1548 return error;
1549 to_nxt += n;
1550 if (to_nxt == to_end)
1551 break;
1552 if (fend != frm_end) // set up next null terminated sequence
1553 {
1554 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001555#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001556 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1557#else
1558 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1559#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001560 if (n != 0) // on error
1561 return error;
1562 ++to_nxt;
1563 ++frm_nxt;
1564 // look for next null in frm
1565 for (fend = frm_nxt; fend != frm_end; ++fend)
1566 if (*fend == 0)
1567 break;
1568 }
1569 }
1570 return frm_nxt == frm_end ? ok : partial;
1571}
1572
1573codecvt<wchar_t, char, mbstate_t>::result
1574codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1575 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1576{
1577 to_nxt = to;
1578 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001579#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001580 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1581#else
1582 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1583#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001584 if (n == size_t(-1) || n == 0) // on error
1585 return error;
1586 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001587 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001588 return partial;
1589 for (extern_type* p = tmp; n; --n) // write it
1590 *to_nxt++ = *p++;
1591 return ok;
1592}
1593
1594int
Howard Hinnantc9834542011-05-31 15:34:58 +00001595codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001596{
Howard Hinnant866569b2011-09-28 23:39:33 +00001597#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001598 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1599#else
1600 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1601#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001602 {
1603 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001604#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001605 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1606#else
1607 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1608#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001609 return 1; // which take more than 1 char to form a wchar_t
1610 return 0;
1611 }
1612 return -1;
1613}
1614
1615bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001616codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001617{
1618 return false;
1619}
1620
1621int
1622codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1623 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1624{
1625 int nbytes = 0;
1626 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1627 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001628#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001629 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001630#else
1631 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1632#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001633 switch (n)
1634 {
1635 case 0:
1636 ++nbytes;
1637 ++frm;
1638 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001639 case size_t(-1):
1640 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001641 return nbytes;
1642 default:
1643 nbytes += n;
1644 frm += n;
1645 break;
1646 }
1647 }
1648 return nbytes;
1649}
1650
1651int
Howard Hinnantc9834542011-05-31 15:34:58 +00001652codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001653{
Howard Hinnant866569b2011-09-28 23:39:33 +00001654#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001655 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001656#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001657 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001658#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001659}
1660
1661// Valid UTF ranges
1662// UTF-32 UTF-16 UTF-8 # of code points
1663// first second first second third fourth
1664// 000000 - 00007F 0000 - 007F 00 - 7F 127
1665// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1666// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1667// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1668// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1669// 00D800 - 00DFFF invalid
1670// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1671// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1672// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1673// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1674
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001675static
1676codecvt_base::result
1677utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1678 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1679 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1680{
1681 frm_nxt = frm;
1682 to_nxt = to;
1683 if (mode & generate_header)
1684 {
1685 if (to_end-to_nxt < 3)
1686 return codecvt_base::partial;
1687 *to_nxt++ = static_cast<uint8_t>(0xEF);
1688 *to_nxt++ = static_cast<uint8_t>(0xBB);
1689 *to_nxt++ = static_cast<uint8_t>(0xBF);
1690 }
1691 for (; frm_nxt < frm_end; ++frm_nxt)
1692 {
1693 uint16_t wc1 = *frm_nxt;
1694 if (wc1 > Maxcode)
1695 return codecvt_base::error;
1696 if (wc1 < 0x0080)
1697 {
1698 if (to_end-to_nxt < 1)
1699 return codecvt_base::partial;
1700 *to_nxt++ = static_cast<uint8_t>(wc1);
1701 }
1702 else if (wc1 < 0x0800)
1703 {
1704 if (to_end-to_nxt < 2)
1705 return codecvt_base::partial;
1706 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1707 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1708 }
1709 else if (wc1 < 0xD800)
1710 {
1711 if (to_end-to_nxt < 3)
1712 return codecvt_base::partial;
1713 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1714 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1715 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1716 }
1717 else if (wc1 < 0xDC00)
1718 {
1719 if (frm_end-frm_nxt < 2)
1720 return codecvt_base::partial;
1721 uint16_t wc2 = frm_nxt[1];
1722 if ((wc2 & 0xFC00) != 0xDC00)
1723 return codecvt_base::error;
1724 if (to_end-to_nxt < 4)
1725 return codecvt_base::partial;
1726 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1727 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1728 return codecvt_base::error;
1729 ++frm_nxt;
1730 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1731 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1732 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1733 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1734 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1735 }
1736 else if (wc1 < 0xE000)
1737 {
1738 return codecvt_base::error;
1739 }
1740 else
1741 {
1742 if (to_end-to_nxt < 3)
1743 return codecvt_base::partial;
1744 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1745 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1746 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1747 }
1748 }
1749 return codecvt_base::ok;
1750}
1751
1752static
1753codecvt_base::result
1754utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1755 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1756 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1757{
1758 frm_nxt = frm;
1759 to_nxt = to;
1760 if (mode & generate_header)
1761 {
1762 if (to_end-to_nxt < 3)
1763 return codecvt_base::partial;
1764 *to_nxt++ = static_cast<uint8_t>(0xEF);
1765 *to_nxt++ = static_cast<uint8_t>(0xBB);
1766 *to_nxt++ = static_cast<uint8_t>(0xBF);
1767 }
1768 for (; frm_nxt < frm_end; ++frm_nxt)
1769 {
1770 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1771 if (wc1 > Maxcode)
1772 return codecvt_base::error;
1773 if (wc1 < 0x0080)
1774 {
1775 if (to_end-to_nxt < 1)
1776 return codecvt_base::partial;
1777 *to_nxt++ = static_cast<uint8_t>(wc1);
1778 }
1779 else if (wc1 < 0x0800)
1780 {
1781 if (to_end-to_nxt < 2)
1782 return codecvt_base::partial;
1783 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1784 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1785 }
1786 else if (wc1 < 0xD800)
1787 {
1788 if (to_end-to_nxt < 3)
1789 return codecvt_base::partial;
1790 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1791 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1792 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1793 }
1794 else if (wc1 < 0xDC00)
1795 {
1796 if (frm_end-frm_nxt < 2)
1797 return codecvt_base::partial;
1798 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1799 if ((wc2 & 0xFC00) != 0xDC00)
1800 return codecvt_base::error;
1801 if (to_end-to_nxt < 4)
1802 return codecvt_base::partial;
1803 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1804 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1805 return codecvt_base::error;
1806 ++frm_nxt;
1807 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1808 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1809 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1810 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1811 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1812 }
1813 else if (wc1 < 0xE000)
1814 {
1815 return codecvt_base::error;
1816 }
1817 else
1818 {
1819 if (to_end-to_nxt < 3)
1820 return codecvt_base::partial;
1821 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1822 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1823 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1824 }
1825 }
1826 return codecvt_base::ok;
1827}
1828
1829static
1830codecvt_base::result
1831utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1832 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1833 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1834{
1835 frm_nxt = frm;
1836 to_nxt = to;
1837 if (mode & consume_header)
1838 {
1839 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1840 frm_nxt[2] == 0xBF)
1841 frm_nxt += 3;
1842 }
1843 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1844 {
1845 uint8_t c1 = *frm_nxt;
1846 if (c1 > Maxcode)
1847 return codecvt_base::error;
1848 if (c1 < 0x80)
1849 {
1850 *to_nxt = static_cast<uint16_t>(c1);
1851 ++frm_nxt;
1852 }
1853 else if (c1 < 0xC2)
1854 {
1855 return codecvt_base::error;
1856 }
1857 else if (c1 < 0xE0)
1858 {
1859 if (frm_end-frm_nxt < 2)
1860 return codecvt_base::partial;
1861 uint8_t c2 = frm_nxt[1];
1862 if ((c2 & 0xC0) != 0x80)
1863 return codecvt_base::error;
1864 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1865 if (t > Maxcode)
1866 return codecvt_base::error;
1867 *to_nxt = t;
1868 frm_nxt += 2;
1869 }
1870 else if (c1 < 0xF0)
1871 {
1872 if (frm_end-frm_nxt < 3)
1873 return codecvt_base::partial;
1874 uint8_t c2 = frm_nxt[1];
1875 uint8_t c3 = frm_nxt[2];
1876 switch (c1)
1877 {
1878 case 0xE0:
1879 if ((c2 & 0xE0) != 0xA0)
1880 return codecvt_base::error;
1881 break;
1882 case 0xED:
1883 if ((c2 & 0xE0) != 0x80)
1884 return codecvt_base::error;
1885 break;
1886 default:
1887 if ((c2 & 0xC0) != 0x80)
1888 return codecvt_base::error;
1889 break;
1890 }
1891 if ((c3 & 0xC0) != 0x80)
1892 return codecvt_base::error;
1893 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1894 | ((c2 & 0x3F) << 6)
1895 | (c3 & 0x3F));
1896 if (t > Maxcode)
1897 return codecvt_base::error;
1898 *to_nxt = t;
1899 frm_nxt += 3;
1900 }
1901 else if (c1 < 0xF5)
1902 {
1903 if (frm_end-frm_nxt < 4)
1904 return codecvt_base::partial;
1905 uint8_t c2 = frm_nxt[1];
1906 uint8_t c3 = frm_nxt[2];
1907 uint8_t c4 = frm_nxt[3];
1908 switch (c1)
1909 {
1910 case 0xF0:
1911 if (!(0x90 <= c2 && c2 <= 0xBF))
1912 return codecvt_base::error;
1913 break;
1914 case 0xF4:
1915 if ((c2 & 0xF0) != 0x80)
1916 return codecvt_base::error;
1917 break;
1918 default:
1919 if ((c2 & 0xC0) != 0x80)
1920 return codecvt_base::error;
1921 break;
1922 }
1923 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1924 return codecvt_base::error;
1925 if (to_end-to_nxt < 2)
1926 return codecvt_base::partial;
1927 if (((((unsigned long)c1 & 7) << 18) +
1928 (((unsigned long)c2 & 0x3F) << 12) +
1929 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1930 return codecvt_base::error;
1931 *to_nxt = static_cast<uint16_t>(
1932 0xD800
1933 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1934 | ((c2 & 0x0F) << 2)
1935 | ((c3 & 0x30) >> 4));
1936 *++to_nxt = static_cast<uint16_t>(
1937 0xDC00
1938 | ((c3 & 0x0F) << 6)
1939 | (c4 & 0x3F));
1940 frm_nxt += 4;
1941 }
1942 else
1943 {
1944 return codecvt_base::error;
1945 }
1946 }
1947 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1948}
1949
1950static
1951codecvt_base::result
1952utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1953 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1954 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1955{
1956 frm_nxt = frm;
1957 to_nxt = to;
1958 if (mode & consume_header)
1959 {
1960 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1961 frm_nxt[2] == 0xBF)
1962 frm_nxt += 3;
1963 }
1964 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1965 {
1966 uint8_t c1 = *frm_nxt;
1967 if (c1 > Maxcode)
1968 return codecvt_base::error;
1969 if (c1 < 0x80)
1970 {
1971 *to_nxt = static_cast<uint32_t>(c1);
1972 ++frm_nxt;
1973 }
1974 else if (c1 < 0xC2)
1975 {
1976 return codecvt_base::error;
1977 }
1978 else if (c1 < 0xE0)
1979 {
1980 if (frm_end-frm_nxt < 2)
1981 return codecvt_base::partial;
1982 uint8_t c2 = frm_nxt[1];
1983 if ((c2 & 0xC0) != 0x80)
1984 return codecvt_base::error;
1985 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1986 if (t > Maxcode)
1987 return codecvt_base::error;
1988 *to_nxt = static_cast<uint32_t>(t);
1989 frm_nxt += 2;
1990 }
1991 else if (c1 < 0xF0)
1992 {
1993 if (frm_end-frm_nxt < 3)
1994 return codecvt_base::partial;
1995 uint8_t c2 = frm_nxt[1];
1996 uint8_t c3 = frm_nxt[2];
1997 switch (c1)
1998 {
1999 case 0xE0:
2000 if ((c2 & 0xE0) != 0xA0)
2001 return codecvt_base::error;
2002 break;
2003 case 0xED:
2004 if ((c2 & 0xE0) != 0x80)
2005 return codecvt_base::error;
2006 break;
2007 default:
2008 if ((c2 & 0xC0) != 0x80)
2009 return codecvt_base::error;
2010 break;
2011 }
2012 if ((c3 & 0xC0) != 0x80)
2013 return codecvt_base::error;
2014 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2015 | ((c2 & 0x3F) << 6)
2016 | (c3 & 0x3F));
2017 if (t > Maxcode)
2018 return codecvt_base::error;
2019 *to_nxt = static_cast<uint32_t>(t);
2020 frm_nxt += 3;
2021 }
2022 else if (c1 < 0xF5)
2023 {
2024 if (frm_end-frm_nxt < 4)
2025 return codecvt_base::partial;
2026 uint8_t c2 = frm_nxt[1];
2027 uint8_t c3 = frm_nxt[2];
2028 uint8_t c4 = frm_nxt[3];
2029 switch (c1)
2030 {
2031 case 0xF0:
2032 if (!(0x90 <= c2 && c2 <= 0xBF))
2033 return codecvt_base::error;
2034 break;
2035 case 0xF4:
2036 if ((c2 & 0xF0) != 0x80)
2037 return codecvt_base::error;
2038 break;
2039 default:
2040 if ((c2 & 0xC0) != 0x80)
2041 return codecvt_base::error;
2042 break;
2043 }
2044 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2045 return codecvt_base::error;
2046 if (to_end-to_nxt < 2)
2047 return codecvt_base::partial;
2048 if (((((unsigned long)c1 & 7) << 18) +
2049 (((unsigned long)c2 & 0x3F) << 12) +
2050 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2051 return codecvt_base::error;
2052 *to_nxt = static_cast<uint32_t>(
2053 0xD800
2054 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2055 | ((c2 & 0x0F) << 2)
2056 | ((c3 & 0x30) >> 4));
2057 *++to_nxt = static_cast<uint32_t>(
2058 0xDC00
2059 | ((c3 & 0x0F) << 6)
2060 | (c4 & 0x3F));
2061 frm_nxt += 4;
2062 }
2063 else
2064 {
2065 return codecvt_base::error;
2066 }
2067 }
2068 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2069}
2070
2071static
2072int
2073utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2074 size_t mx, unsigned long Maxcode = 0x10FFFF,
2075 codecvt_mode mode = codecvt_mode(0))
2076{
2077 const uint8_t* frm_nxt = frm;
2078 if (mode & consume_header)
2079 {
2080 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2081 frm_nxt[2] == 0xBF)
2082 frm_nxt += 3;
2083 }
2084 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2085 {
2086 uint8_t c1 = *frm_nxt;
2087 if (c1 > Maxcode)
2088 break;
2089 if (c1 < 0x80)
2090 {
2091 ++frm_nxt;
2092 }
2093 else if (c1 < 0xC2)
2094 {
2095 break;
2096 }
2097 else if (c1 < 0xE0)
2098 {
2099 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2100 break;
2101 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2102 if (t > Maxcode)
2103 break;
2104 frm_nxt += 2;
2105 }
2106 else if (c1 < 0xF0)
2107 {
2108 if (frm_end-frm_nxt < 3)
2109 break;
2110 uint8_t c2 = frm_nxt[1];
2111 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002112 switch (c1)
2113 {
2114 case 0xE0:
2115 if ((c2 & 0xE0) != 0xA0)
2116 return static_cast<int>(frm_nxt - frm);
2117 break;
2118 case 0xED:
2119 if ((c2 & 0xE0) != 0x80)
2120 return static_cast<int>(frm_nxt - frm);
2121 break;
2122 default:
2123 if ((c2 & 0xC0) != 0x80)
2124 return static_cast<int>(frm_nxt - frm);
2125 break;
2126 }
2127 if ((c3 & 0xC0) != 0x80)
2128 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002129 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002130 break;
2131 frm_nxt += 3;
2132 }
2133 else if (c1 < 0xF5)
2134 {
2135 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2136 break;
2137 uint8_t c2 = frm_nxt[1];
2138 uint8_t c3 = frm_nxt[2];
2139 uint8_t c4 = frm_nxt[3];
2140 switch (c1)
2141 {
2142 case 0xF0:
2143 if (!(0x90 <= c2 && c2 <= 0xBF))
2144 return static_cast<int>(frm_nxt - frm);
2145 break;
2146 case 0xF4:
2147 if ((c2 & 0xF0) != 0x80)
2148 return static_cast<int>(frm_nxt - frm);
2149 break;
2150 default:
2151 if ((c2 & 0xC0) != 0x80)
2152 return static_cast<int>(frm_nxt - frm);
2153 break;
2154 }
2155 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2156 break;
2157 if (((((unsigned long)c1 & 7) << 18) +
2158 (((unsigned long)c2 & 0x3F) << 12) +
2159 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2160 break;
2161 ++nchar16_t;
2162 frm_nxt += 4;
2163 }
2164 else
2165 {
2166 break;
2167 }
2168 }
2169 return static_cast<int>(frm_nxt - frm);
2170}
2171
2172static
2173codecvt_base::result
2174ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2175 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2176 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2177{
2178 frm_nxt = frm;
2179 to_nxt = to;
2180 if (mode & generate_header)
2181 {
2182 if (to_end-to_nxt < 3)
2183 return codecvt_base::partial;
2184 *to_nxt++ = static_cast<uint8_t>(0xEF);
2185 *to_nxt++ = static_cast<uint8_t>(0xBB);
2186 *to_nxt++ = static_cast<uint8_t>(0xBF);
2187 }
2188 for (; frm_nxt < frm_end; ++frm_nxt)
2189 {
2190 uint32_t wc = *frm_nxt;
2191 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2192 return codecvt_base::error;
2193 if (wc < 0x000080)
2194 {
2195 if (to_end-to_nxt < 1)
2196 return codecvt_base::partial;
2197 *to_nxt++ = static_cast<uint8_t>(wc);
2198 }
2199 else if (wc < 0x000800)
2200 {
2201 if (to_end-to_nxt < 2)
2202 return codecvt_base::partial;
2203 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2204 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2205 }
2206 else if (wc < 0x010000)
2207 {
2208 if (to_end-to_nxt < 3)
2209 return codecvt_base::partial;
2210 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2211 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2212 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2213 }
2214 else // if (wc < 0x110000)
2215 {
2216 if (to_end-to_nxt < 4)
2217 return codecvt_base::partial;
2218 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2219 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2220 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2221 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2222 }
2223 }
2224 return codecvt_base::ok;
2225}
2226
2227static
2228codecvt_base::result
2229utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2230 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2231 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2232{
2233 frm_nxt = frm;
2234 to_nxt = to;
2235 if (mode & consume_header)
2236 {
2237 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2238 frm_nxt[2] == 0xBF)
2239 frm_nxt += 3;
2240 }
2241 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2242 {
2243 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2244 if (c1 < 0x80)
2245 {
2246 if (c1 > Maxcode)
2247 return codecvt_base::error;
2248 *to_nxt = static_cast<uint32_t>(c1);
2249 ++frm_nxt;
2250 }
2251 else if (c1 < 0xC2)
2252 {
2253 return codecvt_base::error;
2254 }
2255 else if (c1 < 0xE0)
2256 {
2257 if (frm_end-frm_nxt < 2)
2258 return codecvt_base::partial;
2259 uint8_t c2 = frm_nxt[1];
2260 if ((c2 & 0xC0) != 0x80)
2261 return codecvt_base::error;
2262 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2263 | (c2 & 0x3F));
2264 if (t > Maxcode)
2265 return codecvt_base::error;
2266 *to_nxt = t;
2267 frm_nxt += 2;
2268 }
2269 else if (c1 < 0xF0)
2270 {
2271 if (frm_end-frm_nxt < 3)
2272 return codecvt_base::partial;
2273 uint8_t c2 = frm_nxt[1];
2274 uint8_t c3 = frm_nxt[2];
2275 switch (c1)
2276 {
2277 case 0xE0:
2278 if ((c2 & 0xE0) != 0xA0)
2279 return codecvt_base::error;
2280 break;
2281 case 0xED:
2282 if ((c2 & 0xE0) != 0x80)
2283 return codecvt_base::error;
2284 break;
2285 default:
2286 if ((c2 & 0xC0) != 0x80)
2287 return codecvt_base::error;
2288 break;
2289 }
2290 if ((c3 & 0xC0) != 0x80)
2291 return codecvt_base::error;
2292 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2293 | ((c2 & 0x3F) << 6)
2294 | (c3 & 0x3F));
2295 if (t > Maxcode)
2296 return codecvt_base::error;
2297 *to_nxt = t;
2298 frm_nxt += 3;
2299 }
2300 else if (c1 < 0xF5)
2301 {
2302 if (frm_end-frm_nxt < 4)
2303 return codecvt_base::partial;
2304 uint8_t c2 = frm_nxt[1];
2305 uint8_t c3 = frm_nxt[2];
2306 uint8_t c4 = frm_nxt[3];
2307 switch (c1)
2308 {
2309 case 0xF0:
2310 if (!(0x90 <= c2 && c2 <= 0xBF))
2311 return codecvt_base::error;
2312 break;
2313 case 0xF4:
2314 if ((c2 & 0xF0) != 0x80)
2315 return codecvt_base::error;
2316 break;
2317 default:
2318 if ((c2 & 0xC0) != 0x80)
2319 return codecvt_base::error;
2320 break;
2321 }
2322 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2323 return codecvt_base::error;
2324 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2325 | ((c2 & 0x3F) << 12)
2326 | ((c3 & 0x3F) << 6)
2327 | (c4 & 0x3F));
2328 if (t > Maxcode)
2329 return codecvt_base::error;
2330 *to_nxt = t;
2331 frm_nxt += 4;
2332 }
2333 else
2334 {
2335 return codecvt_base::error;
2336 }
2337 }
2338 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2339}
2340
2341static
2342int
2343utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2344 size_t mx, unsigned long Maxcode = 0x10FFFF,
2345 codecvt_mode mode = codecvt_mode(0))
2346{
2347 const uint8_t* frm_nxt = frm;
2348 if (mode & consume_header)
2349 {
2350 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2351 frm_nxt[2] == 0xBF)
2352 frm_nxt += 3;
2353 }
2354 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2355 {
2356 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2357 if (c1 < 0x80)
2358 {
2359 if (c1 > Maxcode)
2360 break;
2361 ++frm_nxt;
2362 }
2363 else if (c1 < 0xC2)
2364 {
2365 break;
2366 }
2367 else if (c1 < 0xE0)
2368 {
2369 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2370 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002371 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002372 break;
2373 frm_nxt += 2;
2374 }
2375 else if (c1 < 0xF0)
2376 {
2377 if (frm_end-frm_nxt < 3)
2378 break;
2379 uint8_t c2 = frm_nxt[1];
2380 uint8_t c3 = frm_nxt[2];
2381 switch (c1)
2382 {
2383 case 0xE0:
2384 if ((c2 & 0xE0) != 0xA0)
2385 return static_cast<int>(frm_nxt - frm);
2386 break;
2387 case 0xED:
2388 if ((c2 & 0xE0) != 0x80)
2389 return static_cast<int>(frm_nxt - frm);
2390 break;
2391 default:
2392 if ((c2 & 0xC0) != 0x80)
2393 return static_cast<int>(frm_nxt - frm);
2394 break;
2395 }
2396 if ((c3 & 0xC0) != 0x80)
2397 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002398 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002399 break;
2400 frm_nxt += 3;
2401 }
2402 else if (c1 < 0xF5)
2403 {
2404 if (frm_end-frm_nxt < 4)
2405 break;
2406 uint8_t c2 = frm_nxt[1];
2407 uint8_t c3 = frm_nxt[2];
2408 uint8_t c4 = frm_nxt[3];
2409 switch (c1)
2410 {
2411 case 0xF0:
2412 if (!(0x90 <= c2 && c2 <= 0xBF))
2413 return static_cast<int>(frm_nxt - frm);
2414 break;
2415 case 0xF4:
2416 if ((c2 & 0xF0) != 0x80)
2417 return static_cast<int>(frm_nxt - frm);
2418 break;
2419 default:
2420 if ((c2 & 0xC0) != 0x80)
2421 return static_cast<int>(frm_nxt - frm);
2422 break;
2423 }
2424 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2425 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002426 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2427 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002428 break;
2429 frm_nxt += 4;
2430 }
2431 else
2432 {
2433 break;
2434 }
2435 }
2436 return static_cast<int>(frm_nxt - frm);
2437}
2438
2439static
2440codecvt_base::result
2441ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2442 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2443 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2444{
2445 frm_nxt = frm;
2446 to_nxt = to;
2447 if (mode & generate_header)
2448 {
2449 if (to_end-to_nxt < 3)
2450 return codecvt_base::partial;
2451 *to_nxt++ = static_cast<uint8_t>(0xEF);
2452 *to_nxt++ = static_cast<uint8_t>(0xBB);
2453 *to_nxt++ = static_cast<uint8_t>(0xBF);
2454 }
2455 for (; frm_nxt < frm_end; ++frm_nxt)
2456 {
2457 uint16_t wc = *frm_nxt;
2458 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2459 return codecvt_base::error;
2460 if (wc < 0x0080)
2461 {
2462 if (to_end-to_nxt < 1)
2463 return codecvt_base::partial;
2464 *to_nxt++ = static_cast<uint8_t>(wc);
2465 }
2466 else if (wc < 0x0800)
2467 {
2468 if (to_end-to_nxt < 2)
2469 return codecvt_base::partial;
2470 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2471 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2472 }
2473 else // if (wc <= 0xFFFF)
2474 {
2475 if (to_end-to_nxt < 3)
2476 return codecvt_base::partial;
2477 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2478 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2479 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2480 }
2481 }
2482 return codecvt_base::ok;
2483}
2484
2485static
2486codecvt_base::result
2487utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2488 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2489 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2490{
2491 frm_nxt = frm;
2492 to_nxt = to;
2493 if (mode & consume_header)
2494 {
2495 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2496 frm_nxt[2] == 0xBF)
2497 frm_nxt += 3;
2498 }
2499 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2500 {
2501 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2502 if (c1 < 0x80)
2503 {
2504 if (c1 > Maxcode)
2505 return codecvt_base::error;
2506 *to_nxt = static_cast<uint16_t>(c1);
2507 ++frm_nxt;
2508 }
2509 else if (c1 < 0xC2)
2510 {
2511 return codecvt_base::error;
2512 }
2513 else if (c1 < 0xE0)
2514 {
2515 if (frm_end-frm_nxt < 2)
2516 return codecvt_base::partial;
2517 uint8_t c2 = frm_nxt[1];
2518 if ((c2 & 0xC0) != 0x80)
2519 return codecvt_base::error;
2520 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2521 | (c2 & 0x3F));
2522 if (t > Maxcode)
2523 return codecvt_base::error;
2524 *to_nxt = t;
2525 frm_nxt += 2;
2526 }
2527 else if (c1 < 0xF0)
2528 {
2529 if (frm_end-frm_nxt < 3)
2530 return codecvt_base::partial;
2531 uint8_t c2 = frm_nxt[1];
2532 uint8_t c3 = frm_nxt[2];
2533 switch (c1)
2534 {
2535 case 0xE0:
2536 if ((c2 & 0xE0) != 0xA0)
2537 return codecvt_base::error;
2538 break;
2539 case 0xED:
2540 if ((c2 & 0xE0) != 0x80)
2541 return codecvt_base::error;
2542 break;
2543 default:
2544 if ((c2 & 0xC0) != 0x80)
2545 return codecvt_base::error;
2546 break;
2547 }
2548 if ((c3 & 0xC0) != 0x80)
2549 return codecvt_base::error;
2550 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2551 | ((c2 & 0x3F) << 6)
2552 | (c3 & 0x3F));
2553 if (t > Maxcode)
2554 return codecvt_base::error;
2555 *to_nxt = t;
2556 frm_nxt += 3;
2557 }
2558 else
2559 {
2560 return codecvt_base::error;
2561 }
2562 }
2563 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2564}
2565
2566static
2567int
2568utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2569 size_t mx, unsigned long Maxcode = 0x10FFFF,
2570 codecvt_mode mode = codecvt_mode(0))
2571{
2572 const uint8_t* frm_nxt = frm;
2573 if (mode & consume_header)
2574 {
2575 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2576 frm_nxt[2] == 0xBF)
2577 frm_nxt += 3;
2578 }
2579 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2580 {
2581 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2582 if (c1 < 0x80)
2583 {
2584 if (c1 > Maxcode)
2585 break;
2586 ++frm_nxt;
2587 }
2588 else if (c1 < 0xC2)
2589 {
2590 break;
2591 }
2592 else if (c1 < 0xE0)
2593 {
2594 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2595 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002596 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002597 break;
2598 frm_nxt += 2;
2599 }
2600 else if (c1 < 0xF0)
2601 {
2602 if (frm_end-frm_nxt < 3)
2603 break;
2604 uint8_t c2 = frm_nxt[1];
2605 uint8_t c3 = frm_nxt[2];
2606 switch (c1)
2607 {
2608 case 0xE0:
2609 if ((c2 & 0xE0) != 0xA0)
2610 return static_cast<int>(frm_nxt - frm);
2611 break;
2612 case 0xED:
2613 if ((c2 & 0xE0) != 0x80)
2614 return static_cast<int>(frm_nxt - frm);
2615 break;
2616 default:
2617 if ((c2 & 0xC0) != 0x80)
2618 return static_cast<int>(frm_nxt - frm);
2619 break;
2620 }
2621 if ((c3 & 0xC0) != 0x80)
2622 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002623 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002624 break;
2625 frm_nxt += 3;
2626 }
2627 else
2628 {
2629 break;
2630 }
2631 }
2632 return static_cast<int>(frm_nxt - frm);
2633}
2634
2635static
2636codecvt_base::result
2637ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2638 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2639 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2640{
2641 frm_nxt = frm;
2642 to_nxt = to;
2643 if (mode & generate_header)
2644 {
2645 if (to_end-to_nxt < 2)
2646 return codecvt_base::partial;
2647 *to_nxt++ = static_cast<uint8_t>(0xFE);
2648 *to_nxt++ = static_cast<uint8_t>(0xFF);
2649 }
2650 for (; frm_nxt < frm_end; ++frm_nxt)
2651 {
2652 uint32_t wc = *frm_nxt;
2653 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2654 return codecvt_base::error;
2655 if (wc < 0x010000)
2656 {
2657 if (to_end-to_nxt < 2)
2658 return codecvt_base::partial;
2659 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2660 *to_nxt++ = static_cast<uint8_t>(wc);
2661 }
2662 else
2663 {
2664 if (to_end-to_nxt < 4)
2665 return codecvt_base::partial;
2666 uint16_t t = static_cast<uint16_t>(
2667 0xD800
2668 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2669 | ((wc & 0x00FC00) >> 10));
2670 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2671 *to_nxt++ = static_cast<uint8_t>(t);
2672 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2673 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2674 *to_nxt++ = static_cast<uint8_t>(t);
2675 }
2676 }
2677 return codecvt_base::ok;
2678}
2679
2680static
2681codecvt_base::result
2682utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2683 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2684 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2685{
2686 frm_nxt = frm;
2687 to_nxt = to;
2688 if (mode & consume_header)
2689 {
2690 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2691 frm_nxt += 2;
2692 }
2693 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2694 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002695 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002696 if ((c1 & 0xFC00) == 0xDC00)
2697 return codecvt_base::error;
2698 if ((c1 & 0xFC00) != 0xD800)
2699 {
2700 if (c1 > Maxcode)
2701 return codecvt_base::error;
2702 *to_nxt = static_cast<uint32_t>(c1);
2703 frm_nxt += 2;
2704 }
2705 else
2706 {
2707 if (frm_end-frm_nxt < 4)
2708 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002709 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002710 if ((c2 & 0xFC00) != 0xDC00)
2711 return codecvt_base::error;
2712 uint32_t t = static_cast<uint32_t>(
2713 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2714 | ((c1 & 0x003F) << 10)
2715 | (c2 & 0x03FF));
2716 if (t > Maxcode)
2717 return codecvt_base::error;
2718 *to_nxt = t;
2719 frm_nxt += 4;
2720 }
2721 }
2722 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2723}
2724
2725static
2726int
2727utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2728 size_t mx, unsigned long Maxcode = 0x10FFFF,
2729 codecvt_mode mode = codecvt_mode(0))
2730{
2731 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002732 if (mode & consume_header)
2733 {
2734 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2735 frm_nxt += 2;
2736 }
2737 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2738 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002739 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002740 if ((c1 & 0xFC00) == 0xDC00)
2741 break;
2742 if ((c1 & 0xFC00) != 0xD800)
2743 {
2744 if (c1 > Maxcode)
2745 break;
2746 frm_nxt += 2;
2747 }
2748 else
2749 {
2750 if (frm_end-frm_nxt < 4)
2751 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002752 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002753 if ((c2 & 0xFC00) != 0xDC00)
2754 break;
2755 uint32_t t = static_cast<uint32_t>(
2756 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2757 | ((c1 & 0x003F) << 10)
2758 | (c2 & 0x03FF));
2759 if (t > Maxcode)
2760 break;
2761 frm_nxt += 4;
2762 }
2763 }
2764 return static_cast<int>(frm_nxt - frm);
2765}
2766
2767static
2768codecvt_base::result
2769ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2770 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2771 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2772{
2773 frm_nxt = frm;
2774 to_nxt = to;
2775 if (mode & generate_header)
2776 {
2777 if (to_end-to_nxt < 2)
2778 return codecvt_base::partial;
2779 *to_nxt++ = static_cast<uint8_t>(0xFF);
2780 *to_nxt++ = static_cast<uint8_t>(0xFE);
2781 }
2782 for (; frm_nxt < frm_end; ++frm_nxt)
2783 {
2784 uint32_t wc = *frm_nxt;
2785 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2786 return codecvt_base::error;
2787 if (wc < 0x010000)
2788 {
2789 if (to_end-to_nxt < 2)
2790 return codecvt_base::partial;
2791 *to_nxt++ = static_cast<uint8_t>(wc);
2792 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2793 }
2794 else
2795 {
2796 if (to_end-to_nxt < 4)
2797 return codecvt_base::partial;
2798 uint16_t t = static_cast<uint16_t>(
2799 0xD800
2800 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2801 | ((wc & 0x00FC00) >> 10));
2802 *to_nxt++ = static_cast<uint8_t>(t);
2803 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2804 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2805 *to_nxt++ = static_cast<uint8_t>(t);
2806 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2807 }
2808 }
2809 return codecvt_base::ok;
2810}
2811
2812static
2813codecvt_base::result
2814utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2815 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2816 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2817{
2818 frm_nxt = frm;
2819 to_nxt = to;
2820 if (mode & consume_header)
2821 {
2822 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2823 frm_nxt += 2;
2824 }
2825 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2826 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002827 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002828 if ((c1 & 0xFC00) == 0xDC00)
2829 return codecvt_base::error;
2830 if ((c1 & 0xFC00) != 0xD800)
2831 {
2832 if (c1 > Maxcode)
2833 return codecvt_base::error;
2834 *to_nxt = static_cast<uint32_t>(c1);
2835 frm_nxt += 2;
2836 }
2837 else
2838 {
2839 if (frm_end-frm_nxt < 4)
2840 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002841 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002842 if ((c2 & 0xFC00) != 0xDC00)
2843 return codecvt_base::error;
2844 uint32_t t = static_cast<uint32_t>(
2845 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2846 | ((c1 & 0x003F) << 10)
2847 | (c2 & 0x03FF));
2848 if (t > Maxcode)
2849 return codecvt_base::error;
2850 *to_nxt = t;
2851 frm_nxt += 4;
2852 }
2853 }
2854 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2855}
2856
2857static
2858int
2859utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2860 size_t mx, unsigned long Maxcode = 0x10FFFF,
2861 codecvt_mode mode = codecvt_mode(0))
2862{
2863 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002864 if (mode & consume_header)
2865 {
2866 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2867 frm_nxt += 2;
2868 }
2869 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2870 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002871 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002872 if ((c1 & 0xFC00) == 0xDC00)
2873 break;
2874 if ((c1 & 0xFC00) != 0xD800)
2875 {
2876 if (c1 > Maxcode)
2877 break;
2878 frm_nxt += 2;
2879 }
2880 else
2881 {
2882 if (frm_end-frm_nxt < 4)
2883 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002884 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002885 if ((c2 & 0xFC00) != 0xDC00)
2886 break;
2887 uint32_t t = static_cast<uint32_t>(
2888 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2889 | ((c1 & 0x003F) << 10)
2890 | (c2 & 0x03FF));
2891 if (t > Maxcode)
2892 break;
2893 frm_nxt += 4;
2894 }
2895 }
2896 return static_cast<int>(frm_nxt - frm);
2897}
2898
2899static
2900codecvt_base::result
2901ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2902 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2903 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2904{
2905 frm_nxt = frm;
2906 to_nxt = to;
2907 if (mode & generate_header)
2908 {
2909 if (to_end-to_nxt < 2)
2910 return codecvt_base::partial;
2911 *to_nxt++ = static_cast<uint8_t>(0xFE);
2912 *to_nxt++ = static_cast<uint8_t>(0xFF);
2913 }
2914 for (; frm_nxt < frm_end; ++frm_nxt)
2915 {
2916 uint16_t wc = *frm_nxt;
2917 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2918 return codecvt_base::error;
2919 if (to_end-to_nxt < 2)
2920 return codecvt_base::partial;
2921 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2922 *to_nxt++ = static_cast<uint8_t>(wc);
2923 }
2924 return codecvt_base::ok;
2925}
2926
2927static
2928codecvt_base::result
2929utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2930 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2931 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2932{
2933 frm_nxt = frm;
2934 to_nxt = to;
2935 if (mode & consume_header)
2936 {
2937 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2938 frm_nxt += 2;
2939 }
2940 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2941 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002942 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002943 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2944 return codecvt_base::error;
2945 *to_nxt = c1;
2946 frm_nxt += 2;
2947 }
2948 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2949}
2950
2951static
2952int
2953utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2954 size_t mx, unsigned long Maxcode = 0x10FFFF,
2955 codecvt_mode mode = codecvt_mode(0))
2956{
2957 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002958 if (mode & consume_header)
2959 {
2960 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2961 frm_nxt += 2;
2962 }
2963 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2964 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002965 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002966 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2967 break;
2968 frm_nxt += 2;
2969 }
2970 return static_cast<int>(frm_nxt - frm);
2971}
2972
2973static
2974codecvt_base::result
2975ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2976 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2977 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2978{
2979 frm_nxt = frm;
2980 to_nxt = to;
2981 if (mode & generate_header)
2982 {
2983 if (to_end-to_nxt < 2)
2984 return codecvt_base::partial;
2985 *to_nxt++ = static_cast<uint8_t>(0xFF);
2986 *to_nxt++ = static_cast<uint8_t>(0xFE);
2987 }
2988 for (; frm_nxt < frm_end; ++frm_nxt)
2989 {
2990 uint16_t wc = *frm_nxt;
2991 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2992 return codecvt_base::error;
2993 if (to_end-to_nxt < 2)
2994 return codecvt_base::partial;
2995 *to_nxt++ = static_cast<uint8_t>(wc);
2996 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2997 }
2998 return codecvt_base::ok;
2999}
3000
3001static
3002codecvt_base::result
3003utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3004 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3005 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3006{
3007 frm_nxt = frm;
3008 to_nxt = to;
3009 if (mode & consume_header)
3010 {
3011 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3012 frm_nxt += 2;
3013 }
3014 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3015 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003016 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003017 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3018 return codecvt_base::error;
3019 *to_nxt = c1;
3020 frm_nxt += 2;
3021 }
3022 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3023}
3024
3025static
3026int
3027utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3028 size_t mx, unsigned long Maxcode = 0x10FFFF,
3029 codecvt_mode mode = codecvt_mode(0))
3030{
3031 const uint8_t* frm_nxt = frm;
3032 frm_nxt = frm;
3033 if (mode & consume_header)
3034 {
3035 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3036 frm_nxt += 2;
3037 }
3038 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3039 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003040 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003041 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3042 break;
3043 frm_nxt += 2;
3044 }
3045 return static_cast<int>(frm_nxt - frm);
3046}
3047
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003048// template <> class codecvt<char16_t, char, mbstate_t>
3049
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003050locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003051
3052codecvt<char16_t, char, mbstate_t>::~codecvt()
3053{
3054}
3055
3056codecvt<char16_t, char, mbstate_t>::result
3057codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003058 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003059 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3060{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003061 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3062 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3063 const uint16_t* _frm_nxt = _frm;
3064 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3065 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3066 uint8_t* _to_nxt = _to;
3067 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3068 frm_nxt = frm + (_frm_nxt - _frm);
3069 to_nxt = to + (_to_nxt - _to);
3070 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003071}
3072
3073codecvt<char16_t, char, mbstate_t>::result
3074codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003075 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003076 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3077{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003078 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3079 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3080 const uint8_t* _frm_nxt = _frm;
3081 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3082 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3083 uint16_t* _to_nxt = _to;
3084 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3085 frm_nxt = frm + (_frm_nxt - _frm);
3086 to_nxt = to + (_to_nxt - _to);
3087 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003088}
3089
3090codecvt<char16_t, char, mbstate_t>::result
3091codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3092 extern_type* to, extern_type*, extern_type*& to_nxt) const
3093{
3094 to_nxt = to;
3095 return noconv;
3096}
3097
3098int
Howard Hinnantc9834542011-05-31 15:34:58 +00003099codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003100{
3101 return 0;
3102}
3103
3104bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003105codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003106{
3107 return false;
3108}
3109
3110int
3111codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3112 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3113{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003114 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3115 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3116 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003117}
3118
3119int
Howard Hinnantc9834542011-05-31 15:34:58 +00003120codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003121{
3122 return 4;
3123}
3124
3125// template <> class codecvt<char32_t, char, mbstate_t>
3126
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003127locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003128
3129codecvt<char32_t, char, mbstate_t>::~codecvt()
3130{
3131}
3132
3133codecvt<char32_t, char, mbstate_t>::result
3134codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003135 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003136 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3137{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003138 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3139 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3140 const uint32_t* _frm_nxt = _frm;
3141 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3142 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3143 uint8_t* _to_nxt = _to;
3144 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3145 frm_nxt = frm + (_frm_nxt - _frm);
3146 to_nxt = to + (_to_nxt - _to);
3147 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003148}
3149
3150codecvt<char32_t, char, mbstate_t>::result
3151codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003152 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003153 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3154{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003155 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3156 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3157 const uint8_t* _frm_nxt = _frm;
3158 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3159 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3160 uint32_t* _to_nxt = _to;
3161 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3162 frm_nxt = frm + (_frm_nxt - _frm);
3163 to_nxt = to + (_to_nxt - _to);
3164 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003165}
3166
3167codecvt<char32_t, char, mbstate_t>::result
3168codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3169 extern_type* to, extern_type*, extern_type*& to_nxt) const
3170{
3171 to_nxt = to;
3172 return noconv;
3173}
3174
3175int
Howard Hinnantc9834542011-05-31 15:34:58 +00003176codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003177{
3178 return 0;
3179}
3180
3181bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003182codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003183{
3184 return false;
3185}
3186
3187int
3188codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3189 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3190{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003191 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3192 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3193 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003194}
3195
3196int
Howard Hinnantc9834542011-05-31 15:34:58 +00003197codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003198{
3199 return 4;
3200}
3201
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003202// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003203
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003204__codecvt_utf8<wchar_t>::result
3205__codecvt_utf8<wchar_t>::do_out(state_type&,
3206 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003207 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3208{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003209#if _WIN32
3210 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3211 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3212 const uint16_t* _frm_nxt = _frm;
3213#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003214 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3215 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3216 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003217#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003218 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3219 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3220 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003221#if _WIN32
3222 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3223 _Maxcode_, _Mode_);
3224#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003225 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3226 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003227#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003228 frm_nxt = frm + (_frm_nxt - _frm);
3229 to_nxt = to + (_to_nxt - _to);
3230 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003231}
3232
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003233__codecvt_utf8<wchar_t>::result
3234__codecvt_utf8<wchar_t>::do_in(state_type&,
3235 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003236 intern_type* to, intern_type* to_end, intern_type*& to_nxt) 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 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003241#if _WIN32
3242 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3243 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3244 uint16_t* _to_nxt = _to;
3245 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3246 _Maxcode_, _Mode_);
3247#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003248 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3249 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3250 uint32_t* _to_nxt = _to;
3251 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3252 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003253#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003254 frm_nxt = frm + (_frm_nxt - _frm);
3255 to_nxt = to + (_to_nxt - _to);
3256 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003257}
3258
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003259__codecvt_utf8<wchar_t>::result
3260__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003261 extern_type* to, extern_type*, extern_type*& to_nxt) const
3262{
3263 to_nxt = to;
3264 return noconv;
3265}
3266
3267int
Howard Hinnantc9834542011-05-31 15:34:58 +00003268__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003269{
3270 return 0;
3271}
3272
3273bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003274__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003275{
3276 return false;
3277}
3278
3279int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003280__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003281 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3282{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003283 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3284 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3285 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003286}
3287
3288int
Howard Hinnantc9834542011-05-31 15:34:58 +00003289__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003290{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003291 if (_Mode_ & consume_header)
3292 return 7;
3293 return 4;
3294}
3295
3296// __codecvt_utf8<char16_t>
3297
3298__codecvt_utf8<char16_t>::result
3299__codecvt_utf8<char16_t>::do_out(state_type&,
3300 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3301 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3302{
3303 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3304 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3305 const uint16_t* _frm_nxt = _frm;
3306 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3307 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3308 uint8_t* _to_nxt = _to;
3309 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3310 _Maxcode_, _Mode_);
3311 frm_nxt = frm + (_frm_nxt - _frm);
3312 to_nxt = to + (_to_nxt - _to);
3313 return r;
3314}
3315
3316__codecvt_utf8<char16_t>::result
3317__codecvt_utf8<char16_t>::do_in(state_type&,
3318 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3319 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3320{
3321 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3322 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3323 const uint8_t* _frm_nxt = _frm;
3324 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3325 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3326 uint16_t* _to_nxt = _to;
3327 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3328 _Maxcode_, _Mode_);
3329 frm_nxt = frm + (_frm_nxt - _frm);
3330 to_nxt = to + (_to_nxt - _to);
3331 return r;
3332}
3333
3334__codecvt_utf8<char16_t>::result
3335__codecvt_utf8<char16_t>::do_unshift(state_type&,
3336 extern_type* to, extern_type*, extern_type*& to_nxt) const
3337{
3338 to_nxt = to;
3339 return noconv;
3340}
3341
3342int
Howard Hinnantc9834542011-05-31 15:34:58 +00003343__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003344{
3345 return 0;
3346}
3347
3348bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003349__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003350{
3351 return false;
3352}
3353
3354int
3355__codecvt_utf8<char16_t>::do_length(state_type&,
3356 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3357{
3358 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3359 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3360 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3361}
3362
3363int
Howard Hinnantc9834542011-05-31 15:34:58 +00003364__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003365{
3366 if (_Mode_ & consume_header)
3367 return 6;
3368 return 3;
3369}
3370
3371// __codecvt_utf8<char32_t>
3372
3373__codecvt_utf8<char32_t>::result
3374__codecvt_utf8<char32_t>::do_out(state_type&,
3375 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3376 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3377{
3378 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3379 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3380 const uint32_t* _frm_nxt = _frm;
3381 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3382 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3383 uint8_t* _to_nxt = _to;
3384 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3385 _Maxcode_, _Mode_);
3386 frm_nxt = frm + (_frm_nxt - _frm);
3387 to_nxt = to + (_to_nxt - _to);
3388 return r;
3389}
3390
3391__codecvt_utf8<char32_t>::result
3392__codecvt_utf8<char32_t>::do_in(state_type&,
3393 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3394 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3395{
3396 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3397 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3398 const uint8_t* _frm_nxt = _frm;
3399 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3400 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3401 uint32_t* _to_nxt = _to;
3402 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3403 _Maxcode_, _Mode_);
3404 frm_nxt = frm + (_frm_nxt - _frm);
3405 to_nxt = to + (_to_nxt - _to);
3406 return r;
3407}
3408
3409__codecvt_utf8<char32_t>::result
3410__codecvt_utf8<char32_t>::do_unshift(state_type&,
3411 extern_type* to, extern_type*, extern_type*& to_nxt) const
3412{
3413 to_nxt = to;
3414 return noconv;
3415}
3416
3417int
Howard Hinnantc9834542011-05-31 15:34:58 +00003418__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003419{
3420 return 0;
3421}
3422
3423bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003424__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003425{
3426 return false;
3427}
3428
3429int
3430__codecvt_utf8<char32_t>::do_length(state_type&,
3431 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3432{
3433 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3434 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3435 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3436}
3437
3438int
Howard Hinnantc9834542011-05-31 15:34:58 +00003439__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003440{
3441 if (_Mode_ & consume_header)
3442 return 7;
3443 return 4;
3444}
3445
3446// __codecvt_utf16<wchar_t, false>
3447
3448__codecvt_utf16<wchar_t, false>::result
3449__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3450 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3451 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3452{
3453 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3454 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3455 const uint32_t* _frm_nxt = _frm;
3456 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3457 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3458 uint8_t* _to_nxt = _to;
3459 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3460 _Maxcode_, _Mode_);
3461 frm_nxt = frm + (_frm_nxt - _frm);
3462 to_nxt = to + (_to_nxt - _to);
3463 return r;
3464}
3465
3466__codecvt_utf16<wchar_t, false>::result
3467__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3468 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3469 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3470{
3471 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3472 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3473 const uint8_t* _frm_nxt = _frm;
3474 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3475 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3476 uint32_t* _to_nxt = _to;
3477 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3478 _Maxcode_, _Mode_);
3479 frm_nxt = frm + (_frm_nxt - _frm);
3480 to_nxt = to + (_to_nxt - _to);
3481 return r;
3482}
3483
3484__codecvt_utf16<wchar_t, false>::result
3485__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3486 extern_type* to, extern_type*, extern_type*& to_nxt) const
3487{
3488 to_nxt = to;
3489 return noconv;
3490}
3491
3492int
Howard Hinnantc9834542011-05-31 15:34:58 +00003493__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003494{
3495 return 0;
3496}
3497
3498bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003499__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003500{
3501 return false;
3502}
3503
3504int
3505__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3506 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3507{
3508 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3509 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3510 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3511}
3512
3513int
Howard Hinnantc9834542011-05-31 15:34:58 +00003514__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003515{
3516 if (_Mode_ & consume_header)
3517 return 6;
3518 return 4;
3519}
3520
3521// __codecvt_utf16<wchar_t, true>
3522
3523__codecvt_utf16<wchar_t, true>::result
3524__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3525 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3526 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3527{
3528 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3529 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3530 const uint32_t* _frm_nxt = _frm;
3531 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3532 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3533 uint8_t* _to_nxt = _to;
3534 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3535 _Maxcode_, _Mode_);
3536 frm_nxt = frm + (_frm_nxt - _frm);
3537 to_nxt = to + (_to_nxt - _to);
3538 return r;
3539}
3540
3541__codecvt_utf16<wchar_t, true>::result
3542__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3543 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3544 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3545{
3546 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3547 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3548 const uint8_t* _frm_nxt = _frm;
3549 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3550 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3551 uint32_t* _to_nxt = _to;
3552 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3553 _Maxcode_, _Mode_);
3554 frm_nxt = frm + (_frm_nxt - _frm);
3555 to_nxt = to + (_to_nxt - _to);
3556 return r;
3557}
3558
3559__codecvt_utf16<wchar_t, true>::result
3560__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3561 extern_type* to, extern_type*, extern_type*& to_nxt) const
3562{
3563 to_nxt = to;
3564 return noconv;
3565}
3566
3567int
Howard Hinnantc9834542011-05-31 15:34:58 +00003568__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003569{
3570 return 0;
3571}
3572
3573bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003574__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003575{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003576 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003577}
3578
3579int
3580__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3581 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3582{
3583 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3584 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3585 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3586}
3587
3588int
Howard Hinnantc9834542011-05-31 15:34:58 +00003589__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003590{
3591 if (_Mode_ & consume_header)
3592 return 6;
3593 return 4;
3594}
3595
3596// __codecvt_utf16<char16_t, false>
3597
3598__codecvt_utf16<char16_t, false>::result
3599__codecvt_utf16<char16_t, false>::do_out(state_type&,
3600 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3601 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3602{
3603 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3604 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3605 const uint16_t* _frm_nxt = _frm;
3606 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3607 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3608 uint8_t* _to_nxt = _to;
3609 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3610 _Maxcode_, _Mode_);
3611 frm_nxt = frm + (_frm_nxt - _frm);
3612 to_nxt = to + (_to_nxt - _to);
3613 return r;
3614}
3615
3616__codecvt_utf16<char16_t, false>::result
3617__codecvt_utf16<char16_t, false>::do_in(state_type&,
3618 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3619 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3620{
3621 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3622 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3623 const uint8_t* _frm_nxt = _frm;
3624 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3625 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3626 uint16_t* _to_nxt = _to;
3627 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3628 _Maxcode_, _Mode_);
3629 frm_nxt = frm + (_frm_nxt - _frm);
3630 to_nxt = to + (_to_nxt - _to);
3631 return r;
3632}
3633
3634__codecvt_utf16<char16_t, false>::result
3635__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3636 extern_type* to, extern_type*, extern_type*& to_nxt) const
3637{
3638 to_nxt = to;
3639 return noconv;
3640}
3641
3642int
Howard Hinnantc9834542011-05-31 15:34:58 +00003643__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003644{
3645 return 0;
3646}
3647
3648bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003649__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003650{
3651 return false;
3652}
3653
3654int
3655__codecvt_utf16<char16_t, false>::do_length(state_type&,
3656 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3657{
3658 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3659 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3660 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3661}
3662
3663int
Howard Hinnantc9834542011-05-31 15:34:58 +00003664__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003665{
3666 if (_Mode_ & consume_header)
3667 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003668 return 2;
3669}
3670
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003671// __codecvt_utf16<char16_t, true>
3672
3673__codecvt_utf16<char16_t, true>::result
3674__codecvt_utf16<char16_t, true>::do_out(state_type&,
3675 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3676 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3677{
3678 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3679 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3680 const uint16_t* _frm_nxt = _frm;
3681 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3682 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3683 uint8_t* _to_nxt = _to;
3684 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3685 _Maxcode_, _Mode_);
3686 frm_nxt = frm + (_frm_nxt - _frm);
3687 to_nxt = to + (_to_nxt - _to);
3688 return r;
3689}
3690
3691__codecvt_utf16<char16_t, true>::result
3692__codecvt_utf16<char16_t, true>::do_in(state_type&,
3693 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3694 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3695{
3696 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3697 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3698 const uint8_t* _frm_nxt = _frm;
3699 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3700 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3701 uint16_t* _to_nxt = _to;
3702 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3703 _Maxcode_, _Mode_);
3704 frm_nxt = frm + (_frm_nxt - _frm);
3705 to_nxt = to + (_to_nxt - _to);
3706 return r;
3707}
3708
3709__codecvt_utf16<char16_t, true>::result
3710__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3711 extern_type* to, extern_type*, extern_type*& to_nxt) const
3712{
3713 to_nxt = to;
3714 return noconv;
3715}
3716
3717int
Howard Hinnantc9834542011-05-31 15:34:58 +00003718__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003719{
3720 return 0;
3721}
3722
3723bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003724__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003725{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003726 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003727}
3728
3729int
3730__codecvt_utf16<char16_t, true>::do_length(state_type&,
3731 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3732{
3733 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3734 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3735 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3736}
3737
3738int
Howard Hinnantc9834542011-05-31 15:34:58 +00003739__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003740{
3741 if (_Mode_ & consume_header)
3742 return 4;
3743 return 2;
3744}
3745
3746// __codecvt_utf16<char32_t, false>
3747
3748__codecvt_utf16<char32_t, false>::result
3749__codecvt_utf16<char32_t, false>::do_out(state_type&,
3750 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3751 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3752{
3753 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3754 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3755 const uint32_t* _frm_nxt = _frm;
3756 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3757 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3758 uint8_t* _to_nxt = _to;
3759 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3760 _Maxcode_, _Mode_);
3761 frm_nxt = frm + (_frm_nxt - _frm);
3762 to_nxt = to + (_to_nxt - _to);
3763 return r;
3764}
3765
3766__codecvt_utf16<char32_t, false>::result
3767__codecvt_utf16<char32_t, false>::do_in(state_type&,
3768 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3769 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3770{
3771 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3772 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3773 const uint8_t* _frm_nxt = _frm;
3774 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3775 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3776 uint32_t* _to_nxt = _to;
3777 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3778 _Maxcode_, _Mode_);
3779 frm_nxt = frm + (_frm_nxt - _frm);
3780 to_nxt = to + (_to_nxt - _to);
3781 return r;
3782}
3783
3784__codecvt_utf16<char32_t, false>::result
3785__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3786 extern_type* to, extern_type*, extern_type*& to_nxt) const
3787{
3788 to_nxt = to;
3789 return noconv;
3790}
3791
3792int
Howard Hinnantc9834542011-05-31 15:34:58 +00003793__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003794{
3795 return 0;
3796}
3797
3798bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003799__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003800{
3801 return false;
3802}
3803
3804int
3805__codecvt_utf16<char32_t, false>::do_length(state_type&,
3806 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3807{
3808 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3809 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3810 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3811}
3812
3813int
Howard Hinnantc9834542011-05-31 15:34:58 +00003814__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003815{
3816 if (_Mode_ & consume_header)
3817 return 6;
3818 return 4;
3819}
3820
3821// __codecvt_utf16<char32_t, true>
3822
3823__codecvt_utf16<char32_t, true>::result
3824__codecvt_utf16<char32_t, true>::do_out(state_type&,
3825 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3826 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3827{
3828 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3829 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3830 const uint32_t* _frm_nxt = _frm;
3831 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3832 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3833 uint8_t* _to_nxt = _to;
3834 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3835 _Maxcode_, _Mode_);
3836 frm_nxt = frm + (_frm_nxt - _frm);
3837 to_nxt = to + (_to_nxt - _to);
3838 return r;
3839}
3840
3841__codecvt_utf16<char32_t, true>::result
3842__codecvt_utf16<char32_t, true>::do_in(state_type&,
3843 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3844 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3845{
3846 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3847 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3848 const uint8_t* _frm_nxt = _frm;
3849 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3850 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3851 uint32_t* _to_nxt = _to;
3852 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3853 _Maxcode_, _Mode_);
3854 frm_nxt = frm + (_frm_nxt - _frm);
3855 to_nxt = to + (_to_nxt - _to);
3856 return r;
3857}
3858
3859__codecvt_utf16<char32_t, true>::result
3860__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3861 extern_type* to, extern_type*, extern_type*& to_nxt) const
3862{
3863 to_nxt = to;
3864 return noconv;
3865}
3866
3867int
Howard Hinnantc9834542011-05-31 15:34:58 +00003868__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003869{
3870 return 0;
3871}
3872
3873bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003874__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003875{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003876 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003877}
3878
3879int
3880__codecvt_utf16<char32_t, true>::do_length(state_type&,
3881 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3882{
3883 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3884 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3885 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3886}
3887
3888int
Howard Hinnantc9834542011-05-31 15:34:58 +00003889__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003890{
3891 if (_Mode_ & consume_header)
3892 return 6;
3893 return 4;
3894}
3895
3896// __codecvt_utf8_utf16<wchar_t>
3897
3898__codecvt_utf8_utf16<wchar_t>::result
3899__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3900 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3901 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3902{
3903 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3904 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3905 const uint32_t* _frm_nxt = _frm;
3906 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3907 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3908 uint8_t* _to_nxt = _to;
3909 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3910 _Maxcode_, _Mode_);
3911 frm_nxt = frm + (_frm_nxt - _frm);
3912 to_nxt = to + (_to_nxt - _to);
3913 return r;
3914}
3915
3916__codecvt_utf8_utf16<wchar_t>::result
3917__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3918 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3919 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3920{
3921 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3922 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3923 const uint8_t* _frm_nxt = _frm;
3924 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3925 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3926 uint32_t* _to_nxt = _to;
3927 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3928 _Maxcode_, _Mode_);
3929 frm_nxt = frm + (_frm_nxt - _frm);
3930 to_nxt = to + (_to_nxt - _to);
3931 return r;
3932}
3933
3934__codecvt_utf8_utf16<wchar_t>::result
3935__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3936 extern_type* to, extern_type*, extern_type*& to_nxt) const
3937{
3938 to_nxt = to;
3939 return noconv;
3940}
3941
3942int
Howard Hinnantc9834542011-05-31 15:34:58 +00003943__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003944{
3945 return 0;
3946}
3947
3948bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003949__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003950{
3951 return false;
3952}
3953
3954int
3955__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3956 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3957{
3958 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3959 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3960 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3961}
3962
3963int
Howard Hinnantc9834542011-05-31 15:34:58 +00003964__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003965{
3966 if (_Mode_ & consume_header)
3967 return 7;
3968 return 4;
3969}
3970
3971// __codecvt_utf8_utf16<char16_t>
3972
3973__codecvt_utf8_utf16<char16_t>::result
3974__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3975 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3976 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3977{
3978 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3979 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3980 const uint16_t* _frm_nxt = _frm;
3981 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3982 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3983 uint8_t* _to_nxt = _to;
3984 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3985 _Maxcode_, _Mode_);
3986 frm_nxt = frm + (_frm_nxt - _frm);
3987 to_nxt = to + (_to_nxt - _to);
3988 return r;
3989}
3990
3991__codecvt_utf8_utf16<char16_t>::result
3992__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3993 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3994 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3995{
3996 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3997 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3998 const uint8_t* _frm_nxt = _frm;
3999 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4000 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4001 uint16_t* _to_nxt = _to;
4002 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4003 _Maxcode_, _Mode_);
4004 frm_nxt = frm + (_frm_nxt - _frm);
4005 to_nxt = to + (_to_nxt - _to);
4006 return r;
4007}
4008
4009__codecvt_utf8_utf16<char16_t>::result
4010__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4011 extern_type* to, extern_type*, extern_type*& to_nxt) const
4012{
4013 to_nxt = to;
4014 return noconv;
4015}
4016
4017int
Howard Hinnantc9834542011-05-31 15:34:58 +00004018__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004019{
4020 return 0;
4021}
4022
4023bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004024__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004025{
4026 return false;
4027}
4028
4029int
4030__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4031 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4032{
4033 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4034 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4035 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4036}
4037
4038int
Howard Hinnantc9834542011-05-31 15:34:58 +00004039__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004040{
4041 if (_Mode_ & consume_header)
4042 return 7;
4043 return 4;
4044}
4045
4046// __codecvt_utf8_utf16<char32_t>
4047
4048__codecvt_utf8_utf16<char32_t>::result
4049__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4050 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4051 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4052{
4053 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4054 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4055 const uint32_t* _frm_nxt = _frm;
4056 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4057 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4058 uint8_t* _to_nxt = _to;
4059 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4060 _Maxcode_, _Mode_);
4061 frm_nxt = frm + (_frm_nxt - _frm);
4062 to_nxt = to + (_to_nxt - _to);
4063 return r;
4064}
4065
4066__codecvt_utf8_utf16<char32_t>::result
4067__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4068 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4069 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4070{
4071 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4072 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4073 const uint8_t* _frm_nxt = _frm;
4074 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4075 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4076 uint32_t* _to_nxt = _to;
4077 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4078 _Maxcode_, _Mode_);
4079 frm_nxt = frm + (_frm_nxt - _frm);
4080 to_nxt = to + (_to_nxt - _to);
4081 return r;
4082}
4083
4084__codecvt_utf8_utf16<char32_t>::result
4085__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4086 extern_type* to, extern_type*, extern_type*& to_nxt) const
4087{
4088 to_nxt = to;
4089 return noconv;
4090}
4091
4092int
Howard Hinnantc9834542011-05-31 15:34:58 +00004093__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004094{
4095 return 0;
4096}
4097
4098bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004099__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004100{
4101 return false;
4102}
4103
4104int
4105__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4106 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4107{
4108 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4109 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4110 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4111}
4112
4113int
Howard Hinnantc9834542011-05-31 15:34:58 +00004114__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004115{
4116 if (_Mode_ & consume_header)
4117 return 7;
4118 return 4;
4119}
4120
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004121// __narrow_to_utf8<16>
4122
4123__narrow_to_utf8<16>::~__narrow_to_utf8()
4124{
4125}
4126
4127// __narrow_to_utf8<32>
4128
4129__narrow_to_utf8<32>::~__narrow_to_utf8()
4130{
4131}
4132
4133// __widen_from_utf8<16>
4134
4135__widen_from_utf8<16>::~__widen_from_utf8()
4136{
4137}
4138
4139// __widen_from_utf8<32>
4140
4141__widen_from_utf8<32>::~__widen_from_utf8()
4142{
4143}
4144
4145// numpunct<char> && numpunct<wchar_t>
4146
4147locale::id numpunct< char >::id;
4148locale::id numpunct<wchar_t>::id;
4149
4150numpunct<char>::numpunct(size_t refs)
4151 : locale::facet(refs),
4152 __decimal_point_('.'),
4153 __thousands_sep_(',')
4154{
4155}
4156
4157numpunct<wchar_t>::numpunct(size_t refs)
4158 : locale::facet(refs),
4159 __decimal_point_(L'.'),
4160 __thousands_sep_(L',')
4161{
4162}
4163
4164numpunct<char>::~numpunct()
4165{
4166}
4167
4168numpunct<wchar_t>::~numpunct()
4169{
4170}
4171
4172 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4173wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4174
4175 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4176wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4177
4178string numpunct< char >::do_grouping() const {return __grouping_;}
4179string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4180
4181 string numpunct< char >::do_truename() const {return "true";}
4182wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4183
4184 string numpunct< char >::do_falsename() const {return "false";}
4185wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4186
4187// numpunct_byname<char>
4188
4189numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4190 : numpunct<char>(refs)
4191{
4192 __init(nm);
4193}
4194
4195numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4196 : numpunct<char>(refs)
4197{
4198 __init(nm.c_str());
4199}
4200
4201numpunct_byname<char>::~numpunct_byname()
4202{
4203}
4204
4205void
4206numpunct_byname<char>::__init(const char* nm)
4207{
4208 if (strcmp(nm, "C") != 0)
4209 {
Sean Huntf3907e62011-07-15 05:40:33 +00004210 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004211#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004212 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004213 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4214 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004215#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004216#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004217 lconv* lc = localeconv_l(loc.get());
4218#else
4219 lconv* lc = __localeconv_l(loc.get());
4220#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004221 if (*lc->decimal_point)
4222 __decimal_point_ = *lc->decimal_point;
4223 if (*lc->thousands_sep)
4224 __thousands_sep_ = *lc->thousands_sep;
4225 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004226 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004227 }
4228}
4229
4230// numpunct_byname<wchar_t>
4231
4232numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4233 : numpunct<wchar_t>(refs)
4234{
4235 __init(nm);
4236}
4237
4238numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4239 : numpunct<wchar_t>(refs)
4240{
4241 __init(nm.c_str());
4242}
4243
4244numpunct_byname<wchar_t>::~numpunct_byname()
4245{
4246}
4247
4248void
4249numpunct_byname<wchar_t>::__init(const char* nm)
4250{
4251 if (strcmp(nm, "C") != 0)
4252 {
Sean Huntf3907e62011-07-15 05:40:33 +00004253 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004254#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004255 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004256 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4257 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004258#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004259#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004260 lconv* lc = localeconv_l(loc.get());
4261#else
4262 lconv* lc = __localeconv_l(loc.get());
4263#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004264 if (*lc->decimal_point)
4265 __decimal_point_ = *lc->decimal_point;
4266 if (*lc->thousands_sep)
4267 __thousands_sep_ = *lc->thousands_sep;
4268 __grouping_ = lc->grouping;
4269 // locallization for truename and falsename is not available
4270 }
4271}
4272
4273// num_get helpers
4274
4275int
4276__num_get_base::__get_base(ios_base& iob)
4277{
4278 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4279 if (__basefield == ios_base::oct)
4280 return 8;
4281 else if (__basefield == ios_base::hex)
4282 return 16;
4283 else if (__basefield == 0)
4284 return 0;
4285 return 10;
4286}
4287
4288const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4289
4290void
4291__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4292 ios_base::iostate& __err)
4293{
4294 if (__grouping.size() != 0)
4295 {
4296 reverse(__g, __g_end);
4297 const char* __ig = __grouping.data();
4298 const char* __eg = __ig + __grouping.size();
4299 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4300 {
4301 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4302 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004303 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004304 {
4305 __err = ios_base::failbit;
4306 return;
4307 }
4308 }
4309 if (__eg - __ig > 1)
4310 ++__ig;
4311 }
4312 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4313 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004314 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004315 __err = ios_base::failbit;
4316 }
4317 }
4318}
4319
4320void
4321__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4322 ios_base::fmtflags __flags)
4323{
4324 if (__flags & ios_base::showpos)
4325 *__fmtp++ = '+';
4326 if (__flags & ios_base::showbase)
4327 *__fmtp++ = '#';
4328 while(*__len)
4329 *__fmtp++ = *__len++;
4330 if ((__flags & ios_base::basefield) == ios_base::oct)
4331 *__fmtp = 'o';
4332 else if ((__flags & ios_base::basefield) == ios_base::hex)
4333 {
4334 if (__flags & ios_base::uppercase)
4335 *__fmtp = 'X';
4336 else
4337 *__fmtp = 'x';
4338 }
4339 else if (__signd)
4340 *__fmtp = 'd';
4341 else
4342 *__fmtp = 'u';
4343}
4344
4345bool
4346__num_put_base::__format_float(char* __fmtp, const char* __len,
4347 ios_base::fmtflags __flags)
4348{
4349 bool specify_precision = true;
4350 if (__flags & ios_base::showpos)
4351 *__fmtp++ = '+';
4352 if (__flags & ios_base::showpoint)
4353 *__fmtp++ = '#';
4354 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4355 bool uppercase = __flags & ios_base::uppercase;
4356 if (floatfield == (ios_base::fixed | ios_base::scientific))
4357 specify_precision = false;
4358 else
4359 {
4360 *__fmtp++ = '.';
4361 *__fmtp++ = '*';
4362 }
4363 while(*__len)
4364 *__fmtp++ = *__len++;
4365 if (floatfield == ios_base::fixed)
4366 {
4367 if (uppercase)
4368 *__fmtp = 'F';
4369 else
4370 *__fmtp = 'f';
4371 }
4372 else if (floatfield == ios_base::scientific)
4373 {
4374 if (uppercase)
4375 *__fmtp = 'E';
4376 else
4377 *__fmtp = 'e';
4378 }
4379 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4380 {
4381 if (uppercase)
4382 *__fmtp = 'A';
4383 else
4384 *__fmtp = 'a';
4385 }
4386 else
4387 {
4388 if (uppercase)
4389 *__fmtp = 'G';
4390 else
4391 *__fmtp = 'g';
4392 }
4393 return specify_precision;
4394}
4395
4396char*
4397__num_put_base::__identify_padding(char* __nb, char* __ne,
4398 const ios_base& __iob)
4399{
4400 switch (__iob.flags() & ios_base::adjustfield)
4401 {
4402 case ios_base::internal:
4403 if (__nb[0] == '-' || __nb[0] == '+')
4404 return __nb+1;
4405 if (__ne - __nb >= 2 && __nb[0] == '0'
4406 && (__nb[1] == 'x' || __nb[1] == 'X'))
4407 return __nb+2;
4408 break;
4409 case ios_base::left:
4410 return __ne;
4411 case ios_base::right:
4412 default:
4413 break;
4414 }
4415 return __nb;
4416}
4417
4418// time_get
4419
4420static
4421string*
4422init_weeks()
4423{
4424 static string weeks[14];
4425 weeks[0] = "Sunday";
4426 weeks[1] = "Monday";
4427 weeks[2] = "Tuesday";
4428 weeks[3] = "Wednesday";
4429 weeks[4] = "Thursday";
4430 weeks[5] = "Friday";
4431 weeks[6] = "Saturday";
4432 weeks[7] = "Sun";
4433 weeks[8] = "Mon";
4434 weeks[9] = "Tue";
4435 weeks[10] = "Wed";
4436 weeks[11] = "Thu";
4437 weeks[12] = "Fri";
4438 weeks[13] = "Sat";
4439 return weeks;
4440}
4441
4442static
4443wstring*
4444init_wweeks()
4445{
4446 static wstring weeks[14];
4447 weeks[0] = L"Sunday";
4448 weeks[1] = L"Monday";
4449 weeks[2] = L"Tuesday";
4450 weeks[3] = L"Wednesday";
4451 weeks[4] = L"Thursday";
4452 weeks[5] = L"Friday";
4453 weeks[6] = L"Saturday";
4454 weeks[7] = L"Sun";
4455 weeks[8] = L"Mon";
4456 weeks[9] = L"Tue";
4457 weeks[10] = L"Wed";
4458 weeks[11] = L"Thu";
4459 weeks[12] = L"Fri";
4460 weeks[13] = L"Sat";
4461 return weeks;
4462}
4463
4464template <>
4465const string*
4466__time_get_c_storage<char>::__weeks() const
4467{
4468 static const string* weeks = init_weeks();
4469 return weeks;
4470}
4471
4472template <>
4473const wstring*
4474__time_get_c_storage<wchar_t>::__weeks() const
4475{
4476 static const wstring* weeks = init_wweeks();
4477 return weeks;
4478}
4479
4480static
4481string*
4482init_months()
4483{
4484 static string months[24];
4485 months[0] = "January";
4486 months[1] = "February";
4487 months[2] = "March";
4488 months[3] = "April";
4489 months[4] = "May";
4490 months[5] = "June";
4491 months[6] = "July";
4492 months[7] = "August";
4493 months[8] = "September";
4494 months[9] = "October";
4495 months[10] = "November";
4496 months[11] = "December";
4497 months[12] = "Jan";
4498 months[13] = "Feb";
4499 months[14] = "Mar";
4500 months[15] = "Apr";
4501 months[16] = "May";
4502 months[17] = "Jun";
4503 months[18] = "Jul";
4504 months[19] = "Aug";
4505 months[20] = "Sep";
4506 months[21] = "Oct";
4507 months[22] = "Nov";
4508 months[23] = "Dec";
4509 return months;
4510}
4511
4512static
4513wstring*
4514init_wmonths()
4515{
4516 static wstring months[24];
4517 months[0] = L"January";
4518 months[1] = L"February";
4519 months[2] = L"March";
4520 months[3] = L"April";
4521 months[4] = L"May";
4522 months[5] = L"June";
4523 months[6] = L"July";
4524 months[7] = L"August";
4525 months[8] = L"September";
4526 months[9] = L"October";
4527 months[10] = L"November";
4528 months[11] = L"December";
4529 months[12] = L"Jan";
4530 months[13] = L"Feb";
4531 months[14] = L"Mar";
4532 months[15] = L"Apr";
4533 months[16] = L"May";
4534 months[17] = L"Jun";
4535 months[18] = L"Jul";
4536 months[19] = L"Aug";
4537 months[20] = L"Sep";
4538 months[21] = L"Oct";
4539 months[22] = L"Nov";
4540 months[23] = L"Dec";
4541 return months;
4542}
4543
4544template <>
4545const string*
4546__time_get_c_storage<char>::__months() const
4547{
4548 static const string* months = init_months();
4549 return months;
4550}
4551
4552template <>
4553const wstring*
4554__time_get_c_storage<wchar_t>::__months() const
4555{
4556 static const wstring* months = init_wmonths();
4557 return months;
4558}
4559
4560static
4561string*
4562init_am_pm()
4563{
4564 static string am_pm[24];
4565 am_pm[0] = "AM";
4566 am_pm[1] = "PM";
4567 return am_pm;
4568}
4569
4570static
4571wstring*
4572init_wam_pm()
4573{
4574 static wstring am_pm[24];
4575 am_pm[0] = L"AM";
4576 am_pm[1] = L"PM";
4577 return am_pm;
4578}
4579
4580template <>
4581const string*
4582__time_get_c_storage<char>::__am_pm() const
4583{
4584 static const string* am_pm = init_am_pm();
4585 return am_pm;
4586}
4587
4588template <>
4589const wstring*
4590__time_get_c_storage<wchar_t>::__am_pm() const
4591{
4592 static const wstring* am_pm = init_wam_pm();
4593 return am_pm;
4594}
4595
4596template <>
4597const string&
4598__time_get_c_storage<char>::__x() const
4599{
4600 static string s("%m/%d/%y");
4601 return s;
4602}
4603
4604template <>
4605const wstring&
4606__time_get_c_storage<wchar_t>::__x() const
4607{
4608 static wstring s(L"%m/%d/%y");
4609 return s;
4610}
4611
4612template <>
4613const string&
4614__time_get_c_storage<char>::__X() const
4615{
4616 static string s("%H:%M:%S");
4617 return s;
4618}
4619
4620template <>
4621const wstring&
4622__time_get_c_storage<wchar_t>::__X() const
4623{
4624 static wstring s(L"%H:%M:%S");
4625 return s;
4626}
4627
4628template <>
4629const string&
4630__time_get_c_storage<char>::__c() const
4631{
4632 static string s("%a %b %d %H:%M:%S %Y");
4633 return s;
4634}
4635
4636template <>
4637const wstring&
4638__time_get_c_storage<wchar_t>::__c() const
4639{
4640 static wstring s(L"%a %b %d %H:%M:%S %Y");
4641 return s;
4642}
4643
4644template <>
4645const string&
4646__time_get_c_storage<char>::__r() const
4647{
4648 static string s("%I:%M:%S %p");
4649 return s;
4650}
4651
4652template <>
4653const wstring&
4654__time_get_c_storage<wchar_t>::__r() const
4655{
4656 static wstring s(L"%I:%M:%S %p");
4657 return s;
4658}
4659
4660// time_get_byname
4661
4662__time_get::__time_get(const char* nm)
4663 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4664{
Howard Hinnantd4444702010-08-11 17:04:31 +00004665#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004666 if (__loc_ == 0)
4667 throw runtime_error("time_get_byname"
4668 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004669#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004670}
4671
4672__time_get::__time_get(const string& nm)
4673 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4674{
Howard Hinnantd4444702010-08-11 17:04:31 +00004675#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004676 if (__loc_ == 0)
4677 throw runtime_error("time_get_byname"
4678 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004679#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004680}
4681
4682__time_get::~__time_get()
4683{
4684 freelocale(__loc_);
4685}
4686
Howard Hinnant335b1512012-02-20 16:51:43 +00004687#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant21772ec2012-12-28 18:15:01 +00004688#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant335b1512012-02-20 16:51:43 +00004689
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004690template <>
4691string
4692__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4693{
Howard Hinnant3074a052012-02-19 14:55:32 +00004694 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004695 t.tm_sec = 59;
4696 t.tm_min = 55;
4697 t.tm_hour = 23;
4698 t.tm_mday = 31;
4699 t.tm_mon = 11;
4700 t.tm_year = 161;
4701 t.tm_wday = 6;
4702 t.tm_yday = 364;
4703 t.tm_isdst = -1;
4704 char buf[100];
4705 char f[3] = {0};
4706 f[0] = '%';
4707 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004708 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004709 char* bb = buf;
4710 char* be = buf + n;
4711 string result;
4712 while (bb != be)
4713 {
4714 if (ct.is(ctype_base::space, *bb))
4715 {
4716 result.push_back(' ');
4717 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4718 ;
4719 continue;
4720 }
4721 char* w = bb;
4722 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004723 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004724 ct, err, false)
4725 - this->__weeks_;
4726 if (i < 14)
4727 {
4728 result.push_back('%');
4729 if (i < 7)
4730 result.push_back('A');
4731 else
4732 result.push_back('a');
4733 bb = w;
4734 continue;
4735 }
4736 w = bb;
4737 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4738 ct, err, false)
4739 - this->__months_;
4740 if (i < 24)
4741 {
4742 result.push_back('%');
4743 if (i < 12)
4744 result.push_back('B');
4745 else
4746 result.push_back('b');
4747 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4748 result.back() = 'm';
4749 bb = w;
4750 continue;
4751 }
4752 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4753 {
4754 w = bb;
4755 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4756 ct, err, false) - this->__am_pm_;
4757 if (i < 2)
4758 {
4759 result.push_back('%');
4760 result.push_back('p');
4761 bb = w;
4762 continue;
4763 }
4764 }
4765 w = bb;
4766 if (ct.is(ctype_base::digit, *bb))
4767 {
4768 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4769 {
4770 case 6:
4771 result.push_back('%');
4772 result.push_back('w');
4773 break;
4774 case 7:
4775 result.push_back('%');
4776 result.push_back('u');
4777 break;
4778 case 11:
4779 result.push_back('%');
4780 result.push_back('I');
4781 break;
4782 case 12:
4783 result.push_back('%');
4784 result.push_back('m');
4785 break;
4786 case 23:
4787 result.push_back('%');
4788 result.push_back('H');
4789 break;
4790 case 31:
4791 result.push_back('%');
4792 result.push_back('d');
4793 break;
4794 case 55:
4795 result.push_back('%');
4796 result.push_back('M');
4797 break;
4798 case 59:
4799 result.push_back('%');
4800 result.push_back('S');
4801 break;
4802 case 61:
4803 result.push_back('%');
4804 result.push_back('y');
4805 break;
4806 case 364:
4807 result.push_back('%');
4808 result.push_back('j');
4809 break;
4810 case 2061:
4811 result.push_back('%');
4812 result.push_back('Y');
4813 break;
4814 default:
4815 for (; w != bb; ++w)
4816 result.push_back(*w);
4817 break;
4818 }
4819 continue;
4820 }
4821 if (*bb == '%')
4822 {
4823 result.push_back('%');
4824 result.push_back('%');
4825 ++bb;
4826 continue;
4827 }
4828 result.push_back(*bb);
4829 ++bb;
4830 }
4831 return result;
4832}
4833
Howard Hinnantec3773c2011-12-01 20:21:04 +00004834#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004835
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004836template <>
4837wstring
4838__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4839{
Howard Hinnant3074a052012-02-19 14:55:32 +00004840 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004841 t.tm_sec = 59;
4842 t.tm_min = 55;
4843 t.tm_hour = 23;
4844 t.tm_mday = 31;
4845 t.tm_mon = 11;
4846 t.tm_year = 161;
4847 t.tm_wday = 6;
4848 t.tm_yday = 364;
4849 t.tm_isdst = -1;
4850 char buf[100];
4851 char f[3] = {0};
4852 f[0] = '%';
4853 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004854 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004855 wchar_t wbuf[100];
4856 wchar_t* wbb = wbuf;
4857 mbstate_t mb = {0};
4858 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004859#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004860 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004861#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004862 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004863#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004864 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004865 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004866 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004867 wstring result;
4868 while (wbb != wbe)
4869 {
4870 if (ct.is(ctype_base::space, *wbb))
4871 {
4872 result.push_back(L' ');
4873 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4874 ;
4875 continue;
4876 }
4877 wchar_t* w = wbb;
4878 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004879 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004880 ct, err, false)
4881 - this->__weeks_;
4882 if (i < 14)
4883 {
4884 result.push_back(L'%');
4885 if (i < 7)
4886 result.push_back(L'A');
4887 else
4888 result.push_back(L'a');
4889 wbb = w;
4890 continue;
4891 }
4892 w = wbb;
4893 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4894 ct, err, false)
4895 - this->__months_;
4896 if (i < 24)
4897 {
4898 result.push_back(L'%');
4899 if (i < 12)
4900 result.push_back(L'B');
4901 else
4902 result.push_back(L'b');
4903 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4904 result.back() = L'm';
4905 wbb = w;
4906 continue;
4907 }
4908 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4909 {
4910 w = wbb;
4911 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4912 ct, err, false) - this->__am_pm_;
4913 if (i < 2)
4914 {
4915 result.push_back(L'%');
4916 result.push_back(L'p');
4917 wbb = w;
4918 continue;
4919 }
4920 }
4921 w = wbb;
4922 if (ct.is(ctype_base::digit, *wbb))
4923 {
4924 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4925 {
4926 case 6:
4927 result.push_back(L'%');
4928 result.push_back(L'w');
4929 break;
4930 case 7:
4931 result.push_back(L'%');
4932 result.push_back(L'u');
4933 break;
4934 case 11:
4935 result.push_back(L'%');
4936 result.push_back(L'I');
4937 break;
4938 case 12:
4939 result.push_back(L'%');
4940 result.push_back(L'm');
4941 break;
4942 case 23:
4943 result.push_back(L'%');
4944 result.push_back(L'H');
4945 break;
4946 case 31:
4947 result.push_back(L'%');
4948 result.push_back(L'd');
4949 break;
4950 case 55:
4951 result.push_back(L'%');
4952 result.push_back(L'M');
4953 break;
4954 case 59:
4955 result.push_back(L'%');
4956 result.push_back(L'S');
4957 break;
4958 case 61:
4959 result.push_back(L'%');
4960 result.push_back(L'y');
4961 break;
4962 case 364:
4963 result.push_back(L'%');
4964 result.push_back(L'j');
4965 break;
4966 case 2061:
4967 result.push_back(L'%');
4968 result.push_back(L'Y');
4969 break;
4970 default:
4971 for (; w != wbb; ++w)
4972 result.push_back(*w);
4973 break;
4974 }
4975 continue;
4976 }
4977 if (ct.narrow(*wbb, 0) == '%')
4978 {
4979 result.push_back(L'%');
4980 result.push_back(L'%');
4981 ++wbb;
4982 continue;
4983 }
4984 result.push_back(*wbb);
4985 ++wbb;
4986 }
4987 return result;
4988}
4989
4990template <>
4991void
4992__time_get_storage<char>::init(const ctype<char>& ct)
4993{
Howard Hinnantcd992362012-08-02 18:44:17 +00004994 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004995 char buf[100];
4996 // __weeks_
4997 for (int i = 0; i < 7; ++i)
4998 {
4999 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005000 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005001 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005002 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005003 __weeks_[i+7] = buf;
5004 }
5005 // __months_
5006 for (int i = 0; i < 12; ++i)
5007 {
5008 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005009 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005010 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005011 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005012 __months_[i+12] = buf;
5013 }
5014 // __am_pm_
5015 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005016 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005017 __am_pm_[0] = buf;
5018 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005019 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005020 __am_pm_[1] = buf;
5021 __c_ = __analyze('c', ct);
5022 __r_ = __analyze('r', ct);
5023 __x_ = __analyze('x', ct);
5024 __X_ = __analyze('X', ct);
5025}
5026
5027template <>
5028void
5029__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5030{
5031 tm t = {0};
5032 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005033 wchar_t wbuf[100];
5034 wchar_t* wbe;
5035 mbstate_t mb = {0};
5036 // __weeks_
5037 for (int i = 0; i < 7; ++i)
5038 {
5039 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005040 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005041 mb = mbstate_t();
5042 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005043#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005044 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005045#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005046 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005047#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005048 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005049 __throw_runtime_error("locale not supported");
5050 wbe = wbuf + j;
5051 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005052 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005053 mb = mbstate_t();
5054 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005055#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005056 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005057#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005058 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005059#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005060 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005061 __throw_runtime_error("locale not supported");
5062 wbe = wbuf + j;
5063 __weeks_[i+7].assign(wbuf, wbe);
5064 }
5065 // __months_
5066 for (int i = 0; i < 12; ++i)
5067 {
5068 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005069 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005070 mb = mbstate_t();
5071 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005072#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005073 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005074#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005075 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005076#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005077 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005078 __throw_runtime_error("locale not supported");
5079 wbe = wbuf + j;
5080 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005081 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005082 mb = mbstate_t();
5083 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005084#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005085 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005086#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005087 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005088#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005089 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005090 __throw_runtime_error("locale not supported");
5091 wbe = wbuf + j;
5092 __months_[i+12].assign(wbuf, wbe);
5093 }
5094 // __am_pm_
5095 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005096 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005097 mb = mbstate_t();
5098 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005099#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005100 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005101#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005102 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005103#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005104 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005105 __throw_runtime_error("locale not supported");
5106 wbe = wbuf + j;
5107 __am_pm_[0].assign(wbuf, wbe);
5108 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005109 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005110 mb = mbstate_t();
5111 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005112#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005113 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005114#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005115 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005116#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005117 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005118 __throw_runtime_error("locale not supported");
5119 wbe = wbuf + j;
5120 __am_pm_[1].assign(wbuf, wbe);
5121 __c_ = __analyze('c', ct);
5122 __r_ = __analyze('r', ct);
5123 __x_ = __analyze('x', ct);
5124 __X_ = __analyze('X', ct);
5125}
5126
5127template <class CharT>
5128struct _LIBCPP_HIDDEN __time_get_temp
5129 : public ctype_byname<CharT>
5130{
5131 explicit __time_get_temp(const char* nm)
5132 : ctype_byname<CharT>(nm, 1) {}
5133 explicit __time_get_temp(const string& nm)
5134 : ctype_byname<CharT>(nm, 1) {}
5135};
5136
5137template <>
5138__time_get_storage<char>::__time_get_storage(const char* __nm)
5139 : __time_get(__nm)
5140{
5141 const __time_get_temp<char> ct(__nm);
5142 init(ct);
5143}
5144
5145template <>
5146__time_get_storage<char>::__time_get_storage(const string& __nm)
5147 : __time_get(__nm)
5148{
5149 const __time_get_temp<char> ct(__nm);
5150 init(ct);
5151}
5152
5153template <>
5154__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5155 : __time_get(__nm)
5156{
5157 const __time_get_temp<wchar_t> ct(__nm);
5158 init(ct);
5159}
5160
5161template <>
5162__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5163 : __time_get(__nm)
5164{
5165 const __time_get_temp<wchar_t> ct(__nm);
5166 init(ct);
5167}
5168
5169template <>
5170time_base::dateorder
5171__time_get_storage<char>::__do_date_order() const
5172{
5173 unsigned i;
5174 for (i = 0; i < __x_.size(); ++i)
5175 if (__x_[i] == '%')
5176 break;
5177 ++i;
5178 switch (__x_[i])
5179 {
5180 case 'y':
5181 case 'Y':
5182 for (++i; i < __x_.size(); ++i)
5183 if (__x_[i] == '%')
5184 break;
5185 if (i == __x_.size())
5186 break;
5187 ++i;
5188 switch (__x_[i])
5189 {
5190 case 'm':
5191 for (++i; i < __x_.size(); ++i)
5192 if (__x_[i] == '%')
5193 break;
5194 if (i == __x_.size())
5195 break;
5196 ++i;
5197 if (__x_[i] == 'd')
5198 return time_base::ymd;
5199 break;
5200 case 'd':
5201 for (++i; i < __x_.size(); ++i)
5202 if (__x_[i] == '%')
5203 break;
5204 if (i == __x_.size())
5205 break;
5206 ++i;
5207 if (__x_[i] == 'm')
5208 return time_base::ydm;
5209 break;
5210 }
5211 break;
5212 case 'm':
5213 for (++i; i < __x_.size(); ++i)
5214 if (__x_[i] == '%')
5215 break;
5216 if (i == __x_.size())
5217 break;
5218 ++i;
5219 if (__x_[i] == 'd')
5220 {
5221 for (++i; i < __x_.size(); ++i)
5222 if (__x_[i] == '%')
5223 break;
5224 if (i == __x_.size())
5225 break;
5226 ++i;
5227 if (__x_[i] == 'y' || __x_[i] == 'Y')
5228 return time_base::mdy;
5229 break;
5230 }
5231 break;
5232 case 'd':
5233 for (++i; i < __x_.size(); ++i)
5234 if (__x_[i] == '%')
5235 break;
5236 if (i == __x_.size())
5237 break;
5238 ++i;
5239 if (__x_[i] == 'm')
5240 {
5241 for (++i; i < __x_.size(); ++i)
5242 if (__x_[i] == '%')
5243 break;
5244 if (i == __x_.size())
5245 break;
5246 ++i;
5247 if (__x_[i] == 'y' || __x_[i] == 'Y')
5248 return time_base::dmy;
5249 break;
5250 }
5251 break;
5252 }
5253 return time_base::no_order;
5254}
5255
5256template <>
5257time_base::dateorder
5258__time_get_storage<wchar_t>::__do_date_order() const
5259{
5260 unsigned i;
5261 for (i = 0; i < __x_.size(); ++i)
5262 if (__x_[i] == L'%')
5263 break;
5264 ++i;
5265 switch (__x_[i])
5266 {
5267 case L'y':
5268 case L'Y':
5269 for (++i; i < __x_.size(); ++i)
5270 if (__x_[i] == L'%')
5271 break;
5272 if (i == __x_.size())
5273 break;
5274 ++i;
5275 switch (__x_[i])
5276 {
5277 case L'm':
5278 for (++i; i < __x_.size(); ++i)
5279 if (__x_[i] == L'%')
5280 break;
5281 if (i == __x_.size())
5282 break;
5283 ++i;
5284 if (__x_[i] == L'd')
5285 return time_base::ymd;
5286 break;
5287 case L'd':
5288 for (++i; i < __x_.size(); ++i)
5289 if (__x_[i] == L'%')
5290 break;
5291 if (i == __x_.size())
5292 break;
5293 ++i;
5294 if (__x_[i] == L'm')
5295 return time_base::ydm;
5296 break;
5297 }
5298 break;
5299 case L'm':
5300 for (++i; i < __x_.size(); ++i)
5301 if (__x_[i] == L'%')
5302 break;
5303 if (i == __x_.size())
5304 break;
5305 ++i;
5306 if (__x_[i] == L'd')
5307 {
5308 for (++i; i < __x_.size(); ++i)
5309 if (__x_[i] == L'%')
5310 break;
5311 if (i == __x_.size())
5312 break;
5313 ++i;
5314 if (__x_[i] == L'y' || __x_[i] == L'Y')
5315 return time_base::mdy;
5316 break;
5317 }
5318 break;
5319 case L'd':
5320 for (++i; i < __x_.size(); ++i)
5321 if (__x_[i] == L'%')
5322 break;
5323 if (i == __x_.size())
5324 break;
5325 ++i;
5326 if (__x_[i] == L'm')
5327 {
5328 for (++i; i < __x_.size(); ++i)
5329 if (__x_[i] == L'%')
5330 break;
5331 if (i == __x_.size())
5332 break;
5333 ++i;
5334 if (__x_[i] == L'y' || __x_[i] == L'Y')
5335 return time_base::dmy;
5336 break;
5337 }
5338 break;
5339 }
5340 return time_base::no_order;
5341}
5342
5343// time_put
5344
5345__time_put::__time_put(const char* nm)
5346 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5347{
Howard Hinnantd4444702010-08-11 17:04:31 +00005348#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005349 if (__loc_ == 0)
5350 throw runtime_error("time_put_byname"
5351 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005352#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005353}
5354
5355__time_put::__time_put(const string& nm)
5356 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5357{
Howard Hinnantd4444702010-08-11 17:04:31 +00005358#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005359 if (__loc_ == 0)
5360 throw runtime_error("time_put_byname"
5361 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005362#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005363}
5364
5365__time_put::~__time_put()
5366{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005367 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005368 freelocale(__loc_);
5369}
5370
5371void
5372__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5373 char __fmt, char __mod) const
5374{
5375 char fmt[] = {'%', __fmt, __mod, 0};
5376 if (__mod != 0)
5377 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005378 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005379 __ne = __nb + n;
5380}
5381
5382void
5383__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5384 char __fmt, char __mod) const
5385{
5386 char __nar[100];
5387 char* __ne = __nar + 100;
5388 __do_put(__nar, __ne, __tm, __fmt, __mod);
5389 mbstate_t mb = {0};
5390 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005391#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005392 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005393#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005394 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005395#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005396 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005397 __throw_runtime_error("locale not supported");
5398 __we = __wb + j;
5399}
5400
5401// moneypunct_byname
5402
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005403template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005404static
5405void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005406__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5407 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5408 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005409{
5410 const char sign = static_cast<char>(money_base::sign);
5411 const char space = static_cast<char>(money_base::space);
5412 const char none = static_cast<char>(money_base::none);
5413 const char symbol = static_cast<char>(money_base::symbol);
5414 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005415 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5416
5417 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5418 // function'. "Space between sign and symbol or value" means that
5419 // if the sign is adjacent to the symbol, there's a space between
5420 // them, and otherwise there's a space between the sign and value.
5421 //
5422 // C11's localeconv specifies that the fourth character of an
5423 // international curr_symbol is used to separate the sign and
5424 // value when sep_by_space says to do so. C++ can't represent
5425 // that, so we just use a space. When sep_by_space says to
5426 // separate the symbol and value-or-sign with a space, we rearrange the
5427 // curr_symbol to put its spacing character on the correct side of
5428 // the symbol.
5429 //
5430 // We also need to avoid adding an extra space between the sign
5431 // and value when the currency symbol is suppressed (by not
5432 // setting showbase). We match glibc's strfmon by interpreting
5433 // sep_by_space==1 as "omit the space when the currency symbol is
5434 // absent".
5435 //
5436 // Users who want to get this right should use ICU instead.
5437
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005438 switch (cs_precedes)
5439 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005440 case 0: // value before curr_symbol
5441 if (symbol_contains_sep) {
5442 // Move the separator to before the symbol, to place it
5443 // between the value and symbol.
5444 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5445 __curr_symbol_.end());
5446 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005447 switch (sign_posn)
5448 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005449 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005450 pat.field[0] = sign;
5451 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005452 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005453 pat.field[3] = symbol;
5454 switch (sep_by_space)
5455 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005456 case 0: // No space separates the currency symbol and value.
5457 // This case may have changed between C99 and C11;
5458 // assume the currency symbol matches the intention.
5459 case 2: // Space between sign and currency or value.
5460 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005461 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005462 case 1: // Space between currency-and-sign or currency and value.
5463 if (!symbol_contains_sep) {
5464 // We insert the space into the symbol instead of
5465 // setting pat.field[2]=space so that when
5466 // showbase is not set, the space goes away too.
5467 __curr_symbol_.insert(0, 1, space_char);
5468 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005469 return;
5470 default:
5471 break;
5472 }
5473 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005474 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005475 pat.field[0] = sign;
5476 pat.field[3] = symbol;
5477 switch (sep_by_space)
5478 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005479 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005480 pat.field[1] = value;
5481 pat.field[2] = none;
5482 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005483 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005484 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005485 pat.field[2] = none;
5486 if (!symbol_contains_sep) {
5487 // We insert the space into the symbol instead of
5488 // setting pat.field[2]=space so that when
5489 // showbase is not set, the space goes away too.
5490 __curr_symbol_.insert(0, 1, space_char);
5491 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005492 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005493 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005494 pat.field[1] = space;
5495 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005496 if (symbol_contains_sep) {
5497 // Remove the separator from the symbol, since it
5498 // has already appeared after the sign.
5499 __curr_symbol_.erase(__curr_symbol_.begin());
5500 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005501 return;
5502 default:
5503 break;
5504 }
5505 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005506 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005507 pat.field[0] = value;
5508 pat.field[3] = sign;
5509 switch (sep_by_space)
5510 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005511 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005512 pat.field[1] = none;
5513 pat.field[2] = symbol;
5514 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005515 case 1: // Space between currency-and-sign or currency and value.
5516 if (!symbol_contains_sep) {
5517 // We insert the space into the symbol instead of
5518 // setting pat.field[1]=space so that when
5519 // showbase is not set, the space goes away too.
5520 __curr_symbol_.insert(0, 1, space_char);
5521 }
5522 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005523 pat.field[2] = symbol;
5524 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005525 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005526 pat.field[1] = symbol;
5527 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005528 if (symbol_contains_sep) {
5529 // Remove the separator from the symbol, since it
5530 // should not be removed if showbase is absent.
5531 __curr_symbol_.erase(__curr_symbol_.begin());
5532 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005533 return;
5534 default:
5535 break;
5536 }
5537 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005538 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005539 pat.field[0] = value;
5540 pat.field[3] = symbol;
5541 switch (sep_by_space)
5542 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005543 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005544 pat.field[1] = none;
5545 pat.field[2] = sign;
5546 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005547 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005548 pat.field[1] = space;
5549 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005550 if (symbol_contains_sep) {
5551 // Remove the separator from the symbol, since it
5552 // has already appeared before the sign.
5553 __curr_symbol_.erase(__curr_symbol_.begin());
5554 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005555 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005556 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005557 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005558 pat.field[2] = none;
5559 if (!symbol_contains_sep) {
5560 // We insert the space into the symbol instead of
5561 // setting pat.field[2]=space so that when
5562 // showbase is not set, the space goes away too.
5563 __curr_symbol_.insert(0, 1, space_char);
5564 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005565 return;
5566 default:
5567 break;
5568 }
5569 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005570 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005571 pat.field[0] = value;
5572 pat.field[3] = sign;
5573 switch (sep_by_space)
5574 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005575 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005576 pat.field[1] = none;
5577 pat.field[2] = symbol;
5578 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005579 case 1: // Space between currency-and-sign or currency and value.
5580 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005581 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005582 if (!symbol_contains_sep) {
5583 // We insert the space into the symbol instead of
5584 // setting pat.field[1]=space so that when
5585 // showbase is not set, the space goes away too.
5586 __curr_symbol_.insert(0, 1, space_char);
5587 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005588 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005589 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005590 pat.field[1] = symbol;
5591 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005592 if (symbol_contains_sep) {
5593 // Remove the separator from the symbol, since it
5594 // should not disappear when showbase is absent.
5595 __curr_symbol_.erase(__curr_symbol_.begin());
5596 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005597 return;
5598 default:
5599 break;
5600 }
5601 break;
5602 default:
5603 break;
5604 }
5605 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005606 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005607 switch (sign_posn)
5608 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005609 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005610 pat.field[0] = sign;
5611 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005612 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005613 pat.field[3] = value;
5614 switch (sep_by_space)
5615 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005616 case 0: // No space separates the currency symbol and value.
5617 // This case may have changed between C99 and C11;
5618 // assume the currency symbol matches the intention.
5619 case 2: // Space between sign and currency or value.
5620 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005621 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005622 case 1: // Space between currency-and-sign or currency and value.
5623 if (!symbol_contains_sep) {
5624 // We insert the space into the symbol instead of
5625 // setting pat.field[2]=space so that when
5626 // showbase is not set, the space goes away too.
5627 __curr_symbol_.insert(0, 1, space_char);
5628 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005629 return;
5630 default:
5631 break;
5632 }
5633 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005634 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005635 pat.field[0] = sign;
5636 pat.field[3] = value;
5637 switch (sep_by_space)
5638 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005639 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005640 pat.field[1] = symbol;
5641 pat.field[2] = none;
5642 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005643 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005644 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005645 pat.field[2] = none;
5646 if (!symbol_contains_sep) {
5647 // We insert the space into the symbol instead of
5648 // setting pat.field[2]=space so that when
5649 // showbase is not set, the space goes away too.
5650 __curr_symbol_.push_back(space_char);
5651 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005652 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005653 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005654 pat.field[1] = space;
5655 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005656 if (symbol_contains_sep) {
5657 // Remove the separator from the symbol, since it
5658 // has already appeared after the sign.
5659 __curr_symbol_.pop_back();
5660 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005661 return;
5662 default:
5663 break;
5664 }
5665 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005666 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005667 pat.field[0] = symbol;
5668 pat.field[3] = sign;
5669 switch (sep_by_space)
5670 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005671 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005672 pat.field[1] = none;
5673 pat.field[2] = value;
5674 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005675 case 1: // Space between currency-and-sign or currency and value.
5676 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005677 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005678 if (!symbol_contains_sep) {
5679 // We insert the space into the symbol instead of
5680 // setting pat.field[1]=space so that when
5681 // showbase is not set, the space goes away too.
5682 __curr_symbol_.push_back(space_char);
5683 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005684 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005685 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005686 pat.field[1] = value;
5687 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005688 if (symbol_contains_sep) {
5689 // Remove the separator from the symbol, since it
5690 // will appear before the sign.
5691 __curr_symbol_.pop_back();
5692 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005693 return;
5694 default:
5695 break;
5696 }
5697 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005698 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005699 pat.field[0] = sign;
5700 pat.field[3] = value;
5701 switch (sep_by_space)
5702 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005703 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005704 pat.field[1] = symbol;
5705 pat.field[2] = none;
5706 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005707 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005708 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005709 pat.field[2] = none;
5710 if (!symbol_contains_sep) {
5711 // We insert the space into the symbol instead of
5712 // setting pat.field[2]=space so that when
5713 // showbase is not set, the space goes away too.
5714 __curr_symbol_.push_back(space_char);
5715 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005716 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005717 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005718 pat.field[1] = space;
5719 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005720 if (symbol_contains_sep) {
5721 // Remove the separator from the symbol, since it
5722 // has already appeared after the sign.
5723 __curr_symbol_.pop_back();
5724 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005725 return;
5726 default:
5727 break;
5728 }
5729 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005730 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005731 pat.field[0] = symbol;
5732 pat.field[3] = value;
5733 switch (sep_by_space)
5734 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005735 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005736 pat.field[1] = sign;
5737 pat.field[2] = none;
5738 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005739 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005740 pat.field[1] = sign;
5741 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005742 if (symbol_contains_sep) {
5743 // Remove the separator from the symbol, since it
5744 // should not disappear when showbase is absent.
5745 __curr_symbol_.pop_back();
5746 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005747 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005748 case 2: // Space between sign and currency or value.
5749 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005750 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005751 if (!symbol_contains_sep) {
5752 // We insert the space into the symbol instead of
5753 // setting pat.field[1]=space so that when
5754 // showbase is not set, the space goes away too.
5755 __curr_symbol_.push_back(space_char);
5756 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005757 return;
5758 default:
5759 break;
5760 }
5761 break;
5762 default:
5763 break;
5764 }
5765 break;
5766 default:
5767 break;
5768 }
5769 pat.field[0] = symbol;
5770 pat.field[1] = sign;
5771 pat.field[2] = none;
5772 pat.field[3] = value;
5773}
5774
5775template<>
5776void
5777moneypunct_byname<char, false>::init(const char* nm)
5778{
5779 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005780 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005781#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005782 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005783 throw runtime_error("moneypunct_byname"
5784 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005785#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005786#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005787 lconv* lc = localeconv_l(loc.get());
5788#else
5789 lconv* lc = __localeconv_l(loc.get());
5790#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005791 if (*lc->mon_decimal_point)
5792 __decimal_point_ = *lc->mon_decimal_point;
5793 else
5794 __decimal_point_ = base::do_decimal_point();
5795 if (*lc->mon_thousands_sep)
5796 __thousands_sep_ = *lc->mon_thousands_sep;
5797 else
5798 __thousands_sep_ = base::do_thousands_sep();
5799 __grouping_ = lc->mon_grouping;
5800 __curr_symbol_ = lc->currency_symbol;
5801 if (lc->frac_digits != CHAR_MAX)
5802 __frac_digits_ = lc->frac_digits;
5803 else
5804 __frac_digits_ = base::do_frac_digits();
5805 if (lc->p_sign_posn == 0)
5806 __positive_sign_ = "()";
5807 else
5808 __positive_sign_ = lc->positive_sign;
5809 if (lc->n_sign_posn == 0)
5810 __negative_sign_ = "()";
5811 else
5812 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005813 // Assume the positive and negative formats will want spaces in
5814 // the same places in curr_symbol since there's no way to
5815 // represent anything else.
5816 string_type __dummy_curr_symbol = __curr_symbol_;
5817 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5818 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5819 __init_pat(__neg_format_, __curr_symbol_, false,
5820 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005821}
5822
5823template<>
5824void
5825moneypunct_byname<char, true>::init(const char* nm)
5826{
5827 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005828 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005829#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005830 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005831 throw runtime_error("moneypunct_byname"
5832 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005833#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005834#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005835 lconv* lc = localeconv_l(loc.get());
5836#else
5837 lconv* lc = __localeconv_l(loc.get());
5838#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005839 if (*lc->mon_decimal_point)
5840 __decimal_point_ = *lc->mon_decimal_point;
5841 else
5842 __decimal_point_ = base::do_decimal_point();
5843 if (*lc->mon_thousands_sep)
5844 __thousands_sep_ = *lc->mon_thousands_sep;
5845 else
5846 __thousands_sep_ = base::do_thousands_sep();
5847 __grouping_ = lc->mon_grouping;
5848 __curr_symbol_ = lc->int_curr_symbol;
5849 if (lc->int_frac_digits != CHAR_MAX)
5850 __frac_digits_ = lc->int_frac_digits;
5851 else
5852 __frac_digits_ = base::do_frac_digits();
Howard Hinnante9df0a52013-08-01 18:17:34 +00005853#ifdef _LIBCPP_MSVCRT
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005854 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005855#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005856 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005857#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005858 __positive_sign_ = "()";
5859 else
5860 __positive_sign_ = lc->positive_sign;
Howard Hinnante9df0a52013-08-01 18:17:34 +00005861#ifdef _LIBCPP_MSVCRT
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005862 if(lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005863#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005864 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005865#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005866 __negative_sign_ = "()";
5867 else
5868 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005869 // Assume the positive and negative formats will want spaces in
5870 // the same places in curr_symbol since there's no way to
5871 // represent anything else.
5872 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnante9df0a52013-08-01 18:17:34 +00005873#ifdef _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005874 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5875 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5876 __init_pat(__neg_format_, __curr_symbol_, true,
5877 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005878#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005879 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5880 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5881 lc->int_p_sign_posn, ' ');
5882 __init_pat(__neg_format_, __curr_symbol_, true,
5883 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5884 lc->int_n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005885#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005886}
5887
5888template<>
5889void
5890moneypunct_byname<wchar_t, false>::init(const char* nm)
5891{
5892 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005893 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005894#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005895 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005896 throw runtime_error("moneypunct_byname"
5897 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005898#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005899#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005900 lconv* lc = localeconv_l(loc.get());
5901#else
5902 lconv* lc = __localeconv_l(loc.get());
5903#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005904 if (*lc->mon_decimal_point)
5905 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5906 else
5907 __decimal_point_ = base::do_decimal_point();
5908 if (*lc->mon_thousands_sep)
5909 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5910 else
5911 __thousands_sep_ = base::do_thousands_sep();
5912 __grouping_ = lc->mon_grouping;
5913 wchar_t wbuf[100];
5914 mbstate_t mb = {0};
5915 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005916#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005917 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005918#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005919 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005920#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005921 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005922 __throw_runtime_error("locale not supported");
5923 wchar_t* wbe = wbuf + j;
5924 __curr_symbol_.assign(wbuf, wbe);
5925 if (lc->frac_digits != CHAR_MAX)
5926 __frac_digits_ = lc->frac_digits;
5927 else
5928 __frac_digits_ = base::do_frac_digits();
5929 if (lc->p_sign_posn == 0)
5930 __positive_sign_ = L"()";
5931 else
5932 {
5933 mb = mbstate_t();
5934 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005935#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005936 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005937#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005938 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005939#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005940 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005941 __throw_runtime_error("locale not supported");
5942 wbe = wbuf + j;
5943 __positive_sign_.assign(wbuf, wbe);
5944 }
5945 if (lc->n_sign_posn == 0)
5946 __negative_sign_ = L"()";
5947 else
5948 {
5949 mb = mbstate_t();
5950 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005951#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005952 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005953#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005954 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005955#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005956 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005957 __throw_runtime_error("locale not supported");
5958 wbe = wbuf + j;
5959 __negative_sign_.assign(wbuf, wbe);
5960 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005961 // Assume the positive and negative formats will want spaces in
5962 // the same places in curr_symbol since there's no way to
5963 // represent anything else.
5964 string_type __dummy_curr_symbol = __curr_symbol_;
5965 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5966 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5967 __init_pat(__neg_format_, __curr_symbol_, false,
5968 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005969}
5970
5971template<>
5972void
5973moneypunct_byname<wchar_t, true>::init(const char* nm)
5974{
5975 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005976 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005977#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005978 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005979 throw runtime_error("moneypunct_byname"
5980 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005981#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005982#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005983 lconv* lc = localeconv_l(loc.get());
5984#else
5985 lconv* lc = __localeconv_l(loc.get());
5986#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005987 if (*lc->mon_decimal_point)
5988 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5989 else
5990 __decimal_point_ = base::do_decimal_point();
5991 if (*lc->mon_thousands_sep)
5992 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5993 else
5994 __thousands_sep_ = base::do_thousands_sep();
5995 __grouping_ = lc->mon_grouping;
5996 wchar_t wbuf[100];
5997 mbstate_t mb = {0};
5998 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005999#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006000 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006001#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006002 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006003#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006004 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006005 __throw_runtime_error("locale not supported");
6006 wchar_t* wbe = wbuf + j;
6007 __curr_symbol_.assign(wbuf, wbe);
6008 if (lc->int_frac_digits != CHAR_MAX)
6009 __frac_digits_ = lc->int_frac_digits;
6010 else
6011 __frac_digits_ = base::do_frac_digits();
Howard Hinnante9df0a52013-08-01 18:17:34 +00006012#ifdef _LIBCPP_MSVCRT
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006013 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006014#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006015 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006016#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006017 __positive_sign_ = L"()";
6018 else
6019 {
6020 mb = mbstate_t();
6021 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006022#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006023 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006024#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006025 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006026#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006027 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006028 __throw_runtime_error("locale not supported");
6029 wbe = wbuf + j;
6030 __positive_sign_.assign(wbuf, wbe);
6031 }
Howard Hinnante9df0a52013-08-01 18:17:34 +00006032#ifdef _LIBCPP_MSVCRT
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006033 if (lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006034#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006035 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006036#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006037 __negative_sign_ = L"()";
6038 else
6039 {
6040 mb = mbstate_t();
6041 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006042#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006043 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006044#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006045 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006046#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006047 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006048 __throw_runtime_error("locale not supported");
6049 wbe = wbuf + j;
6050 __negative_sign_.assign(wbuf, wbe);
6051 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006052 // Assume the positive and negative formats will want spaces in
6053 // the same places in curr_symbol since there's no way to
6054 // represent anything else.
6055 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnante9df0a52013-08-01 18:17:34 +00006056#ifdef _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006057 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6058 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6059 __init_pat(__neg_format_, __curr_symbol_, true,
6060 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006061#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006062 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6063 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6064 lc->int_p_sign_posn, L' ');
6065 __init_pat(__neg_format_, __curr_symbol_, true,
6066 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6067 lc->int_n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006068#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006069}
6070
6071void __do_nothing(void*) {}
6072
6073void __throw_runtime_error(const char* msg)
6074{
Howard Hinnantd4444702010-08-11 17:04:31 +00006075#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006076 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006077#else
6078 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006079#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006080}
6081
6082template class collate<char>;
6083template class collate<wchar_t>;
6084
6085template class num_get<char>;
6086template class num_get<wchar_t>;
6087
Howard Hinnantec3773c2011-12-01 20:21:04 +00006088template struct __num_get<char>;
6089template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006090
6091template class num_put<char>;
6092template class num_put<wchar_t>;
6093
Howard Hinnantec3773c2011-12-01 20:21:04 +00006094template struct __num_put<char>;
6095template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006096
6097template class time_get<char>;
6098template class time_get<wchar_t>;
6099
6100template class time_get_byname<char>;
6101template class time_get_byname<wchar_t>;
6102
6103template class time_put<char>;
6104template class time_put<wchar_t>;
6105
6106template class time_put_byname<char>;
6107template class time_put_byname<wchar_t>;
6108
6109template class moneypunct<char, false>;
6110template class moneypunct<char, true>;
6111template class moneypunct<wchar_t, false>;
6112template class moneypunct<wchar_t, true>;
6113
6114template class moneypunct_byname<char, false>;
6115template class moneypunct_byname<char, true>;
6116template class moneypunct_byname<wchar_t, false>;
6117template class moneypunct_byname<wchar_t, true>;
6118
6119template class money_get<char>;
6120template class money_get<wchar_t>;
6121
6122template class __money_get<char>;
6123template class __money_get<wchar_t>;
6124
6125template class money_put<char>;
6126template class money_put<wchar_t>;
6127
6128template class __money_put<char>;
6129template class __money_put<wchar_t>;
6130
6131template class messages<char>;
6132template class messages<wchar_t>;
6133
6134template class messages_byname<char>;
6135template class messages_byname<wchar_t>;
6136
6137template class codecvt_byname<char, char, mbstate_t>;
6138template class codecvt_byname<wchar_t, char, mbstate_t>;
6139template class codecvt_byname<char16_t, char, mbstate_t>;
6140template class codecvt_byname<char32_t, char, mbstate_t>;
6141
6142template class __vector_base_common<true>;
6143
6144_LIBCPP_END_NAMESPACE_STD