blob: 5d6ccd5fb02ec9c79a3a158f4aaaf3353b9c79d8 [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
Eric Fiselierbf945a22016-12-11 00:20:59 +00004186
4187static bool checked_string_to_wchar_convert(wchar_t& dest,
4188 const char* ptr,
4189 __locale_struct* loc) {
4190 if (*ptr == '\0')
4191 return false;
4192 mbstate_t mb = {};
4193 wchar_t out;
4194 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4195 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4196 return false;
4197 }
4198 dest = out;
4199 return true;
4200}
4201
4202static bool checked_string_to_char_convert(char& dest,
4203 const char* ptr,
4204 __locale_struct* __loc) {
4205 if (*ptr == '\0')
4206 return false;
4207 if (!ptr[1]) {
4208 dest = *ptr;
4209 return true;
4210 }
4211 // First convert the MBS into a wide char then attempt to narrow it using
4212 // wctob_l.
4213 wchar_t wout;
4214 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4215 return false;
4216 int res;
4217 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4218 dest = res;
4219 return true;
4220 }
4221 // FIXME: Work around specific multibyte sequences that we can reasonable
4222 // translate into a different single byte.
4223 switch (wout) {
4224 case L'\u00A0': // non-breaking space
4225 dest = ' ';
4226 return true;
4227 default:
4228 return false;
4229 }
4230 _LIBCPP_UNREACHABLE();
4231}
4232
4233
Howard Hinnantc51e1022010-05-11 19:42:16 +00004234// numpunct<char> && numpunct<wchar_t>
4235
4236locale::id numpunct< char >::id;
4237locale::id numpunct<wchar_t>::id;
4238
4239numpunct<char>::numpunct(size_t refs)
4240 : locale::facet(refs),
4241 __decimal_point_('.'),
4242 __thousands_sep_(',')
4243{
4244}
4245
4246numpunct<wchar_t>::numpunct(size_t refs)
4247 : locale::facet(refs),
4248 __decimal_point_(L'.'),
4249 __thousands_sep_(L',')
4250{
4251}
4252
4253numpunct<char>::~numpunct()
4254{
4255}
4256
4257numpunct<wchar_t>::~numpunct()
4258{
4259}
4260
4261 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4262wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4263
4264 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4265wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4266
4267string numpunct< char >::do_grouping() const {return __grouping_;}
4268string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4269
4270 string numpunct< char >::do_truename() const {return "true";}
4271wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4272
4273 string numpunct< char >::do_falsename() const {return "false";}
4274wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4275
4276// numpunct_byname<char>
4277
4278numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4279 : numpunct<char>(refs)
4280{
4281 __init(nm);
4282}
4283
4284numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4285 : numpunct<char>(refs)
4286{
4287 __init(nm.c_str());
4288}
4289
4290numpunct_byname<char>::~numpunct_byname()
4291{
4292}
4293
4294void
4295numpunct_byname<char>::__init(const char* nm)
4296{
4297 if (strcmp(nm, "C") != 0)
4298 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004299 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00004300 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00004301 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004302 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004303
Ben Craig3756b922016-03-09 15:39:39 +00004304 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004305 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4306 loc.get());
4307 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4308 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004309 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004310 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004311 }
4312}
4313
4314// numpunct_byname<wchar_t>
4315
4316numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4317 : numpunct<wchar_t>(refs)
4318{
4319 __init(nm);
4320}
4321
4322numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4323 : numpunct<wchar_t>(refs)
4324{
4325 __init(nm.c_str());
4326}
4327
4328numpunct_byname<wchar_t>::~numpunct_byname()
4329{
4330}
4331
4332void
4333numpunct_byname<wchar_t>::__init(const char* nm)
4334{
4335 if (strcmp(nm, "C") != 0)
4336 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004337 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00004338 if (loc == nullptr)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004339 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004340 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004341
Ben Craig3756b922016-03-09 15:39:39 +00004342 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004343 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4344 loc.get());
4345 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4346 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004347 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004348 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004349 }
4350}
4351
4352// num_get helpers
4353
4354int
4355__num_get_base::__get_base(ios_base& iob)
4356{
4357 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4358 if (__basefield == ios_base::oct)
4359 return 8;
4360 else if (__basefield == ios_base::hex)
4361 return 16;
4362 else if (__basefield == 0)
4363 return 0;
4364 return 10;
4365}
4366
4367const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4368
4369void
4370__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4371 ios_base::iostate& __err)
4372{
4373 if (__grouping.size() != 0)
4374 {
4375 reverse(__g, __g_end);
4376 const char* __ig = __grouping.data();
4377 const char* __eg = __ig + __grouping.size();
4378 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4379 {
4380 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4381 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004382 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004383 {
4384 __err = ios_base::failbit;
4385 return;
4386 }
4387 }
4388 if (__eg - __ig > 1)
4389 ++__ig;
4390 }
4391 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4392 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004393 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004394 __err = ios_base::failbit;
4395 }
4396 }
4397}
4398
4399void
4400__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4401 ios_base::fmtflags __flags)
4402{
4403 if (__flags & ios_base::showpos)
4404 *__fmtp++ = '+';
4405 if (__flags & ios_base::showbase)
4406 *__fmtp++ = '#';
4407 while(*__len)
4408 *__fmtp++ = *__len++;
4409 if ((__flags & ios_base::basefield) == ios_base::oct)
4410 *__fmtp = 'o';
4411 else if ((__flags & ios_base::basefield) == ios_base::hex)
4412 {
4413 if (__flags & ios_base::uppercase)
4414 *__fmtp = 'X';
4415 else
4416 *__fmtp = 'x';
4417 }
4418 else if (__signd)
4419 *__fmtp = 'd';
4420 else
4421 *__fmtp = 'u';
4422}
4423
4424bool
4425__num_put_base::__format_float(char* __fmtp, const char* __len,
4426 ios_base::fmtflags __flags)
4427{
4428 bool specify_precision = true;
4429 if (__flags & ios_base::showpos)
4430 *__fmtp++ = '+';
4431 if (__flags & ios_base::showpoint)
4432 *__fmtp++ = '#';
4433 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004434 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004435 if (floatfield == (ios_base::fixed | ios_base::scientific))
4436 specify_precision = false;
4437 else
4438 {
4439 *__fmtp++ = '.';
4440 *__fmtp++ = '*';
4441 }
4442 while(*__len)
4443 *__fmtp++ = *__len++;
4444 if (floatfield == ios_base::fixed)
4445 {
4446 if (uppercase)
4447 *__fmtp = 'F';
4448 else
4449 *__fmtp = 'f';
4450 }
4451 else if (floatfield == ios_base::scientific)
4452 {
4453 if (uppercase)
4454 *__fmtp = 'E';
4455 else
4456 *__fmtp = 'e';
4457 }
4458 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4459 {
4460 if (uppercase)
4461 *__fmtp = 'A';
4462 else
4463 *__fmtp = 'a';
4464 }
4465 else
4466 {
4467 if (uppercase)
4468 *__fmtp = 'G';
4469 else
4470 *__fmtp = 'g';
4471 }
4472 return specify_precision;
4473}
4474
4475char*
4476__num_put_base::__identify_padding(char* __nb, char* __ne,
4477 const ios_base& __iob)
4478{
4479 switch (__iob.flags() & ios_base::adjustfield)
4480 {
4481 case ios_base::internal:
4482 if (__nb[0] == '-' || __nb[0] == '+')
4483 return __nb+1;
4484 if (__ne - __nb >= 2 && __nb[0] == '0'
4485 && (__nb[1] == 'x' || __nb[1] == 'X'))
4486 return __nb+2;
4487 break;
4488 case ios_base::left:
4489 return __ne;
4490 case ios_base::right:
4491 default:
4492 break;
4493 }
4494 return __nb;
4495}
4496
4497// time_get
4498
4499static
4500string*
4501init_weeks()
4502{
4503 static string weeks[14];
4504 weeks[0] = "Sunday";
4505 weeks[1] = "Monday";
4506 weeks[2] = "Tuesday";
4507 weeks[3] = "Wednesday";
4508 weeks[4] = "Thursday";
4509 weeks[5] = "Friday";
4510 weeks[6] = "Saturday";
4511 weeks[7] = "Sun";
4512 weeks[8] = "Mon";
4513 weeks[9] = "Tue";
4514 weeks[10] = "Wed";
4515 weeks[11] = "Thu";
4516 weeks[12] = "Fri";
4517 weeks[13] = "Sat";
4518 return weeks;
4519}
4520
4521static
4522wstring*
4523init_wweeks()
4524{
4525 static wstring weeks[14];
4526 weeks[0] = L"Sunday";
4527 weeks[1] = L"Monday";
4528 weeks[2] = L"Tuesday";
4529 weeks[3] = L"Wednesday";
4530 weeks[4] = L"Thursday";
4531 weeks[5] = L"Friday";
4532 weeks[6] = L"Saturday";
4533 weeks[7] = L"Sun";
4534 weeks[8] = L"Mon";
4535 weeks[9] = L"Tue";
4536 weeks[10] = L"Wed";
4537 weeks[11] = L"Thu";
4538 weeks[12] = L"Fri";
4539 weeks[13] = L"Sat";
4540 return weeks;
4541}
4542
4543template <>
4544const string*
4545__time_get_c_storage<char>::__weeks() const
4546{
4547 static const string* weeks = init_weeks();
4548 return weeks;
4549}
4550
4551template <>
4552const wstring*
4553__time_get_c_storage<wchar_t>::__weeks() const
4554{
4555 static const wstring* weeks = init_wweeks();
4556 return weeks;
4557}
4558
4559static
4560string*
4561init_months()
4562{
4563 static string months[24];
4564 months[0] = "January";
4565 months[1] = "February";
4566 months[2] = "March";
4567 months[3] = "April";
4568 months[4] = "May";
4569 months[5] = "June";
4570 months[6] = "July";
4571 months[7] = "August";
4572 months[8] = "September";
4573 months[9] = "October";
4574 months[10] = "November";
4575 months[11] = "December";
4576 months[12] = "Jan";
4577 months[13] = "Feb";
4578 months[14] = "Mar";
4579 months[15] = "Apr";
4580 months[16] = "May";
4581 months[17] = "Jun";
4582 months[18] = "Jul";
4583 months[19] = "Aug";
4584 months[20] = "Sep";
4585 months[21] = "Oct";
4586 months[22] = "Nov";
4587 months[23] = "Dec";
4588 return months;
4589}
4590
4591static
4592wstring*
4593init_wmonths()
4594{
4595 static wstring months[24];
4596 months[0] = L"January";
4597 months[1] = L"February";
4598 months[2] = L"March";
4599 months[3] = L"April";
4600 months[4] = L"May";
4601 months[5] = L"June";
4602 months[6] = L"July";
4603 months[7] = L"August";
4604 months[8] = L"September";
4605 months[9] = L"October";
4606 months[10] = L"November";
4607 months[11] = L"December";
4608 months[12] = L"Jan";
4609 months[13] = L"Feb";
4610 months[14] = L"Mar";
4611 months[15] = L"Apr";
4612 months[16] = L"May";
4613 months[17] = L"Jun";
4614 months[18] = L"Jul";
4615 months[19] = L"Aug";
4616 months[20] = L"Sep";
4617 months[21] = L"Oct";
4618 months[22] = L"Nov";
4619 months[23] = L"Dec";
4620 return months;
4621}
4622
4623template <>
4624const string*
4625__time_get_c_storage<char>::__months() const
4626{
4627 static const string* months = init_months();
4628 return months;
4629}
4630
4631template <>
4632const wstring*
4633__time_get_c_storage<wchar_t>::__months() const
4634{
4635 static const wstring* months = init_wmonths();
4636 return months;
4637}
4638
4639static
4640string*
4641init_am_pm()
4642{
4643 static string am_pm[24];
4644 am_pm[0] = "AM";
4645 am_pm[1] = "PM";
4646 return am_pm;
4647}
4648
4649static
4650wstring*
4651init_wam_pm()
4652{
4653 static wstring am_pm[24];
4654 am_pm[0] = L"AM";
4655 am_pm[1] = L"PM";
4656 return am_pm;
4657}
4658
4659template <>
4660const string*
4661__time_get_c_storage<char>::__am_pm() const
4662{
4663 static const string* am_pm = init_am_pm();
4664 return am_pm;
4665}
4666
4667template <>
4668const wstring*
4669__time_get_c_storage<wchar_t>::__am_pm() const
4670{
4671 static const wstring* am_pm = init_wam_pm();
4672 return am_pm;
4673}
4674
4675template <>
4676const string&
4677__time_get_c_storage<char>::__x() const
4678{
4679 static string s("%m/%d/%y");
4680 return s;
4681}
4682
4683template <>
4684const wstring&
4685__time_get_c_storage<wchar_t>::__x() const
4686{
4687 static wstring s(L"%m/%d/%y");
4688 return s;
4689}
4690
4691template <>
4692const string&
4693__time_get_c_storage<char>::__X() const
4694{
4695 static string s("%H:%M:%S");
4696 return s;
4697}
4698
4699template <>
4700const wstring&
4701__time_get_c_storage<wchar_t>::__X() const
4702{
4703 static wstring s(L"%H:%M:%S");
4704 return s;
4705}
4706
4707template <>
4708const string&
4709__time_get_c_storage<char>::__c() const
4710{
4711 static string s("%a %b %d %H:%M:%S %Y");
4712 return s;
4713}
4714
4715template <>
4716const wstring&
4717__time_get_c_storage<wchar_t>::__c() const
4718{
4719 static wstring s(L"%a %b %d %H:%M:%S %Y");
4720 return s;
4721}
4722
4723template <>
4724const string&
4725__time_get_c_storage<char>::__r() const
4726{
4727 static string s("%I:%M:%S %p");
4728 return s;
4729}
4730
4731template <>
4732const wstring&
4733__time_get_c_storage<wchar_t>::__r() const
4734{
4735 static wstring s(L"%I:%M:%S %p");
4736 return s;
4737}
4738
4739// time_get_byname
4740
4741__time_get::__time_get(const char* nm)
4742 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4743{
4744 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004745 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004746 " failed to construct for " + string(nm));
4747}
4748
4749__time_get::__time_get(const string& nm)
4750 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4751{
4752 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004753 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004754 " failed to construct for " + nm);
4755}
4756
4757__time_get::~__time_get()
4758{
4759 freelocale(__loc_);
4760}
Marshall Clowd920eea2013-10-21 15:07:28 +00004761#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004762#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004763#endif
4764#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004765#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004766#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004767
Howard Hinnantc51e1022010-05-11 19:42:16 +00004768template <>
4769string
4770__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4771{
Howard Hinnant990207c2012-02-19 14:55:32 +00004772 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004773 t.tm_sec = 59;
4774 t.tm_min = 55;
4775 t.tm_hour = 23;
4776 t.tm_mday = 31;
4777 t.tm_mon = 11;
4778 t.tm_year = 161;
4779 t.tm_wday = 6;
4780 t.tm_yday = 364;
4781 t.tm_isdst = -1;
4782 char buf[100];
4783 char f[3] = {0};
4784 f[0] = '%';
4785 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004786 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004787 char* bb = buf;
4788 char* be = buf + n;
4789 string result;
4790 while (bb != be)
4791 {
4792 if (ct.is(ctype_base::space, *bb))
4793 {
4794 result.push_back(' ');
4795 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4796 ;
4797 continue;
4798 }
4799 char* w = bb;
4800 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004801 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004802 ct, err, false)
4803 - this->__weeks_;
4804 if (i < 14)
4805 {
4806 result.push_back('%');
4807 if (i < 7)
4808 result.push_back('A');
4809 else
4810 result.push_back('a');
4811 bb = w;
4812 continue;
4813 }
4814 w = bb;
4815 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4816 ct, err, false)
4817 - this->__months_;
4818 if (i < 24)
4819 {
4820 result.push_back('%');
4821 if (i < 12)
4822 result.push_back('B');
4823 else
4824 result.push_back('b');
4825 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4826 result.back() = 'm';
4827 bb = w;
4828 continue;
4829 }
4830 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4831 {
4832 w = bb;
4833 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4834 ct, err, false) - this->__am_pm_;
4835 if (i < 2)
4836 {
4837 result.push_back('%');
4838 result.push_back('p');
4839 bb = w;
4840 continue;
4841 }
4842 }
4843 w = bb;
4844 if (ct.is(ctype_base::digit, *bb))
4845 {
4846 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4847 {
4848 case 6:
4849 result.push_back('%');
4850 result.push_back('w');
4851 break;
4852 case 7:
4853 result.push_back('%');
4854 result.push_back('u');
4855 break;
4856 case 11:
4857 result.push_back('%');
4858 result.push_back('I');
4859 break;
4860 case 12:
4861 result.push_back('%');
4862 result.push_back('m');
4863 break;
4864 case 23:
4865 result.push_back('%');
4866 result.push_back('H');
4867 break;
4868 case 31:
4869 result.push_back('%');
4870 result.push_back('d');
4871 break;
4872 case 55:
4873 result.push_back('%');
4874 result.push_back('M');
4875 break;
4876 case 59:
4877 result.push_back('%');
4878 result.push_back('S');
4879 break;
4880 case 61:
4881 result.push_back('%');
4882 result.push_back('y');
4883 break;
4884 case 364:
4885 result.push_back('%');
4886 result.push_back('j');
4887 break;
4888 case 2061:
4889 result.push_back('%');
4890 result.push_back('Y');
4891 break;
4892 default:
4893 for (; w != bb; ++w)
4894 result.push_back(*w);
4895 break;
4896 }
4897 continue;
4898 }
4899 if (*bb == '%')
4900 {
4901 result.push_back('%');
4902 result.push_back('%');
4903 ++bb;
4904 continue;
4905 }
4906 result.push_back(*bb);
4907 ++bb;
4908 }
4909 return result;
4910}
4911
Marshall Clowd920eea2013-10-21 15:07:28 +00004912#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004913#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004914#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004915
Howard Hinnantc51e1022010-05-11 19:42:16 +00004916template <>
4917wstring
4918__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4919{
Howard Hinnant990207c2012-02-19 14:55:32 +00004920 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004921 t.tm_sec = 59;
4922 t.tm_min = 55;
4923 t.tm_hour = 23;
4924 t.tm_mday = 31;
4925 t.tm_mon = 11;
4926 t.tm_year = 161;
4927 t.tm_wday = 6;
4928 t.tm_yday = 364;
4929 t.tm_isdst = -1;
4930 char buf[100];
4931 char f[3] = {0};
4932 f[0] = '%';
4933 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004934 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004935 wchar_t wbuf[100];
4936 wchar_t* wbb = wbuf;
4937 mbstate_t mb = {0};
4938 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004939 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004940 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004941 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004942 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004943 wstring result;
4944 while (wbb != wbe)
4945 {
4946 if (ct.is(ctype_base::space, *wbb))
4947 {
4948 result.push_back(L' ');
4949 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4950 ;
4951 continue;
4952 }
4953 wchar_t* w = wbb;
4954 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004955 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004956 ct, err, false)
4957 - this->__weeks_;
4958 if (i < 14)
4959 {
4960 result.push_back(L'%');
4961 if (i < 7)
4962 result.push_back(L'A');
4963 else
4964 result.push_back(L'a');
4965 wbb = w;
4966 continue;
4967 }
4968 w = wbb;
4969 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4970 ct, err, false)
4971 - this->__months_;
4972 if (i < 24)
4973 {
4974 result.push_back(L'%');
4975 if (i < 12)
4976 result.push_back(L'B');
4977 else
4978 result.push_back(L'b');
4979 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4980 result.back() = L'm';
4981 wbb = w;
4982 continue;
4983 }
4984 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4985 {
4986 w = wbb;
4987 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4988 ct, err, false) - this->__am_pm_;
4989 if (i < 2)
4990 {
4991 result.push_back(L'%');
4992 result.push_back(L'p');
4993 wbb = w;
4994 continue;
4995 }
4996 }
4997 w = wbb;
4998 if (ct.is(ctype_base::digit, *wbb))
4999 {
5000 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5001 {
5002 case 6:
5003 result.push_back(L'%');
5004 result.push_back(L'w');
5005 break;
5006 case 7:
5007 result.push_back(L'%');
5008 result.push_back(L'u');
5009 break;
5010 case 11:
5011 result.push_back(L'%');
5012 result.push_back(L'I');
5013 break;
5014 case 12:
5015 result.push_back(L'%');
5016 result.push_back(L'm');
5017 break;
5018 case 23:
5019 result.push_back(L'%');
5020 result.push_back(L'H');
5021 break;
5022 case 31:
5023 result.push_back(L'%');
5024 result.push_back(L'd');
5025 break;
5026 case 55:
5027 result.push_back(L'%');
5028 result.push_back(L'M');
5029 break;
5030 case 59:
5031 result.push_back(L'%');
5032 result.push_back(L'S');
5033 break;
5034 case 61:
5035 result.push_back(L'%');
5036 result.push_back(L'y');
5037 break;
5038 case 364:
5039 result.push_back(L'%');
5040 result.push_back(L'j');
5041 break;
5042 case 2061:
5043 result.push_back(L'%');
5044 result.push_back(L'Y');
5045 break;
5046 default:
5047 for (; w != wbb; ++w)
5048 result.push_back(*w);
5049 break;
5050 }
5051 continue;
5052 }
5053 if (ct.narrow(*wbb, 0) == '%')
5054 {
5055 result.push_back(L'%');
5056 result.push_back(L'%');
5057 ++wbb;
5058 continue;
5059 }
5060 result.push_back(*wbb);
5061 ++wbb;
5062 }
5063 return result;
5064}
5065
5066template <>
5067void
5068__time_get_storage<char>::init(const ctype<char>& ct)
5069{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005070 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005071 char buf[100];
5072 // __weeks_
5073 for (int i = 0; i < 7; ++i)
5074 {
5075 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005076 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005077 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005078 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005079 __weeks_[i+7] = buf;
5080 }
5081 // __months_
5082 for (int i = 0; i < 12; ++i)
5083 {
5084 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005085 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005086 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005087 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005088 __months_[i+12] = buf;
5089 }
5090 // __am_pm_
5091 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005092 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005093 __am_pm_[0] = buf;
5094 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005095 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005096 __am_pm_[1] = buf;
5097 __c_ = __analyze('c', ct);
5098 __r_ = __analyze('r', ct);
5099 __x_ = __analyze('x', ct);
5100 __X_ = __analyze('X', ct);
5101}
5102
5103template <>
5104void
5105__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5106{
5107 tm t = {0};
5108 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005109 wchar_t wbuf[100];
5110 wchar_t* wbe;
5111 mbstate_t mb = {0};
5112 // __weeks_
5113 for (int i = 0; i < 7; ++i)
5114 {
5115 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005116 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005117 mb = mbstate_t();
5118 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005119 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005120 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005121 __throw_runtime_error("locale not supported");
5122 wbe = wbuf + j;
5123 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005124 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005125 mb = mbstate_t();
5126 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005127 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005128 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005129 __throw_runtime_error("locale not supported");
5130 wbe = wbuf + j;
5131 __weeks_[i+7].assign(wbuf, wbe);
5132 }
5133 // __months_
5134 for (int i = 0; i < 12; ++i)
5135 {
5136 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005137 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005138 mb = mbstate_t();
5139 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005140 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005141 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005142 __throw_runtime_error("locale not supported");
5143 wbe = wbuf + j;
5144 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005145 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005146 mb = mbstate_t();
5147 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005148 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005149 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005150 __throw_runtime_error("locale not supported");
5151 wbe = wbuf + j;
5152 __months_[i+12].assign(wbuf, wbe);
5153 }
5154 // __am_pm_
5155 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005156 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005157 mb = mbstate_t();
5158 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005159 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005160 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005161 __throw_runtime_error("locale not supported");
5162 wbe = wbuf + j;
5163 __am_pm_[0].assign(wbuf, wbe);
5164 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005165 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005166 mb = mbstate_t();
5167 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005168 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005169 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005170 __throw_runtime_error("locale not supported");
5171 wbe = wbuf + j;
5172 __am_pm_[1].assign(wbuf, wbe);
5173 __c_ = __analyze('c', ct);
5174 __r_ = __analyze('r', ct);
5175 __x_ = __analyze('x', ct);
5176 __X_ = __analyze('X', ct);
5177}
5178
5179template <class CharT>
5180struct _LIBCPP_HIDDEN __time_get_temp
5181 : public ctype_byname<CharT>
5182{
5183 explicit __time_get_temp(const char* nm)
5184 : ctype_byname<CharT>(nm, 1) {}
5185 explicit __time_get_temp(const string& nm)
5186 : ctype_byname<CharT>(nm, 1) {}
5187};
5188
5189template <>
5190__time_get_storage<char>::__time_get_storage(const char* __nm)
5191 : __time_get(__nm)
5192{
5193 const __time_get_temp<char> ct(__nm);
5194 init(ct);
5195}
5196
5197template <>
5198__time_get_storage<char>::__time_get_storage(const string& __nm)
5199 : __time_get(__nm)
5200{
5201 const __time_get_temp<char> ct(__nm);
5202 init(ct);
5203}
5204
5205template <>
5206__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5207 : __time_get(__nm)
5208{
5209 const __time_get_temp<wchar_t> ct(__nm);
5210 init(ct);
5211}
5212
5213template <>
5214__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5215 : __time_get(__nm)
5216{
5217 const __time_get_temp<wchar_t> ct(__nm);
5218 init(ct);
5219}
5220
5221template <>
5222time_base::dateorder
5223__time_get_storage<char>::__do_date_order() const
5224{
5225 unsigned i;
5226 for (i = 0; i < __x_.size(); ++i)
5227 if (__x_[i] == '%')
5228 break;
5229 ++i;
5230 switch (__x_[i])
5231 {
5232 case 'y':
5233 case 'Y':
5234 for (++i; i < __x_.size(); ++i)
5235 if (__x_[i] == '%')
5236 break;
5237 if (i == __x_.size())
5238 break;
5239 ++i;
5240 switch (__x_[i])
5241 {
5242 case 'm':
5243 for (++i; i < __x_.size(); ++i)
5244 if (__x_[i] == '%')
5245 break;
5246 if (i == __x_.size())
5247 break;
5248 ++i;
5249 if (__x_[i] == 'd')
5250 return time_base::ymd;
5251 break;
5252 case 'd':
5253 for (++i; i < __x_.size(); ++i)
5254 if (__x_[i] == '%')
5255 break;
5256 if (i == __x_.size())
5257 break;
5258 ++i;
5259 if (__x_[i] == 'm')
5260 return time_base::ydm;
5261 break;
5262 }
5263 break;
5264 case 'm':
5265 for (++i; i < __x_.size(); ++i)
5266 if (__x_[i] == '%')
5267 break;
5268 if (i == __x_.size())
5269 break;
5270 ++i;
5271 if (__x_[i] == 'd')
5272 {
5273 for (++i; i < __x_.size(); ++i)
5274 if (__x_[i] == '%')
5275 break;
5276 if (i == __x_.size())
5277 break;
5278 ++i;
5279 if (__x_[i] == 'y' || __x_[i] == 'Y')
5280 return time_base::mdy;
5281 break;
5282 }
5283 break;
5284 case 'd':
5285 for (++i; i < __x_.size(); ++i)
5286 if (__x_[i] == '%')
5287 break;
5288 if (i == __x_.size())
5289 break;
5290 ++i;
5291 if (__x_[i] == 'm')
5292 {
5293 for (++i; i < __x_.size(); ++i)
5294 if (__x_[i] == '%')
5295 break;
5296 if (i == __x_.size())
5297 break;
5298 ++i;
5299 if (__x_[i] == 'y' || __x_[i] == 'Y')
5300 return time_base::dmy;
5301 break;
5302 }
5303 break;
5304 }
5305 return time_base::no_order;
5306}
5307
5308template <>
5309time_base::dateorder
5310__time_get_storage<wchar_t>::__do_date_order() const
5311{
5312 unsigned i;
5313 for (i = 0; i < __x_.size(); ++i)
5314 if (__x_[i] == L'%')
5315 break;
5316 ++i;
5317 switch (__x_[i])
5318 {
5319 case L'y':
5320 case L'Y':
5321 for (++i; i < __x_.size(); ++i)
5322 if (__x_[i] == L'%')
5323 break;
5324 if (i == __x_.size())
5325 break;
5326 ++i;
5327 switch (__x_[i])
5328 {
5329 case L'm':
5330 for (++i; i < __x_.size(); ++i)
5331 if (__x_[i] == L'%')
5332 break;
5333 if (i == __x_.size())
5334 break;
5335 ++i;
5336 if (__x_[i] == L'd')
5337 return time_base::ymd;
5338 break;
5339 case L'd':
5340 for (++i; i < __x_.size(); ++i)
5341 if (__x_[i] == L'%')
5342 break;
5343 if (i == __x_.size())
5344 break;
5345 ++i;
5346 if (__x_[i] == L'm')
5347 return time_base::ydm;
5348 break;
5349 }
5350 break;
5351 case L'm':
5352 for (++i; i < __x_.size(); ++i)
5353 if (__x_[i] == L'%')
5354 break;
5355 if (i == __x_.size())
5356 break;
5357 ++i;
5358 if (__x_[i] == L'd')
5359 {
5360 for (++i; i < __x_.size(); ++i)
5361 if (__x_[i] == L'%')
5362 break;
5363 if (i == __x_.size())
5364 break;
5365 ++i;
5366 if (__x_[i] == L'y' || __x_[i] == L'Y')
5367 return time_base::mdy;
5368 break;
5369 }
5370 break;
5371 case L'd':
5372 for (++i; i < __x_.size(); ++i)
5373 if (__x_[i] == L'%')
5374 break;
5375 if (i == __x_.size())
5376 break;
5377 ++i;
5378 if (__x_[i] == L'm')
5379 {
5380 for (++i; i < __x_.size(); ++i)
5381 if (__x_[i] == L'%')
5382 break;
5383 if (i == __x_.size())
5384 break;
5385 ++i;
5386 if (__x_[i] == L'y' || __x_[i] == L'Y')
5387 return time_base::dmy;
5388 break;
5389 }
5390 break;
5391 }
5392 return time_base::no_order;
5393}
5394
5395// time_put
5396
5397__time_put::__time_put(const char* nm)
5398 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5399{
5400 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005401 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005402 " failed to construct for " + string(nm));
5403}
5404
5405__time_put::__time_put(const string& nm)
5406 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5407{
5408 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005409 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005410 " failed to construct for " + nm);
5411}
5412
5413__time_put::~__time_put()
5414{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005415 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005416 freelocale(__loc_);
5417}
5418
5419void
5420__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5421 char __fmt, char __mod) const
5422{
5423 char fmt[] = {'%', __fmt, __mod, 0};
5424 if (__mod != 0)
5425 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005426 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005427 __ne = __nb + n;
5428}
5429
5430void
5431__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5432 char __fmt, char __mod) const
5433{
5434 char __nar[100];
5435 char* __ne = __nar + 100;
5436 __do_put(__nar, __ne, __tm, __fmt, __mod);
5437 mbstate_t mb = {0};
5438 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005439 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005440 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005441 __throw_runtime_error("locale not supported");
5442 __we = __wb + j;
5443}
5444
5445// moneypunct_byname
5446
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005447template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005448static
5449void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005450__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5451 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5452 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005453{
5454 const char sign = static_cast<char>(money_base::sign);
5455 const char space = static_cast<char>(money_base::space);
5456 const char none = static_cast<char>(money_base::none);
5457 const char symbol = static_cast<char>(money_base::symbol);
5458 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005459 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5460
5461 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5462 // function'. "Space between sign and symbol or value" means that
5463 // if the sign is adjacent to the symbol, there's a space between
5464 // them, and otherwise there's a space between the sign and value.
5465 //
5466 // C11's localeconv specifies that the fourth character of an
5467 // international curr_symbol is used to separate the sign and
5468 // value when sep_by_space says to do so. C++ can't represent
5469 // that, so we just use a space. When sep_by_space says to
5470 // separate the symbol and value-or-sign with a space, we rearrange the
5471 // curr_symbol to put its spacing character on the correct side of
5472 // the symbol.
5473 //
5474 // We also need to avoid adding an extra space between the sign
5475 // and value when the currency symbol is suppressed (by not
5476 // setting showbase). We match glibc's strfmon by interpreting
5477 // sep_by_space==1 as "omit the space when the currency symbol is
5478 // absent".
5479 //
5480 // Users who want to get this right should use ICU instead.
5481
Howard Hinnantc51e1022010-05-11 19:42:16 +00005482 switch (cs_precedes)
5483 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005484 case 0: // value before curr_symbol
5485 if (symbol_contains_sep) {
5486 // Move the separator to before the symbol, to place it
5487 // between the value and symbol.
5488 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5489 __curr_symbol_.end());
5490 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005491 switch (sign_posn)
5492 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005493 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005494 pat.field[0] = sign;
5495 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005496 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005497 pat.field[3] = symbol;
5498 switch (sep_by_space)
5499 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005500 case 0: // No space separates the currency symbol and value.
5501 // This case may have changed between C99 and C11;
5502 // assume the currency symbol matches the intention.
5503 case 2: // Space between sign and currency or value.
5504 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005505 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005506 case 1: // Space between currency-and-sign or currency and value.
5507 if (!symbol_contains_sep) {
5508 // We insert the space into the symbol instead of
5509 // setting pat.field[2]=space so that when
5510 // showbase is not set, the space goes away too.
5511 __curr_symbol_.insert(0, 1, space_char);
5512 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005513 return;
5514 default:
5515 break;
5516 }
5517 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005518 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005519 pat.field[0] = sign;
5520 pat.field[3] = symbol;
5521 switch (sep_by_space)
5522 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005523 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005524 pat.field[1] = value;
5525 pat.field[2] = none;
5526 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005527 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005528 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005529 pat.field[2] = none;
5530 if (!symbol_contains_sep) {
5531 // We insert the space into the symbol instead of
5532 // setting pat.field[2]=space so that when
5533 // showbase is not set, the space goes away too.
5534 __curr_symbol_.insert(0, 1, space_char);
5535 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005536 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005537 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005538 pat.field[1] = space;
5539 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005540 if (symbol_contains_sep) {
5541 // Remove the separator from the symbol, since it
5542 // has already appeared after the sign.
5543 __curr_symbol_.erase(__curr_symbol_.begin());
5544 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005545 return;
5546 default:
5547 break;
5548 }
5549 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005550 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005551 pat.field[0] = value;
5552 pat.field[3] = sign;
5553 switch (sep_by_space)
5554 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005555 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005556 pat.field[1] = none;
5557 pat.field[2] = symbol;
5558 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005559 case 1: // Space between currency-and-sign or currency and value.
5560 if (!symbol_contains_sep) {
5561 // We insert the space into the symbol instead of
5562 // setting pat.field[1]=space so that when
5563 // showbase is not set, the space goes away too.
5564 __curr_symbol_.insert(0, 1, space_char);
5565 }
5566 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005567 pat.field[2] = symbol;
5568 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005569 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005570 pat.field[1] = symbol;
5571 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005572 if (symbol_contains_sep) {
5573 // Remove the separator from the symbol, since it
5574 // should not be removed if showbase is absent.
5575 __curr_symbol_.erase(__curr_symbol_.begin());
5576 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005577 return;
5578 default:
5579 break;
5580 }
5581 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005582 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005583 pat.field[0] = value;
5584 pat.field[3] = symbol;
5585 switch (sep_by_space)
5586 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005587 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005588 pat.field[1] = none;
5589 pat.field[2] = sign;
5590 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005591 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005592 pat.field[1] = space;
5593 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005594 if (symbol_contains_sep) {
5595 // Remove the separator from the symbol, since it
5596 // has already appeared before the sign.
5597 __curr_symbol_.erase(__curr_symbol_.begin());
5598 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005599 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005600 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005601 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005602 pat.field[2] = none;
5603 if (!symbol_contains_sep) {
5604 // We insert the space into the symbol instead of
5605 // setting pat.field[2]=space so that when
5606 // showbase is not set, the space goes away too.
5607 __curr_symbol_.insert(0, 1, space_char);
5608 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005609 return;
5610 default:
5611 break;
5612 }
5613 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005614 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005615 pat.field[0] = value;
5616 pat.field[3] = sign;
5617 switch (sep_by_space)
5618 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005619 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005620 pat.field[1] = none;
5621 pat.field[2] = symbol;
5622 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005623 case 1: // Space between currency-and-sign or currency and value.
5624 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005625 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005626 if (!symbol_contains_sep) {
5627 // We insert the space into the symbol instead of
5628 // setting pat.field[1]=space so that when
5629 // showbase is not set, the space goes away too.
5630 __curr_symbol_.insert(0, 1, space_char);
5631 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005632 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005633 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005634 pat.field[1] = symbol;
5635 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005636 if (symbol_contains_sep) {
5637 // Remove the separator from the symbol, since it
5638 // should not disappear when showbase is absent.
5639 __curr_symbol_.erase(__curr_symbol_.begin());
5640 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005641 return;
5642 default:
5643 break;
5644 }
5645 break;
5646 default:
5647 break;
5648 }
5649 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005650 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005651 switch (sign_posn)
5652 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005653 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005654 pat.field[0] = sign;
5655 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005656 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005657 pat.field[3] = value;
5658 switch (sep_by_space)
5659 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005660 case 0: // No space separates the currency symbol and value.
5661 // This case may have changed between C99 and C11;
5662 // assume the currency symbol matches the intention.
5663 case 2: // Space between sign and currency or value.
5664 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005665 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005666 case 1: // Space between currency-and-sign or currency and value.
5667 if (!symbol_contains_sep) {
5668 // We insert the space into the symbol instead of
5669 // setting pat.field[2]=space so that when
5670 // showbase is not set, the space goes away too.
5671 __curr_symbol_.insert(0, 1, space_char);
5672 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005673 return;
5674 default:
5675 break;
5676 }
5677 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005678 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005679 pat.field[0] = sign;
5680 pat.field[3] = value;
5681 switch (sep_by_space)
5682 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005683 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005684 pat.field[1] = symbol;
5685 pat.field[2] = none;
5686 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005687 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005688 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005689 pat.field[2] = none;
5690 if (!symbol_contains_sep) {
5691 // We insert the space into the symbol instead of
5692 // setting pat.field[2]=space so that when
5693 // showbase is not set, the space goes away too.
5694 __curr_symbol_.push_back(space_char);
5695 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005696 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005697 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005698 pat.field[1] = space;
5699 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005700 if (symbol_contains_sep) {
5701 // Remove the separator from the symbol, since it
5702 // has already appeared after the sign.
5703 __curr_symbol_.pop_back();
5704 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005705 return;
5706 default:
5707 break;
5708 }
5709 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005710 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005711 pat.field[0] = symbol;
5712 pat.field[3] = sign;
5713 switch (sep_by_space)
5714 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005715 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005716 pat.field[1] = none;
5717 pat.field[2] = value;
5718 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005719 case 1: // Space between currency-and-sign or currency and value.
5720 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005721 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005722 if (!symbol_contains_sep) {
5723 // We insert the space into the symbol instead of
5724 // setting pat.field[1]=space so that when
5725 // showbase is not set, the space goes away too.
5726 __curr_symbol_.push_back(space_char);
5727 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005728 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005729 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005730 pat.field[1] = value;
5731 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005732 if (symbol_contains_sep) {
5733 // Remove the separator from the symbol, since it
5734 // will appear before the sign.
5735 __curr_symbol_.pop_back();
5736 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005737 return;
5738 default:
5739 break;
5740 }
5741 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005742 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005743 pat.field[0] = sign;
5744 pat.field[3] = value;
5745 switch (sep_by_space)
5746 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005747 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005748 pat.field[1] = symbol;
5749 pat.field[2] = none;
5750 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005751 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005752 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005753 pat.field[2] = none;
5754 if (!symbol_contains_sep) {
5755 // We insert the space into the symbol instead of
5756 // setting pat.field[2]=space so that when
5757 // showbase is not set, the space goes away too.
5758 __curr_symbol_.push_back(space_char);
5759 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005760 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005761 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005762 pat.field[1] = space;
5763 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005764 if (symbol_contains_sep) {
5765 // Remove the separator from the symbol, since it
5766 // has already appeared after the sign.
5767 __curr_symbol_.pop_back();
5768 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005769 return;
5770 default:
5771 break;
5772 }
5773 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005774 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005775 pat.field[0] = symbol;
5776 pat.field[3] = value;
5777 switch (sep_by_space)
5778 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005779 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005780 pat.field[1] = sign;
5781 pat.field[2] = none;
5782 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005783 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005784 pat.field[1] = sign;
5785 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005786 if (symbol_contains_sep) {
5787 // Remove the separator from the symbol, since it
5788 // should not disappear when showbase is absent.
5789 __curr_symbol_.pop_back();
5790 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005791 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005792 case 2: // Space between sign and currency or value.
5793 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005794 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005795 if (!symbol_contains_sep) {
5796 // We insert the space into the symbol instead of
5797 // setting pat.field[1]=space so that when
5798 // showbase is not set, the space goes away too.
5799 __curr_symbol_.push_back(space_char);
5800 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005801 return;
5802 default:
5803 break;
5804 }
5805 break;
5806 default:
5807 break;
5808 }
5809 break;
5810 default:
5811 break;
5812 }
5813 pat.field[0] = symbol;
5814 pat.field[1] = sign;
5815 pat.field[2] = none;
5816 pat.field[3] = value;
5817}
5818
5819template<>
5820void
5821moneypunct_byname<char, false>::init(const char* nm)
5822{
5823 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005824 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005825 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005826 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005827 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005828
Ben Craig3756b922016-03-09 15:39:39 +00005829 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005830 if (!checked_string_to_char_convert(__decimal_point_,
5831 lc->mon_decimal_point,
5832 loc.get()))
5833 __decimal_point_ = base::do_decimal_point();
5834 if (!checked_string_to_char_convert(__thousands_sep_,
5835 lc->mon_thousands_sep,
5836 loc.get()))
5837 __thousands_sep_ = base::do_thousands_sep();
5838
Howard Hinnantc51e1022010-05-11 19:42:16 +00005839 __grouping_ = lc->mon_grouping;
5840 __curr_symbol_ = lc->currency_symbol;
5841 if (lc->frac_digits != CHAR_MAX)
5842 __frac_digits_ = lc->frac_digits;
5843 else
5844 __frac_digits_ = base::do_frac_digits();
5845 if (lc->p_sign_posn == 0)
5846 __positive_sign_ = "()";
5847 else
5848 __positive_sign_ = lc->positive_sign;
5849 if (lc->n_sign_posn == 0)
5850 __negative_sign_ = "()";
5851 else
5852 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005853 // Assume the positive and negative formats will want spaces in
5854 // the same places in curr_symbol since there's no way to
5855 // represent anything else.
5856 string_type __dummy_curr_symbol = __curr_symbol_;
5857 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5858 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5859 __init_pat(__neg_format_, __curr_symbol_, false,
5860 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005861}
5862
5863template<>
5864void
5865moneypunct_byname<char, true>::init(const char* nm)
5866{
5867 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005868 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005869 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005870 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005871 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005872
Ben Craig3756b922016-03-09 15:39:39 +00005873 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005874 if (!checked_string_to_char_convert(__decimal_point_,
5875 lc->mon_decimal_point,
5876 loc.get()))
5877 __decimal_point_ = base::do_decimal_point();
5878 if (!checked_string_to_char_convert(__thousands_sep_,
5879 lc->mon_thousands_sep,
5880 loc.get()))
5881 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005882 __grouping_ = lc->mon_grouping;
5883 __curr_symbol_ = lc->int_curr_symbol;
5884 if (lc->int_frac_digits != CHAR_MAX)
5885 __frac_digits_ = lc->int_frac_digits;
5886 else
5887 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005888#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005889 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005890#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005891 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005892#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005893 __positive_sign_ = "()";
5894 else
5895 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005896#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005897 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005898#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005899 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005900#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005901 __negative_sign_ = "()";
5902 else
5903 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005904 // Assume the positive and negative formats will want spaces in
5905 // the same places in curr_symbol since there's no way to
5906 // represent anything else.
5907 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005908#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005909 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5910 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5911 __init_pat(__neg_format_, __curr_symbol_, true,
5912 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005913#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005914 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5915 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5916 lc->int_p_sign_posn, ' ');
5917 __init_pat(__neg_format_, __curr_symbol_, true,
5918 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5919 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005920#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005921}
5922
5923template<>
5924void
5925moneypunct_byname<wchar_t, false>::init(const char* nm)
5926{
5927 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005928 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005929 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005930 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005931 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00005932 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005933 if (!checked_string_to_wchar_convert(__decimal_point_,
5934 lc->mon_decimal_point,
5935 loc.get()))
5936 __decimal_point_ = base::do_decimal_point();
5937 if (!checked_string_to_wchar_convert(__thousands_sep_,
5938 lc->mon_thousands_sep,
5939 loc.get()))
5940 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005941 __grouping_ = lc->mon_grouping;
5942 wchar_t wbuf[100];
5943 mbstate_t mb = {0};
5944 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005945 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005946 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005947 __throw_runtime_error("locale not supported");
5948 wchar_t* wbe = wbuf + j;
5949 __curr_symbol_.assign(wbuf, wbe);
5950 if (lc->frac_digits != CHAR_MAX)
5951 __frac_digits_ = lc->frac_digits;
5952 else
5953 __frac_digits_ = base::do_frac_digits();
5954 if (lc->p_sign_posn == 0)
5955 __positive_sign_ = L"()";
5956 else
5957 {
5958 mb = mbstate_t();
5959 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005960 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005961 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005962 __throw_runtime_error("locale not supported");
5963 wbe = wbuf + j;
5964 __positive_sign_.assign(wbuf, wbe);
5965 }
5966 if (lc->n_sign_posn == 0)
5967 __negative_sign_ = L"()";
5968 else
5969 {
5970 mb = mbstate_t();
5971 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005972 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005973 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005974 __throw_runtime_error("locale not supported");
5975 wbe = wbuf + j;
5976 __negative_sign_.assign(wbuf, wbe);
5977 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005978 // Assume the positive and negative formats will want spaces in
5979 // the same places in curr_symbol since there's no way to
5980 // represent anything else.
5981 string_type __dummy_curr_symbol = __curr_symbol_;
5982 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5983 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5984 __init_pat(__neg_format_, __curr_symbol_, false,
5985 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005986}
5987
5988template<>
5989void
5990moneypunct_byname<wchar_t, true>::init(const char* nm)
5991{
5992 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005993 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005994 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005995 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005996 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005997
Ben Craig3756b922016-03-09 15:39:39 +00005998 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005999 if (!checked_string_to_wchar_convert(__decimal_point_,
6000 lc->mon_decimal_point,
6001 loc.get()))
6002 __decimal_point_ = base::do_decimal_point();
6003 if (!checked_string_to_wchar_convert(__thousands_sep_,
6004 lc->mon_thousands_sep,
6005 loc.get()))
6006 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006007 __grouping_ = lc->mon_grouping;
6008 wchar_t wbuf[100];
6009 mbstate_t mb = {0};
6010 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006011 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006012 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006013 __throw_runtime_error("locale not supported");
6014 wchar_t* wbe = wbuf + j;
6015 __curr_symbol_.assign(wbuf, wbe);
6016 if (lc->int_frac_digits != CHAR_MAX)
6017 __frac_digits_ = lc->int_frac_digits;
6018 else
6019 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006020#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006021 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006022#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006023 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006024#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006025 __positive_sign_ = L"()";
6026 else
6027 {
6028 mb = mbstate_t();
6029 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006030 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006031 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006032 __throw_runtime_error("locale not supported");
6033 wbe = wbuf + j;
6034 __positive_sign_.assign(wbuf, wbe);
6035 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006036#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006037 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006038#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006039 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006040#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006041 __negative_sign_ = L"()";
6042 else
6043 {
6044 mb = mbstate_t();
6045 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006046 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006047 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006048 __throw_runtime_error("locale not supported");
6049 wbe = wbuf + j;
6050 __negative_sign_.assign(wbuf, wbe);
6051 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006052 // Assume the positive and negative formats will want spaces in
6053 // the same places in curr_symbol since there's no way to
6054 // represent anything else.
6055 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006056#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006057 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6058 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6059 __init_pat(__neg_format_, __curr_symbol_, true,
6060 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006061#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006062 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6063 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6064 lc->int_p_sign_posn, L' ');
6065 __init_pat(__neg_format_, __curr_symbol_, true,
6066 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6067 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006068#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006069}
6070
6071void __do_nothing(void*) {}
6072
6073void __throw_runtime_error(const char* msg)
6074{
Howard Hinnant72f73582010-08-11 17:04:31 +00006075#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006076 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006077#else
6078 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006079 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006080#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006081}
6082
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006083template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6084template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006085
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006086template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6087template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006088
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006089template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6090template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006091
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006092template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6093template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006094
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006095template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6096template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006097
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006098template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6099template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006100
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006101template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6102template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006103
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006104template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6105template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006106
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006107template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6108template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006109
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006110template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6111template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6112template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6113template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006114
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006115template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6116template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6117template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6118template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006119
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006120template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6121template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006122
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006123template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6124template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006125
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006126template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6127template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006128
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006129template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6130template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006131
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006132template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6133template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006134
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006135template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6136template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006137
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006138template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6139template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
6140template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6141template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006142
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006143template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006144
6145_LIBCPP_END_NAMESPACE_STD