blob: 8fadbb6fdfd09deeb35449385efb0206e0c58b6f [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
Howard Hinnant04a2c712013-08-29 20:56:53 +000010#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
11
David Chisnall997e4542012-02-29 13:05:08 +000012// On Solaris, we need to define something to make the C99 parts of localeconv
13// visible.
14#ifdef __sun__
15#define _LCONV_C99
16#endif
17
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000018#include "string"
19#include "locale"
Howard Hinnant87d1a8a2010-05-30 21:39:41 +000020#include "codecvt"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000021#include "vector"
22#include "algorithm"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000023#include "typeinfo"
Howard Hinnantb87922c2013-07-28 18:20:00 +000024#ifndef _LIBCPP_NO_EXCEPTIONS
25# include "type_traits"
26#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000027#include "clocale"
28#include "cstring"
29#include "cwctype"
30#include "__sso_allocator"
Howard Hinnantef5aa932013-09-17 01:34:47 +000031#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant14fa9f92011-09-29 20:33:10 +000032#include <support/win32/locale_win32.h>
Howard Hinnante9df0a52013-08-01 18:17:34 +000033#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000034#include <langinfo.h>
Howard Hinnante9df0a52013-08-01 18:17:34 +000035#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000036#include <stdlib.h>
Howard Hinnanted14a762013-07-23 16:05:56 +000037#include <stdio.h>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000038
Marshall Clow9ae96d02013-02-07 17:20:56 +000039// On Linux, wint_t and wchar_t have different signed-ness, and this causes
40// lots of noise in the build log, but no bugs that I know of.
Marshall Clowa3645132013-10-21 15:07:28 +000041#if defined(__clang__)
Marshall Clow9ae96d02013-02-07 17:20:56 +000042#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowa3645132013-10-21 15:07:28 +000043#endif
Marshall Clow9ae96d02013-02-07 17:20:56 +000044
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000045_LIBCPP_BEGIN_NAMESPACE_STD
46
Howard Hinnant866569b2011-09-28 23:39:33 +000047#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000048locale_t __cloc() {
49 // In theory this could create a race condition. In practice
50 // the race condition is non-fatal since it will just create
51 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000052 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
53 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000054}
Howard Hinnant866569b2011-09-28 23:39:33 +000055#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000056
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000057namespace {
58
59struct release
60{
61 void operator()(locale::facet* p) {p->__release_shared();}
62};
63
64template <class T, class A0>
65inline
66T&
67make(A0 a0)
68{
69 static typename aligned_storage<sizeof(T)>::type buf;
70 ::new (&buf) T(a0);
71 return *(T*)&buf;
72}
73
74template <class T, class A0, class A1>
75inline
76T&
77make(A0 a0, A1 a1)
78{
79 static typename aligned_storage<sizeof(T)>::type buf;
80 ::new (&buf) T(a0, a1);
81 return *(T*)&buf;
82}
83
84template <class T, class A0, class A1, class A2>
85inline
86T&
87make(A0 a0, A1 a1, A2 a2)
88{
89 static typename aligned_storage<sizeof(T)>::type buf;
90 ::new (&buf) T(a0, a1, a2);
91 return *(T*)&buf;
92}
93
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000094template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000095inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000096_LIBCPP_CONSTEXPR
97size_t
98countof(const T (&)[N])
99{
100 return N;
101}
102
103template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +0000104inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +0000105_LIBCPP_CONSTEXPR
106size_t
107countof(const T * const begin, const T * const end)
108{
109 return static_cast<size_t>(end - begin);
110}
111
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000112}
113
Howard Hinnant51437222013-08-29 23:37:50 +0000114#if defined(_AIX)
115// Set priority to INT_MIN + 256 + 150
116# pragma priority ( -2147483242 )
117#endif
118
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000119const locale::category locale::none;
120const locale::category locale::collate;
121const locale::category locale::ctype;
122const locale::category locale::monetary;
123const locale::category locale::numeric;
124const locale::category locale::time;
125const locale::category locale::messages;
126const locale::category locale::all;
127
Marshall Clowa3645132013-10-21 15:07:28 +0000128#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000129#pragma clang diagnostic push
130#pragma clang diagnostic ignored "-Wpadded"
Marshall Clowa3645132013-10-21 15:07:28 +0000131#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000132
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000133class _LIBCPP_HIDDEN locale::__imp
134 : public facet
135{
136 enum {N = 28};
Marshall Clowa3645132013-10-21 15:07:28 +0000137#if defined(_LIBCPP_MSVC)
138// FIXME: MSVC doesn't support aligned parameters by value.
139// I can't get the __sso_allocator to work here
140// for MSVC I think for this reason.
141 vector<facet*> facets_;
142#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000143 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowa3645132013-10-21 15:07:28 +0000144#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000145 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000146public:
147 explicit __imp(size_t refs = 0);
148 explicit __imp(const string& name, size_t refs = 0);
149 __imp(const __imp&);
150 __imp(const __imp&, const string&, locale::category c);
151 __imp(const __imp& other, const __imp& one, locale::category c);
152 __imp(const __imp&, facet* f, long id);
153 ~__imp();
154
155 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000156 bool has_facet(long id) const
157 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000158 const locale::facet* use_facet(long id) const;
159
160 static const locale& make_classic();
161 static locale& make_global();
162private:
163 void install(facet* f, long id);
164 template <class F> void install(F* f) {install(f, f->id.__get());}
165 template <class F> void install_from(const __imp& other);
166};
167
Marshall Clowa3645132013-10-21 15:07:28 +0000168#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000169#pragma clang diagnostic pop
Marshall Clowa3645132013-10-21 15:07:28 +0000170#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000171
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000172locale::__imp::__imp(size_t refs)
173 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000174 facets_(N),
175 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000176{
177 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000178 install(&make<_VSTD::collate<char> >(1u));
179 install(&make<_VSTD::collate<wchar_t> >(1u));
180 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
181 install(&make<_VSTD::ctype<wchar_t> >(1u));
182 install(&make<codecvt<char, char, mbstate_t> >(1u));
183 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
184 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
185 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
186 install(&make<numpunct<char> >(1u));
187 install(&make<numpunct<wchar_t> >(1u));
188 install(&make<num_get<char> >(1u));
189 install(&make<num_get<wchar_t> >(1u));
190 install(&make<num_put<char> >(1u));
191 install(&make<num_put<wchar_t> >(1u));
192 install(&make<moneypunct<char, false> >(1u));
193 install(&make<moneypunct<char, true> >(1u));
194 install(&make<moneypunct<wchar_t, false> >(1u));
195 install(&make<moneypunct<wchar_t, true> >(1u));
196 install(&make<money_get<char> >(1u));
197 install(&make<money_get<wchar_t> >(1u));
198 install(&make<money_put<char> >(1u));
199 install(&make<money_put<wchar_t> >(1u));
200 install(&make<time_get<char> >(1u));
201 install(&make<time_get<wchar_t> >(1u));
202 install(&make<time_put<char> >(1u));
203 install(&make<time_put<wchar_t> >(1u));
204 install(&make<_VSTD::messages<char> >(1u));
205 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000206}
207
208locale::__imp::__imp(const string& name, size_t refs)
209 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000210 facets_(N),
211 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000212{
Howard Hinnantd4444702010-08-11 17:04:31 +0000213#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000214 try
215 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000216#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000217 facets_ = locale::classic().__locale_->facets_;
218 for (unsigned i = 0; i < facets_.size(); ++i)
219 if (facets_[i])
220 facets_[i]->__add_shared();
221 install(new collate_byname<char>(name_));
222 install(new collate_byname<wchar_t>(name_));
223 install(new ctype_byname<char>(name_));
224 install(new ctype_byname<wchar_t>(name_));
225 install(new codecvt_byname<char, char, mbstate_t>(name_));
226 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
227 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
228 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
229 install(new numpunct_byname<char>(name_));
230 install(new numpunct_byname<wchar_t>(name_));
231 install(new moneypunct_byname<char, false>(name_));
232 install(new moneypunct_byname<char, true>(name_));
233 install(new moneypunct_byname<wchar_t, false>(name_));
234 install(new moneypunct_byname<wchar_t, true>(name_));
235 install(new time_get_byname<char>(name_));
236 install(new time_get_byname<wchar_t>(name_));
237 install(new time_put_byname<char>(name_));
238 install(new time_put_byname<wchar_t>(name_));
239 install(new messages_byname<char>(name_));
240 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000241#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000242 }
243 catch (...)
244 {
245 for (unsigned i = 0; i < facets_.size(); ++i)
246 if (facets_[i])
247 facets_[i]->__release_shared();
248 throw;
249 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000250#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000251}
252
Howard Hinnant21772ec2012-12-28 18:15:01 +0000253// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000254// copy constructor` warning emitted by GCC
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000255#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000256#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000257#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000258#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000259
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000260locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000261 : facets_(max<size_t>(N, other.facets_.size())),
262 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000263{
264 facets_ = other.facets_;
265 for (unsigned i = 0; i < facets_.size(); ++i)
266 if (facets_[i])
267 facets_[i]->__add_shared();
268}
269
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000270#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000271#pragma GCC diagnostic pop
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000272#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000273
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000274locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000275 : facets_(N),
276 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000277{
278 facets_ = other.facets_;
279 for (unsigned i = 0; i < facets_.size(); ++i)
280 if (facets_[i])
281 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000282#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000283 try
284 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000285#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000286 if (c & locale::collate)
287 {
288 install(new collate_byname<char>(name));
289 install(new collate_byname<wchar_t>(name));
290 }
291 if (c & locale::ctype)
292 {
293 install(new ctype_byname<char>(name));
294 install(new ctype_byname<wchar_t>(name));
295 install(new codecvt_byname<char, char, mbstate_t>(name));
296 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
297 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
298 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
299 }
300 if (c & locale::monetary)
301 {
302 install(new moneypunct_byname<char, false>(name));
303 install(new moneypunct_byname<char, true>(name));
304 install(new moneypunct_byname<wchar_t, false>(name));
305 install(new moneypunct_byname<wchar_t, true>(name));
306 }
307 if (c & locale::numeric)
308 {
309 install(new numpunct_byname<char>(name));
310 install(new numpunct_byname<wchar_t>(name));
311 }
312 if (c & locale::time)
313 {
314 install(new time_get_byname<char>(name));
315 install(new time_get_byname<wchar_t>(name));
316 install(new time_put_byname<char>(name));
317 install(new time_put_byname<wchar_t>(name));
318 }
319 if (c & locale::messages)
320 {
321 install(new messages_byname<char>(name));
322 install(new messages_byname<wchar_t>(name));
323 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000324#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000325 }
326 catch (...)
327 {
328 for (unsigned i = 0; i < facets_.size(); ++i)
329 if (facets_[i])
330 facets_[i]->__release_shared();
331 throw;
332 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000333#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000334}
335
336template<class F>
337inline
338void
339locale::__imp::install_from(const locale::__imp& one)
340{
341 long id = F::id.__get();
342 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
343}
344
345locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000346 : facets_(N),
347 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000348{
349 facets_ = other.facets_;
350 for (unsigned i = 0; i < facets_.size(); ++i)
351 if (facets_[i])
352 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000353#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000354 try
355 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000356#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000357 if (c & locale::collate)
358 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000359 install_from<_VSTD::collate<char> >(one);
360 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000361 }
362 if (c & locale::ctype)
363 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000364 install_from<_VSTD::ctype<char> >(one);
365 install_from<_VSTD::ctype<wchar_t> >(one);
366 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
367 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
368 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
369 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000370 }
371 if (c & locale::monetary)
372 {
373 install_from<moneypunct<char, false> >(one);
374 install_from<moneypunct<char, true> >(one);
375 install_from<moneypunct<wchar_t, false> >(one);
376 install_from<moneypunct<wchar_t, true> >(one);
377 install_from<money_get<char> >(one);
378 install_from<money_get<wchar_t> >(one);
379 install_from<money_put<char> >(one);
380 install_from<money_put<wchar_t> >(one);
381 }
382 if (c & locale::numeric)
383 {
384 install_from<numpunct<char> >(one);
385 install_from<numpunct<wchar_t> >(one);
386 install_from<num_get<char> >(one);
387 install_from<num_get<wchar_t> >(one);
388 install_from<num_put<char> >(one);
389 install_from<num_put<wchar_t> >(one);
390 }
391 if (c & locale::time)
392 {
393 install_from<time_get<char> >(one);
394 install_from<time_get<wchar_t> >(one);
395 install_from<time_put<char> >(one);
396 install_from<time_put<wchar_t> >(one);
397 }
398 if (c & locale::messages)
399 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000400 install_from<_VSTD::messages<char> >(one);
401 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000402 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000403#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000404 }
405 catch (...)
406 {
407 for (unsigned i = 0; i < facets_.size(); ++i)
408 if (facets_[i])
409 facets_[i]->__release_shared();
410 throw;
411 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000412#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000413}
414
415locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000416 : facets_(max<size_t>(N, other.facets_.size()+1)),
417 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000418{
419 f->__add_shared();
420 unique_ptr<facet, release> hold(f);
421 facets_ = other.facets_;
422 for (unsigned i = 0; i < other.facets_.size(); ++i)
423 if (facets_[i])
424 facets_[i]->__add_shared();
425 install(hold.get(), id);
426}
427
428locale::__imp::~__imp()
429{
430 for (unsigned i = 0; i < facets_.size(); ++i)
431 if (facets_[i])
432 facets_[i]->__release_shared();
433}
434
435void
436locale::__imp::install(facet* f, long id)
437{
438 f->__add_shared();
439 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000440 if (static_cast<size_t>(id) >= facets_.size())
441 facets_.resize(static_cast<size_t>(id+1));
442 if (facets_[static_cast<size_t>(id)])
443 facets_[static_cast<size_t>(id)]->__release_shared();
444 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000445}
446
447const locale::facet*
448locale::__imp::use_facet(long id) const
449{
Howard Hinnantd4444702010-08-11 17:04:31 +0000450#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000451 if (!has_facet(id))
452 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000453#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000454 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000455}
456
457// locale
458
459const locale&
460locale::__imp::make_classic()
461{
462 // only one thread can get in here and it only gets in once
463 static aligned_storage<sizeof(locale)>::type buf;
464 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000465 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000466 return *c;
467}
468
469const locale&
470locale::classic()
471{
472 static const locale& c = __imp::make_classic();
473 return c;
474}
475
476locale&
477locale::__imp::make_global()
478{
479 // only one thread can get in here and it only gets in once
480 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000481 ::new (&buf) locale(locale::classic());
482 return *(locale*)&buf;
483}
484
485locale&
486locale::__global()
487{
488 static locale& g = __imp::make_global();
489 return g;
490}
491
Howard Hinnantc9834542011-05-31 15:34:58 +0000492locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000493 : __locale_(__global().__locale_)
494{
495 __locale_->__add_shared();
496}
497
Howard Hinnantc9834542011-05-31 15:34:58 +0000498locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000499 : __locale_(l.__locale_)
500{
501 __locale_->__add_shared();
502}
503
Howard Hinnantc9834542011-05-31 15:34:58 +0000504locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000505{
506 __locale_->__release_shared();
507}
508
509const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000510locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000511{
512 other.__locale_->__add_shared();
513 __locale_->__release_shared();
514 __locale_ = other.__locale_;
515 return *this;
516}
517
518locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000519#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000520 : __locale_(name ? new __imp(name)
521 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000522#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000523 : __locale_(new __imp(name))
524#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000525{
526 __locale_->__add_shared();
527}
528
529locale::locale(const string& name)
530 : __locale_(new __imp(name))
531{
532 __locale_->__add_shared();
533}
534
535locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000536#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000537 : __locale_(name ? new __imp(*other.__locale_, name, c)
538 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000539#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000540 : __locale_(new __imp(*other.__locale_, name, c))
541#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000542{
543 __locale_->__add_shared();
544}
545
546locale::locale(const locale& other, const string& name, category c)
547 : __locale_(new __imp(*other.__locale_, name, c))
548{
549 __locale_->__add_shared();
550}
551
552locale::locale(const locale& other, const locale& one, category c)
553 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
554{
555 __locale_->__add_shared();
556}
557
558string
559locale::name() const
560{
561 return __locale_->name();
562}
563
564void
565locale::__install_ctor(const locale& other, facet* f, long id)
566{
567 if (f)
568 __locale_ = new __imp(*other.__locale_, f, id);
569 else
570 __locale_ = other.__locale_;
571 __locale_->__add_shared();
572}
573
574locale
575locale::global(const locale& loc)
576{
577 locale& g = __global();
578 locale r = g;
579 g = loc;
580 if (g.name() != "*")
581 setlocale(LC_ALL, g.name().c_str());
582 return r;
583}
584
585bool
586locale::has_facet(id& x) const
587{
588 return __locale_->has_facet(x.__get());
589}
590
591const locale::facet*
592locale::use_facet(id& x) const
593{
594 return __locale_->use_facet(x.__get());
595}
596
597bool
598locale::operator==(const locale& y) const
599{
600 return (__locale_ == y.__locale_)
601 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
602}
603
604// locale::facet
605
606locale::facet::~facet()
607{
608}
609
610void
Howard Hinnant1694d232011-05-28 14:41:13 +0000611locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000612{
613 delete this;
614}
615
616// locale::id
617
618int32_t locale::id::__next_id = 0;
619
620namespace
621{
622
623class __fake_bind
624{
625 locale::id* id_;
626 void (locale::id::* pmf_)();
627public:
628 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
629 : id_(id), pmf_(pmf) {}
630
631 void operator()() const
632 {
633 (id_->*pmf_)();
634 }
635};
636
637}
638
639long
640locale::id::__get()
641{
642 call_once(__flag_, __fake_bind(&locale::id::__init, this));
643 return __id_ - 1;
644}
645
646void
647locale::id::__init()
648{
Howard Hinnantadff4892010-05-24 17:49:41 +0000649 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000650}
651
652// template <> class collate_byname<char>
653
654collate_byname<char>::collate_byname(const char* n, size_t refs)
655 : collate<char>(refs),
656 __l(newlocale(LC_ALL_MASK, n, 0))
657{
Howard Hinnantd4444702010-08-11 17:04:31 +0000658#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000659 if (__l == 0)
660 throw runtime_error("collate_byname<char>::collate_byname"
661 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000662#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000663}
664
665collate_byname<char>::collate_byname(const string& name, size_t refs)
666 : collate<char>(refs),
667 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
668{
Howard Hinnantd4444702010-08-11 17:04:31 +0000669#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000670 if (__l == 0)
671 throw runtime_error("collate_byname<char>::collate_byname"
672 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000673#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000674}
675
676collate_byname<char>::~collate_byname()
677{
678 freelocale(__l);
679}
680
681int
682collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
683 const char_type* __lo2, const char_type* __hi2) const
684{
685 string_type lhs(__lo1, __hi1);
686 string_type rhs(__lo2, __hi2);
687 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
688 if (r < 0)
689 return -1;
690 if (r > 0)
691 return 1;
692 return r;
693}
694
695collate_byname<char>::string_type
696collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
697{
698 const string_type in(lo, hi);
699 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
700 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
701 return out;
702}
703
704// template <> class collate_byname<wchar_t>
705
706collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
707 : collate<wchar_t>(refs),
708 __l(newlocale(LC_ALL_MASK, n, 0))
709{
Howard Hinnantd4444702010-08-11 17:04:31 +0000710#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000711 if (__l == 0)
712 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
713 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000714#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000715}
716
717collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
718 : collate<wchar_t>(refs),
719 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
720{
Howard Hinnantd4444702010-08-11 17:04:31 +0000721#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000722 if (__l == 0)
723 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
724 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000725#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000726}
727
728collate_byname<wchar_t>::~collate_byname()
729{
730 freelocale(__l);
731}
732
733int
734collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
735 const char_type* __lo2, const char_type* __hi2) const
736{
737 string_type lhs(__lo1, __hi1);
738 string_type rhs(__lo2, __hi2);
739 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
740 if (r < 0)
741 return -1;
742 if (r > 0)
743 return 1;
744 return r;
745}
746
747collate_byname<wchar_t>::string_type
748collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
749{
750 const string_type in(lo, hi);
751 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
752 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
753 return out;
754}
755
756// template <> class ctype<wchar_t>;
757
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000758const ctype_base::mask ctype_base::space;
759const ctype_base::mask ctype_base::print;
760const ctype_base::mask ctype_base::cntrl;
761const ctype_base::mask ctype_base::upper;
762const ctype_base::mask ctype_base::lower;
763const ctype_base::mask ctype_base::alpha;
764const ctype_base::mask ctype_base::digit;
765const ctype_base::mask ctype_base::punct;
766const ctype_base::mask ctype_base::xdigit;
767const ctype_base::mask ctype_base::blank;
768const ctype_base::mask ctype_base::alnum;
769const ctype_base::mask ctype_base::graph;
770
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000771locale::id ctype<wchar_t>::id;
772
773ctype<wchar_t>::~ctype()
774{
775}
776
777bool
778ctype<wchar_t>::do_is(mask m, char_type c) const
779{
Marshall Clowa3645132013-10-21 15:07:28 +0000780 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000781}
782
783const wchar_t*
784ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
785{
786 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000787 *vec = static_cast<mask>(isascii(*low) ?
788 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000789 return low;
790}
791
792const wchar_t*
793ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
794{
795 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000796 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000797 break;
798 return low;
799}
800
801const wchar_t*
802ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
803{
804 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000805 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000806 break;
807 return low;
808}
809
810wchar_t
811ctype<wchar_t>::do_toupper(char_type c) const
812{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000813#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
814 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000815#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000816 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000817#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000818 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000819#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000820}
821
822const wchar_t*
823ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
824{
825 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000826#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
827 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000828#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000829 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
830 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000831#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000832 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000833#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000834 return low;
835}
836
837wchar_t
838ctype<wchar_t>::do_tolower(char_type c) const
839{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000840#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
841 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000842#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000843 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000844#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000845 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000846#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000847}
848
849const wchar_t*
850ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
851{
852 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000853#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
854 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000855#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000856 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
857 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000858#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000859 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000860#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000861 return low;
862}
863
864wchar_t
865ctype<wchar_t>::do_widen(char c) const
866{
867 return c;
868}
869
870const char*
871ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
872{
873 for (; low != high; ++low, ++dest)
874 *dest = *low;
875 return low;
876}
877
878char
879ctype<wchar_t>::do_narrow(char_type c, char dfault) const
880{
881 if (isascii(c))
882 return static_cast<char>(c);
883 return dfault;
884}
885
886const wchar_t*
887ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
888{
889 for (; low != high; ++low, ++dest)
890 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000891 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000892 else
893 *dest = dfault;
894 return low;
895}
896
897// template <> class ctype<char>;
898
899locale::id ctype<char>::id;
900
901ctype<char>::ctype(const mask* tab, bool del, size_t refs)
902 : locale::facet(refs),
903 __tab_(tab),
904 __del_(del)
905{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000906 if (__tab_ == 0)
907 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000908}
909
910ctype<char>::~ctype()
911{
912 if (__tab_ && __del_)
913 delete [] __tab_;
914}
915
916char
917ctype<char>::do_toupper(char_type c) const
918{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000919#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000920 return isascii(c) ?
921 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000922#elif defined(__NetBSD__)
923 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000924#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000925 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000926 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000927#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000928 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000929#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000930}
931
932const char*
933ctype<char>::do_toupper(char_type* low, const char_type* high) const
934{
935 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000936#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000937 *low = isascii(*low) ?
938 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000939#elif defined(__NetBSD__)
940 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000941#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000942 *low = isascii(*low) ?
943 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000944#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000945 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000946#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000947 return low;
948}
949
950char
951ctype<char>::do_tolower(char_type c) const
952{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000953#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000954 return isascii(c) ?
955 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000956#elif defined(__NetBSD__)
957 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
958#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Marshall Clow88c31902013-02-07 14:22:51 +0000959 return isascii(c) ?
960 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000961#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000962 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000963#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000964}
965
966const char*
967ctype<char>::do_tolower(char_type* low, const char_type* high) const
968{
969 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000970#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000971 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000972#elif defined(__NetBSD__)
973 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000974#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000975 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000976#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000977 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000978#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000979 return low;
980}
981
982char
983ctype<char>::do_widen(char c) const
984{
985 return c;
986}
987
988const char*
989ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
990{
991 for (; low != high; ++low, ++dest)
992 *dest = *low;
993 return low;
994}
995
996char
997ctype<char>::do_narrow(char_type c, char dfault) const
998{
999 if (isascii(c))
1000 return static_cast<char>(c);
1001 return dfault;
1002}
1003
1004const char*
1005ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1006{
1007 for (; low != high; ++low, ++dest)
1008 if (isascii(*low))
1009 *dest = *low;
1010 else
1011 *dest = dfault;
1012 return low;
1013}
1014
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001015#ifdef EMSCRIPTEN
1016extern "C" const unsigned short ** __ctype_b_loc();
1017extern "C" const int ** __ctype_tolower_loc();
1018extern "C" const int ** __ctype_toupper_loc();
1019#endif
1020
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001021const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001022ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001023{
David Chisnallc512df12011-09-21 08:39:44 +00001024#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001026#elif defined(__NetBSD__)
1027 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001028#elif defined(__GLIBC__)
1029 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001030#elif __sun__
1031 return __ctype_mask;
Howard Hinnantef5aa932013-09-17 01:34:47 +00001032#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001033 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001034// This is assumed to be safe, which is a nonsense assumption because we're
1035// going to end up dereferencing it later...
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001036#elif defined(EMSCRIPTEN)
1037 return *__ctype_b_loc();
Howard Hinnant7f764502013-08-14 18:00:20 +00001038#elif defined(_AIX)
1039 return (const unsigned long *)__lc_ctype_ptr->obj->mask;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001040#else
David Chisnall997e4542012-02-29 13:05:08 +00001041 // Platform not supported: abort so the person doing the port knows what to
1042 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001043# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001044 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001045 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001046 return NULL;
1047#endif
1048}
1049
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001050#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001051const int*
1052ctype<char>::__classic_lower_table() _NOEXCEPT
1053{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001054 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001055}
1056
1057const int*
1058ctype<char>::__classic_upper_table() _NOEXCEPT
1059{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001060 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001061}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001062#elif __NetBSD__
1063const short*
1064ctype<char>::__classic_lower_table() _NOEXCEPT
1065{
1066 return _C_tolower_tab_ + 1;
1067}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001068
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001069const short*
1070ctype<char>::__classic_upper_table() _NOEXCEPT
1071{
1072 return _C_toupper_tab_ + 1;
1073}
1074
1075#elif defined(EMSCRIPTEN)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001076const int*
1077ctype<char>::__classic_lower_table() _NOEXCEPT
1078{
1079 return *__ctype_tolower_loc();
1080}
1081
1082const int*
1083ctype<char>::__classic_upper_table() _NOEXCEPT
1084{
1085 return *__ctype_toupper_loc();
1086}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001087#endif // __GLIBC__ || EMSCRIPTEN || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001088
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001089// template <> class ctype_byname<char>
1090
1091ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1092 : ctype<char>(0, false, refs),
1093 __l(newlocale(LC_ALL_MASK, name, 0))
1094{
Howard Hinnantd4444702010-08-11 17:04:31 +00001095#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001096 if (__l == 0)
1097 throw runtime_error("ctype_byname<char>::ctype_byname"
1098 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001099#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001100}
1101
1102ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1103 : ctype<char>(0, false, refs),
1104 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1105{
Howard Hinnantd4444702010-08-11 17:04:31 +00001106#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001107 if (__l == 0)
1108 throw runtime_error("ctype_byname<char>::ctype_byname"
1109 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001110#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001111}
1112
1113ctype_byname<char>::~ctype_byname()
1114{
1115 freelocale(__l);
1116}
1117
1118char
1119ctype_byname<char>::do_toupper(char_type c) const
1120{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001121 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001122}
1123
1124const char*
1125ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1126{
1127 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001128 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001129 return low;
1130}
1131
1132char
1133ctype_byname<char>::do_tolower(char_type c) const
1134{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001135 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001136}
1137
1138const char*
1139ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1140{
1141 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001142 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001143 return low;
1144}
1145
1146// template <> class ctype_byname<wchar_t>
1147
1148ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1149 : ctype<wchar_t>(refs),
1150 __l(newlocale(LC_ALL_MASK, name, 0))
1151{
Howard Hinnantd4444702010-08-11 17:04:31 +00001152#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001153 if (__l == 0)
1154 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1155 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001156#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001157}
1158
1159ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1160 : ctype<wchar_t>(refs),
1161 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1162{
Howard Hinnantd4444702010-08-11 17:04:31 +00001163#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001164 if (__l == 0)
1165 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1166 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001167#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001168}
1169
1170ctype_byname<wchar_t>::~ctype_byname()
1171{
1172 freelocale(__l);
1173}
1174
1175bool
1176ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1177{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001178#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001179 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001180#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001181 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001182 wint_t ch = static_cast<wint_t>(c);
1183 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1184 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1185 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1186 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1187 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1188 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1189 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1190 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1191 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1192 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001193 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001194#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001195}
1196
1197const wchar_t*
1198ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1199{
1200 for (; low != high; ++low, ++vec)
1201 {
1202 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001203 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001204 else
1205 {
1206 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001207 wint_t ch = static_cast<wint_t>(*low);
1208 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001209 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001210 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001211 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001212 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001213 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001214 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001215 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001216 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001217 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001218 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001219 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001220 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001221 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001222 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001223 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001224 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001225 *vec |= xdigit;
1226 }
1227 }
1228 return low;
1229}
1230
1231const wchar_t*
1232ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1233{
1234 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001235 {
1236#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001237 if (iswctype_l(*low, m, __l))
1238 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001239#else
Marshall Clow88c31902013-02-07 14:22:51 +00001240 wint_t ch = static_cast<wint_t>(*low);
1241 if (m & space && iswspace_l(ch, __l)) break;
1242 if (m & print && iswprint_l(ch, __l)) break;
1243 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1244 if (m & upper && iswupper_l(ch, __l)) break;
1245 if (m & lower && iswlower_l(ch, __l)) break;
1246 if (m & alpha && iswalpha_l(ch, __l)) break;
1247 if (m & digit && iswdigit_l(ch, __l)) break;
1248 if (m & punct && iswpunct_l(ch, __l)) break;
1249 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1250 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001251#endif
1252 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001253 return low;
1254}
1255
1256const wchar_t*
1257ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1258{
1259 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001260 {
1261#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001262 if (!iswctype_l(*low, m, __l))
1263 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001264#else
Marshall Clow88c31902013-02-07 14:22:51 +00001265 wint_t ch = static_cast<wint_t>(*low);
1266 if (m & space && iswspace_l(ch, __l)) continue;
1267 if (m & print && iswprint_l(ch, __l)) continue;
1268 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1269 if (m & upper && iswupper_l(ch, __l)) continue;
1270 if (m & lower && iswlower_l(ch, __l)) continue;
1271 if (m & alpha && iswalpha_l(ch, __l)) continue;
1272 if (m & digit && iswdigit_l(ch, __l)) continue;
1273 if (m & punct && iswpunct_l(ch, __l)) continue;
1274 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1275 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001276 break;
1277#endif
1278 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001279 return low;
1280}
1281
1282wchar_t
1283ctype_byname<wchar_t>::do_toupper(char_type c) const
1284{
1285 return towupper_l(c, __l);
1286}
1287
1288const wchar_t*
1289ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1290{
1291 for (; low != high; ++low)
1292 *low = towupper_l(*low, __l);
1293 return low;
1294}
1295
1296wchar_t
1297ctype_byname<wchar_t>::do_tolower(char_type c) const
1298{
1299 return towlower_l(c, __l);
1300}
1301
1302const wchar_t*
1303ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1304{
1305 for (; low != high; ++low)
1306 *low = towlower_l(*low, __l);
1307 return low;
1308}
1309
1310wchar_t
1311ctype_byname<wchar_t>::do_widen(char c) const
1312{
Howard Hinnant866569b2011-09-28 23:39:33 +00001313#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001314 return btowc_l(c, __l);
1315#else
1316 return __btowc_l(c, __l);
1317#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001318}
1319
1320const char*
1321ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1322{
1323 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001324#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001325 *dest = btowc_l(*low, __l);
1326#else
1327 *dest = __btowc_l(*low, __l);
1328#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001329 return low;
1330}
1331
1332char
1333ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1334{
Howard Hinnant866569b2011-09-28 23:39:33 +00001335#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001336 int r = wctob_l(c, __l);
1337#else
1338 int r = __wctob_l(c, __l);
1339#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001340 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001341}
1342
1343const wchar_t*
1344ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1345{
1346 for (; low != high; ++low, ++dest)
1347 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001348#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001349 int r = wctob_l(*low, __l);
1350#else
1351 int r = __wctob_l(*low, __l);
1352#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001353 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001354 }
1355 return low;
1356}
1357
1358// template <> class codecvt<char, char, mbstate_t>
1359
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001360locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001361
1362codecvt<char, char, mbstate_t>::~codecvt()
1363{
1364}
1365
1366codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001367codecvt<char, char, mbstate_t>::do_out(state_type&,
1368 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001369 extern_type* to, extern_type*, extern_type*& to_nxt) const
1370{
1371 frm_nxt = frm;
1372 to_nxt = to;
1373 return noconv;
1374}
1375
1376codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001377codecvt<char, char, mbstate_t>::do_in(state_type&,
1378 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001379 intern_type* to, intern_type*, intern_type*& to_nxt) const
1380{
1381 frm_nxt = frm;
1382 to_nxt = to;
1383 return noconv;
1384}
1385
1386codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001387codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001388 extern_type* to, extern_type*, extern_type*& to_nxt) const
1389{
1390 to_nxt = to;
1391 return noconv;
1392}
1393
1394int
Howard Hinnantc9834542011-05-31 15:34:58 +00001395codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001396{
1397 return 1;
1398}
1399
1400bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001401codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001402{
1403 return true;
1404}
1405
1406int
1407codecvt<char, char, mbstate_t>::do_length(state_type&,
1408 const extern_type* frm, const extern_type* end, size_t mx) const
1409{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001410 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001411}
1412
1413int
Howard Hinnantc9834542011-05-31 15:34:58 +00001414codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001415{
1416 return 1;
1417}
1418
1419// template <> class codecvt<wchar_t, char, mbstate_t>
1420
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001421locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001422
1423codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1424 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001425 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001426{
1427}
1428
1429codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1430 : locale::facet(refs),
1431 __l(newlocale(LC_ALL_MASK, nm, 0))
1432{
Howard Hinnantd4444702010-08-11 17:04:31 +00001433#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001434 if (__l == 0)
1435 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1436 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001437#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001438}
1439
1440codecvt<wchar_t, char, mbstate_t>::~codecvt()
1441{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001442 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001443 freelocale(__l);
1444}
1445
1446codecvt<wchar_t, char, mbstate_t>::result
1447codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001448 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001449 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1450{
1451 // look for first internal null in frm
1452 const intern_type* fend = frm;
1453 for (; fend != frm_end; ++fend)
1454 if (*fend == 0)
1455 break;
1456 // loop over all null-terminated sequences in frm
1457 to_nxt = to;
1458 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1459 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001460 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001461 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001462#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001463 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1464 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001465#else
1466 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1467#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001468 if (n == size_t(-1))
1469 {
1470 // need to recover to_nxt
1471 for (to_nxt = to; frm != frm_nxt; ++frm)
1472 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001473#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001474 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1475#else
1476 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1477#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001478 if (n == size_t(-1))
1479 break;
1480 to_nxt += n;
1481 }
1482 frm_nxt = frm;
1483 return error;
1484 }
1485 if (n == 0)
1486 return partial;
1487 to_nxt += n;
1488 if (to_nxt == to_end)
1489 break;
1490 if (fend != frm_end) // set up next null terminated sequence
1491 {
1492 // Try to write the terminating null
1493 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001494#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001495 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1496#else
1497 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1498#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001499 if (n == size_t(-1)) // on error
1500 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001501 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001502 return partial;
1503 for (extern_type* p = tmp; n; --n) // write it
1504 *to_nxt++ = *p++;
1505 ++frm_nxt;
1506 // look for next null in frm
1507 for (fend = frm_nxt; fend != frm_end; ++fend)
1508 if (*fend == 0)
1509 break;
1510 }
1511 }
1512 return frm_nxt == frm_end ? ok : partial;
1513}
1514
1515codecvt<wchar_t, char, mbstate_t>::result
1516codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001517 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001518 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1519{
1520 // look for first internal null in frm
1521 const extern_type* fend = frm;
1522 for (; fend != frm_end; ++fend)
1523 if (*fend == 0)
1524 break;
1525 // loop over all null-terminated sequences in frm
1526 to_nxt = to;
1527 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1528 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001529 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001530 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001531#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001532 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1533 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001534#else
1535 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1536#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001537 if (n == size_t(-1))
1538 {
1539 // need to recover to_nxt
1540 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1541 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001542#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001543 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1544 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001545#else
1546 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1547#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001548 switch (n)
1549 {
1550 case 0:
1551 ++frm;
1552 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001553 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001554 frm_nxt = frm;
1555 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001556 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001557 frm_nxt = frm;
1558 return partial;
1559 default:
1560 frm += n;
1561 break;
1562 }
1563 }
1564 frm_nxt = frm;
1565 return frm_nxt == frm_end ? ok : partial;
1566 }
1567 if (n == 0)
1568 return error;
1569 to_nxt += n;
1570 if (to_nxt == to_end)
1571 break;
1572 if (fend != frm_end) // set up next null terminated sequence
1573 {
1574 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001575#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001576 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1577#else
1578 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1579#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001580 if (n != 0) // on error
1581 return error;
1582 ++to_nxt;
1583 ++frm_nxt;
1584 // look for next null in frm
1585 for (fend = frm_nxt; fend != frm_end; ++fend)
1586 if (*fend == 0)
1587 break;
1588 }
1589 }
1590 return frm_nxt == frm_end ? ok : partial;
1591}
1592
1593codecvt<wchar_t, char, mbstate_t>::result
1594codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1595 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1596{
1597 to_nxt = to;
1598 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001599#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001600 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1601#else
1602 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1603#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001604 if (n == size_t(-1) || n == 0) // on error
1605 return error;
1606 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001607 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001608 return partial;
1609 for (extern_type* p = tmp; n; --n) // write it
1610 *to_nxt++ = *p++;
1611 return ok;
1612}
1613
1614int
Howard Hinnantc9834542011-05-31 15:34:58 +00001615codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001616{
Howard Hinnant866569b2011-09-28 23:39:33 +00001617#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001618 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1619#else
1620 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1621#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001622 {
1623 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001624#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001625 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1626#else
1627 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1628#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001629 return 1; // which take more than 1 char to form a wchar_t
1630 return 0;
1631 }
1632 return -1;
1633}
1634
1635bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001636codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001637{
1638 return false;
1639}
1640
1641int
1642codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1643 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1644{
1645 int nbytes = 0;
1646 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1647 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001648#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001649 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001650#else
1651 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1652#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001653 switch (n)
1654 {
1655 case 0:
1656 ++nbytes;
1657 ++frm;
1658 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001659 case size_t(-1):
1660 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001661 return nbytes;
1662 default:
1663 nbytes += n;
1664 frm += n;
1665 break;
1666 }
1667 }
1668 return nbytes;
1669}
1670
1671int
Howard Hinnantc9834542011-05-31 15:34:58 +00001672codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001673{
Howard Hinnant866569b2011-09-28 23:39:33 +00001674#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001675 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001676#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001677 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001678#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001679}
1680
1681// Valid UTF ranges
1682// UTF-32 UTF-16 UTF-8 # of code points
1683// first second first second third fourth
1684// 000000 - 00007F 0000 - 007F 00 - 7F 127
1685// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1686// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1687// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1688// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1689// 00D800 - 00DFFF invalid
1690// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1691// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1692// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1693// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1694
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001695static
1696codecvt_base::result
1697utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1698 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1699 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1700{
1701 frm_nxt = frm;
1702 to_nxt = to;
1703 if (mode & generate_header)
1704 {
1705 if (to_end-to_nxt < 3)
1706 return codecvt_base::partial;
1707 *to_nxt++ = static_cast<uint8_t>(0xEF);
1708 *to_nxt++ = static_cast<uint8_t>(0xBB);
1709 *to_nxt++ = static_cast<uint8_t>(0xBF);
1710 }
1711 for (; frm_nxt < frm_end; ++frm_nxt)
1712 {
1713 uint16_t wc1 = *frm_nxt;
1714 if (wc1 > Maxcode)
1715 return codecvt_base::error;
1716 if (wc1 < 0x0080)
1717 {
1718 if (to_end-to_nxt < 1)
1719 return codecvt_base::partial;
1720 *to_nxt++ = static_cast<uint8_t>(wc1);
1721 }
1722 else if (wc1 < 0x0800)
1723 {
1724 if (to_end-to_nxt < 2)
1725 return codecvt_base::partial;
1726 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1727 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1728 }
1729 else if (wc1 < 0xD800)
1730 {
1731 if (to_end-to_nxt < 3)
1732 return codecvt_base::partial;
1733 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1734 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1735 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1736 }
1737 else if (wc1 < 0xDC00)
1738 {
1739 if (frm_end-frm_nxt < 2)
1740 return codecvt_base::partial;
1741 uint16_t wc2 = frm_nxt[1];
1742 if ((wc2 & 0xFC00) != 0xDC00)
1743 return codecvt_base::error;
1744 if (to_end-to_nxt < 4)
1745 return codecvt_base::partial;
1746 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1747 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1748 return codecvt_base::error;
1749 ++frm_nxt;
1750 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1751 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1752 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1753 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1754 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1755 }
1756 else if (wc1 < 0xE000)
1757 {
1758 return codecvt_base::error;
1759 }
1760 else
1761 {
1762 if (to_end-to_nxt < 3)
1763 return codecvt_base::partial;
1764 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1765 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1766 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1767 }
1768 }
1769 return codecvt_base::ok;
1770}
1771
1772static
1773codecvt_base::result
1774utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1775 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1776 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1777{
1778 frm_nxt = frm;
1779 to_nxt = to;
1780 if (mode & generate_header)
1781 {
1782 if (to_end-to_nxt < 3)
1783 return codecvt_base::partial;
1784 *to_nxt++ = static_cast<uint8_t>(0xEF);
1785 *to_nxt++ = static_cast<uint8_t>(0xBB);
1786 *to_nxt++ = static_cast<uint8_t>(0xBF);
1787 }
1788 for (; frm_nxt < frm_end; ++frm_nxt)
1789 {
1790 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1791 if (wc1 > Maxcode)
1792 return codecvt_base::error;
1793 if (wc1 < 0x0080)
1794 {
1795 if (to_end-to_nxt < 1)
1796 return codecvt_base::partial;
1797 *to_nxt++ = static_cast<uint8_t>(wc1);
1798 }
1799 else if (wc1 < 0x0800)
1800 {
1801 if (to_end-to_nxt < 2)
1802 return codecvt_base::partial;
1803 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1804 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1805 }
1806 else if (wc1 < 0xD800)
1807 {
1808 if (to_end-to_nxt < 3)
1809 return codecvt_base::partial;
1810 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1811 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1812 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1813 }
1814 else if (wc1 < 0xDC00)
1815 {
1816 if (frm_end-frm_nxt < 2)
1817 return codecvt_base::partial;
1818 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1819 if ((wc2 & 0xFC00) != 0xDC00)
1820 return codecvt_base::error;
1821 if (to_end-to_nxt < 4)
1822 return codecvt_base::partial;
1823 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1824 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1825 return codecvt_base::error;
1826 ++frm_nxt;
1827 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1828 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1829 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1830 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1831 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1832 }
1833 else if (wc1 < 0xE000)
1834 {
1835 return codecvt_base::error;
1836 }
1837 else
1838 {
1839 if (to_end-to_nxt < 3)
1840 return codecvt_base::partial;
1841 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1842 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1843 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1844 }
1845 }
1846 return codecvt_base::ok;
1847}
1848
1849static
1850codecvt_base::result
1851utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1852 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1853 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1854{
1855 frm_nxt = frm;
1856 to_nxt = to;
1857 if (mode & consume_header)
1858 {
1859 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1860 frm_nxt[2] == 0xBF)
1861 frm_nxt += 3;
1862 }
1863 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1864 {
1865 uint8_t c1 = *frm_nxt;
1866 if (c1 > Maxcode)
1867 return codecvt_base::error;
1868 if (c1 < 0x80)
1869 {
1870 *to_nxt = static_cast<uint16_t>(c1);
1871 ++frm_nxt;
1872 }
1873 else if (c1 < 0xC2)
1874 {
1875 return codecvt_base::error;
1876 }
1877 else if (c1 < 0xE0)
1878 {
1879 if (frm_end-frm_nxt < 2)
1880 return codecvt_base::partial;
1881 uint8_t c2 = frm_nxt[1];
1882 if ((c2 & 0xC0) != 0x80)
1883 return codecvt_base::error;
1884 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1885 if (t > Maxcode)
1886 return codecvt_base::error;
1887 *to_nxt = t;
1888 frm_nxt += 2;
1889 }
1890 else if (c1 < 0xF0)
1891 {
1892 if (frm_end-frm_nxt < 3)
1893 return codecvt_base::partial;
1894 uint8_t c2 = frm_nxt[1];
1895 uint8_t c3 = frm_nxt[2];
1896 switch (c1)
1897 {
1898 case 0xE0:
1899 if ((c2 & 0xE0) != 0xA0)
1900 return codecvt_base::error;
1901 break;
1902 case 0xED:
1903 if ((c2 & 0xE0) != 0x80)
1904 return codecvt_base::error;
1905 break;
1906 default:
1907 if ((c2 & 0xC0) != 0x80)
1908 return codecvt_base::error;
1909 break;
1910 }
1911 if ((c3 & 0xC0) != 0x80)
1912 return codecvt_base::error;
1913 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1914 | ((c2 & 0x3F) << 6)
1915 | (c3 & 0x3F));
1916 if (t > Maxcode)
1917 return codecvt_base::error;
1918 *to_nxt = t;
1919 frm_nxt += 3;
1920 }
1921 else if (c1 < 0xF5)
1922 {
1923 if (frm_end-frm_nxt < 4)
1924 return codecvt_base::partial;
1925 uint8_t c2 = frm_nxt[1];
1926 uint8_t c3 = frm_nxt[2];
1927 uint8_t c4 = frm_nxt[3];
1928 switch (c1)
1929 {
1930 case 0xF0:
1931 if (!(0x90 <= c2 && c2 <= 0xBF))
1932 return codecvt_base::error;
1933 break;
1934 case 0xF4:
1935 if ((c2 & 0xF0) != 0x80)
1936 return codecvt_base::error;
1937 break;
1938 default:
1939 if ((c2 & 0xC0) != 0x80)
1940 return codecvt_base::error;
1941 break;
1942 }
1943 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1944 return codecvt_base::error;
1945 if (to_end-to_nxt < 2)
1946 return codecvt_base::partial;
1947 if (((((unsigned long)c1 & 7) << 18) +
1948 (((unsigned long)c2 & 0x3F) << 12) +
1949 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1950 return codecvt_base::error;
1951 *to_nxt = static_cast<uint16_t>(
1952 0xD800
1953 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1954 | ((c2 & 0x0F) << 2)
1955 | ((c3 & 0x30) >> 4));
1956 *++to_nxt = static_cast<uint16_t>(
1957 0xDC00
1958 | ((c3 & 0x0F) << 6)
1959 | (c4 & 0x3F));
1960 frm_nxt += 4;
1961 }
1962 else
1963 {
1964 return codecvt_base::error;
1965 }
1966 }
1967 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1968}
1969
1970static
1971codecvt_base::result
1972utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1973 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1974 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1975{
1976 frm_nxt = frm;
1977 to_nxt = to;
1978 if (mode & consume_header)
1979 {
1980 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1981 frm_nxt[2] == 0xBF)
1982 frm_nxt += 3;
1983 }
1984 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1985 {
1986 uint8_t c1 = *frm_nxt;
1987 if (c1 > Maxcode)
1988 return codecvt_base::error;
1989 if (c1 < 0x80)
1990 {
1991 *to_nxt = static_cast<uint32_t>(c1);
1992 ++frm_nxt;
1993 }
1994 else if (c1 < 0xC2)
1995 {
1996 return codecvt_base::error;
1997 }
1998 else if (c1 < 0xE0)
1999 {
2000 if (frm_end-frm_nxt < 2)
2001 return codecvt_base::partial;
2002 uint8_t c2 = frm_nxt[1];
2003 if ((c2 & 0xC0) != 0x80)
2004 return codecvt_base::error;
2005 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2006 if (t > Maxcode)
2007 return codecvt_base::error;
2008 *to_nxt = static_cast<uint32_t>(t);
2009 frm_nxt += 2;
2010 }
2011 else if (c1 < 0xF0)
2012 {
2013 if (frm_end-frm_nxt < 3)
2014 return codecvt_base::partial;
2015 uint8_t c2 = frm_nxt[1];
2016 uint8_t c3 = frm_nxt[2];
2017 switch (c1)
2018 {
2019 case 0xE0:
2020 if ((c2 & 0xE0) != 0xA0)
2021 return codecvt_base::error;
2022 break;
2023 case 0xED:
2024 if ((c2 & 0xE0) != 0x80)
2025 return codecvt_base::error;
2026 break;
2027 default:
2028 if ((c2 & 0xC0) != 0x80)
2029 return codecvt_base::error;
2030 break;
2031 }
2032 if ((c3 & 0xC0) != 0x80)
2033 return codecvt_base::error;
2034 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2035 | ((c2 & 0x3F) << 6)
2036 | (c3 & 0x3F));
2037 if (t > Maxcode)
2038 return codecvt_base::error;
2039 *to_nxt = static_cast<uint32_t>(t);
2040 frm_nxt += 3;
2041 }
2042 else if (c1 < 0xF5)
2043 {
2044 if (frm_end-frm_nxt < 4)
2045 return codecvt_base::partial;
2046 uint8_t c2 = frm_nxt[1];
2047 uint8_t c3 = frm_nxt[2];
2048 uint8_t c4 = frm_nxt[3];
2049 switch (c1)
2050 {
2051 case 0xF0:
2052 if (!(0x90 <= c2 && c2 <= 0xBF))
2053 return codecvt_base::error;
2054 break;
2055 case 0xF4:
2056 if ((c2 & 0xF0) != 0x80)
2057 return codecvt_base::error;
2058 break;
2059 default:
2060 if ((c2 & 0xC0) != 0x80)
2061 return codecvt_base::error;
2062 break;
2063 }
2064 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2065 return codecvt_base::error;
2066 if (to_end-to_nxt < 2)
2067 return codecvt_base::partial;
2068 if (((((unsigned long)c1 & 7) << 18) +
2069 (((unsigned long)c2 & 0x3F) << 12) +
2070 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2071 return codecvt_base::error;
2072 *to_nxt = static_cast<uint32_t>(
2073 0xD800
2074 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2075 | ((c2 & 0x0F) << 2)
2076 | ((c3 & 0x30) >> 4));
2077 *++to_nxt = static_cast<uint32_t>(
2078 0xDC00
2079 | ((c3 & 0x0F) << 6)
2080 | (c4 & 0x3F));
2081 frm_nxt += 4;
2082 }
2083 else
2084 {
2085 return codecvt_base::error;
2086 }
2087 }
2088 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2089}
2090
2091static
2092int
2093utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2094 size_t mx, unsigned long Maxcode = 0x10FFFF,
2095 codecvt_mode mode = codecvt_mode(0))
2096{
2097 const uint8_t* frm_nxt = frm;
2098 if (mode & consume_header)
2099 {
2100 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2101 frm_nxt[2] == 0xBF)
2102 frm_nxt += 3;
2103 }
2104 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2105 {
2106 uint8_t c1 = *frm_nxt;
2107 if (c1 > Maxcode)
2108 break;
2109 if (c1 < 0x80)
2110 {
2111 ++frm_nxt;
2112 }
2113 else if (c1 < 0xC2)
2114 {
2115 break;
2116 }
2117 else if (c1 < 0xE0)
2118 {
2119 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2120 break;
2121 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2122 if (t > Maxcode)
2123 break;
2124 frm_nxt += 2;
2125 }
2126 else if (c1 < 0xF0)
2127 {
2128 if (frm_end-frm_nxt < 3)
2129 break;
2130 uint8_t c2 = frm_nxt[1];
2131 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002132 switch (c1)
2133 {
2134 case 0xE0:
2135 if ((c2 & 0xE0) != 0xA0)
2136 return static_cast<int>(frm_nxt - frm);
2137 break;
2138 case 0xED:
2139 if ((c2 & 0xE0) != 0x80)
2140 return static_cast<int>(frm_nxt - frm);
2141 break;
2142 default:
2143 if ((c2 & 0xC0) != 0x80)
2144 return static_cast<int>(frm_nxt - frm);
2145 break;
2146 }
2147 if ((c3 & 0xC0) != 0x80)
2148 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002149 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002150 break;
2151 frm_nxt += 3;
2152 }
2153 else if (c1 < 0xF5)
2154 {
2155 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2156 break;
2157 uint8_t c2 = frm_nxt[1];
2158 uint8_t c3 = frm_nxt[2];
2159 uint8_t c4 = frm_nxt[3];
2160 switch (c1)
2161 {
2162 case 0xF0:
2163 if (!(0x90 <= c2 && c2 <= 0xBF))
2164 return static_cast<int>(frm_nxt - frm);
2165 break;
2166 case 0xF4:
2167 if ((c2 & 0xF0) != 0x80)
2168 return static_cast<int>(frm_nxt - frm);
2169 break;
2170 default:
2171 if ((c2 & 0xC0) != 0x80)
2172 return static_cast<int>(frm_nxt - frm);
2173 break;
2174 }
2175 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2176 break;
2177 if (((((unsigned long)c1 & 7) << 18) +
2178 (((unsigned long)c2 & 0x3F) << 12) +
2179 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2180 break;
2181 ++nchar16_t;
2182 frm_nxt += 4;
2183 }
2184 else
2185 {
2186 break;
2187 }
2188 }
2189 return static_cast<int>(frm_nxt - frm);
2190}
2191
2192static
2193codecvt_base::result
2194ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2195 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2196 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2197{
2198 frm_nxt = frm;
2199 to_nxt = to;
2200 if (mode & generate_header)
2201 {
2202 if (to_end-to_nxt < 3)
2203 return codecvt_base::partial;
2204 *to_nxt++ = static_cast<uint8_t>(0xEF);
2205 *to_nxt++ = static_cast<uint8_t>(0xBB);
2206 *to_nxt++ = static_cast<uint8_t>(0xBF);
2207 }
2208 for (; frm_nxt < frm_end; ++frm_nxt)
2209 {
2210 uint32_t wc = *frm_nxt;
2211 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2212 return codecvt_base::error;
2213 if (wc < 0x000080)
2214 {
2215 if (to_end-to_nxt < 1)
2216 return codecvt_base::partial;
2217 *to_nxt++ = static_cast<uint8_t>(wc);
2218 }
2219 else if (wc < 0x000800)
2220 {
2221 if (to_end-to_nxt < 2)
2222 return codecvt_base::partial;
2223 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2224 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2225 }
2226 else if (wc < 0x010000)
2227 {
2228 if (to_end-to_nxt < 3)
2229 return codecvt_base::partial;
2230 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2231 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2232 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2233 }
2234 else // if (wc < 0x110000)
2235 {
2236 if (to_end-to_nxt < 4)
2237 return codecvt_base::partial;
2238 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2239 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2240 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2241 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2242 }
2243 }
2244 return codecvt_base::ok;
2245}
2246
2247static
2248codecvt_base::result
2249utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2250 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2251 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2252{
2253 frm_nxt = frm;
2254 to_nxt = to;
2255 if (mode & consume_header)
2256 {
2257 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2258 frm_nxt[2] == 0xBF)
2259 frm_nxt += 3;
2260 }
2261 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2262 {
2263 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2264 if (c1 < 0x80)
2265 {
2266 if (c1 > Maxcode)
2267 return codecvt_base::error;
2268 *to_nxt = static_cast<uint32_t>(c1);
2269 ++frm_nxt;
2270 }
2271 else if (c1 < 0xC2)
2272 {
2273 return codecvt_base::error;
2274 }
2275 else if (c1 < 0xE0)
2276 {
2277 if (frm_end-frm_nxt < 2)
2278 return codecvt_base::partial;
2279 uint8_t c2 = frm_nxt[1];
2280 if ((c2 & 0xC0) != 0x80)
2281 return codecvt_base::error;
2282 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2283 | (c2 & 0x3F));
2284 if (t > Maxcode)
2285 return codecvt_base::error;
2286 *to_nxt = t;
2287 frm_nxt += 2;
2288 }
2289 else if (c1 < 0xF0)
2290 {
2291 if (frm_end-frm_nxt < 3)
2292 return codecvt_base::partial;
2293 uint8_t c2 = frm_nxt[1];
2294 uint8_t c3 = frm_nxt[2];
2295 switch (c1)
2296 {
2297 case 0xE0:
2298 if ((c2 & 0xE0) != 0xA0)
2299 return codecvt_base::error;
2300 break;
2301 case 0xED:
2302 if ((c2 & 0xE0) != 0x80)
2303 return codecvt_base::error;
2304 break;
2305 default:
2306 if ((c2 & 0xC0) != 0x80)
2307 return codecvt_base::error;
2308 break;
2309 }
2310 if ((c3 & 0xC0) != 0x80)
2311 return codecvt_base::error;
2312 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2313 | ((c2 & 0x3F) << 6)
2314 | (c3 & 0x3F));
2315 if (t > Maxcode)
2316 return codecvt_base::error;
2317 *to_nxt = t;
2318 frm_nxt += 3;
2319 }
2320 else if (c1 < 0xF5)
2321 {
2322 if (frm_end-frm_nxt < 4)
2323 return codecvt_base::partial;
2324 uint8_t c2 = frm_nxt[1];
2325 uint8_t c3 = frm_nxt[2];
2326 uint8_t c4 = frm_nxt[3];
2327 switch (c1)
2328 {
2329 case 0xF0:
2330 if (!(0x90 <= c2 && c2 <= 0xBF))
2331 return codecvt_base::error;
2332 break;
2333 case 0xF4:
2334 if ((c2 & 0xF0) != 0x80)
2335 return codecvt_base::error;
2336 break;
2337 default:
2338 if ((c2 & 0xC0) != 0x80)
2339 return codecvt_base::error;
2340 break;
2341 }
2342 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2343 return codecvt_base::error;
2344 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2345 | ((c2 & 0x3F) << 12)
2346 | ((c3 & 0x3F) << 6)
2347 | (c4 & 0x3F));
2348 if (t > Maxcode)
2349 return codecvt_base::error;
2350 *to_nxt = t;
2351 frm_nxt += 4;
2352 }
2353 else
2354 {
2355 return codecvt_base::error;
2356 }
2357 }
2358 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2359}
2360
2361static
2362int
2363utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2364 size_t mx, unsigned long Maxcode = 0x10FFFF,
2365 codecvt_mode mode = codecvt_mode(0))
2366{
2367 const uint8_t* frm_nxt = frm;
2368 if (mode & consume_header)
2369 {
2370 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2371 frm_nxt[2] == 0xBF)
2372 frm_nxt += 3;
2373 }
2374 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2375 {
2376 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2377 if (c1 < 0x80)
2378 {
2379 if (c1 > Maxcode)
2380 break;
2381 ++frm_nxt;
2382 }
2383 else if (c1 < 0xC2)
2384 {
2385 break;
2386 }
2387 else if (c1 < 0xE0)
2388 {
2389 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2390 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002391 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002392 break;
2393 frm_nxt += 2;
2394 }
2395 else if (c1 < 0xF0)
2396 {
2397 if (frm_end-frm_nxt < 3)
2398 break;
2399 uint8_t c2 = frm_nxt[1];
2400 uint8_t c3 = frm_nxt[2];
2401 switch (c1)
2402 {
2403 case 0xE0:
2404 if ((c2 & 0xE0) != 0xA0)
2405 return static_cast<int>(frm_nxt - frm);
2406 break;
2407 case 0xED:
2408 if ((c2 & 0xE0) != 0x80)
2409 return static_cast<int>(frm_nxt - frm);
2410 break;
2411 default:
2412 if ((c2 & 0xC0) != 0x80)
2413 return static_cast<int>(frm_nxt - frm);
2414 break;
2415 }
2416 if ((c3 & 0xC0) != 0x80)
2417 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002418 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002419 break;
2420 frm_nxt += 3;
2421 }
2422 else if (c1 < 0xF5)
2423 {
2424 if (frm_end-frm_nxt < 4)
2425 break;
2426 uint8_t c2 = frm_nxt[1];
2427 uint8_t c3 = frm_nxt[2];
2428 uint8_t c4 = frm_nxt[3];
2429 switch (c1)
2430 {
2431 case 0xF0:
2432 if (!(0x90 <= c2 && c2 <= 0xBF))
2433 return static_cast<int>(frm_nxt - frm);
2434 break;
2435 case 0xF4:
2436 if ((c2 & 0xF0) != 0x80)
2437 return static_cast<int>(frm_nxt - frm);
2438 break;
2439 default:
2440 if ((c2 & 0xC0) != 0x80)
2441 return static_cast<int>(frm_nxt - frm);
2442 break;
2443 }
2444 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2445 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002446 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2447 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002448 break;
2449 frm_nxt += 4;
2450 }
2451 else
2452 {
2453 break;
2454 }
2455 }
2456 return static_cast<int>(frm_nxt - frm);
2457}
2458
2459static
2460codecvt_base::result
2461ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2462 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2463 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2464{
2465 frm_nxt = frm;
2466 to_nxt = to;
2467 if (mode & generate_header)
2468 {
2469 if (to_end-to_nxt < 3)
2470 return codecvt_base::partial;
2471 *to_nxt++ = static_cast<uint8_t>(0xEF);
2472 *to_nxt++ = static_cast<uint8_t>(0xBB);
2473 *to_nxt++ = static_cast<uint8_t>(0xBF);
2474 }
2475 for (; frm_nxt < frm_end; ++frm_nxt)
2476 {
2477 uint16_t wc = *frm_nxt;
2478 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2479 return codecvt_base::error;
2480 if (wc < 0x0080)
2481 {
2482 if (to_end-to_nxt < 1)
2483 return codecvt_base::partial;
2484 *to_nxt++ = static_cast<uint8_t>(wc);
2485 }
2486 else if (wc < 0x0800)
2487 {
2488 if (to_end-to_nxt < 2)
2489 return codecvt_base::partial;
2490 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2491 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2492 }
2493 else // if (wc <= 0xFFFF)
2494 {
2495 if (to_end-to_nxt < 3)
2496 return codecvt_base::partial;
2497 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2498 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2499 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2500 }
2501 }
2502 return codecvt_base::ok;
2503}
2504
2505static
2506codecvt_base::result
2507utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2508 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2509 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2510{
2511 frm_nxt = frm;
2512 to_nxt = to;
2513 if (mode & consume_header)
2514 {
2515 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2516 frm_nxt[2] == 0xBF)
2517 frm_nxt += 3;
2518 }
2519 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2520 {
2521 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2522 if (c1 < 0x80)
2523 {
2524 if (c1 > Maxcode)
2525 return codecvt_base::error;
2526 *to_nxt = static_cast<uint16_t>(c1);
2527 ++frm_nxt;
2528 }
2529 else if (c1 < 0xC2)
2530 {
2531 return codecvt_base::error;
2532 }
2533 else if (c1 < 0xE0)
2534 {
2535 if (frm_end-frm_nxt < 2)
2536 return codecvt_base::partial;
2537 uint8_t c2 = frm_nxt[1];
2538 if ((c2 & 0xC0) != 0x80)
2539 return codecvt_base::error;
2540 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2541 | (c2 & 0x3F));
2542 if (t > Maxcode)
2543 return codecvt_base::error;
2544 *to_nxt = t;
2545 frm_nxt += 2;
2546 }
2547 else if (c1 < 0xF0)
2548 {
2549 if (frm_end-frm_nxt < 3)
2550 return codecvt_base::partial;
2551 uint8_t c2 = frm_nxt[1];
2552 uint8_t c3 = frm_nxt[2];
2553 switch (c1)
2554 {
2555 case 0xE0:
2556 if ((c2 & 0xE0) != 0xA0)
2557 return codecvt_base::error;
2558 break;
2559 case 0xED:
2560 if ((c2 & 0xE0) != 0x80)
2561 return codecvt_base::error;
2562 break;
2563 default:
2564 if ((c2 & 0xC0) != 0x80)
2565 return codecvt_base::error;
2566 break;
2567 }
2568 if ((c3 & 0xC0) != 0x80)
2569 return codecvt_base::error;
2570 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2571 | ((c2 & 0x3F) << 6)
2572 | (c3 & 0x3F));
2573 if (t > Maxcode)
2574 return codecvt_base::error;
2575 *to_nxt = t;
2576 frm_nxt += 3;
2577 }
2578 else
2579 {
2580 return codecvt_base::error;
2581 }
2582 }
2583 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2584}
2585
2586static
2587int
2588utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2589 size_t mx, unsigned long Maxcode = 0x10FFFF,
2590 codecvt_mode mode = codecvt_mode(0))
2591{
2592 const uint8_t* frm_nxt = frm;
2593 if (mode & consume_header)
2594 {
2595 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2596 frm_nxt[2] == 0xBF)
2597 frm_nxt += 3;
2598 }
2599 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2600 {
2601 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2602 if (c1 < 0x80)
2603 {
2604 if (c1 > Maxcode)
2605 break;
2606 ++frm_nxt;
2607 }
2608 else if (c1 < 0xC2)
2609 {
2610 break;
2611 }
2612 else if (c1 < 0xE0)
2613 {
2614 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2615 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002616 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002617 break;
2618 frm_nxt += 2;
2619 }
2620 else if (c1 < 0xF0)
2621 {
2622 if (frm_end-frm_nxt < 3)
2623 break;
2624 uint8_t c2 = frm_nxt[1];
2625 uint8_t c3 = frm_nxt[2];
2626 switch (c1)
2627 {
2628 case 0xE0:
2629 if ((c2 & 0xE0) != 0xA0)
2630 return static_cast<int>(frm_nxt - frm);
2631 break;
2632 case 0xED:
2633 if ((c2 & 0xE0) != 0x80)
2634 return static_cast<int>(frm_nxt - frm);
2635 break;
2636 default:
2637 if ((c2 & 0xC0) != 0x80)
2638 return static_cast<int>(frm_nxt - frm);
2639 break;
2640 }
2641 if ((c3 & 0xC0) != 0x80)
2642 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002643 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002644 break;
2645 frm_nxt += 3;
2646 }
2647 else
2648 {
2649 break;
2650 }
2651 }
2652 return static_cast<int>(frm_nxt - frm);
2653}
2654
2655static
2656codecvt_base::result
2657ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2658 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2659 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2660{
2661 frm_nxt = frm;
2662 to_nxt = to;
2663 if (mode & generate_header)
2664 {
2665 if (to_end-to_nxt < 2)
2666 return codecvt_base::partial;
2667 *to_nxt++ = static_cast<uint8_t>(0xFE);
2668 *to_nxt++ = static_cast<uint8_t>(0xFF);
2669 }
2670 for (; frm_nxt < frm_end; ++frm_nxt)
2671 {
2672 uint32_t wc = *frm_nxt;
2673 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2674 return codecvt_base::error;
2675 if (wc < 0x010000)
2676 {
2677 if (to_end-to_nxt < 2)
2678 return codecvt_base::partial;
2679 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2680 *to_nxt++ = static_cast<uint8_t>(wc);
2681 }
2682 else
2683 {
2684 if (to_end-to_nxt < 4)
2685 return codecvt_base::partial;
2686 uint16_t t = static_cast<uint16_t>(
2687 0xD800
2688 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2689 | ((wc & 0x00FC00) >> 10));
2690 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2691 *to_nxt++ = static_cast<uint8_t>(t);
2692 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2693 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2694 *to_nxt++ = static_cast<uint8_t>(t);
2695 }
2696 }
2697 return codecvt_base::ok;
2698}
2699
2700static
2701codecvt_base::result
2702utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2703 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2704 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2705{
2706 frm_nxt = frm;
2707 to_nxt = to;
2708 if (mode & consume_header)
2709 {
2710 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2711 frm_nxt += 2;
2712 }
2713 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2714 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002715 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002716 if ((c1 & 0xFC00) == 0xDC00)
2717 return codecvt_base::error;
2718 if ((c1 & 0xFC00) != 0xD800)
2719 {
2720 if (c1 > Maxcode)
2721 return codecvt_base::error;
2722 *to_nxt = static_cast<uint32_t>(c1);
2723 frm_nxt += 2;
2724 }
2725 else
2726 {
2727 if (frm_end-frm_nxt < 4)
2728 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002729 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002730 if ((c2 & 0xFC00) != 0xDC00)
2731 return codecvt_base::error;
2732 uint32_t t = static_cast<uint32_t>(
2733 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2734 | ((c1 & 0x003F) << 10)
2735 | (c2 & 0x03FF));
2736 if (t > Maxcode)
2737 return codecvt_base::error;
2738 *to_nxt = t;
2739 frm_nxt += 4;
2740 }
2741 }
2742 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2743}
2744
2745static
2746int
2747utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2748 size_t mx, unsigned long Maxcode = 0x10FFFF,
2749 codecvt_mode mode = codecvt_mode(0))
2750{
2751 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002752 if (mode & consume_header)
2753 {
2754 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2755 frm_nxt += 2;
2756 }
2757 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2758 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002759 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002760 if ((c1 & 0xFC00) == 0xDC00)
2761 break;
2762 if ((c1 & 0xFC00) != 0xD800)
2763 {
2764 if (c1 > Maxcode)
2765 break;
2766 frm_nxt += 2;
2767 }
2768 else
2769 {
2770 if (frm_end-frm_nxt < 4)
2771 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002772 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002773 if ((c2 & 0xFC00) != 0xDC00)
2774 break;
2775 uint32_t t = static_cast<uint32_t>(
2776 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2777 | ((c1 & 0x003F) << 10)
2778 | (c2 & 0x03FF));
2779 if (t > Maxcode)
2780 break;
2781 frm_nxt += 4;
2782 }
2783 }
2784 return static_cast<int>(frm_nxt - frm);
2785}
2786
2787static
2788codecvt_base::result
2789ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2790 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2791 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2792{
2793 frm_nxt = frm;
2794 to_nxt = to;
2795 if (mode & generate_header)
2796 {
2797 if (to_end-to_nxt < 2)
2798 return codecvt_base::partial;
2799 *to_nxt++ = static_cast<uint8_t>(0xFF);
2800 *to_nxt++ = static_cast<uint8_t>(0xFE);
2801 }
2802 for (; frm_nxt < frm_end; ++frm_nxt)
2803 {
2804 uint32_t wc = *frm_nxt;
2805 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2806 return codecvt_base::error;
2807 if (wc < 0x010000)
2808 {
2809 if (to_end-to_nxt < 2)
2810 return codecvt_base::partial;
2811 *to_nxt++ = static_cast<uint8_t>(wc);
2812 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2813 }
2814 else
2815 {
2816 if (to_end-to_nxt < 4)
2817 return codecvt_base::partial;
2818 uint16_t t = static_cast<uint16_t>(
2819 0xD800
2820 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2821 | ((wc & 0x00FC00) >> 10));
2822 *to_nxt++ = static_cast<uint8_t>(t);
2823 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2824 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2825 *to_nxt++ = static_cast<uint8_t>(t);
2826 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2827 }
2828 }
2829 return codecvt_base::ok;
2830}
2831
2832static
2833codecvt_base::result
2834utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2835 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2836 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2837{
2838 frm_nxt = frm;
2839 to_nxt = to;
2840 if (mode & consume_header)
2841 {
2842 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2843 frm_nxt += 2;
2844 }
2845 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2846 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002847 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002848 if ((c1 & 0xFC00) == 0xDC00)
2849 return codecvt_base::error;
2850 if ((c1 & 0xFC00) != 0xD800)
2851 {
2852 if (c1 > Maxcode)
2853 return codecvt_base::error;
2854 *to_nxt = static_cast<uint32_t>(c1);
2855 frm_nxt += 2;
2856 }
2857 else
2858 {
2859 if (frm_end-frm_nxt < 4)
2860 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002861 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002862 if ((c2 & 0xFC00) != 0xDC00)
2863 return codecvt_base::error;
2864 uint32_t t = static_cast<uint32_t>(
2865 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2866 | ((c1 & 0x003F) << 10)
2867 | (c2 & 0x03FF));
2868 if (t > Maxcode)
2869 return codecvt_base::error;
2870 *to_nxt = t;
2871 frm_nxt += 4;
2872 }
2873 }
2874 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2875}
2876
2877static
2878int
2879utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2880 size_t mx, unsigned long Maxcode = 0x10FFFF,
2881 codecvt_mode mode = codecvt_mode(0))
2882{
2883 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002884 if (mode & consume_header)
2885 {
2886 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2887 frm_nxt += 2;
2888 }
2889 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2890 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002891 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002892 if ((c1 & 0xFC00) == 0xDC00)
2893 break;
2894 if ((c1 & 0xFC00) != 0xD800)
2895 {
2896 if (c1 > Maxcode)
2897 break;
2898 frm_nxt += 2;
2899 }
2900 else
2901 {
2902 if (frm_end-frm_nxt < 4)
2903 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002904 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002905 if ((c2 & 0xFC00) != 0xDC00)
2906 break;
2907 uint32_t t = static_cast<uint32_t>(
2908 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2909 | ((c1 & 0x003F) << 10)
2910 | (c2 & 0x03FF));
2911 if (t > Maxcode)
2912 break;
2913 frm_nxt += 4;
2914 }
2915 }
2916 return static_cast<int>(frm_nxt - frm);
2917}
2918
2919static
2920codecvt_base::result
2921ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2922 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2923 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2924{
2925 frm_nxt = frm;
2926 to_nxt = to;
2927 if (mode & generate_header)
2928 {
2929 if (to_end-to_nxt < 2)
2930 return codecvt_base::partial;
2931 *to_nxt++ = static_cast<uint8_t>(0xFE);
2932 *to_nxt++ = static_cast<uint8_t>(0xFF);
2933 }
2934 for (; frm_nxt < frm_end; ++frm_nxt)
2935 {
2936 uint16_t wc = *frm_nxt;
2937 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2938 return codecvt_base::error;
2939 if (to_end-to_nxt < 2)
2940 return codecvt_base::partial;
2941 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2942 *to_nxt++ = static_cast<uint8_t>(wc);
2943 }
2944 return codecvt_base::ok;
2945}
2946
2947static
2948codecvt_base::result
2949utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2950 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2951 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2952{
2953 frm_nxt = frm;
2954 to_nxt = to;
2955 if (mode & consume_header)
2956 {
2957 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2958 frm_nxt += 2;
2959 }
2960 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2961 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002962 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002963 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2964 return codecvt_base::error;
2965 *to_nxt = c1;
2966 frm_nxt += 2;
2967 }
2968 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2969}
2970
2971static
2972int
2973utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2974 size_t mx, unsigned long Maxcode = 0x10FFFF,
2975 codecvt_mode mode = codecvt_mode(0))
2976{
2977 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002978 if (mode & consume_header)
2979 {
2980 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2981 frm_nxt += 2;
2982 }
2983 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2984 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002985 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002986 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2987 break;
2988 frm_nxt += 2;
2989 }
2990 return static_cast<int>(frm_nxt - frm);
2991}
2992
2993static
2994codecvt_base::result
2995ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2996 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2997 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2998{
2999 frm_nxt = frm;
3000 to_nxt = to;
3001 if (mode & generate_header)
3002 {
3003 if (to_end-to_nxt < 2)
3004 return codecvt_base::partial;
3005 *to_nxt++ = static_cast<uint8_t>(0xFF);
3006 *to_nxt++ = static_cast<uint8_t>(0xFE);
3007 }
3008 for (; frm_nxt < frm_end; ++frm_nxt)
3009 {
3010 uint16_t wc = *frm_nxt;
3011 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3012 return codecvt_base::error;
3013 if (to_end-to_nxt < 2)
3014 return codecvt_base::partial;
3015 *to_nxt++ = static_cast<uint8_t>(wc);
3016 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3017 }
3018 return codecvt_base::ok;
3019}
3020
3021static
3022codecvt_base::result
3023utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3024 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3025 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3026{
3027 frm_nxt = frm;
3028 to_nxt = to;
3029 if (mode & consume_header)
3030 {
3031 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3032 frm_nxt += 2;
3033 }
3034 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3035 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003036 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003037 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3038 return codecvt_base::error;
3039 *to_nxt = c1;
3040 frm_nxt += 2;
3041 }
3042 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3043}
3044
3045static
3046int
3047utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3048 size_t mx, unsigned long Maxcode = 0x10FFFF,
3049 codecvt_mode mode = codecvt_mode(0))
3050{
3051 const uint8_t* frm_nxt = frm;
3052 frm_nxt = frm;
3053 if (mode & consume_header)
3054 {
3055 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3056 frm_nxt += 2;
3057 }
3058 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3059 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003060 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003061 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3062 break;
3063 frm_nxt += 2;
3064 }
3065 return static_cast<int>(frm_nxt - frm);
3066}
3067
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003068// template <> class codecvt<char16_t, char, mbstate_t>
3069
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003070locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003071
3072codecvt<char16_t, char, mbstate_t>::~codecvt()
3073{
3074}
3075
3076codecvt<char16_t, char, mbstate_t>::result
3077codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003078 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003079 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3080{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003081 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3082 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3083 const uint16_t* _frm_nxt = _frm;
3084 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3085 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3086 uint8_t* _to_nxt = _to;
3087 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3088 frm_nxt = frm + (_frm_nxt - _frm);
3089 to_nxt = to + (_to_nxt - _to);
3090 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003091}
3092
3093codecvt<char16_t, char, mbstate_t>::result
3094codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003095 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003096 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3097{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003098 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3099 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3100 const uint8_t* _frm_nxt = _frm;
3101 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3102 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3103 uint16_t* _to_nxt = _to;
3104 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3105 frm_nxt = frm + (_frm_nxt - _frm);
3106 to_nxt = to + (_to_nxt - _to);
3107 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003108}
3109
3110codecvt<char16_t, char, mbstate_t>::result
3111codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3112 extern_type* to, extern_type*, extern_type*& to_nxt) const
3113{
3114 to_nxt = to;
3115 return noconv;
3116}
3117
3118int
Howard Hinnantc9834542011-05-31 15:34:58 +00003119codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003120{
3121 return 0;
3122}
3123
3124bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003125codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003126{
3127 return false;
3128}
3129
3130int
3131codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3132 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3133{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003134 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3135 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3136 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003137}
3138
3139int
Howard Hinnantc9834542011-05-31 15:34:58 +00003140codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003141{
3142 return 4;
3143}
3144
3145// template <> class codecvt<char32_t, char, mbstate_t>
3146
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003147locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003148
3149codecvt<char32_t, char, mbstate_t>::~codecvt()
3150{
3151}
3152
3153codecvt<char32_t, char, mbstate_t>::result
3154codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003155 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003156 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3157{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003158 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3159 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3160 const uint32_t* _frm_nxt = _frm;
3161 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3162 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3163 uint8_t* _to_nxt = _to;
3164 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3165 frm_nxt = frm + (_frm_nxt - _frm);
3166 to_nxt = to + (_to_nxt - _to);
3167 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003168}
3169
3170codecvt<char32_t, char, mbstate_t>::result
3171codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003172 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003173 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3174{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003175 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3176 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3177 const uint8_t* _frm_nxt = _frm;
3178 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3179 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3180 uint32_t* _to_nxt = _to;
3181 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3182 frm_nxt = frm + (_frm_nxt - _frm);
3183 to_nxt = to + (_to_nxt - _to);
3184 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003185}
3186
3187codecvt<char32_t, char, mbstate_t>::result
3188codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3189 extern_type* to, extern_type*, extern_type*& to_nxt) const
3190{
3191 to_nxt = to;
3192 return noconv;
3193}
3194
3195int
Howard Hinnantc9834542011-05-31 15:34:58 +00003196codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003197{
3198 return 0;
3199}
3200
3201bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003202codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003203{
3204 return false;
3205}
3206
3207int
3208codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3209 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3210{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003211 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3212 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3213 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003214}
3215
3216int
Howard Hinnantc9834542011-05-31 15:34:58 +00003217codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003218{
3219 return 4;
3220}
3221
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003222// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003223
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003224__codecvt_utf8<wchar_t>::result
3225__codecvt_utf8<wchar_t>::do_out(state_type&,
3226 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003227 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3228{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003229#if _WIN32
3230 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3231 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3232 const uint16_t* _frm_nxt = _frm;
3233#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003234 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3235 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3236 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003237#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003238 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3239 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3240 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003241#if _WIN32
3242 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3243 _Maxcode_, _Mode_);
3244#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003245 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3246 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003247#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003248 frm_nxt = frm + (_frm_nxt - _frm);
3249 to_nxt = to + (_to_nxt - _to);
3250 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003251}
3252
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003253__codecvt_utf8<wchar_t>::result
3254__codecvt_utf8<wchar_t>::do_in(state_type&,
3255 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003256 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3257{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003258 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3259 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3260 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003261#if _WIN32
3262 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3263 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3264 uint16_t* _to_nxt = _to;
3265 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3266 _Maxcode_, _Mode_);
3267#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003268 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3269 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3270 uint32_t* _to_nxt = _to;
3271 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3272 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003273#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003274 frm_nxt = frm + (_frm_nxt - _frm);
3275 to_nxt = to + (_to_nxt - _to);
3276 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003277}
3278
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003279__codecvt_utf8<wchar_t>::result
3280__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003281 extern_type* to, extern_type*, extern_type*& to_nxt) const
3282{
3283 to_nxt = to;
3284 return noconv;
3285}
3286
3287int
Howard Hinnantc9834542011-05-31 15:34:58 +00003288__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003289{
3290 return 0;
3291}
3292
3293bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003294__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003295{
3296 return false;
3297}
3298
3299int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003300__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003301 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3302{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003303 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3304 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3305 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003306}
3307
3308int
Howard Hinnantc9834542011-05-31 15:34:58 +00003309__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003310{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003311 if (_Mode_ & consume_header)
3312 return 7;
3313 return 4;
3314}
3315
3316// __codecvt_utf8<char16_t>
3317
3318__codecvt_utf8<char16_t>::result
3319__codecvt_utf8<char16_t>::do_out(state_type&,
3320 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3321 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3322{
3323 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3324 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3325 const uint16_t* _frm_nxt = _frm;
3326 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3327 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3328 uint8_t* _to_nxt = _to;
3329 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3330 _Maxcode_, _Mode_);
3331 frm_nxt = frm + (_frm_nxt - _frm);
3332 to_nxt = to + (_to_nxt - _to);
3333 return r;
3334}
3335
3336__codecvt_utf8<char16_t>::result
3337__codecvt_utf8<char16_t>::do_in(state_type&,
3338 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3339 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3340{
3341 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3342 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3343 const uint8_t* _frm_nxt = _frm;
3344 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3345 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3346 uint16_t* _to_nxt = _to;
3347 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3348 _Maxcode_, _Mode_);
3349 frm_nxt = frm + (_frm_nxt - _frm);
3350 to_nxt = to + (_to_nxt - _to);
3351 return r;
3352}
3353
3354__codecvt_utf8<char16_t>::result
3355__codecvt_utf8<char16_t>::do_unshift(state_type&,
3356 extern_type* to, extern_type*, extern_type*& to_nxt) const
3357{
3358 to_nxt = to;
3359 return noconv;
3360}
3361
3362int
Howard Hinnantc9834542011-05-31 15:34:58 +00003363__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003364{
3365 return 0;
3366}
3367
3368bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003369__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003370{
3371 return false;
3372}
3373
3374int
3375__codecvt_utf8<char16_t>::do_length(state_type&,
3376 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3377{
3378 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3379 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3380 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3381}
3382
3383int
Howard Hinnantc9834542011-05-31 15:34:58 +00003384__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003385{
3386 if (_Mode_ & consume_header)
3387 return 6;
3388 return 3;
3389}
3390
3391// __codecvt_utf8<char32_t>
3392
3393__codecvt_utf8<char32_t>::result
3394__codecvt_utf8<char32_t>::do_out(state_type&,
3395 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3396 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3397{
3398 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3399 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3400 const uint32_t* _frm_nxt = _frm;
3401 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3402 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3403 uint8_t* _to_nxt = _to;
3404 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3405 _Maxcode_, _Mode_);
3406 frm_nxt = frm + (_frm_nxt - _frm);
3407 to_nxt = to + (_to_nxt - _to);
3408 return r;
3409}
3410
3411__codecvt_utf8<char32_t>::result
3412__codecvt_utf8<char32_t>::do_in(state_type&,
3413 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3414 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3415{
3416 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3417 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3418 const uint8_t* _frm_nxt = _frm;
3419 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3420 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3421 uint32_t* _to_nxt = _to;
3422 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3423 _Maxcode_, _Mode_);
3424 frm_nxt = frm + (_frm_nxt - _frm);
3425 to_nxt = to + (_to_nxt - _to);
3426 return r;
3427}
3428
3429__codecvt_utf8<char32_t>::result
3430__codecvt_utf8<char32_t>::do_unshift(state_type&,
3431 extern_type* to, extern_type*, extern_type*& to_nxt) const
3432{
3433 to_nxt = to;
3434 return noconv;
3435}
3436
3437int
Howard Hinnantc9834542011-05-31 15:34:58 +00003438__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003439{
3440 return 0;
3441}
3442
3443bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003444__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003445{
3446 return false;
3447}
3448
3449int
3450__codecvt_utf8<char32_t>::do_length(state_type&,
3451 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3452{
3453 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3454 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3455 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3456}
3457
3458int
Howard Hinnantc9834542011-05-31 15:34:58 +00003459__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003460{
3461 if (_Mode_ & consume_header)
3462 return 7;
3463 return 4;
3464}
3465
3466// __codecvt_utf16<wchar_t, false>
3467
3468__codecvt_utf16<wchar_t, false>::result
3469__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3470 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3471 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3472{
3473 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3474 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3475 const uint32_t* _frm_nxt = _frm;
3476 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3477 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3478 uint8_t* _to_nxt = _to;
3479 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3480 _Maxcode_, _Mode_);
3481 frm_nxt = frm + (_frm_nxt - _frm);
3482 to_nxt = to + (_to_nxt - _to);
3483 return r;
3484}
3485
3486__codecvt_utf16<wchar_t, false>::result
3487__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3488 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3489 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3490{
3491 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3492 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3493 const uint8_t* _frm_nxt = _frm;
3494 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3495 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3496 uint32_t* _to_nxt = _to;
3497 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3498 _Maxcode_, _Mode_);
3499 frm_nxt = frm + (_frm_nxt - _frm);
3500 to_nxt = to + (_to_nxt - _to);
3501 return r;
3502}
3503
3504__codecvt_utf16<wchar_t, false>::result
3505__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3506 extern_type* to, extern_type*, extern_type*& to_nxt) const
3507{
3508 to_nxt = to;
3509 return noconv;
3510}
3511
3512int
Howard Hinnantc9834542011-05-31 15:34:58 +00003513__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003514{
3515 return 0;
3516}
3517
3518bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003519__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003520{
3521 return false;
3522}
3523
3524int
3525__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3526 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3527{
3528 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3529 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3530 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3531}
3532
3533int
Howard Hinnantc9834542011-05-31 15:34:58 +00003534__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003535{
3536 if (_Mode_ & consume_header)
3537 return 6;
3538 return 4;
3539}
3540
3541// __codecvt_utf16<wchar_t, true>
3542
3543__codecvt_utf16<wchar_t, true>::result
3544__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3545 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3546 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3547{
3548 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3549 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3550 const uint32_t* _frm_nxt = _frm;
3551 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3552 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3553 uint8_t* _to_nxt = _to;
3554 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3555 _Maxcode_, _Mode_);
3556 frm_nxt = frm + (_frm_nxt - _frm);
3557 to_nxt = to + (_to_nxt - _to);
3558 return r;
3559}
3560
3561__codecvt_utf16<wchar_t, true>::result
3562__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3563 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3564 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3565{
3566 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3567 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3568 const uint8_t* _frm_nxt = _frm;
3569 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3570 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3571 uint32_t* _to_nxt = _to;
3572 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3573 _Maxcode_, _Mode_);
3574 frm_nxt = frm + (_frm_nxt - _frm);
3575 to_nxt = to + (_to_nxt - _to);
3576 return r;
3577}
3578
3579__codecvt_utf16<wchar_t, true>::result
3580__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3581 extern_type* to, extern_type*, extern_type*& to_nxt) const
3582{
3583 to_nxt = to;
3584 return noconv;
3585}
3586
3587int
Howard Hinnantc9834542011-05-31 15:34:58 +00003588__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003589{
3590 return 0;
3591}
3592
3593bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003594__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003595{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003596 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003597}
3598
3599int
3600__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3601 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3602{
3603 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3604 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3605 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3606}
3607
3608int
Howard Hinnantc9834542011-05-31 15:34:58 +00003609__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003610{
3611 if (_Mode_ & consume_header)
3612 return 6;
3613 return 4;
3614}
3615
3616// __codecvt_utf16<char16_t, false>
3617
3618__codecvt_utf16<char16_t, false>::result
3619__codecvt_utf16<char16_t, false>::do_out(state_type&,
3620 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3621 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3622{
3623 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3624 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3625 const uint16_t* _frm_nxt = _frm;
3626 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3627 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3628 uint8_t* _to_nxt = _to;
3629 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3630 _Maxcode_, _Mode_);
3631 frm_nxt = frm + (_frm_nxt - _frm);
3632 to_nxt = to + (_to_nxt - _to);
3633 return r;
3634}
3635
3636__codecvt_utf16<char16_t, false>::result
3637__codecvt_utf16<char16_t, false>::do_in(state_type&,
3638 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3639 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3640{
3641 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3642 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3643 const uint8_t* _frm_nxt = _frm;
3644 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3645 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3646 uint16_t* _to_nxt = _to;
3647 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3648 _Maxcode_, _Mode_);
3649 frm_nxt = frm + (_frm_nxt - _frm);
3650 to_nxt = to + (_to_nxt - _to);
3651 return r;
3652}
3653
3654__codecvt_utf16<char16_t, false>::result
3655__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3656 extern_type* to, extern_type*, extern_type*& to_nxt) const
3657{
3658 to_nxt = to;
3659 return noconv;
3660}
3661
3662int
Howard Hinnantc9834542011-05-31 15:34:58 +00003663__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003664{
3665 return 0;
3666}
3667
3668bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003669__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003670{
3671 return false;
3672}
3673
3674int
3675__codecvt_utf16<char16_t, false>::do_length(state_type&,
3676 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3677{
3678 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3679 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3680 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3681}
3682
3683int
Howard Hinnantc9834542011-05-31 15:34:58 +00003684__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003685{
3686 if (_Mode_ & consume_header)
3687 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003688 return 2;
3689}
3690
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003691// __codecvt_utf16<char16_t, true>
3692
3693__codecvt_utf16<char16_t, true>::result
3694__codecvt_utf16<char16_t, true>::do_out(state_type&,
3695 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3696 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3697{
3698 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3699 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3700 const uint16_t* _frm_nxt = _frm;
3701 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3702 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3703 uint8_t* _to_nxt = _to;
3704 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3705 _Maxcode_, _Mode_);
3706 frm_nxt = frm + (_frm_nxt - _frm);
3707 to_nxt = to + (_to_nxt - _to);
3708 return r;
3709}
3710
3711__codecvt_utf16<char16_t, true>::result
3712__codecvt_utf16<char16_t, true>::do_in(state_type&,
3713 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3714 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3715{
3716 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3717 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3718 const uint8_t* _frm_nxt = _frm;
3719 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3720 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3721 uint16_t* _to_nxt = _to;
3722 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3723 _Maxcode_, _Mode_);
3724 frm_nxt = frm + (_frm_nxt - _frm);
3725 to_nxt = to + (_to_nxt - _to);
3726 return r;
3727}
3728
3729__codecvt_utf16<char16_t, true>::result
3730__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3731 extern_type* to, extern_type*, extern_type*& to_nxt) const
3732{
3733 to_nxt = to;
3734 return noconv;
3735}
3736
3737int
Howard Hinnantc9834542011-05-31 15:34:58 +00003738__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003739{
3740 return 0;
3741}
3742
3743bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003744__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003745{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003746 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003747}
3748
3749int
3750__codecvt_utf16<char16_t, true>::do_length(state_type&,
3751 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3752{
3753 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3754 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3755 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3756}
3757
3758int
Howard Hinnantc9834542011-05-31 15:34:58 +00003759__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003760{
3761 if (_Mode_ & consume_header)
3762 return 4;
3763 return 2;
3764}
3765
3766// __codecvt_utf16<char32_t, false>
3767
3768__codecvt_utf16<char32_t, false>::result
3769__codecvt_utf16<char32_t, false>::do_out(state_type&,
3770 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3771 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3772{
3773 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3774 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3775 const uint32_t* _frm_nxt = _frm;
3776 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3777 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3778 uint8_t* _to_nxt = _to;
3779 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3780 _Maxcode_, _Mode_);
3781 frm_nxt = frm + (_frm_nxt - _frm);
3782 to_nxt = to + (_to_nxt - _to);
3783 return r;
3784}
3785
3786__codecvt_utf16<char32_t, false>::result
3787__codecvt_utf16<char32_t, false>::do_in(state_type&,
3788 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3789 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3790{
3791 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3792 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3793 const uint8_t* _frm_nxt = _frm;
3794 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3795 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3796 uint32_t* _to_nxt = _to;
3797 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3798 _Maxcode_, _Mode_);
3799 frm_nxt = frm + (_frm_nxt - _frm);
3800 to_nxt = to + (_to_nxt - _to);
3801 return r;
3802}
3803
3804__codecvt_utf16<char32_t, false>::result
3805__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3806 extern_type* to, extern_type*, extern_type*& to_nxt) const
3807{
3808 to_nxt = to;
3809 return noconv;
3810}
3811
3812int
Howard Hinnantc9834542011-05-31 15:34:58 +00003813__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003814{
3815 return 0;
3816}
3817
3818bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003819__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003820{
3821 return false;
3822}
3823
3824int
3825__codecvt_utf16<char32_t, false>::do_length(state_type&,
3826 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3827{
3828 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3829 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3830 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3831}
3832
3833int
Howard Hinnantc9834542011-05-31 15:34:58 +00003834__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003835{
3836 if (_Mode_ & consume_header)
3837 return 6;
3838 return 4;
3839}
3840
3841// __codecvt_utf16<char32_t, true>
3842
3843__codecvt_utf16<char32_t, true>::result
3844__codecvt_utf16<char32_t, true>::do_out(state_type&,
3845 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3846 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3847{
3848 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3849 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3850 const uint32_t* _frm_nxt = _frm;
3851 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3852 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3853 uint8_t* _to_nxt = _to;
3854 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3855 _Maxcode_, _Mode_);
3856 frm_nxt = frm + (_frm_nxt - _frm);
3857 to_nxt = to + (_to_nxt - _to);
3858 return r;
3859}
3860
3861__codecvt_utf16<char32_t, true>::result
3862__codecvt_utf16<char32_t, true>::do_in(state_type&,
3863 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3864 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3865{
3866 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3867 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3868 const uint8_t* _frm_nxt = _frm;
3869 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3870 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3871 uint32_t* _to_nxt = _to;
3872 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3873 _Maxcode_, _Mode_);
3874 frm_nxt = frm + (_frm_nxt - _frm);
3875 to_nxt = to + (_to_nxt - _to);
3876 return r;
3877}
3878
3879__codecvt_utf16<char32_t, true>::result
3880__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3881 extern_type* to, extern_type*, extern_type*& to_nxt) const
3882{
3883 to_nxt = to;
3884 return noconv;
3885}
3886
3887int
Howard Hinnantc9834542011-05-31 15:34:58 +00003888__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003889{
3890 return 0;
3891}
3892
3893bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003894__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003895{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003896 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003897}
3898
3899int
3900__codecvt_utf16<char32_t, true>::do_length(state_type&,
3901 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3902{
3903 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3904 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3905 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3906}
3907
3908int
Howard Hinnantc9834542011-05-31 15:34:58 +00003909__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003910{
3911 if (_Mode_ & consume_header)
3912 return 6;
3913 return 4;
3914}
3915
3916// __codecvt_utf8_utf16<wchar_t>
3917
3918__codecvt_utf8_utf16<wchar_t>::result
3919__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3920 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3921 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3922{
3923 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3924 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3925 const uint32_t* _frm_nxt = _frm;
3926 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3927 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3928 uint8_t* _to_nxt = _to;
3929 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3930 _Maxcode_, _Mode_);
3931 frm_nxt = frm + (_frm_nxt - _frm);
3932 to_nxt = to + (_to_nxt - _to);
3933 return r;
3934}
3935
3936__codecvt_utf8_utf16<wchar_t>::result
3937__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3938 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3939 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3940{
3941 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3942 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3943 const uint8_t* _frm_nxt = _frm;
3944 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3945 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3946 uint32_t* _to_nxt = _to;
3947 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3948 _Maxcode_, _Mode_);
3949 frm_nxt = frm + (_frm_nxt - _frm);
3950 to_nxt = to + (_to_nxt - _to);
3951 return r;
3952}
3953
3954__codecvt_utf8_utf16<wchar_t>::result
3955__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3956 extern_type* to, extern_type*, extern_type*& to_nxt) const
3957{
3958 to_nxt = to;
3959 return noconv;
3960}
3961
3962int
Howard Hinnantc9834542011-05-31 15:34:58 +00003963__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003964{
3965 return 0;
3966}
3967
3968bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003969__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003970{
3971 return false;
3972}
3973
3974int
3975__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3976 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3977{
3978 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3979 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3980 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3981}
3982
3983int
Howard Hinnantc9834542011-05-31 15:34:58 +00003984__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003985{
3986 if (_Mode_ & consume_header)
3987 return 7;
3988 return 4;
3989}
3990
3991// __codecvt_utf8_utf16<char16_t>
3992
3993__codecvt_utf8_utf16<char16_t>::result
3994__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3995 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3996 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3997{
3998 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3999 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4000 const uint16_t* _frm_nxt = _frm;
4001 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4002 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4003 uint8_t* _to_nxt = _to;
4004 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4005 _Maxcode_, _Mode_);
4006 frm_nxt = frm + (_frm_nxt - _frm);
4007 to_nxt = to + (_to_nxt - _to);
4008 return r;
4009}
4010
4011__codecvt_utf8_utf16<char16_t>::result
4012__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4013 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4014 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4015{
4016 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4017 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4018 const uint8_t* _frm_nxt = _frm;
4019 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4020 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4021 uint16_t* _to_nxt = _to;
4022 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4023 _Maxcode_, _Mode_);
4024 frm_nxt = frm + (_frm_nxt - _frm);
4025 to_nxt = to + (_to_nxt - _to);
4026 return r;
4027}
4028
4029__codecvt_utf8_utf16<char16_t>::result
4030__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4031 extern_type* to, extern_type*, extern_type*& to_nxt) const
4032{
4033 to_nxt = to;
4034 return noconv;
4035}
4036
4037int
Howard Hinnantc9834542011-05-31 15:34:58 +00004038__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004039{
4040 return 0;
4041}
4042
4043bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004044__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004045{
4046 return false;
4047}
4048
4049int
4050__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4051 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4052{
4053 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4054 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4055 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4056}
4057
4058int
Howard Hinnantc9834542011-05-31 15:34:58 +00004059__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004060{
4061 if (_Mode_ & consume_header)
4062 return 7;
4063 return 4;
4064}
4065
4066// __codecvt_utf8_utf16<char32_t>
4067
4068__codecvt_utf8_utf16<char32_t>::result
4069__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4070 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4071 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4072{
4073 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4074 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4075 const uint32_t* _frm_nxt = _frm;
4076 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4077 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4078 uint8_t* _to_nxt = _to;
4079 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4080 _Maxcode_, _Mode_);
4081 frm_nxt = frm + (_frm_nxt - _frm);
4082 to_nxt = to + (_to_nxt - _to);
4083 return r;
4084}
4085
4086__codecvt_utf8_utf16<char32_t>::result
4087__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4088 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4089 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4090{
4091 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4092 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4093 const uint8_t* _frm_nxt = _frm;
4094 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4095 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4096 uint32_t* _to_nxt = _to;
4097 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4098 _Maxcode_, _Mode_);
4099 frm_nxt = frm + (_frm_nxt - _frm);
4100 to_nxt = to + (_to_nxt - _to);
4101 return r;
4102}
4103
4104__codecvt_utf8_utf16<char32_t>::result
4105__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4106 extern_type* to, extern_type*, extern_type*& to_nxt) const
4107{
4108 to_nxt = to;
4109 return noconv;
4110}
4111
4112int
Howard Hinnantc9834542011-05-31 15:34:58 +00004113__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004114{
4115 return 0;
4116}
4117
4118bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004119__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004120{
4121 return false;
4122}
4123
4124int
4125__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4126 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4127{
4128 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4129 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4130 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4131}
4132
4133int
Howard Hinnantc9834542011-05-31 15:34:58 +00004134__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004135{
4136 if (_Mode_ & consume_header)
4137 return 7;
4138 return 4;
4139}
4140
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004141// __narrow_to_utf8<16>
4142
4143__narrow_to_utf8<16>::~__narrow_to_utf8()
4144{
4145}
4146
4147// __narrow_to_utf8<32>
4148
4149__narrow_to_utf8<32>::~__narrow_to_utf8()
4150{
4151}
4152
4153// __widen_from_utf8<16>
4154
4155__widen_from_utf8<16>::~__widen_from_utf8()
4156{
4157}
4158
4159// __widen_from_utf8<32>
4160
4161__widen_from_utf8<32>::~__widen_from_utf8()
4162{
4163}
4164
4165// numpunct<char> && numpunct<wchar_t>
4166
4167locale::id numpunct< char >::id;
4168locale::id numpunct<wchar_t>::id;
4169
4170numpunct<char>::numpunct(size_t refs)
4171 : locale::facet(refs),
4172 __decimal_point_('.'),
4173 __thousands_sep_(',')
4174{
4175}
4176
4177numpunct<wchar_t>::numpunct(size_t refs)
4178 : locale::facet(refs),
4179 __decimal_point_(L'.'),
4180 __thousands_sep_(L',')
4181{
4182}
4183
4184numpunct<char>::~numpunct()
4185{
4186}
4187
4188numpunct<wchar_t>::~numpunct()
4189{
4190}
4191
4192 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4193wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4194
4195 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4196wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4197
4198string numpunct< char >::do_grouping() const {return __grouping_;}
4199string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4200
4201 string numpunct< char >::do_truename() const {return "true";}
4202wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4203
4204 string numpunct< char >::do_falsename() const {return "false";}
4205wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4206
4207// numpunct_byname<char>
4208
4209numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4210 : numpunct<char>(refs)
4211{
4212 __init(nm);
4213}
4214
4215numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4216 : numpunct<char>(refs)
4217{
4218 __init(nm.c_str());
4219}
4220
4221numpunct_byname<char>::~numpunct_byname()
4222{
4223}
4224
4225void
4226numpunct_byname<char>::__init(const char* nm)
4227{
4228 if (strcmp(nm, "C") != 0)
4229 {
Sean Huntf3907e62011-07-15 05:40:33 +00004230 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004231#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004232 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004233 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4234 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004235#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004236#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004237 lconv* lc = localeconv_l(loc.get());
4238#else
4239 lconv* lc = __localeconv_l(loc.get());
4240#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004241 if (*lc->decimal_point)
4242 __decimal_point_ = *lc->decimal_point;
4243 if (*lc->thousands_sep)
4244 __thousands_sep_ = *lc->thousands_sep;
4245 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004246 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004247 }
4248}
4249
4250// numpunct_byname<wchar_t>
4251
4252numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4253 : numpunct<wchar_t>(refs)
4254{
4255 __init(nm);
4256}
4257
4258numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4259 : numpunct<wchar_t>(refs)
4260{
4261 __init(nm.c_str());
4262}
4263
4264numpunct_byname<wchar_t>::~numpunct_byname()
4265{
4266}
4267
4268void
4269numpunct_byname<wchar_t>::__init(const char* nm)
4270{
4271 if (strcmp(nm, "C") != 0)
4272 {
Sean Huntf3907e62011-07-15 05:40:33 +00004273 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004274#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004275 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004276 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4277 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004278#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004279#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004280 lconv* lc = localeconv_l(loc.get());
4281#else
4282 lconv* lc = __localeconv_l(loc.get());
4283#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004284 if (*lc->decimal_point)
4285 __decimal_point_ = *lc->decimal_point;
4286 if (*lc->thousands_sep)
4287 __thousands_sep_ = *lc->thousands_sep;
4288 __grouping_ = lc->grouping;
4289 // locallization for truename and falsename is not available
4290 }
4291}
4292
4293// num_get helpers
4294
4295int
4296__num_get_base::__get_base(ios_base& iob)
4297{
4298 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4299 if (__basefield == ios_base::oct)
4300 return 8;
4301 else if (__basefield == ios_base::hex)
4302 return 16;
4303 else if (__basefield == 0)
4304 return 0;
4305 return 10;
4306}
4307
4308const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4309
4310void
4311__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4312 ios_base::iostate& __err)
4313{
4314 if (__grouping.size() != 0)
4315 {
4316 reverse(__g, __g_end);
4317 const char* __ig = __grouping.data();
4318 const char* __eg = __ig + __grouping.size();
4319 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4320 {
4321 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4322 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004323 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004324 {
4325 __err = ios_base::failbit;
4326 return;
4327 }
4328 }
4329 if (__eg - __ig > 1)
4330 ++__ig;
4331 }
4332 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4333 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004334 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004335 __err = ios_base::failbit;
4336 }
4337 }
4338}
4339
4340void
4341__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4342 ios_base::fmtflags __flags)
4343{
4344 if (__flags & ios_base::showpos)
4345 *__fmtp++ = '+';
4346 if (__flags & ios_base::showbase)
4347 *__fmtp++ = '#';
4348 while(*__len)
4349 *__fmtp++ = *__len++;
4350 if ((__flags & ios_base::basefield) == ios_base::oct)
4351 *__fmtp = 'o';
4352 else if ((__flags & ios_base::basefield) == ios_base::hex)
4353 {
4354 if (__flags & ios_base::uppercase)
4355 *__fmtp = 'X';
4356 else
4357 *__fmtp = 'x';
4358 }
4359 else if (__signd)
4360 *__fmtp = 'd';
4361 else
4362 *__fmtp = 'u';
4363}
4364
4365bool
4366__num_put_base::__format_float(char* __fmtp, const char* __len,
4367 ios_base::fmtflags __flags)
4368{
4369 bool specify_precision = true;
4370 if (__flags & ios_base::showpos)
4371 *__fmtp++ = '+';
4372 if (__flags & ios_base::showpoint)
4373 *__fmtp++ = '#';
4374 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowa3645132013-10-21 15:07:28 +00004375 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004376 if (floatfield == (ios_base::fixed | ios_base::scientific))
4377 specify_precision = false;
4378 else
4379 {
4380 *__fmtp++ = '.';
4381 *__fmtp++ = '*';
4382 }
4383 while(*__len)
4384 *__fmtp++ = *__len++;
4385 if (floatfield == ios_base::fixed)
4386 {
4387 if (uppercase)
4388 *__fmtp = 'F';
4389 else
4390 *__fmtp = 'f';
4391 }
4392 else if (floatfield == ios_base::scientific)
4393 {
4394 if (uppercase)
4395 *__fmtp = 'E';
4396 else
4397 *__fmtp = 'e';
4398 }
4399 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4400 {
4401 if (uppercase)
4402 *__fmtp = 'A';
4403 else
4404 *__fmtp = 'a';
4405 }
4406 else
4407 {
4408 if (uppercase)
4409 *__fmtp = 'G';
4410 else
4411 *__fmtp = 'g';
4412 }
4413 return specify_precision;
4414}
4415
4416char*
4417__num_put_base::__identify_padding(char* __nb, char* __ne,
4418 const ios_base& __iob)
4419{
4420 switch (__iob.flags() & ios_base::adjustfield)
4421 {
4422 case ios_base::internal:
4423 if (__nb[0] == '-' || __nb[0] == '+')
4424 return __nb+1;
4425 if (__ne - __nb >= 2 && __nb[0] == '0'
4426 && (__nb[1] == 'x' || __nb[1] == 'X'))
4427 return __nb+2;
4428 break;
4429 case ios_base::left:
4430 return __ne;
4431 case ios_base::right:
4432 default:
4433 break;
4434 }
4435 return __nb;
4436}
4437
4438// time_get
4439
4440static
4441string*
4442init_weeks()
4443{
4444 static string weeks[14];
4445 weeks[0] = "Sunday";
4446 weeks[1] = "Monday";
4447 weeks[2] = "Tuesday";
4448 weeks[3] = "Wednesday";
4449 weeks[4] = "Thursday";
4450 weeks[5] = "Friday";
4451 weeks[6] = "Saturday";
4452 weeks[7] = "Sun";
4453 weeks[8] = "Mon";
4454 weeks[9] = "Tue";
4455 weeks[10] = "Wed";
4456 weeks[11] = "Thu";
4457 weeks[12] = "Fri";
4458 weeks[13] = "Sat";
4459 return weeks;
4460}
4461
4462static
4463wstring*
4464init_wweeks()
4465{
4466 static wstring weeks[14];
4467 weeks[0] = L"Sunday";
4468 weeks[1] = L"Monday";
4469 weeks[2] = L"Tuesday";
4470 weeks[3] = L"Wednesday";
4471 weeks[4] = L"Thursday";
4472 weeks[5] = L"Friday";
4473 weeks[6] = L"Saturday";
4474 weeks[7] = L"Sun";
4475 weeks[8] = L"Mon";
4476 weeks[9] = L"Tue";
4477 weeks[10] = L"Wed";
4478 weeks[11] = L"Thu";
4479 weeks[12] = L"Fri";
4480 weeks[13] = L"Sat";
4481 return weeks;
4482}
4483
4484template <>
4485const string*
4486__time_get_c_storage<char>::__weeks() const
4487{
4488 static const string* weeks = init_weeks();
4489 return weeks;
4490}
4491
4492template <>
4493const wstring*
4494__time_get_c_storage<wchar_t>::__weeks() const
4495{
4496 static const wstring* weeks = init_wweeks();
4497 return weeks;
4498}
4499
4500static
4501string*
4502init_months()
4503{
4504 static string months[24];
4505 months[0] = "January";
4506 months[1] = "February";
4507 months[2] = "March";
4508 months[3] = "April";
4509 months[4] = "May";
4510 months[5] = "June";
4511 months[6] = "July";
4512 months[7] = "August";
4513 months[8] = "September";
4514 months[9] = "October";
4515 months[10] = "November";
4516 months[11] = "December";
4517 months[12] = "Jan";
4518 months[13] = "Feb";
4519 months[14] = "Mar";
4520 months[15] = "Apr";
4521 months[16] = "May";
4522 months[17] = "Jun";
4523 months[18] = "Jul";
4524 months[19] = "Aug";
4525 months[20] = "Sep";
4526 months[21] = "Oct";
4527 months[22] = "Nov";
4528 months[23] = "Dec";
4529 return months;
4530}
4531
4532static
4533wstring*
4534init_wmonths()
4535{
4536 static wstring months[24];
4537 months[0] = L"January";
4538 months[1] = L"February";
4539 months[2] = L"March";
4540 months[3] = L"April";
4541 months[4] = L"May";
4542 months[5] = L"June";
4543 months[6] = L"July";
4544 months[7] = L"August";
4545 months[8] = L"September";
4546 months[9] = L"October";
4547 months[10] = L"November";
4548 months[11] = L"December";
4549 months[12] = L"Jan";
4550 months[13] = L"Feb";
4551 months[14] = L"Mar";
4552 months[15] = L"Apr";
4553 months[16] = L"May";
4554 months[17] = L"Jun";
4555 months[18] = L"Jul";
4556 months[19] = L"Aug";
4557 months[20] = L"Sep";
4558 months[21] = L"Oct";
4559 months[22] = L"Nov";
4560 months[23] = L"Dec";
4561 return months;
4562}
4563
4564template <>
4565const string*
4566__time_get_c_storage<char>::__months() const
4567{
4568 static const string* months = init_months();
4569 return months;
4570}
4571
4572template <>
4573const wstring*
4574__time_get_c_storage<wchar_t>::__months() const
4575{
4576 static const wstring* months = init_wmonths();
4577 return months;
4578}
4579
4580static
4581string*
4582init_am_pm()
4583{
4584 static string am_pm[24];
4585 am_pm[0] = "AM";
4586 am_pm[1] = "PM";
4587 return am_pm;
4588}
4589
4590static
4591wstring*
4592init_wam_pm()
4593{
4594 static wstring am_pm[24];
4595 am_pm[0] = L"AM";
4596 am_pm[1] = L"PM";
4597 return am_pm;
4598}
4599
4600template <>
4601const string*
4602__time_get_c_storage<char>::__am_pm() const
4603{
4604 static const string* am_pm = init_am_pm();
4605 return am_pm;
4606}
4607
4608template <>
4609const wstring*
4610__time_get_c_storage<wchar_t>::__am_pm() const
4611{
4612 static const wstring* am_pm = init_wam_pm();
4613 return am_pm;
4614}
4615
4616template <>
4617const string&
4618__time_get_c_storage<char>::__x() const
4619{
4620 static string s("%m/%d/%y");
4621 return s;
4622}
4623
4624template <>
4625const wstring&
4626__time_get_c_storage<wchar_t>::__x() const
4627{
4628 static wstring s(L"%m/%d/%y");
4629 return s;
4630}
4631
4632template <>
4633const string&
4634__time_get_c_storage<char>::__X() const
4635{
4636 static string s("%H:%M:%S");
4637 return s;
4638}
4639
4640template <>
4641const wstring&
4642__time_get_c_storage<wchar_t>::__X() const
4643{
4644 static wstring s(L"%H:%M:%S");
4645 return s;
4646}
4647
4648template <>
4649const string&
4650__time_get_c_storage<char>::__c() const
4651{
4652 static string s("%a %b %d %H:%M:%S %Y");
4653 return s;
4654}
4655
4656template <>
4657const wstring&
4658__time_get_c_storage<wchar_t>::__c() const
4659{
4660 static wstring s(L"%a %b %d %H:%M:%S %Y");
4661 return s;
4662}
4663
4664template <>
4665const string&
4666__time_get_c_storage<char>::__r() const
4667{
4668 static string s("%I:%M:%S %p");
4669 return s;
4670}
4671
4672template <>
4673const wstring&
4674__time_get_c_storage<wchar_t>::__r() const
4675{
4676 static wstring s(L"%I:%M:%S %p");
4677 return s;
4678}
4679
4680// time_get_byname
4681
4682__time_get::__time_get(const char* nm)
4683 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4684{
Howard Hinnantd4444702010-08-11 17:04:31 +00004685#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004686 if (__loc_ == 0)
4687 throw runtime_error("time_get_byname"
4688 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004689#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004690}
4691
4692__time_get::__time_get(const string& nm)
4693 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4694{
Howard Hinnantd4444702010-08-11 17:04:31 +00004695#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004696 if (__loc_ == 0)
4697 throw runtime_error("time_get_byname"
4698 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004699#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004700}
4701
4702__time_get::~__time_get()
4703{
4704 freelocale(__loc_);
4705}
Marshall Clowa3645132013-10-21 15:07:28 +00004706#if defined(__clang__)
Howard Hinnant335b1512012-02-20 16:51:43 +00004707#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004708#endif
4709#if defined(__GNUG__)
Howard Hinnant21772ec2012-12-28 18:15:01 +00004710#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004711#endif
Howard Hinnant335b1512012-02-20 16:51:43 +00004712
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004713template <>
4714string
4715__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4716{
Howard Hinnant3074a052012-02-19 14:55:32 +00004717 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004718 t.tm_sec = 59;
4719 t.tm_min = 55;
4720 t.tm_hour = 23;
4721 t.tm_mday = 31;
4722 t.tm_mon = 11;
4723 t.tm_year = 161;
4724 t.tm_wday = 6;
4725 t.tm_yday = 364;
4726 t.tm_isdst = -1;
4727 char buf[100];
4728 char f[3] = {0};
4729 f[0] = '%';
4730 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004731 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004732 char* bb = buf;
4733 char* be = buf + n;
4734 string result;
4735 while (bb != be)
4736 {
4737 if (ct.is(ctype_base::space, *bb))
4738 {
4739 result.push_back(' ');
4740 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4741 ;
4742 continue;
4743 }
4744 char* w = bb;
4745 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004746 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004747 ct, err, false)
4748 - this->__weeks_;
4749 if (i < 14)
4750 {
4751 result.push_back('%');
4752 if (i < 7)
4753 result.push_back('A');
4754 else
4755 result.push_back('a');
4756 bb = w;
4757 continue;
4758 }
4759 w = bb;
4760 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4761 ct, err, false)
4762 - this->__months_;
4763 if (i < 24)
4764 {
4765 result.push_back('%');
4766 if (i < 12)
4767 result.push_back('B');
4768 else
4769 result.push_back('b');
4770 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4771 result.back() = 'm';
4772 bb = w;
4773 continue;
4774 }
4775 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4776 {
4777 w = bb;
4778 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4779 ct, err, false) - this->__am_pm_;
4780 if (i < 2)
4781 {
4782 result.push_back('%');
4783 result.push_back('p');
4784 bb = w;
4785 continue;
4786 }
4787 }
4788 w = bb;
4789 if (ct.is(ctype_base::digit, *bb))
4790 {
4791 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4792 {
4793 case 6:
4794 result.push_back('%');
4795 result.push_back('w');
4796 break;
4797 case 7:
4798 result.push_back('%');
4799 result.push_back('u');
4800 break;
4801 case 11:
4802 result.push_back('%');
4803 result.push_back('I');
4804 break;
4805 case 12:
4806 result.push_back('%');
4807 result.push_back('m');
4808 break;
4809 case 23:
4810 result.push_back('%');
4811 result.push_back('H');
4812 break;
4813 case 31:
4814 result.push_back('%');
4815 result.push_back('d');
4816 break;
4817 case 55:
4818 result.push_back('%');
4819 result.push_back('M');
4820 break;
4821 case 59:
4822 result.push_back('%');
4823 result.push_back('S');
4824 break;
4825 case 61:
4826 result.push_back('%');
4827 result.push_back('y');
4828 break;
4829 case 364:
4830 result.push_back('%');
4831 result.push_back('j');
4832 break;
4833 case 2061:
4834 result.push_back('%');
4835 result.push_back('Y');
4836 break;
4837 default:
4838 for (; w != bb; ++w)
4839 result.push_back(*w);
4840 break;
4841 }
4842 continue;
4843 }
4844 if (*bb == '%')
4845 {
4846 result.push_back('%');
4847 result.push_back('%');
4848 ++bb;
4849 continue;
4850 }
4851 result.push_back(*bb);
4852 ++bb;
4853 }
4854 return result;
4855}
4856
Marshall Clowa3645132013-10-21 15:07:28 +00004857#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +00004858#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowa3645132013-10-21 15:07:28 +00004859#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004860
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004861template <>
4862wstring
4863__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4864{
Howard Hinnant3074a052012-02-19 14:55:32 +00004865 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004866 t.tm_sec = 59;
4867 t.tm_min = 55;
4868 t.tm_hour = 23;
4869 t.tm_mday = 31;
4870 t.tm_mon = 11;
4871 t.tm_year = 161;
4872 t.tm_wday = 6;
4873 t.tm_yday = 364;
4874 t.tm_isdst = -1;
4875 char buf[100];
4876 char f[3] = {0};
4877 f[0] = '%';
4878 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004879 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004880 wchar_t wbuf[100];
4881 wchar_t* wbb = wbuf;
4882 mbstate_t mb = {0};
4883 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004884#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004885 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004886#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004887 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004888#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004889 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004890 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004891 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004892 wstring result;
4893 while (wbb != wbe)
4894 {
4895 if (ct.is(ctype_base::space, *wbb))
4896 {
4897 result.push_back(L' ');
4898 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4899 ;
4900 continue;
4901 }
4902 wchar_t* w = wbb;
4903 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004904 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004905 ct, err, false)
4906 - this->__weeks_;
4907 if (i < 14)
4908 {
4909 result.push_back(L'%');
4910 if (i < 7)
4911 result.push_back(L'A');
4912 else
4913 result.push_back(L'a');
4914 wbb = w;
4915 continue;
4916 }
4917 w = wbb;
4918 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4919 ct, err, false)
4920 - this->__months_;
4921 if (i < 24)
4922 {
4923 result.push_back(L'%');
4924 if (i < 12)
4925 result.push_back(L'B');
4926 else
4927 result.push_back(L'b');
4928 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4929 result.back() = L'm';
4930 wbb = w;
4931 continue;
4932 }
4933 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4934 {
4935 w = wbb;
4936 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4937 ct, err, false) - this->__am_pm_;
4938 if (i < 2)
4939 {
4940 result.push_back(L'%');
4941 result.push_back(L'p');
4942 wbb = w;
4943 continue;
4944 }
4945 }
4946 w = wbb;
4947 if (ct.is(ctype_base::digit, *wbb))
4948 {
4949 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4950 {
4951 case 6:
4952 result.push_back(L'%');
4953 result.push_back(L'w');
4954 break;
4955 case 7:
4956 result.push_back(L'%');
4957 result.push_back(L'u');
4958 break;
4959 case 11:
4960 result.push_back(L'%');
4961 result.push_back(L'I');
4962 break;
4963 case 12:
4964 result.push_back(L'%');
4965 result.push_back(L'm');
4966 break;
4967 case 23:
4968 result.push_back(L'%');
4969 result.push_back(L'H');
4970 break;
4971 case 31:
4972 result.push_back(L'%');
4973 result.push_back(L'd');
4974 break;
4975 case 55:
4976 result.push_back(L'%');
4977 result.push_back(L'M');
4978 break;
4979 case 59:
4980 result.push_back(L'%');
4981 result.push_back(L'S');
4982 break;
4983 case 61:
4984 result.push_back(L'%');
4985 result.push_back(L'y');
4986 break;
4987 case 364:
4988 result.push_back(L'%');
4989 result.push_back(L'j');
4990 break;
4991 case 2061:
4992 result.push_back(L'%');
4993 result.push_back(L'Y');
4994 break;
4995 default:
4996 for (; w != wbb; ++w)
4997 result.push_back(*w);
4998 break;
4999 }
5000 continue;
5001 }
5002 if (ct.narrow(*wbb, 0) == '%')
5003 {
5004 result.push_back(L'%');
5005 result.push_back(L'%');
5006 ++wbb;
5007 continue;
5008 }
5009 result.push_back(*wbb);
5010 ++wbb;
5011 }
5012 return result;
5013}
5014
5015template <>
5016void
5017__time_get_storage<char>::init(const ctype<char>& ct)
5018{
Howard Hinnantcd992362012-08-02 18:44:17 +00005019 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005020 char buf[100];
5021 // __weeks_
5022 for (int i = 0; i < 7; ++i)
5023 {
5024 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005025 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005026 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005027 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005028 __weeks_[i+7] = buf;
5029 }
5030 // __months_
5031 for (int i = 0; i < 12; ++i)
5032 {
5033 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005034 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005035 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005036 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005037 __months_[i+12] = buf;
5038 }
5039 // __am_pm_
5040 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005041 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005042 __am_pm_[0] = buf;
5043 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005044 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005045 __am_pm_[1] = buf;
5046 __c_ = __analyze('c', ct);
5047 __r_ = __analyze('r', ct);
5048 __x_ = __analyze('x', ct);
5049 __X_ = __analyze('X', ct);
5050}
5051
5052template <>
5053void
5054__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5055{
5056 tm t = {0};
5057 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005058 wchar_t wbuf[100];
5059 wchar_t* wbe;
5060 mbstate_t mb = {0};
5061 // __weeks_
5062 for (int i = 0; i < 7; ++i)
5063 {
5064 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005065 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005066 mb = mbstate_t();
5067 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005068#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005069 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005070#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005073 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005074 __throw_runtime_error("locale not supported");
5075 wbe = wbuf + j;
5076 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005077 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005078 mb = mbstate_t();
5079 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005080#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005081 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005082#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005085 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005086 __throw_runtime_error("locale not supported");
5087 wbe = wbuf + j;
5088 __weeks_[i+7].assign(wbuf, wbe);
5089 }
5090 // __months_
5091 for (int i = 0; i < 12; ++i)
5092 {
5093 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005094 strftime_l(buf, countof(buf), "%B", &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 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005106 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005107 mb = mbstate_t();
5108 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005109#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005110 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005111#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005112 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005113#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005114 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005115 __throw_runtime_error("locale not supported");
5116 wbe = wbuf + j;
5117 __months_[i+12].assign(wbuf, wbe);
5118 }
5119 // __am_pm_
5120 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005121 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005122 mb = mbstate_t();
5123 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005124#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005125 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005126#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005127 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005128#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005129 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005130 __throw_runtime_error("locale not supported");
5131 wbe = wbuf + j;
5132 __am_pm_[0].assign(wbuf, wbe);
5133 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005134 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005135 mb = mbstate_t();
5136 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005137#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005138 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005139#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005140 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005141#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005142 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005143 __throw_runtime_error("locale not supported");
5144 wbe = wbuf + j;
5145 __am_pm_[1].assign(wbuf, wbe);
5146 __c_ = __analyze('c', ct);
5147 __r_ = __analyze('r', ct);
5148 __x_ = __analyze('x', ct);
5149 __X_ = __analyze('X', ct);
5150}
5151
5152template <class CharT>
5153struct _LIBCPP_HIDDEN __time_get_temp
5154 : public ctype_byname<CharT>
5155{
5156 explicit __time_get_temp(const char* nm)
5157 : ctype_byname<CharT>(nm, 1) {}
5158 explicit __time_get_temp(const string& nm)
5159 : ctype_byname<CharT>(nm, 1) {}
5160};
5161
5162template <>
5163__time_get_storage<char>::__time_get_storage(const char* __nm)
5164 : __time_get(__nm)
5165{
5166 const __time_get_temp<char> ct(__nm);
5167 init(ct);
5168}
5169
5170template <>
5171__time_get_storage<char>::__time_get_storage(const string& __nm)
5172 : __time_get(__nm)
5173{
5174 const __time_get_temp<char> ct(__nm);
5175 init(ct);
5176}
5177
5178template <>
5179__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5180 : __time_get(__nm)
5181{
5182 const __time_get_temp<wchar_t> ct(__nm);
5183 init(ct);
5184}
5185
5186template <>
5187__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5188 : __time_get(__nm)
5189{
5190 const __time_get_temp<wchar_t> ct(__nm);
5191 init(ct);
5192}
5193
5194template <>
5195time_base::dateorder
5196__time_get_storage<char>::__do_date_order() const
5197{
5198 unsigned i;
5199 for (i = 0; i < __x_.size(); ++i)
5200 if (__x_[i] == '%')
5201 break;
5202 ++i;
5203 switch (__x_[i])
5204 {
5205 case 'y':
5206 case 'Y':
5207 for (++i; i < __x_.size(); ++i)
5208 if (__x_[i] == '%')
5209 break;
5210 if (i == __x_.size())
5211 break;
5212 ++i;
5213 switch (__x_[i])
5214 {
5215 case 'm':
5216 for (++i; i < __x_.size(); ++i)
5217 if (__x_[i] == '%')
5218 break;
5219 if (i == __x_.size())
5220 break;
5221 ++i;
5222 if (__x_[i] == 'd')
5223 return time_base::ymd;
5224 break;
5225 case 'd':
5226 for (++i; i < __x_.size(); ++i)
5227 if (__x_[i] == '%')
5228 break;
5229 if (i == __x_.size())
5230 break;
5231 ++i;
5232 if (__x_[i] == 'm')
5233 return time_base::ydm;
5234 break;
5235 }
5236 break;
5237 case 'm':
5238 for (++i; i < __x_.size(); ++i)
5239 if (__x_[i] == '%')
5240 break;
5241 if (i == __x_.size())
5242 break;
5243 ++i;
5244 if (__x_[i] == 'd')
5245 {
5246 for (++i; i < __x_.size(); ++i)
5247 if (__x_[i] == '%')
5248 break;
5249 if (i == __x_.size())
5250 break;
5251 ++i;
5252 if (__x_[i] == 'y' || __x_[i] == 'Y')
5253 return time_base::mdy;
5254 break;
5255 }
5256 break;
5257 case 'd':
5258 for (++i; i < __x_.size(); ++i)
5259 if (__x_[i] == '%')
5260 break;
5261 if (i == __x_.size())
5262 break;
5263 ++i;
5264 if (__x_[i] == 'm')
5265 {
5266 for (++i; i < __x_.size(); ++i)
5267 if (__x_[i] == '%')
5268 break;
5269 if (i == __x_.size())
5270 break;
5271 ++i;
5272 if (__x_[i] == 'y' || __x_[i] == 'Y')
5273 return time_base::dmy;
5274 break;
5275 }
5276 break;
5277 }
5278 return time_base::no_order;
5279}
5280
5281template <>
5282time_base::dateorder
5283__time_get_storage<wchar_t>::__do_date_order() const
5284{
5285 unsigned i;
5286 for (i = 0; i < __x_.size(); ++i)
5287 if (__x_[i] == L'%')
5288 break;
5289 ++i;
5290 switch (__x_[i])
5291 {
5292 case L'y':
5293 case L'Y':
5294 for (++i; i < __x_.size(); ++i)
5295 if (__x_[i] == L'%')
5296 break;
5297 if (i == __x_.size())
5298 break;
5299 ++i;
5300 switch (__x_[i])
5301 {
5302 case L'm':
5303 for (++i; i < __x_.size(); ++i)
5304 if (__x_[i] == L'%')
5305 break;
5306 if (i == __x_.size())
5307 break;
5308 ++i;
5309 if (__x_[i] == L'd')
5310 return time_base::ymd;
5311 break;
5312 case L'd':
5313 for (++i; i < __x_.size(); ++i)
5314 if (__x_[i] == L'%')
5315 break;
5316 if (i == __x_.size())
5317 break;
5318 ++i;
5319 if (__x_[i] == L'm')
5320 return time_base::ydm;
5321 break;
5322 }
5323 break;
5324 case L'm':
5325 for (++i; i < __x_.size(); ++i)
5326 if (__x_[i] == L'%')
5327 break;
5328 if (i == __x_.size())
5329 break;
5330 ++i;
5331 if (__x_[i] == L'd')
5332 {
5333 for (++i; i < __x_.size(); ++i)
5334 if (__x_[i] == L'%')
5335 break;
5336 if (i == __x_.size())
5337 break;
5338 ++i;
5339 if (__x_[i] == L'y' || __x_[i] == L'Y')
5340 return time_base::mdy;
5341 break;
5342 }
5343 break;
5344 case L'd':
5345 for (++i; i < __x_.size(); ++i)
5346 if (__x_[i] == L'%')
5347 break;
5348 if (i == __x_.size())
5349 break;
5350 ++i;
5351 if (__x_[i] == L'm')
5352 {
5353 for (++i; i < __x_.size(); ++i)
5354 if (__x_[i] == L'%')
5355 break;
5356 if (i == __x_.size())
5357 break;
5358 ++i;
5359 if (__x_[i] == L'y' || __x_[i] == L'Y')
5360 return time_base::dmy;
5361 break;
5362 }
5363 break;
5364 }
5365 return time_base::no_order;
5366}
5367
5368// time_put
5369
5370__time_put::__time_put(const char* nm)
5371 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5372{
Howard Hinnantd4444702010-08-11 17:04:31 +00005373#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005374 if (__loc_ == 0)
5375 throw runtime_error("time_put_byname"
5376 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005377#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005378}
5379
5380__time_put::__time_put(const string& nm)
5381 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5382{
Howard Hinnantd4444702010-08-11 17:04:31 +00005383#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005384 if (__loc_ == 0)
5385 throw runtime_error("time_put_byname"
5386 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005387#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005388}
5389
5390__time_put::~__time_put()
5391{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005392 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005393 freelocale(__loc_);
5394}
5395
5396void
5397__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5398 char __fmt, char __mod) const
5399{
5400 char fmt[] = {'%', __fmt, __mod, 0};
5401 if (__mod != 0)
5402 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005403 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005404 __ne = __nb + n;
5405}
5406
5407void
5408__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5409 char __fmt, char __mod) const
5410{
5411 char __nar[100];
5412 char* __ne = __nar + 100;
5413 __do_put(__nar, __ne, __tm, __fmt, __mod);
5414 mbstate_t mb = {0};
5415 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005416#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005417 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005418#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005419 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005420#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005421 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005422 __throw_runtime_error("locale not supported");
5423 __we = __wb + j;
5424}
5425
5426// moneypunct_byname
5427
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005428template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005429static
5430void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005431__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5432 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5433 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005434{
5435 const char sign = static_cast<char>(money_base::sign);
5436 const char space = static_cast<char>(money_base::space);
5437 const char none = static_cast<char>(money_base::none);
5438 const char symbol = static_cast<char>(money_base::symbol);
5439 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005440 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5441
5442 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5443 // function'. "Space between sign and symbol or value" means that
5444 // if the sign is adjacent to the symbol, there's a space between
5445 // them, and otherwise there's a space between the sign and value.
5446 //
5447 // C11's localeconv specifies that the fourth character of an
5448 // international curr_symbol is used to separate the sign and
5449 // value when sep_by_space says to do so. C++ can't represent
5450 // that, so we just use a space. When sep_by_space says to
5451 // separate the symbol and value-or-sign with a space, we rearrange the
5452 // curr_symbol to put its spacing character on the correct side of
5453 // the symbol.
5454 //
5455 // We also need to avoid adding an extra space between the sign
5456 // and value when the currency symbol is suppressed (by not
5457 // setting showbase). We match glibc's strfmon by interpreting
5458 // sep_by_space==1 as "omit the space when the currency symbol is
5459 // absent".
5460 //
5461 // Users who want to get this right should use ICU instead.
5462
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005463 switch (cs_precedes)
5464 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005465 case 0: // value before curr_symbol
5466 if (symbol_contains_sep) {
5467 // Move the separator to before the symbol, to place it
5468 // between the value and symbol.
5469 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5470 __curr_symbol_.end());
5471 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005472 switch (sign_posn)
5473 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005474 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005475 pat.field[0] = sign;
5476 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005477 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005478 pat.field[3] = symbol;
5479 switch (sep_by_space)
5480 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005481 case 0: // No space separates the currency symbol and value.
5482 // This case may have changed between C99 and C11;
5483 // assume the currency symbol matches the intention.
5484 case 2: // Space between sign and currency or value.
5485 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005486 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005487 case 1: // Space between currency-and-sign or currency and value.
5488 if (!symbol_contains_sep) {
5489 // We insert the space into the symbol instead of
5490 // setting pat.field[2]=space so that when
5491 // showbase is not set, the space goes away too.
5492 __curr_symbol_.insert(0, 1, space_char);
5493 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005494 return;
5495 default:
5496 break;
5497 }
5498 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005499 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005500 pat.field[0] = sign;
5501 pat.field[3] = symbol;
5502 switch (sep_by_space)
5503 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005504 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005505 pat.field[1] = value;
5506 pat.field[2] = none;
5507 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005508 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005509 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005510 pat.field[2] = none;
5511 if (!symbol_contains_sep) {
5512 // We insert the space into the symbol instead of
5513 // setting pat.field[2]=space so that when
5514 // showbase is not set, the space goes away too.
5515 __curr_symbol_.insert(0, 1, space_char);
5516 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005517 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005518 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005519 pat.field[1] = space;
5520 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005521 if (symbol_contains_sep) {
5522 // Remove the separator from the symbol, since it
5523 // has already appeared after the sign.
5524 __curr_symbol_.erase(__curr_symbol_.begin());
5525 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005526 return;
5527 default:
5528 break;
5529 }
5530 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005531 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005532 pat.field[0] = value;
5533 pat.field[3] = sign;
5534 switch (sep_by_space)
5535 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005536 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005537 pat.field[1] = none;
5538 pat.field[2] = symbol;
5539 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005540 case 1: // Space between currency-and-sign or currency and value.
5541 if (!symbol_contains_sep) {
5542 // We insert the space into the symbol instead of
5543 // setting pat.field[1]=space so that when
5544 // showbase is not set, the space goes away too.
5545 __curr_symbol_.insert(0, 1, space_char);
5546 }
5547 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005548 pat.field[2] = symbol;
5549 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005550 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005551 pat.field[1] = symbol;
5552 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005553 if (symbol_contains_sep) {
5554 // Remove the separator from the symbol, since it
5555 // should not be removed if showbase is absent.
5556 __curr_symbol_.erase(__curr_symbol_.begin());
5557 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005558 return;
5559 default:
5560 break;
5561 }
5562 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005563 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005564 pat.field[0] = value;
5565 pat.field[3] = symbol;
5566 switch (sep_by_space)
5567 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005568 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005569 pat.field[1] = none;
5570 pat.field[2] = sign;
5571 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005572 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005573 pat.field[1] = space;
5574 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005575 if (symbol_contains_sep) {
5576 // Remove the separator from the symbol, since it
5577 // has already appeared before the sign.
5578 __curr_symbol_.erase(__curr_symbol_.begin());
5579 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005580 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005581 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005582 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005583 pat.field[2] = none;
5584 if (!symbol_contains_sep) {
5585 // We insert the space into the symbol instead of
5586 // setting pat.field[2]=space so that when
5587 // showbase is not set, the space goes away too.
5588 __curr_symbol_.insert(0, 1, space_char);
5589 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005590 return;
5591 default:
5592 break;
5593 }
5594 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005595 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005596 pat.field[0] = value;
5597 pat.field[3] = sign;
5598 switch (sep_by_space)
5599 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005600 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005601 pat.field[1] = none;
5602 pat.field[2] = symbol;
5603 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005604 case 1: // Space between currency-and-sign or currency and value.
5605 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005606 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005607 if (!symbol_contains_sep) {
5608 // We insert the space into the symbol instead of
5609 // setting pat.field[1]=space so that when
5610 // showbase is not set, the space goes away too.
5611 __curr_symbol_.insert(0, 1, space_char);
5612 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005613 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005614 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005615 pat.field[1] = symbol;
5616 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005617 if (symbol_contains_sep) {
5618 // Remove the separator from the symbol, since it
5619 // should not disappear when showbase is absent.
5620 __curr_symbol_.erase(__curr_symbol_.begin());
5621 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005622 return;
5623 default:
5624 break;
5625 }
5626 break;
5627 default:
5628 break;
5629 }
5630 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005631 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005632 switch (sign_posn)
5633 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005634 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005635 pat.field[0] = sign;
5636 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005637 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005638 pat.field[3] = value;
5639 switch (sep_by_space)
5640 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005641 case 0: // No space separates the currency symbol and value.
5642 // This case may have changed between C99 and C11;
5643 // assume the currency symbol matches the intention.
5644 case 2: // Space between sign and currency or value.
5645 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005646 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005647 case 1: // Space between currency-and-sign or currency and value.
5648 if (!symbol_contains_sep) {
5649 // We insert the space into the symbol instead of
5650 // setting pat.field[2]=space so that when
5651 // showbase is not set, the space goes away too.
5652 __curr_symbol_.insert(0, 1, space_char);
5653 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005654 return;
5655 default:
5656 break;
5657 }
5658 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005659 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005660 pat.field[0] = sign;
5661 pat.field[3] = value;
5662 switch (sep_by_space)
5663 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005664 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005665 pat.field[1] = symbol;
5666 pat.field[2] = none;
5667 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005668 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005669 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005670 pat.field[2] = none;
5671 if (!symbol_contains_sep) {
5672 // We insert the space into the symbol instead of
5673 // setting pat.field[2]=space so that when
5674 // showbase is not set, the space goes away too.
5675 __curr_symbol_.push_back(space_char);
5676 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005677 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005678 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005679 pat.field[1] = space;
5680 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005681 if (symbol_contains_sep) {
5682 // Remove the separator from the symbol, since it
5683 // has already appeared after the sign.
5684 __curr_symbol_.pop_back();
5685 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005686 return;
5687 default:
5688 break;
5689 }
5690 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005691 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005692 pat.field[0] = symbol;
5693 pat.field[3] = sign;
5694 switch (sep_by_space)
5695 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005696 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005697 pat.field[1] = none;
5698 pat.field[2] = value;
5699 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005700 case 1: // Space between currency-and-sign or currency and value.
5701 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005702 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005703 if (!symbol_contains_sep) {
5704 // We insert the space into the symbol instead of
5705 // setting pat.field[1]=space so that when
5706 // showbase is not set, the space goes away too.
5707 __curr_symbol_.push_back(space_char);
5708 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005709 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005710 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005711 pat.field[1] = value;
5712 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005713 if (symbol_contains_sep) {
5714 // Remove the separator from the symbol, since it
5715 // will appear before the sign.
5716 __curr_symbol_.pop_back();
5717 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005718 return;
5719 default:
5720 break;
5721 }
5722 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005723 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005724 pat.field[0] = sign;
5725 pat.field[3] = value;
5726 switch (sep_by_space)
5727 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005728 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005729 pat.field[1] = symbol;
5730 pat.field[2] = none;
5731 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005732 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005733 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005734 pat.field[2] = none;
5735 if (!symbol_contains_sep) {
5736 // We insert the space into the symbol instead of
5737 // setting pat.field[2]=space so that when
5738 // showbase is not set, the space goes away too.
5739 __curr_symbol_.push_back(space_char);
5740 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005741 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005742 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005743 pat.field[1] = space;
5744 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005745 if (symbol_contains_sep) {
5746 // Remove the separator from the symbol, since it
5747 // has already appeared after the sign.
5748 __curr_symbol_.pop_back();
5749 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005750 return;
5751 default:
5752 break;
5753 }
5754 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005755 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005756 pat.field[0] = symbol;
5757 pat.field[3] = value;
5758 switch (sep_by_space)
5759 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005760 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005761 pat.field[1] = sign;
5762 pat.field[2] = none;
5763 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005764 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005765 pat.field[1] = sign;
5766 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005767 if (symbol_contains_sep) {
5768 // Remove the separator from the symbol, since it
5769 // should not disappear when showbase is absent.
5770 __curr_symbol_.pop_back();
5771 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005772 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005773 case 2: // Space between sign and currency or value.
5774 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005775 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005776 if (!symbol_contains_sep) {
5777 // We insert the space into the symbol instead of
5778 // setting pat.field[1]=space so that when
5779 // showbase is not set, the space goes away too.
5780 __curr_symbol_.push_back(space_char);
5781 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005782 return;
5783 default:
5784 break;
5785 }
5786 break;
5787 default:
5788 break;
5789 }
5790 break;
5791 default:
5792 break;
5793 }
5794 pat.field[0] = symbol;
5795 pat.field[1] = sign;
5796 pat.field[2] = none;
5797 pat.field[3] = value;
5798}
5799
5800template<>
5801void
5802moneypunct_byname<char, false>::init(const char* nm)
5803{
5804 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005805 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005806#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005807 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005808 throw runtime_error("moneypunct_byname"
5809 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005810#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005811#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005812 lconv* lc = localeconv_l(loc.get());
5813#else
5814 lconv* lc = __localeconv_l(loc.get());
5815#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005816 if (*lc->mon_decimal_point)
5817 __decimal_point_ = *lc->mon_decimal_point;
5818 else
5819 __decimal_point_ = base::do_decimal_point();
5820 if (*lc->mon_thousands_sep)
5821 __thousands_sep_ = *lc->mon_thousands_sep;
5822 else
5823 __thousands_sep_ = base::do_thousands_sep();
5824 __grouping_ = lc->mon_grouping;
5825 __curr_symbol_ = lc->currency_symbol;
5826 if (lc->frac_digits != CHAR_MAX)
5827 __frac_digits_ = lc->frac_digits;
5828 else
5829 __frac_digits_ = base::do_frac_digits();
5830 if (lc->p_sign_posn == 0)
5831 __positive_sign_ = "()";
5832 else
5833 __positive_sign_ = lc->positive_sign;
5834 if (lc->n_sign_posn == 0)
5835 __negative_sign_ = "()";
5836 else
5837 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005838 // Assume the positive and negative formats will want spaces in
5839 // the same places in curr_symbol since there's no way to
5840 // represent anything else.
5841 string_type __dummy_curr_symbol = __curr_symbol_;
5842 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5843 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5844 __init_pat(__neg_format_, __curr_symbol_, false,
5845 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005846}
5847
5848template<>
5849void
5850moneypunct_byname<char, true>::init(const char* nm)
5851{
5852 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005853 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005854#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005855 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005856 throw runtime_error("moneypunct_byname"
5857 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005858#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005859#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005860 lconv* lc = localeconv_l(loc.get());
5861#else
5862 lconv* lc = __localeconv_l(loc.get());
5863#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005864 if (*lc->mon_decimal_point)
5865 __decimal_point_ = *lc->mon_decimal_point;
5866 else
5867 __decimal_point_ = base::do_decimal_point();
5868 if (*lc->mon_thousands_sep)
5869 __thousands_sep_ = *lc->mon_thousands_sep;
5870 else
5871 __thousands_sep_ = base::do_thousands_sep();
5872 __grouping_ = lc->mon_grouping;
5873 __curr_symbol_ = lc->int_curr_symbol;
5874 if (lc->int_frac_digits != CHAR_MAX)
5875 __frac_digits_ = lc->int_frac_digits;
5876 else
5877 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00005878#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005879 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005880#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005881 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005882#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005883 __positive_sign_ = "()";
5884 else
5885 __positive_sign_ = lc->positive_sign;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005886#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005887 if(lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005888#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005889 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005890#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005891 __negative_sign_ = "()";
5892 else
5893 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005894 // Assume the positive and negative formats will want spaces in
5895 // the same places in curr_symbol since there's no way to
5896 // represent anything else.
5897 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005898#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005899 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5900 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5901 __init_pat(__neg_format_, __curr_symbol_, true,
5902 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005903#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005904 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5905 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5906 lc->int_p_sign_posn, ' ');
5907 __init_pat(__neg_format_, __curr_symbol_, true,
5908 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5909 lc->int_n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005910#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005911}
5912
5913template<>
5914void
5915moneypunct_byname<wchar_t, false>::init(const char* nm)
5916{
5917 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005918 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005919#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005920 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005921 throw runtime_error("moneypunct_byname"
5922 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005923#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005924#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005925 lconv* lc = localeconv_l(loc.get());
5926#else
5927 lconv* lc = __localeconv_l(loc.get());
5928#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005929 if (*lc->mon_decimal_point)
5930 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5931 else
5932 __decimal_point_ = base::do_decimal_point();
5933 if (*lc->mon_thousands_sep)
5934 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5935 else
5936 __thousands_sep_ = base::do_thousands_sep();
5937 __grouping_ = lc->mon_grouping;
5938 wchar_t wbuf[100];
5939 mbstate_t mb = {0};
5940 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005941#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005942 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005943#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005944 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005945#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005946 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005947 __throw_runtime_error("locale not supported");
5948 wchar_t* wbe = wbuf + j;
5949 __curr_symbol_.assign(wbuf, wbe);
5950 if (lc->frac_digits != CHAR_MAX)
5951 __frac_digits_ = lc->frac_digits;
5952 else
5953 __frac_digits_ = base::do_frac_digits();
5954 if (lc->p_sign_posn == 0)
5955 __positive_sign_ = L"()";
5956 else
5957 {
5958 mb = mbstate_t();
5959 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005960#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005961 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005962#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005963 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005964#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005965 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005966 __throw_runtime_error("locale not supported");
5967 wbe = wbuf + j;
5968 __positive_sign_.assign(wbuf, wbe);
5969 }
5970 if (lc->n_sign_posn == 0)
5971 __negative_sign_ = L"()";
5972 else
5973 {
5974 mb = mbstate_t();
5975 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005976#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005977 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005978#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005979 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005980#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005981 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005982 __throw_runtime_error("locale not supported");
5983 wbe = wbuf + j;
5984 __negative_sign_.assign(wbuf, wbe);
5985 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005986 // Assume the positive and negative formats will want spaces in
5987 // the same places in curr_symbol since there's no way to
5988 // represent anything else.
5989 string_type __dummy_curr_symbol = __curr_symbol_;
5990 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5991 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5992 __init_pat(__neg_format_, __curr_symbol_, false,
5993 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005994}
5995
5996template<>
5997void
5998moneypunct_byname<wchar_t, true>::init(const char* nm)
5999{
6000 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00006001 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00006002#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00006003 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006004 throw runtime_error("moneypunct_byname"
6005 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00006006#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00006007#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00006008 lconv* lc = localeconv_l(loc.get());
6009#else
6010 lconv* lc = __localeconv_l(loc.get());
6011#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006012 if (*lc->mon_decimal_point)
6013 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6014 else
6015 __decimal_point_ = base::do_decimal_point();
6016 if (*lc->mon_thousands_sep)
6017 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6018 else
6019 __thousands_sep_ = base::do_thousands_sep();
6020 __grouping_ = lc->mon_grouping;
6021 wchar_t wbuf[100];
6022 mbstate_t mb = {0};
6023 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006024#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006025 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006026#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006027 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006028#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006029 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006030 __throw_runtime_error("locale not supported");
6031 wchar_t* wbe = wbuf + j;
6032 __curr_symbol_.assign(wbuf, wbe);
6033 if (lc->int_frac_digits != CHAR_MAX)
6034 __frac_digits_ = lc->int_frac_digits;
6035 else
6036 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00006037#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006038 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006039#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006040 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006041#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006042 __positive_sign_ = L"()";
6043 else
6044 {
6045 mb = mbstate_t();
6046 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006047#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006048 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006049#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006050 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006051#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006052 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006053 __throw_runtime_error("locale not supported");
6054 wbe = wbuf + j;
6055 __positive_sign_.assign(wbuf, wbe);
6056 }
Howard Hinnantef5aa932013-09-17 01:34:47 +00006057#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006058 if (lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006059#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006060 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006061#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006062 __negative_sign_ = L"()";
6063 else
6064 {
6065 mb = mbstate_t();
6066 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006067#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006068 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006069#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006070 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006071#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006072 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006073 __throw_runtime_error("locale not supported");
6074 wbe = wbuf + j;
6075 __negative_sign_.assign(wbuf, wbe);
6076 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006077 // Assume the positive and negative formats will want spaces in
6078 // the same places in curr_symbol since there's no way to
6079 // represent anything else.
6080 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00006081#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006082 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6083 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6084 __init_pat(__neg_format_, __curr_symbol_, true,
6085 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006086#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006087 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6088 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6089 lc->int_p_sign_posn, L' ');
6090 __init_pat(__neg_format_, __curr_symbol_, true,
6091 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6092 lc->int_n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006093#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006094}
6095
6096void __do_nothing(void*) {}
6097
6098void __throw_runtime_error(const char* msg)
6099{
Howard Hinnantd4444702010-08-11 17:04:31 +00006100#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006101 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006102#else
6103 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006104#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006105}
6106
6107template class collate<char>;
6108template class collate<wchar_t>;
6109
6110template class num_get<char>;
6111template class num_get<wchar_t>;
6112
Howard Hinnantec3773c2011-12-01 20:21:04 +00006113template struct __num_get<char>;
6114template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006115
6116template class num_put<char>;
6117template class num_put<wchar_t>;
6118
Howard Hinnantec3773c2011-12-01 20:21:04 +00006119template struct __num_put<char>;
6120template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006121
6122template class time_get<char>;
6123template class time_get<wchar_t>;
6124
6125template class time_get_byname<char>;
6126template class time_get_byname<wchar_t>;
6127
6128template class time_put<char>;
6129template class time_put<wchar_t>;
6130
6131template class time_put_byname<char>;
6132template class time_put_byname<wchar_t>;
6133
6134template class moneypunct<char, false>;
6135template class moneypunct<char, true>;
6136template class moneypunct<wchar_t, false>;
6137template class moneypunct<wchar_t, true>;
6138
6139template class moneypunct_byname<char, false>;
6140template class moneypunct_byname<char, true>;
6141template class moneypunct_byname<wchar_t, false>;
6142template class moneypunct_byname<wchar_t, true>;
6143
6144template class money_get<char>;
6145template class money_get<wchar_t>;
6146
6147template class __money_get<char>;
6148template class __money_get<wchar_t>;
6149
6150template class money_put<char>;
6151template class money_put<wchar_t>;
6152
6153template class __money_put<char>;
6154template class __money_put<wchar_t>;
6155
6156template class messages<char>;
6157template class messages<wchar_t>;
6158
6159template class messages_byname<char>;
6160template class messages_byname<wchar_t>;
6161
6162template class codecvt_byname<char, char, mbstate_t>;
6163template class codecvt_byname<wchar_t, char, mbstate_t>;
6164template class codecvt_byname<char16_t, char, mbstate_t>;
6165template class codecvt_byname<char32_t, char, mbstate_t>;
6166
6167template class __vector_base_common<true>;
6168
6169_LIBCPP_END_NAMESPACE_STD