blob: 868c758269ba3f080522a030f2c28de6d5b90a11 [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>
Dan Albert2ef012e2014-04-08 12:03:21 -070033#elif defined(__ANDROID__)
34#include <support/android/langinfo.h>
Howard Hinnante9df0a52013-08-01 18:17:34 +000035#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000036#include <langinfo.h>
Howard Hinnante9df0a52013-08-01 18:17:34 +000037#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000038#include <stdlib.h>
Howard Hinnanted14a762013-07-23 16:05:56 +000039#include <stdio.h>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000040
Marshall Clow9ae96d02013-02-07 17:20:56 +000041// On Linux, wint_t and wchar_t have different signed-ness, and this causes
42// lots of noise in the build log, but no bugs that I know of.
Marshall Clowa3645132013-10-21 15:07:28 +000043#if defined(__clang__)
Marshall Clow9ae96d02013-02-07 17:20:56 +000044#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowa3645132013-10-21 15:07:28 +000045#endif
Marshall Clow9ae96d02013-02-07 17:20:56 +000046
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000047_LIBCPP_BEGIN_NAMESPACE_STD
48
Howard Hinnant866569b2011-09-28 23:39:33 +000049#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000050locale_t __cloc() {
51 // In theory this could create a race condition. In practice
52 // the race condition is non-fatal since it will just create
53 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000054 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
55 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000056}
Howard Hinnant866569b2011-09-28 23:39:33 +000057#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000058
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000059namespace {
60
61struct release
62{
63 void operator()(locale::facet* p) {p->__release_shared();}
64};
65
66template <class T, class A0>
67inline
68T&
69make(A0 a0)
70{
71 static typename aligned_storage<sizeof(T)>::type buf;
72 ::new (&buf) T(a0);
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +000073 return *reinterpret_cast<T*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000074}
75
76template <class T, class A0, class A1>
77inline
78T&
79make(A0 a0, A1 a1)
80{
81 static typename aligned_storage<sizeof(T)>::type buf;
82 ::new (&buf) T(a0, a1);
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +000083 return *reinterpret_cast<T*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000084}
85
86template <class T, class A0, class A1, class A2>
87inline
88T&
89make(A0 a0, A1 a1, A2 a2)
90{
91 static typename aligned_storage<sizeof(T)>::type buf;
92 ::new (&buf) T(a0, a1, a2);
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +000093 return *reinterpret_cast<T*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000094}
95
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000096template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000097inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000098_LIBCPP_CONSTEXPR
99size_t
100countof(const T (&)[N])
101{
102 return N;
103}
104
105template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +0000106inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +0000107_LIBCPP_CONSTEXPR
108size_t
109countof(const T * const begin, const T * const end)
110{
111 return static_cast<size_t>(end - begin);
112}
113
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000114}
115
Howard Hinnant51437222013-08-29 23:37:50 +0000116#if defined(_AIX)
117// Set priority to INT_MIN + 256 + 150
118# pragma priority ( -2147483242 )
119#endif
120
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000121const locale::category locale::none;
122const locale::category locale::collate;
123const locale::category locale::ctype;
124const locale::category locale::monetary;
125const locale::category locale::numeric;
126const locale::category locale::time;
127const locale::category locale::messages;
128const locale::category locale::all;
129
Marshall Clowa3645132013-10-21 15:07:28 +0000130#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000131#pragma clang diagnostic push
132#pragma clang diagnostic ignored "-Wpadded"
Marshall Clowa3645132013-10-21 15:07:28 +0000133#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000134
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000135class _LIBCPP_HIDDEN locale::__imp
136 : public facet
137{
138 enum {N = 28};
Marshall Clowa3645132013-10-21 15:07:28 +0000139#if defined(_LIBCPP_MSVC)
140// FIXME: MSVC doesn't support aligned parameters by value.
141// I can't get the __sso_allocator to work here
142// for MSVC I think for this reason.
143 vector<facet*> facets_;
144#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000145 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowa3645132013-10-21 15:07:28 +0000146#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000147 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000148public:
149 explicit __imp(size_t refs = 0);
150 explicit __imp(const string& name, size_t refs = 0);
151 __imp(const __imp&);
152 __imp(const __imp&, const string&, locale::category c);
153 __imp(const __imp& other, const __imp& one, locale::category c);
154 __imp(const __imp&, facet* f, long id);
155 ~__imp();
156
157 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000158 bool has_facet(long id) const
159 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000160 const locale::facet* use_facet(long id) const;
161
162 static const locale& make_classic();
163 static locale& make_global();
164private:
165 void install(facet* f, long id);
166 template <class F> void install(F* f) {install(f, f->id.__get());}
167 template <class F> void install_from(const __imp& other);
168};
169
Marshall Clowa3645132013-10-21 15:07:28 +0000170#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000171#pragma clang diagnostic pop
Marshall Clowa3645132013-10-21 15:07:28 +0000172#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000173
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000174locale::__imp::__imp(size_t refs)
175 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000176 facets_(N),
177 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000178{
179 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000180 install(&make<_VSTD::collate<char> >(1u));
181 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000182 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnantec3773c2011-12-01 20:21:04 +0000183 install(&make<_VSTD::ctype<wchar_t> >(1u));
184 install(&make<codecvt<char, char, mbstate_t> >(1u));
185 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
186 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
187 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
188 install(&make<numpunct<char> >(1u));
189 install(&make<numpunct<wchar_t> >(1u));
190 install(&make<num_get<char> >(1u));
191 install(&make<num_get<wchar_t> >(1u));
192 install(&make<num_put<char> >(1u));
193 install(&make<num_put<wchar_t> >(1u));
194 install(&make<moneypunct<char, false> >(1u));
195 install(&make<moneypunct<char, true> >(1u));
196 install(&make<moneypunct<wchar_t, false> >(1u));
197 install(&make<moneypunct<wchar_t, true> >(1u));
198 install(&make<money_get<char> >(1u));
199 install(&make<money_get<wchar_t> >(1u));
200 install(&make<money_put<char> >(1u));
201 install(&make<money_put<wchar_t> >(1u));
202 install(&make<time_get<char> >(1u));
203 install(&make<time_get<wchar_t> >(1u));
204 install(&make<time_put<char> >(1u));
205 install(&make<time_put<wchar_t> >(1u));
206 install(&make<_VSTD::messages<char> >(1u));
207 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000208}
209
210locale::__imp::__imp(const string& name, size_t refs)
211 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000212 facets_(N),
213 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000214{
Howard Hinnantd4444702010-08-11 17:04:31 +0000215#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000216 try
217 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000218#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000219 facets_ = locale::classic().__locale_->facets_;
220 for (unsigned i = 0; i < facets_.size(); ++i)
221 if (facets_[i])
222 facets_[i]->__add_shared();
223 install(new collate_byname<char>(name_));
224 install(new collate_byname<wchar_t>(name_));
225 install(new ctype_byname<char>(name_));
226 install(new ctype_byname<wchar_t>(name_));
227 install(new codecvt_byname<char, char, mbstate_t>(name_));
228 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
229 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
230 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
231 install(new numpunct_byname<char>(name_));
232 install(new numpunct_byname<wchar_t>(name_));
233 install(new moneypunct_byname<char, false>(name_));
234 install(new moneypunct_byname<char, true>(name_));
235 install(new moneypunct_byname<wchar_t, false>(name_));
236 install(new moneypunct_byname<wchar_t, true>(name_));
237 install(new time_get_byname<char>(name_));
238 install(new time_get_byname<wchar_t>(name_));
239 install(new time_put_byname<char>(name_));
240 install(new time_put_byname<wchar_t>(name_));
241 install(new messages_byname<char>(name_));
242 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000243#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000244 }
245 catch (...)
246 {
247 for (unsigned i = 0; i < facets_.size(); ++i)
248 if (facets_[i])
249 facets_[i]->__release_shared();
250 throw;
251 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000252#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000253}
254
Howard Hinnant21772ec2012-12-28 18:15:01 +0000255// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000256// copy constructor` warning emitted by GCC
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 push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000259#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000260#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000261
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000262locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000263 : facets_(max<size_t>(N, other.facets_.size())),
264 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000265{
266 facets_ = other.facets_;
267 for (unsigned i = 0; i < facets_.size(); ++i)
268 if (facets_[i])
269 facets_[i]->__add_shared();
270}
271
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000272#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000273#pragma GCC diagnostic pop
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000274#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000275
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000276locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000277 : facets_(N),
278 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000279{
280 facets_ = other.facets_;
281 for (unsigned i = 0; i < facets_.size(); ++i)
282 if (facets_[i])
283 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000284#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000285 try
286 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000287#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000288 if (c & locale::collate)
289 {
290 install(new collate_byname<char>(name));
291 install(new collate_byname<wchar_t>(name));
292 }
293 if (c & locale::ctype)
294 {
295 install(new ctype_byname<char>(name));
296 install(new ctype_byname<wchar_t>(name));
297 install(new codecvt_byname<char, char, mbstate_t>(name));
298 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
299 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
300 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
301 }
302 if (c & locale::monetary)
303 {
304 install(new moneypunct_byname<char, false>(name));
305 install(new moneypunct_byname<char, true>(name));
306 install(new moneypunct_byname<wchar_t, false>(name));
307 install(new moneypunct_byname<wchar_t, true>(name));
308 }
309 if (c & locale::numeric)
310 {
311 install(new numpunct_byname<char>(name));
312 install(new numpunct_byname<wchar_t>(name));
313 }
314 if (c & locale::time)
315 {
316 install(new time_get_byname<char>(name));
317 install(new time_get_byname<wchar_t>(name));
318 install(new time_put_byname<char>(name));
319 install(new time_put_byname<wchar_t>(name));
320 }
321 if (c & locale::messages)
322 {
323 install(new messages_byname<char>(name));
324 install(new messages_byname<wchar_t>(name));
325 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000326#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000327 }
328 catch (...)
329 {
330 for (unsigned i = 0; i < facets_.size(); ++i)
331 if (facets_[i])
332 facets_[i]->__release_shared();
333 throw;
334 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000335#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000336}
337
338template<class F>
339inline
340void
341locale::__imp::install_from(const locale::__imp& one)
342{
343 long id = F::id.__get();
344 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
345}
346
347locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000348 : facets_(N),
349 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000350{
351 facets_ = other.facets_;
352 for (unsigned i = 0; i < facets_.size(); ++i)
353 if (facets_[i])
354 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000355#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000356 try
357 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000358#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000359 if (c & locale::collate)
360 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000361 install_from<_VSTD::collate<char> >(one);
362 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000363 }
364 if (c & locale::ctype)
365 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000366 install_from<_VSTD::ctype<char> >(one);
367 install_from<_VSTD::ctype<wchar_t> >(one);
368 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
369 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
370 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
371 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000372 }
373 if (c & locale::monetary)
374 {
375 install_from<moneypunct<char, false> >(one);
376 install_from<moneypunct<char, true> >(one);
377 install_from<moneypunct<wchar_t, false> >(one);
378 install_from<moneypunct<wchar_t, true> >(one);
379 install_from<money_get<char> >(one);
380 install_from<money_get<wchar_t> >(one);
381 install_from<money_put<char> >(one);
382 install_from<money_put<wchar_t> >(one);
383 }
384 if (c & locale::numeric)
385 {
386 install_from<numpunct<char> >(one);
387 install_from<numpunct<wchar_t> >(one);
388 install_from<num_get<char> >(one);
389 install_from<num_get<wchar_t> >(one);
390 install_from<num_put<char> >(one);
391 install_from<num_put<wchar_t> >(one);
392 }
393 if (c & locale::time)
394 {
395 install_from<time_get<char> >(one);
396 install_from<time_get<wchar_t> >(one);
397 install_from<time_put<char> >(one);
398 install_from<time_put<wchar_t> >(one);
399 }
400 if (c & locale::messages)
401 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000402 install_from<_VSTD::messages<char> >(one);
403 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000404 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000405#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000406 }
407 catch (...)
408 {
409 for (unsigned i = 0; i < facets_.size(); ++i)
410 if (facets_[i])
411 facets_[i]->__release_shared();
412 throw;
413 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000414#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000415}
416
417locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000418 : facets_(max<size_t>(N, other.facets_.size()+1)),
419 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000420{
421 f->__add_shared();
422 unique_ptr<facet, release> hold(f);
423 facets_ = other.facets_;
424 for (unsigned i = 0; i < other.facets_.size(); ++i)
425 if (facets_[i])
426 facets_[i]->__add_shared();
427 install(hold.get(), id);
428}
429
430locale::__imp::~__imp()
431{
432 for (unsigned i = 0; i < facets_.size(); ++i)
433 if (facets_[i])
434 facets_[i]->__release_shared();
435}
436
437void
438locale::__imp::install(facet* f, long id)
439{
440 f->__add_shared();
441 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000442 if (static_cast<size_t>(id) >= facets_.size())
443 facets_.resize(static_cast<size_t>(id+1));
444 if (facets_[static_cast<size_t>(id)])
445 facets_[static_cast<size_t>(id)]->__release_shared();
446 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000447}
448
449const locale::facet*
450locale::__imp::use_facet(long id) const
451{
Howard Hinnantd4444702010-08-11 17:04:31 +0000452#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000453 if (!has_facet(id))
454 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000455#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000456 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000457}
458
459// locale
460
461const locale&
462locale::__imp::make_classic()
463{
464 // only one thread can get in here and it only gets in once
465 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000466 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000467 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000468 return *c;
469}
470
471const locale&
472locale::classic()
473{
474 static const locale& c = __imp::make_classic();
475 return c;
476}
477
478locale&
479locale::__imp::make_global()
480{
481 // only one thread can get in here and it only gets in once
482 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000483 ::new (&buf) locale(locale::classic());
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000484 return *reinterpret_cast<locale*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000485}
486
487locale&
488locale::__global()
489{
490 static locale& g = __imp::make_global();
491 return g;
492}
493
Howard Hinnantc9834542011-05-31 15:34:58 +0000494locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000495 : __locale_(__global().__locale_)
496{
497 __locale_->__add_shared();
498}
499
Howard Hinnantc9834542011-05-31 15:34:58 +0000500locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000501 : __locale_(l.__locale_)
502{
503 __locale_->__add_shared();
504}
505
Howard Hinnantc9834542011-05-31 15:34:58 +0000506locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000507{
508 __locale_->__release_shared();
509}
510
511const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000512locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000513{
514 other.__locale_->__add_shared();
515 __locale_->__release_shared();
516 __locale_ = other.__locale_;
517 return *this;
518}
519
520locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000521#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000522 : __locale_(name ? new __imp(name)
523 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000524#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000525 : __locale_(new __imp(name))
526#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000527{
528 __locale_->__add_shared();
529}
530
531locale::locale(const string& name)
532 : __locale_(new __imp(name))
533{
534 __locale_->__add_shared();
535}
536
537locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000538#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000539 : __locale_(name ? new __imp(*other.__locale_, name, c)
540 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000541#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000542 : __locale_(new __imp(*other.__locale_, name, c))
543#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000544{
545 __locale_->__add_shared();
546}
547
548locale::locale(const locale& other, const string& name, category c)
549 : __locale_(new __imp(*other.__locale_, name, c))
550{
551 __locale_->__add_shared();
552}
553
554locale::locale(const locale& other, const locale& one, category c)
555 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
556{
557 __locale_->__add_shared();
558}
559
560string
561locale::name() const
562{
563 return __locale_->name();
564}
565
566void
567locale::__install_ctor(const locale& other, facet* f, long id)
568{
569 if (f)
570 __locale_ = new __imp(*other.__locale_, f, id);
571 else
572 __locale_ = other.__locale_;
573 __locale_->__add_shared();
574}
575
576locale
577locale::global(const locale& loc)
578{
579 locale& g = __global();
580 locale r = g;
581 g = loc;
582 if (g.name() != "*")
583 setlocale(LC_ALL, g.name().c_str());
584 return r;
585}
586
587bool
588locale::has_facet(id& x) const
589{
590 return __locale_->has_facet(x.__get());
591}
592
593const locale::facet*
594locale::use_facet(id& x) const
595{
596 return __locale_->use_facet(x.__get());
597}
598
599bool
600locale::operator==(const locale& y) const
601{
602 return (__locale_ == y.__locale_)
603 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
604}
605
606// locale::facet
607
608locale::facet::~facet()
609{
610}
611
612void
Howard Hinnant1694d232011-05-28 14:41:13 +0000613locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000614{
615 delete this;
616}
617
618// locale::id
619
620int32_t locale::id::__next_id = 0;
621
622namespace
623{
624
625class __fake_bind
626{
627 locale::id* id_;
628 void (locale::id::* pmf_)();
629public:
630 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
631 : id_(id), pmf_(pmf) {}
632
633 void operator()() const
634 {
635 (id_->*pmf_)();
636 }
637};
638
639}
640
641long
642locale::id::__get()
643{
644 call_once(__flag_, __fake_bind(&locale::id::__init, this));
645 return __id_ - 1;
646}
647
648void
649locale::id::__init()
650{
Howard Hinnantadff4892010-05-24 17:49:41 +0000651 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000652}
653
654// template <> class collate_byname<char>
655
656collate_byname<char>::collate_byname(const char* n, size_t refs)
657 : collate<char>(refs),
658 __l(newlocale(LC_ALL_MASK, n, 0))
659{
Howard Hinnantd4444702010-08-11 17:04:31 +0000660#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000661 if (__l == 0)
662 throw runtime_error("collate_byname<char>::collate_byname"
663 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000664#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000665}
666
667collate_byname<char>::collate_byname(const string& name, size_t refs)
668 : collate<char>(refs),
669 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
670{
Howard Hinnantd4444702010-08-11 17:04:31 +0000671#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000672 if (__l == 0)
673 throw runtime_error("collate_byname<char>::collate_byname"
674 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000675#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000676}
677
678collate_byname<char>::~collate_byname()
679{
680 freelocale(__l);
681}
682
683int
684collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
685 const char_type* __lo2, const char_type* __hi2) const
686{
687 string_type lhs(__lo1, __hi1);
688 string_type rhs(__lo2, __hi2);
689 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
690 if (r < 0)
691 return -1;
692 if (r > 0)
693 return 1;
694 return r;
695}
696
697collate_byname<char>::string_type
698collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
699{
700 const string_type in(lo, hi);
701 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
702 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
703 return out;
704}
705
706// template <> class collate_byname<wchar_t>
707
708collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
709 : collate<wchar_t>(refs),
710 __l(newlocale(LC_ALL_MASK, n, 0))
711{
Howard Hinnantd4444702010-08-11 17:04:31 +0000712#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000713 if (__l == 0)
714 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
715 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000716#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000717}
718
719collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
720 : collate<wchar_t>(refs),
721 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
722{
Howard Hinnantd4444702010-08-11 17:04:31 +0000723#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000724 if (__l == 0)
725 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
726 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000727#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000728}
729
730collate_byname<wchar_t>::~collate_byname()
731{
732 freelocale(__l);
733}
734
735int
736collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
737 const char_type* __lo2, const char_type* __hi2) const
738{
739 string_type lhs(__lo1, __hi1);
740 string_type rhs(__lo2, __hi2);
741 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
742 if (r < 0)
743 return -1;
744 if (r > 0)
745 return 1;
746 return r;
747}
748
749collate_byname<wchar_t>::string_type
750collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
751{
752 const string_type in(lo, hi);
753 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
754 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
755 return out;
756}
757
758// template <> class ctype<wchar_t>;
759
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000760const ctype_base::mask ctype_base::space;
761const ctype_base::mask ctype_base::print;
762const ctype_base::mask ctype_base::cntrl;
763const ctype_base::mask ctype_base::upper;
764const ctype_base::mask ctype_base::lower;
765const ctype_base::mask ctype_base::alpha;
766const ctype_base::mask ctype_base::digit;
767const ctype_base::mask ctype_base::punct;
768const ctype_base::mask ctype_base::xdigit;
769const ctype_base::mask ctype_base::blank;
770const ctype_base::mask ctype_base::alnum;
771const ctype_base::mask ctype_base::graph;
772
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000773locale::id ctype<wchar_t>::id;
774
775ctype<wchar_t>::~ctype()
776{
777}
778
779bool
780ctype<wchar_t>::do_is(mask m, char_type c) const
781{
Marshall Clowa3645132013-10-21 15:07:28 +0000782 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000783}
784
785const wchar_t*
786ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
787{
788 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000789 *vec = static_cast<mask>(isascii(*low) ?
790 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000791 return low;
792}
793
794const wchar_t*
795ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
796{
797 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000798 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000799 break;
800 return low;
801}
802
803const wchar_t*
804ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
805{
806 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000807 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000808 break;
809 return low;
810}
811
812wchar_t
813ctype<wchar_t>::do_toupper(char_type c) const
814{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000815#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
816 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000817#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000818 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000819#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000820 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000821#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000822}
823
824const wchar_t*
825ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
826{
827 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000828#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
829 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000830#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000831 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
832 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000833#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000834 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000835#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000836 return low;
837}
838
839wchar_t
840ctype<wchar_t>::do_tolower(char_type c) const
841{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000842#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
843 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000844#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000845 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000846#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000847 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000848#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000849}
850
851const wchar_t*
852ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
853{
854 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000855#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
856 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000857#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000858 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
859 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000860#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000861 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000862#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000863 return low;
864}
865
866wchar_t
867ctype<wchar_t>::do_widen(char c) const
868{
869 return c;
870}
871
872const char*
873ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
874{
875 for (; low != high; ++low, ++dest)
876 *dest = *low;
877 return low;
878}
879
880char
881ctype<wchar_t>::do_narrow(char_type c, char dfault) const
882{
883 if (isascii(c))
884 return static_cast<char>(c);
885 return dfault;
886}
887
888const wchar_t*
889ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
890{
891 for (; low != high; ++low, ++dest)
892 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000893 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000894 else
895 *dest = dfault;
896 return low;
897}
898
899// template <> class ctype<char>;
900
901locale::id ctype<char>::id;
902
903ctype<char>::ctype(const mask* tab, bool del, size_t refs)
904 : locale::facet(refs),
905 __tab_(tab),
906 __del_(del)
907{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000908 if (__tab_ == 0)
909 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000910}
911
912ctype<char>::~ctype()
913{
914 if (__tab_ && __del_)
915 delete [] __tab_;
916}
917
918char
919ctype<char>::do_toupper(char_type c) const
920{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000921#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000922 return isascii(c) ?
923 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000924#elif defined(__NetBSD__)
925 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000926#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000927 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000928 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000929#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000930 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000931#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000932}
933
934const char*
935ctype<char>::do_toupper(char_type* low, const char_type* high) const
936{
937 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000938#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000939 *low = isascii(*low) ?
940 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000941#elif defined(__NetBSD__)
942 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000943#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000944 *low = isascii(*low) ?
945 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000946#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000947 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000948#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000949 return low;
950}
951
952char
953ctype<char>::do_tolower(char_type c) const
954{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000955#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000956 return isascii(c) ?
957 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000958#elif defined(__NetBSD__)
959 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000960#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Marshall Clow88c31902013-02-07 14:22:51 +0000961 return isascii(c) ?
962 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000963#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000964 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000965#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000966}
967
968const char*
969ctype<char>::do_tolower(char_type* low, const char_type* high) const
970{
971 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000972#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000973 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000974#elif defined(__NetBSD__)
975 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000976#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000977 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000978#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000979 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000980#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000981 return low;
982}
983
984char
985ctype<char>::do_widen(char c) const
986{
987 return c;
988}
989
990const char*
991ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
992{
993 for (; low != high; ++low, ++dest)
994 *dest = *low;
995 return low;
996}
997
998char
999ctype<char>::do_narrow(char_type c, char dfault) const
1000{
1001 if (isascii(c))
1002 return static_cast<char>(c);
1003 return dfault;
1004}
1005
1006const char*
1007ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1008{
1009 for (; low != high; ++low, ++dest)
1010 if (isascii(*low))
1011 *dest = *low;
1012 else
1013 *dest = dfault;
1014 return low;
1015}
1016
Marshall Clow2ccffef2013-11-19 18:05:03 +00001017#ifdef __EMSCRIPTEN__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001018extern "C" const unsigned short ** __ctype_b_loc();
1019extern "C" const int ** __ctype_tolower_loc();
1020extern "C" const int ** __ctype_toupper_loc();
1021#endif
1022
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001023const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001024ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025{
David Chisnallc512df12011-09-21 08:39:44 +00001026#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001027 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001028#elif defined(__NetBSD__)
1029 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001030#elif defined(__GLIBC__)
1031 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001032#elif __sun__
1033 return __ctype_mask;
Howard Hinnantef5aa932013-09-17 01:34:47 +00001034#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001035 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001036// This is assumed to be safe, which is a nonsense assumption because we're
1037// going to end up dereferencing it later...
Marshall Clow2ccffef2013-11-19 18:05:03 +00001038#elif defined(__EMSCRIPTEN__)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001039 return *__ctype_b_loc();
Howard Hinnant7f764502013-08-14 18:00:20 +00001040#elif defined(_AIX)
Marshall Clow016d4e82013-11-19 19:16:03 +00001041 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Dan Albert2517f4f2014-04-17 17:42:46 -07001042#elif defined(__ANDROID__)
1043 return _ctype_;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001044#else
David Chisnall997e4542012-02-29 13:05:08 +00001045 // Platform not supported: abort so the person doing the port knows what to
1046 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001047# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001048 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001049 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001050 return NULL;
1051#endif
1052}
1053
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001054#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001055const int*
1056ctype<char>::__classic_lower_table() _NOEXCEPT
1057{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001058 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001059}
1060
1061const int*
1062ctype<char>::__classic_upper_table() _NOEXCEPT
1063{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001064 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001065}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001066#elif __NetBSD__
1067const short*
1068ctype<char>::__classic_lower_table() _NOEXCEPT
1069{
1070 return _C_tolower_tab_ + 1;
1071}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001072
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001073const short*
1074ctype<char>::__classic_upper_table() _NOEXCEPT
1075{
1076 return _C_toupper_tab_ + 1;
1077}
1078
Marshall Clow2ccffef2013-11-19 18:05:03 +00001079#elif defined(__EMSCRIPTEN__)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001080const int*
1081ctype<char>::__classic_lower_table() _NOEXCEPT
1082{
1083 return *__ctype_tolower_loc();
1084}
1085
1086const int*
1087ctype<char>::__classic_upper_table() _NOEXCEPT
1088{
1089 return *__ctype_toupper_loc();
1090}
Marshall Clow2ccffef2013-11-19 18:05:03 +00001091#endif // __GLIBC__ || __EMSCRIPTEN__ || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001092
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001093// template <> class ctype_byname<char>
1094
1095ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1096 : ctype<char>(0, false, refs),
1097 __l(newlocale(LC_ALL_MASK, name, 0))
1098{
Howard Hinnantd4444702010-08-11 17:04:31 +00001099#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001100 if (__l == 0)
1101 throw runtime_error("ctype_byname<char>::ctype_byname"
1102 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001103#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001104}
1105
1106ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1107 : ctype<char>(0, false, refs),
1108 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1109{
Howard Hinnantd4444702010-08-11 17:04:31 +00001110#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001111 if (__l == 0)
1112 throw runtime_error("ctype_byname<char>::ctype_byname"
1113 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001114#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001115}
1116
1117ctype_byname<char>::~ctype_byname()
1118{
1119 freelocale(__l);
1120}
1121
1122char
1123ctype_byname<char>::do_toupper(char_type c) const
1124{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001125 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001126}
1127
1128const char*
1129ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1130{
1131 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001132 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001133 return low;
1134}
1135
1136char
1137ctype_byname<char>::do_tolower(char_type c) const
1138{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001139 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001140}
1141
1142const char*
1143ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1144{
1145 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001146 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001147 return low;
1148}
1149
1150// template <> class ctype_byname<wchar_t>
1151
1152ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1153 : ctype<wchar_t>(refs),
1154 __l(newlocale(LC_ALL_MASK, name, 0))
1155{
Howard Hinnantd4444702010-08-11 17:04:31 +00001156#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001157 if (__l == 0)
1158 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1159 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001160#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001161}
1162
1163ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1164 : ctype<wchar_t>(refs),
1165 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1166{
Howard Hinnantd4444702010-08-11 17:04:31 +00001167#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001168 if (__l == 0)
1169 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1170 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001171#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001172}
1173
1174ctype_byname<wchar_t>::~ctype_byname()
1175{
1176 freelocale(__l);
1177}
1178
1179bool
1180ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1181{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001182#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001183 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001184#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001185 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001186 wint_t ch = static_cast<wint_t>(c);
1187 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1188 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1189 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1190 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1191 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1192 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1193 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1194 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1195 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1196 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001197 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001198#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001199}
1200
1201const wchar_t*
1202ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1203{
1204 for (; low != high; ++low, ++vec)
1205 {
1206 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001207 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001208 else
1209 {
1210 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001211 wint_t ch = static_cast<wint_t>(*low);
1212 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001213 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001214 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001215 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001216 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001217 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001218 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001219 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001220 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001221 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001222 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001223 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001224 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001225 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001226 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001227 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001228 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001229 *vec |= xdigit;
1230 }
1231 }
1232 return low;
1233}
1234
1235const wchar_t*
1236ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1237{
1238 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001239 {
1240#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001241 if (iswctype_l(*low, m, __l))
1242 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001243#else
Marshall Clow88c31902013-02-07 14:22:51 +00001244 wint_t ch = static_cast<wint_t>(*low);
1245 if (m & space && iswspace_l(ch, __l)) break;
1246 if (m & print && iswprint_l(ch, __l)) break;
1247 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1248 if (m & upper && iswupper_l(ch, __l)) break;
1249 if (m & lower && iswlower_l(ch, __l)) break;
1250 if (m & alpha && iswalpha_l(ch, __l)) break;
1251 if (m & digit && iswdigit_l(ch, __l)) break;
1252 if (m & punct && iswpunct_l(ch, __l)) break;
1253 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1254 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001255#endif
1256 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001257 return low;
1258}
1259
1260const wchar_t*
1261ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1262{
1263 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001264 {
1265#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001266 if (!iswctype_l(*low, m, __l))
1267 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001268#else
Marshall Clow88c31902013-02-07 14:22:51 +00001269 wint_t ch = static_cast<wint_t>(*low);
1270 if (m & space && iswspace_l(ch, __l)) continue;
1271 if (m & print && iswprint_l(ch, __l)) continue;
1272 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1273 if (m & upper && iswupper_l(ch, __l)) continue;
1274 if (m & lower && iswlower_l(ch, __l)) continue;
1275 if (m & alpha && iswalpha_l(ch, __l)) continue;
1276 if (m & digit && iswdigit_l(ch, __l)) continue;
1277 if (m & punct && iswpunct_l(ch, __l)) continue;
1278 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1279 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001280 break;
1281#endif
1282 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001283 return low;
1284}
1285
1286wchar_t
1287ctype_byname<wchar_t>::do_toupper(char_type c) const
1288{
1289 return towupper_l(c, __l);
1290}
1291
1292const wchar_t*
1293ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1294{
1295 for (; low != high; ++low)
1296 *low = towupper_l(*low, __l);
1297 return low;
1298}
1299
1300wchar_t
1301ctype_byname<wchar_t>::do_tolower(char_type c) const
1302{
1303 return towlower_l(c, __l);
1304}
1305
1306const wchar_t*
1307ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1308{
1309 for (; low != high; ++low)
1310 *low = towlower_l(*low, __l);
1311 return low;
1312}
1313
1314wchar_t
1315ctype_byname<wchar_t>::do_widen(char c) const
1316{
Howard Hinnant866569b2011-09-28 23:39:33 +00001317#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001318 return btowc_l(c, __l);
1319#else
1320 return __btowc_l(c, __l);
1321#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001322}
1323
1324const char*
1325ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1326{
1327 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001328#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001329 *dest = btowc_l(*low, __l);
1330#else
1331 *dest = __btowc_l(*low, __l);
1332#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001333 return low;
1334}
1335
1336char
1337ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1338{
Howard Hinnant866569b2011-09-28 23:39:33 +00001339#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001340 int r = wctob_l(c, __l);
1341#else
1342 int r = __wctob_l(c, __l);
1343#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001344 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001345}
1346
1347const wchar_t*
1348ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1349{
1350 for (; low != high; ++low, ++dest)
1351 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001352#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001353 int r = wctob_l(*low, __l);
1354#else
1355 int r = __wctob_l(*low, __l);
1356#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001357 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001358 }
1359 return low;
1360}
1361
1362// template <> class codecvt<char, char, mbstate_t>
1363
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001364locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001365
1366codecvt<char, char, mbstate_t>::~codecvt()
1367{
1368}
1369
1370codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001371codecvt<char, char, mbstate_t>::do_out(state_type&,
1372 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001373 extern_type* to, extern_type*, extern_type*& to_nxt) const
1374{
1375 frm_nxt = frm;
1376 to_nxt = to;
1377 return noconv;
1378}
1379
1380codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001381codecvt<char, char, mbstate_t>::do_in(state_type&,
1382 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001383 intern_type* to, intern_type*, intern_type*& to_nxt) const
1384{
1385 frm_nxt = frm;
1386 to_nxt = to;
1387 return noconv;
1388}
1389
1390codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001391codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001392 extern_type* to, extern_type*, extern_type*& to_nxt) const
1393{
1394 to_nxt = to;
1395 return noconv;
1396}
1397
1398int
Howard Hinnantc9834542011-05-31 15:34:58 +00001399codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001400{
1401 return 1;
1402}
1403
1404bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001405codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001406{
1407 return true;
1408}
1409
1410int
1411codecvt<char, char, mbstate_t>::do_length(state_type&,
1412 const extern_type* frm, const extern_type* end, size_t mx) const
1413{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001414 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001415}
1416
1417int
Howard Hinnantc9834542011-05-31 15:34:58 +00001418codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001419{
1420 return 1;
1421}
1422
1423// template <> class codecvt<wchar_t, char, mbstate_t>
1424
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001425locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001426
1427codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1428 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001429 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001430{
1431}
1432
1433codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1434 : locale::facet(refs),
1435 __l(newlocale(LC_ALL_MASK, nm, 0))
1436{
Howard Hinnantd4444702010-08-11 17:04:31 +00001437#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001438 if (__l == 0)
1439 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1440 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001441#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001442}
1443
1444codecvt<wchar_t, char, mbstate_t>::~codecvt()
1445{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001446 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001447 freelocale(__l);
1448}
1449
1450codecvt<wchar_t, char, mbstate_t>::result
1451codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001452 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001453 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1454{
1455 // look for first internal null in frm
1456 const intern_type* fend = frm;
1457 for (; fend != frm_end; ++fend)
1458 if (*fend == 0)
1459 break;
1460 // loop over all null-terminated sequences in frm
1461 to_nxt = to;
1462 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1463 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001464 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001465 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001466#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001467 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1468 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001469#else
1470 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1471#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001472 if (n == size_t(-1))
1473 {
1474 // need to recover to_nxt
1475 for (to_nxt = to; frm != frm_nxt; ++frm)
1476 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001477#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001478 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1479#else
1480 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1481#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001482 if (n == size_t(-1))
1483 break;
1484 to_nxt += n;
1485 }
1486 frm_nxt = frm;
1487 return error;
1488 }
1489 if (n == 0)
1490 return partial;
1491 to_nxt += n;
1492 if (to_nxt == to_end)
1493 break;
1494 if (fend != frm_end) // set up next null terminated sequence
1495 {
1496 // Try to write the terminating null
1497 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001498#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001499 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1500#else
1501 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1502#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001503 if (n == size_t(-1)) // on error
1504 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001505 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001506 return partial;
1507 for (extern_type* p = tmp; n; --n) // write it
1508 *to_nxt++ = *p++;
1509 ++frm_nxt;
1510 // look for next null in frm
1511 for (fend = frm_nxt; fend != frm_end; ++fend)
1512 if (*fend == 0)
1513 break;
1514 }
1515 }
1516 return frm_nxt == frm_end ? ok : partial;
1517}
1518
1519codecvt<wchar_t, char, mbstate_t>::result
1520codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001521 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001522 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1523{
1524 // look for first internal null in frm
1525 const extern_type* fend = frm;
1526 for (; fend != frm_end; ++fend)
1527 if (*fend == 0)
1528 break;
1529 // loop over all null-terminated sequences in frm
1530 to_nxt = to;
1531 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1532 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001533 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001534 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001535#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001536 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1537 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001538#else
1539 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1540#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001541 if (n == size_t(-1))
1542 {
1543 // need to recover to_nxt
1544 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1545 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001546#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001547 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1548 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001549#else
1550 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1551#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001552 switch (n)
1553 {
1554 case 0:
1555 ++frm;
1556 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001557 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001558 frm_nxt = frm;
1559 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001560 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001561 frm_nxt = frm;
1562 return partial;
1563 default:
1564 frm += n;
1565 break;
1566 }
1567 }
1568 frm_nxt = frm;
1569 return frm_nxt == frm_end ? ok : partial;
1570 }
1571 if (n == 0)
1572 return error;
1573 to_nxt += n;
1574 if (to_nxt == to_end)
1575 break;
1576 if (fend != frm_end) // set up next null terminated sequence
1577 {
1578 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001579#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001580 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1581#else
1582 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1583#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001584 if (n != 0) // on error
1585 return error;
1586 ++to_nxt;
1587 ++frm_nxt;
1588 // look for next null in frm
1589 for (fend = frm_nxt; fend != frm_end; ++fend)
1590 if (*fend == 0)
1591 break;
1592 }
1593 }
1594 return frm_nxt == frm_end ? ok : partial;
1595}
1596
1597codecvt<wchar_t, char, mbstate_t>::result
1598codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1599 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1600{
1601 to_nxt = to;
1602 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001603#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001604 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1605#else
1606 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1607#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001608 if (n == size_t(-1) || n == 0) // on error
1609 return error;
1610 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001611 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001612 return partial;
1613 for (extern_type* p = tmp; n; --n) // write it
1614 *to_nxt++ = *p++;
1615 return ok;
1616}
1617
1618int
Howard Hinnantc9834542011-05-31 15:34:58 +00001619codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001620{
Howard Hinnant866569b2011-09-28 23:39:33 +00001621#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001622 if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001623#else
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001624 if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001625#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001626 {
1627 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001628#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001629 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1630#else
1631 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1632#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001633 return 1; // which take more than 1 char to form a wchar_t
1634 return 0;
1635 }
1636 return -1;
1637}
1638
1639bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001640codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001641{
1642 return false;
1643}
1644
1645int
1646codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1647 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1648{
1649 int nbytes = 0;
1650 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1651 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001652#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001653 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001654#else
1655 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1656#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001657 switch (n)
1658 {
1659 case 0:
1660 ++nbytes;
1661 ++frm;
1662 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001663 case size_t(-1):
1664 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001665 return nbytes;
1666 default:
1667 nbytes += n;
1668 frm += n;
1669 break;
1670 }
1671 }
1672 return nbytes;
1673}
1674
1675int
Howard Hinnantc9834542011-05-31 15:34:58 +00001676codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001677{
Howard Hinnant866569b2011-09-28 23:39:33 +00001678#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001679 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001680#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001681 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001682#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001683}
1684
1685// Valid UTF ranges
1686// UTF-32 UTF-16 UTF-8 # of code points
1687// first second first second third fourth
1688// 000000 - 00007F 0000 - 007F 00 - 7F 127
1689// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1690// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1691// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1692// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1693// 00D800 - 00DFFF invalid
1694// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1695// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1696// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1697// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1698
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001699static
1700codecvt_base::result
1701utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1702 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1703 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1704{
1705 frm_nxt = frm;
1706 to_nxt = to;
1707 if (mode & generate_header)
1708 {
1709 if (to_end-to_nxt < 3)
1710 return codecvt_base::partial;
1711 *to_nxt++ = static_cast<uint8_t>(0xEF);
1712 *to_nxt++ = static_cast<uint8_t>(0xBB);
1713 *to_nxt++ = static_cast<uint8_t>(0xBF);
1714 }
1715 for (; frm_nxt < frm_end; ++frm_nxt)
1716 {
1717 uint16_t wc1 = *frm_nxt;
1718 if (wc1 > Maxcode)
1719 return codecvt_base::error;
1720 if (wc1 < 0x0080)
1721 {
1722 if (to_end-to_nxt < 1)
1723 return codecvt_base::partial;
1724 *to_nxt++ = static_cast<uint8_t>(wc1);
1725 }
1726 else if (wc1 < 0x0800)
1727 {
1728 if (to_end-to_nxt < 2)
1729 return codecvt_base::partial;
1730 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1731 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1732 }
1733 else if (wc1 < 0xD800)
1734 {
1735 if (to_end-to_nxt < 3)
1736 return codecvt_base::partial;
1737 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1738 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1739 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1740 }
1741 else if (wc1 < 0xDC00)
1742 {
1743 if (frm_end-frm_nxt < 2)
1744 return codecvt_base::partial;
1745 uint16_t wc2 = frm_nxt[1];
1746 if ((wc2 & 0xFC00) != 0xDC00)
1747 return codecvt_base::error;
1748 if (to_end-to_nxt < 4)
1749 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001750 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1751 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001752 return codecvt_base::error;
1753 ++frm_nxt;
1754 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1755 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1756 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1757 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1758 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1759 }
1760 else if (wc1 < 0xE000)
1761 {
1762 return codecvt_base::error;
1763 }
1764 else
1765 {
1766 if (to_end-to_nxt < 3)
1767 return codecvt_base::partial;
1768 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1769 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1770 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1771 }
1772 }
1773 return codecvt_base::ok;
1774}
1775
1776static
1777codecvt_base::result
1778utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1779 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1780 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1781{
1782 frm_nxt = frm;
1783 to_nxt = to;
1784 if (mode & generate_header)
1785 {
1786 if (to_end-to_nxt < 3)
1787 return codecvt_base::partial;
1788 *to_nxt++ = static_cast<uint8_t>(0xEF);
1789 *to_nxt++ = static_cast<uint8_t>(0xBB);
1790 *to_nxt++ = static_cast<uint8_t>(0xBF);
1791 }
1792 for (; frm_nxt < frm_end; ++frm_nxt)
1793 {
1794 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1795 if (wc1 > Maxcode)
1796 return codecvt_base::error;
1797 if (wc1 < 0x0080)
1798 {
1799 if (to_end-to_nxt < 1)
1800 return codecvt_base::partial;
1801 *to_nxt++ = static_cast<uint8_t>(wc1);
1802 }
1803 else if (wc1 < 0x0800)
1804 {
1805 if (to_end-to_nxt < 2)
1806 return codecvt_base::partial;
1807 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1808 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1809 }
1810 else if (wc1 < 0xD800)
1811 {
1812 if (to_end-to_nxt < 3)
1813 return codecvt_base::partial;
1814 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1815 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1816 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1817 }
1818 else if (wc1 < 0xDC00)
1819 {
1820 if (frm_end-frm_nxt < 2)
1821 return codecvt_base::partial;
1822 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1823 if ((wc2 & 0xFC00) != 0xDC00)
1824 return codecvt_base::error;
1825 if (to_end-to_nxt < 4)
1826 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001827 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1828 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001829 return codecvt_base::error;
1830 ++frm_nxt;
1831 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1832 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1833 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1834 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1835 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1836 }
1837 else if (wc1 < 0xE000)
1838 {
1839 return codecvt_base::error;
1840 }
1841 else
1842 {
1843 if (to_end-to_nxt < 3)
1844 return codecvt_base::partial;
1845 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1846 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1847 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1848 }
1849 }
1850 return codecvt_base::ok;
1851}
1852
1853static
1854codecvt_base::result
1855utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1856 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1857 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1858{
1859 frm_nxt = frm;
1860 to_nxt = to;
1861 if (mode & consume_header)
1862 {
1863 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1864 frm_nxt[2] == 0xBF)
1865 frm_nxt += 3;
1866 }
1867 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1868 {
1869 uint8_t c1 = *frm_nxt;
1870 if (c1 > Maxcode)
1871 return codecvt_base::error;
1872 if (c1 < 0x80)
1873 {
1874 *to_nxt = static_cast<uint16_t>(c1);
1875 ++frm_nxt;
1876 }
1877 else if (c1 < 0xC2)
1878 {
1879 return codecvt_base::error;
1880 }
1881 else if (c1 < 0xE0)
1882 {
1883 if (frm_end-frm_nxt < 2)
1884 return codecvt_base::partial;
1885 uint8_t c2 = frm_nxt[1];
1886 if ((c2 & 0xC0) != 0x80)
1887 return codecvt_base::error;
1888 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1889 if (t > Maxcode)
1890 return codecvt_base::error;
1891 *to_nxt = t;
1892 frm_nxt += 2;
1893 }
1894 else if (c1 < 0xF0)
1895 {
1896 if (frm_end-frm_nxt < 3)
1897 return codecvt_base::partial;
1898 uint8_t c2 = frm_nxt[1];
1899 uint8_t c3 = frm_nxt[2];
1900 switch (c1)
1901 {
1902 case 0xE0:
1903 if ((c2 & 0xE0) != 0xA0)
1904 return codecvt_base::error;
1905 break;
1906 case 0xED:
1907 if ((c2 & 0xE0) != 0x80)
1908 return codecvt_base::error;
1909 break;
1910 default:
1911 if ((c2 & 0xC0) != 0x80)
1912 return codecvt_base::error;
1913 break;
1914 }
1915 if ((c3 & 0xC0) != 0x80)
1916 return codecvt_base::error;
1917 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1918 | ((c2 & 0x3F) << 6)
1919 | (c3 & 0x3F));
1920 if (t > Maxcode)
1921 return codecvt_base::error;
1922 *to_nxt = t;
1923 frm_nxt += 3;
1924 }
1925 else if (c1 < 0xF5)
1926 {
1927 if (frm_end-frm_nxt < 4)
1928 return codecvt_base::partial;
1929 uint8_t c2 = frm_nxt[1];
1930 uint8_t c3 = frm_nxt[2];
1931 uint8_t c4 = frm_nxt[3];
1932 switch (c1)
1933 {
1934 case 0xF0:
1935 if (!(0x90 <= c2 && c2 <= 0xBF))
1936 return codecvt_base::error;
1937 break;
1938 case 0xF4:
1939 if ((c2 & 0xF0) != 0x80)
1940 return codecvt_base::error;
1941 break;
1942 default:
1943 if ((c2 & 0xC0) != 0x80)
1944 return codecvt_base::error;
1945 break;
1946 }
1947 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1948 return codecvt_base::error;
1949 if (to_end-to_nxt < 2)
1950 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001951 if ((((c1 & 7UL) << 18) +
1952 ((c2 & 0x3FUL) << 12) +
1953 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001954 return codecvt_base::error;
1955 *to_nxt = static_cast<uint16_t>(
1956 0xD800
1957 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1958 | ((c2 & 0x0F) << 2)
1959 | ((c3 & 0x30) >> 4));
1960 *++to_nxt = static_cast<uint16_t>(
1961 0xDC00
1962 | ((c3 & 0x0F) << 6)
1963 | (c4 & 0x3F));
1964 frm_nxt += 4;
1965 }
1966 else
1967 {
1968 return codecvt_base::error;
1969 }
1970 }
1971 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1972}
1973
1974static
1975codecvt_base::result
1976utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1977 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1978 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1979{
1980 frm_nxt = frm;
1981 to_nxt = to;
1982 if (mode & consume_header)
1983 {
1984 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1985 frm_nxt[2] == 0xBF)
1986 frm_nxt += 3;
1987 }
1988 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1989 {
1990 uint8_t c1 = *frm_nxt;
1991 if (c1 > Maxcode)
1992 return codecvt_base::error;
1993 if (c1 < 0x80)
1994 {
1995 *to_nxt = static_cast<uint32_t>(c1);
1996 ++frm_nxt;
1997 }
1998 else if (c1 < 0xC2)
1999 {
2000 return codecvt_base::error;
2001 }
2002 else if (c1 < 0xE0)
2003 {
2004 if (frm_end-frm_nxt < 2)
2005 return codecvt_base::partial;
2006 uint8_t c2 = frm_nxt[1];
2007 if ((c2 & 0xC0) != 0x80)
2008 return codecvt_base::error;
2009 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2010 if (t > Maxcode)
2011 return codecvt_base::error;
2012 *to_nxt = static_cast<uint32_t>(t);
2013 frm_nxt += 2;
2014 }
2015 else if (c1 < 0xF0)
2016 {
2017 if (frm_end-frm_nxt < 3)
2018 return codecvt_base::partial;
2019 uint8_t c2 = frm_nxt[1];
2020 uint8_t c3 = frm_nxt[2];
2021 switch (c1)
2022 {
2023 case 0xE0:
2024 if ((c2 & 0xE0) != 0xA0)
2025 return codecvt_base::error;
2026 break;
2027 case 0xED:
2028 if ((c2 & 0xE0) != 0x80)
2029 return codecvt_base::error;
2030 break;
2031 default:
2032 if ((c2 & 0xC0) != 0x80)
2033 return codecvt_base::error;
2034 break;
2035 }
2036 if ((c3 & 0xC0) != 0x80)
2037 return codecvt_base::error;
2038 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2039 | ((c2 & 0x3F) << 6)
2040 | (c3 & 0x3F));
2041 if (t > Maxcode)
2042 return codecvt_base::error;
2043 *to_nxt = static_cast<uint32_t>(t);
2044 frm_nxt += 3;
2045 }
2046 else if (c1 < 0xF5)
2047 {
2048 if (frm_end-frm_nxt < 4)
2049 return codecvt_base::partial;
2050 uint8_t c2 = frm_nxt[1];
2051 uint8_t c3 = frm_nxt[2];
2052 uint8_t c4 = frm_nxt[3];
2053 switch (c1)
2054 {
2055 case 0xF0:
2056 if (!(0x90 <= c2 && c2 <= 0xBF))
2057 return codecvt_base::error;
2058 break;
2059 case 0xF4:
2060 if ((c2 & 0xF0) != 0x80)
2061 return codecvt_base::error;
2062 break;
2063 default:
2064 if ((c2 & 0xC0) != 0x80)
2065 return codecvt_base::error;
2066 break;
2067 }
2068 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2069 return codecvt_base::error;
2070 if (to_end-to_nxt < 2)
2071 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002072 if ((((c1 & 7UL) << 18) +
2073 ((c2 & 0x3FUL) << 12) +
2074 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002075 return codecvt_base::error;
2076 *to_nxt = static_cast<uint32_t>(
2077 0xD800
2078 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2079 | ((c2 & 0x0F) << 2)
2080 | ((c3 & 0x30) >> 4));
2081 *++to_nxt = static_cast<uint32_t>(
2082 0xDC00
2083 | ((c3 & 0x0F) << 6)
2084 | (c4 & 0x3F));
2085 frm_nxt += 4;
2086 }
2087 else
2088 {
2089 return codecvt_base::error;
2090 }
2091 }
2092 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2093}
2094
2095static
2096int
2097utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2098 size_t mx, unsigned long Maxcode = 0x10FFFF,
2099 codecvt_mode mode = codecvt_mode(0))
2100{
2101 const uint8_t* frm_nxt = frm;
2102 if (mode & consume_header)
2103 {
2104 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2105 frm_nxt[2] == 0xBF)
2106 frm_nxt += 3;
2107 }
2108 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2109 {
2110 uint8_t c1 = *frm_nxt;
2111 if (c1 > Maxcode)
2112 break;
2113 if (c1 < 0x80)
2114 {
2115 ++frm_nxt;
2116 }
2117 else if (c1 < 0xC2)
2118 {
2119 break;
2120 }
2121 else if (c1 < 0xE0)
2122 {
2123 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2124 break;
2125 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2126 if (t > Maxcode)
2127 break;
2128 frm_nxt += 2;
2129 }
2130 else if (c1 < 0xF0)
2131 {
2132 if (frm_end-frm_nxt < 3)
2133 break;
2134 uint8_t c2 = frm_nxt[1];
2135 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002136 switch (c1)
2137 {
2138 case 0xE0:
2139 if ((c2 & 0xE0) != 0xA0)
2140 return static_cast<int>(frm_nxt - frm);
2141 break;
2142 case 0xED:
2143 if ((c2 & 0xE0) != 0x80)
2144 return static_cast<int>(frm_nxt - frm);
2145 break;
2146 default:
2147 if ((c2 & 0xC0) != 0x80)
2148 return static_cast<int>(frm_nxt - frm);
2149 break;
2150 }
2151 if ((c3 & 0xC0) != 0x80)
2152 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002153 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002154 break;
2155 frm_nxt += 3;
2156 }
2157 else if (c1 < 0xF5)
2158 {
2159 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2160 break;
2161 uint8_t c2 = frm_nxt[1];
2162 uint8_t c3 = frm_nxt[2];
2163 uint8_t c4 = frm_nxt[3];
2164 switch (c1)
2165 {
2166 case 0xF0:
2167 if (!(0x90 <= c2 && c2 <= 0xBF))
2168 return static_cast<int>(frm_nxt - frm);
2169 break;
2170 case 0xF4:
2171 if ((c2 & 0xF0) != 0x80)
2172 return static_cast<int>(frm_nxt - frm);
2173 break;
2174 default:
2175 if ((c2 & 0xC0) != 0x80)
2176 return static_cast<int>(frm_nxt - frm);
2177 break;
2178 }
2179 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2180 break;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002181 if ((((c1 & 7UL) << 18) +
2182 ((c2 & 0x3FUL) << 12) +
2183 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002184 break;
2185 ++nchar16_t;
2186 frm_nxt += 4;
2187 }
2188 else
2189 {
2190 break;
2191 }
2192 }
2193 return static_cast<int>(frm_nxt - frm);
2194}
2195
2196static
2197codecvt_base::result
2198ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2199 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2200 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2201{
2202 frm_nxt = frm;
2203 to_nxt = to;
2204 if (mode & generate_header)
2205 {
2206 if (to_end-to_nxt < 3)
2207 return codecvt_base::partial;
2208 *to_nxt++ = static_cast<uint8_t>(0xEF);
2209 *to_nxt++ = static_cast<uint8_t>(0xBB);
2210 *to_nxt++ = static_cast<uint8_t>(0xBF);
2211 }
2212 for (; frm_nxt < frm_end; ++frm_nxt)
2213 {
2214 uint32_t wc = *frm_nxt;
2215 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2216 return codecvt_base::error;
2217 if (wc < 0x000080)
2218 {
2219 if (to_end-to_nxt < 1)
2220 return codecvt_base::partial;
2221 *to_nxt++ = static_cast<uint8_t>(wc);
2222 }
2223 else if (wc < 0x000800)
2224 {
2225 if (to_end-to_nxt < 2)
2226 return codecvt_base::partial;
2227 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2228 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2229 }
2230 else if (wc < 0x010000)
2231 {
2232 if (to_end-to_nxt < 3)
2233 return codecvt_base::partial;
2234 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2235 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2236 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2237 }
2238 else // if (wc < 0x110000)
2239 {
2240 if (to_end-to_nxt < 4)
2241 return codecvt_base::partial;
2242 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2243 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2244 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2245 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2246 }
2247 }
2248 return codecvt_base::ok;
2249}
2250
2251static
2252codecvt_base::result
2253utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2254 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2255 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2256{
2257 frm_nxt = frm;
2258 to_nxt = to;
2259 if (mode & consume_header)
2260 {
2261 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2262 frm_nxt[2] == 0xBF)
2263 frm_nxt += 3;
2264 }
2265 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2266 {
2267 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2268 if (c1 < 0x80)
2269 {
2270 if (c1 > Maxcode)
2271 return codecvt_base::error;
2272 *to_nxt = static_cast<uint32_t>(c1);
2273 ++frm_nxt;
2274 }
2275 else if (c1 < 0xC2)
2276 {
2277 return codecvt_base::error;
2278 }
2279 else if (c1 < 0xE0)
2280 {
2281 if (frm_end-frm_nxt < 2)
2282 return codecvt_base::partial;
2283 uint8_t c2 = frm_nxt[1];
2284 if ((c2 & 0xC0) != 0x80)
2285 return codecvt_base::error;
2286 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2287 | (c2 & 0x3F));
2288 if (t > Maxcode)
2289 return codecvt_base::error;
2290 *to_nxt = t;
2291 frm_nxt += 2;
2292 }
2293 else if (c1 < 0xF0)
2294 {
2295 if (frm_end-frm_nxt < 3)
2296 return codecvt_base::partial;
2297 uint8_t c2 = frm_nxt[1];
2298 uint8_t c3 = frm_nxt[2];
2299 switch (c1)
2300 {
2301 case 0xE0:
2302 if ((c2 & 0xE0) != 0xA0)
2303 return codecvt_base::error;
2304 break;
2305 case 0xED:
2306 if ((c2 & 0xE0) != 0x80)
2307 return codecvt_base::error;
2308 break;
2309 default:
2310 if ((c2 & 0xC0) != 0x80)
2311 return codecvt_base::error;
2312 break;
2313 }
2314 if ((c3 & 0xC0) != 0x80)
2315 return codecvt_base::error;
2316 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2317 | ((c2 & 0x3F) << 6)
2318 | (c3 & 0x3F));
2319 if (t > Maxcode)
2320 return codecvt_base::error;
2321 *to_nxt = t;
2322 frm_nxt += 3;
2323 }
2324 else if (c1 < 0xF5)
2325 {
2326 if (frm_end-frm_nxt < 4)
2327 return codecvt_base::partial;
2328 uint8_t c2 = frm_nxt[1];
2329 uint8_t c3 = frm_nxt[2];
2330 uint8_t c4 = frm_nxt[3];
2331 switch (c1)
2332 {
2333 case 0xF0:
2334 if (!(0x90 <= c2 && c2 <= 0xBF))
2335 return codecvt_base::error;
2336 break;
2337 case 0xF4:
2338 if ((c2 & 0xF0) != 0x80)
2339 return codecvt_base::error;
2340 break;
2341 default:
2342 if ((c2 & 0xC0) != 0x80)
2343 return codecvt_base::error;
2344 break;
2345 }
2346 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2347 return codecvt_base::error;
2348 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2349 | ((c2 & 0x3F) << 12)
2350 | ((c3 & 0x3F) << 6)
2351 | (c4 & 0x3F));
2352 if (t > Maxcode)
2353 return codecvt_base::error;
2354 *to_nxt = t;
2355 frm_nxt += 4;
2356 }
2357 else
2358 {
2359 return codecvt_base::error;
2360 }
2361 }
2362 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2363}
2364
2365static
2366int
2367utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2368 size_t mx, unsigned long Maxcode = 0x10FFFF,
2369 codecvt_mode mode = codecvt_mode(0))
2370{
2371 const uint8_t* frm_nxt = frm;
2372 if (mode & consume_header)
2373 {
2374 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2375 frm_nxt[2] == 0xBF)
2376 frm_nxt += 3;
2377 }
2378 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2379 {
2380 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2381 if (c1 < 0x80)
2382 {
2383 if (c1 > Maxcode)
2384 break;
2385 ++frm_nxt;
2386 }
2387 else if (c1 < 0xC2)
2388 {
2389 break;
2390 }
2391 else if (c1 < 0xE0)
2392 {
2393 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2394 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002395 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002396 break;
2397 frm_nxt += 2;
2398 }
2399 else if (c1 < 0xF0)
2400 {
2401 if (frm_end-frm_nxt < 3)
2402 break;
2403 uint8_t c2 = frm_nxt[1];
2404 uint8_t c3 = frm_nxt[2];
2405 switch (c1)
2406 {
2407 case 0xE0:
2408 if ((c2 & 0xE0) != 0xA0)
2409 return static_cast<int>(frm_nxt - frm);
2410 break;
2411 case 0xED:
2412 if ((c2 & 0xE0) != 0x80)
2413 return static_cast<int>(frm_nxt - frm);
2414 break;
2415 default:
2416 if ((c2 & 0xC0) != 0x80)
2417 return static_cast<int>(frm_nxt - frm);
2418 break;
2419 }
2420 if ((c3 & 0xC0) != 0x80)
2421 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002422 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002423 break;
2424 frm_nxt += 3;
2425 }
2426 else if (c1 < 0xF5)
2427 {
2428 if (frm_end-frm_nxt < 4)
2429 break;
2430 uint8_t c2 = frm_nxt[1];
2431 uint8_t c3 = frm_nxt[2];
2432 uint8_t c4 = frm_nxt[3];
2433 switch (c1)
2434 {
2435 case 0xF0:
2436 if (!(0x90 <= c2 && c2 <= 0xBF))
2437 return static_cast<int>(frm_nxt - frm);
2438 break;
2439 case 0xF4:
2440 if ((c2 & 0xF0) != 0x80)
2441 return static_cast<int>(frm_nxt - frm);
2442 break;
2443 default:
2444 if ((c2 & 0xC0) != 0x80)
2445 return static_cast<int>(frm_nxt - frm);
2446 break;
2447 }
2448 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2449 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002450 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2451 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002452 break;
2453 frm_nxt += 4;
2454 }
2455 else
2456 {
2457 break;
2458 }
2459 }
2460 return static_cast<int>(frm_nxt - frm);
2461}
2462
2463static
2464codecvt_base::result
2465ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2466 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2467 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2468{
2469 frm_nxt = frm;
2470 to_nxt = to;
2471 if (mode & generate_header)
2472 {
2473 if (to_end-to_nxt < 3)
2474 return codecvt_base::partial;
2475 *to_nxt++ = static_cast<uint8_t>(0xEF);
2476 *to_nxt++ = static_cast<uint8_t>(0xBB);
2477 *to_nxt++ = static_cast<uint8_t>(0xBF);
2478 }
2479 for (; frm_nxt < frm_end; ++frm_nxt)
2480 {
2481 uint16_t wc = *frm_nxt;
2482 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2483 return codecvt_base::error;
2484 if (wc < 0x0080)
2485 {
2486 if (to_end-to_nxt < 1)
2487 return codecvt_base::partial;
2488 *to_nxt++ = static_cast<uint8_t>(wc);
2489 }
2490 else if (wc < 0x0800)
2491 {
2492 if (to_end-to_nxt < 2)
2493 return codecvt_base::partial;
2494 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2495 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2496 }
2497 else // if (wc <= 0xFFFF)
2498 {
2499 if (to_end-to_nxt < 3)
2500 return codecvt_base::partial;
2501 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2502 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2503 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2504 }
2505 }
2506 return codecvt_base::ok;
2507}
2508
2509static
2510codecvt_base::result
2511utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2512 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2513 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2514{
2515 frm_nxt = frm;
2516 to_nxt = to;
2517 if (mode & consume_header)
2518 {
2519 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2520 frm_nxt[2] == 0xBF)
2521 frm_nxt += 3;
2522 }
2523 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2524 {
2525 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2526 if (c1 < 0x80)
2527 {
2528 if (c1 > Maxcode)
2529 return codecvt_base::error;
2530 *to_nxt = static_cast<uint16_t>(c1);
2531 ++frm_nxt;
2532 }
2533 else if (c1 < 0xC2)
2534 {
2535 return codecvt_base::error;
2536 }
2537 else if (c1 < 0xE0)
2538 {
2539 if (frm_end-frm_nxt < 2)
2540 return codecvt_base::partial;
2541 uint8_t c2 = frm_nxt[1];
2542 if ((c2 & 0xC0) != 0x80)
2543 return codecvt_base::error;
2544 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2545 | (c2 & 0x3F));
2546 if (t > Maxcode)
2547 return codecvt_base::error;
2548 *to_nxt = t;
2549 frm_nxt += 2;
2550 }
2551 else if (c1 < 0xF0)
2552 {
2553 if (frm_end-frm_nxt < 3)
2554 return codecvt_base::partial;
2555 uint8_t c2 = frm_nxt[1];
2556 uint8_t c3 = frm_nxt[2];
2557 switch (c1)
2558 {
2559 case 0xE0:
2560 if ((c2 & 0xE0) != 0xA0)
2561 return codecvt_base::error;
2562 break;
2563 case 0xED:
2564 if ((c2 & 0xE0) != 0x80)
2565 return codecvt_base::error;
2566 break;
2567 default:
2568 if ((c2 & 0xC0) != 0x80)
2569 return codecvt_base::error;
2570 break;
2571 }
2572 if ((c3 & 0xC0) != 0x80)
2573 return codecvt_base::error;
2574 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2575 | ((c2 & 0x3F) << 6)
2576 | (c3 & 0x3F));
2577 if (t > Maxcode)
2578 return codecvt_base::error;
2579 *to_nxt = t;
2580 frm_nxt += 3;
2581 }
2582 else
2583 {
2584 return codecvt_base::error;
2585 }
2586 }
2587 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2588}
2589
2590static
2591int
2592utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2593 size_t mx, unsigned long Maxcode = 0x10FFFF,
2594 codecvt_mode mode = codecvt_mode(0))
2595{
2596 const uint8_t* frm_nxt = frm;
2597 if (mode & consume_header)
2598 {
2599 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2600 frm_nxt[2] == 0xBF)
2601 frm_nxt += 3;
2602 }
2603 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2604 {
2605 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2606 if (c1 < 0x80)
2607 {
2608 if (c1 > Maxcode)
2609 break;
2610 ++frm_nxt;
2611 }
2612 else if (c1 < 0xC2)
2613 {
2614 break;
2615 }
2616 else if (c1 < 0xE0)
2617 {
2618 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2619 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002620 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002621 break;
2622 frm_nxt += 2;
2623 }
2624 else if (c1 < 0xF0)
2625 {
2626 if (frm_end-frm_nxt < 3)
2627 break;
2628 uint8_t c2 = frm_nxt[1];
2629 uint8_t c3 = frm_nxt[2];
2630 switch (c1)
2631 {
2632 case 0xE0:
2633 if ((c2 & 0xE0) != 0xA0)
2634 return static_cast<int>(frm_nxt - frm);
2635 break;
2636 case 0xED:
2637 if ((c2 & 0xE0) != 0x80)
2638 return static_cast<int>(frm_nxt - frm);
2639 break;
2640 default:
2641 if ((c2 & 0xC0) != 0x80)
2642 return static_cast<int>(frm_nxt - frm);
2643 break;
2644 }
2645 if ((c3 & 0xC0) != 0x80)
2646 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002647 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002648 break;
2649 frm_nxt += 3;
2650 }
2651 else
2652 {
2653 break;
2654 }
2655 }
2656 return static_cast<int>(frm_nxt - frm);
2657}
2658
2659static
2660codecvt_base::result
2661ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2662 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2663 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2664{
2665 frm_nxt = frm;
2666 to_nxt = to;
2667 if (mode & generate_header)
2668 {
2669 if (to_end-to_nxt < 2)
2670 return codecvt_base::partial;
2671 *to_nxt++ = static_cast<uint8_t>(0xFE);
2672 *to_nxt++ = static_cast<uint8_t>(0xFF);
2673 }
2674 for (; frm_nxt < frm_end; ++frm_nxt)
2675 {
2676 uint32_t wc = *frm_nxt;
2677 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2678 return codecvt_base::error;
2679 if (wc < 0x010000)
2680 {
2681 if (to_end-to_nxt < 2)
2682 return codecvt_base::partial;
2683 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2684 *to_nxt++ = static_cast<uint8_t>(wc);
2685 }
2686 else
2687 {
2688 if (to_end-to_nxt < 4)
2689 return codecvt_base::partial;
2690 uint16_t t = static_cast<uint16_t>(
2691 0xD800
2692 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2693 | ((wc & 0x00FC00) >> 10));
2694 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2695 *to_nxt++ = static_cast<uint8_t>(t);
2696 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2697 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2698 *to_nxt++ = static_cast<uint8_t>(t);
2699 }
2700 }
2701 return codecvt_base::ok;
2702}
2703
2704static
2705codecvt_base::result
2706utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2707 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2708 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2709{
2710 frm_nxt = frm;
2711 to_nxt = to;
2712 if (mode & consume_header)
2713 {
2714 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2715 frm_nxt += 2;
2716 }
2717 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2718 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002719 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002720 if ((c1 & 0xFC00) == 0xDC00)
2721 return codecvt_base::error;
2722 if ((c1 & 0xFC00) != 0xD800)
2723 {
2724 if (c1 > Maxcode)
2725 return codecvt_base::error;
2726 *to_nxt = static_cast<uint32_t>(c1);
2727 frm_nxt += 2;
2728 }
2729 else
2730 {
2731 if (frm_end-frm_nxt < 4)
2732 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002733 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002734 if ((c2 & 0xFC00) != 0xDC00)
2735 return codecvt_base::error;
2736 uint32_t t = static_cast<uint32_t>(
2737 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2738 | ((c1 & 0x003F) << 10)
2739 | (c2 & 0x03FF));
2740 if (t > Maxcode)
2741 return codecvt_base::error;
2742 *to_nxt = t;
2743 frm_nxt += 4;
2744 }
2745 }
2746 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2747}
2748
2749static
2750int
2751utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2752 size_t mx, unsigned long Maxcode = 0x10FFFF,
2753 codecvt_mode mode = codecvt_mode(0))
2754{
2755 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002756 if (mode & consume_header)
2757 {
2758 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2759 frm_nxt += 2;
2760 }
2761 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2762 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002763 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002764 if ((c1 & 0xFC00) == 0xDC00)
2765 break;
2766 if ((c1 & 0xFC00) != 0xD800)
2767 {
2768 if (c1 > Maxcode)
2769 break;
2770 frm_nxt += 2;
2771 }
2772 else
2773 {
2774 if (frm_end-frm_nxt < 4)
2775 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002776 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002777 if ((c2 & 0xFC00) != 0xDC00)
2778 break;
2779 uint32_t t = static_cast<uint32_t>(
2780 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2781 | ((c1 & 0x003F) << 10)
2782 | (c2 & 0x03FF));
2783 if (t > Maxcode)
2784 break;
2785 frm_nxt += 4;
2786 }
2787 }
2788 return static_cast<int>(frm_nxt - frm);
2789}
2790
2791static
2792codecvt_base::result
2793ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2794 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2795 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2796{
2797 frm_nxt = frm;
2798 to_nxt = to;
2799 if (mode & generate_header)
2800 {
2801 if (to_end-to_nxt < 2)
2802 return codecvt_base::partial;
2803 *to_nxt++ = static_cast<uint8_t>(0xFF);
2804 *to_nxt++ = static_cast<uint8_t>(0xFE);
2805 }
2806 for (; frm_nxt < frm_end; ++frm_nxt)
2807 {
2808 uint32_t wc = *frm_nxt;
2809 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2810 return codecvt_base::error;
2811 if (wc < 0x010000)
2812 {
2813 if (to_end-to_nxt < 2)
2814 return codecvt_base::partial;
2815 *to_nxt++ = static_cast<uint8_t>(wc);
2816 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2817 }
2818 else
2819 {
2820 if (to_end-to_nxt < 4)
2821 return codecvt_base::partial;
2822 uint16_t t = static_cast<uint16_t>(
2823 0xD800
2824 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2825 | ((wc & 0x00FC00) >> 10));
2826 *to_nxt++ = static_cast<uint8_t>(t);
2827 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2828 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2829 *to_nxt++ = static_cast<uint8_t>(t);
2830 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2831 }
2832 }
2833 return codecvt_base::ok;
2834}
2835
2836static
2837codecvt_base::result
2838utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2839 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2840 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2841{
2842 frm_nxt = frm;
2843 to_nxt = to;
2844 if (mode & consume_header)
2845 {
2846 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2847 frm_nxt += 2;
2848 }
2849 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2850 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002851 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002852 if ((c1 & 0xFC00) == 0xDC00)
2853 return codecvt_base::error;
2854 if ((c1 & 0xFC00) != 0xD800)
2855 {
2856 if (c1 > Maxcode)
2857 return codecvt_base::error;
2858 *to_nxt = static_cast<uint32_t>(c1);
2859 frm_nxt += 2;
2860 }
2861 else
2862 {
2863 if (frm_end-frm_nxt < 4)
2864 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002865 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002866 if ((c2 & 0xFC00) != 0xDC00)
2867 return codecvt_base::error;
2868 uint32_t t = static_cast<uint32_t>(
2869 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2870 | ((c1 & 0x003F) << 10)
2871 | (c2 & 0x03FF));
2872 if (t > Maxcode)
2873 return codecvt_base::error;
2874 *to_nxt = t;
2875 frm_nxt += 4;
2876 }
2877 }
2878 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2879}
2880
2881static
2882int
2883utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2884 size_t mx, unsigned long Maxcode = 0x10FFFF,
2885 codecvt_mode mode = codecvt_mode(0))
2886{
2887 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002888 if (mode & consume_header)
2889 {
2890 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2891 frm_nxt += 2;
2892 }
2893 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2894 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002895 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002896 if ((c1 & 0xFC00) == 0xDC00)
2897 break;
2898 if ((c1 & 0xFC00) != 0xD800)
2899 {
2900 if (c1 > Maxcode)
2901 break;
2902 frm_nxt += 2;
2903 }
2904 else
2905 {
2906 if (frm_end-frm_nxt < 4)
2907 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002908 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002909 if ((c2 & 0xFC00) != 0xDC00)
2910 break;
2911 uint32_t t = static_cast<uint32_t>(
2912 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2913 | ((c1 & 0x003F) << 10)
2914 | (c2 & 0x03FF));
2915 if (t > Maxcode)
2916 break;
2917 frm_nxt += 4;
2918 }
2919 }
2920 return static_cast<int>(frm_nxt - frm);
2921}
2922
2923static
2924codecvt_base::result
2925ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2926 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2927 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2928{
2929 frm_nxt = frm;
2930 to_nxt = to;
2931 if (mode & generate_header)
2932 {
2933 if (to_end-to_nxt < 2)
2934 return codecvt_base::partial;
2935 *to_nxt++ = static_cast<uint8_t>(0xFE);
2936 *to_nxt++ = static_cast<uint8_t>(0xFF);
2937 }
2938 for (; frm_nxt < frm_end; ++frm_nxt)
2939 {
2940 uint16_t wc = *frm_nxt;
2941 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2942 return codecvt_base::error;
2943 if (to_end-to_nxt < 2)
2944 return codecvt_base::partial;
2945 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2946 *to_nxt++ = static_cast<uint8_t>(wc);
2947 }
2948 return codecvt_base::ok;
2949}
2950
2951static
2952codecvt_base::result
2953utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2954 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2955 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2956{
2957 frm_nxt = frm;
2958 to_nxt = to;
2959 if (mode & consume_header)
2960 {
2961 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2962 frm_nxt += 2;
2963 }
2964 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2965 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002966 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002967 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2968 return codecvt_base::error;
2969 *to_nxt = c1;
2970 frm_nxt += 2;
2971 }
2972 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2973}
2974
2975static
2976int
2977utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2978 size_t mx, unsigned long Maxcode = 0x10FFFF,
2979 codecvt_mode mode = codecvt_mode(0))
2980{
2981 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002982 if (mode & consume_header)
2983 {
2984 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2985 frm_nxt += 2;
2986 }
2987 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2988 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002989 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002990 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2991 break;
2992 frm_nxt += 2;
2993 }
2994 return static_cast<int>(frm_nxt - frm);
2995}
2996
2997static
2998codecvt_base::result
2999ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3000 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3001 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3002{
3003 frm_nxt = frm;
3004 to_nxt = to;
3005 if (mode & generate_header)
3006 {
3007 if (to_end-to_nxt < 2)
3008 return codecvt_base::partial;
3009 *to_nxt++ = static_cast<uint8_t>(0xFF);
3010 *to_nxt++ = static_cast<uint8_t>(0xFE);
3011 }
3012 for (; frm_nxt < frm_end; ++frm_nxt)
3013 {
3014 uint16_t wc = *frm_nxt;
3015 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3016 return codecvt_base::error;
3017 if (to_end-to_nxt < 2)
3018 return codecvt_base::partial;
3019 *to_nxt++ = static_cast<uint8_t>(wc);
3020 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3021 }
3022 return codecvt_base::ok;
3023}
3024
3025static
3026codecvt_base::result
3027utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3028 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3029 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3030{
3031 frm_nxt = frm;
3032 to_nxt = to;
3033 if (mode & consume_header)
3034 {
3035 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3036 frm_nxt += 2;
3037 }
3038 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3039 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003040 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003041 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3042 return codecvt_base::error;
3043 *to_nxt = c1;
3044 frm_nxt += 2;
3045 }
3046 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3047}
3048
3049static
3050int
3051utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3052 size_t mx, unsigned long Maxcode = 0x10FFFF,
3053 codecvt_mode mode = codecvt_mode(0))
3054{
3055 const uint8_t* frm_nxt = frm;
3056 frm_nxt = frm;
3057 if (mode & consume_header)
3058 {
3059 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3060 frm_nxt += 2;
3061 }
3062 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3063 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003064 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003065 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3066 break;
3067 frm_nxt += 2;
3068 }
3069 return static_cast<int>(frm_nxt - frm);
3070}
3071
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003072// template <> class codecvt<char16_t, char, mbstate_t>
3073
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003074locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003075
3076codecvt<char16_t, char, mbstate_t>::~codecvt()
3077{
3078}
3079
3080codecvt<char16_t, char, mbstate_t>::result
3081codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003082 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003083 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3084{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003085 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3086 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3087 const uint16_t* _frm_nxt = _frm;
3088 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3089 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3090 uint8_t* _to_nxt = _to;
3091 result r = utf16_to_utf8(_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_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003099 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003100 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3101{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003102 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3103 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3104 const uint8_t* _frm_nxt = _frm;
3105 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3106 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3107 uint16_t* _to_nxt = _to;
3108 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3109 frm_nxt = frm + (_frm_nxt - _frm);
3110 to_nxt = to + (_to_nxt - _to);
3111 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003112}
3113
3114codecvt<char16_t, char, mbstate_t>::result
3115codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3116 extern_type* to, extern_type*, extern_type*& to_nxt) const
3117{
3118 to_nxt = to;
3119 return noconv;
3120}
3121
3122int
Howard Hinnantc9834542011-05-31 15:34:58 +00003123codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003124{
3125 return 0;
3126}
3127
3128bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003129codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003130{
3131 return false;
3132}
3133
3134int
3135codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3136 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3137{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003138 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3139 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3140 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003141}
3142
3143int
Howard Hinnantc9834542011-05-31 15:34:58 +00003144codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003145{
3146 return 4;
3147}
3148
3149// template <> class codecvt<char32_t, char, mbstate_t>
3150
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003151locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003152
3153codecvt<char32_t, char, mbstate_t>::~codecvt()
3154{
3155}
3156
3157codecvt<char32_t, char, mbstate_t>::result
3158codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003159 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003160 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3161{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003162 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3163 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3164 const uint32_t* _frm_nxt = _frm;
3165 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3166 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3167 uint8_t* _to_nxt = _to;
3168 result r = ucs4_to_utf8(_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_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003176 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003177 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3178{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003179 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3180 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3181 const uint8_t* _frm_nxt = _frm;
3182 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3183 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3184 uint32_t* _to_nxt = _to;
3185 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3186 frm_nxt = frm + (_frm_nxt - _frm);
3187 to_nxt = to + (_to_nxt - _to);
3188 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003189}
3190
3191codecvt<char32_t, char, mbstate_t>::result
3192codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3193 extern_type* to, extern_type*, extern_type*& to_nxt) const
3194{
3195 to_nxt = to;
3196 return noconv;
3197}
3198
3199int
Howard Hinnantc9834542011-05-31 15:34:58 +00003200codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003201{
3202 return 0;
3203}
3204
3205bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003206codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003207{
3208 return false;
3209}
3210
3211int
3212codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3213 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3214{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003215 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3216 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3217 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003218}
3219
3220int
Howard Hinnantc9834542011-05-31 15:34:58 +00003221codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003222{
3223 return 4;
3224}
3225
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003226// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003227
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003228__codecvt_utf8<wchar_t>::result
3229__codecvt_utf8<wchar_t>::do_out(state_type&,
3230 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003231 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3232{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003233#if _WIN32
3234 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3235 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3236 const uint16_t* _frm_nxt = _frm;
3237#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003238 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3239 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3240 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003241#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003242 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3243 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3244 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003245#if _WIN32
3246 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3247 _Maxcode_, _Mode_);
3248#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003249 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3250 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003251#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003252 frm_nxt = frm + (_frm_nxt - _frm);
3253 to_nxt = to + (_to_nxt - _to);
3254 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003255}
3256
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003257__codecvt_utf8<wchar_t>::result
3258__codecvt_utf8<wchar_t>::do_in(state_type&,
3259 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003260 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3261{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003262 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3263 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3264 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003265#if _WIN32
3266 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3267 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3268 uint16_t* _to_nxt = _to;
3269 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3270 _Maxcode_, _Mode_);
3271#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003272 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3273 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3274 uint32_t* _to_nxt = _to;
3275 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3276 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003277#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003278 frm_nxt = frm + (_frm_nxt - _frm);
3279 to_nxt = to + (_to_nxt - _to);
3280 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003281}
3282
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003283__codecvt_utf8<wchar_t>::result
3284__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003285 extern_type* to, extern_type*, extern_type*& to_nxt) const
3286{
3287 to_nxt = to;
3288 return noconv;
3289}
3290
3291int
Howard Hinnantc9834542011-05-31 15:34:58 +00003292__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003293{
3294 return 0;
3295}
3296
3297bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003298__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003299{
3300 return false;
3301}
3302
3303int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003304__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003305 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3306{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003307 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3308 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3309 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003310}
3311
3312int
Howard Hinnantc9834542011-05-31 15:34:58 +00003313__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003314{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003315 if (_Mode_ & consume_header)
3316 return 7;
3317 return 4;
3318}
3319
3320// __codecvt_utf8<char16_t>
3321
3322__codecvt_utf8<char16_t>::result
3323__codecvt_utf8<char16_t>::do_out(state_type&,
3324 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3325 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3326{
3327 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3328 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3329 const uint16_t* _frm_nxt = _frm;
3330 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3331 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3332 uint8_t* _to_nxt = _to;
3333 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3334 _Maxcode_, _Mode_);
3335 frm_nxt = frm + (_frm_nxt - _frm);
3336 to_nxt = to + (_to_nxt - _to);
3337 return r;
3338}
3339
3340__codecvt_utf8<char16_t>::result
3341__codecvt_utf8<char16_t>::do_in(state_type&,
3342 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3343 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3344{
3345 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3346 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3347 const uint8_t* _frm_nxt = _frm;
3348 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3349 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3350 uint16_t* _to_nxt = _to;
3351 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3352 _Maxcode_, _Mode_);
3353 frm_nxt = frm + (_frm_nxt - _frm);
3354 to_nxt = to + (_to_nxt - _to);
3355 return r;
3356}
3357
3358__codecvt_utf8<char16_t>::result
3359__codecvt_utf8<char16_t>::do_unshift(state_type&,
3360 extern_type* to, extern_type*, extern_type*& to_nxt) const
3361{
3362 to_nxt = to;
3363 return noconv;
3364}
3365
3366int
Howard Hinnantc9834542011-05-31 15:34:58 +00003367__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003368{
3369 return 0;
3370}
3371
3372bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003373__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003374{
3375 return false;
3376}
3377
3378int
3379__codecvt_utf8<char16_t>::do_length(state_type&,
3380 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3381{
3382 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3383 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3384 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3385}
3386
3387int
Howard Hinnantc9834542011-05-31 15:34:58 +00003388__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003389{
3390 if (_Mode_ & consume_header)
3391 return 6;
3392 return 3;
3393}
3394
3395// __codecvt_utf8<char32_t>
3396
3397__codecvt_utf8<char32_t>::result
3398__codecvt_utf8<char32_t>::do_out(state_type&,
3399 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3400 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3401{
3402 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3403 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3404 const uint32_t* _frm_nxt = _frm;
3405 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3406 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3407 uint8_t* _to_nxt = _to;
3408 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3409 _Maxcode_, _Mode_);
3410 frm_nxt = frm + (_frm_nxt - _frm);
3411 to_nxt = to + (_to_nxt - _to);
3412 return r;
3413}
3414
3415__codecvt_utf8<char32_t>::result
3416__codecvt_utf8<char32_t>::do_in(state_type&,
3417 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3418 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3419{
3420 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3421 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3422 const uint8_t* _frm_nxt = _frm;
3423 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3424 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3425 uint32_t* _to_nxt = _to;
3426 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3427 _Maxcode_, _Mode_);
3428 frm_nxt = frm + (_frm_nxt - _frm);
3429 to_nxt = to + (_to_nxt - _to);
3430 return r;
3431}
3432
3433__codecvt_utf8<char32_t>::result
3434__codecvt_utf8<char32_t>::do_unshift(state_type&,
3435 extern_type* to, extern_type*, extern_type*& to_nxt) const
3436{
3437 to_nxt = to;
3438 return noconv;
3439}
3440
3441int
Howard Hinnantc9834542011-05-31 15:34:58 +00003442__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003443{
3444 return 0;
3445}
3446
3447bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003448__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003449{
3450 return false;
3451}
3452
3453int
3454__codecvt_utf8<char32_t>::do_length(state_type&,
3455 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3456{
3457 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3458 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3459 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3460}
3461
3462int
Howard Hinnantc9834542011-05-31 15:34:58 +00003463__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003464{
3465 if (_Mode_ & consume_header)
3466 return 7;
3467 return 4;
3468}
3469
3470// __codecvt_utf16<wchar_t, false>
3471
3472__codecvt_utf16<wchar_t, false>::result
3473__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3474 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3475 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3476{
3477 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3478 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3479 const uint32_t* _frm_nxt = _frm;
3480 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3481 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3482 uint8_t* _to_nxt = _to;
3483 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3484 _Maxcode_, _Mode_);
3485 frm_nxt = frm + (_frm_nxt - _frm);
3486 to_nxt = to + (_to_nxt - _to);
3487 return r;
3488}
3489
3490__codecvt_utf16<wchar_t, false>::result
3491__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3492 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3493 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3494{
3495 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3496 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3497 const uint8_t* _frm_nxt = _frm;
3498 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3499 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3500 uint32_t* _to_nxt = _to;
3501 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3502 _Maxcode_, _Mode_);
3503 frm_nxt = frm + (_frm_nxt - _frm);
3504 to_nxt = to + (_to_nxt - _to);
3505 return r;
3506}
3507
3508__codecvt_utf16<wchar_t, false>::result
3509__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3510 extern_type* to, extern_type*, extern_type*& to_nxt) const
3511{
3512 to_nxt = to;
3513 return noconv;
3514}
3515
3516int
Howard Hinnantc9834542011-05-31 15:34:58 +00003517__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003518{
3519 return 0;
3520}
3521
3522bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003523__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003524{
3525 return false;
3526}
3527
3528int
3529__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3530 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3531{
3532 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3533 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3534 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3535}
3536
3537int
Howard Hinnantc9834542011-05-31 15:34:58 +00003538__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003539{
3540 if (_Mode_ & consume_header)
3541 return 6;
3542 return 4;
3543}
3544
3545// __codecvt_utf16<wchar_t, true>
3546
3547__codecvt_utf16<wchar_t, true>::result
3548__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3549 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3550 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3551{
3552 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3553 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3554 const uint32_t* _frm_nxt = _frm;
3555 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3556 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3557 uint8_t* _to_nxt = _to;
3558 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3559 _Maxcode_, _Mode_);
3560 frm_nxt = frm + (_frm_nxt - _frm);
3561 to_nxt = to + (_to_nxt - _to);
3562 return r;
3563}
3564
3565__codecvt_utf16<wchar_t, true>::result
3566__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3567 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3568 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3569{
3570 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3571 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3572 const uint8_t* _frm_nxt = _frm;
3573 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3574 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3575 uint32_t* _to_nxt = _to;
3576 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3577 _Maxcode_, _Mode_);
3578 frm_nxt = frm + (_frm_nxt - _frm);
3579 to_nxt = to + (_to_nxt - _to);
3580 return r;
3581}
3582
3583__codecvt_utf16<wchar_t, true>::result
3584__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3585 extern_type* to, extern_type*, extern_type*& to_nxt) const
3586{
3587 to_nxt = to;
3588 return noconv;
3589}
3590
3591int
Howard Hinnantc9834542011-05-31 15:34:58 +00003592__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003593{
3594 return 0;
3595}
3596
3597bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003598__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003599{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003600 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003601}
3602
3603int
3604__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3605 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3606{
3607 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3608 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3609 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3610}
3611
3612int
Howard Hinnantc9834542011-05-31 15:34:58 +00003613__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003614{
3615 if (_Mode_ & consume_header)
3616 return 6;
3617 return 4;
3618}
3619
3620// __codecvt_utf16<char16_t, false>
3621
3622__codecvt_utf16<char16_t, false>::result
3623__codecvt_utf16<char16_t, false>::do_out(state_type&,
3624 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3625 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3626{
3627 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3628 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3629 const uint16_t* _frm_nxt = _frm;
3630 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3631 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3632 uint8_t* _to_nxt = _to;
3633 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3634 _Maxcode_, _Mode_);
3635 frm_nxt = frm + (_frm_nxt - _frm);
3636 to_nxt = to + (_to_nxt - _to);
3637 return r;
3638}
3639
3640__codecvt_utf16<char16_t, false>::result
3641__codecvt_utf16<char16_t, false>::do_in(state_type&,
3642 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3643 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3644{
3645 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3646 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3647 const uint8_t* _frm_nxt = _frm;
3648 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3649 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3650 uint16_t* _to_nxt = _to;
3651 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3652 _Maxcode_, _Mode_);
3653 frm_nxt = frm + (_frm_nxt - _frm);
3654 to_nxt = to + (_to_nxt - _to);
3655 return r;
3656}
3657
3658__codecvt_utf16<char16_t, false>::result
3659__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3660 extern_type* to, extern_type*, extern_type*& to_nxt) const
3661{
3662 to_nxt = to;
3663 return noconv;
3664}
3665
3666int
Howard Hinnantc9834542011-05-31 15:34:58 +00003667__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003668{
3669 return 0;
3670}
3671
3672bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003673__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003674{
3675 return false;
3676}
3677
3678int
3679__codecvt_utf16<char16_t, false>::do_length(state_type&,
3680 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3681{
3682 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3683 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3684 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3685}
3686
3687int
Howard Hinnantc9834542011-05-31 15:34:58 +00003688__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003689{
3690 if (_Mode_ & consume_header)
3691 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003692 return 2;
3693}
3694
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003695// __codecvt_utf16<char16_t, true>
3696
3697__codecvt_utf16<char16_t, true>::result
3698__codecvt_utf16<char16_t, true>::do_out(state_type&,
3699 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3700 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3701{
3702 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3703 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3704 const uint16_t* _frm_nxt = _frm;
3705 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3706 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3707 uint8_t* _to_nxt = _to;
3708 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3709 _Maxcode_, _Mode_);
3710 frm_nxt = frm + (_frm_nxt - _frm);
3711 to_nxt = to + (_to_nxt - _to);
3712 return r;
3713}
3714
3715__codecvt_utf16<char16_t, true>::result
3716__codecvt_utf16<char16_t, true>::do_in(state_type&,
3717 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3718 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3719{
3720 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3721 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3722 const uint8_t* _frm_nxt = _frm;
3723 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3724 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3725 uint16_t* _to_nxt = _to;
3726 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3727 _Maxcode_, _Mode_);
3728 frm_nxt = frm + (_frm_nxt - _frm);
3729 to_nxt = to + (_to_nxt - _to);
3730 return r;
3731}
3732
3733__codecvt_utf16<char16_t, true>::result
3734__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3735 extern_type* to, extern_type*, extern_type*& to_nxt) const
3736{
3737 to_nxt = to;
3738 return noconv;
3739}
3740
3741int
Howard Hinnantc9834542011-05-31 15:34:58 +00003742__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003743{
3744 return 0;
3745}
3746
3747bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003748__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003749{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003750 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003751}
3752
3753int
3754__codecvt_utf16<char16_t, true>::do_length(state_type&,
3755 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3756{
3757 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3758 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3759 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3760}
3761
3762int
Howard Hinnantc9834542011-05-31 15:34:58 +00003763__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003764{
3765 if (_Mode_ & consume_header)
3766 return 4;
3767 return 2;
3768}
3769
3770// __codecvt_utf16<char32_t, false>
3771
3772__codecvt_utf16<char32_t, false>::result
3773__codecvt_utf16<char32_t, false>::do_out(state_type&,
3774 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3775 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3776{
3777 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3778 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3779 const uint32_t* _frm_nxt = _frm;
3780 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3781 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3782 uint8_t* _to_nxt = _to;
3783 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3784 _Maxcode_, _Mode_);
3785 frm_nxt = frm + (_frm_nxt - _frm);
3786 to_nxt = to + (_to_nxt - _to);
3787 return r;
3788}
3789
3790__codecvt_utf16<char32_t, false>::result
3791__codecvt_utf16<char32_t, false>::do_in(state_type&,
3792 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3793 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3794{
3795 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3796 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3797 const uint8_t* _frm_nxt = _frm;
3798 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3799 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3800 uint32_t* _to_nxt = _to;
3801 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3802 _Maxcode_, _Mode_);
3803 frm_nxt = frm + (_frm_nxt - _frm);
3804 to_nxt = to + (_to_nxt - _to);
3805 return r;
3806}
3807
3808__codecvt_utf16<char32_t, false>::result
3809__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3810 extern_type* to, extern_type*, extern_type*& to_nxt) const
3811{
3812 to_nxt = to;
3813 return noconv;
3814}
3815
3816int
Howard Hinnantc9834542011-05-31 15:34:58 +00003817__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003818{
3819 return 0;
3820}
3821
3822bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003823__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003824{
3825 return false;
3826}
3827
3828int
3829__codecvt_utf16<char32_t, false>::do_length(state_type&,
3830 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3831{
3832 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3833 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3834 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3835}
3836
3837int
Howard Hinnantc9834542011-05-31 15:34:58 +00003838__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003839{
3840 if (_Mode_ & consume_header)
3841 return 6;
3842 return 4;
3843}
3844
3845// __codecvt_utf16<char32_t, true>
3846
3847__codecvt_utf16<char32_t, true>::result
3848__codecvt_utf16<char32_t, true>::do_out(state_type&,
3849 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3850 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3851{
3852 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3853 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3854 const uint32_t* _frm_nxt = _frm;
3855 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3856 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3857 uint8_t* _to_nxt = _to;
3858 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3859 _Maxcode_, _Mode_);
3860 frm_nxt = frm + (_frm_nxt - _frm);
3861 to_nxt = to + (_to_nxt - _to);
3862 return r;
3863}
3864
3865__codecvt_utf16<char32_t, true>::result
3866__codecvt_utf16<char32_t, true>::do_in(state_type&,
3867 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3868 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3869{
3870 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3871 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3872 const uint8_t* _frm_nxt = _frm;
3873 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3874 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3875 uint32_t* _to_nxt = _to;
3876 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3877 _Maxcode_, _Mode_);
3878 frm_nxt = frm + (_frm_nxt - _frm);
3879 to_nxt = to + (_to_nxt - _to);
3880 return r;
3881}
3882
3883__codecvt_utf16<char32_t, true>::result
3884__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3885 extern_type* to, extern_type*, extern_type*& to_nxt) const
3886{
3887 to_nxt = to;
3888 return noconv;
3889}
3890
3891int
Howard Hinnantc9834542011-05-31 15:34:58 +00003892__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003893{
3894 return 0;
3895}
3896
3897bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003898__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003899{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003900 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003901}
3902
3903int
3904__codecvt_utf16<char32_t, true>::do_length(state_type&,
3905 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3906{
3907 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3908 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3909 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3910}
3911
3912int
Howard Hinnantc9834542011-05-31 15:34:58 +00003913__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003914{
3915 if (_Mode_ & consume_header)
3916 return 6;
3917 return 4;
3918}
3919
3920// __codecvt_utf8_utf16<wchar_t>
3921
3922__codecvt_utf8_utf16<wchar_t>::result
3923__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3924 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3925 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3926{
3927 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3928 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3929 const uint32_t* _frm_nxt = _frm;
3930 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3931 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3932 uint8_t* _to_nxt = _to;
3933 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3934 _Maxcode_, _Mode_);
3935 frm_nxt = frm + (_frm_nxt - _frm);
3936 to_nxt = to + (_to_nxt - _to);
3937 return r;
3938}
3939
3940__codecvt_utf8_utf16<wchar_t>::result
3941__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3942 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3943 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3944{
3945 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3946 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3947 const uint8_t* _frm_nxt = _frm;
3948 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3949 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3950 uint32_t* _to_nxt = _to;
3951 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3952 _Maxcode_, _Mode_);
3953 frm_nxt = frm + (_frm_nxt - _frm);
3954 to_nxt = to + (_to_nxt - _to);
3955 return r;
3956}
3957
3958__codecvt_utf8_utf16<wchar_t>::result
3959__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3960 extern_type* to, extern_type*, extern_type*& to_nxt) const
3961{
3962 to_nxt = to;
3963 return noconv;
3964}
3965
3966int
Howard Hinnantc9834542011-05-31 15:34:58 +00003967__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003968{
3969 return 0;
3970}
3971
3972bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003973__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003974{
3975 return false;
3976}
3977
3978int
3979__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3980 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3981{
3982 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3983 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3984 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3985}
3986
3987int
Howard Hinnantc9834542011-05-31 15:34:58 +00003988__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003989{
3990 if (_Mode_ & consume_header)
3991 return 7;
3992 return 4;
3993}
3994
3995// __codecvt_utf8_utf16<char16_t>
3996
3997__codecvt_utf8_utf16<char16_t>::result
3998__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3999 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4000 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4001{
4002 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4003 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4004 const uint16_t* _frm_nxt = _frm;
4005 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4006 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4007 uint8_t* _to_nxt = _to;
4008 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4009 _Maxcode_, _Mode_);
4010 frm_nxt = frm + (_frm_nxt - _frm);
4011 to_nxt = to + (_to_nxt - _to);
4012 return r;
4013}
4014
4015__codecvt_utf8_utf16<char16_t>::result
4016__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4017 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4018 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4019{
4020 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4021 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4022 const uint8_t* _frm_nxt = _frm;
4023 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4024 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4025 uint16_t* _to_nxt = _to;
4026 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4027 _Maxcode_, _Mode_);
4028 frm_nxt = frm + (_frm_nxt - _frm);
4029 to_nxt = to + (_to_nxt - _to);
4030 return r;
4031}
4032
4033__codecvt_utf8_utf16<char16_t>::result
4034__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4035 extern_type* to, extern_type*, extern_type*& to_nxt) const
4036{
4037 to_nxt = to;
4038 return noconv;
4039}
4040
4041int
Howard Hinnantc9834542011-05-31 15:34:58 +00004042__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004043{
4044 return 0;
4045}
4046
4047bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004048__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004049{
4050 return false;
4051}
4052
4053int
4054__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4055 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4056{
4057 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4058 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4059 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4060}
4061
4062int
Howard Hinnantc9834542011-05-31 15:34:58 +00004063__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004064{
4065 if (_Mode_ & consume_header)
4066 return 7;
4067 return 4;
4068}
4069
4070// __codecvt_utf8_utf16<char32_t>
4071
4072__codecvt_utf8_utf16<char32_t>::result
4073__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4074 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4075 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4076{
4077 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4078 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4079 const uint32_t* _frm_nxt = _frm;
4080 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4081 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4082 uint8_t* _to_nxt = _to;
4083 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4084 _Maxcode_, _Mode_);
4085 frm_nxt = frm + (_frm_nxt - _frm);
4086 to_nxt = to + (_to_nxt - _to);
4087 return r;
4088}
4089
4090__codecvt_utf8_utf16<char32_t>::result
4091__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4092 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4093 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4094{
4095 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4096 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4097 const uint8_t* _frm_nxt = _frm;
4098 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4099 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4100 uint32_t* _to_nxt = _to;
4101 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4102 _Maxcode_, _Mode_);
4103 frm_nxt = frm + (_frm_nxt - _frm);
4104 to_nxt = to + (_to_nxt - _to);
4105 return r;
4106}
4107
4108__codecvt_utf8_utf16<char32_t>::result
4109__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4110 extern_type* to, extern_type*, extern_type*& to_nxt) const
4111{
4112 to_nxt = to;
4113 return noconv;
4114}
4115
4116int
Howard Hinnantc9834542011-05-31 15:34:58 +00004117__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004118{
4119 return 0;
4120}
4121
4122bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004123__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004124{
4125 return false;
4126}
4127
4128int
4129__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4130 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4131{
4132 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4133 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4134 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4135}
4136
4137int
Howard Hinnantc9834542011-05-31 15:34:58 +00004138__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004139{
4140 if (_Mode_ & consume_header)
4141 return 7;
4142 return 4;
4143}
4144
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004145// __narrow_to_utf8<16>
4146
4147__narrow_to_utf8<16>::~__narrow_to_utf8()
4148{
4149}
4150
4151// __narrow_to_utf8<32>
4152
4153__narrow_to_utf8<32>::~__narrow_to_utf8()
4154{
4155}
4156
4157// __widen_from_utf8<16>
4158
4159__widen_from_utf8<16>::~__widen_from_utf8()
4160{
4161}
4162
4163// __widen_from_utf8<32>
4164
4165__widen_from_utf8<32>::~__widen_from_utf8()
4166{
4167}
4168
4169// numpunct<char> && numpunct<wchar_t>
4170
4171locale::id numpunct< char >::id;
4172locale::id numpunct<wchar_t>::id;
4173
4174numpunct<char>::numpunct(size_t refs)
4175 : locale::facet(refs),
4176 __decimal_point_('.'),
4177 __thousands_sep_(',')
4178{
4179}
4180
4181numpunct<wchar_t>::numpunct(size_t refs)
4182 : locale::facet(refs),
4183 __decimal_point_(L'.'),
4184 __thousands_sep_(L',')
4185{
4186}
4187
4188numpunct<char>::~numpunct()
4189{
4190}
4191
4192numpunct<wchar_t>::~numpunct()
4193{
4194}
4195
4196 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4197wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4198
4199 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4200wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4201
4202string numpunct< char >::do_grouping() const {return __grouping_;}
4203string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4204
4205 string numpunct< char >::do_truename() const {return "true";}
4206wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4207
4208 string numpunct< char >::do_falsename() const {return "false";}
4209wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4210
4211// numpunct_byname<char>
4212
4213numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4214 : numpunct<char>(refs)
4215{
4216 __init(nm);
4217}
4218
4219numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4220 : numpunct<char>(refs)
4221{
4222 __init(nm.c_str());
4223}
4224
4225numpunct_byname<char>::~numpunct_byname()
4226{
4227}
4228
4229void
4230numpunct_byname<char>::__init(const char* nm)
4231{
4232 if (strcmp(nm, "C") != 0)
4233 {
Sean Huntf3907e62011-07-15 05:40:33 +00004234 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004235#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004236 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004237 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4238 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004239#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004240#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004241 lconv* lc = localeconv_l(loc.get());
4242#else
4243 lconv* lc = __localeconv_l(loc.get());
4244#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004245 if (*lc->decimal_point)
4246 __decimal_point_ = *lc->decimal_point;
4247 if (*lc->thousands_sep)
4248 __thousands_sep_ = *lc->thousands_sep;
4249 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004250 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004251 }
4252}
4253
4254// numpunct_byname<wchar_t>
4255
4256numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4257 : numpunct<wchar_t>(refs)
4258{
4259 __init(nm);
4260}
4261
4262numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4263 : numpunct<wchar_t>(refs)
4264{
4265 __init(nm.c_str());
4266}
4267
4268numpunct_byname<wchar_t>::~numpunct_byname()
4269{
4270}
4271
4272void
4273numpunct_byname<wchar_t>::__init(const char* nm)
4274{
4275 if (strcmp(nm, "C") != 0)
4276 {
Sean Huntf3907e62011-07-15 05:40:33 +00004277 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004278#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004279 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004280 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4281 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004282#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004283#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004284 lconv* lc = localeconv_l(loc.get());
4285#else
4286 lconv* lc = __localeconv_l(loc.get());
4287#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004288 if (*lc->decimal_point)
4289 __decimal_point_ = *lc->decimal_point;
4290 if (*lc->thousands_sep)
4291 __thousands_sep_ = *lc->thousands_sep;
4292 __grouping_ = lc->grouping;
4293 // locallization for truename and falsename is not available
4294 }
4295}
4296
4297// num_get helpers
4298
4299int
4300__num_get_base::__get_base(ios_base& iob)
4301{
4302 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4303 if (__basefield == ios_base::oct)
4304 return 8;
4305 else if (__basefield == ios_base::hex)
4306 return 16;
4307 else if (__basefield == 0)
4308 return 0;
4309 return 10;
4310}
4311
4312const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4313
4314void
4315__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4316 ios_base::iostate& __err)
4317{
4318 if (__grouping.size() != 0)
4319 {
4320 reverse(__g, __g_end);
4321 const char* __ig = __grouping.data();
4322 const char* __eg = __ig + __grouping.size();
4323 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4324 {
4325 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4326 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004327 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004328 {
4329 __err = ios_base::failbit;
4330 return;
4331 }
4332 }
4333 if (__eg - __ig > 1)
4334 ++__ig;
4335 }
4336 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4337 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004338 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004339 __err = ios_base::failbit;
4340 }
4341 }
4342}
4343
4344void
4345__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4346 ios_base::fmtflags __flags)
4347{
4348 if (__flags & ios_base::showpos)
4349 *__fmtp++ = '+';
4350 if (__flags & ios_base::showbase)
4351 *__fmtp++ = '#';
4352 while(*__len)
4353 *__fmtp++ = *__len++;
4354 if ((__flags & ios_base::basefield) == ios_base::oct)
4355 *__fmtp = 'o';
4356 else if ((__flags & ios_base::basefield) == ios_base::hex)
4357 {
4358 if (__flags & ios_base::uppercase)
4359 *__fmtp = 'X';
4360 else
4361 *__fmtp = 'x';
4362 }
4363 else if (__signd)
4364 *__fmtp = 'd';
4365 else
4366 *__fmtp = 'u';
4367}
4368
4369bool
4370__num_put_base::__format_float(char* __fmtp, const char* __len,
4371 ios_base::fmtflags __flags)
4372{
4373 bool specify_precision = true;
4374 if (__flags & ios_base::showpos)
4375 *__fmtp++ = '+';
4376 if (__flags & ios_base::showpoint)
4377 *__fmtp++ = '#';
4378 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowa3645132013-10-21 15:07:28 +00004379 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004380 if (floatfield == (ios_base::fixed | ios_base::scientific))
4381 specify_precision = false;
4382 else
4383 {
4384 *__fmtp++ = '.';
4385 *__fmtp++ = '*';
4386 }
4387 while(*__len)
4388 *__fmtp++ = *__len++;
4389 if (floatfield == ios_base::fixed)
4390 {
4391 if (uppercase)
4392 *__fmtp = 'F';
4393 else
4394 *__fmtp = 'f';
4395 }
4396 else if (floatfield == ios_base::scientific)
4397 {
4398 if (uppercase)
4399 *__fmtp = 'E';
4400 else
4401 *__fmtp = 'e';
4402 }
4403 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4404 {
4405 if (uppercase)
4406 *__fmtp = 'A';
4407 else
4408 *__fmtp = 'a';
4409 }
4410 else
4411 {
4412 if (uppercase)
4413 *__fmtp = 'G';
4414 else
4415 *__fmtp = 'g';
4416 }
4417 return specify_precision;
4418}
4419
4420char*
4421__num_put_base::__identify_padding(char* __nb, char* __ne,
4422 const ios_base& __iob)
4423{
4424 switch (__iob.flags() & ios_base::adjustfield)
4425 {
4426 case ios_base::internal:
4427 if (__nb[0] == '-' || __nb[0] == '+')
4428 return __nb+1;
4429 if (__ne - __nb >= 2 && __nb[0] == '0'
4430 && (__nb[1] == 'x' || __nb[1] == 'X'))
4431 return __nb+2;
4432 break;
4433 case ios_base::left:
4434 return __ne;
4435 case ios_base::right:
4436 default:
4437 break;
4438 }
4439 return __nb;
4440}
4441
4442// time_get
4443
4444static
4445string*
4446init_weeks()
4447{
4448 static string weeks[14];
4449 weeks[0] = "Sunday";
4450 weeks[1] = "Monday";
4451 weeks[2] = "Tuesday";
4452 weeks[3] = "Wednesday";
4453 weeks[4] = "Thursday";
4454 weeks[5] = "Friday";
4455 weeks[6] = "Saturday";
4456 weeks[7] = "Sun";
4457 weeks[8] = "Mon";
4458 weeks[9] = "Tue";
4459 weeks[10] = "Wed";
4460 weeks[11] = "Thu";
4461 weeks[12] = "Fri";
4462 weeks[13] = "Sat";
4463 return weeks;
4464}
4465
4466static
4467wstring*
4468init_wweeks()
4469{
4470 static wstring weeks[14];
4471 weeks[0] = L"Sunday";
4472 weeks[1] = L"Monday";
4473 weeks[2] = L"Tuesday";
4474 weeks[3] = L"Wednesday";
4475 weeks[4] = L"Thursday";
4476 weeks[5] = L"Friday";
4477 weeks[6] = L"Saturday";
4478 weeks[7] = L"Sun";
4479 weeks[8] = L"Mon";
4480 weeks[9] = L"Tue";
4481 weeks[10] = L"Wed";
4482 weeks[11] = L"Thu";
4483 weeks[12] = L"Fri";
4484 weeks[13] = L"Sat";
4485 return weeks;
4486}
4487
4488template <>
4489const string*
4490__time_get_c_storage<char>::__weeks() const
4491{
4492 static const string* weeks = init_weeks();
4493 return weeks;
4494}
4495
4496template <>
4497const wstring*
4498__time_get_c_storage<wchar_t>::__weeks() const
4499{
4500 static const wstring* weeks = init_wweeks();
4501 return weeks;
4502}
4503
4504static
4505string*
4506init_months()
4507{
4508 static string months[24];
4509 months[0] = "January";
4510 months[1] = "February";
4511 months[2] = "March";
4512 months[3] = "April";
4513 months[4] = "May";
4514 months[5] = "June";
4515 months[6] = "July";
4516 months[7] = "August";
4517 months[8] = "September";
4518 months[9] = "October";
4519 months[10] = "November";
4520 months[11] = "December";
4521 months[12] = "Jan";
4522 months[13] = "Feb";
4523 months[14] = "Mar";
4524 months[15] = "Apr";
4525 months[16] = "May";
4526 months[17] = "Jun";
4527 months[18] = "Jul";
4528 months[19] = "Aug";
4529 months[20] = "Sep";
4530 months[21] = "Oct";
4531 months[22] = "Nov";
4532 months[23] = "Dec";
4533 return months;
4534}
4535
4536static
4537wstring*
4538init_wmonths()
4539{
4540 static wstring months[24];
4541 months[0] = L"January";
4542 months[1] = L"February";
4543 months[2] = L"March";
4544 months[3] = L"April";
4545 months[4] = L"May";
4546 months[5] = L"June";
4547 months[6] = L"July";
4548 months[7] = L"August";
4549 months[8] = L"September";
4550 months[9] = L"October";
4551 months[10] = L"November";
4552 months[11] = L"December";
4553 months[12] = L"Jan";
4554 months[13] = L"Feb";
4555 months[14] = L"Mar";
4556 months[15] = L"Apr";
4557 months[16] = L"May";
4558 months[17] = L"Jun";
4559 months[18] = L"Jul";
4560 months[19] = L"Aug";
4561 months[20] = L"Sep";
4562 months[21] = L"Oct";
4563 months[22] = L"Nov";
4564 months[23] = L"Dec";
4565 return months;
4566}
4567
4568template <>
4569const string*
4570__time_get_c_storage<char>::__months() const
4571{
4572 static const string* months = init_months();
4573 return months;
4574}
4575
4576template <>
4577const wstring*
4578__time_get_c_storage<wchar_t>::__months() const
4579{
4580 static const wstring* months = init_wmonths();
4581 return months;
4582}
4583
4584static
4585string*
4586init_am_pm()
4587{
4588 static string am_pm[24];
4589 am_pm[0] = "AM";
4590 am_pm[1] = "PM";
4591 return am_pm;
4592}
4593
4594static
4595wstring*
4596init_wam_pm()
4597{
4598 static wstring am_pm[24];
4599 am_pm[0] = L"AM";
4600 am_pm[1] = L"PM";
4601 return am_pm;
4602}
4603
4604template <>
4605const string*
4606__time_get_c_storage<char>::__am_pm() const
4607{
4608 static const string* am_pm = init_am_pm();
4609 return am_pm;
4610}
4611
4612template <>
4613const wstring*
4614__time_get_c_storage<wchar_t>::__am_pm() const
4615{
4616 static const wstring* am_pm = init_wam_pm();
4617 return am_pm;
4618}
4619
4620template <>
4621const string&
4622__time_get_c_storage<char>::__x() const
4623{
4624 static string s("%m/%d/%y");
4625 return s;
4626}
4627
4628template <>
4629const wstring&
4630__time_get_c_storage<wchar_t>::__x() const
4631{
4632 static wstring s(L"%m/%d/%y");
4633 return s;
4634}
4635
4636template <>
4637const string&
4638__time_get_c_storage<char>::__X() const
4639{
4640 static string s("%H:%M:%S");
4641 return s;
4642}
4643
4644template <>
4645const wstring&
4646__time_get_c_storage<wchar_t>::__X() const
4647{
4648 static wstring s(L"%H:%M:%S");
4649 return s;
4650}
4651
4652template <>
4653const string&
4654__time_get_c_storage<char>::__c() const
4655{
4656 static string s("%a %b %d %H:%M:%S %Y");
4657 return s;
4658}
4659
4660template <>
4661const wstring&
4662__time_get_c_storage<wchar_t>::__c() const
4663{
4664 static wstring s(L"%a %b %d %H:%M:%S %Y");
4665 return s;
4666}
4667
4668template <>
4669const string&
4670__time_get_c_storage<char>::__r() const
4671{
4672 static string s("%I:%M:%S %p");
4673 return s;
4674}
4675
4676template <>
4677const wstring&
4678__time_get_c_storage<wchar_t>::__r() const
4679{
4680 static wstring s(L"%I:%M:%S %p");
4681 return s;
4682}
4683
4684// time_get_byname
4685
4686__time_get::__time_get(const char* nm)
4687 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4688{
Howard Hinnantd4444702010-08-11 17:04:31 +00004689#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004690 if (__loc_ == 0)
4691 throw runtime_error("time_get_byname"
4692 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004693#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004694}
4695
4696__time_get::__time_get(const string& nm)
4697 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4698{
Howard Hinnantd4444702010-08-11 17:04:31 +00004699#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004700 if (__loc_ == 0)
4701 throw runtime_error("time_get_byname"
4702 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004703#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004704}
4705
4706__time_get::~__time_get()
4707{
4708 freelocale(__loc_);
4709}
Marshall Clowa3645132013-10-21 15:07:28 +00004710#if defined(__clang__)
Howard Hinnant335b1512012-02-20 16:51:43 +00004711#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004712#endif
4713#if defined(__GNUG__)
Howard Hinnant21772ec2012-12-28 18:15:01 +00004714#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004715#endif
Howard Hinnant335b1512012-02-20 16:51:43 +00004716
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004717template <>
4718string
4719__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4720{
Howard Hinnant3074a052012-02-19 14:55:32 +00004721 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004722 t.tm_sec = 59;
4723 t.tm_min = 55;
4724 t.tm_hour = 23;
4725 t.tm_mday = 31;
4726 t.tm_mon = 11;
4727 t.tm_year = 161;
4728 t.tm_wday = 6;
4729 t.tm_yday = 364;
4730 t.tm_isdst = -1;
4731 char buf[100];
4732 char f[3] = {0};
4733 f[0] = '%';
4734 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004735 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004736 char* bb = buf;
4737 char* be = buf + n;
4738 string result;
4739 while (bb != be)
4740 {
4741 if (ct.is(ctype_base::space, *bb))
4742 {
4743 result.push_back(' ');
4744 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4745 ;
4746 continue;
4747 }
4748 char* w = bb;
4749 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004750 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004751 ct, err, false)
4752 - this->__weeks_;
4753 if (i < 14)
4754 {
4755 result.push_back('%');
4756 if (i < 7)
4757 result.push_back('A');
4758 else
4759 result.push_back('a');
4760 bb = w;
4761 continue;
4762 }
4763 w = bb;
4764 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4765 ct, err, false)
4766 - this->__months_;
4767 if (i < 24)
4768 {
4769 result.push_back('%');
4770 if (i < 12)
4771 result.push_back('B');
4772 else
4773 result.push_back('b');
4774 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4775 result.back() = 'm';
4776 bb = w;
4777 continue;
4778 }
4779 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4780 {
4781 w = bb;
4782 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4783 ct, err, false) - this->__am_pm_;
4784 if (i < 2)
4785 {
4786 result.push_back('%');
4787 result.push_back('p');
4788 bb = w;
4789 continue;
4790 }
4791 }
4792 w = bb;
4793 if (ct.is(ctype_base::digit, *bb))
4794 {
4795 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4796 {
4797 case 6:
4798 result.push_back('%');
4799 result.push_back('w');
4800 break;
4801 case 7:
4802 result.push_back('%');
4803 result.push_back('u');
4804 break;
4805 case 11:
4806 result.push_back('%');
4807 result.push_back('I');
4808 break;
4809 case 12:
4810 result.push_back('%');
4811 result.push_back('m');
4812 break;
4813 case 23:
4814 result.push_back('%');
4815 result.push_back('H');
4816 break;
4817 case 31:
4818 result.push_back('%');
4819 result.push_back('d');
4820 break;
4821 case 55:
4822 result.push_back('%');
4823 result.push_back('M');
4824 break;
4825 case 59:
4826 result.push_back('%');
4827 result.push_back('S');
4828 break;
4829 case 61:
4830 result.push_back('%');
4831 result.push_back('y');
4832 break;
4833 case 364:
4834 result.push_back('%');
4835 result.push_back('j');
4836 break;
4837 case 2061:
4838 result.push_back('%');
4839 result.push_back('Y');
4840 break;
4841 default:
4842 for (; w != bb; ++w)
4843 result.push_back(*w);
4844 break;
4845 }
4846 continue;
4847 }
4848 if (*bb == '%')
4849 {
4850 result.push_back('%');
4851 result.push_back('%');
4852 ++bb;
4853 continue;
4854 }
4855 result.push_back(*bb);
4856 ++bb;
4857 }
4858 return result;
4859}
4860
Marshall Clowa3645132013-10-21 15:07:28 +00004861#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +00004862#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowa3645132013-10-21 15:07:28 +00004863#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004864
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004865template <>
4866wstring
4867__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4868{
Howard Hinnant3074a052012-02-19 14:55:32 +00004869 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004870 t.tm_sec = 59;
4871 t.tm_min = 55;
4872 t.tm_hour = 23;
4873 t.tm_mday = 31;
4874 t.tm_mon = 11;
4875 t.tm_year = 161;
4876 t.tm_wday = 6;
4877 t.tm_yday = 364;
4878 t.tm_isdst = -1;
4879 char buf[100];
4880 char f[3] = {0};
4881 f[0] = '%';
4882 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004883 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004884 wchar_t wbuf[100];
4885 wchar_t* wbb = wbuf;
4886 mbstate_t mb = {0};
4887 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004888#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004889 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004890#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004891 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004892#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004893 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004894 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004895 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004896 wstring result;
4897 while (wbb != wbe)
4898 {
4899 if (ct.is(ctype_base::space, *wbb))
4900 {
4901 result.push_back(L' ');
4902 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4903 ;
4904 continue;
4905 }
4906 wchar_t* w = wbb;
4907 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004908 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004909 ct, err, false)
4910 - this->__weeks_;
4911 if (i < 14)
4912 {
4913 result.push_back(L'%');
4914 if (i < 7)
4915 result.push_back(L'A');
4916 else
4917 result.push_back(L'a');
4918 wbb = w;
4919 continue;
4920 }
4921 w = wbb;
4922 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4923 ct, err, false)
4924 - this->__months_;
4925 if (i < 24)
4926 {
4927 result.push_back(L'%');
4928 if (i < 12)
4929 result.push_back(L'B');
4930 else
4931 result.push_back(L'b');
4932 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4933 result.back() = L'm';
4934 wbb = w;
4935 continue;
4936 }
4937 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4938 {
4939 w = wbb;
4940 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4941 ct, err, false) - this->__am_pm_;
4942 if (i < 2)
4943 {
4944 result.push_back(L'%');
4945 result.push_back(L'p');
4946 wbb = w;
4947 continue;
4948 }
4949 }
4950 w = wbb;
4951 if (ct.is(ctype_base::digit, *wbb))
4952 {
4953 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4954 {
4955 case 6:
4956 result.push_back(L'%');
4957 result.push_back(L'w');
4958 break;
4959 case 7:
4960 result.push_back(L'%');
4961 result.push_back(L'u');
4962 break;
4963 case 11:
4964 result.push_back(L'%');
4965 result.push_back(L'I');
4966 break;
4967 case 12:
4968 result.push_back(L'%');
4969 result.push_back(L'm');
4970 break;
4971 case 23:
4972 result.push_back(L'%');
4973 result.push_back(L'H');
4974 break;
4975 case 31:
4976 result.push_back(L'%');
4977 result.push_back(L'd');
4978 break;
4979 case 55:
4980 result.push_back(L'%');
4981 result.push_back(L'M');
4982 break;
4983 case 59:
4984 result.push_back(L'%');
4985 result.push_back(L'S');
4986 break;
4987 case 61:
4988 result.push_back(L'%');
4989 result.push_back(L'y');
4990 break;
4991 case 364:
4992 result.push_back(L'%');
4993 result.push_back(L'j');
4994 break;
4995 case 2061:
4996 result.push_back(L'%');
4997 result.push_back(L'Y');
4998 break;
4999 default:
5000 for (; w != wbb; ++w)
5001 result.push_back(*w);
5002 break;
5003 }
5004 continue;
5005 }
5006 if (ct.narrow(*wbb, 0) == '%')
5007 {
5008 result.push_back(L'%');
5009 result.push_back(L'%');
5010 ++wbb;
5011 continue;
5012 }
5013 result.push_back(*wbb);
5014 ++wbb;
5015 }
5016 return result;
5017}
5018
5019template <>
5020void
5021__time_get_storage<char>::init(const ctype<char>& ct)
5022{
Howard Hinnantcd992362012-08-02 18:44:17 +00005023 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005024 char buf[100];
5025 // __weeks_
5026 for (int i = 0; i < 7; ++i)
5027 {
5028 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005029 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005030 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005031 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005032 __weeks_[i+7] = buf;
5033 }
5034 // __months_
5035 for (int i = 0; i < 12; ++i)
5036 {
5037 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005038 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005039 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005040 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005041 __months_[i+12] = buf;
5042 }
5043 // __am_pm_
5044 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005045 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005046 __am_pm_[0] = buf;
5047 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005048 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005049 __am_pm_[1] = buf;
5050 __c_ = __analyze('c', ct);
5051 __r_ = __analyze('r', ct);
5052 __x_ = __analyze('x', ct);
5053 __X_ = __analyze('X', ct);
5054}
5055
5056template <>
5057void
5058__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5059{
5060 tm t = {0};
5061 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005062 wchar_t wbuf[100];
5063 wchar_t* wbe;
5064 mbstate_t mb = {0};
5065 // __weeks_
5066 for (int i = 0; i < 7; ++i)
5067 {
5068 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005069 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005070 mb = mbstate_t();
5071 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005072#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005073 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005074#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005075 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005076#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005077 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005078 __throw_runtime_error("locale not supported");
5079 wbe = wbuf + j;
5080 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005081 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005082 mb = mbstate_t();
5083 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005084#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005085 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005086#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005087 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005088#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005089 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005090 __throw_runtime_error("locale not supported");
5091 wbe = wbuf + j;
5092 __weeks_[i+7].assign(wbuf, wbe);
5093 }
5094 // __months_
5095 for (int i = 0; i < 12; ++i)
5096 {
5097 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005098 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005099 mb = mbstate_t();
5100 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005101#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005102 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005103#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005104 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005105#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005106 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005107 __throw_runtime_error("locale not supported");
5108 wbe = wbuf + j;
5109 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005110 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005111 mb = mbstate_t();
5112 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005113#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005114 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005115#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005116 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005117#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005118 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005119 __throw_runtime_error("locale not supported");
5120 wbe = wbuf + j;
5121 __months_[i+12].assign(wbuf, wbe);
5122 }
5123 // __am_pm_
5124 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005125 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005126 mb = mbstate_t();
5127 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005128#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005129 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005130#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005131 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005132#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005133 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005134 __throw_runtime_error("locale not supported");
5135 wbe = wbuf + j;
5136 __am_pm_[0].assign(wbuf, wbe);
5137 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005138 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005139 mb = mbstate_t();
5140 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005141#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005142 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005143#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005144 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005145#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005146 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005147 __throw_runtime_error("locale not supported");
5148 wbe = wbuf + j;
5149 __am_pm_[1].assign(wbuf, wbe);
5150 __c_ = __analyze('c', ct);
5151 __r_ = __analyze('r', ct);
5152 __x_ = __analyze('x', ct);
5153 __X_ = __analyze('X', ct);
5154}
5155
5156template <class CharT>
5157struct _LIBCPP_HIDDEN __time_get_temp
5158 : public ctype_byname<CharT>
5159{
5160 explicit __time_get_temp(const char* nm)
5161 : ctype_byname<CharT>(nm, 1) {}
5162 explicit __time_get_temp(const string& nm)
5163 : ctype_byname<CharT>(nm, 1) {}
5164};
5165
5166template <>
5167__time_get_storage<char>::__time_get_storage(const char* __nm)
5168 : __time_get(__nm)
5169{
5170 const __time_get_temp<char> ct(__nm);
5171 init(ct);
5172}
5173
5174template <>
5175__time_get_storage<char>::__time_get_storage(const string& __nm)
5176 : __time_get(__nm)
5177{
5178 const __time_get_temp<char> ct(__nm);
5179 init(ct);
5180}
5181
5182template <>
5183__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5184 : __time_get(__nm)
5185{
5186 const __time_get_temp<wchar_t> ct(__nm);
5187 init(ct);
5188}
5189
5190template <>
5191__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5192 : __time_get(__nm)
5193{
5194 const __time_get_temp<wchar_t> ct(__nm);
5195 init(ct);
5196}
5197
5198template <>
5199time_base::dateorder
5200__time_get_storage<char>::__do_date_order() const
5201{
5202 unsigned i;
5203 for (i = 0; i < __x_.size(); ++i)
5204 if (__x_[i] == '%')
5205 break;
5206 ++i;
5207 switch (__x_[i])
5208 {
5209 case 'y':
5210 case 'Y':
5211 for (++i; i < __x_.size(); ++i)
5212 if (__x_[i] == '%')
5213 break;
5214 if (i == __x_.size())
5215 break;
5216 ++i;
5217 switch (__x_[i])
5218 {
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 return time_base::ymd;
5228 break;
5229 case 'd':
5230 for (++i; i < __x_.size(); ++i)
5231 if (__x_[i] == '%')
5232 break;
5233 if (i == __x_.size())
5234 break;
5235 ++i;
5236 if (__x_[i] == 'm')
5237 return time_base::ydm;
5238 break;
5239 }
5240 break;
5241 case 'm':
5242 for (++i; i < __x_.size(); ++i)
5243 if (__x_[i] == '%')
5244 break;
5245 if (i == __x_.size())
5246 break;
5247 ++i;
5248 if (__x_[i] == 'd')
5249 {
5250 for (++i; i < __x_.size(); ++i)
5251 if (__x_[i] == '%')
5252 break;
5253 if (i == __x_.size())
5254 break;
5255 ++i;
5256 if (__x_[i] == 'y' || __x_[i] == 'Y')
5257 return time_base::mdy;
5258 break;
5259 }
5260 break;
5261 case 'd':
5262 for (++i; i < __x_.size(); ++i)
5263 if (__x_[i] == '%')
5264 break;
5265 if (i == __x_.size())
5266 break;
5267 ++i;
5268 if (__x_[i] == 'm')
5269 {
5270 for (++i; i < __x_.size(); ++i)
5271 if (__x_[i] == '%')
5272 break;
5273 if (i == __x_.size())
5274 break;
5275 ++i;
5276 if (__x_[i] == 'y' || __x_[i] == 'Y')
5277 return time_base::dmy;
5278 break;
5279 }
5280 break;
5281 }
5282 return time_base::no_order;
5283}
5284
5285template <>
5286time_base::dateorder
5287__time_get_storage<wchar_t>::__do_date_order() const
5288{
5289 unsigned i;
5290 for (i = 0; i < __x_.size(); ++i)
5291 if (__x_[i] == L'%')
5292 break;
5293 ++i;
5294 switch (__x_[i])
5295 {
5296 case L'y':
5297 case L'Y':
5298 for (++i; i < __x_.size(); ++i)
5299 if (__x_[i] == L'%')
5300 break;
5301 if (i == __x_.size())
5302 break;
5303 ++i;
5304 switch (__x_[i])
5305 {
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 return time_base::ymd;
5315 break;
5316 case L'd':
5317 for (++i; i < __x_.size(); ++i)
5318 if (__x_[i] == L'%')
5319 break;
5320 if (i == __x_.size())
5321 break;
5322 ++i;
5323 if (__x_[i] == L'm')
5324 return time_base::ydm;
5325 break;
5326 }
5327 break;
5328 case L'm':
5329 for (++i; i < __x_.size(); ++i)
5330 if (__x_[i] == L'%')
5331 break;
5332 if (i == __x_.size())
5333 break;
5334 ++i;
5335 if (__x_[i] == L'd')
5336 {
5337 for (++i; i < __x_.size(); ++i)
5338 if (__x_[i] == L'%')
5339 break;
5340 if (i == __x_.size())
5341 break;
5342 ++i;
5343 if (__x_[i] == L'y' || __x_[i] == L'Y')
5344 return time_base::mdy;
5345 break;
5346 }
5347 break;
5348 case L'd':
5349 for (++i; i < __x_.size(); ++i)
5350 if (__x_[i] == L'%')
5351 break;
5352 if (i == __x_.size())
5353 break;
5354 ++i;
5355 if (__x_[i] == L'm')
5356 {
5357 for (++i; i < __x_.size(); ++i)
5358 if (__x_[i] == L'%')
5359 break;
5360 if (i == __x_.size())
5361 break;
5362 ++i;
5363 if (__x_[i] == L'y' || __x_[i] == L'Y')
5364 return time_base::dmy;
5365 break;
5366 }
5367 break;
5368 }
5369 return time_base::no_order;
5370}
5371
5372// time_put
5373
5374__time_put::__time_put(const char* nm)
5375 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5376{
Howard Hinnantd4444702010-08-11 17:04:31 +00005377#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005378 if (__loc_ == 0)
5379 throw runtime_error("time_put_byname"
5380 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005381#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005382}
5383
5384__time_put::__time_put(const string& nm)
5385 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5386{
Howard Hinnantd4444702010-08-11 17:04:31 +00005387#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005388 if (__loc_ == 0)
5389 throw runtime_error("time_put_byname"
5390 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005391#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005392}
5393
5394__time_put::~__time_put()
5395{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005396 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005397 freelocale(__loc_);
5398}
5399
5400void
5401__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5402 char __fmt, char __mod) const
5403{
5404 char fmt[] = {'%', __fmt, __mod, 0};
5405 if (__mod != 0)
5406 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005407 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005408 __ne = __nb + n;
5409}
5410
5411void
5412__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5413 char __fmt, char __mod) const
5414{
5415 char __nar[100];
5416 char* __ne = __nar + 100;
5417 __do_put(__nar, __ne, __tm, __fmt, __mod);
5418 mbstate_t mb = {0};
5419 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005420#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005421 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005422#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005423 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005424#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005425 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005426 __throw_runtime_error("locale not supported");
5427 __we = __wb + j;
5428}
5429
5430// moneypunct_byname
5431
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005432template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005433static
5434void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005435__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5436 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5437 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005438{
5439 const char sign = static_cast<char>(money_base::sign);
5440 const char space = static_cast<char>(money_base::space);
5441 const char none = static_cast<char>(money_base::none);
5442 const char symbol = static_cast<char>(money_base::symbol);
5443 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005444 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5445
5446 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5447 // function'. "Space between sign and symbol or value" means that
5448 // if the sign is adjacent to the symbol, there's a space between
5449 // them, and otherwise there's a space between the sign and value.
5450 //
5451 // C11's localeconv specifies that the fourth character of an
5452 // international curr_symbol is used to separate the sign and
5453 // value when sep_by_space says to do so. C++ can't represent
5454 // that, so we just use a space. When sep_by_space says to
5455 // separate the symbol and value-or-sign with a space, we rearrange the
5456 // curr_symbol to put its spacing character on the correct side of
5457 // the symbol.
5458 //
5459 // We also need to avoid adding an extra space between the sign
5460 // and value when the currency symbol is suppressed (by not
5461 // setting showbase). We match glibc's strfmon by interpreting
5462 // sep_by_space==1 as "omit the space when the currency symbol is
5463 // absent".
5464 //
5465 // Users who want to get this right should use ICU instead.
5466
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005467 switch (cs_precedes)
5468 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005469 case 0: // value before curr_symbol
5470 if (symbol_contains_sep) {
5471 // Move the separator to before the symbol, to place it
5472 // between the value and symbol.
5473 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5474 __curr_symbol_.end());
5475 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005476 switch (sign_posn)
5477 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005478 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005479 pat.field[0] = sign;
5480 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005481 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005482 pat.field[3] = symbol;
5483 switch (sep_by_space)
5484 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005485 case 0: // No space separates the currency symbol and value.
5486 // This case may have changed between C99 and C11;
5487 // assume the currency symbol matches the intention.
5488 case 2: // Space between sign and currency or value.
5489 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005490 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005491 case 1: // Space between currency-and-sign or currency and value.
5492 if (!symbol_contains_sep) {
5493 // We insert the space into the symbol instead of
5494 // setting pat.field[2]=space so that when
5495 // showbase is not set, the space goes away too.
5496 __curr_symbol_.insert(0, 1, space_char);
5497 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005498 return;
5499 default:
5500 break;
5501 }
5502 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005503 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005504 pat.field[0] = sign;
5505 pat.field[3] = symbol;
5506 switch (sep_by_space)
5507 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005508 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005509 pat.field[1] = value;
5510 pat.field[2] = none;
5511 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005512 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005513 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005514 pat.field[2] = none;
5515 if (!symbol_contains_sep) {
5516 // We insert the space into the symbol instead of
5517 // setting pat.field[2]=space so that when
5518 // showbase is not set, the space goes away too.
5519 __curr_symbol_.insert(0, 1, space_char);
5520 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005521 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005522 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005523 pat.field[1] = space;
5524 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005525 if (symbol_contains_sep) {
5526 // Remove the separator from the symbol, since it
5527 // has already appeared after the sign.
5528 __curr_symbol_.erase(__curr_symbol_.begin());
5529 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005530 return;
5531 default:
5532 break;
5533 }
5534 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005535 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005536 pat.field[0] = value;
5537 pat.field[3] = sign;
5538 switch (sep_by_space)
5539 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005540 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005541 pat.field[1] = none;
5542 pat.field[2] = symbol;
5543 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005544 case 1: // Space between currency-and-sign or currency and value.
5545 if (!symbol_contains_sep) {
5546 // We insert the space into the symbol instead of
5547 // setting pat.field[1]=space so that when
5548 // showbase is not set, the space goes away too.
5549 __curr_symbol_.insert(0, 1, space_char);
5550 }
5551 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005552 pat.field[2] = symbol;
5553 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005554 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005555 pat.field[1] = symbol;
5556 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005557 if (symbol_contains_sep) {
5558 // Remove the separator from the symbol, since it
5559 // should not be removed if showbase is absent.
5560 __curr_symbol_.erase(__curr_symbol_.begin());
5561 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005562 return;
5563 default:
5564 break;
5565 }
5566 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005567 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005568 pat.field[0] = value;
5569 pat.field[3] = symbol;
5570 switch (sep_by_space)
5571 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005572 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005573 pat.field[1] = none;
5574 pat.field[2] = sign;
5575 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005576 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005577 pat.field[1] = space;
5578 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005579 if (symbol_contains_sep) {
5580 // Remove the separator from the symbol, since it
5581 // has already appeared before the sign.
5582 __curr_symbol_.erase(__curr_symbol_.begin());
5583 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005584 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005585 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005586 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005587 pat.field[2] = none;
5588 if (!symbol_contains_sep) {
5589 // We insert the space into the symbol instead of
5590 // setting pat.field[2]=space so that when
5591 // showbase is not set, the space goes away too.
5592 __curr_symbol_.insert(0, 1, space_char);
5593 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005594 return;
5595 default:
5596 break;
5597 }
5598 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005599 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005600 pat.field[0] = value;
5601 pat.field[3] = sign;
5602 switch (sep_by_space)
5603 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005604 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005605 pat.field[1] = none;
5606 pat.field[2] = symbol;
5607 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005608 case 1: // Space between currency-and-sign or currency and value.
5609 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005610 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005611 if (!symbol_contains_sep) {
5612 // We insert the space into the symbol instead of
5613 // setting pat.field[1]=space so that when
5614 // showbase is not set, the space goes away too.
5615 __curr_symbol_.insert(0, 1, space_char);
5616 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005617 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005618 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005619 pat.field[1] = symbol;
5620 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005621 if (symbol_contains_sep) {
5622 // Remove the separator from the symbol, since it
5623 // should not disappear when showbase is absent.
5624 __curr_symbol_.erase(__curr_symbol_.begin());
5625 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005626 return;
5627 default:
5628 break;
5629 }
5630 break;
5631 default:
5632 break;
5633 }
5634 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005635 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005636 switch (sign_posn)
5637 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005638 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005639 pat.field[0] = sign;
5640 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005641 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005642 pat.field[3] = value;
5643 switch (sep_by_space)
5644 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005645 case 0: // No space separates the currency symbol and value.
5646 // This case may have changed between C99 and C11;
5647 // assume the currency symbol matches the intention.
5648 case 2: // Space between sign and currency or value.
5649 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005650 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005651 case 1: // Space between currency-and-sign or currency and value.
5652 if (!symbol_contains_sep) {
5653 // We insert the space into the symbol instead of
5654 // setting pat.field[2]=space so that when
5655 // showbase is not set, the space goes away too.
5656 __curr_symbol_.insert(0, 1, space_char);
5657 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005658 return;
5659 default:
5660 break;
5661 }
5662 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005663 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005664 pat.field[0] = sign;
5665 pat.field[3] = value;
5666 switch (sep_by_space)
5667 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005668 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005669 pat.field[1] = symbol;
5670 pat.field[2] = none;
5671 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005672 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005673 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005674 pat.field[2] = none;
5675 if (!symbol_contains_sep) {
5676 // We insert the space into the symbol instead of
5677 // setting pat.field[2]=space so that when
5678 // showbase is not set, the space goes away too.
5679 __curr_symbol_.push_back(space_char);
5680 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005681 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005682 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005683 pat.field[1] = space;
5684 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005685 if (symbol_contains_sep) {
5686 // Remove the separator from the symbol, since it
5687 // has already appeared after the sign.
5688 __curr_symbol_.pop_back();
5689 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005690 return;
5691 default:
5692 break;
5693 }
5694 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005695 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005696 pat.field[0] = symbol;
5697 pat.field[3] = sign;
5698 switch (sep_by_space)
5699 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005700 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005701 pat.field[1] = none;
5702 pat.field[2] = value;
5703 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005704 case 1: // Space between currency-and-sign or currency and value.
5705 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005706 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005707 if (!symbol_contains_sep) {
5708 // We insert the space into the symbol instead of
5709 // setting pat.field[1]=space so that when
5710 // showbase is not set, the space goes away too.
5711 __curr_symbol_.push_back(space_char);
5712 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005713 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005714 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005715 pat.field[1] = value;
5716 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005717 if (symbol_contains_sep) {
5718 // Remove the separator from the symbol, since it
5719 // will appear before the sign.
5720 __curr_symbol_.pop_back();
5721 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005722 return;
5723 default:
5724 break;
5725 }
5726 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005727 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005728 pat.field[0] = sign;
5729 pat.field[3] = value;
5730 switch (sep_by_space)
5731 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005732 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005733 pat.field[1] = symbol;
5734 pat.field[2] = none;
5735 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005736 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005737 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005738 pat.field[2] = none;
5739 if (!symbol_contains_sep) {
5740 // We insert the space into the symbol instead of
5741 // setting pat.field[2]=space so that when
5742 // showbase is not set, the space goes away too.
5743 __curr_symbol_.push_back(space_char);
5744 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005745 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005746 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005747 pat.field[1] = space;
5748 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005749 if (symbol_contains_sep) {
5750 // Remove the separator from the symbol, since it
5751 // has already appeared after the sign.
5752 __curr_symbol_.pop_back();
5753 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005754 return;
5755 default:
5756 break;
5757 }
5758 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005759 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005760 pat.field[0] = symbol;
5761 pat.field[3] = value;
5762 switch (sep_by_space)
5763 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005764 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005765 pat.field[1] = sign;
5766 pat.field[2] = none;
5767 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005768 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005769 pat.field[1] = sign;
5770 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005771 if (symbol_contains_sep) {
5772 // Remove the separator from the symbol, since it
5773 // should not disappear when showbase is absent.
5774 __curr_symbol_.pop_back();
5775 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005776 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005777 case 2: // Space between sign and currency or value.
5778 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005779 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005780 if (!symbol_contains_sep) {
5781 // We insert the space into the symbol instead of
5782 // setting pat.field[1]=space so that when
5783 // showbase is not set, the space goes away too.
5784 __curr_symbol_.push_back(space_char);
5785 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005786 return;
5787 default:
5788 break;
5789 }
5790 break;
5791 default:
5792 break;
5793 }
5794 break;
5795 default:
5796 break;
5797 }
5798 pat.field[0] = symbol;
5799 pat.field[1] = sign;
5800 pat.field[2] = none;
5801 pat.field[3] = value;
5802}
5803
5804template<>
5805void
5806moneypunct_byname<char, false>::init(const char* nm)
5807{
5808 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005809 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005810#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005811 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005812 throw runtime_error("moneypunct_byname"
5813 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005814#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005815#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005816 lconv* lc = localeconv_l(loc.get());
5817#else
5818 lconv* lc = __localeconv_l(loc.get());
5819#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005820 if (*lc->mon_decimal_point)
5821 __decimal_point_ = *lc->mon_decimal_point;
5822 else
5823 __decimal_point_ = base::do_decimal_point();
5824 if (*lc->mon_thousands_sep)
5825 __thousands_sep_ = *lc->mon_thousands_sep;
5826 else
5827 __thousands_sep_ = base::do_thousands_sep();
5828 __grouping_ = lc->mon_grouping;
5829 __curr_symbol_ = lc->currency_symbol;
5830 if (lc->frac_digits != CHAR_MAX)
5831 __frac_digits_ = lc->frac_digits;
5832 else
5833 __frac_digits_ = base::do_frac_digits();
5834 if (lc->p_sign_posn == 0)
5835 __positive_sign_ = "()";
5836 else
5837 __positive_sign_ = lc->positive_sign;
5838 if (lc->n_sign_posn == 0)
5839 __negative_sign_ = "()";
5840 else
5841 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005842 // Assume the positive and negative formats will want spaces in
5843 // the same places in curr_symbol since there's no way to
5844 // represent anything else.
5845 string_type __dummy_curr_symbol = __curr_symbol_;
5846 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5847 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5848 __init_pat(__neg_format_, __curr_symbol_, false,
5849 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005850}
5851
5852template<>
5853void
5854moneypunct_byname<char, true>::init(const char* nm)
5855{
5856 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005857 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005858#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005859 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005860 throw runtime_error("moneypunct_byname"
5861 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005862#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005863#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005864 lconv* lc = localeconv_l(loc.get());
5865#else
5866 lconv* lc = __localeconv_l(loc.get());
5867#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005868 if (*lc->mon_decimal_point)
5869 __decimal_point_ = *lc->mon_decimal_point;
5870 else
5871 __decimal_point_ = base::do_decimal_point();
5872 if (*lc->mon_thousands_sep)
5873 __thousands_sep_ = *lc->mon_thousands_sep;
5874 else
5875 __thousands_sep_ = base::do_thousands_sep();
5876 __grouping_ = lc->mon_grouping;
5877 __curr_symbol_ = lc->int_curr_symbol;
5878 if (lc->int_frac_digits != CHAR_MAX)
5879 __frac_digits_ = lc->int_frac_digits;
5880 else
5881 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00005882#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005883 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005884#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005885 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005886#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005887 __positive_sign_ = "()";
5888 else
5889 __positive_sign_ = lc->positive_sign;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005890#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005891 if(lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005892#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005893 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005894#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005895 __negative_sign_ = "()";
5896 else
5897 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005898 // Assume the positive and negative formats will want spaces in
5899 // the same places in curr_symbol since there's no way to
5900 // represent anything else.
5901 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005902#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005903 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5904 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5905 __init_pat(__neg_format_, __curr_symbol_, true,
5906 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005907#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005908 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5909 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5910 lc->int_p_sign_posn, ' ');
5911 __init_pat(__neg_format_, __curr_symbol_, true,
5912 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5913 lc->int_n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005914#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005915}
5916
5917template<>
5918void
5919moneypunct_byname<wchar_t, false>::init(const char* nm)
5920{
5921 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005922 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005923#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005924 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005925 throw runtime_error("moneypunct_byname"
5926 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005927#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005928#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005929 lconv* lc = localeconv_l(loc.get());
5930#else
5931 lconv* lc = __localeconv_l(loc.get());
5932#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005933 if (*lc->mon_decimal_point)
5934 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5935 else
5936 __decimal_point_ = base::do_decimal_point();
5937 if (*lc->mon_thousands_sep)
5938 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5939 else
5940 __thousands_sep_ = base::do_thousands_sep();
5941 __grouping_ = lc->mon_grouping;
5942 wchar_t wbuf[100];
5943 mbstate_t mb = {0};
5944 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005945#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005946 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005947#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005948 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005949#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005950 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005951 __throw_runtime_error("locale not supported");
5952 wchar_t* wbe = wbuf + j;
5953 __curr_symbol_.assign(wbuf, wbe);
5954 if (lc->frac_digits != CHAR_MAX)
5955 __frac_digits_ = lc->frac_digits;
5956 else
5957 __frac_digits_ = base::do_frac_digits();
5958 if (lc->p_sign_posn == 0)
5959 __positive_sign_ = L"()";
5960 else
5961 {
5962 mb = mbstate_t();
5963 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005964#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005965 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005966#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005967 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005968#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005969 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005970 __throw_runtime_error("locale not supported");
5971 wbe = wbuf + j;
5972 __positive_sign_.assign(wbuf, wbe);
5973 }
5974 if (lc->n_sign_posn == 0)
5975 __negative_sign_ = L"()";
5976 else
5977 {
5978 mb = mbstate_t();
5979 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005980#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005981 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005982#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005983 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005984#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005985 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005986 __throw_runtime_error("locale not supported");
5987 wbe = wbuf + j;
5988 __negative_sign_.assign(wbuf, wbe);
5989 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005990 // Assume the positive and negative formats will want spaces in
5991 // the same places in curr_symbol since there's no way to
5992 // represent anything else.
5993 string_type __dummy_curr_symbol = __curr_symbol_;
5994 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5995 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5996 __init_pat(__neg_format_, __curr_symbol_, false,
5997 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005998}
5999
6000template<>
6001void
6002moneypunct_byname<wchar_t, true>::init(const char* nm)
6003{
6004 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00006005 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00006006#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00006007 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006008 throw runtime_error("moneypunct_byname"
6009 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00006010#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00006011#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00006012 lconv* lc = localeconv_l(loc.get());
6013#else
6014 lconv* lc = __localeconv_l(loc.get());
6015#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006016 if (*lc->mon_decimal_point)
6017 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6018 else
6019 __decimal_point_ = base::do_decimal_point();
6020 if (*lc->mon_thousands_sep)
6021 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6022 else
6023 __thousands_sep_ = base::do_thousands_sep();
6024 __grouping_ = lc->mon_grouping;
6025 wchar_t wbuf[100];
6026 mbstate_t mb = {0};
6027 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006028#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006029 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006030#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006031 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006032#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006033 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006034 __throw_runtime_error("locale not supported");
6035 wchar_t* wbe = wbuf + j;
6036 __curr_symbol_.assign(wbuf, wbe);
6037 if (lc->int_frac_digits != CHAR_MAX)
6038 __frac_digits_ = lc->int_frac_digits;
6039 else
6040 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00006041#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006042 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006043#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006044 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006045#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006046 __positive_sign_ = L"()";
6047 else
6048 {
6049 mb = mbstate_t();
6050 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006051#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
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#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006054 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006055#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006056 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006057 __throw_runtime_error("locale not supported");
6058 wbe = wbuf + j;
6059 __positive_sign_.assign(wbuf, wbe);
6060 }
Howard Hinnantef5aa932013-09-17 01:34:47 +00006061#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006062 if (lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006063#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006064 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006065#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006066 __negative_sign_ = L"()";
6067 else
6068 {
6069 mb = mbstate_t();
6070 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006071#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006072 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006073#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006074 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006075#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006076 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006077 __throw_runtime_error("locale not supported");
6078 wbe = wbuf + j;
6079 __negative_sign_.assign(wbuf, wbe);
6080 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006081 // Assume the positive and negative formats will want spaces in
6082 // the same places in curr_symbol since there's no way to
6083 // represent anything else.
6084 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00006085#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006086 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6087 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6088 __init_pat(__neg_format_, __curr_symbol_, true,
6089 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006090#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006091 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6092 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6093 lc->int_p_sign_posn, L' ');
6094 __init_pat(__neg_format_, __curr_symbol_, true,
6095 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6096 lc->int_n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006097#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006098}
6099
6100void __do_nothing(void*) {}
6101
6102void __throw_runtime_error(const char* msg)
6103{
Howard Hinnantd4444702010-08-11 17:04:31 +00006104#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006105 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006106#else
6107 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006108#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006109}
6110
6111template class collate<char>;
6112template class collate<wchar_t>;
6113
6114template class num_get<char>;
6115template class num_get<wchar_t>;
6116
Howard Hinnantec3773c2011-12-01 20:21:04 +00006117template struct __num_get<char>;
6118template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006119
6120template class num_put<char>;
6121template class num_put<wchar_t>;
6122
Howard Hinnantec3773c2011-12-01 20:21:04 +00006123template struct __num_put<char>;
6124template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006125
6126template class time_get<char>;
6127template class time_get<wchar_t>;
6128
6129template class time_get_byname<char>;
6130template class time_get_byname<wchar_t>;
6131
6132template class time_put<char>;
6133template class time_put<wchar_t>;
6134
6135template class time_put_byname<char>;
6136template class time_put_byname<wchar_t>;
6137
6138template class moneypunct<char, false>;
6139template class moneypunct<char, true>;
6140template class moneypunct<wchar_t, false>;
6141template class moneypunct<wchar_t, true>;
6142
6143template class moneypunct_byname<char, false>;
6144template class moneypunct_byname<char, true>;
6145template class moneypunct_byname<wchar_t, false>;
6146template class moneypunct_byname<wchar_t, true>;
6147
6148template class money_get<char>;
6149template class money_get<wchar_t>;
6150
6151template class __money_get<char>;
6152template class __money_get<wchar_t>;
6153
6154template class money_put<char>;
6155template class money_put<wchar_t>;
6156
6157template class __money_put<char>;
6158template class __money_put<wchar_t>;
6159
6160template class messages<char>;
6161template class messages<wchar_t>;
6162
6163template class messages_byname<char>;
6164template class messages_byname<wchar_t>;
6165
6166template class codecvt_byname<char, char, mbstate_t>;
6167template class codecvt_byname<wchar_t, char, mbstate_t>;
6168template class codecvt_byname<char16_t, char, mbstate_t>;
6169template class codecvt_byname<char32_t, char, mbstate_t>;
6170
6171template class __vector_base_common<true>;
6172
6173_LIBCPP_END_NAMESPACE_STD