blob: 43603f0fbc51cfe102bb05c2627c3a7599399063 [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.
41#pragma clang diagnostic ignored "-Wsign-conversion"
42
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000043_LIBCPP_BEGIN_NAMESPACE_STD
44
Howard Hinnant866569b2011-09-28 23:39:33 +000045#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000046locale_t __cloc() {
47 // In theory this could create a race condition. In practice
48 // the race condition is non-fatal since it will just create
49 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000050 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
51 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000052}
Howard Hinnant866569b2011-09-28 23:39:33 +000053#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000054
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000055namespace {
56
57struct release
58{
59 void operator()(locale::facet* p) {p->__release_shared();}
60};
61
62template <class T, class A0>
63inline
64T&
65make(A0 a0)
66{
67 static typename aligned_storage<sizeof(T)>::type buf;
68 ::new (&buf) T(a0);
69 return *(T*)&buf;
70}
71
72template <class T, class A0, class A1>
73inline
74T&
75make(A0 a0, A1 a1)
76{
77 static typename aligned_storage<sizeof(T)>::type buf;
78 ::new (&buf) T(a0, a1);
79 return *(T*)&buf;
80}
81
82template <class T, class A0, class A1, class A2>
83inline
84T&
85make(A0 a0, A1 a1, A2 a2)
86{
87 static typename aligned_storage<sizeof(T)>::type buf;
88 ::new (&buf) T(a0, a1, a2);
89 return *(T*)&buf;
90}
91
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000092template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000093inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000094_LIBCPP_CONSTEXPR
95size_t
96countof(const T (&)[N])
97{
98 return N;
99}
100
101template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +0000102inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +0000103_LIBCPP_CONSTEXPR
104size_t
105countof(const T * const begin, const T * const end)
106{
107 return static_cast<size_t>(end - begin);
108}
109
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000110}
111
Howard Hinnant51437222013-08-29 23:37:50 +0000112#if defined(_AIX)
113// Set priority to INT_MIN + 256 + 150
114# pragma priority ( -2147483242 )
115#endif
116
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000117const locale::category locale::none;
118const locale::category locale::collate;
119const locale::category locale::ctype;
120const locale::category locale::monetary;
121const locale::category locale::numeric;
122const locale::category locale::time;
123const locale::category locale::messages;
124const locale::category locale::all;
125
Howard Hinnantec3773c2011-12-01 20:21:04 +0000126#pragma clang diagnostic push
127#pragma clang diagnostic ignored "-Wpadded"
128
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000129class _LIBCPP_HIDDEN locale::__imp
130 : public facet
131{
132 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000133 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000134 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000135public:
136 explicit __imp(size_t refs = 0);
137 explicit __imp(const string& name, size_t refs = 0);
138 __imp(const __imp&);
139 __imp(const __imp&, const string&, locale::category c);
140 __imp(const __imp& other, const __imp& one, locale::category c);
141 __imp(const __imp&, facet* f, long id);
142 ~__imp();
143
144 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000145 bool has_facet(long id) const
146 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000147 const locale::facet* use_facet(long id) const;
148
149 static const locale& make_classic();
150 static locale& make_global();
151private:
152 void install(facet* f, long id);
153 template <class F> void install(F* f) {install(f, f->id.__get());}
154 template <class F> void install_from(const __imp& other);
155};
156
Howard Hinnantec3773c2011-12-01 20:21:04 +0000157#pragma clang diagnostic pop
158
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000159locale::__imp::__imp(size_t refs)
160 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000161 facets_(N),
162 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000163{
164 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000165 install(&make<_VSTD::collate<char> >(1u));
166 install(&make<_VSTD::collate<wchar_t> >(1u));
167 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
168 install(&make<_VSTD::ctype<wchar_t> >(1u));
169 install(&make<codecvt<char, char, mbstate_t> >(1u));
170 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
171 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
172 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
173 install(&make<numpunct<char> >(1u));
174 install(&make<numpunct<wchar_t> >(1u));
175 install(&make<num_get<char> >(1u));
176 install(&make<num_get<wchar_t> >(1u));
177 install(&make<num_put<char> >(1u));
178 install(&make<num_put<wchar_t> >(1u));
179 install(&make<moneypunct<char, false> >(1u));
180 install(&make<moneypunct<char, true> >(1u));
181 install(&make<moneypunct<wchar_t, false> >(1u));
182 install(&make<moneypunct<wchar_t, true> >(1u));
183 install(&make<money_get<char> >(1u));
184 install(&make<money_get<wchar_t> >(1u));
185 install(&make<money_put<char> >(1u));
186 install(&make<money_put<wchar_t> >(1u));
187 install(&make<time_get<char> >(1u));
188 install(&make<time_get<wchar_t> >(1u));
189 install(&make<time_put<char> >(1u));
190 install(&make<time_put<wchar_t> >(1u));
191 install(&make<_VSTD::messages<char> >(1u));
192 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000193}
194
195locale::__imp::__imp(const string& name, size_t refs)
196 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000197 facets_(N),
198 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000199{
Howard Hinnantd4444702010-08-11 17:04:31 +0000200#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000201 try
202 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000203#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000204 facets_ = locale::classic().__locale_->facets_;
205 for (unsigned i = 0; i < facets_.size(); ++i)
206 if (facets_[i])
207 facets_[i]->__add_shared();
208 install(new collate_byname<char>(name_));
209 install(new collate_byname<wchar_t>(name_));
210 install(new ctype_byname<char>(name_));
211 install(new ctype_byname<wchar_t>(name_));
212 install(new codecvt_byname<char, char, mbstate_t>(name_));
213 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
214 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
215 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
216 install(new numpunct_byname<char>(name_));
217 install(new numpunct_byname<wchar_t>(name_));
218 install(new moneypunct_byname<char, false>(name_));
219 install(new moneypunct_byname<char, true>(name_));
220 install(new moneypunct_byname<wchar_t, false>(name_));
221 install(new moneypunct_byname<wchar_t, true>(name_));
222 install(new time_get_byname<char>(name_));
223 install(new time_get_byname<wchar_t>(name_));
224 install(new time_put_byname<char>(name_));
225 install(new time_put_byname<wchar_t>(name_));
226 install(new messages_byname<char>(name_));
227 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000228#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000229 }
230 catch (...)
231 {
232 for (unsigned i = 0; i < facets_.size(); ++i)
233 if (facets_[i])
234 facets_[i]->__release_shared();
235 throw;
236 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000237#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000238}
239
Howard Hinnant21772ec2012-12-28 18:15:01 +0000240// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000241// copy constructor` warning emitted by GCC
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000242#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000243#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000244#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000245#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000246
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000247locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000248 : facets_(max<size_t>(N, other.facets_.size())),
249 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000250{
251 facets_ = other.facets_;
252 for (unsigned i = 0; i < facets_.size(); ++i)
253 if (facets_[i])
254 facets_[i]->__add_shared();
255}
256
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000257#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000258#pragma GCC diagnostic pop
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000259#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000260
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000261locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000262 : facets_(N),
263 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000264{
265 facets_ = other.facets_;
266 for (unsigned i = 0; i < facets_.size(); ++i)
267 if (facets_[i])
268 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000269#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000270 try
271 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000272#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000273 if (c & locale::collate)
274 {
275 install(new collate_byname<char>(name));
276 install(new collate_byname<wchar_t>(name));
277 }
278 if (c & locale::ctype)
279 {
280 install(new ctype_byname<char>(name));
281 install(new ctype_byname<wchar_t>(name));
282 install(new codecvt_byname<char, char, mbstate_t>(name));
283 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
284 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
285 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
286 }
287 if (c & locale::monetary)
288 {
289 install(new moneypunct_byname<char, false>(name));
290 install(new moneypunct_byname<char, true>(name));
291 install(new moneypunct_byname<wchar_t, false>(name));
292 install(new moneypunct_byname<wchar_t, true>(name));
293 }
294 if (c & locale::numeric)
295 {
296 install(new numpunct_byname<char>(name));
297 install(new numpunct_byname<wchar_t>(name));
298 }
299 if (c & locale::time)
300 {
301 install(new time_get_byname<char>(name));
302 install(new time_get_byname<wchar_t>(name));
303 install(new time_put_byname<char>(name));
304 install(new time_put_byname<wchar_t>(name));
305 }
306 if (c & locale::messages)
307 {
308 install(new messages_byname<char>(name));
309 install(new messages_byname<wchar_t>(name));
310 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000311#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000312 }
313 catch (...)
314 {
315 for (unsigned i = 0; i < facets_.size(); ++i)
316 if (facets_[i])
317 facets_[i]->__release_shared();
318 throw;
319 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000320#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000321}
322
323template<class F>
324inline
325void
326locale::__imp::install_from(const locale::__imp& one)
327{
328 long id = F::id.__get();
329 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
330}
331
332locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000333 : facets_(N),
334 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000335{
336 facets_ = other.facets_;
337 for (unsigned i = 0; i < facets_.size(); ++i)
338 if (facets_[i])
339 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000340#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000341 try
342 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000343#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000344 if (c & locale::collate)
345 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000346 install_from<_VSTD::collate<char> >(one);
347 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000348 }
349 if (c & locale::ctype)
350 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000351 install_from<_VSTD::ctype<char> >(one);
352 install_from<_VSTD::ctype<wchar_t> >(one);
353 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
354 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
355 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
356 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000357 }
358 if (c & locale::monetary)
359 {
360 install_from<moneypunct<char, false> >(one);
361 install_from<moneypunct<char, true> >(one);
362 install_from<moneypunct<wchar_t, false> >(one);
363 install_from<moneypunct<wchar_t, true> >(one);
364 install_from<money_get<char> >(one);
365 install_from<money_get<wchar_t> >(one);
366 install_from<money_put<char> >(one);
367 install_from<money_put<wchar_t> >(one);
368 }
369 if (c & locale::numeric)
370 {
371 install_from<numpunct<char> >(one);
372 install_from<numpunct<wchar_t> >(one);
373 install_from<num_get<char> >(one);
374 install_from<num_get<wchar_t> >(one);
375 install_from<num_put<char> >(one);
376 install_from<num_put<wchar_t> >(one);
377 }
378 if (c & locale::time)
379 {
380 install_from<time_get<char> >(one);
381 install_from<time_get<wchar_t> >(one);
382 install_from<time_put<char> >(one);
383 install_from<time_put<wchar_t> >(one);
384 }
385 if (c & locale::messages)
386 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000387 install_from<_VSTD::messages<char> >(one);
388 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000389 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000390#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000391 }
392 catch (...)
393 {
394 for (unsigned i = 0; i < facets_.size(); ++i)
395 if (facets_[i])
396 facets_[i]->__release_shared();
397 throw;
398 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000399#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000400}
401
402locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000403 : facets_(max<size_t>(N, other.facets_.size()+1)),
404 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000405{
406 f->__add_shared();
407 unique_ptr<facet, release> hold(f);
408 facets_ = other.facets_;
409 for (unsigned i = 0; i < other.facets_.size(); ++i)
410 if (facets_[i])
411 facets_[i]->__add_shared();
412 install(hold.get(), id);
413}
414
415locale::__imp::~__imp()
416{
417 for (unsigned i = 0; i < facets_.size(); ++i)
418 if (facets_[i])
419 facets_[i]->__release_shared();
420}
421
422void
423locale::__imp::install(facet* f, long id)
424{
425 f->__add_shared();
426 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000427 if (static_cast<size_t>(id) >= facets_.size())
428 facets_.resize(static_cast<size_t>(id+1));
429 if (facets_[static_cast<size_t>(id)])
430 facets_[static_cast<size_t>(id)]->__release_shared();
431 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000432}
433
434const locale::facet*
435locale::__imp::use_facet(long id) const
436{
Howard Hinnantd4444702010-08-11 17:04:31 +0000437#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000438 if (!has_facet(id))
439 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000440#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000441 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000442}
443
444// locale
445
446const locale&
447locale::__imp::make_classic()
448{
449 // only one thread can get in here and it only gets in once
450 static aligned_storage<sizeof(locale)>::type buf;
451 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000452 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000453 return *c;
454}
455
456const locale&
457locale::classic()
458{
459 static const locale& c = __imp::make_classic();
460 return c;
461}
462
463locale&
464locale::__imp::make_global()
465{
466 // only one thread can get in here and it only gets in once
467 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000468 ::new (&buf) locale(locale::classic());
469 return *(locale*)&buf;
470}
471
472locale&
473locale::__global()
474{
475 static locale& g = __imp::make_global();
476 return g;
477}
478
Howard Hinnantc9834542011-05-31 15:34:58 +0000479locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000480 : __locale_(__global().__locale_)
481{
482 __locale_->__add_shared();
483}
484
Howard Hinnantc9834542011-05-31 15:34:58 +0000485locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000486 : __locale_(l.__locale_)
487{
488 __locale_->__add_shared();
489}
490
Howard Hinnantc9834542011-05-31 15:34:58 +0000491locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000492{
493 __locale_->__release_shared();
494}
495
496const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000497locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000498{
499 other.__locale_->__add_shared();
500 __locale_->__release_shared();
501 __locale_ = other.__locale_;
502 return *this;
503}
504
505locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000506#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000507 : __locale_(name ? new __imp(name)
508 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000509#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000510 : __locale_(new __imp(name))
511#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000512{
513 __locale_->__add_shared();
514}
515
516locale::locale(const string& name)
517 : __locale_(new __imp(name))
518{
519 __locale_->__add_shared();
520}
521
522locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000523#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000524 : __locale_(name ? new __imp(*other.__locale_, name, c)
525 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000526#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000527 : __locale_(new __imp(*other.__locale_, name, c))
528#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000529{
530 __locale_->__add_shared();
531}
532
533locale::locale(const locale& other, const string& name, category c)
534 : __locale_(new __imp(*other.__locale_, name, c))
535{
536 __locale_->__add_shared();
537}
538
539locale::locale(const locale& other, const locale& one, category c)
540 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
541{
542 __locale_->__add_shared();
543}
544
545string
546locale::name() const
547{
548 return __locale_->name();
549}
550
551void
552locale::__install_ctor(const locale& other, facet* f, long id)
553{
554 if (f)
555 __locale_ = new __imp(*other.__locale_, f, id);
556 else
557 __locale_ = other.__locale_;
558 __locale_->__add_shared();
559}
560
561locale
562locale::global(const locale& loc)
563{
564 locale& g = __global();
565 locale r = g;
566 g = loc;
567 if (g.name() != "*")
568 setlocale(LC_ALL, g.name().c_str());
569 return r;
570}
571
572bool
573locale::has_facet(id& x) const
574{
575 return __locale_->has_facet(x.__get());
576}
577
578const locale::facet*
579locale::use_facet(id& x) const
580{
581 return __locale_->use_facet(x.__get());
582}
583
584bool
585locale::operator==(const locale& y) const
586{
587 return (__locale_ == y.__locale_)
588 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
589}
590
591// locale::facet
592
593locale::facet::~facet()
594{
595}
596
597void
Howard Hinnant1694d232011-05-28 14:41:13 +0000598locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000599{
600 delete this;
601}
602
603// locale::id
604
605int32_t locale::id::__next_id = 0;
606
607namespace
608{
609
610class __fake_bind
611{
612 locale::id* id_;
613 void (locale::id::* pmf_)();
614public:
615 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
616 : id_(id), pmf_(pmf) {}
617
618 void operator()() const
619 {
620 (id_->*pmf_)();
621 }
622};
623
624}
625
626long
627locale::id::__get()
628{
629 call_once(__flag_, __fake_bind(&locale::id::__init, this));
630 return __id_ - 1;
631}
632
633void
634locale::id::__init()
635{
Howard Hinnantadff4892010-05-24 17:49:41 +0000636 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000637}
638
639// template <> class collate_byname<char>
640
641collate_byname<char>::collate_byname(const char* n, size_t refs)
642 : collate<char>(refs),
643 __l(newlocale(LC_ALL_MASK, n, 0))
644{
Howard Hinnantd4444702010-08-11 17:04:31 +0000645#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000646 if (__l == 0)
647 throw runtime_error("collate_byname<char>::collate_byname"
648 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000649#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000650}
651
652collate_byname<char>::collate_byname(const string& name, size_t refs)
653 : collate<char>(refs),
654 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
655{
Howard Hinnantd4444702010-08-11 17:04:31 +0000656#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000657 if (__l == 0)
658 throw runtime_error("collate_byname<char>::collate_byname"
659 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000660#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000661}
662
663collate_byname<char>::~collate_byname()
664{
665 freelocale(__l);
666}
667
668int
669collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
670 const char_type* __lo2, const char_type* __hi2) const
671{
672 string_type lhs(__lo1, __hi1);
673 string_type rhs(__lo2, __hi2);
674 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
675 if (r < 0)
676 return -1;
677 if (r > 0)
678 return 1;
679 return r;
680}
681
682collate_byname<char>::string_type
683collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
684{
685 const string_type in(lo, hi);
686 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
687 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
688 return out;
689}
690
691// template <> class collate_byname<wchar_t>
692
693collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
694 : collate<wchar_t>(refs),
695 __l(newlocale(LC_ALL_MASK, n, 0))
696{
Howard Hinnantd4444702010-08-11 17:04:31 +0000697#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000698 if (__l == 0)
699 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
700 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000701#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000702}
703
704collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
705 : collate<wchar_t>(refs),
706 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
707{
Howard Hinnantd4444702010-08-11 17:04:31 +0000708#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000709 if (__l == 0)
710 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
711 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000712#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000713}
714
715collate_byname<wchar_t>::~collate_byname()
716{
717 freelocale(__l);
718}
719
720int
721collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
722 const char_type* __lo2, const char_type* __hi2) const
723{
724 string_type lhs(__lo1, __hi1);
725 string_type rhs(__lo2, __hi2);
726 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
727 if (r < 0)
728 return -1;
729 if (r > 0)
730 return 1;
731 return r;
732}
733
734collate_byname<wchar_t>::string_type
735collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
736{
737 const string_type in(lo, hi);
738 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
739 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
740 return out;
741}
742
743// template <> class ctype<wchar_t>;
744
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000745const ctype_base::mask ctype_base::space;
746const ctype_base::mask ctype_base::print;
747const ctype_base::mask ctype_base::cntrl;
748const ctype_base::mask ctype_base::upper;
749const ctype_base::mask ctype_base::lower;
750const ctype_base::mask ctype_base::alpha;
751const ctype_base::mask ctype_base::digit;
752const ctype_base::mask ctype_base::punct;
753const ctype_base::mask ctype_base::xdigit;
754const ctype_base::mask ctype_base::blank;
755const ctype_base::mask ctype_base::alnum;
756const ctype_base::mask ctype_base::graph;
757
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000758locale::id ctype<wchar_t>::id;
759
760ctype<wchar_t>::~ctype()
761{
762}
763
764bool
765ctype<wchar_t>::do_is(mask m, char_type c) const
766{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000767 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000768}
769
770const wchar_t*
771ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
772{
773 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000774 *vec = static_cast<mask>(isascii(*low) ?
775 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000776 return low;
777}
778
779const wchar_t*
780ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
781{
782 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000783 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000784 break;
785 return low;
786}
787
788const wchar_t*
789ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
790{
791 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000792 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000793 break;
794 return low;
795}
796
797wchar_t
798ctype<wchar_t>::do_toupper(char_type c) const
799{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000800#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
801 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000802#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000803 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000804#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000805 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000806#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000807}
808
809const wchar_t*
810ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
811{
812 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000813#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
814 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000815#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000816 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
817 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000818#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000819 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000820#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000821 return low;
822}
823
824wchar_t
825ctype<wchar_t>::do_tolower(char_type c) const
826{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000827#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
828 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000829#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000830 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000831#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000832 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000833#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000834}
835
836const wchar_t*
837ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
838{
839 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000840#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
841 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000842#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000843 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
844 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000845#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000846 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000847#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000848 return low;
849}
850
851wchar_t
852ctype<wchar_t>::do_widen(char c) const
853{
854 return c;
855}
856
857const char*
858ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
859{
860 for (; low != high; ++low, ++dest)
861 *dest = *low;
862 return low;
863}
864
865char
866ctype<wchar_t>::do_narrow(char_type c, char dfault) const
867{
868 if (isascii(c))
869 return static_cast<char>(c);
870 return dfault;
871}
872
873const wchar_t*
874ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
875{
876 for (; low != high; ++low, ++dest)
877 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000878 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000879 else
880 *dest = dfault;
881 return low;
882}
883
884// template <> class ctype<char>;
885
886locale::id ctype<char>::id;
887
888ctype<char>::ctype(const mask* tab, bool del, size_t refs)
889 : locale::facet(refs),
890 __tab_(tab),
891 __del_(del)
892{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000893 if (__tab_ == 0)
894 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000895}
896
897ctype<char>::~ctype()
898{
899 if (__tab_ && __del_)
900 delete [] __tab_;
901}
902
903char
904ctype<char>::do_toupper(char_type c) const
905{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000906#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000907 return isascii(c) ?
908 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000909#elif defined(__NetBSD__)
910 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000911#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000912 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000913 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000914#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000915 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000916#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000917}
918
919const char*
920ctype<char>::do_toupper(char_type* low, const char_type* high) const
921{
922 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000923#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000924 *low = isascii(*low) ?
925 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000926#elif defined(__NetBSD__)
927 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000928#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000929 *low = isascii(*low) ?
930 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000931#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000932 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000933#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000934 return low;
935}
936
937char
938ctype<char>::do_tolower(char_type c) const
939{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000940#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000941 return isascii(c) ?
942 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000943#elif defined(__NetBSD__)
944 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
945#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Marshall Clow88c31902013-02-07 14:22:51 +0000946 return isascii(c) ?
947 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000948#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000949 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000950#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000951}
952
953const char*
954ctype<char>::do_tolower(char_type* low, const char_type* high) const
955{
956 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000957#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000958 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000959#elif defined(__NetBSD__)
960 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000961#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clow88c31902013-02-07 14:22:51 +0000962 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000963#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000964 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000965#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000966 return low;
967}
968
969char
970ctype<char>::do_widen(char c) const
971{
972 return c;
973}
974
975const char*
976ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
977{
978 for (; low != high; ++low, ++dest)
979 *dest = *low;
980 return low;
981}
982
983char
984ctype<char>::do_narrow(char_type c, char dfault) const
985{
986 if (isascii(c))
987 return static_cast<char>(c);
988 return dfault;
989}
990
991const char*
992ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
993{
994 for (; low != high; ++low, ++dest)
995 if (isascii(*low))
996 *dest = *low;
997 else
998 *dest = dfault;
999 return low;
1000}
1001
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001002#ifdef EMSCRIPTEN
1003extern "C" const unsigned short ** __ctype_b_loc();
1004extern "C" const int ** __ctype_tolower_loc();
1005extern "C" const int ** __ctype_toupper_loc();
1006#endif
1007
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001008const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001009ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001010{
David Chisnallc512df12011-09-21 08:39:44 +00001011#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001012 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001013#elif defined(__NetBSD__)
1014 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001015#elif defined(__GLIBC__)
1016 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001017#elif __sun__
1018 return __ctype_mask;
Howard Hinnantef5aa932013-09-17 01:34:47 +00001019#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001020 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001021// This is assumed to be safe, which is a nonsense assumption because we're
1022// going to end up dereferencing it later...
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001023#elif defined(EMSCRIPTEN)
1024 return *__ctype_b_loc();
Howard Hinnant7f764502013-08-14 18:00:20 +00001025#elif defined(_AIX)
1026 return (const unsigned long *)__lc_ctype_ptr->obj->mask;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001027#else
David Chisnall997e4542012-02-29 13:05:08 +00001028 // Platform not supported: abort so the person doing the port knows what to
1029 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001030# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001031 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001032 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001033 return NULL;
1034#endif
1035}
1036
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001037#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001038const int*
1039ctype<char>::__classic_lower_table() _NOEXCEPT
1040{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001041 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001042}
1043
1044const int*
1045ctype<char>::__classic_upper_table() _NOEXCEPT
1046{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001047 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001048}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001049#elif __NetBSD__
1050const short*
1051ctype<char>::__classic_lower_table() _NOEXCEPT
1052{
1053 return _C_tolower_tab_ + 1;
1054}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001055
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001056const short*
1057ctype<char>::__classic_upper_table() _NOEXCEPT
1058{
1059 return _C_toupper_tab_ + 1;
1060}
1061
1062#elif defined(EMSCRIPTEN)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001063const int*
1064ctype<char>::__classic_lower_table() _NOEXCEPT
1065{
1066 return *__ctype_tolower_loc();
1067}
1068
1069const int*
1070ctype<char>::__classic_upper_table() _NOEXCEPT
1071{
1072 return *__ctype_toupper_loc();
1073}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001074#endif // __GLIBC__ || EMSCRIPTEN || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001075
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001076// template <> class ctype_byname<char>
1077
1078ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1079 : ctype<char>(0, false, refs),
1080 __l(newlocale(LC_ALL_MASK, name, 0))
1081{
Howard Hinnantd4444702010-08-11 17:04:31 +00001082#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001083 if (__l == 0)
1084 throw runtime_error("ctype_byname<char>::ctype_byname"
1085 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001086#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001087}
1088
1089ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1090 : ctype<char>(0, false, refs),
1091 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1092{
Howard Hinnantd4444702010-08-11 17:04:31 +00001093#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001094 if (__l == 0)
1095 throw runtime_error("ctype_byname<char>::ctype_byname"
1096 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001097#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001098}
1099
1100ctype_byname<char>::~ctype_byname()
1101{
1102 freelocale(__l);
1103}
1104
1105char
1106ctype_byname<char>::do_toupper(char_type c) const
1107{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001108 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001109}
1110
1111const char*
1112ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1113{
1114 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001115 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001116 return low;
1117}
1118
1119char
1120ctype_byname<char>::do_tolower(char_type c) const
1121{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001122 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001123}
1124
1125const char*
1126ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1127{
1128 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001129 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001130 return low;
1131}
1132
1133// template <> class ctype_byname<wchar_t>
1134
1135ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1136 : ctype<wchar_t>(refs),
1137 __l(newlocale(LC_ALL_MASK, name, 0))
1138{
Howard Hinnantd4444702010-08-11 17:04:31 +00001139#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001140 if (__l == 0)
1141 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1142 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001143#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001144}
1145
1146ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1147 : ctype<wchar_t>(refs),
1148 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1149{
Howard Hinnantd4444702010-08-11 17:04:31 +00001150#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001151 if (__l == 0)
1152 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1153 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001154#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001155}
1156
1157ctype_byname<wchar_t>::~ctype_byname()
1158{
1159 freelocale(__l);
1160}
1161
1162bool
1163ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1164{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001165#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001166 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001167#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001168 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001169 wint_t ch = static_cast<wint_t>(c);
1170 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1171 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1172 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1173 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1174 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1175 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1176 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1177 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1178 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1179 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001180 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001181#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001182}
1183
1184const wchar_t*
1185ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1186{
1187 for (; low != high; ++low, ++vec)
1188 {
1189 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001190 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001191 else
1192 {
1193 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001194 wint_t ch = static_cast<wint_t>(*low);
1195 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001196 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001197 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001198 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001199 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001201 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001202 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001203 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001204 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001205 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001206 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001207 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001208 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001209 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001210 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001211 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001212 *vec |= xdigit;
1213 }
1214 }
1215 return low;
1216}
1217
1218const wchar_t*
1219ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1220{
1221 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001222 {
1223#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001224 if (iswctype_l(*low, m, __l))
1225 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001226#else
Marshall Clow88c31902013-02-07 14:22:51 +00001227 wint_t ch = static_cast<wint_t>(*low);
1228 if (m & space && iswspace_l(ch, __l)) break;
1229 if (m & print && iswprint_l(ch, __l)) break;
1230 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1231 if (m & upper && iswupper_l(ch, __l)) break;
1232 if (m & lower && iswlower_l(ch, __l)) break;
1233 if (m & alpha && iswalpha_l(ch, __l)) break;
1234 if (m & digit && iswdigit_l(ch, __l)) break;
1235 if (m & punct && iswpunct_l(ch, __l)) break;
1236 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1237 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001238#endif
1239 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 return low;
1241}
1242
1243const wchar_t*
1244ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1245{
1246 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001247 {
1248#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001249 if (!iswctype_l(*low, m, __l))
1250 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001251#else
Marshall Clow88c31902013-02-07 14:22:51 +00001252 wint_t ch = static_cast<wint_t>(*low);
1253 if (m & space && iswspace_l(ch, __l)) continue;
1254 if (m & print && iswprint_l(ch, __l)) continue;
1255 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1256 if (m & upper && iswupper_l(ch, __l)) continue;
1257 if (m & lower && iswlower_l(ch, __l)) continue;
1258 if (m & alpha && iswalpha_l(ch, __l)) continue;
1259 if (m & digit && iswdigit_l(ch, __l)) continue;
1260 if (m & punct && iswpunct_l(ch, __l)) continue;
1261 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1262 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001263 break;
1264#endif
1265 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001266 return low;
1267}
1268
1269wchar_t
1270ctype_byname<wchar_t>::do_toupper(char_type c) const
1271{
1272 return towupper_l(c, __l);
1273}
1274
1275const wchar_t*
1276ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1277{
1278 for (; low != high; ++low)
1279 *low = towupper_l(*low, __l);
1280 return low;
1281}
1282
1283wchar_t
1284ctype_byname<wchar_t>::do_tolower(char_type c) const
1285{
1286 return towlower_l(c, __l);
1287}
1288
1289const wchar_t*
1290ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1291{
1292 for (; low != high; ++low)
1293 *low = towlower_l(*low, __l);
1294 return low;
1295}
1296
1297wchar_t
1298ctype_byname<wchar_t>::do_widen(char c) const
1299{
Howard Hinnant866569b2011-09-28 23:39:33 +00001300#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001301 return btowc_l(c, __l);
1302#else
1303 return __btowc_l(c, __l);
1304#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001305}
1306
1307const char*
1308ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1309{
1310 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001311#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001312 *dest = btowc_l(*low, __l);
1313#else
1314 *dest = __btowc_l(*low, __l);
1315#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001316 return low;
1317}
1318
1319char
1320ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1321{
Howard Hinnant866569b2011-09-28 23:39:33 +00001322#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001323 int r = wctob_l(c, __l);
1324#else
1325 int r = __wctob_l(c, __l);
1326#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001327 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001328}
1329
1330const wchar_t*
1331ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1332{
1333 for (; low != high; ++low, ++dest)
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(*low, __l);
1337#else
1338 int r = __wctob_l(*low, __l);
1339#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001340 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001341 }
1342 return low;
1343}
1344
1345// template <> class codecvt<char, char, mbstate_t>
1346
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001347locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001348
1349codecvt<char, char, mbstate_t>::~codecvt()
1350{
1351}
1352
1353codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001354codecvt<char, char, mbstate_t>::do_out(state_type&,
1355 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001356 extern_type* to, extern_type*, extern_type*& to_nxt) const
1357{
1358 frm_nxt = frm;
1359 to_nxt = to;
1360 return noconv;
1361}
1362
1363codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001364codecvt<char, char, mbstate_t>::do_in(state_type&,
1365 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001366 intern_type* to, intern_type*, intern_type*& to_nxt) const
1367{
1368 frm_nxt = frm;
1369 to_nxt = to;
1370 return noconv;
1371}
1372
1373codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001374codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001375 extern_type* to, extern_type*, extern_type*& to_nxt) const
1376{
1377 to_nxt = to;
1378 return noconv;
1379}
1380
1381int
Howard Hinnantc9834542011-05-31 15:34:58 +00001382codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001383{
1384 return 1;
1385}
1386
1387bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001388codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001389{
1390 return true;
1391}
1392
1393int
1394codecvt<char, char, mbstate_t>::do_length(state_type&,
1395 const extern_type* frm, const extern_type* end, size_t mx) const
1396{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001397 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001398}
1399
1400int
Howard Hinnantc9834542011-05-31 15:34:58 +00001401codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001402{
1403 return 1;
1404}
1405
1406// template <> class codecvt<wchar_t, char, mbstate_t>
1407
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001408locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001409
1410codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1411 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001412 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001413{
1414}
1415
1416codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1417 : locale::facet(refs),
1418 __l(newlocale(LC_ALL_MASK, nm, 0))
1419{
Howard Hinnantd4444702010-08-11 17:04:31 +00001420#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001421 if (__l == 0)
1422 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1423 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001424#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001425}
1426
1427codecvt<wchar_t, char, mbstate_t>::~codecvt()
1428{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001429 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001430 freelocale(__l);
1431}
1432
1433codecvt<wchar_t, char, mbstate_t>::result
1434codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001435 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001436 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1437{
1438 // look for first internal null in frm
1439 const intern_type* fend = frm;
1440 for (; fend != frm_end; ++fend)
1441 if (*fend == 0)
1442 break;
1443 // loop over all null-terminated sequences in frm
1444 to_nxt = to;
1445 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1446 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001447 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001448 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001449#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001450 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1451 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001452#else
1453 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1454#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001455 if (n == size_t(-1))
1456 {
1457 // need to recover to_nxt
1458 for (to_nxt = to; frm != frm_nxt; ++frm)
1459 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001460#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001461 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1462#else
1463 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1464#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001465 if (n == size_t(-1))
1466 break;
1467 to_nxt += n;
1468 }
1469 frm_nxt = frm;
1470 return error;
1471 }
1472 if (n == 0)
1473 return partial;
1474 to_nxt += n;
1475 if (to_nxt == to_end)
1476 break;
1477 if (fend != frm_end) // set up next null terminated sequence
1478 {
1479 // Try to write the terminating null
1480 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001481#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001482 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1483#else
1484 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1485#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001486 if (n == size_t(-1)) // on error
1487 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001488 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001489 return partial;
1490 for (extern_type* p = tmp; n; --n) // write it
1491 *to_nxt++ = *p++;
1492 ++frm_nxt;
1493 // look for next null in frm
1494 for (fend = frm_nxt; fend != frm_end; ++fend)
1495 if (*fend == 0)
1496 break;
1497 }
1498 }
1499 return frm_nxt == frm_end ? ok : partial;
1500}
1501
1502codecvt<wchar_t, char, mbstate_t>::result
1503codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001504 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001505 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1506{
1507 // look for first internal null in frm
1508 const extern_type* fend = frm;
1509 for (; fend != frm_end; ++fend)
1510 if (*fend == 0)
1511 break;
1512 // loop over all null-terminated sequences in frm
1513 to_nxt = to;
1514 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1515 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001516 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001517 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001518#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001519 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1520 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001521#else
1522 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1523#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001524 if (n == size_t(-1))
1525 {
1526 // need to recover to_nxt
1527 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1528 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001529#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001530 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1531 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001532#else
1533 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1534#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001535 switch (n)
1536 {
1537 case 0:
1538 ++frm;
1539 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001540 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001541 frm_nxt = frm;
1542 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001543 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001544 frm_nxt = frm;
1545 return partial;
1546 default:
1547 frm += n;
1548 break;
1549 }
1550 }
1551 frm_nxt = frm;
1552 return frm_nxt == frm_end ? ok : partial;
1553 }
1554 if (n == 0)
1555 return error;
1556 to_nxt += n;
1557 if (to_nxt == to_end)
1558 break;
1559 if (fend != frm_end) // set up next null terminated sequence
1560 {
1561 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001562#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001563 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1564#else
1565 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1566#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001567 if (n != 0) // on error
1568 return error;
1569 ++to_nxt;
1570 ++frm_nxt;
1571 // look for next null in frm
1572 for (fend = frm_nxt; fend != frm_end; ++fend)
1573 if (*fend == 0)
1574 break;
1575 }
1576 }
1577 return frm_nxt == frm_end ? ok : partial;
1578}
1579
1580codecvt<wchar_t, char, mbstate_t>::result
1581codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1582 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1583{
1584 to_nxt = to;
1585 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001586#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001587 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1588#else
1589 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1590#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001591 if (n == size_t(-1) || n == 0) // on error
1592 return error;
1593 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001594 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001595 return partial;
1596 for (extern_type* p = tmp; n; --n) // write it
1597 *to_nxt++ = *p++;
1598 return ok;
1599}
1600
1601int
Howard Hinnantc9834542011-05-31 15:34:58 +00001602codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001603{
Howard Hinnant866569b2011-09-28 23:39:33 +00001604#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001605 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1606#else
1607 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1608#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001609 {
1610 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001611#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001612 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1613#else
1614 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1615#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001616 return 1; // which take more than 1 char to form a wchar_t
1617 return 0;
1618 }
1619 return -1;
1620}
1621
1622bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001623codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001624{
1625 return false;
1626}
1627
1628int
1629codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1630 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1631{
1632 int nbytes = 0;
1633 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1634 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001635#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001636 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001637#else
1638 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1639#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001640 switch (n)
1641 {
1642 case 0:
1643 ++nbytes;
1644 ++frm;
1645 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001646 case size_t(-1):
1647 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001648 return nbytes;
1649 default:
1650 nbytes += n;
1651 frm += n;
1652 break;
1653 }
1654 }
1655 return nbytes;
1656}
1657
1658int
Howard Hinnantc9834542011-05-31 15:34:58 +00001659codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001660{
Howard Hinnant866569b2011-09-28 23:39:33 +00001661#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001662 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001663#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001664 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001665#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001666}
1667
1668// Valid UTF ranges
1669// UTF-32 UTF-16 UTF-8 # of code points
1670// first second first second third fourth
1671// 000000 - 00007F 0000 - 007F 00 - 7F 127
1672// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1673// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1674// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1675// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1676// 00D800 - 00DFFF invalid
1677// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1678// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1679// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1680// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1681
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001682static
1683codecvt_base::result
1684utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1685 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1686 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1687{
1688 frm_nxt = frm;
1689 to_nxt = to;
1690 if (mode & generate_header)
1691 {
1692 if (to_end-to_nxt < 3)
1693 return codecvt_base::partial;
1694 *to_nxt++ = static_cast<uint8_t>(0xEF);
1695 *to_nxt++ = static_cast<uint8_t>(0xBB);
1696 *to_nxt++ = static_cast<uint8_t>(0xBF);
1697 }
1698 for (; frm_nxt < frm_end; ++frm_nxt)
1699 {
1700 uint16_t wc1 = *frm_nxt;
1701 if (wc1 > Maxcode)
1702 return codecvt_base::error;
1703 if (wc1 < 0x0080)
1704 {
1705 if (to_end-to_nxt < 1)
1706 return codecvt_base::partial;
1707 *to_nxt++ = static_cast<uint8_t>(wc1);
1708 }
1709 else if (wc1 < 0x0800)
1710 {
1711 if (to_end-to_nxt < 2)
1712 return codecvt_base::partial;
1713 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1714 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1715 }
1716 else if (wc1 < 0xD800)
1717 {
1718 if (to_end-to_nxt < 3)
1719 return codecvt_base::partial;
1720 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1721 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1722 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1723 }
1724 else if (wc1 < 0xDC00)
1725 {
1726 if (frm_end-frm_nxt < 2)
1727 return codecvt_base::partial;
1728 uint16_t wc2 = frm_nxt[1];
1729 if ((wc2 & 0xFC00) != 0xDC00)
1730 return codecvt_base::error;
1731 if (to_end-to_nxt < 4)
1732 return codecvt_base::partial;
1733 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1734 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1735 return codecvt_base::error;
1736 ++frm_nxt;
1737 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1738 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1739 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1740 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1741 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1742 }
1743 else if (wc1 < 0xE000)
1744 {
1745 return codecvt_base::error;
1746 }
1747 else
1748 {
1749 if (to_end-to_nxt < 3)
1750 return codecvt_base::partial;
1751 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1752 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1753 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1754 }
1755 }
1756 return codecvt_base::ok;
1757}
1758
1759static
1760codecvt_base::result
1761utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1762 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1763 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1764{
1765 frm_nxt = frm;
1766 to_nxt = to;
1767 if (mode & generate_header)
1768 {
1769 if (to_end-to_nxt < 3)
1770 return codecvt_base::partial;
1771 *to_nxt++ = static_cast<uint8_t>(0xEF);
1772 *to_nxt++ = static_cast<uint8_t>(0xBB);
1773 *to_nxt++ = static_cast<uint8_t>(0xBF);
1774 }
1775 for (; frm_nxt < frm_end; ++frm_nxt)
1776 {
1777 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1778 if (wc1 > Maxcode)
1779 return codecvt_base::error;
1780 if (wc1 < 0x0080)
1781 {
1782 if (to_end-to_nxt < 1)
1783 return codecvt_base::partial;
1784 *to_nxt++ = static_cast<uint8_t>(wc1);
1785 }
1786 else if (wc1 < 0x0800)
1787 {
1788 if (to_end-to_nxt < 2)
1789 return codecvt_base::partial;
1790 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1791 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1792 }
1793 else if (wc1 < 0xD800)
1794 {
1795 if (to_end-to_nxt < 3)
1796 return codecvt_base::partial;
1797 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1798 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1799 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1800 }
1801 else if (wc1 < 0xDC00)
1802 {
1803 if (frm_end-frm_nxt < 2)
1804 return codecvt_base::partial;
1805 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1806 if ((wc2 & 0xFC00) != 0xDC00)
1807 return codecvt_base::error;
1808 if (to_end-to_nxt < 4)
1809 return codecvt_base::partial;
1810 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1811 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1812 return codecvt_base::error;
1813 ++frm_nxt;
1814 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1815 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1816 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1817 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1818 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1819 }
1820 else if (wc1 < 0xE000)
1821 {
1822 return codecvt_base::error;
1823 }
1824 else
1825 {
1826 if (to_end-to_nxt < 3)
1827 return codecvt_base::partial;
1828 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1829 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1830 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1831 }
1832 }
1833 return codecvt_base::ok;
1834}
1835
1836static
1837codecvt_base::result
1838utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1839 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1840 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1841{
1842 frm_nxt = frm;
1843 to_nxt = to;
1844 if (mode & consume_header)
1845 {
1846 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1847 frm_nxt[2] == 0xBF)
1848 frm_nxt += 3;
1849 }
1850 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1851 {
1852 uint8_t c1 = *frm_nxt;
1853 if (c1 > Maxcode)
1854 return codecvt_base::error;
1855 if (c1 < 0x80)
1856 {
1857 *to_nxt = static_cast<uint16_t>(c1);
1858 ++frm_nxt;
1859 }
1860 else if (c1 < 0xC2)
1861 {
1862 return codecvt_base::error;
1863 }
1864 else if (c1 < 0xE0)
1865 {
1866 if (frm_end-frm_nxt < 2)
1867 return codecvt_base::partial;
1868 uint8_t c2 = frm_nxt[1];
1869 if ((c2 & 0xC0) != 0x80)
1870 return codecvt_base::error;
1871 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1872 if (t > Maxcode)
1873 return codecvt_base::error;
1874 *to_nxt = t;
1875 frm_nxt += 2;
1876 }
1877 else if (c1 < 0xF0)
1878 {
1879 if (frm_end-frm_nxt < 3)
1880 return codecvt_base::partial;
1881 uint8_t c2 = frm_nxt[1];
1882 uint8_t c3 = frm_nxt[2];
1883 switch (c1)
1884 {
1885 case 0xE0:
1886 if ((c2 & 0xE0) != 0xA0)
1887 return codecvt_base::error;
1888 break;
1889 case 0xED:
1890 if ((c2 & 0xE0) != 0x80)
1891 return codecvt_base::error;
1892 break;
1893 default:
1894 if ((c2 & 0xC0) != 0x80)
1895 return codecvt_base::error;
1896 break;
1897 }
1898 if ((c3 & 0xC0) != 0x80)
1899 return codecvt_base::error;
1900 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1901 | ((c2 & 0x3F) << 6)
1902 | (c3 & 0x3F));
1903 if (t > Maxcode)
1904 return codecvt_base::error;
1905 *to_nxt = t;
1906 frm_nxt += 3;
1907 }
1908 else if (c1 < 0xF5)
1909 {
1910 if (frm_end-frm_nxt < 4)
1911 return codecvt_base::partial;
1912 uint8_t c2 = frm_nxt[1];
1913 uint8_t c3 = frm_nxt[2];
1914 uint8_t c4 = frm_nxt[3];
1915 switch (c1)
1916 {
1917 case 0xF0:
1918 if (!(0x90 <= c2 && c2 <= 0xBF))
1919 return codecvt_base::error;
1920 break;
1921 case 0xF4:
1922 if ((c2 & 0xF0) != 0x80)
1923 return codecvt_base::error;
1924 break;
1925 default:
1926 if ((c2 & 0xC0) != 0x80)
1927 return codecvt_base::error;
1928 break;
1929 }
1930 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1931 return codecvt_base::error;
1932 if (to_end-to_nxt < 2)
1933 return codecvt_base::partial;
1934 if (((((unsigned long)c1 & 7) << 18) +
1935 (((unsigned long)c2 & 0x3F) << 12) +
1936 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1937 return codecvt_base::error;
1938 *to_nxt = static_cast<uint16_t>(
1939 0xD800
1940 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1941 | ((c2 & 0x0F) << 2)
1942 | ((c3 & 0x30) >> 4));
1943 *++to_nxt = static_cast<uint16_t>(
1944 0xDC00
1945 | ((c3 & 0x0F) << 6)
1946 | (c4 & 0x3F));
1947 frm_nxt += 4;
1948 }
1949 else
1950 {
1951 return codecvt_base::error;
1952 }
1953 }
1954 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1955}
1956
1957static
1958codecvt_base::result
1959utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1960 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1961 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1962{
1963 frm_nxt = frm;
1964 to_nxt = to;
1965 if (mode & consume_header)
1966 {
1967 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1968 frm_nxt[2] == 0xBF)
1969 frm_nxt += 3;
1970 }
1971 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1972 {
1973 uint8_t c1 = *frm_nxt;
1974 if (c1 > Maxcode)
1975 return codecvt_base::error;
1976 if (c1 < 0x80)
1977 {
1978 *to_nxt = static_cast<uint32_t>(c1);
1979 ++frm_nxt;
1980 }
1981 else if (c1 < 0xC2)
1982 {
1983 return codecvt_base::error;
1984 }
1985 else if (c1 < 0xE0)
1986 {
1987 if (frm_end-frm_nxt < 2)
1988 return codecvt_base::partial;
1989 uint8_t c2 = frm_nxt[1];
1990 if ((c2 & 0xC0) != 0x80)
1991 return codecvt_base::error;
1992 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1993 if (t > Maxcode)
1994 return codecvt_base::error;
1995 *to_nxt = static_cast<uint32_t>(t);
1996 frm_nxt += 2;
1997 }
1998 else if (c1 < 0xF0)
1999 {
2000 if (frm_end-frm_nxt < 3)
2001 return codecvt_base::partial;
2002 uint8_t c2 = frm_nxt[1];
2003 uint8_t c3 = frm_nxt[2];
2004 switch (c1)
2005 {
2006 case 0xE0:
2007 if ((c2 & 0xE0) != 0xA0)
2008 return codecvt_base::error;
2009 break;
2010 case 0xED:
2011 if ((c2 & 0xE0) != 0x80)
2012 return codecvt_base::error;
2013 break;
2014 default:
2015 if ((c2 & 0xC0) != 0x80)
2016 return codecvt_base::error;
2017 break;
2018 }
2019 if ((c3 & 0xC0) != 0x80)
2020 return codecvt_base::error;
2021 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2022 | ((c2 & 0x3F) << 6)
2023 | (c3 & 0x3F));
2024 if (t > Maxcode)
2025 return codecvt_base::error;
2026 *to_nxt = static_cast<uint32_t>(t);
2027 frm_nxt += 3;
2028 }
2029 else if (c1 < 0xF5)
2030 {
2031 if (frm_end-frm_nxt < 4)
2032 return codecvt_base::partial;
2033 uint8_t c2 = frm_nxt[1];
2034 uint8_t c3 = frm_nxt[2];
2035 uint8_t c4 = frm_nxt[3];
2036 switch (c1)
2037 {
2038 case 0xF0:
2039 if (!(0x90 <= c2 && c2 <= 0xBF))
2040 return codecvt_base::error;
2041 break;
2042 case 0xF4:
2043 if ((c2 & 0xF0) != 0x80)
2044 return codecvt_base::error;
2045 break;
2046 default:
2047 if ((c2 & 0xC0) != 0x80)
2048 return codecvt_base::error;
2049 break;
2050 }
2051 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2052 return codecvt_base::error;
2053 if (to_end-to_nxt < 2)
2054 return codecvt_base::partial;
2055 if (((((unsigned long)c1 & 7) << 18) +
2056 (((unsigned long)c2 & 0x3F) << 12) +
2057 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2058 return codecvt_base::error;
2059 *to_nxt = static_cast<uint32_t>(
2060 0xD800
2061 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2062 | ((c2 & 0x0F) << 2)
2063 | ((c3 & 0x30) >> 4));
2064 *++to_nxt = static_cast<uint32_t>(
2065 0xDC00
2066 | ((c3 & 0x0F) << 6)
2067 | (c4 & 0x3F));
2068 frm_nxt += 4;
2069 }
2070 else
2071 {
2072 return codecvt_base::error;
2073 }
2074 }
2075 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2076}
2077
2078static
2079int
2080utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2081 size_t mx, unsigned long Maxcode = 0x10FFFF,
2082 codecvt_mode mode = codecvt_mode(0))
2083{
2084 const uint8_t* frm_nxt = frm;
2085 if (mode & consume_header)
2086 {
2087 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2088 frm_nxt[2] == 0xBF)
2089 frm_nxt += 3;
2090 }
2091 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2092 {
2093 uint8_t c1 = *frm_nxt;
2094 if (c1 > Maxcode)
2095 break;
2096 if (c1 < 0x80)
2097 {
2098 ++frm_nxt;
2099 }
2100 else if (c1 < 0xC2)
2101 {
2102 break;
2103 }
2104 else if (c1 < 0xE0)
2105 {
2106 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2107 break;
2108 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2109 if (t > Maxcode)
2110 break;
2111 frm_nxt += 2;
2112 }
2113 else if (c1 < 0xF0)
2114 {
2115 if (frm_end-frm_nxt < 3)
2116 break;
2117 uint8_t c2 = frm_nxt[1];
2118 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002119 switch (c1)
2120 {
2121 case 0xE0:
2122 if ((c2 & 0xE0) != 0xA0)
2123 return static_cast<int>(frm_nxt - frm);
2124 break;
2125 case 0xED:
2126 if ((c2 & 0xE0) != 0x80)
2127 return static_cast<int>(frm_nxt - frm);
2128 break;
2129 default:
2130 if ((c2 & 0xC0) != 0x80)
2131 return static_cast<int>(frm_nxt - frm);
2132 break;
2133 }
2134 if ((c3 & 0xC0) != 0x80)
2135 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002136 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002137 break;
2138 frm_nxt += 3;
2139 }
2140 else if (c1 < 0xF5)
2141 {
2142 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2143 break;
2144 uint8_t c2 = frm_nxt[1];
2145 uint8_t c3 = frm_nxt[2];
2146 uint8_t c4 = frm_nxt[3];
2147 switch (c1)
2148 {
2149 case 0xF0:
2150 if (!(0x90 <= c2 && c2 <= 0xBF))
2151 return static_cast<int>(frm_nxt - frm);
2152 break;
2153 case 0xF4:
2154 if ((c2 & 0xF0) != 0x80)
2155 return static_cast<int>(frm_nxt - frm);
2156 break;
2157 default:
2158 if ((c2 & 0xC0) != 0x80)
2159 return static_cast<int>(frm_nxt - frm);
2160 break;
2161 }
2162 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2163 break;
2164 if (((((unsigned long)c1 & 7) << 18) +
2165 (((unsigned long)c2 & 0x3F) << 12) +
2166 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2167 break;
2168 ++nchar16_t;
2169 frm_nxt += 4;
2170 }
2171 else
2172 {
2173 break;
2174 }
2175 }
2176 return static_cast<int>(frm_nxt - frm);
2177}
2178
2179static
2180codecvt_base::result
2181ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2182 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2183 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2184{
2185 frm_nxt = frm;
2186 to_nxt = to;
2187 if (mode & generate_header)
2188 {
2189 if (to_end-to_nxt < 3)
2190 return codecvt_base::partial;
2191 *to_nxt++ = static_cast<uint8_t>(0xEF);
2192 *to_nxt++ = static_cast<uint8_t>(0xBB);
2193 *to_nxt++ = static_cast<uint8_t>(0xBF);
2194 }
2195 for (; frm_nxt < frm_end; ++frm_nxt)
2196 {
2197 uint32_t wc = *frm_nxt;
2198 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2199 return codecvt_base::error;
2200 if (wc < 0x000080)
2201 {
2202 if (to_end-to_nxt < 1)
2203 return codecvt_base::partial;
2204 *to_nxt++ = static_cast<uint8_t>(wc);
2205 }
2206 else if (wc < 0x000800)
2207 {
2208 if (to_end-to_nxt < 2)
2209 return codecvt_base::partial;
2210 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2211 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2212 }
2213 else if (wc < 0x010000)
2214 {
2215 if (to_end-to_nxt < 3)
2216 return codecvt_base::partial;
2217 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2218 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2219 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2220 }
2221 else // if (wc < 0x110000)
2222 {
2223 if (to_end-to_nxt < 4)
2224 return codecvt_base::partial;
2225 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2226 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2227 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2228 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2229 }
2230 }
2231 return codecvt_base::ok;
2232}
2233
2234static
2235codecvt_base::result
2236utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2237 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2238 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2239{
2240 frm_nxt = frm;
2241 to_nxt = to;
2242 if (mode & consume_header)
2243 {
2244 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2245 frm_nxt[2] == 0xBF)
2246 frm_nxt += 3;
2247 }
2248 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2249 {
2250 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2251 if (c1 < 0x80)
2252 {
2253 if (c1 > Maxcode)
2254 return codecvt_base::error;
2255 *to_nxt = static_cast<uint32_t>(c1);
2256 ++frm_nxt;
2257 }
2258 else if (c1 < 0xC2)
2259 {
2260 return codecvt_base::error;
2261 }
2262 else if (c1 < 0xE0)
2263 {
2264 if (frm_end-frm_nxt < 2)
2265 return codecvt_base::partial;
2266 uint8_t c2 = frm_nxt[1];
2267 if ((c2 & 0xC0) != 0x80)
2268 return codecvt_base::error;
2269 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2270 | (c2 & 0x3F));
2271 if (t > Maxcode)
2272 return codecvt_base::error;
2273 *to_nxt = t;
2274 frm_nxt += 2;
2275 }
2276 else if (c1 < 0xF0)
2277 {
2278 if (frm_end-frm_nxt < 3)
2279 return codecvt_base::partial;
2280 uint8_t c2 = frm_nxt[1];
2281 uint8_t c3 = frm_nxt[2];
2282 switch (c1)
2283 {
2284 case 0xE0:
2285 if ((c2 & 0xE0) != 0xA0)
2286 return codecvt_base::error;
2287 break;
2288 case 0xED:
2289 if ((c2 & 0xE0) != 0x80)
2290 return codecvt_base::error;
2291 break;
2292 default:
2293 if ((c2 & 0xC0) != 0x80)
2294 return codecvt_base::error;
2295 break;
2296 }
2297 if ((c3 & 0xC0) != 0x80)
2298 return codecvt_base::error;
2299 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2300 | ((c2 & 0x3F) << 6)
2301 | (c3 & 0x3F));
2302 if (t > Maxcode)
2303 return codecvt_base::error;
2304 *to_nxt = t;
2305 frm_nxt += 3;
2306 }
2307 else if (c1 < 0xF5)
2308 {
2309 if (frm_end-frm_nxt < 4)
2310 return codecvt_base::partial;
2311 uint8_t c2 = frm_nxt[1];
2312 uint8_t c3 = frm_nxt[2];
2313 uint8_t c4 = frm_nxt[3];
2314 switch (c1)
2315 {
2316 case 0xF0:
2317 if (!(0x90 <= c2 && c2 <= 0xBF))
2318 return codecvt_base::error;
2319 break;
2320 case 0xF4:
2321 if ((c2 & 0xF0) != 0x80)
2322 return codecvt_base::error;
2323 break;
2324 default:
2325 if ((c2 & 0xC0) != 0x80)
2326 return codecvt_base::error;
2327 break;
2328 }
2329 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2330 return codecvt_base::error;
2331 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2332 | ((c2 & 0x3F) << 12)
2333 | ((c3 & 0x3F) << 6)
2334 | (c4 & 0x3F));
2335 if (t > Maxcode)
2336 return codecvt_base::error;
2337 *to_nxt = t;
2338 frm_nxt += 4;
2339 }
2340 else
2341 {
2342 return codecvt_base::error;
2343 }
2344 }
2345 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2346}
2347
2348static
2349int
2350utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2351 size_t mx, unsigned long Maxcode = 0x10FFFF,
2352 codecvt_mode mode = codecvt_mode(0))
2353{
2354 const uint8_t* frm_nxt = frm;
2355 if (mode & consume_header)
2356 {
2357 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2358 frm_nxt[2] == 0xBF)
2359 frm_nxt += 3;
2360 }
2361 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2362 {
2363 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2364 if (c1 < 0x80)
2365 {
2366 if (c1 > Maxcode)
2367 break;
2368 ++frm_nxt;
2369 }
2370 else if (c1 < 0xC2)
2371 {
2372 break;
2373 }
2374 else if (c1 < 0xE0)
2375 {
2376 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2377 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002378 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002379 break;
2380 frm_nxt += 2;
2381 }
2382 else if (c1 < 0xF0)
2383 {
2384 if (frm_end-frm_nxt < 3)
2385 break;
2386 uint8_t c2 = frm_nxt[1];
2387 uint8_t c3 = frm_nxt[2];
2388 switch (c1)
2389 {
2390 case 0xE0:
2391 if ((c2 & 0xE0) != 0xA0)
2392 return static_cast<int>(frm_nxt - frm);
2393 break;
2394 case 0xED:
2395 if ((c2 & 0xE0) != 0x80)
2396 return static_cast<int>(frm_nxt - frm);
2397 break;
2398 default:
2399 if ((c2 & 0xC0) != 0x80)
2400 return static_cast<int>(frm_nxt - frm);
2401 break;
2402 }
2403 if ((c3 & 0xC0) != 0x80)
2404 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002405 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002406 break;
2407 frm_nxt += 3;
2408 }
2409 else if (c1 < 0xF5)
2410 {
2411 if (frm_end-frm_nxt < 4)
2412 break;
2413 uint8_t c2 = frm_nxt[1];
2414 uint8_t c3 = frm_nxt[2];
2415 uint8_t c4 = frm_nxt[3];
2416 switch (c1)
2417 {
2418 case 0xF0:
2419 if (!(0x90 <= c2 && c2 <= 0xBF))
2420 return static_cast<int>(frm_nxt - frm);
2421 break;
2422 case 0xF4:
2423 if ((c2 & 0xF0) != 0x80)
2424 return static_cast<int>(frm_nxt - frm);
2425 break;
2426 default:
2427 if ((c2 & 0xC0) != 0x80)
2428 return static_cast<int>(frm_nxt - frm);
2429 break;
2430 }
2431 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2432 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002433 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2434 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002435 break;
2436 frm_nxt += 4;
2437 }
2438 else
2439 {
2440 break;
2441 }
2442 }
2443 return static_cast<int>(frm_nxt - frm);
2444}
2445
2446static
2447codecvt_base::result
2448ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2449 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2450 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2451{
2452 frm_nxt = frm;
2453 to_nxt = to;
2454 if (mode & generate_header)
2455 {
2456 if (to_end-to_nxt < 3)
2457 return codecvt_base::partial;
2458 *to_nxt++ = static_cast<uint8_t>(0xEF);
2459 *to_nxt++ = static_cast<uint8_t>(0xBB);
2460 *to_nxt++ = static_cast<uint8_t>(0xBF);
2461 }
2462 for (; frm_nxt < frm_end; ++frm_nxt)
2463 {
2464 uint16_t wc = *frm_nxt;
2465 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2466 return codecvt_base::error;
2467 if (wc < 0x0080)
2468 {
2469 if (to_end-to_nxt < 1)
2470 return codecvt_base::partial;
2471 *to_nxt++ = static_cast<uint8_t>(wc);
2472 }
2473 else if (wc < 0x0800)
2474 {
2475 if (to_end-to_nxt < 2)
2476 return codecvt_base::partial;
2477 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2478 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2479 }
2480 else // if (wc <= 0xFFFF)
2481 {
2482 if (to_end-to_nxt < 3)
2483 return codecvt_base::partial;
2484 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2485 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2486 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2487 }
2488 }
2489 return codecvt_base::ok;
2490}
2491
2492static
2493codecvt_base::result
2494utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2495 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2496 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2497{
2498 frm_nxt = frm;
2499 to_nxt = to;
2500 if (mode & consume_header)
2501 {
2502 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2503 frm_nxt[2] == 0xBF)
2504 frm_nxt += 3;
2505 }
2506 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2507 {
2508 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2509 if (c1 < 0x80)
2510 {
2511 if (c1 > Maxcode)
2512 return codecvt_base::error;
2513 *to_nxt = static_cast<uint16_t>(c1);
2514 ++frm_nxt;
2515 }
2516 else if (c1 < 0xC2)
2517 {
2518 return codecvt_base::error;
2519 }
2520 else if (c1 < 0xE0)
2521 {
2522 if (frm_end-frm_nxt < 2)
2523 return codecvt_base::partial;
2524 uint8_t c2 = frm_nxt[1];
2525 if ((c2 & 0xC0) != 0x80)
2526 return codecvt_base::error;
2527 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2528 | (c2 & 0x3F));
2529 if (t > Maxcode)
2530 return codecvt_base::error;
2531 *to_nxt = t;
2532 frm_nxt += 2;
2533 }
2534 else if (c1 < 0xF0)
2535 {
2536 if (frm_end-frm_nxt < 3)
2537 return codecvt_base::partial;
2538 uint8_t c2 = frm_nxt[1];
2539 uint8_t c3 = frm_nxt[2];
2540 switch (c1)
2541 {
2542 case 0xE0:
2543 if ((c2 & 0xE0) != 0xA0)
2544 return codecvt_base::error;
2545 break;
2546 case 0xED:
2547 if ((c2 & 0xE0) != 0x80)
2548 return codecvt_base::error;
2549 break;
2550 default:
2551 if ((c2 & 0xC0) != 0x80)
2552 return codecvt_base::error;
2553 break;
2554 }
2555 if ((c3 & 0xC0) != 0x80)
2556 return codecvt_base::error;
2557 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2558 | ((c2 & 0x3F) << 6)
2559 | (c3 & 0x3F));
2560 if (t > Maxcode)
2561 return codecvt_base::error;
2562 *to_nxt = t;
2563 frm_nxt += 3;
2564 }
2565 else
2566 {
2567 return codecvt_base::error;
2568 }
2569 }
2570 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2571}
2572
2573static
2574int
2575utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2576 size_t mx, unsigned long Maxcode = 0x10FFFF,
2577 codecvt_mode mode = codecvt_mode(0))
2578{
2579 const uint8_t* frm_nxt = frm;
2580 if (mode & consume_header)
2581 {
2582 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2583 frm_nxt[2] == 0xBF)
2584 frm_nxt += 3;
2585 }
2586 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2587 {
2588 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2589 if (c1 < 0x80)
2590 {
2591 if (c1 > Maxcode)
2592 break;
2593 ++frm_nxt;
2594 }
2595 else if (c1 < 0xC2)
2596 {
2597 break;
2598 }
2599 else if (c1 < 0xE0)
2600 {
2601 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2602 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002603 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002604 break;
2605 frm_nxt += 2;
2606 }
2607 else if (c1 < 0xF0)
2608 {
2609 if (frm_end-frm_nxt < 3)
2610 break;
2611 uint8_t c2 = frm_nxt[1];
2612 uint8_t c3 = frm_nxt[2];
2613 switch (c1)
2614 {
2615 case 0xE0:
2616 if ((c2 & 0xE0) != 0xA0)
2617 return static_cast<int>(frm_nxt - frm);
2618 break;
2619 case 0xED:
2620 if ((c2 & 0xE0) != 0x80)
2621 return static_cast<int>(frm_nxt - frm);
2622 break;
2623 default:
2624 if ((c2 & 0xC0) != 0x80)
2625 return static_cast<int>(frm_nxt - frm);
2626 break;
2627 }
2628 if ((c3 & 0xC0) != 0x80)
2629 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002630 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002631 break;
2632 frm_nxt += 3;
2633 }
2634 else
2635 {
2636 break;
2637 }
2638 }
2639 return static_cast<int>(frm_nxt - frm);
2640}
2641
2642static
2643codecvt_base::result
2644ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2645 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2646 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2647{
2648 frm_nxt = frm;
2649 to_nxt = to;
2650 if (mode & generate_header)
2651 {
2652 if (to_end-to_nxt < 2)
2653 return codecvt_base::partial;
2654 *to_nxt++ = static_cast<uint8_t>(0xFE);
2655 *to_nxt++ = static_cast<uint8_t>(0xFF);
2656 }
2657 for (; frm_nxt < frm_end; ++frm_nxt)
2658 {
2659 uint32_t wc = *frm_nxt;
2660 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2661 return codecvt_base::error;
2662 if (wc < 0x010000)
2663 {
2664 if (to_end-to_nxt < 2)
2665 return codecvt_base::partial;
2666 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2667 *to_nxt++ = static_cast<uint8_t>(wc);
2668 }
2669 else
2670 {
2671 if (to_end-to_nxt < 4)
2672 return codecvt_base::partial;
2673 uint16_t t = static_cast<uint16_t>(
2674 0xD800
2675 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2676 | ((wc & 0x00FC00) >> 10));
2677 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2678 *to_nxt++ = static_cast<uint8_t>(t);
2679 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2680 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2681 *to_nxt++ = static_cast<uint8_t>(t);
2682 }
2683 }
2684 return codecvt_base::ok;
2685}
2686
2687static
2688codecvt_base::result
2689utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2690 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2691 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2692{
2693 frm_nxt = frm;
2694 to_nxt = to;
2695 if (mode & consume_header)
2696 {
2697 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2698 frm_nxt += 2;
2699 }
2700 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2701 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002702 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002703 if ((c1 & 0xFC00) == 0xDC00)
2704 return codecvt_base::error;
2705 if ((c1 & 0xFC00) != 0xD800)
2706 {
2707 if (c1 > Maxcode)
2708 return codecvt_base::error;
2709 *to_nxt = static_cast<uint32_t>(c1);
2710 frm_nxt += 2;
2711 }
2712 else
2713 {
2714 if (frm_end-frm_nxt < 4)
2715 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002716 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002717 if ((c2 & 0xFC00) != 0xDC00)
2718 return codecvt_base::error;
2719 uint32_t t = static_cast<uint32_t>(
2720 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2721 | ((c1 & 0x003F) << 10)
2722 | (c2 & 0x03FF));
2723 if (t > Maxcode)
2724 return codecvt_base::error;
2725 *to_nxt = t;
2726 frm_nxt += 4;
2727 }
2728 }
2729 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2730}
2731
2732static
2733int
2734utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2735 size_t mx, unsigned long Maxcode = 0x10FFFF,
2736 codecvt_mode mode = codecvt_mode(0))
2737{
2738 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002739 if (mode & consume_header)
2740 {
2741 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2742 frm_nxt += 2;
2743 }
2744 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2745 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002746 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002747 if ((c1 & 0xFC00) == 0xDC00)
2748 break;
2749 if ((c1 & 0xFC00) != 0xD800)
2750 {
2751 if (c1 > Maxcode)
2752 break;
2753 frm_nxt += 2;
2754 }
2755 else
2756 {
2757 if (frm_end-frm_nxt < 4)
2758 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002759 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002760 if ((c2 & 0xFC00) != 0xDC00)
2761 break;
2762 uint32_t t = static_cast<uint32_t>(
2763 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2764 | ((c1 & 0x003F) << 10)
2765 | (c2 & 0x03FF));
2766 if (t > Maxcode)
2767 break;
2768 frm_nxt += 4;
2769 }
2770 }
2771 return static_cast<int>(frm_nxt - frm);
2772}
2773
2774static
2775codecvt_base::result
2776ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2777 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2778 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2779{
2780 frm_nxt = frm;
2781 to_nxt = to;
2782 if (mode & generate_header)
2783 {
2784 if (to_end-to_nxt < 2)
2785 return codecvt_base::partial;
2786 *to_nxt++ = static_cast<uint8_t>(0xFF);
2787 *to_nxt++ = static_cast<uint8_t>(0xFE);
2788 }
2789 for (; frm_nxt < frm_end; ++frm_nxt)
2790 {
2791 uint32_t wc = *frm_nxt;
2792 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2793 return codecvt_base::error;
2794 if (wc < 0x010000)
2795 {
2796 if (to_end-to_nxt < 2)
2797 return codecvt_base::partial;
2798 *to_nxt++ = static_cast<uint8_t>(wc);
2799 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2800 }
2801 else
2802 {
2803 if (to_end-to_nxt < 4)
2804 return codecvt_base::partial;
2805 uint16_t t = static_cast<uint16_t>(
2806 0xD800
2807 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2808 | ((wc & 0x00FC00) >> 10));
2809 *to_nxt++ = static_cast<uint8_t>(t);
2810 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2811 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2812 *to_nxt++ = static_cast<uint8_t>(t);
2813 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2814 }
2815 }
2816 return codecvt_base::ok;
2817}
2818
2819static
2820codecvt_base::result
2821utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2822 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2823 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2824{
2825 frm_nxt = frm;
2826 to_nxt = to;
2827 if (mode & consume_header)
2828 {
2829 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2830 frm_nxt += 2;
2831 }
2832 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2833 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002834 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002835 if ((c1 & 0xFC00) == 0xDC00)
2836 return codecvt_base::error;
2837 if ((c1 & 0xFC00) != 0xD800)
2838 {
2839 if (c1 > Maxcode)
2840 return codecvt_base::error;
2841 *to_nxt = static_cast<uint32_t>(c1);
2842 frm_nxt += 2;
2843 }
2844 else
2845 {
2846 if (frm_end-frm_nxt < 4)
2847 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002848 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002849 if ((c2 & 0xFC00) != 0xDC00)
2850 return codecvt_base::error;
2851 uint32_t t = static_cast<uint32_t>(
2852 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2853 | ((c1 & 0x003F) << 10)
2854 | (c2 & 0x03FF));
2855 if (t > Maxcode)
2856 return codecvt_base::error;
2857 *to_nxt = t;
2858 frm_nxt += 4;
2859 }
2860 }
2861 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2862}
2863
2864static
2865int
2866utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2867 size_t mx, unsigned long Maxcode = 0x10FFFF,
2868 codecvt_mode mode = codecvt_mode(0))
2869{
2870 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002871 if (mode & consume_header)
2872 {
2873 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2874 frm_nxt += 2;
2875 }
2876 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2877 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002878 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002879 if ((c1 & 0xFC00) == 0xDC00)
2880 break;
2881 if ((c1 & 0xFC00) != 0xD800)
2882 {
2883 if (c1 > Maxcode)
2884 break;
2885 frm_nxt += 2;
2886 }
2887 else
2888 {
2889 if (frm_end-frm_nxt < 4)
2890 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002891 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002892 if ((c2 & 0xFC00) != 0xDC00)
2893 break;
2894 uint32_t t = static_cast<uint32_t>(
2895 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2896 | ((c1 & 0x003F) << 10)
2897 | (c2 & 0x03FF));
2898 if (t > Maxcode)
2899 break;
2900 frm_nxt += 4;
2901 }
2902 }
2903 return static_cast<int>(frm_nxt - frm);
2904}
2905
2906static
2907codecvt_base::result
2908ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2909 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2910 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2911{
2912 frm_nxt = frm;
2913 to_nxt = to;
2914 if (mode & generate_header)
2915 {
2916 if (to_end-to_nxt < 2)
2917 return codecvt_base::partial;
2918 *to_nxt++ = static_cast<uint8_t>(0xFE);
2919 *to_nxt++ = static_cast<uint8_t>(0xFF);
2920 }
2921 for (; frm_nxt < frm_end; ++frm_nxt)
2922 {
2923 uint16_t wc = *frm_nxt;
2924 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2925 return codecvt_base::error;
2926 if (to_end-to_nxt < 2)
2927 return codecvt_base::partial;
2928 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2929 *to_nxt++ = static_cast<uint8_t>(wc);
2930 }
2931 return codecvt_base::ok;
2932}
2933
2934static
2935codecvt_base::result
2936utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2937 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2938 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2939{
2940 frm_nxt = frm;
2941 to_nxt = to;
2942 if (mode & consume_header)
2943 {
2944 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2945 frm_nxt += 2;
2946 }
2947 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2948 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002949 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002950 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2951 return codecvt_base::error;
2952 *to_nxt = c1;
2953 frm_nxt += 2;
2954 }
2955 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2956}
2957
2958static
2959int
2960utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2961 size_t mx, unsigned long Maxcode = 0x10FFFF,
2962 codecvt_mode mode = codecvt_mode(0))
2963{
2964 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002965 if (mode & consume_header)
2966 {
2967 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2968 frm_nxt += 2;
2969 }
2970 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2971 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002972 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002973 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2974 break;
2975 frm_nxt += 2;
2976 }
2977 return static_cast<int>(frm_nxt - frm);
2978}
2979
2980static
2981codecvt_base::result
2982ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2983 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2984 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2985{
2986 frm_nxt = frm;
2987 to_nxt = to;
2988 if (mode & generate_header)
2989 {
2990 if (to_end-to_nxt < 2)
2991 return codecvt_base::partial;
2992 *to_nxt++ = static_cast<uint8_t>(0xFF);
2993 *to_nxt++ = static_cast<uint8_t>(0xFE);
2994 }
2995 for (; frm_nxt < frm_end; ++frm_nxt)
2996 {
2997 uint16_t wc = *frm_nxt;
2998 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2999 return codecvt_base::error;
3000 if (to_end-to_nxt < 2)
3001 return codecvt_base::partial;
3002 *to_nxt++ = static_cast<uint8_t>(wc);
3003 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3004 }
3005 return codecvt_base::ok;
3006}
3007
3008static
3009codecvt_base::result
3010utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3011 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3012 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3013{
3014 frm_nxt = frm;
3015 to_nxt = to;
3016 if (mode & consume_header)
3017 {
3018 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3019 frm_nxt += 2;
3020 }
3021 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3022 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003023 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003024 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3025 return codecvt_base::error;
3026 *to_nxt = c1;
3027 frm_nxt += 2;
3028 }
3029 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3030}
3031
3032static
3033int
3034utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3035 size_t mx, unsigned long Maxcode = 0x10FFFF,
3036 codecvt_mode mode = codecvt_mode(0))
3037{
3038 const uint8_t* frm_nxt = frm;
3039 frm_nxt = frm;
3040 if (mode & consume_header)
3041 {
3042 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3043 frm_nxt += 2;
3044 }
3045 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3046 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003047 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003048 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3049 break;
3050 frm_nxt += 2;
3051 }
3052 return static_cast<int>(frm_nxt - frm);
3053}
3054
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003055// template <> class codecvt<char16_t, char, mbstate_t>
3056
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003057locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003058
3059codecvt<char16_t, char, mbstate_t>::~codecvt()
3060{
3061}
3062
3063codecvt<char16_t, char, mbstate_t>::result
3064codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003065 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003066 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3067{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003068 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3069 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3070 const uint16_t* _frm_nxt = _frm;
3071 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3072 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3073 uint8_t* _to_nxt = _to;
3074 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3075 frm_nxt = frm + (_frm_nxt - _frm);
3076 to_nxt = to + (_to_nxt - _to);
3077 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003078}
3079
3080codecvt<char16_t, char, mbstate_t>::result
3081codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003082 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003083 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3084{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003085 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3086 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3087 const uint8_t* _frm_nxt = _frm;
3088 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3089 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3090 uint16_t* _to_nxt = _to;
3091 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3092 frm_nxt = frm + (_frm_nxt - _frm);
3093 to_nxt = to + (_to_nxt - _to);
3094 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003095}
3096
3097codecvt<char16_t, char, mbstate_t>::result
3098codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3099 extern_type* to, extern_type*, extern_type*& to_nxt) const
3100{
3101 to_nxt = to;
3102 return noconv;
3103}
3104
3105int
Howard Hinnantc9834542011-05-31 15:34:58 +00003106codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003107{
3108 return 0;
3109}
3110
3111bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003112codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003113{
3114 return false;
3115}
3116
3117int
3118codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3119 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3120{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003121 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3122 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3123 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003124}
3125
3126int
Howard Hinnantc9834542011-05-31 15:34:58 +00003127codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003128{
3129 return 4;
3130}
3131
3132// template <> class codecvt<char32_t, char, mbstate_t>
3133
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003134locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003135
3136codecvt<char32_t, char, mbstate_t>::~codecvt()
3137{
3138}
3139
3140codecvt<char32_t, char, mbstate_t>::result
3141codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003142 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003143 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3144{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003145 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3146 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3147 const uint32_t* _frm_nxt = _frm;
3148 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3149 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3150 uint8_t* _to_nxt = _to;
3151 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3152 frm_nxt = frm + (_frm_nxt - _frm);
3153 to_nxt = to + (_to_nxt - _to);
3154 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003155}
3156
3157codecvt<char32_t, char, mbstate_t>::result
3158codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003159 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003160 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3161{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003162 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3163 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3164 const uint8_t* _frm_nxt = _frm;
3165 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3166 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3167 uint32_t* _to_nxt = _to;
3168 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3169 frm_nxt = frm + (_frm_nxt - _frm);
3170 to_nxt = to + (_to_nxt - _to);
3171 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003172}
3173
3174codecvt<char32_t, char, mbstate_t>::result
3175codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3176 extern_type* to, extern_type*, extern_type*& to_nxt) const
3177{
3178 to_nxt = to;
3179 return noconv;
3180}
3181
3182int
Howard Hinnantc9834542011-05-31 15:34:58 +00003183codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003184{
3185 return 0;
3186}
3187
3188bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003189codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003190{
3191 return false;
3192}
3193
3194int
3195codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3196 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3197{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003198 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3199 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3200 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003201}
3202
3203int
Howard Hinnantc9834542011-05-31 15:34:58 +00003204codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003205{
3206 return 4;
3207}
3208
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003209// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003210
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003211__codecvt_utf8<wchar_t>::result
3212__codecvt_utf8<wchar_t>::do_out(state_type&,
3213 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003214 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3215{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003216#if _WIN32
3217 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3218 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3219 const uint16_t* _frm_nxt = _frm;
3220#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003221 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3222 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3223 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003224#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003225 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3226 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3227 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003228#if _WIN32
3229 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3230 _Maxcode_, _Mode_);
3231#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003232 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3233 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003234#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003235 frm_nxt = frm + (_frm_nxt - _frm);
3236 to_nxt = to + (_to_nxt - _to);
3237 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003238}
3239
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003240__codecvt_utf8<wchar_t>::result
3241__codecvt_utf8<wchar_t>::do_in(state_type&,
3242 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003243 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3244{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003245 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3246 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3247 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003248#if _WIN32
3249 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3250 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3251 uint16_t* _to_nxt = _to;
3252 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3253 _Maxcode_, _Mode_);
3254#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003255 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3256 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3257 uint32_t* _to_nxt = _to;
3258 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3259 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003260#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003261 frm_nxt = frm + (_frm_nxt - _frm);
3262 to_nxt = to + (_to_nxt - _to);
3263 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003264}
3265
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003266__codecvt_utf8<wchar_t>::result
3267__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003268 extern_type* to, extern_type*, extern_type*& to_nxt) const
3269{
3270 to_nxt = to;
3271 return noconv;
3272}
3273
3274int
Howard Hinnantc9834542011-05-31 15:34:58 +00003275__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003276{
3277 return 0;
3278}
3279
3280bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003281__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003282{
3283 return false;
3284}
3285
3286int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003287__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003288 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3289{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003290 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3291 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3292 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003293}
3294
3295int
Howard Hinnantc9834542011-05-31 15:34:58 +00003296__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003297{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003298 if (_Mode_ & consume_header)
3299 return 7;
3300 return 4;
3301}
3302
3303// __codecvt_utf8<char16_t>
3304
3305__codecvt_utf8<char16_t>::result
3306__codecvt_utf8<char16_t>::do_out(state_type&,
3307 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3308 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3309{
3310 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3311 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3312 const uint16_t* _frm_nxt = _frm;
3313 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3314 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3315 uint8_t* _to_nxt = _to;
3316 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3317 _Maxcode_, _Mode_);
3318 frm_nxt = frm + (_frm_nxt - _frm);
3319 to_nxt = to + (_to_nxt - _to);
3320 return r;
3321}
3322
3323__codecvt_utf8<char16_t>::result
3324__codecvt_utf8<char16_t>::do_in(state_type&,
3325 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3326 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3327{
3328 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3329 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3330 const uint8_t* _frm_nxt = _frm;
3331 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3332 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3333 uint16_t* _to_nxt = _to;
3334 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3335 _Maxcode_, _Mode_);
3336 frm_nxt = frm + (_frm_nxt - _frm);
3337 to_nxt = to + (_to_nxt - _to);
3338 return r;
3339}
3340
3341__codecvt_utf8<char16_t>::result
3342__codecvt_utf8<char16_t>::do_unshift(state_type&,
3343 extern_type* to, extern_type*, extern_type*& to_nxt) const
3344{
3345 to_nxt = to;
3346 return noconv;
3347}
3348
3349int
Howard Hinnantc9834542011-05-31 15:34:58 +00003350__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003351{
3352 return 0;
3353}
3354
3355bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003356__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003357{
3358 return false;
3359}
3360
3361int
3362__codecvt_utf8<char16_t>::do_length(state_type&,
3363 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3364{
3365 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3366 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3367 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3368}
3369
3370int
Howard Hinnantc9834542011-05-31 15:34:58 +00003371__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003372{
3373 if (_Mode_ & consume_header)
3374 return 6;
3375 return 3;
3376}
3377
3378// __codecvt_utf8<char32_t>
3379
3380__codecvt_utf8<char32_t>::result
3381__codecvt_utf8<char32_t>::do_out(state_type&,
3382 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3383 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3384{
3385 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3386 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3387 const uint32_t* _frm_nxt = _frm;
3388 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3389 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3390 uint8_t* _to_nxt = _to;
3391 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3392 _Maxcode_, _Mode_);
3393 frm_nxt = frm + (_frm_nxt - _frm);
3394 to_nxt = to + (_to_nxt - _to);
3395 return r;
3396}
3397
3398__codecvt_utf8<char32_t>::result
3399__codecvt_utf8<char32_t>::do_in(state_type&,
3400 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3401 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3402{
3403 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3404 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3405 const uint8_t* _frm_nxt = _frm;
3406 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3407 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3408 uint32_t* _to_nxt = _to;
3409 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3410 _Maxcode_, _Mode_);
3411 frm_nxt = frm + (_frm_nxt - _frm);
3412 to_nxt = to + (_to_nxt - _to);
3413 return r;
3414}
3415
3416__codecvt_utf8<char32_t>::result
3417__codecvt_utf8<char32_t>::do_unshift(state_type&,
3418 extern_type* to, extern_type*, extern_type*& to_nxt) const
3419{
3420 to_nxt = to;
3421 return noconv;
3422}
3423
3424int
Howard Hinnantc9834542011-05-31 15:34:58 +00003425__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003426{
3427 return 0;
3428}
3429
3430bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003431__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003432{
3433 return false;
3434}
3435
3436int
3437__codecvt_utf8<char32_t>::do_length(state_type&,
3438 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3439{
3440 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3441 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3442 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3443}
3444
3445int
Howard Hinnantc9834542011-05-31 15:34:58 +00003446__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003447{
3448 if (_Mode_ & consume_header)
3449 return 7;
3450 return 4;
3451}
3452
3453// __codecvt_utf16<wchar_t, false>
3454
3455__codecvt_utf16<wchar_t, false>::result
3456__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3457 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3458 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3459{
3460 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3461 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3462 const uint32_t* _frm_nxt = _frm;
3463 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3464 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3465 uint8_t* _to_nxt = _to;
3466 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3467 _Maxcode_, _Mode_);
3468 frm_nxt = frm + (_frm_nxt - _frm);
3469 to_nxt = to + (_to_nxt - _to);
3470 return r;
3471}
3472
3473__codecvt_utf16<wchar_t, false>::result
3474__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3475 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3476 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3477{
3478 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3479 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3480 const uint8_t* _frm_nxt = _frm;
3481 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3482 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3483 uint32_t* _to_nxt = _to;
3484 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3485 _Maxcode_, _Mode_);
3486 frm_nxt = frm + (_frm_nxt - _frm);
3487 to_nxt = to + (_to_nxt - _to);
3488 return r;
3489}
3490
3491__codecvt_utf16<wchar_t, false>::result
3492__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3493 extern_type* to, extern_type*, extern_type*& to_nxt) const
3494{
3495 to_nxt = to;
3496 return noconv;
3497}
3498
3499int
Howard Hinnantc9834542011-05-31 15:34:58 +00003500__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003501{
3502 return 0;
3503}
3504
3505bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003506__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003507{
3508 return false;
3509}
3510
3511int
3512__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3513 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3514{
3515 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3516 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3517 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3518}
3519
3520int
Howard Hinnantc9834542011-05-31 15:34:58 +00003521__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003522{
3523 if (_Mode_ & consume_header)
3524 return 6;
3525 return 4;
3526}
3527
3528// __codecvt_utf16<wchar_t, true>
3529
3530__codecvt_utf16<wchar_t, true>::result
3531__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3532 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3533 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3534{
3535 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3536 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3537 const uint32_t* _frm_nxt = _frm;
3538 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3539 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3540 uint8_t* _to_nxt = _to;
3541 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3542 _Maxcode_, _Mode_);
3543 frm_nxt = frm + (_frm_nxt - _frm);
3544 to_nxt = to + (_to_nxt - _to);
3545 return r;
3546}
3547
3548__codecvt_utf16<wchar_t, true>::result
3549__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3550 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3551 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3552{
3553 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3554 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3555 const uint8_t* _frm_nxt = _frm;
3556 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3557 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3558 uint32_t* _to_nxt = _to;
3559 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3560 _Maxcode_, _Mode_);
3561 frm_nxt = frm + (_frm_nxt - _frm);
3562 to_nxt = to + (_to_nxt - _to);
3563 return r;
3564}
3565
3566__codecvt_utf16<wchar_t, true>::result
3567__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3568 extern_type* to, extern_type*, extern_type*& to_nxt) const
3569{
3570 to_nxt = to;
3571 return noconv;
3572}
3573
3574int
Howard Hinnantc9834542011-05-31 15:34:58 +00003575__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003576{
3577 return 0;
3578}
3579
3580bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003581__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003582{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003583 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003584}
3585
3586int
3587__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3588 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3589{
3590 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3591 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3592 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3593}
3594
3595int
Howard Hinnantc9834542011-05-31 15:34:58 +00003596__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003597{
3598 if (_Mode_ & consume_header)
3599 return 6;
3600 return 4;
3601}
3602
3603// __codecvt_utf16<char16_t, false>
3604
3605__codecvt_utf16<char16_t, false>::result
3606__codecvt_utf16<char16_t, false>::do_out(state_type&,
3607 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3608 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3609{
3610 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3611 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3612 const uint16_t* _frm_nxt = _frm;
3613 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3614 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3615 uint8_t* _to_nxt = _to;
3616 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3617 _Maxcode_, _Mode_);
3618 frm_nxt = frm + (_frm_nxt - _frm);
3619 to_nxt = to + (_to_nxt - _to);
3620 return r;
3621}
3622
3623__codecvt_utf16<char16_t, false>::result
3624__codecvt_utf16<char16_t, false>::do_in(state_type&,
3625 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3626 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3627{
3628 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3629 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3630 const uint8_t* _frm_nxt = _frm;
3631 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3632 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3633 uint16_t* _to_nxt = _to;
3634 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3635 _Maxcode_, _Mode_);
3636 frm_nxt = frm + (_frm_nxt - _frm);
3637 to_nxt = to + (_to_nxt - _to);
3638 return r;
3639}
3640
3641__codecvt_utf16<char16_t, false>::result
3642__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3643 extern_type* to, extern_type*, extern_type*& to_nxt) const
3644{
3645 to_nxt = to;
3646 return noconv;
3647}
3648
3649int
Howard Hinnantc9834542011-05-31 15:34:58 +00003650__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003651{
3652 return 0;
3653}
3654
3655bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003656__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003657{
3658 return false;
3659}
3660
3661int
3662__codecvt_utf16<char16_t, false>::do_length(state_type&,
3663 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3664{
3665 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3666 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3667 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3668}
3669
3670int
Howard Hinnantc9834542011-05-31 15:34:58 +00003671__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003672{
3673 if (_Mode_ & consume_header)
3674 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003675 return 2;
3676}
3677
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003678// __codecvt_utf16<char16_t, true>
3679
3680__codecvt_utf16<char16_t, true>::result
3681__codecvt_utf16<char16_t, true>::do_out(state_type&,
3682 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3683 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3684{
3685 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3686 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3687 const uint16_t* _frm_nxt = _frm;
3688 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3689 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3690 uint8_t* _to_nxt = _to;
3691 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3692 _Maxcode_, _Mode_);
3693 frm_nxt = frm + (_frm_nxt - _frm);
3694 to_nxt = to + (_to_nxt - _to);
3695 return r;
3696}
3697
3698__codecvt_utf16<char16_t, true>::result
3699__codecvt_utf16<char16_t, true>::do_in(state_type&,
3700 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3701 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3702{
3703 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3704 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3705 const uint8_t* _frm_nxt = _frm;
3706 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3707 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3708 uint16_t* _to_nxt = _to;
3709 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3710 _Maxcode_, _Mode_);
3711 frm_nxt = frm + (_frm_nxt - _frm);
3712 to_nxt = to + (_to_nxt - _to);
3713 return r;
3714}
3715
3716__codecvt_utf16<char16_t, true>::result
3717__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3718 extern_type* to, extern_type*, extern_type*& to_nxt) const
3719{
3720 to_nxt = to;
3721 return noconv;
3722}
3723
3724int
Howard Hinnantc9834542011-05-31 15:34:58 +00003725__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003726{
3727 return 0;
3728}
3729
3730bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003731__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003732{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003733 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003734}
3735
3736int
3737__codecvt_utf16<char16_t, true>::do_length(state_type&,
3738 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3739{
3740 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3741 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3742 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3743}
3744
3745int
Howard Hinnantc9834542011-05-31 15:34:58 +00003746__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003747{
3748 if (_Mode_ & consume_header)
3749 return 4;
3750 return 2;
3751}
3752
3753// __codecvt_utf16<char32_t, false>
3754
3755__codecvt_utf16<char32_t, false>::result
3756__codecvt_utf16<char32_t, false>::do_out(state_type&,
3757 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3758 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3759{
3760 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3761 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3762 const uint32_t* _frm_nxt = _frm;
3763 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3764 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3765 uint8_t* _to_nxt = _to;
3766 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3767 _Maxcode_, _Mode_);
3768 frm_nxt = frm + (_frm_nxt - _frm);
3769 to_nxt = to + (_to_nxt - _to);
3770 return r;
3771}
3772
3773__codecvt_utf16<char32_t, false>::result
3774__codecvt_utf16<char32_t, false>::do_in(state_type&,
3775 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3776 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3777{
3778 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3779 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3780 const uint8_t* _frm_nxt = _frm;
3781 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3782 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3783 uint32_t* _to_nxt = _to;
3784 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3785 _Maxcode_, _Mode_);
3786 frm_nxt = frm + (_frm_nxt - _frm);
3787 to_nxt = to + (_to_nxt - _to);
3788 return r;
3789}
3790
3791__codecvt_utf16<char32_t, false>::result
3792__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3793 extern_type* to, extern_type*, extern_type*& to_nxt) const
3794{
3795 to_nxt = to;
3796 return noconv;
3797}
3798
3799int
Howard Hinnantc9834542011-05-31 15:34:58 +00003800__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003801{
3802 return 0;
3803}
3804
3805bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003806__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003807{
3808 return false;
3809}
3810
3811int
3812__codecvt_utf16<char32_t, false>::do_length(state_type&,
3813 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3814{
3815 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3816 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3817 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3818}
3819
3820int
Howard Hinnantc9834542011-05-31 15:34:58 +00003821__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003822{
3823 if (_Mode_ & consume_header)
3824 return 6;
3825 return 4;
3826}
3827
3828// __codecvt_utf16<char32_t, true>
3829
3830__codecvt_utf16<char32_t, true>::result
3831__codecvt_utf16<char32_t, true>::do_out(state_type&,
3832 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3833 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3834{
3835 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3836 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3837 const uint32_t* _frm_nxt = _frm;
3838 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3839 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3840 uint8_t* _to_nxt = _to;
3841 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3842 _Maxcode_, _Mode_);
3843 frm_nxt = frm + (_frm_nxt - _frm);
3844 to_nxt = to + (_to_nxt - _to);
3845 return r;
3846}
3847
3848__codecvt_utf16<char32_t, true>::result
3849__codecvt_utf16<char32_t, true>::do_in(state_type&,
3850 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3851 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3852{
3853 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3854 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3855 const uint8_t* _frm_nxt = _frm;
3856 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3857 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3858 uint32_t* _to_nxt = _to;
3859 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3860 _Maxcode_, _Mode_);
3861 frm_nxt = frm + (_frm_nxt - _frm);
3862 to_nxt = to + (_to_nxt - _to);
3863 return r;
3864}
3865
3866__codecvt_utf16<char32_t, true>::result
3867__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3868 extern_type* to, extern_type*, extern_type*& to_nxt) const
3869{
3870 to_nxt = to;
3871 return noconv;
3872}
3873
3874int
Howard Hinnantc9834542011-05-31 15:34:58 +00003875__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003876{
3877 return 0;
3878}
3879
3880bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003881__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003882{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003883 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003884}
3885
3886int
3887__codecvt_utf16<char32_t, true>::do_length(state_type&,
3888 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3889{
3890 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3891 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3892 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3893}
3894
3895int
Howard Hinnantc9834542011-05-31 15:34:58 +00003896__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003897{
3898 if (_Mode_ & consume_header)
3899 return 6;
3900 return 4;
3901}
3902
3903// __codecvt_utf8_utf16<wchar_t>
3904
3905__codecvt_utf8_utf16<wchar_t>::result
3906__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3907 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3908 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3909{
3910 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3911 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3912 const uint32_t* _frm_nxt = _frm;
3913 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3914 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3915 uint8_t* _to_nxt = _to;
3916 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3917 _Maxcode_, _Mode_);
3918 frm_nxt = frm + (_frm_nxt - _frm);
3919 to_nxt = to + (_to_nxt - _to);
3920 return r;
3921}
3922
3923__codecvt_utf8_utf16<wchar_t>::result
3924__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3925 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3926 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3927{
3928 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3929 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3930 const uint8_t* _frm_nxt = _frm;
3931 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3932 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3933 uint32_t* _to_nxt = _to;
3934 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3935 _Maxcode_, _Mode_);
3936 frm_nxt = frm + (_frm_nxt - _frm);
3937 to_nxt = to + (_to_nxt - _to);
3938 return r;
3939}
3940
3941__codecvt_utf8_utf16<wchar_t>::result
3942__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3943 extern_type* to, extern_type*, extern_type*& to_nxt) const
3944{
3945 to_nxt = to;
3946 return noconv;
3947}
3948
3949int
Howard Hinnantc9834542011-05-31 15:34:58 +00003950__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003951{
3952 return 0;
3953}
3954
3955bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003956__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003957{
3958 return false;
3959}
3960
3961int
3962__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3963 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3964{
3965 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3966 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3967 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3968}
3969
3970int
Howard Hinnantc9834542011-05-31 15:34:58 +00003971__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003972{
3973 if (_Mode_ & consume_header)
3974 return 7;
3975 return 4;
3976}
3977
3978// __codecvt_utf8_utf16<char16_t>
3979
3980__codecvt_utf8_utf16<char16_t>::result
3981__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3982 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3983 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3984{
3985 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3986 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3987 const uint16_t* _frm_nxt = _frm;
3988 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3989 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3990 uint8_t* _to_nxt = _to;
3991 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3992 _Maxcode_, _Mode_);
3993 frm_nxt = frm + (_frm_nxt - _frm);
3994 to_nxt = to + (_to_nxt - _to);
3995 return r;
3996}
3997
3998__codecvt_utf8_utf16<char16_t>::result
3999__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4000 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4001 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4002{
4003 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4004 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4005 const uint8_t* _frm_nxt = _frm;
4006 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4007 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4008 uint16_t* _to_nxt = _to;
4009 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4010 _Maxcode_, _Mode_);
4011 frm_nxt = frm + (_frm_nxt - _frm);
4012 to_nxt = to + (_to_nxt - _to);
4013 return r;
4014}
4015
4016__codecvt_utf8_utf16<char16_t>::result
4017__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4018 extern_type* to, extern_type*, extern_type*& to_nxt) const
4019{
4020 to_nxt = to;
4021 return noconv;
4022}
4023
4024int
Howard Hinnantc9834542011-05-31 15:34:58 +00004025__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004026{
4027 return 0;
4028}
4029
4030bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004031__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004032{
4033 return false;
4034}
4035
4036int
4037__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4038 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4039{
4040 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4041 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4042 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4043}
4044
4045int
Howard Hinnantc9834542011-05-31 15:34:58 +00004046__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004047{
4048 if (_Mode_ & consume_header)
4049 return 7;
4050 return 4;
4051}
4052
4053// __codecvt_utf8_utf16<char32_t>
4054
4055__codecvt_utf8_utf16<char32_t>::result
4056__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4057 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4058 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4059{
4060 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4061 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4062 const uint32_t* _frm_nxt = _frm;
4063 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4064 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4065 uint8_t* _to_nxt = _to;
4066 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4067 _Maxcode_, _Mode_);
4068 frm_nxt = frm + (_frm_nxt - _frm);
4069 to_nxt = to + (_to_nxt - _to);
4070 return r;
4071}
4072
4073__codecvt_utf8_utf16<char32_t>::result
4074__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4075 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4076 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4077{
4078 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4079 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4080 const uint8_t* _frm_nxt = _frm;
4081 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4082 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4083 uint32_t* _to_nxt = _to;
4084 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4085 _Maxcode_, _Mode_);
4086 frm_nxt = frm + (_frm_nxt - _frm);
4087 to_nxt = to + (_to_nxt - _to);
4088 return r;
4089}
4090
4091__codecvt_utf8_utf16<char32_t>::result
4092__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4093 extern_type* to, extern_type*, extern_type*& to_nxt) const
4094{
4095 to_nxt = to;
4096 return noconv;
4097}
4098
4099int
Howard Hinnantc9834542011-05-31 15:34:58 +00004100__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004101{
4102 return 0;
4103}
4104
4105bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004106__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004107{
4108 return false;
4109}
4110
4111int
4112__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4113 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4114{
4115 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4116 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4117 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4118}
4119
4120int
Howard Hinnantc9834542011-05-31 15:34:58 +00004121__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004122{
4123 if (_Mode_ & consume_header)
4124 return 7;
4125 return 4;
4126}
4127
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004128// __narrow_to_utf8<16>
4129
4130__narrow_to_utf8<16>::~__narrow_to_utf8()
4131{
4132}
4133
4134// __narrow_to_utf8<32>
4135
4136__narrow_to_utf8<32>::~__narrow_to_utf8()
4137{
4138}
4139
4140// __widen_from_utf8<16>
4141
4142__widen_from_utf8<16>::~__widen_from_utf8()
4143{
4144}
4145
4146// __widen_from_utf8<32>
4147
4148__widen_from_utf8<32>::~__widen_from_utf8()
4149{
4150}
4151
4152// numpunct<char> && numpunct<wchar_t>
4153
4154locale::id numpunct< char >::id;
4155locale::id numpunct<wchar_t>::id;
4156
4157numpunct<char>::numpunct(size_t refs)
4158 : locale::facet(refs),
4159 __decimal_point_('.'),
4160 __thousands_sep_(',')
4161{
4162}
4163
4164numpunct<wchar_t>::numpunct(size_t refs)
4165 : locale::facet(refs),
4166 __decimal_point_(L'.'),
4167 __thousands_sep_(L',')
4168{
4169}
4170
4171numpunct<char>::~numpunct()
4172{
4173}
4174
4175numpunct<wchar_t>::~numpunct()
4176{
4177}
4178
4179 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4180wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4181
4182 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4183wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4184
4185string numpunct< char >::do_grouping() const {return __grouping_;}
4186string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4187
4188 string numpunct< char >::do_truename() const {return "true";}
4189wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4190
4191 string numpunct< char >::do_falsename() const {return "false";}
4192wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4193
4194// numpunct_byname<char>
4195
4196numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4197 : numpunct<char>(refs)
4198{
4199 __init(nm);
4200}
4201
4202numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4203 : numpunct<char>(refs)
4204{
4205 __init(nm.c_str());
4206}
4207
4208numpunct_byname<char>::~numpunct_byname()
4209{
4210}
4211
4212void
4213numpunct_byname<char>::__init(const char* nm)
4214{
4215 if (strcmp(nm, "C") != 0)
4216 {
Sean Huntf3907e62011-07-15 05:40:33 +00004217 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004218#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004219 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004220 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4221 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004222#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004223#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004224 lconv* lc = localeconv_l(loc.get());
4225#else
4226 lconv* lc = __localeconv_l(loc.get());
4227#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004228 if (*lc->decimal_point)
4229 __decimal_point_ = *lc->decimal_point;
4230 if (*lc->thousands_sep)
4231 __thousands_sep_ = *lc->thousands_sep;
4232 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004233 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004234 }
4235}
4236
4237// numpunct_byname<wchar_t>
4238
4239numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4240 : numpunct<wchar_t>(refs)
4241{
4242 __init(nm);
4243}
4244
4245numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4246 : numpunct<wchar_t>(refs)
4247{
4248 __init(nm.c_str());
4249}
4250
4251numpunct_byname<wchar_t>::~numpunct_byname()
4252{
4253}
4254
4255void
4256numpunct_byname<wchar_t>::__init(const char* nm)
4257{
4258 if (strcmp(nm, "C") != 0)
4259 {
Sean Huntf3907e62011-07-15 05:40:33 +00004260 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004261#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004262 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004263 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4264 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004265#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004266#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004267 lconv* lc = localeconv_l(loc.get());
4268#else
4269 lconv* lc = __localeconv_l(loc.get());
4270#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004271 if (*lc->decimal_point)
4272 __decimal_point_ = *lc->decimal_point;
4273 if (*lc->thousands_sep)
4274 __thousands_sep_ = *lc->thousands_sep;
4275 __grouping_ = lc->grouping;
4276 // locallization for truename and falsename is not available
4277 }
4278}
4279
4280// num_get helpers
4281
4282int
4283__num_get_base::__get_base(ios_base& iob)
4284{
4285 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4286 if (__basefield == ios_base::oct)
4287 return 8;
4288 else if (__basefield == ios_base::hex)
4289 return 16;
4290 else if (__basefield == 0)
4291 return 0;
4292 return 10;
4293}
4294
4295const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4296
4297void
4298__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4299 ios_base::iostate& __err)
4300{
4301 if (__grouping.size() != 0)
4302 {
4303 reverse(__g, __g_end);
4304 const char* __ig = __grouping.data();
4305 const char* __eg = __ig + __grouping.size();
4306 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4307 {
4308 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4309 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004310 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004311 {
4312 __err = ios_base::failbit;
4313 return;
4314 }
4315 }
4316 if (__eg - __ig > 1)
4317 ++__ig;
4318 }
4319 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4320 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004321 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004322 __err = ios_base::failbit;
4323 }
4324 }
4325}
4326
4327void
4328__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4329 ios_base::fmtflags __flags)
4330{
4331 if (__flags & ios_base::showpos)
4332 *__fmtp++ = '+';
4333 if (__flags & ios_base::showbase)
4334 *__fmtp++ = '#';
4335 while(*__len)
4336 *__fmtp++ = *__len++;
4337 if ((__flags & ios_base::basefield) == ios_base::oct)
4338 *__fmtp = 'o';
4339 else if ((__flags & ios_base::basefield) == ios_base::hex)
4340 {
4341 if (__flags & ios_base::uppercase)
4342 *__fmtp = 'X';
4343 else
4344 *__fmtp = 'x';
4345 }
4346 else if (__signd)
4347 *__fmtp = 'd';
4348 else
4349 *__fmtp = 'u';
4350}
4351
4352bool
4353__num_put_base::__format_float(char* __fmtp, const char* __len,
4354 ios_base::fmtflags __flags)
4355{
4356 bool specify_precision = true;
4357 if (__flags & ios_base::showpos)
4358 *__fmtp++ = '+';
4359 if (__flags & ios_base::showpoint)
4360 *__fmtp++ = '#';
4361 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4362 bool uppercase = __flags & ios_base::uppercase;
4363 if (floatfield == (ios_base::fixed | ios_base::scientific))
4364 specify_precision = false;
4365 else
4366 {
4367 *__fmtp++ = '.';
4368 *__fmtp++ = '*';
4369 }
4370 while(*__len)
4371 *__fmtp++ = *__len++;
4372 if (floatfield == ios_base::fixed)
4373 {
4374 if (uppercase)
4375 *__fmtp = 'F';
4376 else
4377 *__fmtp = 'f';
4378 }
4379 else if (floatfield == ios_base::scientific)
4380 {
4381 if (uppercase)
4382 *__fmtp = 'E';
4383 else
4384 *__fmtp = 'e';
4385 }
4386 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4387 {
4388 if (uppercase)
4389 *__fmtp = 'A';
4390 else
4391 *__fmtp = 'a';
4392 }
4393 else
4394 {
4395 if (uppercase)
4396 *__fmtp = 'G';
4397 else
4398 *__fmtp = 'g';
4399 }
4400 return specify_precision;
4401}
4402
4403char*
4404__num_put_base::__identify_padding(char* __nb, char* __ne,
4405 const ios_base& __iob)
4406{
4407 switch (__iob.flags() & ios_base::adjustfield)
4408 {
4409 case ios_base::internal:
4410 if (__nb[0] == '-' || __nb[0] == '+')
4411 return __nb+1;
4412 if (__ne - __nb >= 2 && __nb[0] == '0'
4413 && (__nb[1] == 'x' || __nb[1] == 'X'))
4414 return __nb+2;
4415 break;
4416 case ios_base::left:
4417 return __ne;
4418 case ios_base::right:
4419 default:
4420 break;
4421 }
4422 return __nb;
4423}
4424
4425// time_get
4426
4427static
4428string*
4429init_weeks()
4430{
4431 static string weeks[14];
4432 weeks[0] = "Sunday";
4433 weeks[1] = "Monday";
4434 weeks[2] = "Tuesday";
4435 weeks[3] = "Wednesday";
4436 weeks[4] = "Thursday";
4437 weeks[5] = "Friday";
4438 weeks[6] = "Saturday";
4439 weeks[7] = "Sun";
4440 weeks[8] = "Mon";
4441 weeks[9] = "Tue";
4442 weeks[10] = "Wed";
4443 weeks[11] = "Thu";
4444 weeks[12] = "Fri";
4445 weeks[13] = "Sat";
4446 return weeks;
4447}
4448
4449static
4450wstring*
4451init_wweeks()
4452{
4453 static wstring weeks[14];
4454 weeks[0] = L"Sunday";
4455 weeks[1] = L"Monday";
4456 weeks[2] = L"Tuesday";
4457 weeks[3] = L"Wednesday";
4458 weeks[4] = L"Thursday";
4459 weeks[5] = L"Friday";
4460 weeks[6] = L"Saturday";
4461 weeks[7] = L"Sun";
4462 weeks[8] = L"Mon";
4463 weeks[9] = L"Tue";
4464 weeks[10] = L"Wed";
4465 weeks[11] = L"Thu";
4466 weeks[12] = L"Fri";
4467 weeks[13] = L"Sat";
4468 return weeks;
4469}
4470
4471template <>
4472const string*
4473__time_get_c_storage<char>::__weeks() const
4474{
4475 static const string* weeks = init_weeks();
4476 return weeks;
4477}
4478
4479template <>
4480const wstring*
4481__time_get_c_storage<wchar_t>::__weeks() const
4482{
4483 static const wstring* weeks = init_wweeks();
4484 return weeks;
4485}
4486
4487static
4488string*
4489init_months()
4490{
4491 static string months[24];
4492 months[0] = "January";
4493 months[1] = "February";
4494 months[2] = "March";
4495 months[3] = "April";
4496 months[4] = "May";
4497 months[5] = "June";
4498 months[6] = "July";
4499 months[7] = "August";
4500 months[8] = "September";
4501 months[9] = "October";
4502 months[10] = "November";
4503 months[11] = "December";
4504 months[12] = "Jan";
4505 months[13] = "Feb";
4506 months[14] = "Mar";
4507 months[15] = "Apr";
4508 months[16] = "May";
4509 months[17] = "Jun";
4510 months[18] = "Jul";
4511 months[19] = "Aug";
4512 months[20] = "Sep";
4513 months[21] = "Oct";
4514 months[22] = "Nov";
4515 months[23] = "Dec";
4516 return months;
4517}
4518
4519static
4520wstring*
4521init_wmonths()
4522{
4523 static wstring months[24];
4524 months[0] = L"January";
4525 months[1] = L"February";
4526 months[2] = L"March";
4527 months[3] = L"April";
4528 months[4] = L"May";
4529 months[5] = L"June";
4530 months[6] = L"July";
4531 months[7] = L"August";
4532 months[8] = L"September";
4533 months[9] = L"October";
4534 months[10] = L"November";
4535 months[11] = L"December";
4536 months[12] = L"Jan";
4537 months[13] = L"Feb";
4538 months[14] = L"Mar";
4539 months[15] = L"Apr";
4540 months[16] = L"May";
4541 months[17] = L"Jun";
4542 months[18] = L"Jul";
4543 months[19] = L"Aug";
4544 months[20] = L"Sep";
4545 months[21] = L"Oct";
4546 months[22] = L"Nov";
4547 months[23] = L"Dec";
4548 return months;
4549}
4550
4551template <>
4552const string*
4553__time_get_c_storage<char>::__months() const
4554{
4555 static const string* months = init_months();
4556 return months;
4557}
4558
4559template <>
4560const wstring*
4561__time_get_c_storage<wchar_t>::__months() const
4562{
4563 static const wstring* months = init_wmonths();
4564 return months;
4565}
4566
4567static
4568string*
4569init_am_pm()
4570{
4571 static string am_pm[24];
4572 am_pm[0] = "AM";
4573 am_pm[1] = "PM";
4574 return am_pm;
4575}
4576
4577static
4578wstring*
4579init_wam_pm()
4580{
4581 static wstring am_pm[24];
4582 am_pm[0] = L"AM";
4583 am_pm[1] = L"PM";
4584 return am_pm;
4585}
4586
4587template <>
4588const string*
4589__time_get_c_storage<char>::__am_pm() const
4590{
4591 static const string* am_pm = init_am_pm();
4592 return am_pm;
4593}
4594
4595template <>
4596const wstring*
4597__time_get_c_storage<wchar_t>::__am_pm() const
4598{
4599 static const wstring* am_pm = init_wam_pm();
4600 return am_pm;
4601}
4602
4603template <>
4604const string&
4605__time_get_c_storage<char>::__x() const
4606{
4607 static string s("%m/%d/%y");
4608 return s;
4609}
4610
4611template <>
4612const wstring&
4613__time_get_c_storage<wchar_t>::__x() const
4614{
4615 static wstring s(L"%m/%d/%y");
4616 return s;
4617}
4618
4619template <>
4620const string&
4621__time_get_c_storage<char>::__X() const
4622{
4623 static string s("%H:%M:%S");
4624 return s;
4625}
4626
4627template <>
4628const wstring&
4629__time_get_c_storage<wchar_t>::__X() const
4630{
4631 static wstring s(L"%H:%M:%S");
4632 return s;
4633}
4634
4635template <>
4636const string&
4637__time_get_c_storage<char>::__c() const
4638{
4639 static string s("%a %b %d %H:%M:%S %Y");
4640 return s;
4641}
4642
4643template <>
4644const wstring&
4645__time_get_c_storage<wchar_t>::__c() const
4646{
4647 static wstring s(L"%a %b %d %H:%M:%S %Y");
4648 return s;
4649}
4650
4651template <>
4652const string&
4653__time_get_c_storage<char>::__r() const
4654{
4655 static string s("%I:%M:%S %p");
4656 return s;
4657}
4658
4659template <>
4660const wstring&
4661__time_get_c_storage<wchar_t>::__r() const
4662{
4663 static wstring s(L"%I:%M:%S %p");
4664 return s;
4665}
4666
4667// time_get_byname
4668
4669__time_get::__time_get(const char* nm)
4670 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4671{
Howard Hinnantd4444702010-08-11 17:04:31 +00004672#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004673 if (__loc_ == 0)
4674 throw runtime_error("time_get_byname"
4675 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004676#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004677}
4678
4679__time_get::__time_get(const string& nm)
4680 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4681{
Howard Hinnantd4444702010-08-11 17:04:31 +00004682#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004683 if (__loc_ == 0)
4684 throw runtime_error("time_get_byname"
4685 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004686#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004687}
4688
4689__time_get::~__time_get()
4690{
4691 freelocale(__loc_);
4692}
4693
Howard Hinnant335b1512012-02-20 16:51:43 +00004694#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant21772ec2012-12-28 18:15:01 +00004695#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant335b1512012-02-20 16:51:43 +00004696
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004697template <>
4698string
4699__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4700{
Howard Hinnant3074a052012-02-19 14:55:32 +00004701 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004702 t.tm_sec = 59;
4703 t.tm_min = 55;
4704 t.tm_hour = 23;
4705 t.tm_mday = 31;
4706 t.tm_mon = 11;
4707 t.tm_year = 161;
4708 t.tm_wday = 6;
4709 t.tm_yday = 364;
4710 t.tm_isdst = -1;
4711 char buf[100];
4712 char f[3] = {0};
4713 f[0] = '%';
4714 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004715 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004716 char* bb = buf;
4717 char* be = buf + n;
4718 string result;
4719 while (bb != be)
4720 {
4721 if (ct.is(ctype_base::space, *bb))
4722 {
4723 result.push_back(' ');
4724 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4725 ;
4726 continue;
4727 }
4728 char* w = bb;
4729 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004730 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004731 ct, err, false)
4732 - this->__weeks_;
4733 if (i < 14)
4734 {
4735 result.push_back('%');
4736 if (i < 7)
4737 result.push_back('A');
4738 else
4739 result.push_back('a');
4740 bb = w;
4741 continue;
4742 }
4743 w = bb;
4744 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4745 ct, err, false)
4746 - this->__months_;
4747 if (i < 24)
4748 {
4749 result.push_back('%');
4750 if (i < 12)
4751 result.push_back('B');
4752 else
4753 result.push_back('b');
4754 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4755 result.back() = 'm';
4756 bb = w;
4757 continue;
4758 }
4759 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4760 {
4761 w = bb;
4762 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4763 ct, err, false) - this->__am_pm_;
4764 if (i < 2)
4765 {
4766 result.push_back('%');
4767 result.push_back('p');
4768 bb = w;
4769 continue;
4770 }
4771 }
4772 w = bb;
4773 if (ct.is(ctype_base::digit, *bb))
4774 {
4775 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4776 {
4777 case 6:
4778 result.push_back('%');
4779 result.push_back('w');
4780 break;
4781 case 7:
4782 result.push_back('%');
4783 result.push_back('u');
4784 break;
4785 case 11:
4786 result.push_back('%');
4787 result.push_back('I');
4788 break;
4789 case 12:
4790 result.push_back('%');
4791 result.push_back('m');
4792 break;
4793 case 23:
4794 result.push_back('%');
4795 result.push_back('H');
4796 break;
4797 case 31:
4798 result.push_back('%');
4799 result.push_back('d');
4800 break;
4801 case 55:
4802 result.push_back('%');
4803 result.push_back('M');
4804 break;
4805 case 59:
4806 result.push_back('%');
4807 result.push_back('S');
4808 break;
4809 case 61:
4810 result.push_back('%');
4811 result.push_back('y');
4812 break;
4813 case 364:
4814 result.push_back('%');
4815 result.push_back('j');
4816 break;
4817 case 2061:
4818 result.push_back('%');
4819 result.push_back('Y');
4820 break;
4821 default:
4822 for (; w != bb; ++w)
4823 result.push_back(*w);
4824 break;
4825 }
4826 continue;
4827 }
4828 if (*bb == '%')
4829 {
4830 result.push_back('%');
4831 result.push_back('%');
4832 ++bb;
4833 continue;
4834 }
4835 result.push_back(*bb);
4836 ++bb;
4837 }
4838 return result;
4839}
4840
Howard Hinnantec3773c2011-12-01 20:21:04 +00004841#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004842
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004843template <>
4844wstring
4845__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4846{
Howard Hinnant3074a052012-02-19 14:55:32 +00004847 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004848 t.tm_sec = 59;
4849 t.tm_min = 55;
4850 t.tm_hour = 23;
4851 t.tm_mday = 31;
4852 t.tm_mon = 11;
4853 t.tm_year = 161;
4854 t.tm_wday = 6;
4855 t.tm_yday = 364;
4856 t.tm_isdst = -1;
4857 char buf[100];
4858 char f[3] = {0};
4859 f[0] = '%';
4860 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004861 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004862 wchar_t wbuf[100];
4863 wchar_t* wbb = wbuf;
4864 mbstate_t mb = {0};
4865 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004866#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004867 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004868#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004869 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004870#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004871 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004872 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004873 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004874 wstring result;
4875 while (wbb != wbe)
4876 {
4877 if (ct.is(ctype_base::space, *wbb))
4878 {
4879 result.push_back(L' ');
4880 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4881 ;
4882 continue;
4883 }
4884 wchar_t* w = wbb;
4885 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004886 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004887 ct, err, false)
4888 - this->__weeks_;
4889 if (i < 14)
4890 {
4891 result.push_back(L'%');
4892 if (i < 7)
4893 result.push_back(L'A');
4894 else
4895 result.push_back(L'a');
4896 wbb = w;
4897 continue;
4898 }
4899 w = wbb;
4900 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4901 ct, err, false)
4902 - this->__months_;
4903 if (i < 24)
4904 {
4905 result.push_back(L'%');
4906 if (i < 12)
4907 result.push_back(L'B');
4908 else
4909 result.push_back(L'b');
4910 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4911 result.back() = L'm';
4912 wbb = w;
4913 continue;
4914 }
4915 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4916 {
4917 w = wbb;
4918 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4919 ct, err, false) - this->__am_pm_;
4920 if (i < 2)
4921 {
4922 result.push_back(L'%');
4923 result.push_back(L'p');
4924 wbb = w;
4925 continue;
4926 }
4927 }
4928 w = wbb;
4929 if (ct.is(ctype_base::digit, *wbb))
4930 {
4931 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4932 {
4933 case 6:
4934 result.push_back(L'%');
4935 result.push_back(L'w');
4936 break;
4937 case 7:
4938 result.push_back(L'%');
4939 result.push_back(L'u');
4940 break;
4941 case 11:
4942 result.push_back(L'%');
4943 result.push_back(L'I');
4944 break;
4945 case 12:
4946 result.push_back(L'%');
4947 result.push_back(L'm');
4948 break;
4949 case 23:
4950 result.push_back(L'%');
4951 result.push_back(L'H');
4952 break;
4953 case 31:
4954 result.push_back(L'%');
4955 result.push_back(L'd');
4956 break;
4957 case 55:
4958 result.push_back(L'%');
4959 result.push_back(L'M');
4960 break;
4961 case 59:
4962 result.push_back(L'%');
4963 result.push_back(L'S');
4964 break;
4965 case 61:
4966 result.push_back(L'%');
4967 result.push_back(L'y');
4968 break;
4969 case 364:
4970 result.push_back(L'%');
4971 result.push_back(L'j');
4972 break;
4973 case 2061:
4974 result.push_back(L'%');
4975 result.push_back(L'Y');
4976 break;
4977 default:
4978 for (; w != wbb; ++w)
4979 result.push_back(*w);
4980 break;
4981 }
4982 continue;
4983 }
4984 if (ct.narrow(*wbb, 0) == '%')
4985 {
4986 result.push_back(L'%');
4987 result.push_back(L'%');
4988 ++wbb;
4989 continue;
4990 }
4991 result.push_back(*wbb);
4992 ++wbb;
4993 }
4994 return result;
4995}
4996
4997template <>
4998void
4999__time_get_storage<char>::init(const ctype<char>& ct)
5000{
Howard Hinnantcd992362012-08-02 18:44:17 +00005001 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005002 char buf[100];
5003 // __weeks_
5004 for (int i = 0; i < 7; ++i)
5005 {
5006 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005007 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005008 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005009 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005010 __weeks_[i+7] = buf;
5011 }
5012 // __months_
5013 for (int i = 0; i < 12; ++i)
5014 {
5015 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005016 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005017 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005018 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005019 __months_[i+12] = buf;
5020 }
5021 // __am_pm_
5022 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005023 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005024 __am_pm_[0] = buf;
5025 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005026 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005027 __am_pm_[1] = buf;
5028 __c_ = __analyze('c', ct);
5029 __r_ = __analyze('r', ct);
5030 __x_ = __analyze('x', ct);
5031 __X_ = __analyze('X', ct);
5032}
5033
5034template <>
5035void
5036__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5037{
5038 tm t = {0};
5039 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005040 wchar_t wbuf[100];
5041 wchar_t* wbe;
5042 mbstate_t mb = {0};
5043 // __weeks_
5044 for (int i = 0; i < 7; ++i)
5045 {
5046 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005047 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005048 mb = mbstate_t();
5049 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005050#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005051 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005052#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005053 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005054#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005055 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005056 __throw_runtime_error("locale not supported");
5057 wbe = wbuf + j;
5058 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005059 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005060 mb = mbstate_t();
5061 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005062#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005063 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005064#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005065 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005066#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005067 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005068 __throw_runtime_error("locale not supported");
5069 wbe = wbuf + j;
5070 __weeks_[i+7].assign(wbuf, wbe);
5071 }
5072 // __months_
5073 for (int i = 0; i < 12; ++i)
5074 {
5075 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005076 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005077 mb = mbstate_t();
5078 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005079#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005080 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005081#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005082 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005083#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005084 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005085 __throw_runtime_error("locale not supported");
5086 wbe = wbuf + j;
5087 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005088 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005089 mb = mbstate_t();
5090 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005091#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005092 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005093#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005094 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005095#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005096 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005097 __throw_runtime_error("locale not supported");
5098 wbe = wbuf + j;
5099 __months_[i+12].assign(wbuf, wbe);
5100 }
5101 // __am_pm_
5102 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005103 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005104 mb = mbstate_t();
5105 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005106#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005107 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005108#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005109 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005110#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005111 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005112 __throw_runtime_error("locale not supported");
5113 wbe = wbuf + j;
5114 __am_pm_[0].assign(wbuf, wbe);
5115 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005116 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005117 mb = mbstate_t();
5118 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005119#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005120 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005121#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005122 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005123#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005124 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005125 __throw_runtime_error("locale not supported");
5126 wbe = wbuf + j;
5127 __am_pm_[1].assign(wbuf, wbe);
5128 __c_ = __analyze('c', ct);
5129 __r_ = __analyze('r', ct);
5130 __x_ = __analyze('x', ct);
5131 __X_ = __analyze('X', ct);
5132}
5133
5134template <class CharT>
5135struct _LIBCPP_HIDDEN __time_get_temp
5136 : public ctype_byname<CharT>
5137{
5138 explicit __time_get_temp(const char* nm)
5139 : ctype_byname<CharT>(nm, 1) {}
5140 explicit __time_get_temp(const string& nm)
5141 : ctype_byname<CharT>(nm, 1) {}
5142};
5143
5144template <>
5145__time_get_storage<char>::__time_get_storage(const char* __nm)
5146 : __time_get(__nm)
5147{
5148 const __time_get_temp<char> ct(__nm);
5149 init(ct);
5150}
5151
5152template <>
5153__time_get_storage<char>::__time_get_storage(const string& __nm)
5154 : __time_get(__nm)
5155{
5156 const __time_get_temp<char> ct(__nm);
5157 init(ct);
5158}
5159
5160template <>
5161__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5162 : __time_get(__nm)
5163{
5164 const __time_get_temp<wchar_t> ct(__nm);
5165 init(ct);
5166}
5167
5168template <>
5169__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5170 : __time_get(__nm)
5171{
5172 const __time_get_temp<wchar_t> ct(__nm);
5173 init(ct);
5174}
5175
5176template <>
5177time_base::dateorder
5178__time_get_storage<char>::__do_date_order() const
5179{
5180 unsigned i;
5181 for (i = 0; i < __x_.size(); ++i)
5182 if (__x_[i] == '%')
5183 break;
5184 ++i;
5185 switch (__x_[i])
5186 {
5187 case 'y':
5188 case 'Y':
5189 for (++i; i < __x_.size(); ++i)
5190 if (__x_[i] == '%')
5191 break;
5192 if (i == __x_.size())
5193 break;
5194 ++i;
5195 switch (__x_[i])
5196 {
5197 case 'm':
5198 for (++i; i < __x_.size(); ++i)
5199 if (__x_[i] == '%')
5200 break;
5201 if (i == __x_.size())
5202 break;
5203 ++i;
5204 if (__x_[i] == 'd')
5205 return time_base::ymd;
5206 break;
5207 case 'd':
5208 for (++i; i < __x_.size(); ++i)
5209 if (__x_[i] == '%')
5210 break;
5211 if (i == __x_.size())
5212 break;
5213 ++i;
5214 if (__x_[i] == 'm')
5215 return time_base::ydm;
5216 break;
5217 }
5218 break;
5219 case 'm':
5220 for (++i; i < __x_.size(); ++i)
5221 if (__x_[i] == '%')
5222 break;
5223 if (i == __x_.size())
5224 break;
5225 ++i;
5226 if (__x_[i] == 'd')
5227 {
5228 for (++i; i < __x_.size(); ++i)
5229 if (__x_[i] == '%')
5230 break;
5231 if (i == __x_.size())
5232 break;
5233 ++i;
5234 if (__x_[i] == 'y' || __x_[i] == 'Y')
5235 return time_base::mdy;
5236 break;
5237 }
5238 break;
5239 case 'd':
5240 for (++i; i < __x_.size(); ++i)
5241 if (__x_[i] == '%')
5242 break;
5243 if (i == __x_.size())
5244 break;
5245 ++i;
5246 if (__x_[i] == 'm')
5247 {
5248 for (++i; i < __x_.size(); ++i)
5249 if (__x_[i] == '%')
5250 break;
5251 if (i == __x_.size())
5252 break;
5253 ++i;
5254 if (__x_[i] == 'y' || __x_[i] == 'Y')
5255 return time_base::dmy;
5256 break;
5257 }
5258 break;
5259 }
5260 return time_base::no_order;
5261}
5262
5263template <>
5264time_base::dateorder
5265__time_get_storage<wchar_t>::__do_date_order() const
5266{
5267 unsigned i;
5268 for (i = 0; i < __x_.size(); ++i)
5269 if (__x_[i] == L'%')
5270 break;
5271 ++i;
5272 switch (__x_[i])
5273 {
5274 case L'y':
5275 case L'Y':
5276 for (++i; i < __x_.size(); ++i)
5277 if (__x_[i] == L'%')
5278 break;
5279 if (i == __x_.size())
5280 break;
5281 ++i;
5282 switch (__x_[i])
5283 {
5284 case L'm':
5285 for (++i; i < __x_.size(); ++i)
5286 if (__x_[i] == L'%')
5287 break;
5288 if (i == __x_.size())
5289 break;
5290 ++i;
5291 if (__x_[i] == L'd')
5292 return time_base::ymd;
5293 break;
5294 case L'd':
5295 for (++i; i < __x_.size(); ++i)
5296 if (__x_[i] == L'%')
5297 break;
5298 if (i == __x_.size())
5299 break;
5300 ++i;
5301 if (__x_[i] == L'm')
5302 return time_base::ydm;
5303 break;
5304 }
5305 break;
5306 case L'm':
5307 for (++i; i < __x_.size(); ++i)
5308 if (__x_[i] == L'%')
5309 break;
5310 if (i == __x_.size())
5311 break;
5312 ++i;
5313 if (__x_[i] == L'd')
5314 {
5315 for (++i; i < __x_.size(); ++i)
5316 if (__x_[i] == L'%')
5317 break;
5318 if (i == __x_.size())
5319 break;
5320 ++i;
5321 if (__x_[i] == L'y' || __x_[i] == L'Y')
5322 return time_base::mdy;
5323 break;
5324 }
5325 break;
5326 case L'd':
5327 for (++i; i < __x_.size(); ++i)
5328 if (__x_[i] == L'%')
5329 break;
5330 if (i == __x_.size())
5331 break;
5332 ++i;
5333 if (__x_[i] == L'm')
5334 {
5335 for (++i; i < __x_.size(); ++i)
5336 if (__x_[i] == L'%')
5337 break;
5338 if (i == __x_.size())
5339 break;
5340 ++i;
5341 if (__x_[i] == L'y' || __x_[i] == L'Y')
5342 return time_base::dmy;
5343 break;
5344 }
5345 break;
5346 }
5347 return time_base::no_order;
5348}
5349
5350// time_put
5351
5352__time_put::__time_put(const char* nm)
5353 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5354{
Howard Hinnantd4444702010-08-11 17:04:31 +00005355#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005356 if (__loc_ == 0)
5357 throw runtime_error("time_put_byname"
5358 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005359#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005360}
5361
5362__time_put::__time_put(const string& nm)
5363 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5364{
Howard Hinnantd4444702010-08-11 17:04:31 +00005365#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005366 if (__loc_ == 0)
5367 throw runtime_error("time_put_byname"
5368 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005369#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005370}
5371
5372__time_put::~__time_put()
5373{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005374 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005375 freelocale(__loc_);
5376}
5377
5378void
5379__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5380 char __fmt, char __mod) const
5381{
5382 char fmt[] = {'%', __fmt, __mod, 0};
5383 if (__mod != 0)
5384 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005385 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005386 __ne = __nb + n;
5387}
5388
5389void
5390__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5391 char __fmt, char __mod) const
5392{
5393 char __nar[100];
5394 char* __ne = __nar + 100;
5395 __do_put(__nar, __ne, __tm, __fmt, __mod);
5396 mbstate_t mb = {0};
5397 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005398#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005399 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005400#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005401 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005402#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005403 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005404 __throw_runtime_error("locale not supported");
5405 __we = __wb + j;
5406}
5407
5408// moneypunct_byname
5409
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005410template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005411static
5412void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005413__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5414 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5415 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005416{
5417 const char sign = static_cast<char>(money_base::sign);
5418 const char space = static_cast<char>(money_base::space);
5419 const char none = static_cast<char>(money_base::none);
5420 const char symbol = static_cast<char>(money_base::symbol);
5421 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005422 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5423
5424 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5425 // function'. "Space between sign and symbol or value" means that
5426 // if the sign is adjacent to the symbol, there's a space between
5427 // them, and otherwise there's a space between the sign and value.
5428 //
5429 // C11's localeconv specifies that the fourth character of an
5430 // international curr_symbol is used to separate the sign and
5431 // value when sep_by_space says to do so. C++ can't represent
5432 // that, so we just use a space. When sep_by_space says to
5433 // separate the symbol and value-or-sign with a space, we rearrange the
5434 // curr_symbol to put its spacing character on the correct side of
5435 // the symbol.
5436 //
5437 // We also need to avoid adding an extra space between the sign
5438 // and value when the currency symbol is suppressed (by not
5439 // setting showbase). We match glibc's strfmon by interpreting
5440 // sep_by_space==1 as "omit the space when the currency symbol is
5441 // absent".
5442 //
5443 // Users who want to get this right should use ICU instead.
5444
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005445 switch (cs_precedes)
5446 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005447 case 0: // value before curr_symbol
5448 if (symbol_contains_sep) {
5449 // Move the separator to before the symbol, to place it
5450 // between the value and symbol.
5451 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5452 __curr_symbol_.end());
5453 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005454 switch (sign_posn)
5455 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005456 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005457 pat.field[0] = sign;
5458 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005459 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005460 pat.field[3] = symbol;
5461 switch (sep_by_space)
5462 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005463 case 0: // No space separates the currency symbol and value.
5464 // This case may have changed between C99 and C11;
5465 // assume the currency symbol matches the intention.
5466 case 2: // Space between sign and currency or value.
5467 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005468 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005469 case 1: // Space between currency-and-sign or currency and value.
5470 if (!symbol_contains_sep) {
5471 // We insert the space into the symbol instead of
5472 // setting pat.field[2]=space so that when
5473 // showbase is not set, the space goes away too.
5474 __curr_symbol_.insert(0, 1, space_char);
5475 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005476 return;
5477 default:
5478 break;
5479 }
5480 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005481 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005482 pat.field[0] = sign;
5483 pat.field[3] = symbol;
5484 switch (sep_by_space)
5485 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005486 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005487 pat.field[1] = value;
5488 pat.field[2] = none;
5489 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005490 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005491 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005492 pat.field[2] = none;
5493 if (!symbol_contains_sep) {
5494 // We insert the space into the symbol instead of
5495 // setting pat.field[2]=space so that when
5496 // showbase is not set, the space goes away too.
5497 __curr_symbol_.insert(0, 1, space_char);
5498 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005499 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005500 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005501 pat.field[1] = space;
5502 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005503 if (symbol_contains_sep) {
5504 // Remove the separator from the symbol, since it
5505 // has already appeared after the sign.
5506 __curr_symbol_.erase(__curr_symbol_.begin());
5507 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005508 return;
5509 default:
5510 break;
5511 }
5512 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005513 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005514 pat.field[0] = value;
5515 pat.field[3] = sign;
5516 switch (sep_by_space)
5517 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005518 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005519 pat.field[1] = none;
5520 pat.field[2] = symbol;
5521 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005522 case 1: // Space between currency-and-sign or currency and value.
5523 if (!symbol_contains_sep) {
5524 // We insert the space into the symbol instead of
5525 // setting pat.field[1]=space so that when
5526 // showbase is not set, the space goes away too.
5527 __curr_symbol_.insert(0, 1, space_char);
5528 }
5529 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005530 pat.field[2] = symbol;
5531 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005532 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005533 pat.field[1] = symbol;
5534 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005535 if (symbol_contains_sep) {
5536 // Remove the separator from the symbol, since it
5537 // should not be removed if showbase is absent.
5538 __curr_symbol_.erase(__curr_symbol_.begin());
5539 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005540 return;
5541 default:
5542 break;
5543 }
5544 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005545 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005546 pat.field[0] = value;
5547 pat.field[3] = symbol;
5548 switch (sep_by_space)
5549 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005550 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005551 pat.field[1] = none;
5552 pat.field[2] = sign;
5553 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005554 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005555 pat.field[1] = space;
5556 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005557 if (symbol_contains_sep) {
5558 // Remove the separator from the symbol, since it
5559 // has already appeared before the sign.
5560 __curr_symbol_.erase(__curr_symbol_.begin());
5561 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005562 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005563 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005564 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005565 pat.field[2] = none;
5566 if (!symbol_contains_sep) {
5567 // We insert the space into the symbol instead of
5568 // setting pat.field[2]=space so that when
5569 // showbase is not set, the space goes away too.
5570 __curr_symbol_.insert(0, 1, space_char);
5571 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005572 return;
5573 default:
5574 break;
5575 }
5576 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005577 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005578 pat.field[0] = value;
5579 pat.field[3] = sign;
5580 switch (sep_by_space)
5581 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005582 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005583 pat.field[1] = none;
5584 pat.field[2] = symbol;
5585 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005586 case 1: // Space between currency-and-sign or currency and value.
5587 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005588 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005589 if (!symbol_contains_sep) {
5590 // We insert the space into the symbol instead of
5591 // setting pat.field[1]=space so that when
5592 // showbase is not set, the space goes away too.
5593 __curr_symbol_.insert(0, 1, space_char);
5594 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005595 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005596 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005597 pat.field[1] = symbol;
5598 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005599 if (symbol_contains_sep) {
5600 // Remove the separator from the symbol, since it
5601 // should not disappear when showbase is absent.
5602 __curr_symbol_.erase(__curr_symbol_.begin());
5603 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005604 return;
5605 default:
5606 break;
5607 }
5608 break;
5609 default:
5610 break;
5611 }
5612 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005613 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005614 switch (sign_posn)
5615 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005616 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005617 pat.field[0] = sign;
5618 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005619 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005620 pat.field[3] = value;
5621 switch (sep_by_space)
5622 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005623 case 0: // No space separates the currency symbol and value.
5624 // This case may have changed between C99 and C11;
5625 // assume the currency symbol matches the intention.
5626 case 2: // Space between sign and currency or value.
5627 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005628 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005629 case 1: // Space between currency-and-sign or currency and value.
5630 if (!symbol_contains_sep) {
5631 // We insert the space into the symbol instead of
5632 // setting pat.field[2]=space so that when
5633 // showbase is not set, the space goes away too.
5634 __curr_symbol_.insert(0, 1, space_char);
5635 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005636 return;
5637 default:
5638 break;
5639 }
5640 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005641 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005642 pat.field[0] = sign;
5643 pat.field[3] = value;
5644 switch (sep_by_space)
5645 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005646 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005647 pat.field[1] = symbol;
5648 pat.field[2] = none;
5649 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005650 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005651 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005652 pat.field[2] = none;
5653 if (!symbol_contains_sep) {
5654 // We insert the space into the symbol instead of
5655 // setting pat.field[2]=space so that when
5656 // showbase is not set, the space goes away too.
5657 __curr_symbol_.push_back(space_char);
5658 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005659 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005660 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005661 pat.field[1] = space;
5662 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005663 if (symbol_contains_sep) {
5664 // Remove the separator from the symbol, since it
5665 // has already appeared after the sign.
5666 __curr_symbol_.pop_back();
5667 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005668 return;
5669 default:
5670 break;
5671 }
5672 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005673 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005674 pat.field[0] = symbol;
5675 pat.field[3] = sign;
5676 switch (sep_by_space)
5677 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005678 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005679 pat.field[1] = none;
5680 pat.field[2] = value;
5681 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005682 case 1: // Space between currency-and-sign or currency and value.
5683 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005684 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005685 if (!symbol_contains_sep) {
5686 // We insert the space into the symbol instead of
5687 // setting pat.field[1]=space so that when
5688 // showbase is not set, the space goes away too.
5689 __curr_symbol_.push_back(space_char);
5690 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005691 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005692 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005693 pat.field[1] = value;
5694 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005695 if (symbol_contains_sep) {
5696 // Remove the separator from the symbol, since it
5697 // will appear before the sign.
5698 __curr_symbol_.pop_back();
5699 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005700 return;
5701 default:
5702 break;
5703 }
5704 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005705 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005706 pat.field[0] = sign;
5707 pat.field[3] = value;
5708 switch (sep_by_space)
5709 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005710 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005711 pat.field[1] = symbol;
5712 pat.field[2] = none;
5713 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005714 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005715 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005716 pat.field[2] = none;
5717 if (!symbol_contains_sep) {
5718 // We insert the space into the symbol instead of
5719 // setting pat.field[2]=space so that when
5720 // showbase is not set, the space goes away too.
5721 __curr_symbol_.push_back(space_char);
5722 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005723 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005724 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005725 pat.field[1] = space;
5726 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005727 if (symbol_contains_sep) {
5728 // Remove the separator from the symbol, since it
5729 // has already appeared after the sign.
5730 __curr_symbol_.pop_back();
5731 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005732 return;
5733 default:
5734 break;
5735 }
5736 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005737 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005738 pat.field[0] = symbol;
5739 pat.field[3] = value;
5740 switch (sep_by_space)
5741 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005742 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005743 pat.field[1] = sign;
5744 pat.field[2] = none;
5745 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005746 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005747 pat.field[1] = sign;
5748 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005749 if (symbol_contains_sep) {
5750 // Remove the separator from the symbol, since it
5751 // should not disappear when showbase is absent.
5752 __curr_symbol_.pop_back();
5753 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005754 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005755 case 2: // Space between sign and currency or value.
5756 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005757 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005758 if (!symbol_contains_sep) {
5759 // We insert the space into the symbol instead of
5760 // setting pat.field[1]=space so that when
5761 // showbase is not set, the space goes away too.
5762 __curr_symbol_.push_back(space_char);
5763 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005764 return;
5765 default:
5766 break;
5767 }
5768 break;
5769 default:
5770 break;
5771 }
5772 break;
5773 default:
5774 break;
5775 }
5776 pat.field[0] = symbol;
5777 pat.field[1] = sign;
5778 pat.field[2] = none;
5779 pat.field[3] = value;
5780}
5781
5782template<>
5783void
5784moneypunct_byname<char, false>::init(const char* nm)
5785{
5786 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005787 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005788#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005789 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005790 throw runtime_error("moneypunct_byname"
5791 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005792#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005793#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005794 lconv* lc = localeconv_l(loc.get());
5795#else
5796 lconv* lc = __localeconv_l(loc.get());
5797#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005798 if (*lc->mon_decimal_point)
5799 __decimal_point_ = *lc->mon_decimal_point;
5800 else
5801 __decimal_point_ = base::do_decimal_point();
5802 if (*lc->mon_thousands_sep)
5803 __thousands_sep_ = *lc->mon_thousands_sep;
5804 else
5805 __thousands_sep_ = base::do_thousands_sep();
5806 __grouping_ = lc->mon_grouping;
5807 __curr_symbol_ = lc->currency_symbol;
5808 if (lc->frac_digits != CHAR_MAX)
5809 __frac_digits_ = lc->frac_digits;
5810 else
5811 __frac_digits_ = base::do_frac_digits();
5812 if (lc->p_sign_posn == 0)
5813 __positive_sign_ = "()";
5814 else
5815 __positive_sign_ = lc->positive_sign;
5816 if (lc->n_sign_posn == 0)
5817 __negative_sign_ = "()";
5818 else
5819 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005820 // Assume the positive and negative formats will want spaces in
5821 // the same places in curr_symbol since there's no way to
5822 // represent anything else.
5823 string_type __dummy_curr_symbol = __curr_symbol_;
5824 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5825 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5826 __init_pat(__neg_format_, __curr_symbol_, false,
5827 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005828}
5829
5830template<>
5831void
5832moneypunct_byname<char, true>::init(const char* nm)
5833{
5834 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005835 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005836#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005837 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005838 throw runtime_error("moneypunct_byname"
5839 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005840#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005841#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005842 lconv* lc = localeconv_l(loc.get());
5843#else
5844 lconv* lc = __localeconv_l(loc.get());
5845#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005846 if (*lc->mon_decimal_point)
5847 __decimal_point_ = *lc->mon_decimal_point;
5848 else
5849 __decimal_point_ = base::do_decimal_point();
5850 if (*lc->mon_thousands_sep)
5851 __thousands_sep_ = *lc->mon_thousands_sep;
5852 else
5853 __thousands_sep_ = base::do_thousands_sep();
5854 __grouping_ = lc->mon_grouping;
5855 __curr_symbol_ = lc->int_curr_symbol;
5856 if (lc->int_frac_digits != CHAR_MAX)
5857 __frac_digits_ = lc->int_frac_digits;
5858 else
5859 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00005860#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005861 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005862#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005863 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005864#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005865 __positive_sign_ = "()";
5866 else
5867 __positive_sign_ = lc->positive_sign;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005868#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005869 if(lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005870#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005871 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005872#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005873 __negative_sign_ = "()";
5874 else
5875 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005876 // Assume the positive and negative formats will want spaces in
5877 // the same places in curr_symbol since there's no way to
5878 // represent anything else.
5879 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005880#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005881 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5882 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5883 __init_pat(__neg_format_, __curr_symbol_, true,
5884 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005885#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005886 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5887 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5888 lc->int_p_sign_posn, ' ');
5889 __init_pat(__neg_format_, __curr_symbol_, true,
5890 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5891 lc->int_n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005892#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005893}
5894
5895template<>
5896void
5897moneypunct_byname<wchar_t, false>::init(const char* nm)
5898{
5899 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005900 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005901#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005902 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005903 throw runtime_error("moneypunct_byname"
5904 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005905#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005906#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005907 lconv* lc = localeconv_l(loc.get());
5908#else
5909 lconv* lc = __localeconv_l(loc.get());
5910#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005911 if (*lc->mon_decimal_point)
5912 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5913 else
5914 __decimal_point_ = base::do_decimal_point();
5915 if (*lc->mon_thousands_sep)
5916 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5917 else
5918 __thousands_sep_ = base::do_thousands_sep();
5919 __grouping_ = lc->mon_grouping;
5920 wchar_t wbuf[100];
5921 mbstate_t mb = {0};
5922 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005923#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005924 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005925#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005926 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005927#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005928 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005929 __throw_runtime_error("locale not supported");
5930 wchar_t* wbe = wbuf + j;
5931 __curr_symbol_.assign(wbuf, wbe);
5932 if (lc->frac_digits != CHAR_MAX)
5933 __frac_digits_ = lc->frac_digits;
5934 else
5935 __frac_digits_ = base::do_frac_digits();
5936 if (lc->p_sign_posn == 0)
5937 __positive_sign_ = L"()";
5938 else
5939 {
5940 mb = mbstate_t();
5941 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005942#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005943 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005944#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005945 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005946#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005947 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005948 __throw_runtime_error("locale not supported");
5949 wbe = wbuf + j;
5950 __positive_sign_.assign(wbuf, wbe);
5951 }
5952 if (lc->n_sign_posn == 0)
5953 __negative_sign_ = L"()";
5954 else
5955 {
5956 mb = mbstate_t();
5957 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005958#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005959 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005960#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005963 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005964 __throw_runtime_error("locale not supported");
5965 wbe = wbuf + j;
5966 __negative_sign_.assign(wbuf, wbe);
5967 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005968 // Assume the positive and negative formats will want spaces in
5969 // the same places in curr_symbol since there's no way to
5970 // represent anything else.
5971 string_type __dummy_curr_symbol = __curr_symbol_;
5972 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5973 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5974 __init_pat(__neg_format_, __curr_symbol_, false,
5975 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005976}
5977
5978template<>
5979void
5980moneypunct_byname<wchar_t, true>::init(const char* nm)
5981{
5982 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005983 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005984#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005985 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005986 throw runtime_error("moneypunct_byname"
5987 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005988#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005989#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005990 lconv* lc = localeconv_l(loc.get());
5991#else
5992 lconv* lc = __localeconv_l(loc.get());
5993#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005994 if (*lc->mon_decimal_point)
5995 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5996 else
5997 __decimal_point_ = base::do_decimal_point();
5998 if (*lc->mon_thousands_sep)
5999 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6000 else
6001 __thousands_sep_ = base::do_thousands_sep();
6002 __grouping_ = lc->mon_grouping;
6003 wchar_t wbuf[100];
6004 mbstate_t mb = {0};
6005 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006006#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006007 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006008#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006009 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006010#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006011 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006012 __throw_runtime_error("locale not supported");
6013 wchar_t* wbe = wbuf + j;
6014 __curr_symbol_.assign(wbuf, wbe);
6015 if (lc->int_frac_digits != CHAR_MAX)
6016 __frac_digits_ = lc->int_frac_digits;
6017 else
6018 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00006019#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006020 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006021#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006022 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006023#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006024 __positive_sign_ = L"()";
6025 else
6026 {
6027 mb = mbstate_t();
6028 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006029#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006030 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006031#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006032 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006033#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006034 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006035 __throw_runtime_error("locale not supported");
6036 wbe = wbuf + j;
6037 __positive_sign_.assign(wbuf, wbe);
6038 }
Howard Hinnantef5aa932013-09-17 01:34:47 +00006039#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006040 if (lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006041#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006042 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006043#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006044 __negative_sign_ = L"()";
6045 else
6046 {
6047 mb = mbstate_t();
6048 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006049#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
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#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006052 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006053#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006054 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006055 __throw_runtime_error("locale not supported");
6056 wbe = wbuf + j;
6057 __negative_sign_.assign(wbuf, wbe);
6058 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006059 // Assume the positive and negative formats will want spaces in
6060 // the same places in curr_symbol since there's no way to
6061 // represent anything else.
6062 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00006063#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006064 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6065 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6066 __init_pat(__neg_format_, __curr_symbol_, true,
6067 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006068#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006069 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6070 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6071 lc->int_p_sign_posn, L' ');
6072 __init_pat(__neg_format_, __curr_symbol_, true,
6073 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6074 lc->int_n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006075#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006076}
6077
6078void __do_nothing(void*) {}
6079
6080void __throw_runtime_error(const char* msg)
6081{
Howard Hinnantd4444702010-08-11 17:04:31 +00006082#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006083 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006084#else
6085 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006086#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006087}
6088
6089template class collate<char>;
6090template class collate<wchar_t>;
6091
6092template class num_get<char>;
6093template class num_get<wchar_t>;
6094
Howard Hinnantec3773c2011-12-01 20:21:04 +00006095template struct __num_get<char>;
6096template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006097
6098template class num_put<char>;
6099template class num_put<wchar_t>;
6100
Howard Hinnantec3773c2011-12-01 20:21:04 +00006101template struct __num_put<char>;
6102template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006103
6104template class time_get<char>;
6105template class time_get<wchar_t>;
6106
6107template class time_get_byname<char>;
6108template class time_get_byname<wchar_t>;
6109
6110template class time_put<char>;
6111template class time_put<wchar_t>;
6112
6113template class time_put_byname<char>;
6114template class time_put_byname<wchar_t>;
6115
6116template class moneypunct<char, false>;
6117template class moneypunct<char, true>;
6118template class moneypunct<wchar_t, false>;
6119template class moneypunct<wchar_t, true>;
6120
6121template class moneypunct_byname<char, false>;
6122template class moneypunct_byname<char, true>;
6123template class moneypunct_byname<wchar_t, false>;
6124template class moneypunct_byname<wchar_t, true>;
6125
6126template class money_get<char>;
6127template class money_get<wchar_t>;
6128
6129template class __money_get<char>;
6130template class __money_get<wchar_t>;
6131
6132template class money_put<char>;
6133template class money_put<wchar_t>;
6134
6135template class __money_put<char>;
6136template class __money_put<wchar_t>;
6137
6138template class messages<char>;
6139template class messages<wchar_t>;
6140
6141template class messages_byname<char>;
6142template class messages_byname<wchar_t>;
6143
6144template class codecvt_byname<char, char, mbstate_t>;
6145template class codecvt_byname<wchar_t, char, mbstate_t>;
6146template class codecvt_byname<char16_t, char, mbstate_t>;
6147template class codecvt_byname<char32_t, char, mbstate_t>;
6148
6149template class __vector_base_common<true>;
6150
6151_LIBCPP_END_NAMESPACE_STD