blob: 12f05413c60d660feac0d301d396aeb2eba0104c [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Howard Hinnantc566dc32010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00004//
Howard Hinnantee11c312010-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 Hinnantc51e1022010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
David Chisnall8074c342012-02-29 13:05:08 +000010// On Solaris, we need to define something to make the C99 parts of localeconv
11// visible.
12#ifdef __sun__
13#define _LCONV_C99
14#endif
15
Howard Hinnantc51e1022010-05-11 19:42:16 +000016#include "string"
17#include "locale"
Howard Hinnant7282c5a2010-05-30 21:39:41 +000018#include "codecvt"
Howard Hinnantc51e1022010-05-11 19:42:16 +000019#include "vector"
20#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000021#include "typeinfo"
Howard Hinnant718dae32013-07-28 18:20:00 +000022#ifndef _LIBCPP_NO_EXCEPTIONS
23# include "type_traits"
24#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000025#include "clocale"
26#include "cstring"
27#include "cwctype"
28#include "__sso_allocator"
Howard Hinnant8ad70912013-09-17 01:34:47 +000029#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Marshall Clowccb92572015-06-23 14:45:02 +000030#include "support/win32/locale_win32.h"
Dan Albert21800dc2016-09-19 18:00:45 +000031#elif !defined(__BIONIC__)
Howard Hinnantc51e1022010-05-11 19:42:16 +000032#include <langinfo.h>
Marshall Clow3477ec92014-07-10 15:20:28 +000033#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000034#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000035#include <stdio.h>
Howard Hinnantc51e1022010-05-11 19:42:16 +000036
Marshall Clowab9c1772013-02-07 17:20:56 +000037// On Linux, wint_t and wchar_t have different signed-ness, and this causes
38// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000039#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000040#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000041#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000042
Howard Hinnantc51e1022010-05-11 19:42:16 +000043_LIBCPP_BEGIN_NAMESPACE_STD
44
Howard Hinnantf312e3e2011-09-28 23:39:33 +000045#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000046locale_t __cloc() {
47 // In theory this could create a race condition. In practice
48 // the race condition is non-fatal since it will just create
49 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000050 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
51 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000052}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000053#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000054
Howard Hinnantc51e1022010-05-11 19:42:16 +000055namespace {
56
57struct release
58{
59 void operator()(locale::facet* p) {p->__release_shared();}
60};
61
62template <class T, class A0>
63inline
64T&
65make(A0 a0)
66{
67 static typename aligned_storage<sizeof(T)>::type buf;
68 ::new (&buf) T(a0);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000069 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000070}
71
72template <class T, class A0, class A1>
73inline
74T&
75make(A0 a0, A1 a1)
76{
77 static typename aligned_storage<sizeof(T)>::type buf;
78 ::new (&buf) T(a0, a1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000079 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000080}
81
82template <class T, class A0, class A1, class A2>
83inline
84T&
85make(A0 a0, A1 a1, A2 a2)
86{
87 static typename aligned_storage<sizeof(T)>::type buf;
88 ::new (&buf) T(a0, a1, a2);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000089 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000090}
91
Howard Hinnant3d2417c2012-12-27 21:17:53 +000092template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +000093inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +000094_LIBCPP_CONSTEXPR
95size_t
96countof(const T (&)[N])
97{
98 return N;
99}
100
101template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000102inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000103_LIBCPP_CONSTEXPR
104size_t
105countof(const T * const begin, const T * const end)
106{
107 return static_cast<size_t>(end - begin);
108}
109
Marshall Clow8fea1612016-08-25 15:09:01 +0000110_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
111{
112#ifndef _LIBCPP_NO_EXCEPTIONS
113 throw runtime_error(msg);
114#else
115 (void)msg;
116 _VSTD::abort();
117#endif
118}
119
Howard Hinnantc51e1022010-05-11 19:42:16 +0000120}
121
Howard Hinnantdd099492013-08-29 23:37:50 +0000122#if defined(_AIX)
123// Set priority to INT_MIN + 256 + 150
124# pragma priority ( -2147483242 )
125#endif
126
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000127const locale::category locale::none;
128const locale::category locale::collate;
129const locale::category locale::ctype;
130const locale::category locale::monetary;
131const locale::category locale::numeric;
132const locale::category locale::time;
133const locale::category locale::messages;
134const locale::category locale::all;
135
Howard Hinnantc51e1022010-05-11 19:42:16 +0000136class _LIBCPP_HIDDEN locale::__imp
137 : public facet
138{
139 enum {N = 28};
Marshall Clowd920eea2013-10-21 15:07:28 +0000140#if defined(_LIBCPP_MSVC)
141// FIXME: MSVC doesn't support aligned parameters by value.
142// I can't get the __sso_allocator to work here
143// for MSVC I think for this reason.
144 vector<facet*> facets_;
145#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000146 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000147#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000148 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000149public:
150 explicit __imp(size_t refs = 0);
151 explicit __imp(const string& name, size_t refs = 0);
152 __imp(const __imp&);
153 __imp(const __imp&, const string&, locale::category c);
154 __imp(const __imp& other, const __imp& one, locale::category c);
155 __imp(const __imp&, facet* f, long id);
156 ~__imp();
157
158 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000159 bool has_facet(long id) const
160 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000161 const locale::facet* use_facet(long id) const;
162
163 static const locale& make_classic();
164 static locale& make_global();
165private:
166 void install(facet* f, long id);
167 template <class F> void install(F* f) {install(f, f->id.__get());}
168 template <class F> void install_from(const __imp& other);
169};
170
171locale::__imp::__imp(size_t refs)
172 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000173 facets_(N),
174 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000175{
176 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000177 install(&make<_VSTD::collate<char> >(1u));
178 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000179 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000180 install(&make<_VSTD::ctype<wchar_t> >(1u));
181 install(&make<codecvt<char, char, mbstate_t> >(1u));
182 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
183 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
184 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
185 install(&make<numpunct<char> >(1u));
186 install(&make<numpunct<wchar_t> >(1u));
187 install(&make<num_get<char> >(1u));
188 install(&make<num_get<wchar_t> >(1u));
189 install(&make<num_put<char> >(1u));
190 install(&make<num_put<wchar_t> >(1u));
191 install(&make<moneypunct<char, false> >(1u));
192 install(&make<moneypunct<char, true> >(1u));
193 install(&make<moneypunct<wchar_t, false> >(1u));
194 install(&make<moneypunct<wchar_t, true> >(1u));
195 install(&make<money_get<char> >(1u));
196 install(&make<money_get<wchar_t> >(1u));
197 install(&make<money_put<char> >(1u));
198 install(&make<money_put<wchar_t> >(1u));
199 install(&make<time_get<char> >(1u));
200 install(&make<time_get<wchar_t> >(1u));
201 install(&make<time_put<char> >(1u));
202 install(&make<time_put<wchar_t> >(1u));
203 install(&make<_VSTD::messages<char> >(1u));
204 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000205}
206
207locale::__imp::__imp(const string& name, size_t refs)
208 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000209 facets_(N),
210 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000211{
Howard Hinnant72f73582010-08-11 17:04:31 +0000212#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000213 try
214 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000215#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000216 facets_ = locale::classic().__locale_->facets_;
217 for (unsigned i = 0; i < facets_.size(); ++i)
218 if (facets_[i])
219 facets_[i]->__add_shared();
220 install(new collate_byname<char>(name_));
221 install(new collate_byname<wchar_t>(name_));
222 install(new ctype_byname<char>(name_));
223 install(new ctype_byname<wchar_t>(name_));
224 install(new codecvt_byname<char, char, mbstate_t>(name_));
225 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
226 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
227 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
228 install(new numpunct_byname<char>(name_));
229 install(new numpunct_byname<wchar_t>(name_));
230 install(new moneypunct_byname<char, false>(name_));
231 install(new moneypunct_byname<char, true>(name_));
232 install(new moneypunct_byname<wchar_t, false>(name_));
233 install(new moneypunct_byname<wchar_t, true>(name_));
234 install(new time_get_byname<char>(name_));
235 install(new time_get_byname<wchar_t>(name_));
236 install(new time_put_byname<char>(name_));
237 install(new time_put_byname<wchar_t>(name_));
238 install(new messages_byname<char>(name_));
239 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000240#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000241 }
242 catch (...)
243 {
244 for (unsigned i = 0; i < facets_.size(); ++i)
245 if (facets_[i])
246 facets_[i]->__release_shared();
247 throw;
248 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000249#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000250}
251
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000252// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000253// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000254#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000255#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000256#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000257#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000258
Howard Hinnantc51e1022010-05-11 19:42:16 +0000259locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000260 : facets_(max<size_t>(N, other.facets_.size())),
261 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000262{
263 facets_ = other.facets_;
264 for (unsigned i = 0; i < facets_.size(); ++i)
265 if (facets_[i])
266 facets_[i]->__add_shared();
267}
268
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000269#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000270#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000271#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000272
Howard Hinnantc51e1022010-05-11 19:42:16 +0000273locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000274 : facets_(N),
275 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000276{
277 facets_ = other.facets_;
278 for (unsigned i = 0; i < facets_.size(); ++i)
279 if (facets_[i])
280 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000281#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000282 try
283 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000284#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000285 if (c & locale::collate)
286 {
287 install(new collate_byname<char>(name));
288 install(new collate_byname<wchar_t>(name));
289 }
290 if (c & locale::ctype)
291 {
292 install(new ctype_byname<char>(name));
293 install(new ctype_byname<wchar_t>(name));
294 install(new codecvt_byname<char, char, mbstate_t>(name));
295 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
296 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
297 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
298 }
299 if (c & locale::monetary)
300 {
301 install(new moneypunct_byname<char, false>(name));
302 install(new moneypunct_byname<char, true>(name));
303 install(new moneypunct_byname<wchar_t, false>(name));
304 install(new moneypunct_byname<wchar_t, true>(name));
305 }
306 if (c & locale::numeric)
307 {
308 install(new numpunct_byname<char>(name));
309 install(new numpunct_byname<wchar_t>(name));
310 }
311 if (c & locale::time)
312 {
313 install(new time_get_byname<char>(name));
314 install(new time_get_byname<wchar_t>(name));
315 install(new time_put_byname<char>(name));
316 install(new time_put_byname<wchar_t>(name));
317 }
318 if (c & locale::messages)
319 {
320 install(new messages_byname<char>(name));
321 install(new messages_byname<wchar_t>(name));
322 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000323#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000324 }
325 catch (...)
326 {
327 for (unsigned i = 0; i < facets_.size(); ++i)
328 if (facets_[i])
329 facets_[i]->__release_shared();
330 throw;
331 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000332#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000333}
334
335template<class F>
336inline
337void
338locale::__imp::install_from(const locale::__imp& one)
339{
340 long id = F::id.__get();
341 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
342}
343
344locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000345 : facets_(N),
346 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000347{
348 facets_ = other.facets_;
349 for (unsigned i = 0; i < facets_.size(); ++i)
350 if (facets_[i])
351 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000352#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000353 try
354 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000355#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000356 if (c & locale::collate)
357 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000358 install_from<_VSTD::collate<char> >(one);
359 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000360 }
361 if (c & locale::ctype)
362 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000363 install_from<_VSTD::ctype<char> >(one);
364 install_from<_VSTD::ctype<wchar_t> >(one);
365 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
366 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
367 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
368 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000369 }
370 if (c & locale::monetary)
371 {
372 install_from<moneypunct<char, false> >(one);
373 install_from<moneypunct<char, true> >(one);
374 install_from<moneypunct<wchar_t, false> >(one);
375 install_from<moneypunct<wchar_t, true> >(one);
376 install_from<money_get<char> >(one);
377 install_from<money_get<wchar_t> >(one);
378 install_from<money_put<char> >(one);
379 install_from<money_put<wchar_t> >(one);
380 }
381 if (c & locale::numeric)
382 {
383 install_from<numpunct<char> >(one);
384 install_from<numpunct<wchar_t> >(one);
385 install_from<num_get<char> >(one);
386 install_from<num_get<wchar_t> >(one);
387 install_from<num_put<char> >(one);
388 install_from<num_put<wchar_t> >(one);
389 }
390 if (c & locale::time)
391 {
392 install_from<time_get<char> >(one);
393 install_from<time_get<wchar_t> >(one);
394 install_from<time_put<char> >(one);
395 install_from<time_put<wchar_t> >(one);
396 }
397 if (c & locale::messages)
398 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000399 install_from<_VSTD::messages<char> >(one);
400 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000401 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000402#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000403 }
404 catch (...)
405 {
406 for (unsigned i = 0; i < facets_.size(); ++i)
407 if (facets_[i])
408 facets_[i]->__release_shared();
409 throw;
410 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000411#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000412}
413
414locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000415 : facets_(max<size_t>(N, other.facets_.size()+1)),
416 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000417{
418 f->__add_shared();
419 unique_ptr<facet, release> hold(f);
420 facets_ = other.facets_;
421 for (unsigned i = 0; i < other.facets_.size(); ++i)
422 if (facets_[i])
423 facets_[i]->__add_shared();
424 install(hold.get(), id);
425}
426
427locale::__imp::~__imp()
428{
429 for (unsigned i = 0; i < facets_.size(); ++i)
430 if (facets_[i])
431 facets_[i]->__release_shared();
432}
433
434void
435locale::__imp::install(facet* f, long id)
436{
437 f->__add_shared();
438 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000439 if (static_cast<size_t>(id) >= facets_.size())
440 facets_.resize(static_cast<size_t>(id+1));
441 if (facets_[static_cast<size_t>(id)])
442 facets_[static_cast<size_t>(id)]->__release_shared();
443 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000444}
445
446const locale::facet*
447locale::__imp::use_facet(long id) const
448{
Howard Hinnant72f73582010-08-11 17:04:31 +0000449#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000450 if (!has_facet(id))
451 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000452#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant28b24882011-12-01 20:21:04 +0000453 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000454}
455
456// locale
457
458const locale&
459locale::__imp::make_classic()
460{
461 // only one thread can get in here and it only gets in once
462 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000463 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000464 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000465 return *c;
466}
467
468const locale&
469locale::classic()
470{
471 static const locale& c = __imp::make_classic();
472 return c;
473}
474
475locale&
476locale::__imp::make_global()
477{
478 // only one thread can get in here and it only gets in once
479 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000480 ::new (&buf) locale(locale::classic());
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000481 return *reinterpret_cast<locale*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000482}
483
484locale&
485locale::__global()
486{
487 static locale& g = __imp::make_global();
488 return g;
489}
490
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000491locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000492 : __locale_(__global().__locale_)
493{
494 __locale_->__add_shared();
495}
496
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000497locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000498 : __locale_(l.__locale_)
499{
500 __locale_->__add_shared();
501}
502
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000503locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000504{
505 __locale_->__release_shared();
506}
507
508const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000509locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000510{
511 other.__locale_->__add_shared();
512 __locale_->__release_shared();
513 __locale_ = other.__locale_;
514 return *this;
515}
516
517locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000518#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000519 : __locale_(name ? new __imp(name)
520 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000521#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000522 : __locale_(new __imp(name))
523#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000524{
525 __locale_->__add_shared();
526}
527
528locale::locale(const string& name)
529 : __locale_(new __imp(name))
530{
531 __locale_->__add_shared();
532}
533
534locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000535#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000536 : __locale_(name ? new __imp(*other.__locale_, name, c)
537 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000538#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000539 : __locale_(new __imp(*other.__locale_, name, c))
540#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000541{
542 __locale_->__add_shared();
543}
544
545locale::locale(const locale& other, const string& name, category c)
546 : __locale_(new __imp(*other.__locale_, name, c))
547{
548 __locale_->__add_shared();
549}
550
551locale::locale(const locale& other, const locale& one, category c)
552 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
553{
554 __locale_->__add_shared();
555}
556
557string
558locale::name() const
559{
560 return __locale_->name();
561}
562
563void
564locale::__install_ctor(const locale& other, facet* f, long id)
565{
566 if (f)
567 __locale_ = new __imp(*other.__locale_, f, id);
568 else
569 __locale_ = other.__locale_;
570 __locale_->__add_shared();
571}
572
573locale
574locale::global(const locale& loc)
575{
576 locale& g = __global();
577 locale r = g;
578 g = loc;
Ed Schouten3d3341e2015-07-06 15:39:36 +0000579#ifndef __CloudABI__
Howard Hinnantc51e1022010-05-11 19:42:16 +0000580 if (g.name() != "*")
581 setlocale(LC_ALL, g.name().c_str());
Ed Schouten3d3341e2015-07-06 15:39:36 +0000582#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000583 return r;
584}
585
586bool
587locale::has_facet(id& x) const
588{
589 return __locale_->has_facet(x.__get());
590}
591
592const locale::facet*
593locale::use_facet(id& x) const
594{
595 return __locale_->use_facet(x.__get());
596}
597
598bool
599locale::operator==(const locale& y) const
600{
601 return (__locale_ == y.__locale_)
602 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
603}
604
605// locale::facet
606
607locale::facet::~facet()
608{
609}
610
611void
Howard Hinnant719bda32011-05-28 14:41:13 +0000612locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000613{
614 delete this;
615}
616
617// locale::id
618
619int32_t locale::id::__next_id = 0;
620
621namespace
622{
623
624class __fake_bind
625{
626 locale::id* id_;
627 void (locale::id::* pmf_)();
628public:
629 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
630 : id_(id), pmf_(pmf) {}
631
632 void operator()() const
633 {
634 (id_->*pmf_)();
635 }
636};
637
638}
639
640long
641locale::id::__get()
642{
643 call_once(__flag_, __fake_bind(&locale::id::__init, this));
644 return __id_ - 1;
645}
646
647void
648locale::id::__init()
649{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000650 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000651}
652
653// template <> class collate_byname<char>
654
655collate_byname<char>::collate_byname(const char* n, size_t refs)
656 : collate<char>(refs),
657 __l(newlocale(LC_ALL_MASK, n, 0))
658{
659 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000660 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000661 " failed to construct for " + string(n));
662}
663
664collate_byname<char>::collate_byname(const string& name, size_t refs)
665 : collate<char>(refs),
666 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
667{
668 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000669 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000670 " failed to construct for " + name);
671}
672
673collate_byname<char>::~collate_byname()
674{
675 freelocale(__l);
676}
677
678int
679collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
680 const char_type* __lo2, const char_type* __hi2) const
681{
682 string_type lhs(__lo1, __hi1);
683 string_type rhs(__lo2, __hi2);
684 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
685 if (r < 0)
686 return -1;
687 if (r > 0)
688 return 1;
689 return r;
690}
691
692collate_byname<char>::string_type
693collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
694{
695 const string_type in(lo, hi);
696 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
697 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
698 return out;
699}
700
701// template <> class collate_byname<wchar_t>
702
703collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
704 : collate<wchar_t>(refs),
705 __l(newlocale(LC_ALL_MASK, n, 0))
706{
707 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000708 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000709 " failed to construct for " + string(n));
710}
711
712collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
713 : collate<wchar_t>(refs),
714 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
715{
716 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000717 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000718 " failed to construct for " + name);
719}
720
721collate_byname<wchar_t>::~collate_byname()
722{
723 freelocale(__l);
724}
725
726int
727collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
728 const char_type* __lo2, const char_type* __hi2) const
729{
730 string_type lhs(__lo1, __hi1);
731 string_type rhs(__lo2, __hi2);
732 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
733 if (r < 0)
734 return -1;
735 if (r > 0)
736 return 1;
737 return r;
738}
739
740collate_byname<wchar_t>::string_type
741collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
742{
743 const string_type in(lo, hi);
744 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
745 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
746 return out;
747}
748
749// template <> class ctype<wchar_t>;
750
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000751const ctype_base::mask ctype_base::space;
752const ctype_base::mask ctype_base::print;
753const ctype_base::mask ctype_base::cntrl;
754const ctype_base::mask ctype_base::upper;
755const ctype_base::mask ctype_base::lower;
756const ctype_base::mask ctype_base::alpha;
757const ctype_base::mask ctype_base::digit;
758const ctype_base::mask ctype_base::punct;
759const ctype_base::mask ctype_base::xdigit;
760const ctype_base::mask ctype_base::blank;
761const ctype_base::mask ctype_base::alnum;
762const ctype_base::mask ctype_base::graph;
763
Howard Hinnantc51e1022010-05-11 19:42:16 +0000764locale::id ctype<wchar_t>::id;
765
766ctype<wchar_t>::~ctype()
767{
768}
769
770bool
771ctype<wchar_t>::do_is(mask m, char_type c) const
772{
Marshall Clowd920eea2013-10-21 15:07:28 +0000773 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000774}
775
776const wchar_t*
777ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
778{
779 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000780 *vec = static_cast<mask>(isascii(*low) ?
781 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000782 return low;
783}
784
785const wchar_t*
786ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
787{
788 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000789 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000790 break;
791 return low;
792}
793
794const wchar_t*
795ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
796{
797 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000798 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000799 break;
800 return low;
801}
802
803wchar_t
804ctype<wchar_t>::do_toupper(char_type c) const
805{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000806#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
807 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000808#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000809 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000810 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000811#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000812 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000813#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000814}
815
816const wchar_t*
817ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
818{
819 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000820#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
821 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000822#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000823 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000824 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
825 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000826#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000827 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000828#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000829 return low;
830}
831
832wchar_t
833ctype<wchar_t>::do_tolower(char_type c) const
834{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000835#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
836 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000837#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000838 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000839 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000840#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000841 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000842#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000843}
844
845const wchar_t*
846ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
847{
848 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000849#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
850 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000851#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000852 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000853 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
854 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000855#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000856 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000857#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000858 return low;
859}
860
861wchar_t
862ctype<wchar_t>::do_widen(char c) const
863{
864 return c;
865}
866
867const char*
868ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
869{
870 for (; low != high; ++low, ++dest)
871 *dest = *low;
872 return low;
873}
874
875char
876ctype<wchar_t>::do_narrow(char_type c, char dfault) const
877{
878 if (isascii(c))
879 return static_cast<char>(c);
880 return dfault;
881}
882
883const wchar_t*
884ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
885{
886 for (; low != high; ++low, ++dest)
887 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000888 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000889 else
890 *dest = dfault;
891 return low;
892}
893
894// template <> class ctype<char>;
895
896locale::id ctype<char>::id;
897
898ctype<char>::ctype(const mask* tab, bool del, size_t refs)
899 : locale::facet(refs),
900 __tab_(tab),
901 __del_(del)
902{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000903 if (__tab_ == 0)
904 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000905}
906
907ctype<char>::~ctype()
908{
909 if (__tab_ && __del_)
910 delete [] __tab_;
911}
912
913char
914ctype<char>::do_toupper(char_type c) const
915{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000916#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000917 return isascii(c) ?
918 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000919#elif defined(__NetBSD__)
920 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000921#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000922 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000923 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000924#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000925 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000926#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000927}
928
929const char*
930ctype<char>::do_toupper(char_type* low, const char_type* high) const
931{
932 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000933#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000934 *low = isascii(*low) ?
935 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000936#elif defined(__NetBSD__)
937 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000938#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000939 *low = isascii(*low) ?
940 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000941#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000942 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000943#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000944 return low;
945}
946
947char
948ctype<char>::do_tolower(char_type c) const
949{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000950#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000951 return isascii(c) ?
952 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000953#elif defined(__NetBSD__)
954 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000955#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000956 return isascii(c) ?
957 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000958#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000959 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000960#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000961}
962
963const char*
964ctype<char>::do_tolower(char_type* low, const char_type* high) const
965{
966 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000967#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000968 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000969#elif defined(__NetBSD__)
970 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000971#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000972 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000973#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000974 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000975#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000976 return low;
977}
978
979char
980ctype<char>::do_widen(char c) const
981{
982 return c;
983}
984
985const char*
986ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
987{
988 for (; low != high; ++low, ++dest)
989 *dest = *low;
990 return low;
991}
992
993char
994ctype<char>::do_narrow(char_type c, char dfault) const
995{
996 if (isascii(c))
997 return static_cast<char>(c);
998 return dfault;
999}
1000
1001const char*
1002ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1003{
1004 for (; low != high; ++low, ++dest)
1005 if (isascii(*low))
1006 *dest = *low;
1007 else
1008 *dest = dfault;
1009 return low;
1010}
1011
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001012#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001013extern "C" const unsigned short ** __ctype_b_loc();
1014extern "C" const int ** __ctype_tolower_loc();
1015extern "C" const int ** __ctype_toupper_loc();
1016#endif
1017
Marshall Clow8f870232015-03-04 16:50:02 +00001018#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001019const ctype<char>::mask*
1020ctype<char>::classic_table() _NOEXCEPT
1021{
1022 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1023 cntrl, cntrl,
1024 cntrl, cntrl,
1025 cntrl, cntrl,
1026 cntrl, cntrl,
1027 cntrl, cntrl | space | blank,
1028 cntrl | space, cntrl | space,
1029 cntrl | space, cntrl | space,
1030 cntrl, cntrl,
1031 cntrl, cntrl,
1032 cntrl, cntrl,
1033 cntrl, cntrl,
1034 cntrl, cntrl,
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 cntrl, cntrl,
1038 cntrl, cntrl,
1039 space | blank | print, punct | print,
1040 punct | print, punct | print,
1041 punct | print, punct | print,
1042 punct | print, punct | print,
1043 punct | print, punct | print,
1044 punct | print, punct | print,
1045 punct | print, punct | print,
1046 punct | print, punct | print,
1047 digit | print | xdigit, digit | print | xdigit,
1048 digit | print | xdigit, digit | print | xdigit,
1049 digit | print | xdigit, digit | print | xdigit,
1050 digit | print | xdigit, digit | print | xdigit,
1051 digit | print | xdigit, digit | print | xdigit,
1052 punct | print, punct | print,
1053 punct | print, punct | print,
1054 punct | print, punct | print,
1055 punct | print, upper | xdigit | print | alpha,
1056 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1057 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1058 upper | xdigit | print | alpha, upper | print | alpha,
1059 upper | print | alpha, upper | print | alpha,
1060 upper | print | alpha, upper | print | alpha,
1061 upper | print | alpha, upper | print | alpha,
1062 upper | print | alpha, upper | print | alpha,
1063 upper | print | alpha, upper | print | alpha,
1064 upper | print | alpha, upper | print | alpha,
1065 upper | print | alpha, upper | print | alpha,
1066 upper | print | alpha, upper | print | alpha,
1067 upper | print | alpha, upper | print | alpha,
1068 upper | print | alpha, punct | print,
1069 punct | print, punct | print,
1070 punct | print, punct | print,
1071 punct | print, lower | xdigit | print | alpha,
1072 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1073 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1074 lower | xdigit | print | alpha, lower | print | alpha,
1075 lower | print | alpha, lower | print | alpha,
1076 lower | print | alpha, lower | print | alpha,
1077 lower | print | alpha, lower | print | alpha,
1078 lower | print | alpha, lower | print | alpha,
1079 lower | print | alpha, lower | print | alpha,
1080 lower | print | alpha, lower | print | alpha,
1081 lower | print | alpha, lower | print | alpha,
1082 lower | print | alpha, lower | print | alpha,
1083 lower | print | alpha, lower | print | alpha,
1084 lower | print | alpha, punct | print,
1085 punct | print, punct | print,
1086 punct | print, cntrl,
1087 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1088 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1089 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1090 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1091 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1092 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1093 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1094 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1095 };
1096 return builtin_table;
1097}
1098#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001099const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001100ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001101{
David Chisnall1d581062011-09-21 08:39:44 +00001102#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001103 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001104#elif defined(__NetBSD__)
1105 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001106#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001107 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001108#elif __sun__
1109 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001110#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001111 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnall1d581062011-09-21 08:39:44 +00001112// This is assumed to be safe, which is a nonsense assumption because we're
1113// going to end up dereferencing it later...
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001114#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001115 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001116#elif defined(_NEWLIB_VERSION)
1117 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1118 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001119#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001120 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001121#else
David Chisnall8074c342012-02-29 13:05:08 +00001122 // Platform not supported: abort so the person doing the port knows what to
1123 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001124# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001125 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001126 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001127 return NULL;
1128#endif
1129}
Marshall Clowb3f62842015-03-04 16:10:14 +00001130#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001131
Howard Hinnantd7a78632011-09-29 13:33:15 +00001132#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001133const int*
1134ctype<char>::__classic_lower_table() _NOEXCEPT
1135{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001136 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001137}
1138
1139const int*
1140ctype<char>::__classic_upper_table() _NOEXCEPT
1141{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001142 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001143}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001144#elif __NetBSD__
1145const short*
1146ctype<char>::__classic_lower_table() _NOEXCEPT
1147{
1148 return _C_tolower_tab_ + 1;
1149}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001150
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001151const short*
1152ctype<char>::__classic_upper_table() _NOEXCEPT
1153{
1154 return _C_toupper_tab_ + 1;
1155}
1156
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001157#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001158const int*
1159ctype<char>::__classic_lower_table() _NOEXCEPT
1160{
1161 return *__ctype_tolower_loc();
1162}
1163
1164const int*
1165ctype<char>::__classic_upper_table() _NOEXCEPT
1166{
1167 return *__ctype_toupper_loc();
1168}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001169#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001170
Howard Hinnantc51e1022010-05-11 19:42:16 +00001171// template <> class ctype_byname<char>
1172
1173ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1174 : ctype<char>(0, false, refs),
1175 __l(newlocale(LC_ALL_MASK, name, 0))
1176{
1177 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001178 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001179 " failed to construct for " + string(name));
1180}
1181
1182ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1183 : ctype<char>(0, false, refs),
1184 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1185{
1186 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001187 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001188 " failed to construct for " + name);
1189}
1190
1191ctype_byname<char>::~ctype_byname()
1192{
1193 freelocale(__l);
1194}
1195
1196char
1197ctype_byname<char>::do_toupper(char_type c) const
1198{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001199 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001200}
1201
1202const char*
1203ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1204{
1205 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001206 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001207 return low;
1208}
1209
1210char
1211ctype_byname<char>::do_tolower(char_type c) const
1212{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001213 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001214}
1215
1216const char*
1217ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1218{
1219 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001220 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001221 return low;
1222}
1223
1224// template <> class ctype_byname<wchar_t>
1225
1226ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1227 : ctype<wchar_t>(refs),
1228 __l(newlocale(LC_ALL_MASK, name, 0))
1229{
1230 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001231 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001232 " failed to construct for " + string(name));
1233}
1234
1235ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1236 : ctype<wchar_t>(refs),
1237 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1238{
1239 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001240 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001241 " failed to construct for " + name);
1242}
1243
1244ctype_byname<wchar_t>::~ctype_byname()
1245{
1246 freelocale(__l);
1247}
1248
1249bool
1250ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1251{
Alexis Huntc2017f12011-07-09 03:40:04 +00001252#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001253 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001254#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001255 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001256 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001257 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1258 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1259 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1260 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1261 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1262 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1263 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1264 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1265 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1266 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001267 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001268#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001269}
1270
1271const wchar_t*
1272ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1273{
1274 for (; low != high; ++low, ++vec)
1275 {
1276 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001277 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001278 else
1279 {
1280 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001281 wint_t ch = static_cast<wint_t>(*low);
1282 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001283 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001284#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001285 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001286 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001287#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001288 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001289 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001290 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001291 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001292 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001293 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001294#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001295 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001296 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001297#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001298 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001299 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001300 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001301 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001302#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001303 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001304 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001305#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001306#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001307 if (iswblank_l(ch, __l))
1308 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001309#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001310 }
1311 }
1312 return low;
1313}
1314
1315const wchar_t*
1316ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1317{
1318 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001319 {
1320#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001321 if (iswctype_l(*low, m, __l))
1322 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001323#else
Marshall Clowada0f732013-02-07 14:22:51 +00001324 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001325 if ((m & space) == space && iswspace_l(ch, __l)) break;
1326 if ((m & print) == print && iswprint_l(ch, __l)) break;
1327 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1328 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1329 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1330 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1331 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1332 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1333 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1334 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001335#endif
1336 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001337 return low;
1338}
1339
1340const wchar_t*
1341ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1342{
1343 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001344 {
1345#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001346 if (!iswctype_l(*low, m, __l))
1347 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001348#else
Marshall Clowada0f732013-02-07 14:22:51 +00001349 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001350 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1351 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1352 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1353 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1354 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1355 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1356 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1357 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1358 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1359 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001360 break;
1361#endif
1362 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001363 return low;
1364}
1365
1366wchar_t
1367ctype_byname<wchar_t>::do_toupper(char_type c) const
1368{
1369 return towupper_l(c, __l);
1370}
1371
1372const wchar_t*
1373ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1374{
1375 for (; low != high; ++low)
1376 *low = towupper_l(*low, __l);
1377 return low;
1378}
1379
1380wchar_t
1381ctype_byname<wchar_t>::do_tolower(char_type c) const
1382{
1383 return towlower_l(c, __l);
1384}
1385
1386const wchar_t*
1387ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1388{
1389 for (; low != high; ++low)
1390 *low = towlower_l(*low, __l);
1391 return low;
1392}
1393
1394wchar_t
1395ctype_byname<wchar_t>::do_widen(char c) const
1396{
Ben Craig3756b922016-03-09 15:39:39 +00001397 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001398}
1399
1400const char*
1401ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1402{
1403 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001404 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001405 return low;
1406}
1407
1408char
1409ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1410{
Ben Craig3756b922016-03-09 15:39:39 +00001411 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001412 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001413}
1414
1415const wchar_t*
1416ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1417{
1418 for (; low != high; ++low, ++dest)
1419 {
Ben Craig3756b922016-03-09 15:39:39 +00001420 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001421 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001422 }
1423 return low;
1424}
1425
1426// template <> class codecvt<char, char, mbstate_t>
1427
Howard Hinnantffb308e2010-08-22 00:03:27 +00001428locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001429
1430codecvt<char, char, mbstate_t>::~codecvt()
1431{
1432}
1433
1434codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001435codecvt<char, char, mbstate_t>::do_out(state_type&,
1436 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001437 extern_type* to, extern_type*, extern_type*& to_nxt) const
1438{
1439 frm_nxt = frm;
1440 to_nxt = to;
1441 return noconv;
1442}
1443
1444codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001445codecvt<char, char, mbstate_t>::do_in(state_type&,
1446 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001447 intern_type* to, intern_type*, intern_type*& to_nxt) const
1448{
1449 frm_nxt = frm;
1450 to_nxt = to;
1451 return noconv;
1452}
1453
1454codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001455codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001456 extern_type* to, extern_type*, extern_type*& to_nxt) const
1457{
1458 to_nxt = to;
1459 return noconv;
1460}
1461
1462int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001463codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001464{
1465 return 1;
1466}
1467
1468bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001469codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001470{
1471 return true;
1472}
1473
1474int
1475codecvt<char, char, mbstate_t>::do_length(state_type&,
1476 const extern_type* frm, const extern_type* end, size_t mx) const
1477{
Howard Hinnant28b24882011-12-01 20:21:04 +00001478 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001479}
1480
1481int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001482codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001483{
1484 return 1;
1485}
1486
1487// template <> class codecvt<wchar_t, char, mbstate_t>
1488
Howard Hinnantffb308e2010-08-22 00:03:27 +00001489locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001490
1491codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1492 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001493 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001494{
1495}
1496
1497codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1498 : locale::facet(refs),
1499 __l(newlocale(LC_ALL_MASK, nm, 0))
1500{
1501 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001502 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001503 " failed to construct for " + string(nm));
1504}
1505
1506codecvt<wchar_t, char, mbstate_t>::~codecvt()
1507{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001508 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001509 freelocale(__l);
1510}
1511
1512codecvt<wchar_t, char, mbstate_t>::result
1513codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001514 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001515 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1516{
1517 // look for first internal null in frm
1518 const intern_type* fend = frm;
1519 for (; fend != frm_end; ++fend)
1520 if (*fend == 0)
1521 break;
1522 // loop over all null-terminated sequences in frm
1523 to_nxt = to;
1524 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1525 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001526 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001527 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001528 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1529 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001530 if (n == size_t(-1))
1531 {
1532 // need to recover to_nxt
1533 for (to_nxt = to; frm != frm_nxt; ++frm)
1534 {
Ben Craig3756b922016-03-09 15:39:39 +00001535 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001536 if (n == size_t(-1))
1537 break;
1538 to_nxt += n;
1539 }
1540 frm_nxt = frm;
1541 return error;
1542 }
1543 if (n == 0)
1544 return partial;
1545 to_nxt += n;
1546 if (to_nxt == to_end)
1547 break;
1548 if (fend != frm_end) // set up next null terminated sequence
1549 {
1550 // Try to write the terminating null
1551 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001552 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001553 if (n == size_t(-1)) // on error
1554 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001555 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001556 return partial;
1557 for (extern_type* p = tmp; n; --n) // write it
1558 *to_nxt++ = *p++;
1559 ++frm_nxt;
1560 // look for next null in frm
1561 for (fend = frm_nxt; fend != frm_end; ++fend)
1562 if (*fend == 0)
1563 break;
1564 }
1565 }
1566 return frm_nxt == frm_end ? ok : partial;
1567}
1568
1569codecvt<wchar_t, char, mbstate_t>::result
1570codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001571 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001572 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1573{
1574 // look for first internal null in frm
1575 const extern_type* fend = frm;
1576 for (; fend != frm_end; ++fend)
1577 if (*fend == 0)
1578 break;
1579 // loop over all null-terminated sequences in frm
1580 to_nxt = to;
1581 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1582 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001583 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001584 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001585 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1586 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001587 if (n == size_t(-1))
1588 {
1589 // need to recover to_nxt
1590 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1591 {
Ben Craig3756b922016-03-09 15:39:39 +00001592 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1593 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001594 switch (n)
1595 {
1596 case 0:
1597 ++frm;
1598 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001599 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001600 frm_nxt = frm;
1601 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001602 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001603 frm_nxt = frm;
1604 return partial;
1605 default:
1606 frm += n;
1607 break;
1608 }
1609 }
1610 frm_nxt = frm;
1611 return frm_nxt == frm_end ? ok : partial;
1612 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001613 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001614 return error;
1615 to_nxt += n;
1616 if (to_nxt == to_end)
1617 break;
1618 if (fend != frm_end) // set up next null terminated sequence
1619 {
1620 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001621 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001622 if (n != 0) // on error
1623 return error;
1624 ++to_nxt;
1625 ++frm_nxt;
1626 // look for next null in frm
1627 for (fend = frm_nxt; fend != frm_end; ++fend)
1628 if (*fend == 0)
1629 break;
1630 }
1631 }
1632 return frm_nxt == frm_end ? ok : partial;
1633}
1634
1635codecvt<wchar_t, char, mbstate_t>::result
1636codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1637 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1638{
1639 to_nxt = to;
1640 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001641 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001642 if (n == size_t(-1) || n == 0) // on error
1643 return error;
1644 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001645 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001646 return partial;
1647 for (extern_type* p = tmp; n; --n) // write it
1648 *to_nxt++ = *p++;
1649 return ok;
1650}
1651
1652int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001653codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001654{
Ben Craig3756b922016-03-09 15:39:39 +00001655 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001656 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001657
1658 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001659 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001660 return 1; // which take more than 1 char to form a wchar_t
1661 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001662}
1663
1664bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001665codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001666{
1667 return false;
1668}
1669
1670int
1671codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1672 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1673{
1674 int nbytes = 0;
1675 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1676 {
Ben Craig3756b922016-03-09 15:39:39 +00001677 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001678 switch (n)
1679 {
1680 case 0:
1681 ++nbytes;
1682 ++frm;
1683 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001684 case size_t(-1):
1685 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001686 return nbytes;
1687 default:
1688 nbytes += n;
1689 frm += n;
1690 break;
1691 }
1692 }
1693 return nbytes;
1694}
1695
1696int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001697codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001698{
Ben Craig3756b922016-03-09 15:39:39 +00001699 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001700}
1701
1702// Valid UTF ranges
1703// UTF-32 UTF-16 UTF-8 # of code points
1704// first second first second third fourth
1705// 000000 - 00007F 0000 - 007F 00 - 7F 127
1706// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1707// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1708// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1709// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1710// 00D800 - 00DFFF invalid
1711// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1712// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1713// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1714// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1715
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001716static
1717codecvt_base::result
1718utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1719 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1720 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1721{
1722 frm_nxt = frm;
1723 to_nxt = to;
1724 if (mode & generate_header)
1725 {
1726 if (to_end-to_nxt < 3)
1727 return codecvt_base::partial;
1728 *to_nxt++ = static_cast<uint8_t>(0xEF);
1729 *to_nxt++ = static_cast<uint8_t>(0xBB);
1730 *to_nxt++ = static_cast<uint8_t>(0xBF);
1731 }
1732 for (; frm_nxt < frm_end; ++frm_nxt)
1733 {
1734 uint16_t wc1 = *frm_nxt;
1735 if (wc1 > Maxcode)
1736 return codecvt_base::error;
1737 if (wc1 < 0x0080)
1738 {
1739 if (to_end-to_nxt < 1)
1740 return codecvt_base::partial;
1741 *to_nxt++ = static_cast<uint8_t>(wc1);
1742 }
1743 else if (wc1 < 0x0800)
1744 {
1745 if (to_end-to_nxt < 2)
1746 return codecvt_base::partial;
1747 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1748 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1749 }
1750 else if (wc1 < 0xD800)
1751 {
1752 if (to_end-to_nxt < 3)
1753 return codecvt_base::partial;
1754 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1755 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1756 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1757 }
1758 else if (wc1 < 0xDC00)
1759 {
1760 if (frm_end-frm_nxt < 2)
1761 return codecvt_base::partial;
1762 uint16_t wc2 = frm_nxt[1];
1763 if ((wc2 & 0xFC00) != 0xDC00)
1764 return codecvt_base::error;
1765 if (to_end-to_nxt < 4)
1766 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001767 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1768 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001769 return codecvt_base::error;
1770 ++frm_nxt;
1771 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1772 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1773 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1774 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1775 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1776 }
1777 else if (wc1 < 0xE000)
1778 {
1779 return codecvt_base::error;
1780 }
1781 else
1782 {
1783 if (to_end-to_nxt < 3)
1784 return codecvt_base::partial;
1785 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1786 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1787 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1788 }
1789 }
1790 return codecvt_base::ok;
1791}
1792
1793static
1794codecvt_base::result
1795utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1796 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1797 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1798{
1799 frm_nxt = frm;
1800 to_nxt = to;
1801 if (mode & generate_header)
1802 {
1803 if (to_end-to_nxt < 3)
1804 return codecvt_base::partial;
1805 *to_nxt++ = static_cast<uint8_t>(0xEF);
1806 *to_nxt++ = static_cast<uint8_t>(0xBB);
1807 *to_nxt++ = static_cast<uint8_t>(0xBF);
1808 }
1809 for (; frm_nxt < frm_end; ++frm_nxt)
1810 {
1811 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1812 if (wc1 > Maxcode)
1813 return codecvt_base::error;
1814 if (wc1 < 0x0080)
1815 {
1816 if (to_end-to_nxt < 1)
1817 return codecvt_base::partial;
1818 *to_nxt++ = static_cast<uint8_t>(wc1);
1819 }
1820 else if (wc1 < 0x0800)
1821 {
1822 if (to_end-to_nxt < 2)
1823 return codecvt_base::partial;
1824 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1825 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1826 }
1827 else if (wc1 < 0xD800)
1828 {
1829 if (to_end-to_nxt < 3)
1830 return codecvt_base::partial;
1831 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1832 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1833 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1834 }
1835 else if (wc1 < 0xDC00)
1836 {
1837 if (frm_end-frm_nxt < 2)
1838 return codecvt_base::partial;
1839 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1840 if ((wc2 & 0xFC00) != 0xDC00)
1841 return codecvt_base::error;
1842 if (to_end-to_nxt < 4)
1843 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001844 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1845 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001846 return codecvt_base::error;
1847 ++frm_nxt;
1848 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1849 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1851 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1852 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1853 }
1854 else if (wc1 < 0xE000)
1855 {
1856 return codecvt_base::error;
1857 }
1858 else
1859 {
1860 if (to_end-to_nxt < 3)
1861 return codecvt_base::partial;
1862 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1863 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1864 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1865 }
1866 }
1867 return codecvt_base::ok;
1868}
1869
1870static
1871codecvt_base::result
1872utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1873 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1874 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1875{
1876 frm_nxt = frm;
1877 to_nxt = to;
1878 if (mode & consume_header)
1879 {
1880 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1881 frm_nxt[2] == 0xBF)
1882 frm_nxt += 3;
1883 }
1884 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1885 {
1886 uint8_t c1 = *frm_nxt;
1887 if (c1 > Maxcode)
1888 return codecvt_base::error;
1889 if (c1 < 0x80)
1890 {
1891 *to_nxt = static_cast<uint16_t>(c1);
1892 ++frm_nxt;
1893 }
1894 else if (c1 < 0xC2)
1895 {
1896 return codecvt_base::error;
1897 }
1898 else if (c1 < 0xE0)
1899 {
1900 if (frm_end-frm_nxt < 2)
1901 return codecvt_base::partial;
1902 uint8_t c2 = frm_nxt[1];
1903 if ((c2 & 0xC0) != 0x80)
1904 return codecvt_base::error;
1905 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1906 if (t > Maxcode)
1907 return codecvt_base::error;
1908 *to_nxt = t;
1909 frm_nxt += 2;
1910 }
1911 else if (c1 < 0xF0)
1912 {
1913 if (frm_end-frm_nxt < 3)
1914 return codecvt_base::partial;
1915 uint8_t c2 = frm_nxt[1];
1916 uint8_t c3 = frm_nxt[2];
1917 switch (c1)
1918 {
1919 case 0xE0:
1920 if ((c2 & 0xE0) != 0xA0)
1921 return codecvt_base::error;
1922 break;
1923 case 0xED:
1924 if ((c2 & 0xE0) != 0x80)
1925 return codecvt_base::error;
1926 break;
1927 default:
1928 if ((c2 & 0xC0) != 0x80)
1929 return codecvt_base::error;
1930 break;
1931 }
1932 if ((c3 & 0xC0) != 0x80)
1933 return codecvt_base::error;
1934 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1935 | ((c2 & 0x3F) << 6)
1936 | (c3 & 0x3F));
1937 if (t > Maxcode)
1938 return codecvt_base::error;
1939 *to_nxt = t;
1940 frm_nxt += 3;
1941 }
1942 else if (c1 < 0xF5)
1943 {
1944 if (frm_end-frm_nxt < 4)
1945 return codecvt_base::partial;
1946 uint8_t c2 = frm_nxt[1];
1947 uint8_t c3 = frm_nxt[2];
1948 uint8_t c4 = frm_nxt[3];
1949 switch (c1)
1950 {
1951 case 0xF0:
1952 if (!(0x90 <= c2 && c2 <= 0xBF))
1953 return codecvt_base::error;
1954 break;
1955 case 0xF4:
1956 if ((c2 & 0xF0) != 0x80)
1957 return codecvt_base::error;
1958 break;
1959 default:
1960 if ((c2 & 0xC0) != 0x80)
1961 return codecvt_base::error;
1962 break;
1963 }
1964 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1965 return codecvt_base::error;
1966 if (to_end-to_nxt < 2)
1967 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001968 if ((((c1 & 7UL) << 18) +
1969 ((c2 & 0x3FUL) << 12) +
1970 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001971 return codecvt_base::error;
1972 *to_nxt = static_cast<uint16_t>(
1973 0xD800
1974 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1975 | ((c2 & 0x0F) << 2)
1976 | ((c3 & 0x30) >> 4));
1977 *++to_nxt = static_cast<uint16_t>(
1978 0xDC00
1979 | ((c3 & 0x0F) << 6)
1980 | (c4 & 0x3F));
1981 frm_nxt += 4;
1982 }
1983 else
1984 {
1985 return codecvt_base::error;
1986 }
1987 }
1988 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1989}
1990
1991static
1992codecvt_base::result
1993utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1994 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1995 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1996{
1997 frm_nxt = frm;
1998 to_nxt = to;
1999 if (mode & consume_header)
2000 {
2001 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2002 frm_nxt[2] == 0xBF)
2003 frm_nxt += 3;
2004 }
2005 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2006 {
2007 uint8_t c1 = *frm_nxt;
2008 if (c1 > Maxcode)
2009 return codecvt_base::error;
2010 if (c1 < 0x80)
2011 {
2012 *to_nxt = static_cast<uint32_t>(c1);
2013 ++frm_nxt;
2014 }
2015 else if (c1 < 0xC2)
2016 {
2017 return codecvt_base::error;
2018 }
2019 else if (c1 < 0xE0)
2020 {
2021 if (frm_end-frm_nxt < 2)
2022 return codecvt_base::partial;
2023 uint8_t c2 = frm_nxt[1];
2024 if ((c2 & 0xC0) != 0x80)
2025 return codecvt_base::error;
2026 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2027 if (t > Maxcode)
2028 return codecvt_base::error;
2029 *to_nxt = static_cast<uint32_t>(t);
2030 frm_nxt += 2;
2031 }
2032 else if (c1 < 0xF0)
2033 {
2034 if (frm_end-frm_nxt < 3)
2035 return codecvt_base::partial;
2036 uint8_t c2 = frm_nxt[1];
2037 uint8_t c3 = frm_nxt[2];
2038 switch (c1)
2039 {
2040 case 0xE0:
2041 if ((c2 & 0xE0) != 0xA0)
2042 return codecvt_base::error;
2043 break;
2044 case 0xED:
2045 if ((c2 & 0xE0) != 0x80)
2046 return codecvt_base::error;
2047 break;
2048 default:
2049 if ((c2 & 0xC0) != 0x80)
2050 return codecvt_base::error;
2051 break;
2052 }
2053 if ((c3 & 0xC0) != 0x80)
2054 return codecvt_base::error;
2055 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2056 | ((c2 & 0x3F) << 6)
2057 | (c3 & 0x3F));
2058 if (t > Maxcode)
2059 return codecvt_base::error;
2060 *to_nxt = static_cast<uint32_t>(t);
2061 frm_nxt += 3;
2062 }
2063 else if (c1 < 0xF5)
2064 {
2065 if (frm_end-frm_nxt < 4)
2066 return codecvt_base::partial;
2067 uint8_t c2 = frm_nxt[1];
2068 uint8_t c3 = frm_nxt[2];
2069 uint8_t c4 = frm_nxt[3];
2070 switch (c1)
2071 {
2072 case 0xF0:
2073 if (!(0x90 <= c2 && c2 <= 0xBF))
2074 return codecvt_base::error;
2075 break;
2076 case 0xF4:
2077 if ((c2 & 0xF0) != 0x80)
2078 return codecvt_base::error;
2079 break;
2080 default:
2081 if ((c2 & 0xC0) != 0x80)
2082 return codecvt_base::error;
2083 break;
2084 }
2085 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2086 return codecvt_base::error;
2087 if (to_end-to_nxt < 2)
2088 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002089 if ((((c1 & 7UL) << 18) +
2090 ((c2 & 0x3FUL) << 12) +
2091 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002092 return codecvt_base::error;
2093 *to_nxt = static_cast<uint32_t>(
2094 0xD800
2095 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2096 | ((c2 & 0x0F) << 2)
2097 | ((c3 & 0x30) >> 4));
2098 *++to_nxt = static_cast<uint32_t>(
2099 0xDC00
2100 | ((c3 & 0x0F) << 6)
2101 | (c4 & 0x3F));
2102 frm_nxt += 4;
2103 }
2104 else
2105 {
2106 return codecvt_base::error;
2107 }
2108 }
2109 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2110}
2111
2112static
2113int
2114utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2115 size_t mx, unsigned long Maxcode = 0x10FFFF,
2116 codecvt_mode mode = codecvt_mode(0))
2117{
2118 const uint8_t* frm_nxt = frm;
2119 if (mode & consume_header)
2120 {
2121 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2122 frm_nxt[2] == 0xBF)
2123 frm_nxt += 3;
2124 }
2125 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2126 {
2127 uint8_t c1 = *frm_nxt;
2128 if (c1 > Maxcode)
2129 break;
2130 if (c1 < 0x80)
2131 {
2132 ++frm_nxt;
2133 }
2134 else if (c1 < 0xC2)
2135 {
2136 break;
2137 }
2138 else if (c1 < 0xE0)
2139 {
2140 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2141 break;
2142 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2143 if (t > Maxcode)
2144 break;
2145 frm_nxt += 2;
2146 }
2147 else if (c1 < 0xF0)
2148 {
2149 if (frm_end-frm_nxt < 3)
2150 break;
2151 uint8_t c2 = frm_nxt[1];
2152 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002153 switch (c1)
2154 {
2155 case 0xE0:
2156 if ((c2 & 0xE0) != 0xA0)
2157 return static_cast<int>(frm_nxt - frm);
2158 break;
2159 case 0xED:
2160 if ((c2 & 0xE0) != 0x80)
2161 return static_cast<int>(frm_nxt - frm);
2162 break;
2163 default:
2164 if ((c2 & 0xC0) != 0x80)
2165 return static_cast<int>(frm_nxt - frm);
2166 break;
2167 }
2168 if ((c3 & 0xC0) != 0x80)
2169 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002170 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002171 break;
2172 frm_nxt += 3;
2173 }
2174 else if (c1 < 0xF5)
2175 {
2176 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2177 break;
2178 uint8_t c2 = frm_nxt[1];
2179 uint8_t c3 = frm_nxt[2];
2180 uint8_t c4 = frm_nxt[3];
2181 switch (c1)
2182 {
2183 case 0xF0:
2184 if (!(0x90 <= c2 && c2 <= 0xBF))
2185 return static_cast<int>(frm_nxt - frm);
2186 break;
2187 case 0xF4:
2188 if ((c2 & 0xF0) != 0x80)
2189 return static_cast<int>(frm_nxt - frm);
2190 break;
2191 default:
2192 if ((c2 & 0xC0) != 0x80)
2193 return static_cast<int>(frm_nxt - frm);
2194 break;
2195 }
2196 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2197 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002198 if ((((c1 & 7UL) << 18) +
2199 ((c2 & 0x3FUL) << 12) +
2200 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002201 break;
2202 ++nchar16_t;
2203 frm_nxt += 4;
2204 }
2205 else
2206 {
2207 break;
2208 }
2209 }
2210 return static_cast<int>(frm_nxt - frm);
2211}
2212
2213static
2214codecvt_base::result
2215ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2216 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2217 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2218{
2219 frm_nxt = frm;
2220 to_nxt = to;
2221 if (mode & generate_header)
2222 {
2223 if (to_end-to_nxt < 3)
2224 return codecvt_base::partial;
2225 *to_nxt++ = static_cast<uint8_t>(0xEF);
2226 *to_nxt++ = static_cast<uint8_t>(0xBB);
2227 *to_nxt++ = static_cast<uint8_t>(0xBF);
2228 }
2229 for (; frm_nxt < frm_end; ++frm_nxt)
2230 {
2231 uint32_t wc = *frm_nxt;
2232 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2233 return codecvt_base::error;
2234 if (wc < 0x000080)
2235 {
2236 if (to_end-to_nxt < 1)
2237 return codecvt_base::partial;
2238 *to_nxt++ = static_cast<uint8_t>(wc);
2239 }
2240 else if (wc < 0x000800)
2241 {
2242 if (to_end-to_nxt < 2)
2243 return codecvt_base::partial;
2244 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2245 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2246 }
2247 else if (wc < 0x010000)
2248 {
2249 if (to_end-to_nxt < 3)
2250 return codecvt_base::partial;
2251 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2252 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2253 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2254 }
2255 else // if (wc < 0x110000)
2256 {
2257 if (to_end-to_nxt < 4)
2258 return codecvt_base::partial;
2259 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2260 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2261 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2262 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2263 }
2264 }
2265 return codecvt_base::ok;
2266}
2267
2268static
2269codecvt_base::result
2270utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2271 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2272 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2273{
2274 frm_nxt = frm;
2275 to_nxt = to;
2276 if (mode & consume_header)
2277 {
2278 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2279 frm_nxt[2] == 0xBF)
2280 frm_nxt += 3;
2281 }
2282 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2283 {
2284 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2285 if (c1 < 0x80)
2286 {
2287 if (c1 > Maxcode)
2288 return codecvt_base::error;
2289 *to_nxt = static_cast<uint32_t>(c1);
2290 ++frm_nxt;
2291 }
2292 else if (c1 < 0xC2)
2293 {
2294 return codecvt_base::error;
2295 }
2296 else if (c1 < 0xE0)
2297 {
2298 if (frm_end-frm_nxt < 2)
2299 return codecvt_base::partial;
2300 uint8_t c2 = frm_nxt[1];
2301 if ((c2 & 0xC0) != 0x80)
2302 return codecvt_base::error;
2303 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2304 | (c2 & 0x3F));
2305 if (t > Maxcode)
2306 return codecvt_base::error;
2307 *to_nxt = t;
2308 frm_nxt += 2;
2309 }
2310 else if (c1 < 0xF0)
2311 {
2312 if (frm_end-frm_nxt < 3)
2313 return codecvt_base::partial;
2314 uint8_t c2 = frm_nxt[1];
2315 uint8_t c3 = frm_nxt[2];
2316 switch (c1)
2317 {
2318 case 0xE0:
2319 if ((c2 & 0xE0) != 0xA0)
2320 return codecvt_base::error;
2321 break;
2322 case 0xED:
2323 if ((c2 & 0xE0) != 0x80)
2324 return codecvt_base::error;
2325 break;
2326 default:
2327 if ((c2 & 0xC0) != 0x80)
2328 return codecvt_base::error;
2329 break;
2330 }
2331 if ((c3 & 0xC0) != 0x80)
2332 return codecvt_base::error;
2333 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2334 | ((c2 & 0x3F) << 6)
2335 | (c3 & 0x3F));
2336 if (t > Maxcode)
2337 return codecvt_base::error;
2338 *to_nxt = t;
2339 frm_nxt += 3;
2340 }
2341 else if (c1 < 0xF5)
2342 {
2343 if (frm_end-frm_nxt < 4)
2344 return codecvt_base::partial;
2345 uint8_t c2 = frm_nxt[1];
2346 uint8_t c3 = frm_nxt[2];
2347 uint8_t c4 = frm_nxt[3];
2348 switch (c1)
2349 {
2350 case 0xF0:
2351 if (!(0x90 <= c2 && c2 <= 0xBF))
2352 return codecvt_base::error;
2353 break;
2354 case 0xF4:
2355 if ((c2 & 0xF0) != 0x80)
2356 return codecvt_base::error;
2357 break;
2358 default:
2359 if ((c2 & 0xC0) != 0x80)
2360 return codecvt_base::error;
2361 break;
2362 }
2363 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2364 return codecvt_base::error;
2365 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2366 | ((c2 & 0x3F) << 12)
2367 | ((c3 & 0x3F) << 6)
2368 | (c4 & 0x3F));
2369 if (t > Maxcode)
2370 return codecvt_base::error;
2371 *to_nxt = t;
2372 frm_nxt += 4;
2373 }
2374 else
2375 {
2376 return codecvt_base::error;
2377 }
2378 }
2379 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2380}
2381
2382static
2383int
2384utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2385 size_t mx, unsigned long Maxcode = 0x10FFFF,
2386 codecvt_mode mode = codecvt_mode(0))
2387{
2388 const uint8_t* frm_nxt = frm;
2389 if (mode & consume_header)
2390 {
2391 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2392 frm_nxt[2] == 0xBF)
2393 frm_nxt += 3;
2394 }
2395 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2396 {
2397 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2398 if (c1 < 0x80)
2399 {
2400 if (c1 > Maxcode)
2401 break;
2402 ++frm_nxt;
2403 }
2404 else if (c1 < 0xC2)
2405 {
2406 break;
2407 }
2408 else if (c1 < 0xE0)
2409 {
2410 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2411 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002412 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002413 break;
2414 frm_nxt += 2;
2415 }
2416 else if (c1 < 0xF0)
2417 {
2418 if (frm_end-frm_nxt < 3)
2419 break;
2420 uint8_t c2 = frm_nxt[1];
2421 uint8_t c3 = frm_nxt[2];
2422 switch (c1)
2423 {
2424 case 0xE0:
2425 if ((c2 & 0xE0) != 0xA0)
2426 return static_cast<int>(frm_nxt - frm);
2427 break;
2428 case 0xED:
2429 if ((c2 & 0xE0) != 0x80)
2430 return static_cast<int>(frm_nxt - frm);
2431 break;
2432 default:
2433 if ((c2 & 0xC0) != 0x80)
2434 return static_cast<int>(frm_nxt - frm);
2435 break;
2436 }
2437 if ((c3 & 0xC0) != 0x80)
2438 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002439 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002440 break;
2441 frm_nxt += 3;
2442 }
2443 else if (c1 < 0xF5)
2444 {
2445 if (frm_end-frm_nxt < 4)
2446 break;
2447 uint8_t c2 = frm_nxt[1];
2448 uint8_t c3 = frm_nxt[2];
2449 uint8_t c4 = frm_nxt[3];
2450 switch (c1)
2451 {
2452 case 0xF0:
2453 if (!(0x90 <= c2 && c2 <= 0xBF))
2454 return static_cast<int>(frm_nxt - frm);
2455 break;
2456 case 0xF4:
2457 if ((c2 & 0xF0) != 0x80)
2458 return static_cast<int>(frm_nxt - frm);
2459 break;
2460 default:
2461 if ((c2 & 0xC0) != 0x80)
2462 return static_cast<int>(frm_nxt - frm);
2463 break;
2464 }
2465 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2466 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002467 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2468 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002469 break;
2470 frm_nxt += 4;
2471 }
2472 else
2473 {
2474 break;
2475 }
2476 }
2477 return static_cast<int>(frm_nxt - frm);
2478}
2479
2480static
2481codecvt_base::result
2482ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2483 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2484 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2485{
2486 frm_nxt = frm;
2487 to_nxt = to;
2488 if (mode & generate_header)
2489 {
2490 if (to_end-to_nxt < 3)
2491 return codecvt_base::partial;
2492 *to_nxt++ = static_cast<uint8_t>(0xEF);
2493 *to_nxt++ = static_cast<uint8_t>(0xBB);
2494 *to_nxt++ = static_cast<uint8_t>(0xBF);
2495 }
2496 for (; frm_nxt < frm_end; ++frm_nxt)
2497 {
2498 uint16_t wc = *frm_nxt;
2499 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2500 return codecvt_base::error;
2501 if (wc < 0x0080)
2502 {
2503 if (to_end-to_nxt < 1)
2504 return codecvt_base::partial;
2505 *to_nxt++ = static_cast<uint8_t>(wc);
2506 }
2507 else if (wc < 0x0800)
2508 {
2509 if (to_end-to_nxt < 2)
2510 return codecvt_base::partial;
2511 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2512 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2513 }
2514 else // if (wc <= 0xFFFF)
2515 {
2516 if (to_end-to_nxt < 3)
2517 return codecvt_base::partial;
2518 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2519 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2520 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2521 }
2522 }
2523 return codecvt_base::ok;
2524}
2525
2526static
2527codecvt_base::result
2528utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2529 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2530 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2531{
2532 frm_nxt = frm;
2533 to_nxt = to;
2534 if (mode & consume_header)
2535 {
2536 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2537 frm_nxt[2] == 0xBF)
2538 frm_nxt += 3;
2539 }
2540 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2541 {
2542 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2543 if (c1 < 0x80)
2544 {
2545 if (c1 > Maxcode)
2546 return codecvt_base::error;
2547 *to_nxt = static_cast<uint16_t>(c1);
2548 ++frm_nxt;
2549 }
2550 else if (c1 < 0xC2)
2551 {
2552 return codecvt_base::error;
2553 }
2554 else if (c1 < 0xE0)
2555 {
2556 if (frm_end-frm_nxt < 2)
2557 return codecvt_base::partial;
2558 uint8_t c2 = frm_nxt[1];
2559 if ((c2 & 0xC0) != 0x80)
2560 return codecvt_base::error;
2561 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2562 | (c2 & 0x3F));
2563 if (t > Maxcode)
2564 return codecvt_base::error;
2565 *to_nxt = t;
2566 frm_nxt += 2;
2567 }
2568 else if (c1 < 0xF0)
2569 {
2570 if (frm_end-frm_nxt < 3)
2571 return codecvt_base::partial;
2572 uint8_t c2 = frm_nxt[1];
2573 uint8_t c3 = frm_nxt[2];
2574 switch (c1)
2575 {
2576 case 0xE0:
2577 if ((c2 & 0xE0) != 0xA0)
2578 return codecvt_base::error;
2579 break;
2580 case 0xED:
2581 if ((c2 & 0xE0) != 0x80)
2582 return codecvt_base::error;
2583 break;
2584 default:
2585 if ((c2 & 0xC0) != 0x80)
2586 return codecvt_base::error;
2587 break;
2588 }
2589 if ((c3 & 0xC0) != 0x80)
2590 return codecvt_base::error;
2591 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2592 | ((c2 & 0x3F) << 6)
2593 | (c3 & 0x3F));
2594 if (t > Maxcode)
2595 return codecvt_base::error;
2596 *to_nxt = t;
2597 frm_nxt += 3;
2598 }
2599 else
2600 {
2601 return codecvt_base::error;
2602 }
2603 }
2604 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2605}
2606
2607static
2608int
2609utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2610 size_t mx, unsigned long Maxcode = 0x10FFFF,
2611 codecvt_mode mode = codecvt_mode(0))
2612{
2613 const uint8_t* frm_nxt = frm;
2614 if (mode & consume_header)
2615 {
2616 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2617 frm_nxt[2] == 0xBF)
2618 frm_nxt += 3;
2619 }
2620 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2621 {
2622 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2623 if (c1 < 0x80)
2624 {
2625 if (c1 > Maxcode)
2626 break;
2627 ++frm_nxt;
2628 }
2629 else if (c1 < 0xC2)
2630 {
2631 break;
2632 }
2633 else if (c1 < 0xE0)
2634 {
2635 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2636 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002637 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002638 break;
2639 frm_nxt += 2;
2640 }
2641 else if (c1 < 0xF0)
2642 {
2643 if (frm_end-frm_nxt < 3)
2644 break;
2645 uint8_t c2 = frm_nxt[1];
2646 uint8_t c3 = frm_nxt[2];
2647 switch (c1)
2648 {
2649 case 0xE0:
2650 if ((c2 & 0xE0) != 0xA0)
2651 return static_cast<int>(frm_nxt - frm);
2652 break;
2653 case 0xED:
2654 if ((c2 & 0xE0) != 0x80)
2655 return static_cast<int>(frm_nxt - frm);
2656 break;
2657 default:
2658 if ((c2 & 0xC0) != 0x80)
2659 return static_cast<int>(frm_nxt - frm);
2660 break;
2661 }
2662 if ((c3 & 0xC0) != 0x80)
2663 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002664 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002665 break;
2666 frm_nxt += 3;
2667 }
2668 else
2669 {
2670 break;
2671 }
2672 }
2673 return static_cast<int>(frm_nxt - frm);
2674}
2675
2676static
2677codecvt_base::result
2678ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2679 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2680 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2681{
2682 frm_nxt = frm;
2683 to_nxt = to;
2684 if (mode & generate_header)
2685 {
2686 if (to_end-to_nxt < 2)
2687 return codecvt_base::partial;
2688 *to_nxt++ = static_cast<uint8_t>(0xFE);
2689 *to_nxt++ = static_cast<uint8_t>(0xFF);
2690 }
2691 for (; frm_nxt < frm_end; ++frm_nxt)
2692 {
2693 uint32_t wc = *frm_nxt;
2694 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2695 return codecvt_base::error;
2696 if (wc < 0x010000)
2697 {
2698 if (to_end-to_nxt < 2)
2699 return codecvt_base::partial;
2700 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2701 *to_nxt++ = static_cast<uint8_t>(wc);
2702 }
2703 else
2704 {
2705 if (to_end-to_nxt < 4)
2706 return codecvt_base::partial;
2707 uint16_t t = static_cast<uint16_t>(
2708 0xD800
2709 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2710 | ((wc & 0x00FC00) >> 10));
2711 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2712 *to_nxt++ = static_cast<uint8_t>(t);
2713 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2714 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2715 *to_nxt++ = static_cast<uint8_t>(t);
2716 }
2717 }
2718 return codecvt_base::ok;
2719}
2720
2721static
2722codecvt_base::result
2723utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2724 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2725 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2726{
2727 frm_nxt = frm;
2728 to_nxt = to;
2729 if (mode & consume_header)
2730 {
2731 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2732 frm_nxt += 2;
2733 }
2734 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2735 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002736 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002737 if ((c1 & 0xFC00) == 0xDC00)
2738 return codecvt_base::error;
2739 if ((c1 & 0xFC00) != 0xD800)
2740 {
2741 if (c1 > Maxcode)
2742 return codecvt_base::error;
2743 *to_nxt = static_cast<uint32_t>(c1);
2744 frm_nxt += 2;
2745 }
2746 else
2747 {
2748 if (frm_end-frm_nxt < 4)
2749 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002750 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002751 if ((c2 & 0xFC00) != 0xDC00)
2752 return codecvt_base::error;
2753 uint32_t t = static_cast<uint32_t>(
2754 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2755 | ((c1 & 0x003F) << 10)
2756 | (c2 & 0x03FF));
2757 if (t > Maxcode)
2758 return codecvt_base::error;
2759 *to_nxt = t;
2760 frm_nxt += 4;
2761 }
2762 }
2763 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2764}
2765
2766static
2767int
2768utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2769 size_t mx, unsigned long Maxcode = 0x10FFFF,
2770 codecvt_mode mode = codecvt_mode(0))
2771{
2772 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002773 if (mode & consume_header)
2774 {
2775 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2776 frm_nxt += 2;
2777 }
2778 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2779 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002780 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002781 if ((c1 & 0xFC00) == 0xDC00)
2782 break;
2783 if ((c1 & 0xFC00) != 0xD800)
2784 {
2785 if (c1 > Maxcode)
2786 break;
2787 frm_nxt += 2;
2788 }
2789 else
2790 {
2791 if (frm_end-frm_nxt < 4)
2792 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002793 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002794 if ((c2 & 0xFC00) != 0xDC00)
2795 break;
2796 uint32_t t = static_cast<uint32_t>(
2797 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2798 | ((c1 & 0x003F) << 10)
2799 | (c2 & 0x03FF));
2800 if (t > Maxcode)
2801 break;
2802 frm_nxt += 4;
2803 }
2804 }
2805 return static_cast<int>(frm_nxt - frm);
2806}
2807
2808static
2809codecvt_base::result
2810ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2811 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2812 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2813{
2814 frm_nxt = frm;
2815 to_nxt = to;
2816 if (mode & generate_header)
2817 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002818 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002819 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002820 *to_nxt++ = static_cast<uint8_t>(0xFF);
2821 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002822 }
2823 for (; frm_nxt < frm_end; ++frm_nxt)
2824 {
2825 uint32_t wc = *frm_nxt;
2826 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2827 return codecvt_base::error;
2828 if (wc < 0x010000)
2829 {
2830 if (to_end-to_nxt < 2)
2831 return codecvt_base::partial;
2832 *to_nxt++ = static_cast<uint8_t>(wc);
2833 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2834 }
2835 else
2836 {
2837 if (to_end-to_nxt < 4)
2838 return codecvt_base::partial;
2839 uint16_t t = static_cast<uint16_t>(
2840 0xD800
2841 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2842 | ((wc & 0x00FC00) >> 10));
2843 *to_nxt++ = static_cast<uint8_t>(t);
2844 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2845 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2846 *to_nxt++ = static_cast<uint8_t>(t);
2847 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2848 }
2849 }
2850 return codecvt_base::ok;
2851}
2852
2853static
2854codecvt_base::result
2855utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2856 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2857 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2858{
2859 frm_nxt = frm;
2860 to_nxt = to;
2861 if (mode & consume_header)
2862 {
2863 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2864 frm_nxt += 2;
2865 }
2866 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2867 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002868 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002869 if ((c1 & 0xFC00) == 0xDC00)
2870 return codecvt_base::error;
2871 if ((c1 & 0xFC00) != 0xD800)
2872 {
2873 if (c1 > Maxcode)
2874 return codecvt_base::error;
2875 *to_nxt = static_cast<uint32_t>(c1);
2876 frm_nxt += 2;
2877 }
2878 else
2879 {
2880 if (frm_end-frm_nxt < 4)
2881 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002882 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002883 if ((c2 & 0xFC00) != 0xDC00)
2884 return codecvt_base::error;
2885 uint32_t t = static_cast<uint32_t>(
2886 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2887 | ((c1 & 0x003F) << 10)
2888 | (c2 & 0x03FF));
2889 if (t > Maxcode)
2890 return codecvt_base::error;
2891 *to_nxt = t;
2892 frm_nxt += 4;
2893 }
2894 }
2895 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2896}
2897
2898static
2899int
2900utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2901 size_t mx, unsigned long Maxcode = 0x10FFFF,
2902 codecvt_mode mode = codecvt_mode(0))
2903{
2904 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002905 if (mode & consume_header)
2906 {
2907 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2908 frm_nxt += 2;
2909 }
2910 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2911 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002912 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002913 if ((c1 & 0xFC00) == 0xDC00)
2914 break;
2915 if ((c1 & 0xFC00) != 0xD800)
2916 {
2917 if (c1 > Maxcode)
2918 break;
2919 frm_nxt += 2;
2920 }
2921 else
2922 {
2923 if (frm_end-frm_nxt < 4)
2924 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002925 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002926 if ((c2 & 0xFC00) != 0xDC00)
2927 break;
2928 uint32_t t = static_cast<uint32_t>(
2929 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2930 | ((c1 & 0x003F) << 10)
2931 | (c2 & 0x03FF));
2932 if (t > Maxcode)
2933 break;
2934 frm_nxt += 4;
2935 }
2936 }
2937 return static_cast<int>(frm_nxt - frm);
2938}
2939
2940static
2941codecvt_base::result
2942ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2943 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2944 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2945{
2946 frm_nxt = frm;
2947 to_nxt = to;
2948 if (mode & generate_header)
2949 {
2950 if (to_end-to_nxt < 2)
2951 return codecvt_base::partial;
2952 *to_nxt++ = static_cast<uint8_t>(0xFE);
2953 *to_nxt++ = static_cast<uint8_t>(0xFF);
2954 }
2955 for (; frm_nxt < frm_end; ++frm_nxt)
2956 {
2957 uint16_t wc = *frm_nxt;
2958 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2959 return codecvt_base::error;
2960 if (to_end-to_nxt < 2)
2961 return codecvt_base::partial;
2962 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2963 *to_nxt++ = static_cast<uint8_t>(wc);
2964 }
2965 return codecvt_base::ok;
2966}
2967
2968static
2969codecvt_base::result
2970utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2971 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2972 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2973{
2974 frm_nxt = frm;
2975 to_nxt = to;
2976 if (mode & consume_header)
2977 {
2978 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2979 frm_nxt += 2;
2980 }
2981 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2982 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002983 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002984 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2985 return codecvt_base::error;
2986 *to_nxt = c1;
2987 frm_nxt += 2;
2988 }
2989 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2990}
2991
2992static
2993int
2994utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2995 size_t mx, unsigned long Maxcode = 0x10FFFF,
2996 codecvt_mode mode = codecvt_mode(0))
2997{
2998 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002999 if (mode & consume_header)
3000 {
3001 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3002 frm_nxt += 2;
3003 }
3004 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3005 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003006 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003007 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3008 break;
3009 frm_nxt += 2;
3010 }
3011 return static_cast<int>(frm_nxt - frm);
3012}
3013
3014static
3015codecvt_base::result
3016ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3017 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3018 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3019{
3020 frm_nxt = frm;
3021 to_nxt = to;
3022 if (mode & generate_header)
3023 {
3024 if (to_end-to_nxt < 2)
3025 return codecvt_base::partial;
3026 *to_nxt++ = static_cast<uint8_t>(0xFF);
3027 *to_nxt++ = static_cast<uint8_t>(0xFE);
3028 }
3029 for (; frm_nxt < frm_end; ++frm_nxt)
3030 {
3031 uint16_t wc = *frm_nxt;
3032 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3033 return codecvt_base::error;
3034 if (to_end-to_nxt < 2)
3035 return codecvt_base::partial;
3036 *to_nxt++ = static_cast<uint8_t>(wc);
3037 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3038 }
3039 return codecvt_base::ok;
3040}
3041
3042static
3043codecvt_base::result
3044utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3045 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3046 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3047{
3048 frm_nxt = frm;
3049 to_nxt = to;
3050 if (mode & consume_header)
3051 {
3052 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3053 frm_nxt += 2;
3054 }
3055 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3056 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003057 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003058 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3059 return codecvt_base::error;
3060 *to_nxt = c1;
3061 frm_nxt += 2;
3062 }
3063 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3064}
3065
3066static
3067int
3068utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3069 size_t mx, unsigned long Maxcode = 0x10FFFF,
3070 codecvt_mode mode = codecvt_mode(0))
3071{
3072 const uint8_t* frm_nxt = frm;
3073 frm_nxt = frm;
3074 if (mode & consume_header)
3075 {
3076 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3077 frm_nxt += 2;
3078 }
3079 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3080 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003081 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003082 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3083 break;
3084 frm_nxt += 2;
3085 }
3086 return static_cast<int>(frm_nxt - frm);
3087}
3088
Howard Hinnantc51e1022010-05-11 19:42:16 +00003089// template <> class codecvt<char16_t, char, mbstate_t>
3090
Howard Hinnantffb308e2010-08-22 00:03:27 +00003091locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003092
3093codecvt<char16_t, char, mbstate_t>::~codecvt()
3094{
3095}
3096
3097codecvt<char16_t, char, mbstate_t>::result
3098codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003099 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003100 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3101{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003102 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3103 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3104 const uint16_t* _frm_nxt = _frm;
3105 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3106 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3107 uint8_t* _to_nxt = _to;
3108 result r = utf16_to_utf8(_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 Hinnantc51e1022010-05-11 19:42:16 +00003112}
3113
3114codecvt<char16_t, char, mbstate_t>::result
3115codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003116 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003117 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3118{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003119 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3120 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3121 const uint8_t* _frm_nxt = _frm;
3122 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3123 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3124 uint16_t* _to_nxt = _to;
3125 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3126 frm_nxt = frm + (_frm_nxt - _frm);
3127 to_nxt = to + (_to_nxt - _to);
3128 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003129}
3130
3131codecvt<char16_t, char, mbstate_t>::result
3132codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3133 extern_type* to, extern_type*, extern_type*& to_nxt) const
3134{
3135 to_nxt = to;
3136 return noconv;
3137}
3138
3139int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003140codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003141{
3142 return 0;
3143}
3144
3145bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003146codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003147{
3148 return false;
3149}
3150
3151int
3152codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3153 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3154{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003155 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3156 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3157 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003158}
3159
3160int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003161codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003162{
3163 return 4;
3164}
3165
3166// template <> class codecvt<char32_t, char, mbstate_t>
3167
Howard Hinnantffb308e2010-08-22 00:03:27 +00003168locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003169
3170codecvt<char32_t, char, mbstate_t>::~codecvt()
3171{
3172}
3173
3174codecvt<char32_t, char, mbstate_t>::result
3175codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003176 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003177 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3178{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003179 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3180 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3181 const uint32_t* _frm_nxt = _frm;
3182 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3183 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3184 uint8_t* _to_nxt = _to;
3185 result r = ucs4_to_utf8(_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 Hinnantc51e1022010-05-11 19:42:16 +00003189}
3190
3191codecvt<char32_t, char, mbstate_t>::result
3192codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003193 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003194 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3195{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003196 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3197 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3198 const uint8_t* _frm_nxt = _frm;
3199 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3200 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3201 uint32_t* _to_nxt = _to;
3202 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3203 frm_nxt = frm + (_frm_nxt - _frm);
3204 to_nxt = to + (_to_nxt - _to);
3205 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003206}
3207
3208codecvt<char32_t, char, mbstate_t>::result
3209codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3210 extern_type* to, extern_type*, extern_type*& to_nxt) const
3211{
3212 to_nxt = to;
3213 return noconv;
3214}
3215
3216int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003217codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003218{
3219 return 0;
3220}
3221
3222bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003223codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003224{
3225 return false;
3226}
3227
3228int
3229codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3230 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3231{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003232 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3233 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3234 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003235}
3236
3237int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003238codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003239{
3240 return 4;
3241}
3242
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003243// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003244
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003245__codecvt_utf8<wchar_t>::result
3246__codecvt_utf8<wchar_t>::do_out(state_type&,
3247 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003248 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3249{
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003250#if _WIN32
3251 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3252 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3253 const uint16_t* _frm_nxt = _frm;
3254#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003255 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3256 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3257 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003258#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003259 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3260 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3261 uint8_t* _to_nxt = _to;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003262#if _WIN32
3263 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3264 _Maxcode_, _Mode_);
3265#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003266 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3267 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003268#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003269 frm_nxt = frm + (_frm_nxt - _frm);
3270 to_nxt = to + (_to_nxt - _to);
3271 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003272}
3273
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003274__codecvt_utf8<wchar_t>::result
3275__codecvt_utf8<wchar_t>::do_in(state_type&,
3276 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003277 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3278{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003279 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3280 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3281 const uint8_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003282#if _WIN32
3283 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3284 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3285 uint16_t* _to_nxt = _to;
3286 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3287 _Maxcode_, _Mode_);
3288#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003289 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3290 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3291 uint32_t* _to_nxt = _to;
3292 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3293 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003294#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003295 frm_nxt = frm + (_frm_nxt - _frm);
3296 to_nxt = to + (_to_nxt - _to);
3297 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003298}
3299
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003300__codecvt_utf8<wchar_t>::result
3301__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003302 extern_type* to, extern_type*, extern_type*& to_nxt) const
3303{
3304 to_nxt = to;
3305 return noconv;
3306}
3307
3308int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003309__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003310{
3311 return 0;
3312}
3313
3314bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003315__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003316{
3317 return false;
3318}
3319
3320int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003321__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003322 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3323{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003324 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3325 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3326 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003327}
3328
3329int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003330__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003331{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003332 if (_Mode_ & consume_header)
3333 return 7;
3334 return 4;
3335}
3336
3337// __codecvt_utf8<char16_t>
3338
3339__codecvt_utf8<char16_t>::result
3340__codecvt_utf8<char16_t>::do_out(state_type&,
3341 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3342 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3343{
3344 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3345 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3346 const uint16_t* _frm_nxt = _frm;
3347 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3348 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3349 uint8_t* _to_nxt = _to;
3350 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3351 _Maxcode_, _Mode_);
3352 frm_nxt = frm + (_frm_nxt - _frm);
3353 to_nxt = to + (_to_nxt - _to);
3354 return r;
3355}
3356
3357__codecvt_utf8<char16_t>::result
3358__codecvt_utf8<char16_t>::do_in(state_type&,
3359 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3360 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3361{
3362 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3363 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3364 const uint8_t* _frm_nxt = _frm;
3365 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3366 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3367 uint16_t* _to_nxt = _to;
3368 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3369 _Maxcode_, _Mode_);
3370 frm_nxt = frm + (_frm_nxt - _frm);
3371 to_nxt = to + (_to_nxt - _to);
3372 return r;
3373}
3374
3375__codecvt_utf8<char16_t>::result
3376__codecvt_utf8<char16_t>::do_unshift(state_type&,
3377 extern_type* to, extern_type*, extern_type*& to_nxt) const
3378{
3379 to_nxt = to;
3380 return noconv;
3381}
3382
3383int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003384__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003385{
3386 return 0;
3387}
3388
3389bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003390__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003391{
3392 return false;
3393}
3394
3395int
3396__codecvt_utf8<char16_t>::do_length(state_type&,
3397 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3398{
3399 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3400 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3401 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3402}
3403
3404int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003405__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003406{
3407 if (_Mode_ & consume_header)
3408 return 6;
3409 return 3;
3410}
3411
3412// __codecvt_utf8<char32_t>
3413
3414__codecvt_utf8<char32_t>::result
3415__codecvt_utf8<char32_t>::do_out(state_type&,
3416 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3417 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3418{
3419 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3420 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3421 const uint32_t* _frm_nxt = _frm;
3422 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3423 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3424 uint8_t* _to_nxt = _to;
3425 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3426 _Maxcode_, _Mode_);
3427 frm_nxt = frm + (_frm_nxt - _frm);
3428 to_nxt = to + (_to_nxt - _to);
3429 return r;
3430}
3431
3432__codecvt_utf8<char32_t>::result
3433__codecvt_utf8<char32_t>::do_in(state_type&,
3434 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3435 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3436{
3437 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3438 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3439 const uint8_t* _frm_nxt = _frm;
3440 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3441 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3442 uint32_t* _to_nxt = _to;
3443 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3444 _Maxcode_, _Mode_);
3445 frm_nxt = frm + (_frm_nxt - _frm);
3446 to_nxt = to + (_to_nxt - _to);
3447 return r;
3448}
3449
3450__codecvt_utf8<char32_t>::result
3451__codecvt_utf8<char32_t>::do_unshift(state_type&,
3452 extern_type* to, extern_type*, extern_type*& to_nxt) const
3453{
3454 to_nxt = to;
3455 return noconv;
3456}
3457
3458int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003459__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003460{
3461 return 0;
3462}
3463
3464bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003465__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003466{
3467 return false;
3468}
3469
3470int
3471__codecvt_utf8<char32_t>::do_length(state_type&,
3472 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3473{
3474 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3475 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3476 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3477}
3478
3479int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003480__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003481{
3482 if (_Mode_ & consume_header)
3483 return 7;
3484 return 4;
3485}
3486
3487// __codecvt_utf16<wchar_t, false>
3488
3489__codecvt_utf16<wchar_t, false>::result
3490__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3491 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3492 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3493{
3494 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3495 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3496 const uint32_t* _frm_nxt = _frm;
3497 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3498 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3499 uint8_t* _to_nxt = _to;
3500 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3501 _Maxcode_, _Mode_);
3502 frm_nxt = frm + (_frm_nxt - _frm);
3503 to_nxt = to + (_to_nxt - _to);
3504 return r;
3505}
3506
3507__codecvt_utf16<wchar_t, false>::result
3508__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3509 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3510 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3511{
3512 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3513 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3514 const uint8_t* _frm_nxt = _frm;
3515 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3516 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3517 uint32_t* _to_nxt = _to;
3518 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3519 _Maxcode_, _Mode_);
3520 frm_nxt = frm + (_frm_nxt - _frm);
3521 to_nxt = to + (_to_nxt - _to);
3522 return r;
3523}
3524
3525__codecvt_utf16<wchar_t, false>::result
3526__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3527 extern_type* to, extern_type*, extern_type*& to_nxt) const
3528{
3529 to_nxt = to;
3530 return noconv;
3531}
3532
3533int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003534__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003535{
3536 return 0;
3537}
3538
3539bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003540__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003541{
3542 return false;
3543}
3544
3545int
3546__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3547 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3548{
3549 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3550 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3551 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3552}
3553
3554int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003555__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003556{
3557 if (_Mode_ & consume_header)
3558 return 6;
3559 return 4;
3560}
3561
3562// __codecvt_utf16<wchar_t, true>
3563
3564__codecvt_utf16<wchar_t, true>::result
3565__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3566 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3567 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3568{
3569 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3570 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3571 const uint32_t* _frm_nxt = _frm;
3572 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3573 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3574 uint8_t* _to_nxt = _to;
3575 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3576 _Maxcode_, _Mode_);
3577 frm_nxt = frm + (_frm_nxt - _frm);
3578 to_nxt = to + (_to_nxt - _to);
3579 return r;
3580}
3581
3582__codecvt_utf16<wchar_t, true>::result
3583__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3584 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3585 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3586{
3587 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3588 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3589 const uint8_t* _frm_nxt = _frm;
3590 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3591 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3592 uint32_t* _to_nxt = _to;
3593 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3594 _Maxcode_, _Mode_);
3595 frm_nxt = frm + (_frm_nxt - _frm);
3596 to_nxt = to + (_to_nxt - _to);
3597 return r;
3598}
3599
3600__codecvt_utf16<wchar_t, true>::result
3601__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3602 extern_type* to, extern_type*, extern_type*& to_nxt) const
3603{
3604 to_nxt = to;
3605 return noconv;
3606}
3607
3608int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003609__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003610{
3611 return 0;
3612}
3613
3614bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003615__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003616{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003617 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003618}
3619
3620int
3621__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3622 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3623{
3624 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3625 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3626 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3627}
3628
3629int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003630__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003631{
3632 if (_Mode_ & consume_header)
3633 return 6;
3634 return 4;
3635}
3636
3637// __codecvt_utf16<char16_t, false>
3638
3639__codecvt_utf16<char16_t, false>::result
3640__codecvt_utf16<char16_t, false>::do_out(state_type&,
3641 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3642 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3643{
3644 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3645 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3646 const uint16_t* _frm_nxt = _frm;
3647 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3648 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3649 uint8_t* _to_nxt = _to;
3650 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3651 _Maxcode_, _Mode_);
3652 frm_nxt = frm + (_frm_nxt - _frm);
3653 to_nxt = to + (_to_nxt - _to);
3654 return r;
3655}
3656
3657__codecvt_utf16<char16_t, false>::result
3658__codecvt_utf16<char16_t, false>::do_in(state_type&,
3659 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3660 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3661{
3662 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3663 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3664 const uint8_t* _frm_nxt = _frm;
3665 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3666 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3667 uint16_t* _to_nxt = _to;
3668 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3669 _Maxcode_, _Mode_);
3670 frm_nxt = frm + (_frm_nxt - _frm);
3671 to_nxt = to + (_to_nxt - _to);
3672 return r;
3673}
3674
3675__codecvt_utf16<char16_t, false>::result
3676__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3677 extern_type* to, extern_type*, extern_type*& to_nxt) const
3678{
3679 to_nxt = to;
3680 return noconv;
3681}
3682
3683int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003684__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003685{
3686 return 0;
3687}
3688
3689bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003690__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003691{
3692 return false;
3693}
3694
3695int
3696__codecvt_utf16<char16_t, false>::do_length(state_type&,
3697 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3698{
3699 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3700 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3701 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3702}
3703
3704int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003705__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003706{
3707 if (_Mode_ & consume_header)
3708 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003709 return 2;
3710}
3711
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003712// __codecvt_utf16<char16_t, true>
3713
3714__codecvt_utf16<char16_t, true>::result
3715__codecvt_utf16<char16_t, true>::do_out(state_type&,
3716 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3717 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3718{
3719 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3720 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3721 const uint16_t* _frm_nxt = _frm;
3722 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3723 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3724 uint8_t* _to_nxt = _to;
3725 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3726 _Maxcode_, _Mode_);
3727 frm_nxt = frm + (_frm_nxt - _frm);
3728 to_nxt = to + (_to_nxt - _to);
3729 return r;
3730}
3731
3732__codecvt_utf16<char16_t, true>::result
3733__codecvt_utf16<char16_t, true>::do_in(state_type&,
3734 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3735 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3736{
3737 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3738 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3739 const uint8_t* _frm_nxt = _frm;
3740 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3741 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3742 uint16_t* _to_nxt = _to;
3743 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3744 _Maxcode_, _Mode_);
3745 frm_nxt = frm + (_frm_nxt - _frm);
3746 to_nxt = to + (_to_nxt - _to);
3747 return r;
3748}
3749
3750__codecvt_utf16<char16_t, true>::result
3751__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3752 extern_type* to, extern_type*, extern_type*& to_nxt) const
3753{
3754 to_nxt = to;
3755 return noconv;
3756}
3757
3758int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003759__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003760{
3761 return 0;
3762}
3763
3764bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003765__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003766{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003767 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003768}
3769
3770int
3771__codecvt_utf16<char16_t, true>::do_length(state_type&,
3772 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3773{
3774 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3775 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3776 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3777}
3778
3779int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003780__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003781{
3782 if (_Mode_ & consume_header)
3783 return 4;
3784 return 2;
3785}
3786
3787// __codecvt_utf16<char32_t, false>
3788
3789__codecvt_utf16<char32_t, false>::result
3790__codecvt_utf16<char32_t, false>::do_out(state_type&,
3791 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3792 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3793{
3794 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3795 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3796 const uint32_t* _frm_nxt = _frm;
3797 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3798 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3799 uint8_t* _to_nxt = _to;
3800 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3801 _Maxcode_, _Mode_);
3802 frm_nxt = frm + (_frm_nxt - _frm);
3803 to_nxt = to + (_to_nxt - _to);
3804 return r;
3805}
3806
3807__codecvt_utf16<char32_t, false>::result
3808__codecvt_utf16<char32_t, false>::do_in(state_type&,
3809 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3810 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3811{
3812 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3813 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3814 const uint8_t* _frm_nxt = _frm;
3815 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3816 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3817 uint32_t* _to_nxt = _to;
3818 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3819 _Maxcode_, _Mode_);
3820 frm_nxt = frm + (_frm_nxt - _frm);
3821 to_nxt = to + (_to_nxt - _to);
3822 return r;
3823}
3824
3825__codecvt_utf16<char32_t, false>::result
3826__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3827 extern_type* to, extern_type*, extern_type*& to_nxt) const
3828{
3829 to_nxt = to;
3830 return noconv;
3831}
3832
3833int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003834__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003835{
3836 return 0;
3837}
3838
3839bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003840__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003841{
3842 return false;
3843}
3844
3845int
3846__codecvt_utf16<char32_t, false>::do_length(state_type&,
3847 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3848{
3849 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3850 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3851 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3852}
3853
3854int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003855__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003856{
3857 if (_Mode_ & consume_header)
3858 return 6;
3859 return 4;
3860}
3861
3862// __codecvt_utf16<char32_t, true>
3863
3864__codecvt_utf16<char32_t, true>::result
3865__codecvt_utf16<char32_t, true>::do_out(state_type&,
3866 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3867 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3868{
3869 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3870 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3871 const uint32_t* _frm_nxt = _frm;
3872 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3873 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3874 uint8_t* _to_nxt = _to;
3875 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3876 _Maxcode_, _Mode_);
3877 frm_nxt = frm + (_frm_nxt - _frm);
3878 to_nxt = to + (_to_nxt - _to);
3879 return r;
3880}
3881
3882__codecvt_utf16<char32_t, true>::result
3883__codecvt_utf16<char32_t, true>::do_in(state_type&,
3884 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3885 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3886{
3887 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3888 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3889 const uint8_t* _frm_nxt = _frm;
3890 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3891 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3892 uint32_t* _to_nxt = _to;
3893 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3894 _Maxcode_, _Mode_);
3895 frm_nxt = frm + (_frm_nxt - _frm);
3896 to_nxt = to + (_to_nxt - _to);
3897 return r;
3898}
3899
3900__codecvt_utf16<char32_t, true>::result
3901__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3902 extern_type* to, extern_type*, extern_type*& to_nxt) const
3903{
3904 to_nxt = to;
3905 return noconv;
3906}
3907
3908int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003909__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003910{
3911 return 0;
3912}
3913
3914bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003915__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003916{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003917 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003918}
3919
3920int
3921__codecvt_utf16<char32_t, true>::do_length(state_type&,
3922 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3923{
3924 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3925 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3926 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3927}
3928
3929int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003930__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003931{
3932 if (_Mode_ & consume_header)
3933 return 6;
3934 return 4;
3935}
3936
3937// __codecvt_utf8_utf16<wchar_t>
3938
3939__codecvt_utf8_utf16<wchar_t>::result
3940__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3941 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3942 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3943{
3944 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3945 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3946 const uint32_t* _frm_nxt = _frm;
3947 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3948 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3949 uint8_t* _to_nxt = _to;
3950 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3951 _Maxcode_, _Mode_);
3952 frm_nxt = frm + (_frm_nxt - _frm);
3953 to_nxt = to + (_to_nxt - _to);
3954 return r;
3955}
3956
3957__codecvt_utf8_utf16<wchar_t>::result
3958__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3959 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3960 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3961{
3962 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3963 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3964 const uint8_t* _frm_nxt = _frm;
3965 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3966 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3967 uint32_t* _to_nxt = _to;
3968 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3969 _Maxcode_, _Mode_);
3970 frm_nxt = frm + (_frm_nxt - _frm);
3971 to_nxt = to + (_to_nxt - _to);
3972 return r;
3973}
3974
3975__codecvt_utf8_utf16<wchar_t>::result
3976__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3977 extern_type* to, extern_type*, extern_type*& to_nxt) const
3978{
3979 to_nxt = to;
3980 return noconv;
3981}
3982
3983int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003984__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003985{
3986 return 0;
3987}
3988
3989bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003990__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003991{
3992 return false;
3993}
3994
3995int
3996__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3997 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3998{
3999 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4000 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4001 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4002}
4003
4004int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004005__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004006{
4007 if (_Mode_ & consume_header)
4008 return 7;
4009 return 4;
4010}
4011
4012// __codecvt_utf8_utf16<char16_t>
4013
4014__codecvt_utf8_utf16<char16_t>::result
4015__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4016 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4017 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4018{
4019 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4020 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4021 const uint16_t* _frm_nxt = _frm;
4022 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4023 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4024 uint8_t* _to_nxt = _to;
4025 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4026 _Maxcode_, _Mode_);
4027 frm_nxt = frm + (_frm_nxt - _frm);
4028 to_nxt = to + (_to_nxt - _to);
4029 return r;
4030}
4031
4032__codecvt_utf8_utf16<char16_t>::result
4033__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4034 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4035 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4036{
4037 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4038 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4039 const uint8_t* _frm_nxt = _frm;
4040 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4041 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4042 uint16_t* _to_nxt = _to;
4043 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4044 _Maxcode_, _Mode_);
4045 frm_nxt = frm + (_frm_nxt - _frm);
4046 to_nxt = to + (_to_nxt - _to);
4047 return r;
4048}
4049
4050__codecvt_utf8_utf16<char16_t>::result
4051__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4052 extern_type* to, extern_type*, extern_type*& to_nxt) const
4053{
4054 to_nxt = to;
4055 return noconv;
4056}
4057
4058int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004059__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004060{
4061 return 0;
4062}
4063
4064bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004065__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004066{
4067 return false;
4068}
4069
4070int
4071__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4072 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4073{
4074 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4075 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4076 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4077}
4078
4079int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004080__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004081{
4082 if (_Mode_ & consume_header)
4083 return 7;
4084 return 4;
4085}
4086
4087// __codecvt_utf8_utf16<char32_t>
4088
4089__codecvt_utf8_utf16<char32_t>::result
4090__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4091 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4092 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4093{
4094 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4095 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4096 const uint32_t* _frm_nxt = _frm;
4097 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4098 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4099 uint8_t* _to_nxt = _to;
4100 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4101 _Maxcode_, _Mode_);
4102 frm_nxt = frm + (_frm_nxt - _frm);
4103 to_nxt = to + (_to_nxt - _to);
4104 return r;
4105}
4106
4107__codecvt_utf8_utf16<char32_t>::result
4108__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4109 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4110 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4111{
4112 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4113 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4114 const uint8_t* _frm_nxt = _frm;
4115 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4116 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4117 uint32_t* _to_nxt = _to;
4118 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4119 _Maxcode_, _Mode_);
4120 frm_nxt = frm + (_frm_nxt - _frm);
4121 to_nxt = to + (_to_nxt - _to);
4122 return r;
4123}
4124
4125__codecvt_utf8_utf16<char32_t>::result
4126__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4127 extern_type* to, extern_type*, extern_type*& to_nxt) const
4128{
4129 to_nxt = to;
4130 return noconv;
4131}
4132
4133int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004134__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004135{
4136 return 0;
4137}
4138
4139bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004140__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004141{
4142 return false;
4143}
4144
4145int
4146__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4147 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4148{
4149 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4150 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4151 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4152}
4153
4154int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004155__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004156{
4157 if (_Mode_ & consume_header)
4158 return 7;
4159 return 4;
4160}
4161
Howard Hinnantc51e1022010-05-11 19:42:16 +00004162// __narrow_to_utf8<16>
4163
4164__narrow_to_utf8<16>::~__narrow_to_utf8()
4165{
4166}
4167
4168// __narrow_to_utf8<32>
4169
4170__narrow_to_utf8<32>::~__narrow_to_utf8()
4171{
4172}
4173
4174// __widen_from_utf8<16>
4175
4176__widen_from_utf8<16>::~__widen_from_utf8()
4177{
4178}
4179
4180// __widen_from_utf8<32>
4181
4182__widen_from_utf8<32>::~__widen_from_utf8()
4183{
4184}
4185
4186// numpunct<char> && numpunct<wchar_t>
4187
4188locale::id numpunct< char >::id;
4189locale::id numpunct<wchar_t>::id;
4190
4191numpunct<char>::numpunct(size_t refs)
4192 : locale::facet(refs),
4193 __decimal_point_('.'),
4194 __thousands_sep_(',')
4195{
4196}
4197
4198numpunct<wchar_t>::numpunct(size_t refs)
4199 : locale::facet(refs),
4200 __decimal_point_(L'.'),
4201 __thousands_sep_(L',')
4202{
4203}
4204
4205numpunct<char>::~numpunct()
4206{
4207}
4208
4209numpunct<wchar_t>::~numpunct()
4210{
4211}
4212
4213 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4214wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4215
4216 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4217wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4218
4219string numpunct< char >::do_grouping() const {return __grouping_;}
4220string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4221
4222 string numpunct< char >::do_truename() const {return "true";}
4223wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4224
4225 string numpunct< char >::do_falsename() const {return "false";}
4226wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4227
4228// numpunct_byname<char>
4229
4230numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4231 : numpunct<char>(refs)
4232{
4233 __init(nm);
4234}
4235
4236numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4237 : numpunct<char>(refs)
4238{
4239 __init(nm.c_str());
4240}
4241
4242numpunct_byname<char>::~numpunct_byname()
4243{
4244}
4245
4246void
4247numpunct_byname<char>::__init(const char* nm)
4248{
4249 if (strcmp(nm, "C") != 0)
4250 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004251 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00004252 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00004253 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004254 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004255
Ben Craig3756b922016-03-09 15:39:39 +00004256 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004257 if (*lc->decimal_point)
4258 __decimal_point_ = *lc->decimal_point;
4259 if (*lc->thousands_sep)
4260 __thousands_sep_ = *lc->thousands_sep;
4261 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004262 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004263 }
4264}
4265
4266// numpunct_byname<wchar_t>
4267
4268numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4269 : numpunct<wchar_t>(refs)
4270{
4271 __init(nm);
4272}
4273
4274numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4275 : numpunct<wchar_t>(refs)
4276{
4277 __init(nm.c_str());
4278}
4279
4280numpunct_byname<wchar_t>::~numpunct_byname()
4281{
4282}
4283
4284void
4285numpunct_byname<wchar_t>::__init(const char* nm)
4286{
4287 if (strcmp(nm, "C") != 0)
4288 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004289 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00004290 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00004291 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004292 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004293
Ben Craig3756b922016-03-09 15:39:39 +00004294 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004295 if (*lc->decimal_point)
4296 __decimal_point_ = *lc->decimal_point;
4297 if (*lc->thousands_sep)
4298 __thousands_sep_ = *lc->thousands_sep;
4299 __grouping_ = lc->grouping;
4300 // locallization for truename and falsename is not available
4301 }
4302}
4303
4304// num_get helpers
4305
4306int
4307__num_get_base::__get_base(ios_base& iob)
4308{
4309 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4310 if (__basefield == ios_base::oct)
4311 return 8;
4312 else if (__basefield == ios_base::hex)
4313 return 16;
4314 else if (__basefield == 0)
4315 return 0;
4316 return 10;
4317}
4318
4319const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4320
4321void
4322__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4323 ios_base::iostate& __err)
4324{
4325 if (__grouping.size() != 0)
4326 {
4327 reverse(__g, __g_end);
4328 const char* __ig = __grouping.data();
4329 const char* __eg = __ig + __grouping.size();
4330 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4331 {
4332 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4333 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004334 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004335 {
4336 __err = ios_base::failbit;
4337 return;
4338 }
4339 }
4340 if (__eg - __ig > 1)
4341 ++__ig;
4342 }
4343 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4344 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004345 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004346 __err = ios_base::failbit;
4347 }
4348 }
4349}
4350
4351void
4352__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4353 ios_base::fmtflags __flags)
4354{
4355 if (__flags & ios_base::showpos)
4356 *__fmtp++ = '+';
4357 if (__flags & ios_base::showbase)
4358 *__fmtp++ = '#';
4359 while(*__len)
4360 *__fmtp++ = *__len++;
4361 if ((__flags & ios_base::basefield) == ios_base::oct)
4362 *__fmtp = 'o';
4363 else if ((__flags & ios_base::basefield) == ios_base::hex)
4364 {
4365 if (__flags & ios_base::uppercase)
4366 *__fmtp = 'X';
4367 else
4368 *__fmtp = 'x';
4369 }
4370 else if (__signd)
4371 *__fmtp = 'd';
4372 else
4373 *__fmtp = 'u';
4374}
4375
4376bool
4377__num_put_base::__format_float(char* __fmtp, const char* __len,
4378 ios_base::fmtflags __flags)
4379{
4380 bool specify_precision = true;
4381 if (__flags & ios_base::showpos)
4382 *__fmtp++ = '+';
4383 if (__flags & ios_base::showpoint)
4384 *__fmtp++ = '#';
4385 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004386 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004387 if (floatfield == (ios_base::fixed | ios_base::scientific))
4388 specify_precision = false;
4389 else
4390 {
4391 *__fmtp++ = '.';
4392 *__fmtp++ = '*';
4393 }
4394 while(*__len)
4395 *__fmtp++ = *__len++;
4396 if (floatfield == ios_base::fixed)
4397 {
4398 if (uppercase)
4399 *__fmtp = 'F';
4400 else
4401 *__fmtp = 'f';
4402 }
4403 else if (floatfield == ios_base::scientific)
4404 {
4405 if (uppercase)
4406 *__fmtp = 'E';
4407 else
4408 *__fmtp = 'e';
4409 }
4410 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4411 {
4412 if (uppercase)
4413 *__fmtp = 'A';
4414 else
4415 *__fmtp = 'a';
4416 }
4417 else
4418 {
4419 if (uppercase)
4420 *__fmtp = 'G';
4421 else
4422 *__fmtp = 'g';
4423 }
4424 return specify_precision;
4425}
4426
4427char*
4428__num_put_base::__identify_padding(char* __nb, char* __ne,
4429 const ios_base& __iob)
4430{
4431 switch (__iob.flags() & ios_base::adjustfield)
4432 {
4433 case ios_base::internal:
4434 if (__nb[0] == '-' || __nb[0] == '+')
4435 return __nb+1;
4436 if (__ne - __nb >= 2 && __nb[0] == '0'
4437 && (__nb[1] == 'x' || __nb[1] == 'X'))
4438 return __nb+2;
4439 break;
4440 case ios_base::left:
4441 return __ne;
4442 case ios_base::right:
4443 default:
4444 break;
4445 }
4446 return __nb;
4447}
4448
4449// time_get
4450
4451static
4452string*
4453init_weeks()
4454{
4455 static string weeks[14];
4456 weeks[0] = "Sunday";
4457 weeks[1] = "Monday";
4458 weeks[2] = "Tuesday";
4459 weeks[3] = "Wednesday";
4460 weeks[4] = "Thursday";
4461 weeks[5] = "Friday";
4462 weeks[6] = "Saturday";
4463 weeks[7] = "Sun";
4464 weeks[8] = "Mon";
4465 weeks[9] = "Tue";
4466 weeks[10] = "Wed";
4467 weeks[11] = "Thu";
4468 weeks[12] = "Fri";
4469 weeks[13] = "Sat";
4470 return weeks;
4471}
4472
4473static
4474wstring*
4475init_wweeks()
4476{
4477 static wstring weeks[14];
4478 weeks[0] = L"Sunday";
4479 weeks[1] = L"Monday";
4480 weeks[2] = L"Tuesday";
4481 weeks[3] = L"Wednesday";
4482 weeks[4] = L"Thursday";
4483 weeks[5] = L"Friday";
4484 weeks[6] = L"Saturday";
4485 weeks[7] = L"Sun";
4486 weeks[8] = L"Mon";
4487 weeks[9] = L"Tue";
4488 weeks[10] = L"Wed";
4489 weeks[11] = L"Thu";
4490 weeks[12] = L"Fri";
4491 weeks[13] = L"Sat";
4492 return weeks;
4493}
4494
4495template <>
4496const string*
4497__time_get_c_storage<char>::__weeks() const
4498{
4499 static const string* weeks = init_weeks();
4500 return weeks;
4501}
4502
4503template <>
4504const wstring*
4505__time_get_c_storage<wchar_t>::__weeks() const
4506{
4507 static const wstring* weeks = init_wweeks();
4508 return weeks;
4509}
4510
4511static
4512string*
4513init_months()
4514{
4515 static string months[24];
4516 months[0] = "January";
4517 months[1] = "February";
4518 months[2] = "March";
4519 months[3] = "April";
4520 months[4] = "May";
4521 months[5] = "June";
4522 months[6] = "July";
4523 months[7] = "August";
4524 months[8] = "September";
4525 months[9] = "October";
4526 months[10] = "November";
4527 months[11] = "December";
4528 months[12] = "Jan";
4529 months[13] = "Feb";
4530 months[14] = "Mar";
4531 months[15] = "Apr";
4532 months[16] = "May";
4533 months[17] = "Jun";
4534 months[18] = "Jul";
4535 months[19] = "Aug";
4536 months[20] = "Sep";
4537 months[21] = "Oct";
4538 months[22] = "Nov";
4539 months[23] = "Dec";
4540 return months;
4541}
4542
4543static
4544wstring*
4545init_wmonths()
4546{
4547 static wstring months[24];
4548 months[0] = L"January";
4549 months[1] = L"February";
4550 months[2] = L"March";
4551 months[3] = L"April";
4552 months[4] = L"May";
4553 months[5] = L"June";
4554 months[6] = L"July";
4555 months[7] = L"August";
4556 months[8] = L"September";
4557 months[9] = L"October";
4558 months[10] = L"November";
4559 months[11] = L"December";
4560 months[12] = L"Jan";
4561 months[13] = L"Feb";
4562 months[14] = L"Mar";
4563 months[15] = L"Apr";
4564 months[16] = L"May";
4565 months[17] = L"Jun";
4566 months[18] = L"Jul";
4567 months[19] = L"Aug";
4568 months[20] = L"Sep";
4569 months[21] = L"Oct";
4570 months[22] = L"Nov";
4571 months[23] = L"Dec";
4572 return months;
4573}
4574
4575template <>
4576const string*
4577__time_get_c_storage<char>::__months() const
4578{
4579 static const string* months = init_months();
4580 return months;
4581}
4582
4583template <>
4584const wstring*
4585__time_get_c_storage<wchar_t>::__months() const
4586{
4587 static const wstring* months = init_wmonths();
4588 return months;
4589}
4590
4591static
4592string*
4593init_am_pm()
4594{
4595 static string am_pm[24];
4596 am_pm[0] = "AM";
4597 am_pm[1] = "PM";
4598 return am_pm;
4599}
4600
4601static
4602wstring*
4603init_wam_pm()
4604{
4605 static wstring am_pm[24];
4606 am_pm[0] = L"AM";
4607 am_pm[1] = L"PM";
4608 return am_pm;
4609}
4610
4611template <>
4612const string*
4613__time_get_c_storage<char>::__am_pm() const
4614{
4615 static const string* am_pm = init_am_pm();
4616 return am_pm;
4617}
4618
4619template <>
4620const wstring*
4621__time_get_c_storage<wchar_t>::__am_pm() const
4622{
4623 static const wstring* am_pm = init_wam_pm();
4624 return am_pm;
4625}
4626
4627template <>
4628const string&
4629__time_get_c_storage<char>::__x() const
4630{
4631 static string s("%m/%d/%y");
4632 return s;
4633}
4634
4635template <>
4636const wstring&
4637__time_get_c_storage<wchar_t>::__x() const
4638{
4639 static wstring s(L"%m/%d/%y");
4640 return s;
4641}
4642
4643template <>
4644const string&
4645__time_get_c_storage<char>::__X() const
4646{
4647 static string s("%H:%M:%S");
4648 return s;
4649}
4650
4651template <>
4652const wstring&
4653__time_get_c_storage<wchar_t>::__X() const
4654{
4655 static wstring s(L"%H:%M:%S");
4656 return s;
4657}
4658
4659template <>
4660const string&
4661__time_get_c_storage<char>::__c() const
4662{
4663 static string s("%a %b %d %H:%M:%S %Y");
4664 return s;
4665}
4666
4667template <>
4668const wstring&
4669__time_get_c_storage<wchar_t>::__c() const
4670{
4671 static wstring s(L"%a %b %d %H:%M:%S %Y");
4672 return s;
4673}
4674
4675template <>
4676const string&
4677__time_get_c_storage<char>::__r() const
4678{
4679 static string s("%I:%M:%S %p");
4680 return s;
4681}
4682
4683template <>
4684const wstring&
4685__time_get_c_storage<wchar_t>::__r() const
4686{
4687 static wstring s(L"%I:%M:%S %p");
4688 return s;
4689}
4690
4691// time_get_byname
4692
4693__time_get::__time_get(const char* nm)
4694 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4695{
4696 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004697 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004698 " failed to construct for " + string(nm));
4699}
4700
4701__time_get::__time_get(const string& nm)
4702 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4703{
4704 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004705 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004706 " failed to construct for " + nm);
4707}
4708
4709__time_get::~__time_get()
4710{
4711 freelocale(__loc_);
4712}
Marshall Clowd920eea2013-10-21 15:07:28 +00004713#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004714#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004715#endif
4716#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004717#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004718#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004719
Howard Hinnantc51e1022010-05-11 19:42:16 +00004720template <>
4721string
4722__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4723{
Howard Hinnant990207c2012-02-19 14:55:32 +00004724 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004725 t.tm_sec = 59;
4726 t.tm_min = 55;
4727 t.tm_hour = 23;
4728 t.tm_mday = 31;
4729 t.tm_mon = 11;
4730 t.tm_year = 161;
4731 t.tm_wday = 6;
4732 t.tm_yday = 364;
4733 t.tm_isdst = -1;
4734 char buf[100];
4735 char f[3] = {0};
4736 f[0] = '%';
4737 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004738 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004739 char* bb = buf;
4740 char* be = buf + n;
4741 string result;
4742 while (bb != be)
4743 {
4744 if (ct.is(ctype_base::space, *bb))
4745 {
4746 result.push_back(' ');
4747 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4748 ;
4749 continue;
4750 }
4751 char* w = bb;
4752 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004753 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004754 ct, err, false)
4755 - this->__weeks_;
4756 if (i < 14)
4757 {
4758 result.push_back('%');
4759 if (i < 7)
4760 result.push_back('A');
4761 else
4762 result.push_back('a');
4763 bb = w;
4764 continue;
4765 }
4766 w = bb;
4767 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4768 ct, err, false)
4769 - this->__months_;
4770 if (i < 24)
4771 {
4772 result.push_back('%');
4773 if (i < 12)
4774 result.push_back('B');
4775 else
4776 result.push_back('b');
4777 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4778 result.back() = 'm';
4779 bb = w;
4780 continue;
4781 }
4782 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4783 {
4784 w = bb;
4785 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4786 ct, err, false) - this->__am_pm_;
4787 if (i < 2)
4788 {
4789 result.push_back('%');
4790 result.push_back('p');
4791 bb = w;
4792 continue;
4793 }
4794 }
4795 w = bb;
4796 if (ct.is(ctype_base::digit, *bb))
4797 {
4798 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4799 {
4800 case 6:
4801 result.push_back('%');
4802 result.push_back('w');
4803 break;
4804 case 7:
4805 result.push_back('%');
4806 result.push_back('u');
4807 break;
4808 case 11:
4809 result.push_back('%');
4810 result.push_back('I');
4811 break;
4812 case 12:
4813 result.push_back('%');
4814 result.push_back('m');
4815 break;
4816 case 23:
4817 result.push_back('%');
4818 result.push_back('H');
4819 break;
4820 case 31:
4821 result.push_back('%');
4822 result.push_back('d');
4823 break;
4824 case 55:
4825 result.push_back('%');
4826 result.push_back('M');
4827 break;
4828 case 59:
4829 result.push_back('%');
4830 result.push_back('S');
4831 break;
4832 case 61:
4833 result.push_back('%');
4834 result.push_back('y');
4835 break;
4836 case 364:
4837 result.push_back('%');
4838 result.push_back('j');
4839 break;
4840 case 2061:
4841 result.push_back('%');
4842 result.push_back('Y');
4843 break;
4844 default:
4845 for (; w != bb; ++w)
4846 result.push_back(*w);
4847 break;
4848 }
4849 continue;
4850 }
4851 if (*bb == '%')
4852 {
4853 result.push_back('%');
4854 result.push_back('%');
4855 ++bb;
4856 continue;
4857 }
4858 result.push_back(*bb);
4859 ++bb;
4860 }
4861 return result;
4862}
4863
Marshall Clowd920eea2013-10-21 15:07:28 +00004864#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004865#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004866#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004867
Howard Hinnantc51e1022010-05-11 19:42:16 +00004868template <>
4869wstring
4870__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4871{
Howard Hinnant990207c2012-02-19 14:55:32 +00004872 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004873 t.tm_sec = 59;
4874 t.tm_min = 55;
4875 t.tm_hour = 23;
4876 t.tm_mday = 31;
4877 t.tm_mon = 11;
4878 t.tm_year = 161;
4879 t.tm_wday = 6;
4880 t.tm_yday = 364;
4881 t.tm_isdst = -1;
4882 char buf[100];
4883 char f[3] = {0};
4884 f[0] = '%';
4885 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004886 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004887 wchar_t wbuf[100];
4888 wchar_t* wbb = wbuf;
4889 mbstate_t mb = {0};
4890 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004891 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004892 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004893 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004894 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004895 wstring result;
4896 while (wbb != wbe)
4897 {
4898 if (ct.is(ctype_base::space, *wbb))
4899 {
4900 result.push_back(L' ');
4901 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4902 ;
4903 continue;
4904 }
4905 wchar_t* w = wbb;
4906 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004907 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004908 ct, err, false)
4909 - this->__weeks_;
4910 if (i < 14)
4911 {
4912 result.push_back(L'%');
4913 if (i < 7)
4914 result.push_back(L'A');
4915 else
4916 result.push_back(L'a');
4917 wbb = w;
4918 continue;
4919 }
4920 w = wbb;
4921 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4922 ct, err, false)
4923 - this->__months_;
4924 if (i < 24)
4925 {
4926 result.push_back(L'%');
4927 if (i < 12)
4928 result.push_back(L'B');
4929 else
4930 result.push_back(L'b');
4931 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4932 result.back() = L'm';
4933 wbb = w;
4934 continue;
4935 }
4936 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4937 {
4938 w = wbb;
4939 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4940 ct, err, false) - this->__am_pm_;
4941 if (i < 2)
4942 {
4943 result.push_back(L'%');
4944 result.push_back(L'p');
4945 wbb = w;
4946 continue;
4947 }
4948 }
4949 w = wbb;
4950 if (ct.is(ctype_base::digit, *wbb))
4951 {
4952 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4953 {
4954 case 6:
4955 result.push_back(L'%');
4956 result.push_back(L'w');
4957 break;
4958 case 7:
4959 result.push_back(L'%');
4960 result.push_back(L'u');
4961 break;
4962 case 11:
4963 result.push_back(L'%');
4964 result.push_back(L'I');
4965 break;
4966 case 12:
4967 result.push_back(L'%');
4968 result.push_back(L'm');
4969 break;
4970 case 23:
4971 result.push_back(L'%');
4972 result.push_back(L'H');
4973 break;
4974 case 31:
4975 result.push_back(L'%');
4976 result.push_back(L'd');
4977 break;
4978 case 55:
4979 result.push_back(L'%');
4980 result.push_back(L'M');
4981 break;
4982 case 59:
4983 result.push_back(L'%');
4984 result.push_back(L'S');
4985 break;
4986 case 61:
4987 result.push_back(L'%');
4988 result.push_back(L'y');
4989 break;
4990 case 364:
4991 result.push_back(L'%');
4992 result.push_back(L'j');
4993 break;
4994 case 2061:
4995 result.push_back(L'%');
4996 result.push_back(L'Y');
4997 break;
4998 default:
4999 for (; w != wbb; ++w)
5000 result.push_back(*w);
5001 break;
5002 }
5003 continue;
5004 }
5005 if (ct.narrow(*wbb, 0) == '%')
5006 {
5007 result.push_back(L'%');
5008 result.push_back(L'%');
5009 ++wbb;
5010 continue;
5011 }
5012 result.push_back(*wbb);
5013 ++wbb;
5014 }
5015 return result;
5016}
5017
5018template <>
5019void
5020__time_get_storage<char>::init(const ctype<char>& ct)
5021{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005022 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005023 char buf[100];
5024 // __weeks_
5025 for (int i = 0; i < 7; ++i)
5026 {
5027 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005028 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005029 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005030 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005031 __weeks_[i+7] = buf;
5032 }
5033 // __months_
5034 for (int i = 0; i < 12; ++i)
5035 {
5036 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005037 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005038 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005039 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005040 __months_[i+12] = buf;
5041 }
5042 // __am_pm_
5043 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005044 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005045 __am_pm_[0] = buf;
5046 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005047 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005048 __am_pm_[1] = buf;
5049 __c_ = __analyze('c', ct);
5050 __r_ = __analyze('r', ct);
5051 __x_ = __analyze('x', ct);
5052 __X_ = __analyze('X', ct);
5053}
5054
5055template <>
5056void
5057__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5058{
5059 tm t = {0};
5060 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005061 wchar_t wbuf[100];
5062 wchar_t* wbe;
5063 mbstate_t mb = {0};
5064 // __weeks_
5065 for (int i = 0; i < 7; ++i)
5066 {
5067 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005068 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005069 mb = mbstate_t();
5070 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005071 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005072 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005073 __throw_runtime_error("locale not supported");
5074 wbe = wbuf + j;
5075 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005076 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005077 mb = mbstate_t();
5078 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005079 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005080 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005081 __throw_runtime_error("locale not supported");
5082 wbe = wbuf + j;
5083 __weeks_[i+7].assign(wbuf, wbe);
5084 }
5085 // __months_
5086 for (int i = 0; i < 12; ++i)
5087 {
5088 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005089 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005090 mb = mbstate_t();
5091 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005092 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005093 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005094 __throw_runtime_error("locale not supported");
5095 wbe = wbuf + j;
5096 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005097 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005098 mb = mbstate_t();
5099 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005100 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005101 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005102 __throw_runtime_error("locale not supported");
5103 wbe = wbuf + j;
5104 __months_[i+12].assign(wbuf, wbe);
5105 }
5106 // __am_pm_
5107 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005108 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005109 mb = mbstate_t();
5110 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005111 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005112 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005113 __throw_runtime_error("locale not supported");
5114 wbe = wbuf + j;
5115 __am_pm_[0].assign(wbuf, wbe);
5116 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005117 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005118 mb = mbstate_t();
5119 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005120 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005121 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005122 __throw_runtime_error("locale not supported");
5123 wbe = wbuf + j;
5124 __am_pm_[1].assign(wbuf, wbe);
5125 __c_ = __analyze('c', ct);
5126 __r_ = __analyze('r', ct);
5127 __x_ = __analyze('x', ct);
5128 __X_ = __analyze('X', ct);
5129}
5130
5131template <class CharT>
5132struct _LIBCPP_HIDDEN __time_get_temp
5133 : public ctype_byname<CharT>
5134{
5135 explicit __time_get_temp(const char* nm)
5136 : ctype_byname<CharT>(nm, 1) {}
5137 explicit __time_get_temp(const string& nm)
5138 : ctype_byname<CharT>(nm, 1) {}
5139};
5140
5141template <>
5142__time_get_storage<char>::__time_get_storage(const char* __nm)
5143 : __time_get(__nm)
5144{
5145 const __time_get_temp<char> ct(__nm);
5146 init(ct);
5147}
5148
5149template <>
5150__time_get_storage<char>::__time_get_storage(const string& __nm)
5151 : __time_get(__nm)
5152{
5153 const __time_get_temp<char> ct(__nm);
5154 init(ct);
5155}
5156
5157template <>
5158__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5159 : __time_get(__nm)
5160{
5161 const __time_get_temp<wchar_t> ct(__nm);
5162 init(ct);
5163}
5164
5165template <>
5166__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5167 : __time_get(__nm)
5168{
5169 const __time_get_temp<wchar_t> ct(__nm);
5170 init(ct);
5171}
5172
5173template <>
5174time_base::dateorder
5175__time_get_storage<char>::__do_date_order() const
5176{
5177 unsigned i;
5178 for (i = 0; i < __x_.size(); ++i)
5179 if (__x_[i] == '%')
5180 break;
5181 ++i;
5182 switch (__x_[i])
5183 {
5184 case 'y':
5185 case 'Y':
5186 for (++i; i < __x_.size(); ++i)
5187 if (__x_[i] == '%')
5188 break;
5189 if (i == __x_.size())
5190 break;
5191 ++i;
5192 switch (__x_[i])
5193 {
5194 case 'm':
5195 for (++i; i < __x_.size(); ++i)
5196 if (__x_[i] == '%')
5197 break;
5198 if (i == __x_.size())
5199 break;
5200 ++i;
5201 if (__x_[i] == 'd')
5202 return time_base::ymd;
5203 break;
5204 case 'd':
5205 for (++i; i < __x_.size(); ++i)
5206 if (__x_[i] == '%')
5207 break;
5208 if (i == __x_.size())
5209 break;
5210 ++i;
5211 if (__x_[i] == 'm')
5212 return time_base::ydm;
5213 break;
5214 }
5215 break;
5216 case 'm':
5217 for (++i; i < __x_.size(); ++i)
5218 if (__x_[i] == '%')
5219 break;
5220 if (i == __x_.size())
5221 break;
5222 ++i;
5223 if (__x_[i] == 'd')
5224 {
5225 for (++i; i < __x_.size(); ++i)
5226 if (__x_[i] == '%')
5227 break;
5228 if (i == __x_.size())
5229 break;
5230 ++i;
5231 if (__x_[i] == 'y' || __x_[i] == 'Y')
5232 return time_base::mdy;
5233 break;
5234 }
5235 break;
5236 case 'd':
5237 for (++i; i < __x_.size(); ++i)
5238 if (__x_[i] == '%')
5239 break;
5240 if (i == __x_.size())
5241 break;
5242 ++i;
5243 if (__x_[i] == 'm')
5244 {
5245 for (++i; i < __x_.size(); ++i)
5246 if (__x_[i] == '%')
5247 break;
5248 if (i == __x_.size())
5249 break;
5250 ++i;
5251 if (__x_[i] == 'y' || __x_[i] == 'Y')
5252 return time_base::dmy;
5253 break;
5254 }
5255 break;
5256 }
5257 return time_base::no_order;
5258}
5259
5260template <>
5261time_base::dateorder
5262__time_get_storage<wchar_t>::__do_date_order() const
5263{
5264 unsigned i;
5265 for (i = 0; i < __x_.size(); ++i)
5266 if (__x_[i] == L'%')
5267 break;
5268 ++i;
5269 switch (__x_[i])
5270 {
5271 case L'y':
5272 case L'Y':
5273 for (++i; i < __x_.size(); ++i)
5274 if (__x_[i] == L'%')
5275 break;
5276 if (i == __x_.size())
5277 break;
5278 ++i;
5279 switch (__x_[i])
5280 {
5281 case L'm':
5282 for (++i; i < __x_.size(); ++i)
5283 if (__x_[i] == L'%')
5284 break;
5285 if (i == __x_.size())
5286 break;
5287 ++i;
5288 if (__x_[i] == L'd')
5289 return time_base::ymd;
5290 break;
5291 case L'd':
5292 for (++i; i < __x_.size(); ++i)
5293 if (__x_[i] == L'%')
5294 break;
5295 if (i == __x_.size())
5296 break;
5297 ++i;
5298 if (__x_[i] == L'm')
5299 return time_base::ydm;
5300 break;
5301 }
5302 break;
5303 case L'm':
5304 for (++i; i < __x_.size(); ++i)
5305 if (__x_[i] == L'%')
5306 break;
5307 if (i == __x_.size())
5308 break;
5309 ++i;
5310 if (__x_[i] == L'd')
5311 {
5312 for (++i; i < __x_.size(); ++i)
5313 if (__x_[i] == L'%')
5314 break;
5315 if (i == __x_.size())
5316 break;
5317 ++i;
5318 if (__x_[i] == L'y' || __x_[i] == L'Y')
5319 return time_base::mdy;
5320 break;
5321 }
5322 break;
5323 case L'd':
5324 for (++i; i < __x_.size(); ++i)
5325 if (__x_[i] == L'%')
5326 break;
5327 if (i == __x_.size())
5328 break;
5329 ++i;
5330 if (__x_[i] == L'm')
5331 {
5332 for (++i; i < __x_.size(); ++i)
5333 if (__x_[i] == L'%')
5334 break;
5335 if (i == __x_.size())
5336 break;
5337 ++i;
5338 if (__x_[i] == L'y' || __x_[i] == L'Y')
5339 return time_base::dmy;
5340 break;
5341 }
5342 break;
5343 }
5344 return time_base::no_order;
5345}
5346
5347// time_put
5348
5349__time_put::__time_put(const char* nm)
5350 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5351{
5352 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005353 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005354 " failed to construct for " + string(nm));
5355}
5356
5357__time_put::__time_put(const string& nm)
5358 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5359{
5360 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005361 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005362 " failed to construct for " + nm);
5363}
5364
5365__time_put::~__time_put()
5366{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005367 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005368 freelocale(__loc_);
5369}
5370
5371void
5372__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5373 char __fmt, char __mod) const
5374{
5375 char fmt[] = {'%', __fmt, __mod, 0};
5376 if (__mod != 0)
5377 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005378 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005379 __ne = __nb + n;
5380}
5381
5382void
5383__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5384 char __fmt, char __mod) const
5385{
5386 char __nar[100];
5387 char* __ne = __nar + 100;
5388 __do_put(__nar, __ne, __tm, __fmt, __mod);
5389 mbstate_t mb = {0};
5390 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005391 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005392 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005393 __throw_runtime_error("locale not supported");
5394 __we = __wb + j;
5395}
5396
5397// moneypunct_byname
5398
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005399template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005400static
5401void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005402__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5403 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5404 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005405{
5406 const char sign = static_cast<char>(money_base::sign);
5407 const char space = static_cast<char>(money_base::space);
5408 const char none = static_cast<char>(money_base::none);
5409 const char symbol = static_cast<char>(money_base::symbol);
5410 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005411 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5412
5413 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5414 // function'. "Space between sign and symbol or value" means that
5415 // if the sign is adjacent to the symbol, there's a space between
5416 // them, and otherwise there's a space between the sign and value.
5417 //
5418 // C11's localeconv specifies that the fourth character of an
5419 // international curr_symbol is used to separate the sign and
5420 // value when sep_by_space says to do so. C++ can't represent
5421 // that, so we just use a space. When sep_by_space says to
5422 // separate the symbol and value-or-sign with a space, we rearrange the
5423 // curr_symbol to put its spacing character on the correct side of
5424 // the symbol.
5425 //
5426 // We also need to avoid adding an extra space between the sign
5427 // and value when the currency symbol is suppressed (by not
5428 // setting showbase). We match glibc's strfmon by interpreting
5429 // sep_by_space==1 as "omit the space when the currency symbol is
5430 // absent".
5431 //
5432 // Users who want to get this right should use ICU instead.
5433
Howard Hinnantc51e1022010-05-11 19:42:16 +00005434 switch (cs_precedes)
5435 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005436 case 0: // value before curr_symbol
5437 if (symbol_contains_sep) {
5438 // Move the separator to before the symbol, to place it
5439 // between the value and symbol.
5440 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5441 __curr_symbol_.end());
5442 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005443 switch (sign_posn)
5444 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005445 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005446 pat.field[0] = sign;
5447 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005448 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005449 pat.field[3] = symbol;
5450 switch (sep_by_space)
5451 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005452 case 0: // No space separates the currency symbol and value.
5453 // This case may have changed between C99 and C11;
5454 // assume the currency symbol matches the intention.
5455 case 2: // Space between sign and currency or value.
5456 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005457 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005458 case 1: // Space between currency-and-sign or currency and value.
5459 if (!symbol_contains_sep) {
5460 // We insert the space into the symbol instead of
5461 // setting pat.field[2]=space so that when
5462 // showbase is not set, the space goes away too.
5463 __curr_symbol_.insert(0, 1, space_char);
5464 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005465 return;
5466 default:
5467 break;
5468 }
5469 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005470 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005471 pat.field[0] = sign;
5472 pat.field[3] = symbol;
5473 switch (sep_by_space)
5474 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005475 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005476 pat.field[1] = value;
5477 pat.field[2] = none;
5478 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005479 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005480 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005481 pat.field[2] = none;
5482 if (!symbol_contains_sep) {
5483 // We insert the space into the symbol instead of
5484 // setting pat.field[2]=space so that when
5485 // showbase is not set, the space goes away too.
5486 __curr_symbol_.insert(0, 1, space_char);
5487 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005488 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005489 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005490 pat.field[1] = space;
5491 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005492 if (symbol_contains_sep) {
5493 // Remove the separator from the symbol, since it
5494 // has already appeared after the sign.
5495 __curr_symbol_.erase(__curr_symbol_.begin());
5496 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005497 return;
5498 default:
5499 break;
5500 }
5501 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005502 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005503 pat.field[0] = value;
5504 pat.field[3] = sign;
5505 switch (sep_by_space)
5506 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005507 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005508 pat.field[1] = none;
5509 pat.field[2] = symbol;
5510 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005511 case 1: // Space between currency-and-sign or currency and value.
5512 if (!symbol_contains_sep) {
5513 // We insert the space into the symbol instead of
5514 // setting pat.field[1]=space so that when
5515 // showbase is not set, the space goes away too.
5516 __curr_symbol_.insert(0, 1, space_char);
5517 }
5518 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005519 pat.field[2] = symbol;
5520 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005521 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005522 pat.field[1] = symbol;
5523 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005524 if (symbol_contains_sep) {
5525 // Remove the separator from the symbol, since it
5526 // should not be removed if showbase is absent.
5527 __curr_symbol_.erase(__curr_symbol_.begin());
5528 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005529 return;
5530 default:
5531 break;
5532 }
5533 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005534 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005535 pat.field[0] = value;
5536 pat.field[3] = symbol;
5537 switch (sep_by_space)
5538 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005539 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005540 pat.field[1] = none;
5541 pat.field[2] = sign;
5542 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005543 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005544 pat.field[1] = space;
5545 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005546 if (symbol_contains_sep) {
5547 // Remove the separator from the symbol, since it
5548 // has already appeared before the sign.
5549 __curr_symbol_.erase(__curr_symbol_.begin());
5550 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005551 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005552 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005553 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005554 pat.field[2] = none;
5555 if (!symbol_contains_sep) {
5556 // We insert the space into the symbol instead of
5557 // setting pat.field[2]=space so that when
5558 // showbase is not set, the space goes away too.
5559 __curr_symbol_.insert(0, 1, space_char);
5560 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005561 return;
5562 default:
5563 break;
5564 }
5565 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005566 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005567 pat.field[0] = value;
5568 pat.field[3] = sign;
5569 switch (sep_by_space)
5570 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005571 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005572 pat.field[1] = none;
5573 pat.field[2] = symbol;
5574 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005575 case 1: // Space between currency-and-sign or currency and value.
5576 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005577 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005578 if (!symbol_contains_sep) {
5579 // We insert the space into the symbol instead of
5580 // setting pat.field[1]=space so that when
5581 // showbase is not set, the space goes away too.
5582 __curr_symbol_.insert(0, 1, space_char);
5583 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005584 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005585 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005586 pat.field[1] = symbol;
5587 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005588 if (symbol_contains_sep) {
5589 // Remove the separator from the symbol, since it
5590 // should not disappear when showbase is absent.
5591 __curr_symbol_.erase(__curr_symbol_.begin());
5592 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005593 return;
5594 default:
5595 break;
5596 }
5597 break;
5598 default:
5599 break;
5600 }
5601 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005602 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005603 switch (sign_posn)
5604 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005605 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005606 pat.field[0] = sign;
5607 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005608 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005609 pat.field[3] = value;
5610 switch (sep_by_space)
5611 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005612 case 0: // No space separates the currency symbol and value.
5613 // This case may have changed between C99 and C11;
5614 // assume the currency symbol matches the intention.
5615 case 2: // Space between sign and currency or value.
5616 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005617 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005618 case 1: // Space between currency-and-sign or currency and value.
5619 if (!symbol_contains_sep) {
5620 // We insert the space into the symbol instead of
5621 // setting pat.field[2]=space so that when
5622 // showbase is not set, the space goes away too.
5623 __curr_symbol_.insert(0, 1, space_char);
5624 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005625 return;
5626 default:
5627 break;
5628 }
5629 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005630 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005631 pat.field[0] = sign;
5632 pat.field[3] = value;
5633 switch (sep_by_space)
5634 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005635 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005636 pat.field[1] = symbol;
5637 pat.field[2] = none;
5638 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005639 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005640 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005641 pat.field[2] = none;
5642 if (!symbol_contains_sep) {
5643 // We insert the space into the symbol instead of
5644 // setting pat.field[2]=space so that when
5645 // showbase is not set, the space goes away too.
5646 __curr_symbol_.push_back(space_char);
5647 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005648 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005649 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005650 pat.field[1] = space;
5651 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005652 if (symbol_contains_sep) {
5653 // Remove the separator from the symbol, since it
5654 // has already appeared after the sign.
5655 __curr_symbol_.pop_back();
5656 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005657 return;
5658 default:
5659 break;
5660 }
5661 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005662 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005663 pat.field[0] = symbol;
5664 pat.field[3] = sign;
5665 switch (sep_by_space)
5666 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005667 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005668 pat.field[1] = none;
5669 pat.field[2] = value;
5670 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005671 case 1: // Space between currency-and-sign or currency and value.
5672 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005673 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005674 if (!symbol_contains_sep) {
5675 // We insert the space into the symbol instead of
5676 // setting pat.field[1]=space so that when
5677 // showbase is not set, the space goes away too.
5678 __curr_symbol_.push_back(space_char);
5679 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005680 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005681 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005682 pat.field[1] = value;
5683 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005684 if (symbol_contains_sep) {
5685 // Remove the separator from the symbol, since it
5686 // will appear before the sign.
5687 __curr_symbol_.pop_back();
5688 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005689 return;
5690 default:
5691 break;
5692 }
5693 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005694 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005695 pat.field[0] = sign;
5696 pat.field[3] = value;
5697 switch (sep_by_space)
5698 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005699 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005700 pat.field[1] = symbol;
5701 pat.field[2] = none;
5702 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005703 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005704 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005705 pat.field[2] = none;
5706 if (!symbol_contains_sep) {
5707 // We insert the space into the symbol instead of
5708 // setting pat.field[2]=space so that when
5709 // showbase is not set, the space goes away too.
5710 __curr_symbol_.push_back(space_char);
5711 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005712 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005713 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005714 pat.field[1] = space;
5715 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005716 if (symbol_contains_sep) {
5717 // Remove the separator from the symbol, since it
5718 // has already appeared after the sign.
5719 __curr_symbol_.pop_back();
5720 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005721 return;
5722 default:
5723 break;
5724 }
5725 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005726 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005727 pat.field[0] = symbol;
5728 pat.field[3] = value;
5729 switch (sep_by_space)
5730 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005731 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005732 pat.field[1] = sign;
5733 pat.field[2] = none;
5734 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005735 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005736 pat.field[1] = sign;
5737 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005738 if (symbol_contains_sep) {
5739 // Remove the separator from the symbol, since it
5740 // should not disappear when showbase is absent.
5741 __curr_symbol_.pop_back();
5742 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005743 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005744 case 2: // Space between sign and currency or value.
5745 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005746 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005747 if (!symbol_contains_sep) {
5748 // We insert the space into the symbol instead of
5749 // setting pat.field[1]=space so that when
5750 // showbase is not set, the space goes away too.
5751 __curr_symbol_.push_back(space_char);
5752 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005753 return;
5754 default:
5755 break;
5756 }
5757 break;
5758 default:
5759 break;
5760 }
5761 break;
5762 default:
5763 break;
5764 }
5765 pat.field[0] = symbol;
5766 pat.field[1] = sign;
5767 pat.field[2] = none;
5768 pat.field[3] = value;
5769}
5770
5771template<>
5772void
5773moneypunct_byname<char, false>::init(const char* nm)
5774{
5775 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005776 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005777 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005778 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005779 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005780
Ben Craig3756b922016-03-09 15:39:39 +00005781 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005782 if (*lc->mon_decimal_point)
5783 __decimal_point_ = *lc->mon_decimal_point;
5784 else
5785 __decimal_point_ = base::do_decimal_point();
5786 if (*lc->mon_thousands_sep)
5787 __thousands_sep_ = *lc->mon_thousands_sep;
5788 else
5789 __thousands_sep_ = base::do_thousands_sep();
5790 __grouping_ = lc->mon_grouping;
5791 __curr_symbol_ = lc->currency_symbol;
5792 if (lc->frac_digits != CHAR_MAX)
5793 __frac_digits_ = lc->frac_digits;
5794 else
5795 __frac_digits_ = base::do_frac_digits();
5796 if (lc->p_sign_posn == 0)
5797 __positive_sign_ = "()";
5798 else
5799 __positive_sign_ = lc->positive_sign;
5800 if (lc->n_sign_posn == 0)
5801 __negative_sign_ = "()";
5802 else
5803 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005804 // Assume the positive and negative formats will want spaces in
5805 // the same places in curr_symbol since there's no way to
5806 // represent anything else.
5807 string_type __dummy_curr_symbol = __curr_symbol_;
5808 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5809 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5810 __init_pat(__neg_format_, __curr_symbol_, false,
5811 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005812}
5813
5814template<>
5815void
5816moneypunct_byname<char, true>::init(const char* nm)
5817{
5818 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005819 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005820 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005821 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005822 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005823
Ben Craig3756b922016-03-09 15:39:39 +00005824 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005825 if (*lc->mon_decimal_point)
5826 __decimal_point_ = *lc->mon_decimal_point;
5827 else
5828 __decimal_point_ = base::do_decimal_point();
5829 if (*lc->mon_thousands_sep)
5830 __thousands_sep_ = *lc->mon_thousands_sep;
5831 else
5832 __thousands_sep_ = base::do_thousands_sep();
5833 __grouping_ = lc->mon_grouping;
5834 __curr_symbol_ = lc->int_curr_symbol;
5835 if (lc->int_frac_digits != CHAR_MAX)
5836 __frac_digits_ = lc->int_frac_digits;
5837 else
5838 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005839#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005840 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005841#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005842 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005843#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005844 __positive_sign_ = "()";
5845 else
5846 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005847#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005848 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005849#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005850 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005851#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005852 __negative_sign_ = "()";
5853 else
5854 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005855 // Assume the positive and negative formats will want spaces in
5856 // the same places in curr_symbol since there's no way to
5857 // represent anything else.
5858 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005859#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005860 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5861 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5862 __init_pat(__neg_format_, __curr_symbol_, true,
5863 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005864#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005865 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5866 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5867 lc->int_p_sign_posn, ' ');
5868 __init_pat(__neg_format_, __curr_symbol_, true,
5869 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5870 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005871#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005872}
5873
5874template<>
5875void
5876moneypunct_byname<wchar_t, false>::init(const char* nm)
5877{
5878 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005879 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005880 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005881 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005882 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00005883 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005884 if (*lc->mon_decimal_point)
5885 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5886 else
5887 __decimal_point_ = base::do_decimal_point();
5888 if (*lc->mon_thousands_sep)
5889 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5890 else
5891 __thousands_sep_ = base::do_thousands_sep();
5892 __grouping_ = lc->mon_grouping;
5893 wchar_t wbuf[100];
5894 mbstate_t mb = {0};
5895 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005896 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005897 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005898 __throw_runtime_error("locale not supported");
5899 wchar_t* wbe = wbuf + j;
5900 __curr_symbol_.assign(wbuf, wbe);
5901 if (lc->frac_digits != CHAR_MAX)
5902 __frac_digits_ = lc->frac_digits;
5903 else
5904 __frac_digits_ = base::do_frac_digits();
5905 if (lc->p_sign_posn == 0)
5906 __positive_sign_ = L"()";
5907 else
5908 {
5909 mb = mbstate_t();
5910 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005911 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005912 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005913 __throw_runtime_error("locale not supported");
5914 wbe = wbuf + j;
5915 __positive_sign_.assign(wbuf, wbe);
5916 }
5917 if (lc->n_sign_posn == 0)
5918 __negative_sign_ = L"()";
5919 else
5920 {
5921 mb = mbstate_t();
5922 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005923 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005924 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005925 __throw_runtime_error("locale not supported");
5926 wbe = wbuf + j;
5927 __negative_sign_.assign(wbuf, wbe);
5928 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005929 // Assume the positive and negative formats will want spaces in
5930 // the same places in curr_symbol since there's no way to
5931 // represent anything else.
5932 string_type __dummy_curr_symbol = __curr_symbol_;
5933 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5934 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5935 __init_pat(__neg_format_, __curr_symbol_, false,
5936 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005937}
5938
5939template<>
5940void
5941moneypunct_byname<wchar_t, true>::init(const char* nm)
5942{
5943 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005944 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005945 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005946 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005947 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005948
Ben Craig3756b922016-03-09 15:39:39 +00005949 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005950 if (*lc->mon_decimal_point)
5951 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5952 else
5953 __decimal_point_ = base::do_decimal_point();
5954 if (*lc->mon_thousands_sep)
5955 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5956 else
5957 __thousands_sep_ = base::do_thousands_sep();
5958 __grouping_ = lc->mon_grouping;
5959 wchar_t wbuf[100];
5960 mbstate_t mb = {0};
5961 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005962 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005963 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005964 __throw_runtime_error("locale not supported");
5965 wchar_t* wbe = wbuf + j;
5966 __curr_symbol_.assign(wbuf, wbe);
5967 if (lc->int_frac_digits != CHAR_MAX)
5968 __frac_digits_ = lc->int_frac_digits;
5969 else
5970 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005971#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005972 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005973#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005974 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005975#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005976 __positive_sign_ = L"()";
5977 else
5978 {
5979 mb = mbstate_t();
5980 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005981 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005982 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005983 __throw_runtime_error("locale not supported");
5984 wbe = wbuf + j;
5985 __positive_sign_.assign(wbuf, wbe);
5986 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00005987#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005988 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005989#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005990 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005991#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005992 __negative_sign_ = L"()";
5993 else
5994 {
5995 mb = mbstate_t();
5996 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005997 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005998 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005999 __throw_runtime_error("locale not supported");
6000 wbe = wbuf + j;
6001 __negative_sign_.assign(wbuf, wbe);
6002 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006003 // Assume the positive and negative formats will want spaces in
6004 // the same places in curr_symbol since there's no way to
6005 // represent anything else.
6006 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006007#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006008 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6009 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6010 __init_pat(__neg_format_, __curr_symbol_, true,
6011 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006012#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006013 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6014 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6015 lc->int_p_sign_posn, L' ');
6016 __init_pat(__neg_format_, __curr_symbol_, true,
6017 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6018 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006019#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006020}
6021
6022void __do_nothing(void*) {}
6023
6024void __throw_runtime_error(const char* msg)
6025{
Howard Hinnant72f73582010-08-11 17:04:31 +00006026#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006027 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006028#else
6029 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006030 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006031#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006032}
6033
6034template class collate<char>;
6035template class collate<wchar_t>;
6036
6037template class num_get<char>;
6038template class num_get<wchar_t>;
6039
Howard Hinnant28b24882011-12-01 20:21:04 +00006040template struct __num_get<char>;
6041template struct __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006042
6043template class num_put<char>;
6044template class num_put<wchar_t>;
6045
Howard Hinnant28b24882011-12-01 20:21:04 +00006046template struct __num_put<char>;
6047template struct __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006048
6049template class time_get<char>;
6050template class time_get<wchar_t>;
6051
6052template class time_get_byname<char>;
6053template class time_get_byname<wchar_t>;
6054
6055template class time_put<char>;
6056template class time_put<wchar_t>;
6057
6058template class time_put_byname<char>;
6059template class time_put_byname<wchar_t>;
6060
6061template class moneypunct<char, false>;
6062template class moneypunct<char, true>;
6063template class moneypunct<wchar_t, false>;
6064template class moneypunct<wchar_t, true>;
6065
6066template class moneypunct_byname<char, false>;
6067template class moneypunct_byname<char, true>;
6068template class moneypunct_byname<wchar_t, false>;
6069template class moneypunct_byname<wchar_t, true>;
6070
6071template class money_get<char>;
6072template class money_get<wchar_t>;
6073
6074template class __money_get<char>;
6075template class __money_get<wchar_t>;
6076
6077template class money_put<char>;
6078template class money_put<wchar_t>;
6079
6080template class __money_put<char>;
6081template class __money_put<wchar_t>;
6082
6083template class messages<char>;
6084template class messages<wchar_t>;
6085
6086template class messages_byname<char>;
6087template class messages_byname<wchar_t>;
6088
6089template class codecvt_byname<char, char, mbstate_t>;
6090template class codecvt_byname<wchar_t, char, mbstate_t>;
6091template class codecvt_byname<char16_t, char, mbstate_t>;
6092template class codecvt_byname<char32_t, char, mbstate_t>;
6093
6094template class __vector_base_common<true>;
6095
6096_LIBCPP_END_NAMESPACE_STD