blob: d95d0c9c954d5375661502bf42f3dd808d6a8c79 [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();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001018#else
David Chisnall997e4542012-02-29 13:05:08 +00001019 // Platform not supported: abort so the person doing the port knows what to
1020 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001021# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001022 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001023 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001024 return NULL;
1025#endif
1026}
1027
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001028#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001029const int*
1030ctype<char>::__classic_lower_table() _NOEXCEPT
1031{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001032 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001033}
1034
1035const int*
1036ctype<char>::__classic_upper_table() _NOEXCEPT
1037{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001038 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001039}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001040#elif __NetBSD__
1041const short*
1042ctype<char>::__classic_lower_table() _NOEXCEPT
1043{
1044 return _C_tolower_tab_ + 1;
1045}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001046
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001047const short*
1048ctype<char>::__classic_upper_table() _NOEXCEPT
1049{
1050 return _C_toupper_tab_ + 1;
1051}
1052
1053#elif defined(EMSCRIPTEN)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001054const int*
1055ctype<char>::__classic_lower_table() _NOEXCEPT
1056{
1057 return *__ctype_tolower_loc();
1058}
1059
1060const int*
1061ctype<char>::__classic_upper_table() _NOEXCEPT
1062{
1063 return *__ctype_toupper_loc();
1064}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001065#endif // __GLIBC__ || EMSCRIPTEN || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001066
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001067// template <> class ctype_byname<char>
1068
1069ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1070 : ctype<char>(0, false, refs),
1071 __l(newlocale(LC_ALL_MASK, name, 0))
1072{
Howard Hinnantd4444702010-08-11 17:04:31 +00001073#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001074 if (__l == 0)
1075 throw runtime_error("ctype_byname<char>::ctype_byname"
1076 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001077#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001078}
1079
1080ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1081 : ctype<char>(0, false, refs),
1082 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1083{
Howard Hinnantd4444702010-08-11 17:04:31 +00001084#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001085 if (__l == 0)
1086 throw runtime_error("ctype_byname<char>::ctype_byname"
1087 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001088#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001089}
1090
1091ctype_byname<char>::~ctype_byname()
1092{
1093 freelocale(__l);
1094}
1095
1096char
1097ctype_byname<char>::do_toupper(char_type c) const
1098{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001099 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001100}
1101
1102const char*
1103ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1104{
1105 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001106 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001107 return low;
1108}
1109
1110char
1111ctype_byname<char>::do_tolower(char_type c) const
1112{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001113 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001114}
1115
1116const char*
1117ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1118{
1119 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001120 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001121 return low;
1122}
1123
1124// template <> class ctype_byname<wchar_t>
1125
1126ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1127 : ctype<wchar_t>(refs),
1128 __l(newlocale(LC_ALL_MASK, name, 0))
1129{
Howard Hinnantd4444702010-08-11 17:04:31 +00001130#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001131 if (__l == 0)
1132 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1133 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001134#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001135}
1136
1137ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1138 : ctype<wchar_t>(refs),
1139 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1140{
Howard Hinnantd4444702010-08-11 17:04:31 +00001141#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001142 if (__l == 0)
1143 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1144 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001145#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001146}
1147
1148ctype_byname<wchar_t>::~ctype_byname()
1149{
1150 freelocale(__l);
1151}
1152
1153bool
1154ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1155{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001156#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001157 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001158#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001159 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001160 wint_t ch = static_cast<wint_t>(c);
1161 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1162 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1163 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1164 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1165 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1166 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1167 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1168 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1169 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1170 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001171 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001172#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001173}
1174
1175const wchar_t*
1176ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1177{
1178 for (; low != high; ++low, ++vec)
1179 {
1180 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001181 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001182 else
1183 {
1184 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001185 wint_t ch = static_cast<wint_t>(*low);
1186 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001187 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001188 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001189 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001190 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001191 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001192 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001193 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001194 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001195 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001196 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001197 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001198 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001199 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001200 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001201 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001202 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001203 *vec |= xdigit;
1204 }
1205 }
1206 return low;
1207}
1208
1209const wchar_t*
1210ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1211{
1212 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001213 {
1214#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001215 if (iswctype_l(*low, m, __l))
1216 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001217#else
Marshall Clow88c31902013-02-07 14:22:51 +00001218 wint_t ch = static_cast<wint_t>(*low);
1219 if (m & space && iswspace_l(ch, __l)) break;
1220 if (m & print && iswprint_l(ch, __l)) break;
1221 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1222 if (m & upper && iswupper_l(ch, __l)) break;
1223 if (m & lower && iswlower_l(ch, __l)) break;
1224 if (m & alpha && iswalpha_l(ch, __l)) break;
1225 if (m & digit && iswdigit_l(ch, __l)) break;
1226 if (m & punct && iswpunct_l(ch, __l)) break;
1227 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1228 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001229#endif
1230 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001231 return low;
1232}
1233
1234const wchar_t*
1235ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1236{
1237 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001238 {
1239#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 if (!iswctype_l(*low, m, __l))
1241 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001242#else
Marshall Clow88c31902013-02-07 14:22:51 +00001243 wint_t ch = static_cast<wint_t>(*low);
1244 if (m & space && iswspace_l(ch, __l)) continue;
1245 if (m & print && iswprint_l(ch, __l)) continue;
1246 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1247 if (m & upper && iswupper_l(ch, __l)) continue;
1248 if (m & lower && iswlower_l(ch, __l)) continue;
1249 if (m & alpha && iswalpha_l(ch, __l)) continue;
1250 if (m & digit && iswdigit_l(ch, __l)) continue;
1251 if (m & punct && iswpunct_l(ch, __l)) continue;
1252 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1253 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001254 break;
1255#endif
1256 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001257 return low;
1258}
1259
1260wchar_t
1261ctype_byname<wchar_t>::do_toupper(char_type c) const
1262{
1263 return towupper_l(c, __l);
1264}
1265
1266const wchar_t*
1267ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1268{
1269 for (; low != high; ++low)
1270 *low = towupper_l(*low, __l);
1271 return low;
1272}
1273
1274wchar_t
1275ctype_byname<wchar_t>::do_tolower(char_type c) const
1276{
1277 return towlower_l(c, __l);
1278}
1279
1280const wchar_t*
1281ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1282{
1283 for (; low != high; ++low)
1284 *low = towlower_l(*low, __l);
1285 return low;
1286}
1287
1288wchar_t
1289ctype_byname<wchar_t>::do_widen(char c) const
1290{
Howard Hinnant866569b2011-09-28 23:39:33 +00001291#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001292 return btowc_l(c, __l);
1293#else
1294 return __btowc_l(c, __l);
1295#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001296}
1297
1298const char*
1299ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1300{
1301 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001302#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001303 *dest = btowc_l(*low, __l);
1304#else
1305 *dest = __btowc_l(*low, __l);
1306#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001307 return low;
1308}
1309
1310char
1311ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1312{
Howard Hinnant866569b2011-09-28 23:39:33 +00001313#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001314 int r = wctob_l(c, __l);
1315#else
1316 int r = __wctob_l(c, __l);
1317#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001318 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001319}
1320
1321const wchar_t*
1322ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1323{
1324 for (; low != high; ++low, ++dest)
1325 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001326#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001327 int r = wctob_l(*low, __l);
1328#else
1329 int r = __wctob_l(*low, __l);
1330#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001331 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001332 }
1333 return low;
1334}
1335
1336// template <> class codecvt<char, char, mbstate_t>
1337
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001338locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001339
1340codecvt<char, char, mbstate_t>::~codecvt()
1341{
1342}
1343
1344codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001345codecvt<char, char, mbstate_t>::do_out(state_type&,
1346 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001347 extern_type* to, extern_type*, extern_type*& to_nxt) const
1348{
1349 frm_nxt = frm;
1350 to_nxt = to;
1351 return noconv;
1352}
1353
1354codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001355codecvt<char, char, mbstate_t>::do_in(state_type&,
1356 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001357 intern_type* to, intern_type*, intern_type*& to_nxt) const
1358{
1359 frm_nxt = frm;
1360 to_nxt = to;
1361 return noconv;
1362}
1363
1364codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001365codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001366 extern_type* to, extern_type*, extern_type*& to_nxt) const
1367{
1368 to_nxt = to;
1369 return noconv;
1370}
1371
1372int
Howard Hinnantc9834542011-05-31 15:34:58 +00001373codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001374{
1375 return 1;
1376}
1377
1378bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001379codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001380{
1381 return true;
1382}
1383
1384int
1385codecvt<char, char, mbstate_t>::do_length(state_type&,
1386 const extern_type* frm, const extern_type* end, size_t mx) const
1387{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001388 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001389}
1390
1391int
Howard Hinnantc9834542011-05-31 15:34:58 +00001392codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001393{
1394 return 1;
1395}
1396
1397// template <> class codecvt<wchar_t, char, mbstate_t>
1398
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001399locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001400
1401codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1402 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001403 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001404{
1405}
1406
1407codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1408 : locale::facet(refs),
1409 __l(newlocale(LC_ALL_MASK, nm, 0))
1410{
Howard Hinnantd4444702010-08-11 17:04:31 +00001411#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001412 if (__l == 0)
1413 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1414 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001415#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001416}
1417
1418codecvt<wchar_t, char, mbstate_t>::~codecvt()
1419{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001420 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001421 freelocale(__l);
1422}
1423
1424codecvt<wchar_t, char, mbstate_t>::result
1425codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001426 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001427 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1428{
1429 // look for first internal null in frm
1430 const intern_type* fend = frm;
1431 for (; fend != frm_end; ++fend)
1432 if (*fend == 0)
1433 break;
1434 // loop over all null-terminated sequences in frm
1435 to_nxt = to;
1436 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1437 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001438 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001439 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001440#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001441 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1442 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001443#else
1444 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1445#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001446 if (n == size_t(-1))
1447 {
1448 // need to recover to_nxt
1449 for (to_nxt = to; frm != frm_nxt; ++frm)
1450 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001451#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001452 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1453#else
1454 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1455#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001456 if (n == size_t(-1))
1457 break;
1458 to_nxt += n;
1459 }
1460 frm_nxt = frm;
1461 return error;
1462 }
1463 if (n == 0)
1464 return partial;
1465 to_nxt += n;
1466 if (to_nxt == to_end)
1467 break;
1468 if (fend != frm_end) // set up next null terminated sequence
1469 {
1470 // Try to write the terminating null
1471 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001472#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001473 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1474#else
1475 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1476#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001477 if (n == size_t(-1)) // on error
1478 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001479 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001480 return partial;
1481 for (extern_type* p = tmp; n; --n) // write it
1482 *to_nxt++ = *p++;
1483 ++frm_nxt;
1484 // look for next null in frm
1485 for (fend = frm_nxt; fend != frm_end; ++fend)
1486 if (*fend == 0)
1487 break;
1488 }
1489 }
1490 return frm_nxt == frm_end ? ok : partial;
1491}
1492
1493codecvt<wchar_t, char, mbstate_t>::result
1494codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001495 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001496 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1497{
1498 // look for first internal null in frm
1499 const extern_type* fend = frm;
1500 for (; fend != frm_end; ++fend)
1501 if (*fend == 0)
1502 break;
1503 // loop over all null-terminated sequences in frm
1504 to_nxt = to;
1505 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1506 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001507 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001508 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001509#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001510 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1511 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001512#else
1513 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1514#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001515 if (n == size_t(-1))
1516 {
1517 // need to recover to_nxt
1518 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1519 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001520#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001521 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1522 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001523#else
1524 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1525#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001526 switch (n)
1527 {
1528 case 0:
1529 ++frm;
1530 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001531 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 frm_nxt = frm;
1533 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001534 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001535 frm_nxt = frm;
1536 return partial;
1537 default:
1538 frm += n;
1539 break;
1540 }
1541 }
1542 frm_nxt = frm;
1543 return frm_nxt == frm_end ? ok : partial;
1544 }
1545 if (n == 0)
1546 return error;
1547 to_nxt += n;
1548 if (to_nxt == to_end)
1549 break;
1550 if (fend != frm_end) // set up next null terminated sequence
1551 {
1552 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001553#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001554 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1555#else
1556 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1557#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001558 if (n != 0) // on error
1559 return error;
1560 ++to_nxt;
1561 ++frm_nxt;
1562 // look for next null in frm
1563 for (fend = frm_nxt; fend != frm_end; ++fend)
1564 if (*fend == 0)
1565 break;
1566 }
1567 }
1568 return frm_nxt == frm_end ? ok : partial;
1569}
1570
1571codecvt<wchar_t, char, mbstate_t>::result
1572codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1573 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1574{
1575 to_nxt = to;
1576 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001577#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001578 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1579#else
1580 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1581#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001582 if (n == size_t(-1) || n == 0) // on error
1583 return error;
1584 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001585 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001586 return partial;
1587 for (extern_type* p = tmp; n; --n) // write it
1588 *to_nxt++ = *p++;
1589 return ok;
1590}
1591
1592int
Howard Hinnantc9834542011-05-31 15:34:58 +00001593codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001594{
Howard Hinnant866569b2011-09-28 23:39:33 +00001595#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001596 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1597#else
1598 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1599#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001600 {
1601 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001602#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001603 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1604#else
1605 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1606#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001607 return 1; // which take more than 1 char to form a wchar_t
1608 return 0;
1609 }
1610 return -1;
1611}
1612
1613bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001614codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001615{
1616 return false;
1617}
1618
1619int
1620codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1621 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1622{
1623 int nbytes = 0;
1624 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1625 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001626#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001627 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001628#else
1629 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1630#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001631 switch (n)
1632 {
1633 case 0:
1634 ++nbytes;
1635 ++frm;
1636 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001637 case size_t(-1):
1638 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001639 return nbytes;
1640 default:
1641 nbytes += n;
1642 frm += n;
1643 break;
1644 }
1645 }
1646 return nbytes;
1647}
1648
1649int
Howard Hinnantc9834542011-05-31 15:34:58 +00001650codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001651{
Howard Hinnant866569b2011-09-28 23:39:33 +00001652#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001653 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001654#else
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#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001657}
1658
1659// Valid UTF ranges
1660// UTF-32 UTF-16 UTF-8 # of code points
1661// first second first second third fourth
1662// 000000 - 00007F 0000 - 007F 00 - 7F 127
1663// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1664// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1665// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1666// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1667// 00D800 - 00DFFF invalid
1668// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1669// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1670// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1671// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1672
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001673static
1674codecvt_base::result
1675utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1676 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1677 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1678{
1679 frm_nxt = frm;
1680 to_nxt = to;
1681 if (mode & generate_header)
1682 {
1683 if (to_end-to_nxt < 3)
1684 return codecvt_base::partial;
1685 *to_nxt++ = static_cast<uint8_t>(0xEF);
1686 *to_nxt++ = static_cast<uint8_t>(0xBB);
1687 *to_nxt++ = static_cast<uint8_t>(0xBF);
1688 }
1689 for (; frm_nxt < frm_end; ++frm_nxt)
1690 {
1691 uint16_t wc1 = *frm_nxt;
1692 if (wc1 > Maxcode)
1693 return codecvt_base::error;
1694 if (wc1 < 0x0080)
1695 {
1696 if (to_end-to_nxt < 1)
1697 return codecvt_base::partial;
1698 *to_nxt++ = static_cast<uint8_t>(wc1);
1699 }
1700 else if (wc1 < 0x0800)
1701 {
1702 if (to_end-to_nxt < 2)
1703 return codecvt_base::partial;
1704 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1705 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1706 }
1707 else if (wc1 < 0xD800)
1708 {
1709 if (to_end-to_nxt < 3)
1710 return codecvt_base::partial;
1711 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1712 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1713 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1714 }
1715 else if (wc1 < 0xDC00)
1716 {
1717 if (frm_end-frm_nxt < 2)
1718 return codecvt_base::partial;
1719 uint16_t wc2 = frm_nxt[1];
1720 if ((wc2 & 0xFC00) != 0xDC00)
1721 return codecvt_base::error;
1722 if (to_end-to_nxt < 4)
1723 return codecvt_base::partial;
1724 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1725 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1726 return codecvt_base::error;
1727 ++frm_nxt;
1728 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1729 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1730 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1731 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1732 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1733 }
1734 else if (wc1 < 0xE000)
1735 {
1736 return codecvt_base::error;
1737 }
1738 else
1739 {
1740 if (to_end-to_nxt < 3)
1741 return codecvt_base::partial;
1742 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1743 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1744 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1745 }
1746 }
1747 return codecvt_base::ok;
1748}
1749
1750static
1751codecvt_base::result
1752utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1753 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1754 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1755{
1756 frm_nxt = frm;
1757 to_nxt = to;
1758 if (mode & generate_header)
1759 {
1760 if (to_end-to_nxt < 3)
1761 return codecvt_base::partial;
1762 *to_nxt++ = static_cast<uint8_t>(0xEF);
1763 *to_nxt++ = static_cast<uint8_t>(0xBB);
1764 *to_nxt++ = static_cast<uint8_t>(0xBF);
1765 }
1766 for (; frm_nxt < frm_end; ++frm_nxt)
1767 {
1768 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1769 if (wc1 > Maxcode)
1770 return codecvt_base::error;
1771 if (wc1 < 0x0080)
1772 {
1773 if (to_end-to_nxt < 1)
1774 return codecvt_base::partial;
1775 *to_nxt++ = static_cast<uint8_t>(wc1);
1776 }
1777 else if (wc1 < 0x0800)
1778 {
1779 if (to_end-to_nxt < 2)
1780 return codecvt_base::partial;
1781 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1782 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1783 }
1784 else if (wc1 < 0xD800)
1785 {
1786 if (to_end-to_nxt < 3)
1787 return codecvt_base::partial;
1788 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1789 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1790 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1791 }
1792 else if (wc1 < 0xDC00)
1793 {
1794 if (frm_end-frm_nxt < 2)
1795 return codecvt_base::partial;
1796 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1797 if ((wc2 & 0xFC00) != 0xDC00)
1798 return codecvt_base::error;
1799 if (to_end-to_nxt < 4)
1800 return codecvt_base::partial;
1801 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1802 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1803 return codecvt_base::error;
1804 ++frm_nxt;
1805 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1806 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1807 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1808 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1809 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1810 }
1811 else if (wc1 < 0xE000)
1812 {
1813 return codecvt_base::error;
1814 }
1815 else
1816 {
1817 if (to_end-to_nxt < 3)
1818 return codecvt_base::partial;
1819 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1820 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1821 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1822 }
1823 }
1824 return codecvt_base::ok;
1825}
1826
1827static
1828codecvt_base::result
1829utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1830 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1831 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1832{
1833 frm_nxt = frm;
1834 to_nxt = to;
1835 if (mode & consume_header)
1836 {
1837 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1838 frm_nxt[2] == 0xBF)
1839 frm_nxt += 3;
1840 }
1841 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1842 {
1843 uint8_t c1 = *frm_nxt;
1844 if (c1 > Maxcode)
1845 return codecvt_base::error;
1846 if (c1 < 0x80)
1847 {
1848 *to_nxt = static_cast<uint16_t>(c1);
1849 ++frm_nxt;
1850 }
1851 else if (c1 < 0xC2)
1852 {
1853 return codecvt_base::error;
1854 }
1855 else if (c1 < 0xE0)
1856 {
1857 if (frm_end-frm_nxt < 2)
1858 return codecvt_base::partial;
1859 uint8_t c2 = frm_nxt[1];
1860 if ((c2 & 0xC0) != 0x80)
1861 return codecvt_base::error;
1862 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1863 if (t > Maxcode)
1864 return codecvt_base::error;
1865 *to_nxt = t;
1866 frm_nxt += 2;
1867 }
1868 else if (c1 < 0xF0)
1869 {
1870 if (frm_end-frm_nxt < 3)
1871 return codecvt_base::partial;
1872 uint8_t c2 = frm_nxt[1];
1873 uint8_t c3 = frm_nxt[2];
1874 switch (c1)
1875 {
1876 case 0xE0:
1877 if ((c2 & 0xE0) != 0xA0)
1878 return codecvt_base::error;
1879 break;
1880 case 0xED:
1881 if ((c2 & 0xE0) != 0x80)
1882 return codecvt_base::error;
1883 break;
1884 default:
1885 if ((c2 & 0xC0) != 0x80)
1886 return codecvt_base::error;
1887 break;
1888 }
1889 if ((c3 & 0xC0) != 0x80)
1890 return codecvt_base::error;
1891 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1892 | ((c2 & 0x3F) << 6)
1893 | (c3 & 0x3F));
1894 if (t > Maxcode)
1895 return codecvt_base::error;
1896 *to_nxt = t;
1897 frm_nxt += 3;
1898 }
1899 else if (c1 < 0xF5)
1900 {
1901 if (frm_end-frm_nxt < 4)
1902 return codecvt_base::partial;
1903 uint8_t c2 = frm_nxt[1];
1904 uint8_t c3 = frm_nxt[2];
1905 uint8_t c4 = frm_nxt[3];
1906 switch (c1)
1907 {
1908 case 0xF0:
1909 if (!(0x90 <= c2 && c2 <= 0xBF))
1910 return codecvt_base::error;
1911 break;
1912 case 0xF4:
1913 if ((c2 & 0xF0) != 0x80)
1914 return codecvt_base::error;
1915 break;
1916 default:
1917 if ((c2 & 0xC0) != 0x80)
1918 return codecvt_base::error;
1919 break;
1920 }
1921 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1922 return codecvt_base::error;
1923 if (to_end-to_nxt < 2)
1924 return codecvt_base::partial;
1925 if (((((unsigned long)c1 & 7) << 18) +
1926 (((unsigned long)c2 & 0x3F) << 12) +
1927 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1928 return codecvt_base::error;
1929 *to_nxt = static_cast<uint16_t>(
1930 0xD800
1931 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1932 | ((c2 & 0x0F) << 2)
1933 | ((c3 & 0x30) >> 4));
1934 *++to_nxt = static_cast<uint16_t>(
1935 0xDC00
1936 | ((c3 & 0x0F) << 6)
1937 | (c4 & 0x3F));
1938 frm_nxt += 4;
1939 }
1940 else
1941 {
1942 return codecvt_base::error;
1943 }
1944 }
1945 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1946}
1947
1948static
1949codecvt_base::result
1950utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1951 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1952 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1953{
1954 frm_nxt = frm;
1955 to_nxt = to;
1956 if (mode & consume_header)
1957 {
1958 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1959 frm_nxt[2] == 0xBF)
1960 frm_nxt += 3;
1961 }
1962 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1963 {
1964 uint8_t c1 = *frm_nxt;
1965 if (c1 > Maxcode)
1966 return codecvt_base::error;
1967 if (c1 < 0x80)
1968 {
1969 *to_nxt = static_cast<uint32_t>(c1);
1970 ++frm_nxt;
1971 }
1972 else if (c1 < 0xC2)
1973 {
1974 return codecvt_base::error;
1975 }
1976 else if (c1 < 0xE0)
1977 {
1978 if (frm_end-frm_nxt < 2)
1979 return codecvt_base::partial;
1980 uint8_t c2 = frm_nxt[1];
1981 if ((c2 & 0xC0) != 0x80)
1982 return codecvt_base::error;
1983 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1984 if (t > Maxcode)
1985 return codecvt_base::error;
1986 *to_nxt = static_cast<uint32_t>(t);
1987 frm_nxt += 2;
1988 }
1989 else if (c1 < 0xF0)
1990 {
1991 if (frm_end-frm_nxt < 3)
1992 return codecvt_base::partial;
1993 uint8_t c2 = frm_nxt[1];
1994 uint8_t c3 = frm_nxt[2];
1995 switch (c1)
1996 {
1997 case 0xE0:
1998 if ((c2 & 0xE0) != 0xA0)
1999 return codecvt_base::error;
2000 break;
2001 case 0xED:
2002 if ((c2 & 0xE0) != 0x80)
2003 return codecvt_base::error;
2004 break;
2005 default:
2006 if ((c2 & 0xC0) != 0x80)
2007 return codecvt_base::error;
2008 break;
2009 }
2010 if ((c3 & 0xC0) != 0x80)
2011 return codecvt_base::error;
2012 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2013 | ((c2 & 0x3F) << 6)
2014 | (c3 & 0x3F));
2015 if (t > Maxcode)
2016 return codecvt_base::error;
2017 *to_nxt = static_cast<uint32_t>(t);
2018 frm_nxt += 3;
2019 }
2020 else if (c1 < 0xF5)
2021 {
2022 if (frm_end-frm_nxt < 4)
2023 return codecvt_base::partial;
2024 uint8_t c2 = frm_nxt[1];
2025 uint8_t c3 = frm_nxt[2];
2026 uint8_t c4 = frm_nxt[3];
2027 switch (c1)
2028 {
2029 case 0xF0:
2030 if (!(0x90 <= c2 && c2 <= 0xBF))
2031 return codecvt_base::error;
2032 break;
2033 case 0xF4:
2034 if ((c2 & 0xF0) != 0x80)
2035 return codecvt_base::error;
2036 break;
2037 default:
2038 if ((c2 & 0xC0) != 0x80)
2039 return codecvt_base::error;
2040 break;
2041 }
2042 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2043 return codecvt_base::error;
2044 if (to_end-to_nxt < 2)
2045 return codecvt_base::partial;
2046 if (((((unsigned long)c1 & 7) << 18) +
2047 (((unsigned long)c2 & 0x3F) << 12) +
2048 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2049 return codecvt_base::error;
2050 *to_nxt = static_cast<uint32_t>(
2051 0xD800
2052 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2053 | ((c2 & 0x0F) << 2)
2054 | ((c3 & 0x30) >> 4));
2055 *++to_nxt = static_cast<uint32_t>(
2056 0xDC00
2057 | ((c3 & 0x0F) << 6)
2058 | (c4 & 0x3F));
2059 frm_nxt += 4;
2060 }
2061 else
2062 {
2063 return codecvt_base::error;
2064 }
2065 }
2066 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2067}
2068
2069static
2070int
2071utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2072 size_t mx, unsigned long Maxcode = 0x10FFFF,
2073 codecvt_mode mode = codecvt_mode(0))
2074{
2075 const uint8_t* frm_nxt = frm;
2076 if (mode & consume_header)
2077 {
2078 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2079 frm_nxt[2] == 0xBF)
2080 frm_nxt += 3;
2081 }
2082 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2083 {
2084 uint8_t c1 = *frm_nxt;
2085 if (c1 > Maxcode)
2086 break;
2087 if (c1 < 0x80)
2088 {
2089 ++frm_nxt;
2090 }
2091 else if (c1 < 0xC2)
2092 {
2093 break;
2094 }
2095 else if (c1 < 0xE0)
2096 {
2097 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2098 break;
2099 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2100 if (t > Maxcode)
2101 break;
2102 frm_nxt += 2;
2103 }
2104 else if (c1 < 0xF0)
2105 {
2106 if (frm_end-frm_nxt < 3)
2107 break;
2108 uint8_t c2 = frm_nxt[1];
2109 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002110 switch (c1)
2111 {
2112 case 0xE0:
2113 if ((c2 & 0xE0) != 0xA0)
2114 return static_cast<int>(frm_nxt - frm);
2115 break;
2116 case 0xED:
2117 if ((c2 & 0xE0) != 0x80)
2118 return static_cast<int>(frm_nxt - frm);
2119 break;
2120 default:
2121 if ((c2 & 0xC0) != 0x80)
2122 return static_cast<int>(frm_nxt - frm);
2123 break;
2124 }
2125 if ((c3 & 0xC0) != 0x80)
2126 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002127 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002128 break;
2129 frm_nxt += 3;
2130 }
2131 else if (c1 < 0xF5)
2132 {
2133 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2134 break;
2135 uint8_t c2 = frm_nxt[1];
2136 uint8_t c3 = frm_nxt[2];
2137 uint8_t c4 = frm_nxt[3];
2138 switch (c1)
2139 {
2140 case 0xF0:
2141 if (!(0x90 <= c2 && c2 <= 0xBF))
2142 return static_cast<int>(frm_nxt - frm);
2143 break;
2144 case 0xF4:
2145 if ((c2 & 0xF0) != 0x80)
2146 return static_cast<int>(frm_nxt - frm);
2147 break;
2148 default:
2149 if ((c2 & 0xC0) != 0x80)
2150 return static_cast<int>(frm_nxt - frm);
2151 break;
2152 }
2153 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2154 break;
2155 if (((((unsigned long)c1 & 7) << 18) +
2156 (((unsigned long)c2 & 0x3F) << 12) +
2157 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2158 break;
2159 ++nchar16_t;
2160 frm_nxt += 4;
2161 }
2162 else
2163 {
2164 break;
2165 }
2166 }
2167 return static_cast<int>(frm_nxt - frm);
2168}
2169
2170static
2171codecvt_base::result
2172ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2173 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2174 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2175{
2176 frm_nxt = frm;
2177 to_nxt = to;
2178 if (mode & generate_header)
2179 {
2180 if (to_end-to_nxt < 3)
2181 return codecvt_base::partial;
2182 *to_nxt++ = static_cast<uint8_t>(0xEF);
2183 *to_nxt++ = static_cast<uint8_t>(0xBB);
2184 *to_nxt++ = static_cast<uint8_t>(0xBF);
2185 }
2186 for (; frm_nxt < frm_end; ++frm_nxt)
2187 {
2188 uint32_t wc = *frm_nxt;
2189 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2190 return codecvt_base::error;
2191 if (wc < 0x000080)
2192 {
2193 if (to_end-to_nxt < 1)
2194 return codecvt_base::partial;
2195 *to_nxt++ = static_cast<uint8_t>(wc);
2196 }
2197 else if (wc < 0x000800)
2198 {
2199 if (to_end-to_nxt < 2)
2200 return codecvt_base::partial;
2201 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2202 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2203 }
2204 else if (wc < 0x010000)
2205 {
2206 if (to_end-to_nxt < 3)
2207 return codecvt_base::partial;
2208 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2209 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2210 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2211 }
2212 else // if (wc < 0x110000)
2213 {
2214 if (to_end-to_nxt < 4)
2215 return codecvt_base::partial;
2216 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2217 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2218 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2219 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2220 }
2221 }
2222 return codecvt_base::ok;
2223}
2224
2225static
2226codecvt_base::result
2227utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2228 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2229 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2230{
2231 frm_nxt = frm;
2232 to_nxt = to;
2233 if (mode & consume_header)
2234 {
2235 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2236 frm_nxt[2] == 0xBF)
2237 frm_nxt += 3;
2238 }
2239 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2240 {
2241 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2242 if (c1 < 0x80)
2243 {
2244 if (c1 > Maxcode)
2245 return codecvt_base::error;
2246 *to_nxt = static_cast<uint32_t>(c1);
2247 ++frm_nxt;
2248 }
2249 else if (c1 < 0xC2)
2250 {
2251 return codecvt_base::error;
2252 }
2253 else if (c1 < 0xE0)
2254 {
2255 if (frm_end-frm_nxt < 2)
2256 return codecvt_base::partial;
2257 uint8_t c2 = frm_nxt[1];
2258 if ((c2 & 0xC0) != 0x80)
2259 return codecvt_base::error;
2260 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2261 | (c2 & 0x3F));
2262 if (t > Maxcode)
2263 return codecvt_base::error;
2264 *to_nxt = t;
2265 frm_nxt += 2;
2266 }
2267 else if (c1 < 0xF0)
2268 {
2269 if (frm_end-frm_nxt < 3)
2270 return codecvt_base::partial;
2271 uint8_t c2 = frm_nxt[1];
2272 uint8_t c3 = frm_nxt[2];
2273 switch (c1)
2274 {
2275 case 0xE0:
2276 if ((c2 & 0xE0) != 0xA0)
2277 return codecvt_base::error;
2278 break;
2279 case 0xED:
2280 if ((c2 & 0xE0) != 0x80)
2281 return codecvt_base::error;
2282 break;
2283 default:
2284 if ((c2 & 0xC0) != 0x80)
2285 return codecvt_base::error;
2286 break;
2287 }
2288 if ((c3 & 0xC0) != 0x80)
2289 return codecvt_base::error;
2290 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2291 | ((c2 & 0x3F) << 6)
2292 | (c3 & 0x3F));
2293 if (t > Maxcode)
2294 return codecvt_base::error;
2295 *to_nxt = t;
2296 frm_nxt += 3;
2297 }
2298 else if (c1 < 0xF5)
2299 {
2300 if (frm_end-frm_nxt < 4)
2301 return codecvt_base::partial;
2302 uint8_t c2 = frm_nxt[1];
2303 uint8_t c3 = frm_nxt[2];
2304 uint8_t c4 = frm_nxt[3];
2305 switch (c1)
2306 {
2307 case 0xF0:
2308 if (!(0x90 <= c2 && c2 <= 0xBF))
2309 return codecvt_base::error;
2310 break;
2311 case 0xF4:
2312 if ((c2 & 0xF0) != 0x80)
2313 return codecvt_base::error;
2314 break;
2315 default:
2316 if ((c2 & 0xC0) != 0x80)
2317 return codecvt_base::error;
2318 break;
2319 }
2320 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2321 return codecvt_base::error;
2322 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2323 | ((c2 & 0x3F) << 12)
2324 | ((c3 & 0x3F) << 6)
2325 | (c4 & 0x3F));
2326 if (t > Maxcode)
2327 return codecvt_base::error;
2328 *to_nxt = t;
2329 frm_nxt += 4;
2330 }
2331 else
2332 {
2333 return codecvt_base::error;
2334 }
2335 }
2336 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2337}
2338
2339static
2340int
2341utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2342 size_t mx, unsigned long Maxcode = 0x10FFFF,
2343 codecvt_mode mode = codecvt_mode(0))
2344{
2345 const uint8_t* frm_nxt = frm;
2346 if (mode & consume_header)
2347 {
2348 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2349 frm_nxt[2] == 0xBF)
2350 frm_nxt += 3;
2351 }
2352 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2353 {
2354 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2355 if (c1 < 0x80)
2356 {
2357 if (c1 > Maxcode)
2358 break;
2359 ++frm_nxt;
2360 }
2361 else if (c1 < 0xC2)
2362 {
2363 break;
2364 }
2365 else if (c1 < 0xE0)
2366 {
2367 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2368 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002369 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002370 break;
2371 frm_nxt += 2;
2372 }
2373 else if (c1 < 0xF0)
2374 {
2375 if (frm_end-frm_nxt < 3)
2376 break;
2377 uint8_t c2 = frm_nxt[1];
2378 uint8_t c3 = frm_nxt[2];
2379 switch (c1)
2380 {
2381 case 0xE0:
2382 if ((c2 & 0xE0) != 0xA0)
2383 return static_cast<int>(frm_nxt - frm);
2384 break;
2385 case 0xED:
2386 if ((c2 & 0xE0) != 0x80)
2387 return static_cast<int>(frm_nxt - frm);
2388 break;
2389 default:
2390 if ((c2 & 0xC0) != 0x80)
2391 return static_cast<int>(frm_nxt - frm);
2392 break;
2393 }
2394 if ((c3 & 0xC0) != 0x80)
2395 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002396 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002397 break;
2398 frm_nxt += 3;
2399 }
2400 else if (c1 < 0xF5)
2401 {
2402 if (frm_end-frm_nxt < 4)
2403 break;
2404 uint8_t c2 = frm_nxt[1];
2405 uint8_t c3 = frm_nxt[2];
2406 uint8_t c4 = frm_nxt[3];
2407 switch (c1)
2408 {
2409 case 0xF0:
2410 if (!(0x90 <= c2 && c2 <= 0xBF))
2411 return static_cast<int>(frm_nxt - frm);
2412 break;
2413 case 0xF4:
2414 if ((c2 & 0xF0) != 0x80)
2415 return static_cast<int>(frm_nxt - frm);
2416 break;
2417 default:
2418 if ((c2 & 0xC0) != 0x80)
2419 return static_cast<int>(frm_nxt - frm);
2420 break;
2421 }
2422 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2423 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002424 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2425 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002426 break;
2427 frm_nxt += 4;
2428 }
2429 else
2430 {
2431 break;
2432 }
2433 }
2434 return static_cast<int>(frm_nxt - frm);
2435}
2436
2437static
2438codecvt_base::result
2439ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2440 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2441 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2442{
2443 frm_nxt = frm;
2444 to_nxt = to;
2445 if (mode & generate_header)
2446 {
2447 if (to_end-to_nxt < 3)
2448 return codecvt_base::partial;
2449 *to_nxt++ = static_cast<uint8_t>(0xEF);
2450 *to_nxt++ = static_cast<uint8_t>(0xBB);
2451 *to_nxt++ = static_cast<uint8_t>(0xBF);
2452 }
2453 for (; frm_nxt < frm_end; ++frm_nxt)
2454 {
2455 uint16_t wc = *frm_nxt;
2456 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2457 return codecvt_base::error;
2458 if (wc < 0x0080)
2459 {
2460 if (to_end-to_nxt < 1)
2461 return codecvt_base::partial;
2462 *to_nxt++ = static_cast<uint8_t>(wc);
2463 }
2464 else if (wc < 0x0800)
2465 {
2466 if (to_end-to_nxt < 2)
2467 return codecvt_base::partial;
2468 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2469 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2470 }
2471 else // if (wc <= 0xFFFF)
2472 {
2473 if (to_end-to_nxt < 3)
2474 return codecvt_base::partial;
2475 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2476 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2477 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2478 }
2479 }
2480 return codecvt_base::ok;
2481}
2482
2483static
2484codecvt_base::result
2485utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2486 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2487 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2488{
2489 frm_nxt = frm;
2490 to_nxt = to;
2491 if (mode & consume_header)
2492 {
2493 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2494 frm_nxt[2] == 0xBF)
2495 frm_nxt += 3;
2496 }
2497 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2498 {
2499 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2500 if (c1 < 0x80)
2501 {
2502 if (c1 > Maxcode)
2503 return codecvt_base::error;
2504 *to_nxt = static_cast<uint16_t>(c1);
2505 ++frm_nxt;
2506 }
2507 else if (c1 < 0xC2)
2508 {
2509 return codecvt_base::error;
2510 }
2511 else if (c1 < 0xE0)
2512 {
2513 if (frm_end-frm_nxt < 2)
2514 return codecvt_base::partial;
2515 uint8_t c2 = frm_nxt[1];
2516 if ((c2 & 0xC0) != 0x80)
2517 return codecvt_base::error;
2518 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2519 | (c2 & 0x3F));
2520 if (t > Maxcode)
2521 return codecvt_base::error;
2522 *to_nxt = t;
2523 frm_nxt += 2;
2524 }
2525 else if (c1 < 0xF0)
2526 {
2527 if (frm_end-frm_nxt < 3)
2528 return codecvt_base::partial;
2529 uint8_t c2 = frm_nxt[1];
2530 uint8_t c3 = frm_nxt[2];
2531 switch (c1)
2532 {
2533 case 0xE0:
2534 if ((c2 & 0xE0) != 0xA0)
2535 return codecvt_base::error;
2536 break;
2537 case 0xED:
2538 if ((c2 & 0xE0) != 0x80)
2539 return codecvt_base::error;
2540 break;
2541 default:
2542 if ((c2 & 0xC0) != 0x80)
2543 return codecvt_base::error;
2544 break;
2545 }
2546 if ((c3 & 0xC0) != 0x80)
2547 return codecvt_base::error;
2548 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2549 | ((c2 & 0x3F) << 6)
2550 | (c3 & 0x3F));
2551 if (t > Maxcode)
2552 return codecvt_base::error;
2553 *to_nxt = t;
2554 frm_nxt += 3;
2555 }
2556 else
2557 {
2558 return codecvt_base::error;
2559 }
2560 }
2561 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2562}
2563
2564static
2565int
2566utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2567 size_t mx, unsigned long Maxcode = 0x10FFFF,
2568 codecvt_mode mode = codecvt_mode(0))
2569{
2570 const uint8_t* frm_nxt = frm;
2571 if (mode & consume_header)
2572 {
2573 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2574 frm_nxt[2] == 0xBF)
2575 frm_nxt += 3;
2576 }
2577 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2578 {
2579 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2580 if (c1 < 0x80)
2581 {
2582 if (c1 > Maxcode)
2583 break;
2584 ++frm_nxt;
2585 }
2586 else if (c1 < 0xC2)
2587 {
2588 break;
2589 }
2590 else if (c1 < 0xE0)
2591 {
2592 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2593 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002594 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002595 break;
2596 frm_nxt += 2;
2597 }
2598 else if (c1 < 0xF0)
2599 {
2600 if (frm_end-frm_nxt < 3)
2601 break;
2602 uint8_t c2 = frm_nxt[1];
2603 uint8_t c3 = frm_nxt[2];
2604 switch (c1)
2605 {
2606 case 0xE0:
2607 if ((c2 & 0xE0) != 0xA0)
2608 return static_cast<int>(frm_nxt - frm);
2609 break;
2610 case 0xED:
2611 if ((c2 & 0xE0) != 0x80)
2612 return static_cast<int>(frm_nxt - frm);
2613 break;
2614 default:
2615 if ((c2 & 0xC0) != 0x80)
2616 return static_cast<int>(frm_nxt - frm);
2617 break;
2618 }
2619 if ((c3 & 0xC0) != 0x80)
2620 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002621 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002622 break;
2623 frm_nxt += 3;
2624 }
2625 else
2626 {
2627 break;
2628 }
2629 }
2630 return static_cast<int>(frm_nxt - frm);
2631}
2632
2633static
2634codecvt_base::result
2635ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2636 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2637 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2638{
2639 frm_nxt = frm;
2640 to_nxt = to;
2641 if (mode & generate_header)
2642 {
2643 if (to_end-to_nxt < 2)
2644 return codecvt_base::partial;
2645 *to_nxt++ = static_cast<uint8_t>(0xFE);
2646 *to_nxt++ = static_cast<uint8_t>(0xFF);
2647 }
2648 for (; frm_nxt < frm_end; ++frm_nxt)
2649 {
2650 uint32_t wc = *frm_nxt;
2651 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2652 return codecvt_base::error;
2653 if (wc < 0x010000)
2654 {
2655 if (to_end-to_nxt < 2)
2656 return codecvt_base::partial;
2657 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2658 *to_nxt++ = static_cast<uint8_t>(wc);
2659 }
2660 else
2661 {
2662 if (to_end-to_nxt < 4)
2663 return codecvt_base::partial;
2664 uint16_t t = static_cast<uint16_t>(
2665 0xD800
2666 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2667 | ((wc & 0x00FC00) >> 10));
2668 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2669 *to_nxt++ = static_cast<uint8_t>(t);
2670 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2671 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2672 *to_nxt++ = static_cast<uint8_t>(t);
2673 }
2674 }
2675 return codecvt_base::ok;
2676}
2677
2678static
2679codecvt_base::result
2680utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2681 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2682 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2683{
2684 frm_nxt = frm;
2685 to_nxt = to;
2686 if (mode & consume_header)
2687 {
2688 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2689 frm_nxt += 2;
2690 }
2691 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2692 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002693 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002694 if ((c1 & 0xFC00) == 0xDC00)
2695 return codecvt_base::error;
2696 if ((c1 & 0xFC00) != 0xD800)
2697 {
2698 if (c1 > Maxcode)
2699 return codecvt_base::error;
2700 *to_nxt = static_cast<uint32_t>(c1);
2701 frm_nxt += 2;
2702 }
2703 else
2704 {
2705 if (frm_end-frm_nxt < 4)
2706 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002707 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002708 if ((c2 & 0xFC00) != 0xDC00)
2709 return codecvt_base::error;
2710 uint32_t t = static_cast<uint32_t>(
2711 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2712 | ((c1 & 0x003F) << 10)
2713 | (c2 & 0x03FF));
2714 if (t > Maxcode)
2715 return codecvt_base::error;
2716 *to_nxt = t;
2717 frm_nxt += 4;
2718 }
2719 }
2720 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2721}
2722
2723static
2724int
2725utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2726 size_t mx, unsigned long Maxcode = 0x10FFFF,
2727 codecvt_mode mode = codecvt_mode(0))
2728{
2729 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002730 if (mode & consume_header)
2731 {
2732 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2733 frm_nxt += 2;
2734 }
2735 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2736 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002737 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002738 if ((c1 & 0xFC00) == 0xDC00)
2739 break;
2740 if ((c1 & 0xFC00) != 0xD800)
2741 {
2742 if (c1 > Maxcode)
2743 break;
2744 frm_nxt += 2;
2745 }
2746 else
2747 {
2748 if (frm_end-frm_nxt < 4)
2749 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002750 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002751 if ((c2 & 0xFC00) != 0xDC00)
2752 break;
2753 uint32_t t = static_cast<uint32_t>(
2754 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2755 | ((c1 & 0x003F) << 10)
2756 | (c2 & 0x03FF));
2757 if (t > Maxcode)
2758 break;
2759 frm_nxt += 4;
2760 }
2761 }
2762 return static_cast<int>(frm_nxt - frm);
2763}
2764
2765static
2766codecvt_base::result
2767ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2768 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2769 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2770{
2771 frm_nxt = frm;
2772 to_nxt = to;
2773 if (mode & generate_header)
2774 {
2775 if (to_end-to_nxt < 2)
2776 return codecvt_base::partial;
2777 *to_nxt++ = static_cast<uint8_t>(0xFF);
2778 *to_nxt++ = static_cast<uint8_t>(0xFE);
2779 }
2780 for (; frm_nxt < frm_end; ++frm_nxt)
2781 {
2782 uint32_t wc = *frm_nxt;
2783 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2784 return codecvt_base::error;
2785 if (wc < 0x010000)
2786 {
2787 if (to_end-to_nxt < 2)
2788 return codecvt_base::partial;
2789 *to_nxt++ = static_cast<uint8_t>(wc);
2790 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2791 }
2792 else
2793 {
2794 if (to_end-to_nxt < 4)
2795 return codecvt_base::partial;
2796 uint16_t t = static_cast<uint16_t>(
2797 0xD800
2798 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2799 | ((wc & 0x00FC00) >> 10));
2800 *to_nxt++ = static_cast<uint8_t>(t);
2801 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2802 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2803 *to_nxt++ = static_cast<uint8_t>(t);
2804 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2805 }
2806 }
2807 return codecvt_base::ok;
2808}
2809
2810static
2811codecvt_base::result
2812utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2813 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2814 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2815{
2816 frm_nxt = frm;
2817 to_nxt = to;
2818 if (mode & consume_header)
2819 {
2820 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2821 frm_nxt += 2;
2822 }
2823 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2824 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002825 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002826 if ((c1 & 0xFC00) == 0xDC00)
2827 return codecvt_base::error;
2828 if ((c1 & 0xFC00) != 0xD800)
2829 {
2830 if (c1 > Maxcode)
2831 return codecvt_base::error;
2832 *to_nxt = static_cast<uint32_t>(c1);
2833 frm_nxt += 2;
2834 }
2835 else
2836 {
2837 if (frm_end-frm_nxt < 4)
2838 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002839 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002840 if ((c2 & 0xFC00) != 0xDC00)
2841 return codecvt_base::error;
2842 uint32_t t = static_cast<uint32_t>(
2843 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2844 | ((c1 & 0x003F) << 10)
2845 | (c2 & 0x03FF));
2846 if (t > Maxcode)
2847 return codecvt_base::error;
2848 *to_nxt = t;
2849 frm_nxt += 4;
2850 }
2851 }
2852 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2853}
2854
2855static
2856int
2857utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2858 size_t mx, unsigned long Maxcode = 0x10FFFF,
2859 codecvt_mode mode = codecvt_mode(0))
2860{
2861 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002862 if (mode & consume_header)
2863 {
2864 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2865 frm_nxt += 2;
2866 }
2867 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2868 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002869 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002870 if ((c1 & 0xFC00) == 0xDC00)
2871 break;
2872 if ((c1 & 0xFC00) != 0xD800)
2873 {
2874 if (c1 > Maxcode)
2875 break;
2876 frm_nxt += 2;
2877 }
2878 else
2879 {
2880 if (frm_end-frm_nxt < 4)
2881 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002882 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002883 if ((c2 & 0xFC00) != 0xDC00)
2884 break;
2885 uint32_t t = static_cast<uint32_t>(
2886 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2887 | ((c1 & 0x003F) << 10)
2888 | (c2 & 0x03FF));
2889 if (t > Maxcode)
2890 break;
2891 frm_nxt += 4;
2892 }
2893 }
2894 return static_cast<int>(frm_nxt - frm);
2895}
2896
2897static
2898codecvt_base::result
2899ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2900 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2901 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2902{
2903 frm_nxt = frm;
2904 to_nxt = to;
2905 if (mode & generate_header)
2906 {
2907 if (to_end-to_nxt < 2)
2908 return codecvt_base::partial;
2909 *to_nxt++ = static_cast<uint8_t>(0xFE);
2910 *to_nxt++ = static_cast<uint8_t>(0xFF);
2911 }
2912 for (; frm_nxt < frm_end; ++frm_nxt)
2913 {
2914 uint16_t wc = *frm_nxt;
2915 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2916 return codecvt_base::error;
2917 if (to_end-to_nxt < 2)
2918 return codecvt_base::partial;
2919 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2920 *to_nxt++ = static_cast<uint8_t>(wc);
2921 }
2922 return codecvt_base::ok;
2923}
2924
2925static
2926codecvt_base::result
2927utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2928 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2929 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2930{
2931 frm_nxt = frm;
2932 to_nxt = to;
2933 if (mode & consume_header)
2934 {
2935 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2936 frm_nxt += 2;
2937 }
2938 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2939 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002940 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002941 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2942 return codecvt_base::error;
2943 *to_nxt = c1;
2944 frm_nxt += 2;
2945 }
2946 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2947}
2948
2949static
2950int
2951utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2952 size_t mx, unsigned long Maxcode = 0x10FFFF,
2953 codecvt_mode mode = codecvt_mode(0))
2954{
2955 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002956 if (mode & consume_header)
2957 {
2958 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2959 frm_nxt += 2;
2960 }
2961 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2962 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002963 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002964 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2965 break;
2966 frm_nxt += 2;
2967 }
2968 return static_cast<int>(frm_nxt - frm);
2969}
2970
2971static
2972codecvt_base::result
2973ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2974 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2975 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2976{
2977 frm_nxt = frm;
2978 to_nxt = to;
2979 if (mode & generate_header)
2980 {
2981 if (to_end-to_nxt < 2)
2982 return codecvt_base::partial;
2983 *to_nxt++ = static_cast<uint8_t>(0xFF);
2984 *to_nxt++ = static_cast<uint8_t>(0xFE);
2985 }
2986 for (; frm_nxt < frm_end; ++frm_nxt)
2987 {
2988 uint16_t wc = *frm_nxt;
2989 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2990 return codecvt_base::error;
2991 if (to_end-to_nxt < 2)
2992 return codecvt_base::partial;
2993 *to_nxt++ = static_cast<uint8_t>(wc);
2994 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2995 }
2996 return codecvt_base::ok;
2997}
2998
2999static
3000codecvt_base::result
3001utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3002 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3003 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3004{
3005 frm_nxt = frm;
3006 to_nxt = to;
3007 if (mode & consume_header)
3008 {
3009 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3010 frm_nxt += 2;
3011 }
3012 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3013 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003014 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003015 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3016 return codecvt_base::error;
3017 *to_nxt = c1;
3018 frm_nxt += 2;
3019 }
3020 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3021}
3022
3023static
3024int
3025utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3026 size_t mx, unsigned long Maxcode = 0x10FFFF,
3027 codecvt_mode mode = codecvt_mode(0))
3028{
3029 const uint8_t* frm_nxt = frm;
3030 frm_nxt = frm;
3031 if (mode & consume_header)
3032 {
3033 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3034 frm_nxt += 2;
3035 }
3036 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3037 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003038 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003039 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3040 break;
3041 frm_nxt += 2;
3042 }
3043 return static_cast<int>(frm_nxt - frm);
3044}
3045
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003046// template <> class codecvt<char16_t, char, mbstate_t>
3047
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003048locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003049
3050codecvt<char16_t, char, mbstate_t>::~codecvt()
3051{
3052}
3053
3054codecvt<char16_t, char, mbstate_t>::result
3055codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003056 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003057 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3058{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003059 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3060 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3061 const uint16_t* _frm_nxt = _frm;
3062 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3063 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3064 uint8_t* _to_nxt = _to;
3065 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3066 frm_nxt = frm + (_frm_nxt - _frm);
3067 to_nxt = to + (_to_nxt - _to);
3068 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003069}
3070
3071codecvt<char16_t, char, mbstate_t>::result
3072codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003073 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003074 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3075{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003076 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3077 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3078 const uint8_t* _frm_nxt = _frm;
3079 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3080 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3081 uint16_t* _to_nxt = _to;
3082 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3083 frm_nxt = frm + (_frm_nxt - _frm);
3084 to_nxt = to + (_to_nxt - _to);
3085 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003086}
3087
3088codecvt<char16_t, char, mbstate_t>::result
3089codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3090 extern_type* to, extern_type*, extern_type*& to_nxt) const
3091{
3092 to_nxt = to;
3093 return noconv;
3094}
3095
3096int
Howard Hinnantc9834542011-05-31 15:34:58 +00003097codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003098{
3099 return 0;
3100}
3101
3102bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003103codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003104{
3105 return false;
3106}
3107
3108int
3109codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3110 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3111{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003112 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3113 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3114 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003115}
3116
3117int
Howard Hinnantc9834542011-05-31 15:34:58 +00003118codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003119{
3120 return 4;
3121}
3122
3123// template <> class codecvt<char32_t, char, mbstate_t>
3124
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003125locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003126
3127codecvt<char32_t, char, mbstate_t>::~codecvt()
3128{
3129}
3130
3131codecvt<char32_t, char, mbstate_t>::result
3132codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003133 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003134 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3135{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003136 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3137 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3138 const uint32_t* _frm_nxt = _frm;
3139 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3140 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3141 uint8_t* _to_nxt = _to;
3142 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3143 frm_nxt = frm + (_frm_nxt - _frm);
3144 to_nxt = to + (_to_nxt - _to);
3145 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003146}
3147
3148codecvt<char32_t, char, mbstate_t>::result
3149codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003150 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003151 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3152{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003153 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3154 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3155 const uint8_t* _frm_nxt = _frm;
3156 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3157 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3158 uint32_t* _to_nxt = _to;
3159 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3160 frm_nxt = frm + (_frm_nxt - _frm);
3161 to_nxt = to + (_to_nxt - _to);
3162 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003163}
3164
3165codecvt<char32_t, char, mbstate_t>::result
3166codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3167 extern_type* to, extern_type*, extern_type*& to_nxt) const
3168{
3169 to_nxt = to;
3170 return noconv;
3171}
3172
3173int
Howard Hinnantc9834542011-05-31 15:34:58 +00003174codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003175{
3176 return 0;
3177}
3178
3179bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003180codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003181{
3182 return false;
3183}
3184
3185int
3186codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3187 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3188{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003189 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3190 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3191 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003192}
3193
3194int
Howard Hinnantc9834542011-05-31 15:34:58 +00003195codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003196{
3197 return 4;
3198}
3199
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003200// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003201
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003202__codecvt_utf8<wchar_t>::result
3203__codecvt_utf8<wchar_t>::do_out(state_type&,
3204 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003205 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3206{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003207#if _WIN32
3208 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3209 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3210 const uint16_t* _frm_nxt = _frm;
3211#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003212 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3213 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3214 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003215#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003216 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3217 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3218 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003219#if _WIN32
3220 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3221 _Maxcode_, _Mode_);
3222#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003223 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3224 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003225#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003226 frm_nxt = frm + (_frm_nxt - _frm);
3227 to_nxt = to + (_to_nxt - _to);
3228 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003229}
3230
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003231__codecvt_utf8<wchar_t>::result
3232__codecvt_utf8<wchar_t>::do_in(state_type&,
3233 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003234 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3235{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003236 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3237 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3238 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003239#if _WIN32
3240 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3241 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3242 uint16_t* _to_nxt = _to;
3243 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3244 _Maxcode_, _Mode_);
3245#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003246 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3247 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3248 uint32_t* _to_nxt = _to;
3249 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3250 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003251#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003252 frm_nxt = frm + (_frm_nxt - _frm);
3253 to_nxt = to + (_to_nxt - _to);
3254 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003255}
3256
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003257__codecvt_utf8<wchar_t>::result
3258__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003259 extern_type* to, extern_type*, extern_type*& to_nxt) const
3260{
3261 to_nxt = to;
3262 return noconv;
3263}
3264
3265int
Howard Hinnantc9834542011-05-31 15:34:58 +00003266__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003267{
3268 return 0;
3269}
3270
3271bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003272__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003273{
3274 return false;
3275}
3276
3277int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003278__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003279 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3280{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003281 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3282 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3283 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003284}
3285
3286int
Howard Hinnantc9834542011-05-31 15:34:58 +00003287__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003288{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003289 if (_Mode_ & consume_header)
3290 return 7;
3291 return 4;
3292}
3293
3294// __codecvt_utf8<char16_t>
3295
3296__codecvt_utf8<char16_t>::result
3297__codecvt_utf8<char16_t>::do_out(state_type&,
3298 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3299 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3300{
3301 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3302 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3303 const uint16_t* _frm_nxt = _frm;
3304 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3305 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3306 uint8_t* _to_nxt = _to;
3307 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3308 _Maxcode_, _Mode_);
3309 frm_nxt = frm + (_frm_nxt - _frm);
3310 to_nxt = to + (_to_nxt - _to);
3311 return r;
3312}
3313
3314__codecvt_utf8<char16_t>::result
3315__codecvt_utf8<char16_t>::do_in(state_type&,
3316 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3317 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3318{
3319 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3320 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3321 const uint8_t* _frm_nxt = _frm;
3322 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3323 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3324 uint16_t* _to_nxt = _to;
3325 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3326 _Maxcode_, _Mode_);
3327 frm_nxt = frm + (_frm_nxt - _frm);
3328 to_nxt = to + (_to_nxt - _to);
3329 return r;
3330}
3331
3332__codecvt_utf8<char16_t>::result
3333__codecvt_utf8<char16_t>::do_unshift(state_type&,
3334 extern_type* to, extern_type*, extern_type*& to_nxt) const
3335{
3336 to_nxt = to;
3337 return noconv;
3338}
3339
3340int
Howard Hinnantc9834542011-05-31 15:34:58 +00003341__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003342{
3343 return 0;
3344}
3345
3346bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003347__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003348{
3349 return false;
3350}
3351
3352int
3353__codecvt_utf8<char16_t>::do_length(state_type&,
3354 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3355{
3356 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3357 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3358 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3359}
3360
3361int
Howard Hinnantc9834542011-05-31 15:34:58 +00003362__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003363{
3364 if (_Mode_ & consume_header)
3365 return 6;
3366 return 3;
3367}
3368
3369// __codecvt_utf8<char32_t>
3370
3371__codecvt_utf8<char32_t>::result
3372__codecvt_utf8<char32_t>::do_out(state_type&,
3373 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3374 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3375{
3376 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3377 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3378 const uint32_t* _frm_nxt = _frm;
3379 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3380 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3381 uint8_t* _to_nxt = _to;
3382 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3383 _Maxcode_, _Mode_);
3384 frm_nxt = frm + (_frm_nxt - _frm);
3385 to_nxt = to + (_to_nxt - _to);
3386 return r;
3387}
3388
3389__codecvt_utf8<char32_t>::result
3390__codecvt_utf8<char32_t>::do_in(state_type&,
3391 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3392 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3393{
3394 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3395 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3396 const uint8_t* _frm_nxt = _frm;
3397 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3398 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3399 uint32_t* _to_nxt = _to;
3400 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3401 _Maxcode_, _Mode_);
3402 frm_nxt = frm + (_frm_nxt - _frm);
3403 to_nxt = to + (_to_nxt - _to);
3404 return r;
3405}
3406
3407__codecvt_utf8<char32_t>::result
3408__codecvt_utf8<char32_t>::do_unshift(state_type&,
3409 extern_type* to, extern_type*, extern_type*& to_nxt) const
3410{
3411 to_nxt = to;
3412 return noconv;
3413}
3414
3415int
Howard Hinnantc9834542011-05-31 15:34:58 +00003416__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003417{
3418 return 0;
3419}
3420
3421bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003422__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003423{
3424 return false;
3425}
3426
3427int
3428__codecvt_utf8<char32_t>::do_length(state_type&,
3429 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3430{
3431 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3432 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3433 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3434}
3435
3436int
Howard Hinnantc9834542011-05-31 15:34:58 +00003437__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003438{
3439 if (_Mode_ & consume_header)
3440 return 7;
3441 return 4;
3442}
3443
3444// __codecvt_utf16<wchar_t, false>
3445
3446__codecvt_utf16<wchar_t, false>::result
3447__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3448 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3449 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3450{
3451 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3452 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3453 const uint32_t* _frm_nxt = _frm;
3454 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3455 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3456 uint8_t* _to_nxt = _to;
3457 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3458 _Maxcode_, _Mode_);
3459 frm_nxt = frm + (_frm_nxt - _frm);
3460 to_nxt = to + (_to_nxt - _to);
3461 return r;
3462}
3463
3464__codecvt_utf16<wchar_t, false>::result
3465__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3466 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3467 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3468{
3469 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3470 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3471 const uint8_t* _frm_nxt = _frm;
3472 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3473 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3474 uint32_t* _to_nxt = _to;
3475 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3476 _Maxcode_, _Mode_);
3477 frm_nxt = frm + (_frm_nxt - _frm);
3478 to_nxt = to + (_to_nxt - _to);
3479 return r;
3480}
3481
3482__codecvt_utf16<wchar_t, false>::result
3483__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3484 extern_type* to, extern_type*, extern_type*& to_nxt) const
3485{
3486 to_nxt = to;
3487 return noconv;
3488}
3489
3490int
Howard Hinnantc9834542011-05-31 15:34:58 +00003491__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003492{
3493 return 0;
3494}
3495
3496bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003497__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003498{
3499 return false;
3500}
3501
3502int
3503__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3504 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3505{
3506 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3507 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3508 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3509}
3510
3511int
Howard Hinnantc9834542011-05-31 15:34:58 +00003512__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003513{
3514 if (_Mode_ & consume_header)
3515 return 6;
3516 return 4;
3517}
3518
3519// __codecvt_utf16<wchar_t, true>
3520
3521__codecvt_utf16<wchar_t, true>::result
3522__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3523 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3524 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3525{
3526 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3527 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3528 const uint32_t* _frm_nxt = _frm;
3529 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3530 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3531 uint8_t* _to_nxt = _to;
3532 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3533 _Maxcode_, _Mode_);
3534 frm_nxt = frm + (_frm_nxt - _frm);
3535 to_nxt = to + (_to_nxt - _to);
3536 return r;
3537}
3538
3539__codecvt_utf16<wchar_t, true>::result
3540__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3541 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3542 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3543{
3544 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3545 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3546 const uint8_t* _frm_nxt = _frm;
3547 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3548 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3549 uint32_t* _to_nxt = _to;
3550 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3551 _Maxcode_, _Mode_);
3552 frm_nxt = frm + (_frm_nxt - _frm);
3553 to_nxt = to + (_to_nxt - _to);
3554 return r;
3555}
3556
3557__codecvt_utf16<wchar_t, true>::result
3558__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3559 extern_type* to, extern_type*, extern_type*& to_nxt) const
3560{
3561 to_nxt = to;
3562 return noconv;
3563}
3564
3565int
Howard Hinnantc9834542011-05-31 15:34:58 +00003566__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003567{
3568 return 0;
3569}
3570
3571bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003572__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003573{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003574 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003575}
3576
3577int
3578__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3579 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3580{
3581 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3582 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3583 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3584}
3585
3586int
Howard Hinnantc9834542011-05-31 15:34:58 +00003587__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003588{
3589 if (_Mode_ & consume_header)
3590 return 6;
3591 return 4;
3592}
3593
3594// __codecvt_utf16<char16_t, false>
3595
3596__codecvt_utf16<char16_t, false>::result
3597__codecvt_utf16<char16_t, false>::do_out(state_type&,
3598 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3599 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3600{
3601 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3602 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3603 const uint16_t* _frm_nxt = _frm;
3604 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3605 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3606 uint8_t* _to_nxt = _to;
3607 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3608 _Maxcode_, _Mode_);
3609 frm_nxt = frm + (_frm_nxt - _frm);
3610 to_nxt = to + (_to_nxt - _to);
3611 return r;
3612}
3613
3614__codecvt_utf16<char16_t, false>::result
3615__codecvt_utf16<char16_t, false>::do_in(state_type&,
3616 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3617 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3618{
3619 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3620 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3621 const uint8_t* _frm_nxt = _frm;
3622 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3623 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3624 uint16_t* _to_nxt = _to;
3625 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3626 _Maxcode_, _Mode_);
3627 frm_nxt = frm + (_frm_nxt - _frm);
3628 to_nxt = to + (_to_nxt - _to);
3629 return r;
3630}
3631
3632__codecvt_utf16<char16_t, false>::result
3633__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3634 extern_type* to, extern_type*, extern_type*& to_nxt) const
3635{
3636 to_nxt = to;
3637 return noconv;
3638}
3639
3640int
Howard Hinnantc9834542011-05-31 15:34:58 +00003641__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003642{
3643 return 0;
3644}
3645
3646bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003647__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003648{
3649 return false;
3650}
3651
3652int
3653__codecvt_utf16<char16_t, false>::do_length(state_type&,
3654 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3655{
3656 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3657 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3658 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3659}
3660
3661int
Howard Hinnantc9834542011-05-31 15:34:58 +00003662__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003663{
3664 if (_Mode_ & consume_header)
3665 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003666 return 2;
3667}
3668
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003669// __codecvt_utf16<char16_t, true>
3670
3671__codecvt_utf16<char16_t, true>::result
3672__codecvt_utf16<char16_t, true>::do_out(state_type&,
3673 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3674 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3675{
3676 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3677 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3678 const uint16_t* _frm_nxt = _frm;
3679 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3680 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3681 uint8_t* _to_nxt = _to;
3682 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3683 _Maxcode_, _Mode_);
3684 frm_nxt = frm + (_frm_nxt - _frm);
3685 to_nxt = to + (_to_nxt - _to);
3686 return r;
3687}
3688
3689__codecvt_utf16<char16_t, true>::result
3690__codecvt_utf16<char16_t, true>::do_in(state_type&,
3691 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3692 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3693{
3694 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3695 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3696 const uint8_t* _frm_nxt = _frm;
3697 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3698 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3699 uint16_t* _to_nxt = _to;
3700 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3701 _Maxcode_, _Mode_);
3702 frm_nxt = frm + (_frm_nxt - _frm);
3703 to_nxt = to + (_to_nxt - _to);
3704 return r;
3705}
3706
3707__codecvt_utf16<char16_t, true>::result
3708__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3709 extern_type* to, extern_type*, extern_type*& to_nxt) const
3710{
3711 to_nxt = to;
3712 return noconv;
3713}
3714
3715int
Howard Hinnantc9834542011-05-31 15:34:58 +00003716__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003717{
3718 return 0;
3719}
3720
3721bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003722__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003723{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003724 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003725}
3726
3727int
3728__codecvt_utf16<char16_t, true>::do_length(state_type&,
3729 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3730{
3731 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3732 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3733 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3734}
3735
3736int
Howard Hinnantc9834542011-05-31 15:34:58 +00003737__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003738{
3739 if (_Mode_ & consume_header)
3740 return 4;
3741 return 2;
3742}
3743
3744// __codecvt_utf16<char32_t, false>
3745
3746__codecvt_utf16<char32_t, false>::result
3747__codecvt_utf16<char32_t, false>::do_out(state_type&,
3748 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3749 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3750{
3751 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3752 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3753 const uint32_t* _frm_nxt = _frm;
3754 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3755 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3756 uint8_t* _to_nxt = _to;
3757 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3758 _Maxcode_, _Mode_);
3759 frm_nxt = frm + (_frm_nxt - _frm);
3760 to_nxt = to + (_to_nxt - _to);
3761 return r;
3762}
3763
3764__codecvt_utf16<char32_t, false>::result
3765__codecvt_utf16<char32_t, false>::do_in(state_type&,
3766 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3767 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3768{
3769 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3770 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3771 const uint8_t* _frm_nxt = _frm;
3772 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3773 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3774 uint32_t* _to_nxt = _to;
3775 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3776 _Maxcode_, _Mode_);
3777 frm_nxt = frm + (_frm_nxt - _frm);
3778 to_nxt = to + (_to_nxt - _to);
3779 return r;
3780}
3781
3782__codecvt_utf16<char32_t, false>::result
3783__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3784 extern_type* to, extern_type*, extern_type*& to_nxt) const
3785{
3786 to_nxt = to;
3787 return noconv;
3788}
3789
3790int
Howard Hinnantc9834542011-05-31 15:34:58 +00003791__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003792{
3793 return 0;
3794}
3795
3796bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003797__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003798{
3799 return false;
3800}
3801
3802int
3803__codecvt_utf16<char32_t, false>::do_length(state_type&,
3804 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3805{
3806 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3807 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3808 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3809}
3810
3811int
Howard Hinnantc9834542011-05-31 15:34:58 +00003812__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003813{
3814 if (_Mode_ & consume_header)
3815 return 6;
3816 return 4;
3817}
3818
3819// __codecvt_utf16<char32_t, true>
3820
3821__codecvt_utf16<char32_t, true>::result
3822__codecvt_utf16<char32_t, true>::do_out(state_type&,
3823 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3824 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3825{
3826 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3827 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3828 const uint32_t* _frm_nxt = _frm;
3829 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3830 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3831 uint8_t* _to_nxt = _to;
3832 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3833 _Maxcode_, _Mode_);
3834 frm_nxt = frm + (_frm_nxt - _frm);
3835 to_nxt = to + (_to_nxt - _to);
3836 return r;
3837}
3838
3839__codecvt_utf16<char32_t, true>::result
3840__codecvt_utf16<char32_t, true>::do_in(state_type&,
3841 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3842 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3843{
3844 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3845 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3846 const uint8_t* _frm_nxt = _frm;
3847 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3848 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3849 uint32_t* _to_nxt = _to;
3850 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3851 _Maxcode_, _Mode_);
3852 frm_nxt = frm + (_frm_nxt - _frm);
3853 to_nxt = to + (_to_nxt - _to);
3854 return r;
3855}
3856
3857__codecvt_utf16<char32_t, true>::result
3858__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3859 extern_type* to, extern_type*, extern_type*& to_nxt) const
3860{
3861 to_nxt = to;
3862 return noconv;
3863}
3864
3865int
Howard Hinnantc9834542011-05-31 15:34:58 +00003866__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003867{
3868 return 0;
3869}
3870
3871bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003872__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003873{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003874 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003875}
3876
3877int
3878__codecvt_utf16<char32_t, true>::do_length(state_type&,
3879 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3880{
3881 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3882 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3883 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3884}
3885
3886int
Howard Hinnantc9834542011-05-31 15:34:58 +00003887__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003888{
3889 if (_Mode_ & consume_header)
3890 return 6;
3891 return 4;
3892}
3893
3894// __codecvt_utf8_utf16<wchar_t>
3895
3896__codecvt_utf8_utf16<wchar_t>::result
3897__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3898 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3899 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3900{
3901 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3902 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3903 const uint32_t* _frm_nxt = _frm;
3904 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3905 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3906 uint8_t* _to_nxt = _to;
3907 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3908 _Maxcode_, _Mode_);
3909 frm_nxt = frm + (_frm_nxt - _frm);
3910 to_nxt = to + (_to_nxt - _to);
3911 return r;
3912}
3913
3914__codecvt_utf8_utf16<wchar_t>::result
3915__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3916 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3917 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3918{
3919 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3920 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3921 const uint8_t* _frm_nxt = _frm;
3922 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3923 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3924 uint32_t* _to_nxt = _to;
3925 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3926 _Maxcode_, _Mode_);
3927 frm_nxt = frm + (_frm_nxt - _frm);
3928 to_nxt = to + (_to_nxt - _to);
3929 return r;
3930}
3931
3932__codecvt_utf8_utf16<wchar_t>::result
3933__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3934 extern_type* to, extern_type*, extern_type*& to_nxt) const
3935{
3936 to_nxt = to;
3937 return noconv;
3938}
3939
3940int
Howard Hinnantc9834542011-05-31 15:34:58 +00003941__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003942{
3943 return 0;
3944}
3945
3946bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003947__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003948{
3949 return false;
3950}
3951
3952int
3953__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3954 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3955{
3956 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3957 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3958 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3959}
3960
3961int
Howard Hinnantc9834542011-05-31 15:34:58 +00003962__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003963{
3964 if (_Mode_ & consume_header)
3965 return 7;
3966 return 4;
3967}
3968
3969// __codecvt_utf8_utf16<char16_t>
3970
3971__codecvt_utf8_utf16<char16_t>::result
3972__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3973 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3974 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3975{
3976 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3977 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3978 const uint16_t* _frm_nxt = _frm;
3979 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3980 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3981 uint8_t* _to_nxt = _to;
3982 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3983 _Maxcode_, _Mode_);
3984 frm_nxt = frm + (_frm_nxt - _frm);
3985 to_nxt = to + (_to_nxt - _to);
3986 return r;
3987}
3988
3989__codecvt_utf8_utf16<char16_t>::result
3990__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3991 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3992 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3993{
3994 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3995 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3996 const uint8_t* _frm_nxt = _frm;
3997 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3998 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3999 uint16_t* _to_nxt = _to;
4000 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4001 _Maxcode_, _Mode_);
4002 frm_nxt = frm + (_frm_nxt - _frm);
4003 to_nxt = to + (_to_nxt - _to);
4004 return r;
4005}
4006
4007__codecvt_utf8_utf16<char16_t>::result
4008__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4009 extern_type* to, extern_type*, extern_type*& to_nxt) const
4010{
4011 to_nxt = to;
4012 return noconv;
4013}
4014
4015int
Howard Hinnantc9834542011-05-31 15:34:58 +00004016__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004017{
4018 return 0;
4019}
4020
4021bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004022__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004023{
4024 return false;
4025}
4026
4027int
4028__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4029 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4030{
4031 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4032 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4033 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4034}
4035
4036int
Howard Hinnantc9834542011-05-31 15:34:58 +00004037__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004038{
4039 if (_Mode_ & consume_header)
4040 return 7;
4041 return 4;
4042}
4043
4044// __codecvt_utf8_utf16<char32_t>
4045
4046__codecvt_utf8_utf16<char32_t>::result
4047__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4048 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4049 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4050{
4051 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4052 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4053 const uint32_t* _frm_nxt = _frm;
4054 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4055 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4056 uint8_t* _to_nxt = _to;
4057 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4058 _Maxcode_, _Mode_);
4059 frm_nxt = frm + (_frm_nxt - _frm);
4060 to_nxt = to + (_to_nxt - _to);
4061 return r;
4062}
4063
4064__codecvt_utf8_utf16<char32_t>::result
4065__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4066 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4067 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4068{
4069 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4070 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4071 const uint8_t* _frm_nxt = _frm;
4072 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4073 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4074 uint32_t* _to_nxt = _to;
4075 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4076 _Maxcode_, _Mode_);
4077 frm_nxt = frm + (_frm_nxt - _frm);
4078 to_nxt = to + (_to_nxt - _to);
4079 return r;
4080}
4081
4082__codecvt_utf8_utf16<char32_t>::result
4083__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4084 extern_type* to, extern_type*, extern_type*& to_nxt) const
4085{
4086 to_nxt = to;
4087 return noconv;
4088}
4089
4090int
Howard Hinnantc9834542011-05-31 15:34:58 +00004091__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004092{
4093 return 0;
4094}
4095
4096bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004097__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004098{
4099 return false;
4100}
4101
4102int
4103__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4104 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4105{
4106 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4107 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4108 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4109}
4110
4111int
Howard Hinnantc9834542011-05-31 15:34:58 +00004112__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004113{
4114 if (_Mode_ & consume_header)
4115 return 7;
4116 return 4;
4117}
4118
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004119// __narrow_to_utf8<16>
4120
4121__narrow_to_utf8<16>::~__narrow_to_utf8()
4122{
4123}
4124
4125// __narrow_to_utf8<32>
4126
4127__narrow_to_utf8<32>::~__narrow_to_utf8()
4128{
4129}
4130
4131// __widen_from_utf8<16>
4132
4133__widen_from_utf8<16>::~__widen_from_utf8()
4134{
4135}
4136
4137// __widen_from_utf8<32>
4138
4139__widen_from_utf8<32>::~__widen_from_utf8()
4140{
4141}
4142
4143// numpunct<char> && numpunct<wchar_t>
4144
4145locale::id numpunct< char >::id;
4146locale::id numpunct<wchar_t>::id;
4147
4148numpunct<char>::numpunct(size_t refs)
4149 : locale::facet(refs),
4150 __decimal_point_('.'),
4151 __thousands_sep_(',')
4152{
4153}
4154
4155numpunct<wchar_t>::numpunct(size_t refs)
4156 : locale::facet(refs),
4157 __decimal_point_(L'.'),
4158 __thousands_sep_(L',')
4159{
4160}
4161
4162numpunct<char>::~numpunct()
4163{
4164}
4165
4166numpunct<wchar_t>::~numpunct()
4167{
4168}
4169
4170 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4171wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4172
4173 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4174wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4175
4176string numpunct< char >::do_grouping() const {return __grouping_;}
4177string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4178
4179 string numpunct< char >::do_truename() const {return "true";}
4180wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4181
4182 string numpunct< char >::do_falsename() const {return "false";}
4183wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4184
4185// numpunct_byname<char>
4186
4187numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4188 : numpunct<char>(refs)
4189{
4190 __init(nm);
4191}
4192
4193numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4194 : numpunct<char>(refs)
4195{
4196 __init(nm.c_str());
4197}
4198
4199numpunct_byname<char>::~numpunct_byname()
4200{
4201}
4202
4203void
4204numpunct_byname<char>::__init(const char* nm)
4205{
4206 if (strcmp(nm, "C") != 0)
4207 {
Sean Huntf3907e62011-07-15 05:40:33 +00004208 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004209#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004210 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004211 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4212 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004213#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004214#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004215 lconv* lc = localeconv_l(loc.get());
4216#else
4217 lconv* lc = __localeconv_l(loc.get());
4218#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004219 if (*lc->decimal_point)
4220 __decimal_point_ = *lc->decimal_point;
4221 if (*lc->thousands_sep)
4222 __thousands_sep_ = *lc->thousands_sep;
4223 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004224 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004225 }
4226}
4227
4228// numpunct_byname<wchar_t>
4229
4230numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4231 : numpunct<wchar_t>(refs)
4232{
4233 __init(nm);
4234}
4235
4236numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4237 : numpunct<wchar_t>(refs)
4238{
4239 __init(nm.c_str());
4240}
4241
4242numpunct_byname<wchar_t>::~numpunct_byname()
4243{
4244}
4245
4246void
4247numpunct_byname<wchar_t>::__init(const char* nm)
4248{
4249 if (strcmp(nm, "C") != 0)
4250 {
Sean Huntf3907e62011-07-15 05:40:33 +00004251 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004252#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004253 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004254 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4255 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004256#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004257#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004258 lconv* lc = localeconv_l(loc.get());
4259#else
4260 lconv* lc = __localeconv_l(loc.get());
4261#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004262 if (*lc->decimal_point)
4263 __decimal_point_ = *lc->decimal_point;
4264 if (*lc->thousands_sep)
4265 __thousands_sep_ = *lc->thousands_sep;
4266 __grouping_ = lc->grouping;
4267 // locallization for truename and falsename is not available
4268 }
4269}
4270
4271// num_get helpers
4272
4273int
4274__num_get_base::__get_base(ios_base& iob)
4275{
4276 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4277 if (__basefield == ios_base::oct)
4278 return 8;
4279 else if (__basefield == ios_base::hex)
4280 return 16;
4281 else if (__basefield == 0)
4282 return 0;
4283 return 10;
4284}
4285
4286const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4287
4288void
4289__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4290 ios_base::iostate& __err)
4291{
4292 if (__grouping.size() != 0)
4293 {
4294 reverse(__g, __g_end);
4295 const char* __ig = __grouping.data();
4296 const char* __eg = __ig + __grouping.size();
4297 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4298 {
4299 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4300 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004301 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004302 {
4303 __err = ios_base::failbit;
4304 return;
4305 }
4306 }
4307 if (__eg - __ig > 1)
4308 ++__ig;
4309 }
4310 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4311 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004312 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004313 __err = ios_base::failbit;
4314 }
4315 }
4316}
4317
4318void
4319__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4320 ios_base::fmtflags __flags)
4321{
4322 if (__flags & ios_base::showpos)
4323 *__fmtp++ = '+';
4324 if (__flags & ios_base::showbase)
4325 *__fmtp++ = '#';
4326 while(*__len)
4327 *__fmtp++ = *__len++;
4328 if ((__flags & ios_base::basefield) == ios_base::oct)
4329 *__fmtp = 'o';
4330 else if ((__flags & ios_base::basefield) == ios_base::hex)
4331 {
4332 if (__flags & ios_base::uppercase)
4333 *__fmtp = 'X';
4334 else
4335 *__fmtp = 'x';
4336 }
4337 else if (__signd)
4338 *__fmtp = 'd';
4339 else
4340 *__fmtp = 'u';
4341}
4342
4343bool
4344__num_put_base::__format_float(char* __fmtp, const char* __len,
4345 ios_base::fmtflags __flags)
4346{
4347 bool specify_precision = true;
4348 if (__flags & ios_base::showpos)
4349 *__fmtp++ = '+';
4350 if (__flags & ios_base::showpoint)
4351 *__fmtp++ = '#';
4352 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4353 bool uppercase = __flags & ios_base::uppercase;
4354 if (floatfield == (ios_base::fixed | ios_base::scientific))
4355 specify_precision = false;
4356 else
4357 {
4358 *__fmtp++ = '.';
4359 *__fmtp++ = '*';
4360 }
4361 while(*__len)
4362 *__fmtp++ = *__len++;
4363 if (floatfield == ios_base::fixed)
4364 {
4365 if (uppercase)
4366 *__fmtp = 'F';
4367 else
4368 *__fmtp = 'f';
4369 }
4370 else if (floatfield == ios_base::scientific)
4371 {
4372 if (uppercase)
4373 *__fmtp = 'E';
4374 else
4375 *__fmtp = 'e';
4376 }
4377 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4378 {
4379 if (uppercase)
4380 *__fmtp = 'A';
4381 else
4382 *__fmtp = 'a';
4383 }
4384 else
4385 {
4386 if (uppercase)
4387 *__fmtp = 'G';
4388 else
4389 *__fmtp = 'g';
4390 }
4391 return specify_precision;
4392}
4393
4394char*
4395__num_put_base::__identify_padding(char* __nb, char* __ne,
4396 const ios_base& __iob)
4397{
4398 switch (__iob.flags() & ios_base::adjustfield)
4399 {
4400 case ios_base::internal:
4401 if (__nb[0] == '-' || __nb[0] == '+')
4402 return __nb+1;
4403 if (__ne - __nb >= 2 && __nb[0] == '0'
4404 && (__nb[1] == 'x' || __nb[1] == 'X'))
4405 return __nb+2;
4406 break;
4407 case ios_base::left:
4408 return __ne;
4409 case ios_base::right:
4410 default:
4411 break;
4412 }
4413 return __nb;
4414}
4415
4416// time_get
4417
4418static
4419string*
4420init_weeks()
4421{
4422 static string weeks[14];
4423 weeks[0] = "Sunday";
4424 weeks[1] = "Monday";
4425 weeks[2] = "Tuesday";
4426 weeks[3] = "Wednesday";
4427 weeks[4] = "Thursday";
4428 weeks[5] = "Friday";
4429 weeks[6] = "Saturday";
4430 weeks[7] = "Sun";
4431 weeks[8] = "Mon";
4432 weeks[9] = "Tue";
4433 weeks[10] = "Wed";
4434 weeks[11] = "Thu";
4435 weeks[12] = "Fri";
4436 weeks[13] = "Sat";
4437 return weeks;
4438}
4439
4440static
4441wstring*
4442init_wweeks()
4443{
4444 static wstring weeks[14];
4445 weeks[0] = L"Sunday";
4446 weeks[1] = L"Monday";
4447 weeks[2] = L"Tuesday";
4448 weeks[3] = L"Wednesday";
4449 weeks[4] = L"Thursday";
4450 weeks[5] = L"Friday";
4451 weeks[6] = L"Saturday";
4452 weeks[7] = L"Sun";
4453 weeks[8] = L"Mon";
4454 weeks[9] = L"Tue";
4455 weeks[10] = L"Wed";
4456 weeks[11] = L"Thu";
4457 weeks[12] = L"Fri";
4458 weeks[13] = L"Sat";
4459 return weeks;
4460}
4461
4462template <>
4463const string*
4464__time_get_c_storage<char>::__weeks() const
4465{
4466 static const string* weeks = init_weeks();
4467 return weeks;
4468}
4469
4470template <>
4471const wstring*
4472__time_get_c_storage<wchar_t>::__weeks() const
4473{
4474 static const wstring* weeks = init_wweeks();
4475 return weeks;
4476}
4477
4478static
4479string*
4480init_months()
4481{
4482 static string months[24];
4483 months[0] = "January";
4484 months[1] = "February";
4485 months[2] = "March";
4486 months[3] = "April";
4487 months[4] = "May";
4488 months[5] = "June";
4489 months[6] = "July";
4490 months[7] = "August";
4491 months[8] = "September";
4492 months[9] = "October";
4493 months[10] = "November";
4494 months[11] = "December";
4495 months[12] = "Jan";
4496 months[13] = "Feb";
4497 months[14] = "Mar";
4498 months[15] = "Apr";
4499 months[16] = "May";
4500 months[17] = "Jun";
4501 months[18] = "Jul";
4502 months[19] = "Aug";
4503 months[20] = "Sep";
4504 months[21] = "Oct";
4505 months[22] = "Nov";
4506 months[23] = "Dec";
4507 return months;
4508}
4509
4510static
4511wstring*
4512init_wmonths()
4513{
4514 static wstring months[24];
4515 months[0] = L"January";
4516 months[1] = L"February";
4517 months[2] = L"March";
4518 months[3] = L"April";
4519 months[4] = L"May";
4520 months[5] = L"June";
4521 months[6] = L"July";
4522 months[7] = L"August";
4523 months[8] = L"September";
4524 months[9] = L"October";
4525 months[10] = L"November";
4526 months[11] = L"December";
4527 months[12] = L"Jan";
4528 months[13] = L"Feb";
4529 months[14] = L"Mar";
4530 months[15] = L"Apr";
4531 months[16] = L"May";
4532 months[17] = L"Jun";
4533 months[18] = L"Jul";
4534 months[19] = L"Aug";
4535 months[20] = L"Sep";
4536 months[21] = L"Oct";
4537 months[22] = L"Nov";
4538 months[23] = L"Dec";
4539 return months;
4540}
4541
4542template <>
4543const string*
4544__time_get_c_storage<char>::__months() const
4545{
4546 static const string* months = init_months();
4547 return months;
4548}
4549
4550template <>
4551const wstring*
4552__time_get_c_storage<wchar_t>::__months() const
4553{
4554 static const wstring* months = init_wmonths();
4555 return months;
4556}
4557
4558static
4559string*
4560init_am_pm()
4561{
4562 static string am_pm[24];
4563 am_pm[0] = "AM";
4564 am_pm[1] = "PM";
4565 return am_pm;
4566}
4567
4568static
4569wstring*
4570init_wam_pm()
4571{
4572 static wstring am_pm[24];
4573 am_pm[0] = L"AM";
4574 am_pm[1] = L"PM";
4575 return am_pm;
4576}
4577
4578template <>
4579const string*
4580__time_get_c_storage<char>::__am_pm() const
4581{
4582 static const string* am_pm = init_am_pm();
4583 return am_pm;
4584}
4585
4586template <>
4587const wstring*
4588__time_get_c_storage<wchar_t>::__am_pm() const
4589{
4590 static const wstring* am_pm = init_wam_pm();
4591 return am_pm;
4592}
4593
4594template <>
4595const string&
4596__time_get_c_storage<char>::__x() const
4597{
4598 static string s("%m/%d/%y");
4599 return s;
4600}
4601
4602template <>
4603const wstring&
4604__time_get_c_storage<wchar_t>::__x() const
4605{
4606 static wstring s(L"%m/%d/%y");
4607 return s;
4608}
4609
4610template <>
4611const string&
4612__time_get_c_storage<char>::__X() const
4613{
4614 static string s("%H:%M:%S");
4615 return s;
4616}
4617
4618template <>
4619const wstring&
4620__time_get_c_storage<wchar_t>::__X() const
4621{
4622 static wstring s(L"%H:%M:%S");
4623 return s;
4624}
4625
4626template <>
4627const string&
4628__time_get_c_storage<char>::__c() const
4629{
4630 static string s("%a %b %d %H:%M:%S %Y");
4631 return s;
4632}
4633
4634template <>
4635const wstring&
4636__time_get_c_storage<wchar_t>::__c() const
4637{
4638 static wstring s(L"%a %b %d %H:%M:%S %Y");
4639 return s;
4640}
4641
4642template <>
4643const string&
4644__time_get_c_storage<char>::__r() const
4645{
4646 static string s("%I:%M:%S %p");
4647 return s;
4648}
4649
4650template <>
4651const wstring&
4652__time_get_c_storage<wchar_t>::__r() const
4653{
4654 static wstring s(L"%I:%M:%S %p");
4655 return s;
4656}
4657
4658// time_get_byname
4659
4660__time_get::__time_get(const char* nm)
4661 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4662{
Howard Hinnantd4444702010-08-11 17:04:31 +00004663#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004664 if (__loc_ == 0)
4665 throw runtime_error("time_get_byname"
4666 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004667#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004668}
4669
4670__time_get::__time_get(const string& nm)
4671 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4672{
Howard Hinnantd4444702010-08-11 17:04:31 +00004673#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004674 if (__loc_ == 0)
4675 throw runtime_error("time_get_byname"
4676 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004677#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004678}
4679
4680__time_get::~__time_get()
4681{
4682 freelocale(__loc_);
4683}
4684
Howard Hinnant335b1512012-02-20 16:51:43 +00004685#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant21772ec2012-12-28 18:15:01 +00004686#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant335b1512012-02-20 16:51:43 +00004687
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004688template <>
4689string
4690__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4691{
Howard Hinnant3074a052012-02-19 14:55:32 +00004692 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004693 t.tm_sec = 59;
4694 t.tm_min = 55;
4695 t.tm_hour = 23;
4696 t.tm_mday = 31;
4697 t.tm_mon = 11;
4698 t.tm_year = 161;
4699 t.tm_wday = 6;
4700 t.tm_yday = 364;
4701 t.tm_isdst = -1;
4702 char buf[100];
4703 char f[3] = {0};
4704 f[0] = '%';
4705 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004706 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004707 char* bb = buf;
4708 char* be = buf + n;
4709 string result;
4710 while (bb != be)
4711 {
4712 if (ct.is(ctype_base::space, *bb))
4713 {
4714 result.push_back(' ');
4715 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4716 ;
4717 continue;
4718 }
4719 char* w = bb;
4720 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004721 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004722 ct, err, false)
4723 - this->__weeks_;
4724 if (i < 14)
4725 {
4726 result.push_back('%');
4727 if (i < 7)
4728 result.push_back('A');
4729 else
4730 result.push_back('a');
4731 bb = w;
4732 continue;
4733 }
4734 w = bb;
4735 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4736 ct, err, false)
4737 - this->__months_;
4738 if (i < 24)
4739 {
4740 result.push_back('%');
4741 if (i < 12)
4742 result.push_back('B');
4743 else
4744 result.push_back('b');
4745 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4746 result.back() = 'm';
4747 bb = w;
4748 continue;
4749 }
4750 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4751 {
4752 w = bb;
4753 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4754 ct, err, false) - this->__am_pm_;
4755 if (i < 2)
4756 {
4757 result.push_back('%');
4758 result.push_back('p');
4759 bb = w;
4760 continue;
4761 }
4762 }
4763 w = bb;
4764 if (ct.is(ctype_base::digit, *bb))
4765 {
4766 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4767 {
4768 case 6:
4769 result.push_back('%');
4770 result.push_back('w');
4771 break;
4772 case 7:
4773 result.push_back('%');
4774 result.push_back('u');
4775 break;
4776 case 11:
4777 result.push_back('%');
4778 result.push_back('I');
4779 break;
4780 case 12:
4781 result.push_back('%');
4782 result.push_back('m');
4783 break;
4784 case 23:
4785 result.push_back('%');
4786 result.push_back('H');
4787 break;
4788 case 31:
4789 result.push_back('%');
4790 result.push_back('d');
4791 break;
4792 case 55:
4793 result.push_back('%');
4794 result.push_back('M');
4795 break;
4796 case 59:
4797 result.push_back('%');
4798 result.push_back('S');
4799 break;
4800 case 61:
4801 result.push_back('%');
4802 result.push_back('y');
4803 break;
4804 case 364:
4805 result.push_back('%');
4806 result.push_back('j');
4807 break;
4808 case 2061:
4809 result.push_back('%');
4810 result.push_back('Y');
4811 break;
4812 default:
4813 for (; w != bb; ++w)
4814 result.push_back(*w);
4815 break;
4816 }
4817 continue;
4818 }
4819 if (*bb == '%')
4820 {
4821 result.push_back('%');
4822 result.push_back('%');
4823 ++bb;
4824 continue;
4825 }
4826 result.push_back(*bb);
4827 ++bb;
4828 }
4829 return result;
4830}
4831
Howard Hinnantec3773c2011-12-01 20:21:04 +00004832#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004833
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004834template <>
4835wstring
4836__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4837{
Howard Hinnant3074a052012-02-19 14:55:32 +00004838 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004839 t.tm_sec = 59;
4840 t.tm_min = 55;
4841 t.tm_hour = 23;
4842 t.tm_mday = 31;
4843 t.tm_mon = 11;
4844 t.tm_year = 161;
4845 t.tm_wday = 6;
4846 t.tm_yday = 364;
4847 t.tm_isdst = -1;
4848 char buf[100];
4849 char f[3] = {0};
4850 f[0] = '%';
4851 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004852 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004853 wchar_t wbuf[100];
4854 wchar_t* wbb = wbuf;
4855 mbstate_t mb = {0};
4856 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004857#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004858 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004859#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004862 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004863 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004864 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004865 wstring result;
4866 while (wbb != wbe)
4867 {
4868 if (ct.is(ctype_base::space, *wbb))
4869 {
4870 result.push_back(L' ');
4871 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4872 ;
4873 continue;
4874 }
4875 wchar_t* w = wbb;
4876 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004877 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004878 ct, err, false)
4879 - this->__weeks_;
4880 if (i < 14)
4881 {
4882 result.push_back(L'%');
4883 if (i < 7)
4884 result.push_back(L'A');
4885 else
4886 result.push_back(L'a');
4887 wbb = w;
4888 continue;
4889 }
4890 w = wbb;
4891 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4892 ct, err, false)
4893 - this->__months_;
4894 if (i < 24)
4895 {
4896 result.push_back(L'%');
4897 if (i < 12)
4898 result.push_back(L'B');
4899 else
4900 result.push_back(L'b');
4901 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4902 result.back() = L'm';
4903 wbb = w;
4904 continue;
4905 }
4906 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4907 {
4908 w = wbb;
4909 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4910 ct, err, false) - this->__am_pm_;
4911 if (i < 2)
4912 {
4913 result.push_back(L'%');
4914 result.push_back(L'p');
4915 wbb = w;
4916 continue;
4917 }
4918 }
4919 w = wbb;
4920 if (ct.is(ctype_base::digit, *wbb))
4921 {
4922 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4923 {
4924 case 6:
4925 result.push_back(L'%');
4926 result.push_back(L'w');
4927 break;
4928 case 7:
4929 result.push_back(L'%');
4930 result.push_back(L'u');
4931 break;
4932 case 11:
4933 result.push_back(L'%');
4934 result.push_back(L'I');
4935 break;
4936 case 12:
4937 result.push_back(L'%');
4938 result.push_back(L'm');
4939 break;
4940 case 23:
4941 result.push_back(L'%');
4942 result.push_back(L'H');
4943 break;
4944 case 31:
4945 result.push_back(L'%');
4946 result.push_back(L'd');
4947 break;
4948 case 55:
4949 result.push_back(L'%');
4950 result.push_back(L'M');
4951 break;
4952 case 59:
4953 result.push_back(L'%');
4954 result.push_back(L'S');
4955 break;
4956 case 61:
4957 result.push_back(L'%');
4958 result.push_back(L'y');
4959 break;
4960 case 364:
4961 result.push_back(L'%');
4962 result.push_back(L'j');
4963 break;
4964 case 2061:
4965 result.push_back(L'%');
4966 result.push_back(L'Y');
4967 break;
4968 default:
4969 for (; w != wbb; ++w)
4970 result.push_back(*w);
4971 break;
4972 }
4973 continue;
4974 }
4975 if (ct.narrow(*wbb, 0) == '%')
4976 {
4977 result.push_back(L'%');
4978 result.push_back(L'%');
4979 ++wbb;
4980 continue;
4981 }
4982 result.push_back(*wbb);
4983 ++wbb;
4984 }
4985 return result;
4986}
4987
4988template <>
4989void
4990__time_get_storage<char>::init(const ctype<char>& ct)
4991{
Howard Hinnantcd992362012-08-02 18:44:17 +00004992 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004993 char buf[100];
4994 // __weeks_
4995 for (int i = 0; i < 7; ++i)
4996 {
4997 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004998 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004999 __weeks_[i] = buf;
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+7] = buf;
5002 }
5003 // __months_
5004 for (int i = 0; i < 12; ++i)
5005 {
5006 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005007 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005008 __months_[i] = buf;
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+12] = buf;
5011 }
5012 // __am_pm_
5013 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005014 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005015 __am_pm_[0] = buf;
5016 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005017 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005018 __am_pm_[1] = buf;
5019 __c_ = __analyze('c', ct);
5020 __r_ = __analyze('r', ct);
5021 __x_ = __analyze('x', ct);
5022 __X_ = __analyze('X', ct);
5023}
5024
5025template <>
5026void
5027__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5028{
5029 tm t = {0};
5030 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005031 wchar_t wbuf[100];
5032 wchar_t* wbe;
5033 mbstate_t mb = {0};
5034 // __weeks_
5035 for (int i = 0; i < 7; ++i)
5036 {
5037 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005038 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005039 mb = mbstate_t();
5040 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005041#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005042 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005043#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005046 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005047 __throw_runtime_error("locale not supported");
5048 wbe = wbuf + j;
5049 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005050 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005051 mb = mbstate_t();
5052 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005053#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005054 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005055#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005058 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005059 __throw_runtime_error("locale not supported");
5060 wbe = wbuf + j;
5061 __weeks_[i+7].assign(wbuf, wbe);
5062 }
5063 // __months_
5064 for (int i = 0; i < 12; ++i)
5065 {
5066 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005067 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005068 mb = mbstate_t();
5069 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005070#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005071 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005072#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005075 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005076 __throw_runtime_error("locale not supported");
5077 wbe = wbuf + j;
5078 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005079 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005080 mb = mbstate_t();
5081 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005082#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005083 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005084#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005087 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005088 __throw_runtime_error("locale not supported");
5089 wbe = wbuf + j;
5090 __months_[i+12].assign(wbuf, wbe);
5091 }
5092 // __am_pm_
5093 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005094 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005095 mb = mbstate_t();
5096 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005097#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005098 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005099#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005102 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005103 __throw_runtime_error("locale not supported");
5104 wbe = wbuf + j;
5105 __am_pm_[0].assign(wbuf, wbe);
5106 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005107 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005108 mb = mbstate_t();
5109 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005110#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005111 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005112#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005115 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005116 __throw_runtime_error("locale not supported");
5117 wbe = wbuf + j;
5118 __am_pm_[1].assign(wbuf, wbe);
5119 __c_ = __analyze('c', ct);
5120 __r_ = __analyze('r', ct);
5121 __x_ = __analyze('x', ct);
5122 __X_ = __analyze('X', ct);
5123}
5124
5125template <class CharT>
5126struct _LIBCPP_HIDDEN __time_get_temp
5127 : public ctype_byname<CharT>
5128{
5129 explicit __time_get_temp(const char* nm)
5130 : ctype_byname<CharT>(nm, 1) {}
5131 explicit __time_get_temp(const string& nm)
5132 : ctype_byname<CharT>(nm, 1) {}
5133};
5134
5135template <>
5136__time_get_storage<char>::__time_get_storage(const char* __nm)
5137 : __time_get(__nm)
5138{
5139 const __time_get_temp<char> ct(__nm);
5140 init(ct);
5141}
5142
5143template <>
5144__time_get_storage<char>::__time_get_storage(const string& __nm)
5145 : __time_get(__nm)
5146{
5147 const __time_get_temp<char> ct(__nm);
5148 init(ct);
5149}
5150
5151template <>
5152__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5153 : __time_get(__nm)
5154{
5155 const __time_get_temp<wchar_t> ct(__nm);
5156 init(ct);
5157}
5158
5159template <>
5160__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5161 : __time_get(__nm)
5162{
5163 const __time_get_temp<wchar_t> ct(__nm);
5164 init(ct);
5165}
5166
5167template <>
5168time_base::dateorder
5169__time_get_storage<char>::__do_date_order() const
5170{
5171 unsigned i;
5172 for (i = 0; i < __x_.size(); ++i)
5173 if (__x_[i] == '%')
5174 break;
5175 ++i;
5176 switch (__x_[i])
5177 {
5178 case 'y':
5179 case 'Y':
5180 for (++i; i < __x_.size(); ++i)
5181 if (__x_[i] == '%')
5182 break;
5183 if (i == __x_.size())
5184 break;
5185 ++i;
5186 switch (__x_[i])
5187 {
5188 case 'm':
5189 for (++i; i < __x_.size(); ++i)
5190 if (__x_[i] == '%')
5191 break;
5192 if (i == __x_.size())
5193 break;
5194 ++i;
5195 if (__x_[i] == 'd')
5196 return time_base::ymd;
5197 break;
5198 case 'd':
5199 for (++i; i < __x_.size(); ++i)
5200 if (__x_[i] == '%')
5201 break;
5202 if (i == __x_.size())
5203 break;
5204 ++i;
5205 if (__x_[i] == 'm')
5206 return time_base::ydm;
5207 break;
5208 }
5209 break;
5210 case 'm':
5211 for (++i; i < __x_.size(); ++i)
5212 if (__x_[i] == '%')
5213 break;
5214 if (i == __x_.size())
5215 break;
5216 ++i;
5217 if (__x_[i] == 'd')
5218 {
5219 for (++i; i < __x_.size(); ++i)
5220 if (__x_[i] == '%')
5221 break;
5222 if (i == __x_.size())
5223 break;
5224 ++i;
5225 if (__x_[i] == 'y' || __x_[i] == 'Y')
5226 return time_base::mdy;
5227 break;
5228 }
5229 break;
5230 case 'd':
5231 for (++i; i < __x_.size(); ++i)
5232 if (__x_[i] == '%')
5233 break;
5234 if (i == __x_.size())
5235 break;
5236 ++i;
5237 if (__x_[i] == 'm')
5238 {
5239 for (++i; i < __x_.size(); ++i)
5240 if (__x_[i] == '%')
5241 break;
5242 if (i == __x_.size())
5243 break;
5244 ++i;
5245 if (__x_[i] == 'y' || __x_[i] == 'Y')
5246 return time_base::dmy;
5247 break;
5248 }
5249 break;
5250 }
5251 return time_base::no_order;
5252}
5253
5254template <>
5255time_base::dateorder
5256__time_get_storage<wchar_t>::__do_date_order() const
5257{
5258 unsigned i;
5259 for (i = 0; i < __x_.size(); ++i)
5260 if (__x_[i] == L'%')
5261 break;
5262 ++i;
5263 switch (__x_[i])
5264 {
5265 case L'y':
5266 case L'Y':
5267 for (++i; i < __x_.size(); ++i)
5268 if (__x_[i] == L'%')
5269 break;
5270 if (i == __x_.size())
5271 break;
5272 ++i;
5273 switch (__x_[i])
5274 {
5275 case L'm':
5276 for (++i; i < __x_.size(); ++i)
5277 if (__x_[i] == L'%')
5278 break;
5279 if (i == __x_.size())
5280 break;
5281 ++i;
5282 if (__x_[i] == L'd')
5283 return time_base::ymd;
5284 break;
5285 case L'd':
5286 for (++i; i < __x_.size(); ++i)
5287 if (__x_[i] == L'%')
5288 break;
5289 if (i == __x_.size())
5290 break;
5291 ++i;
5292 if (__x_[i] == L'm')
5293 return time_base::ydm;
5294 break;
5295 }
5296 break;
5297 case L'm':
5298 for (++i; i < __x_.size(); ++i)
5299 if (__x_[i] == L'%')
5300 break;
5301 if (i == __x_.size())
5302 break;
5303 ++i;
5304 if (__x_[i] == L'd')
5305 {
5306 for (++i; i < __x_.size(); ++i)
5307 if (__x_[i] == L'%')
5308 break;
5309 if (i == __x_.size())
5310 break;
5311 ++i;
5312 if (__x_[i] == L'y' || __x_[i] == L'Y')
5313 return time_base::mdy;
5314 break;
5315 }
5316 break;
5317 case L'd':
5318 for (++i; i < __x_.size(); ++i)
5319 if (__x_[i] == L'%')
5320 break;
5321 if (i == __x_.size())
5322 break;
5323 ++i;
5324 if (__x_[i] == L'm')
5325 {
5326 for (++i; i < __x_.size(); ++i)
5327 if (__x_[i] == L'%')
5328 break;
5329 if (i == __x_.size())
5330 break;
5331 ++i;
5332 if (__x_[i] == L'y' || __x_[i] == L'Y')
5333 return time_base::dmy;
5334 break;
5335 }
5336 break;
5337 }
5338 return time_base::no_order;
5339}
5340
5341// time_put
5342
5343__time_put::__time_put(const char* nm)
5344 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5345{
Howard Hinnantd4444702010-08-11 17:04:31 +00005346#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005347 if (__loc_ == 0)
5348 throw runtime_error("time_put_byname"
5349 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005350#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005351}
5352
5353__time_put::__time_put(const string& nm)
5354 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5355{
Howard Hinnantd4444702010-08-11 17:04:31 +00005356#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005357 if (__loc_ == 0)
5358 throw runtime_error("time_put_byname"
5359 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005360#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005361}
5362
5363__time_put::~__time_put()
5364{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005365 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005366 freelocale(__loc_);
5367}
5368
5369void
5370__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5371 char __fmt, char __mod) const
5372{
5373 char fmt[] = {'%', __fmt, __mod, 0};
5374 if (__mod != 0)
5375 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005376 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005377 __ne = __nb + n;
5378}
5379
5380void
5381__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5382 char __fmt, char __mod) const
5383{
5384 char __nar[100];
5385 char* __ne = __nar + 100;
5386 __do_put(__nar, __ne, __tm, __fmt, __mod);
5387 mbstate_t mb = {0};
5388 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005389#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005390 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005391#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005394 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005395 __throw_runtime_error("locale not supported");
5396 __we = __wb + j;
5397}
5398
5399// moneypunct_byname
5400
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005401template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005402static
5403void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005404__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5405 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5406 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005407{
5408 const char sign = static_cast<char>(money_base::sign);
5409 const char space = static_cast<char>(money_base::space);
5410 const char none = static_cast<char>(money_base::none);
5411 const char symbol = static_cast<char>(money_base::symbol);
5412 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005413 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5414
5415 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5416 // function'. "Space between sign and symbol or value" means that
5417 // if the sign is adjacent to the symbol, there's a space between
5418 // them, and otherwise there's a space between the sign and value.
5419 //
5420 // C11's localeconv specifies that the fourth character of an
5421 // international curr_symbol is used to separate the sign and
5422 // value when sep_by_space says to do so. C++ can't represent
5423 // that, so we just use a space. When sep_by_space says to
5424 // separate the symbol and value-or-sign with a space, we rearrange the
5425 // curr_symbol to put its spacing character on the correct side of
5426 // the symbol.
5427 //
5428 // We also need to avoid adding an extra space between the sign
5429 // and value when the currency symbol is suppressed (by not
5430 // setting showbase). We match glibc's strfmon by interpreting
5431 // sep_by_space==1 as "omit the space when the currency symbol is
5432 // absent".
5433 //
5434 // Users who want to get this right should use ICU instead.
5435
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005436 switch (cs_precedes)
5437 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005438 case 0: // value before curr_symbol
5439 if (symbol_contains_sep) {
5440 // Move the separator to before the symbol, to place it
5441 // between the value and symbol.
5442 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5443 __curr_symbol_.end());
5444 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005445 switch (sign_posn)
5446 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005447 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005448 pat.field[0] = sign;
5449 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005450 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005451 pat.field[3] = symbol;
5452 switch (sep_by_space)
5453 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005454 case 0: // No space separates the currency symbol and value.
5455 // This case may have changed between C99 and C11;
5456 // assume the currency symbol matches the intention.
5457 case 2: // Space between sign and currency or value.
5458 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005459 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005460 case 1: // Space between currency-and-sign or currency and value.
5461 if (!symbol_contains_sep) {
5462 // We insert the space into the symbol instead of
5463 // setting pat.field[2]=space so that when
5464 // showbase is not set, the space goes away too.
5465 __curr_symbol_.insert(0, 1, space_char);
5466 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005467 return;
5468 default:
5469 break;
5470 }
5471 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005472 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005473 pat.field[0] = sign;
5474 pat.field[3] = symbol;
5475 switch (sep_by_space)
5476 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005477 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005478 pat.field[1] = value;
5479 pat.field[2] = none;
5480 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005481 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005482 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005483 pat.field[2] = none;
5484 if (!symbol_contains_sep) {
5485 // We insert the space into the symbol instead of
5486 // setting pat.field[2]=space so that when
5487 // showbase is not set, the space goes away too.
5488 __curr_symbol_.insert(0, 1, space_char);
5489 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005490 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005491 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005492 pat.field[1] = space;
5493 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005494 if (symbol_contains_sep) {
5495 // Remove the separator from the symbol, since it
5496 // has already appeared after the sign.
5497 __curr_symbol_.erase(__curr_symbol_.begin());
5498 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005499 return;
5500 default:
5501 break;
5502 }
5503 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005504 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005505 pat.field[0] = value;
5506 pat.field[3] = sign;
5507 switch (sep_by_space)
5508 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005509 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005510 pat.field[1] = none;
5511 pat.field[2] = symbol;
5512 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005513 case 1: // Space between currency-and-sign or currency and value.
5514 if (!symbol_contains_sep) {
5515 // We insert the space into the symbol instead of
5516 // setting pat.field[1]=space so that when
5517 // showbase is not set, the space goes away too.
5518 __curr_symbol_.insert(0, 1, space_char);
5519 }
5520 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005521 pat.field[2] = symbol;
5522 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005523 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005524 pat.field[1] = symbol;
5525 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005526 if (symbol_contains_sep) {
5527 // Remove the separator from the symbol, since it
5528 // should not be removed if showbase is absent.
5529 __curr_symbol_.erase(__curr_symbol_.begin());
5530 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005531 return;
5532 default:
5533 break;
5534 }
5535 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005536 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005537 pat.field[0] = value;
5538 pat.field[3] = symbol;
5539 switch (sep_by_space)
5540 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005541 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005542 pat.field[1] = none;
5543 pat.field[2] = sign;
5544 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005545 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005546 pat.field[1] = space;
5547 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005548 if (symbol_contains_sep) {
5549 // Remove the separator from the symbol, since it
5550 // has already appeared before the sign.
5551 __curr_symbol_.erase(__curr_symbol_.begin());
5552 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005553 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005554 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005555 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005556 pat.field[2] = none;
5557 if (!symbol_contains_sep) {
5558 // We insert the space into the symbol instead of
5559 // setting pat.field[2]=space so that when
5560 // showbase is not set, the space goes away too.
5561 __curr_symbol_.insert(0, 1, space_char);
5562 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005563 return;
5564 default:
5565 break;
5566 }
5567 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005568 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005569 pat.field[0] = value;
5570 pat.field[3] = sign;
5571 switch (sep_by_space)
5572 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005573 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005574 pat.field[1] = none;
5575 pat.field[2] = symbol;
5576 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005577 case 1: // Space between currency-and-sign or currency and value.
5578 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005579 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005580 if (!symbol_contains_sep) {
5581 // We insert the space into the symbol instead of
5582 // setting pat.field[1]=space so that when
5583 // showbase is not set, the space goes away too.
5584 __curr_symbol_.insert(0, 1, space_char);
5585 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005586 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005587 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005588 pat.field[1] = symbol;
5589 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005590 if (symbol_contains_sep) {
5591 // Remove the separator from the symbol, since it
5592 // should not disappear when showbase is absent.
5593 __curr_symbol_.erase(__curr_symbol_.begin());
5594 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005595 return;
5596 default:
5597 break;
5598 }
5599 break;
5600 default:
5601 break;
5602 }
5603 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005604 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005605 switch (sign_posn)
5606 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005607 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005608 pat.field[0] = sign;
5609 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005610 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005611 pat.field[3] = value;
5612 switch (sep_by_space)
5613 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005614 case 0: // No space separates the currency symbol and value.
5615 // This case may have changed between C99 and C11;
5616 // assume the currency symbol matches the intention.
5617 case 2: // Space between sign and currency or value.
5618 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005619 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005620 case 1: // Space between currency-and-sign or currency and value.
5621 if (!symbol_contains_sep) {
5622 // We insert the space into the symbol instead of
5623 // setting pat.field[2]=space so that when
5624 // showbase is not set, the space goes away too.
5625 __curr_symbol_.insert(0, 1, space_char);
5626 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005627 return;
5628 default:
5629 break;
5630 }
5631 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005632 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005633 pat.field[0] = sign;
5634 pat.field[3] = value;
5635 switch (sep_by_space)
5636 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005637 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005638 pat.field[1] = symbol;
5639 pat.field[2] = none;
5640 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005641 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005642 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005643 pat.field[2] = none;
5644 if (!symbol_contains_sep) {
5645 // We insert the space into the symbol instead of
5646 // setting pat.field[2]=space so that when
5647 // showbase is not set, the space goes away too.
5648 __curr_symbol_.push_back(space_char);
5649 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005650 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005651 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005652 pat.field[1] = space;
5653 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005654 if (symbol_contains_sep) {
5655 // Remove the separator from the symbol, since it
5656 // has already appeared after the sign.
5657 __curr_symbol_.pop_back();
5658 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005659 return;
5660 default:
5661 break;
5662 }
5663 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005664 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005665 pat.field[0] = symbol;
5666 pat.field[3] = sign;
5667 switch (sep_by_space)
5668 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005669 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005670 pat.field[1] = none;
5671 pat.field[2] = value;
5672 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005673 case 1: // Space between currency-and-sign or currency and value.
5674 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005675 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005676 if (!symbol_contains_sep) {
5677 // We insert the space into the symbol instead of
5678 // setting pat.field[1]=space so that when
5679 // showbase is not set, the space goes away too.
5680 __curr_symbol_.push_back(space_char);
5681 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005682 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005683 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005684 pat.field[1] = value;
5685 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005686 if (symbol_contains_sep) {
5687 // Remove the separator from the symbol, since it
5688 // will appear before the sign.
5689 __curr_symbol_.pop_back();
5690 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005691 return;
5692 default:
5693 break;
5694 }
5695 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005696 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005697 pat.field[0] = sign;
5698 pat.field[3] = value;
5699 switch (sep_by_space)
5700 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005701 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005702 pat.field[1] = symbol;
5703 pat.field[2] = none;
5704 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005705 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005706 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005707 pat.field[2] = none;
5708 if (!symbol_contains_sep) {
5709 // We insert the space into the symbol instead of
5710 // setting pat.field[2]=space so that when
5711 // showbase is not set, the space goes away too.
5712 __curr_symbol_.push_back(space_char);
5713 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005714 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005715 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005716 pat.field[1] = space;
5717 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005718 if (symbol_contains_sep) {
5719 // Remove the separator from the symbol, since it
5720 // has already appeared after the sign.
5721 __curr_symbol_.pop_back();
5722 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005723 return;
5724 default:
5725 break;
5726 }
5727 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005728 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005729 pat.field[0] = symbol;
5730 pat.field[3] = value;
5731 switch (sep_by_space)
5732 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005733 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005734 pat.field[1] = sign;
5735 pat.field[2] = none;
5736 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005737 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005738 pat.field[1] = sign;
5739 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005740 if (symbol_contains_sep) {
5741 // Remove the separator from the symbol, since it
5742 // should not disappear when showbase is absent.
5743 __curr_symbol_.pop_back();
5744 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005745 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005746 case 2: // Space between sign and currency or value.
5747 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005748 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005749 if (!symbol_contains_sep) {
5750 // We insert the space into the symbol instead of
5751 // setting pat.field[1]=space so that when
5752 // showbase is not set, the space goes away too.
5753 __curr_symbol_.push_back(space_char);
5754 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005755 return;
5756 default:
5757 break;
5758 }
5759 break;
5760 default:
5761 break;
5762 }
5763 break;
5764 default:
5765 break;
5766 }
5767 pat.field[0] = symbol;
5768 pat.field[1] = sign;
5769 pat.field[2] = none;
5770 pat.field[3] = value;
5771}
5772
5773template<>
5774void
5775moneypunct_byname<char, false>::init(const char* nm)
5776{
5777 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005778 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005779#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005780 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005781 throw runtime_error("moneypunct_byname"
5782 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005783#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005784#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005785 lconv* lc = localeconv_l(loc.get());
5786#else
5787 lconv* lc = __localeconv_l(loc.get());
5788#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005789 if (*lc->mon_decimal_point)
5790 __decimal_point_ = *lc->mon_decimal_point;
5791 else
5792 __decimal_point_ = base::do_decimal_point();
5793 if (*lc->mon_thousands_sep)
5794 __thousands_sep_ = *lc->mon_thousands_sep;
5795 else
5796 __thousands_sep_ = base::do_thousands_sep();
5797 __grouping_ = lc->mon_grouping;
5798 __curr_symbol_ = lc->currency_symbol;
5799 if (lc->frac_digits != CHAR_MAX)
5800 __frac_digits_ = lc->frac_digits;
5801 else
5802 __frac_digits_ = base::do_frac_digits();
5803 if (lc->p_sign_posn == 0)
5804 __positive_sign_ = "()";
5805 else
5806 __positive_sign_ = lc->positive_sign;
5807 if (lc->n_sign_posn == 0)
5808 __negative_sign_ = "()";
5809 else
5810 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005811 // Assume the positive and negative formats will want spaces in
5812 // the same places in curr_symbol since there's no way to
5813 // represent anything else.
5814 string_type __dummy_curr_symbol = __curr_symbol_;
5815 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5816 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5817 __init_pat(__neg_format_, __curr_symbol_, false,
5818 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005819}
5820
5821template<>
5822void
5823moneypunct_byname<char, true>::init(const char* nm)
5824{
5825 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005826 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005827#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005828 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005829 throw runtime_error("moneypunct_byname"
5830 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005831#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005832#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005833 lconv* lc = localeconv_l(loc.get());
5834#else
5835 lconv* lc = __localeconv_l(loc.get());
5836#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005837 if (*lc->mon_decimal_point)
5838 __decimal_point_ = *lc->mon_decimal_point;
5839 else
5840 __decimal_point_ = base::do_decimal_point();
5841 if (*lc->mon_thousands_sep)
5842 __thousands_sep_ = *lc->mon_thousands_sep;
5843 else
5844 __thousands_sep_ = base::do_thousands_sep();
5845 __grouping_ = lc->mon_grouping;
5846 __curr_symbol_ = lc->int_curr_symbol;
5847 if (lc->int_frac_digits != CHAR_MAX)
5848 __frac_digits_ = lc->int_frac_digits;
5849 else
5850 __frac_digits_ = base::do_frac_digits();
Howard Hinnante9df0a52013-08-01 18:17:34 +00005851#ifdef _LIBCPP_MSVCRT
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005852 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005853#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005854 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005855#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005856 __positive_sign_ = "()";
5857 else
5858 __positive_sign_ = lc->positive_sign;
Howard Hinnante9df0a52013-08-01 18:17:34 +00005859#ifdef _LIBCPP_MSVCRT
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005860 if(lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005861#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005862 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005863#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005864 __negative_sign_ = "()";
5865 else
5866 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005867 // Assume the positive and negative formats will want spaces in
5868 // the same places in curr_symbol since there's no way to
5869 // represent anything else.
5870 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnante9df0a52013-08-01 18:17:34 +00005871#ifdef _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005872 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5873 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5874 __init_pat(__neg_format_, __curr_symbol_, true,
5875 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005876#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005877 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5878 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5879 lc->int_p_sign_posn, ' ');
5880 __init_pat(__neg_format_, __curr_symbol_, true,
5881 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5882 lc->int_n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005883#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005884}
5885
5886template<>
5887void
5888moneypunct_byname<wchar_t, false>::init(const char* nm)
5889{
5890 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005891 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005892#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005893 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005894 throw runtime_error("moneypunct_byname"
5895 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005896#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005897#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005898 lconv* lc = localeconv_l(loc.get());
5899#else
5900 lconv* lc = __localeconv_l(loc.get());
5901#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005902 if (*lc->mon_decimal_point)
5903 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5904 else
5905 __decimal_point_ = base::do_decimal_point();
5906 if (*lc->mon_thousands_sep)
5907 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5908 else
5909 __thousands_sep_ = base::do_thousands_sep();
5910 __grouping_ = lc->mon_grouping;
5911 wchar_t wbuf[100];
5912 mbstate_t mb = {0};
5913 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005914#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005915 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005916#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005919 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005920 __throw_runtime_error("locale not supported");
5921 wchar_t* wbe = wbuf + j;
5922 __curr_symbol_.assign(wbuf, wbe);
5923 if (lc->frac_digits != CHAR_MAX)
5924 __frac_digits_ = lc->frac_digits;
5925 else
5926 __frac_digits_ = base::do_frac_digits();
5927 if (lc->p_sign_posn == 0)
5928 __positive_sign_ = L"()";
5929 else
5930 {
5931 mb = mbstate_t();
5932 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005933#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005934 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005935#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005938 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005939 __throw_runtime_error("locale not supported");
5940 wbe = wbuf + j;
5941 __positive_sign_.assign(wbuf, wbe);
5942 }
5943 if (lc->n_sign_posn == 0)
5944 __negative_sign_ = L"()";
5945 else
5946 {
5947 mb = mbstate_t();
5948 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005949#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005950 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005951#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005954 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005955 __throw_runtime_error("locale not supported");
5956 wbe = wbuf + j;
5957 __negative_sign_.assign(wbuf, wbe);
5958 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005959 // Assume the positive and negative formats will want spaces in
5960 // the same places in curr_symbol since there's no way to
5961 // represent anything else.
5962 string_type __dummy_curr_symbol = __curr_symbol_;
5963 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5964 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5965 __init_pat(__neg_format_, __curr_symbol_, false,
5966 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005967}
5968
5969template<>
5970void
5971moneypunct_byname<wchar_t, true>::init(const char* nm)
5972{
5973 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005974 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005975#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005976 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005977 throw runtime_error("moneypunct_byname"
5978 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005979#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005980#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005981 lconv* lc = localeconv_l(loc.get());
5982#else
5983 lconv* lc = __localeconv_l(loc.get());
5984#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005985 if (*lc->mon_decimal_point)
5986 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5987 else
5988 __decimal_point_ = base::do_decimal_point();
5989 if (*lc->mon_thousands_sep)
5990 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5991 else
5992 __thousands_sep_ = base::do_thousands_sep();
5993 __grouping_ = lc->mon_grouping;
5994 wchar_t wbuf[100];
5995 mbstate_t mb = {0};
5996 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005997#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005998 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005999#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006000 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006001#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006002 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006003 __throw_runtime_error("locale not supported");
6004 wchar_t* wbe = wbuf + j;
6005 __curr_symbol_.assign(wbuf, wbe);
6006 if (lc->int_frac_digits != CHAR_MAX)
6007 __frac_digits_ = lc->int_frac_digits;
6008 else
6009 __frac_digits_ = base::do_frac_digits();
Howard Hinnante9df0a52013-08-01 18:17:34 +00006010#ifdef _LIBCPP_MSVCRT
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006011 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006012#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006013 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006014#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006015 __positive_sign_ = L"()";
6016 else
6017 {
6018 mb = mbstate_t();
6019 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006020#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006021 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006022#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006025 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006026 __throw_runtime_error("locale not supported");
6027 wbe = wbuf + j;
6028 __positive_sign_.assign(wbuf, wbe);
6029 }
Howard Hinnante9df0a52013-08-01 18:17:34 +00006030#ifdef _LIBCPP_MSVCRT
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006031 if (lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006032#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006033 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006034#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006035 __negative_sign_ = L"()";
6036 else
6037 {
6038 mb = mbstate_t();
6039 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006040#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006041 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006042#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006045 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006046 __throw_runtime_error("locale not supported");
6047 wbe = wbuf + j;
6048 __negative_sign_.assign(wbuf, wbe);
6049 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006050 // Assume the positive and negative formats will want spaces in
6051 // the same places in curr_symbol since there's no way to
6052 // represent anything else.
6053 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnante9df0a52013-08-01 18:17:34 +00006054#ifdef _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006055 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6056 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6057 __init_pat(__neg_format_, __curr_symbol_, true,
6058 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006059#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006060 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6061 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6062 lc->int_p_sign_posn, L' ');
6063 __init_pat(__neg_format_, __curr_symbol_, true,
6064 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6065 lc->int_n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006066#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006067}
6068
6069void __do_nothing(void*) {}
6070
6071void __throw_runtime_error(const char* msg)
6072{
Howard Hinnantd4444702010-08-11 17:04:31 +00006073#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006074 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006075#else
6076 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006077#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006078}
6079
6080template class collate<char>;
6081template class collate<wchar_t>;
6082
6083template class num_get<char>;
6084template class num_get<wchar_t>;
6085
Howard Hinnantec3773c2011-12-01 20:21:04 +00006086template struct __num_get<char>;
6087template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006088
6089template class num_put<char>;
6090template class num_put<wchar_t>;
6091
Howard Hinnantec3773c2011-12-01 20:21:04 +00006092template struct __num_put<char>;
6093template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006094
6095template class time_get<char>;
6096template class time_get<wchar_t>;
6097
6098template class time_get_byname<char>;
6099template class time_get_byname<wchar_t>;
6100
6101template class time_put<char>;
6102template class time_put<wchar_t>;
6103
6104template class time_put_byname<char>;
6105template class time_put_byname<wchar_t>;
6106
6107template class moneypunct<char, false>;
6108template class moneypunct<char, true>;
6109template class moneypunct<wchar_t, false>;
6110template class moneypunct<wchar_t, true>;
6111
6112template class moneypunct_byname<char, false>;
6113template class moneypunct_byname<char, true>;
6114template class moneypunct_byname<wchar_t, false>;
6115template class moneypunct_byname<wchar_t, true>;
6116
6117template class money_get<char>;
6118template class money_get<wchar_t>;
6119
6120template class __money_get<char>;
6121template class __money_get<wchar_t>;
6122
6123template class money_put<char>;
6124template class money_put<wchar_t>;
6125
6126template class __money_put<char>;
6127template class __money_put<wchar_t>;
6128
6129template class messages<char>;
6130template class messages<wchar_t>;
6131
6132template class messages_byname<char>;
6133template class messages_byname<wchar_t>;
6134
6135template class codecvt_byname<char, char, mbstate_t>;
6136template class codecvt_byname<wchar_t, char, mbstate_t>;
6137template class codecvt_byname<char16_t, char, mbstate_t>;
6138template class codecvt_byname<char32_t, char, mbstate_t>;
6139
6140template class __vector_base_common<true>;
6141
6142_LIBCPP_END_NAMESPACE_STD