blob: 4163c2c0af6537d4a3505cc0dad43b8f7f271745 [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"
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +000027#if defined(_LIBCPP_MSVCRT)
28#define _CTYPE_DISABLE_MACROS
29#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000030#include "cwctype"
31#include "__sso_allocator"
Howard Hinnant8ad70912013-09-17 01:34:47 +000032#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Marshall Clowccb92572015-06-23 14:45:02 +000033#include "support/win32/locale_win32.h"
Dan Albert21800dc2016-09-19 18:00:45 +000034#elif !defined(__BIONIC__)
Howard Hinnantc51e1022010-05-11 19:42:16 +000035#include <langinfo.h>
Marshall Clow3477ec92014-07-10 15:20:28 +000036#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000037#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000038#include <stdio.h>
Howard Hinnantc51e1022010-05-11 19:42:16 +000039
Marshall Clowab9c1772013-02-07 17:20:56 +000040// On Linux, wint_t and wchar_t have different signed-ness, and this causes
41// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000042#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000043#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000044#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000045
Howard Hinnantc51e1022010-05-11 19:42:16 +000046_LIBCPP_BEGIN_NAMESPACE_STD
47
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000048struct __libcpp_unique_locale {
49 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
50
51 ~__libcpp_unique_locale() {
52 if (__loc_)
53 freelocale(__loc_);
54 }
55
56 explicit operator bool() const { return __loc_; }
57
58 locale_t& get() { return __loc_; }
59
60 locale_t __loc_;
61private:
62 __libcpp_unique_locale(__libcpp_unique_locale const&);
63 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
64};
65
Howard Hinnantf312e3e2011-09-28 23:39:33 +000066#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000067locale_t __cloc() {
68 // In theory this could create a race condition. In practice
69 // the race condition is non-fatal since it will just create
70 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000071 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
72 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000073}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000074#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000075
Howard Hinnantc51e1022010-05-11 19:42:16 +000076namespace {
77
78struct release
79{
80 void operator()(locale::facet* p) {p->__release_shared();}
81};
82
83template <class T, class A0>
84inline
85T&
86make(A0 a0)
87{
88 static typename aligned_storage<sizeof(T)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +000089 auto *obj = ::new (&buf) T(a0);
90 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000091}
92
93template <class T, class A0, class A1>
94inline
95T&
96make(A0 a0, A1 a1)
97{
98 static typename aligned_storage<sizeof(T)>::type buf;
99 ::new (&buf) T(a0, a1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000100 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000101}
102
103template <class T, class A0, class A1, class A2>
104inline
105T&
106make(A0 a0, A1 a1, A2 a2)
107{
108 static typename aligned_storage<sizeof(T)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000109 auto *obj = ::new (&buf) T(a0, a1, a2);
110 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000111}
112
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000113template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000114inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000115_LIBCPP_CONSTEXPR
116size_t
117countof(const T (&)[N])
118{
119 return N;
120}
121
122template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000123inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000124_LIBCPP_CONSTEXPR
125size_t
126countof(const T * const begin, const T * const end)
127{
128 return static_cast<size_t>(end - begin);
129}
130
Marshall Clow8fea1612016-08-25 15:09:01 +0000131_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
132{
133#ifndef _LIBCPP_NO_EXCEPTIONS
134 throw runtime_error(msg);
135#else
136 (void)msg;
137 _VSTD::abort();
138#endif
139}
140
Howard Hinnantc51e1022010-05-11 19:42:16 +0000141}
142
Howard Hinnantdd099492013-08-29 23:37:50 +0000143#if defined(_AIX)
144// Set priority to INT_MIN + 256 + 150
145# pragma priority ( -2147483242 )
146#endif
147
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000148const locale::category locale::none;
149const locale::category locale::collate;
150const locale::category locale::ctype;
151const locale::category locale::monetary;
152const locale::category locale::numeric;
153const locale::category locale::time;
154const locale::category locale::messages;
155const locale::category locale::all;
156
Howard Hinnantc51e1022010-05-11 19:42:16 +0000157class _LIBCPP_HIDDEN locale::__imp
158 : public facet
159{
160 enum {N = 28};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000161#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000162// FIXME: MSVC doesn't support aligned parameters by value.
163// I can't get the __sso_allocator to work here
164// for MSVC I think for this reason.
165 vector<facet*> facets_;
166#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000167 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000168#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000169 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000170public:
171 explicit __imp(size_t refs = 0);
172 explicit __imp(const string& name, size_t refs = 0);
173 __imp(const __imp&);
174 __imp(const __imp&, const string&, locale::category c);
175 __imp(const __imp& other, const __imp& one, locale::category c);
176 __imp(const __imp&, facet* f, long id);
177 ~__imp();
178
179 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000180 bool has_facet(long id) const
181 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000182 const locale::facet* use_facet(long id) const;
183
184 static const locale& make_classic();
185 static locale& make_global();
186private:
187 void install(facet* f, long id);
188 template <class F> void install(F* f) {install(f, f->id.__get());}
189 template <class F> void install_from(const __imp& other);
190};
191
192locale::__imp::__imp(size_t refs)
193 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000194 facets_(N),
195 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000196{
197 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000198 install(&make<_VSTD::collate<char> >(1u));
199 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000200 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000201 install(&make<_VSTD::ctype<wchar_t> >(1u));
202 install(&make<codecvt<char, char, mbstate_t> >(1u));
203 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
204 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
205 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
206 install(&make<numpunct<char> >(1u));
207 install(&make<numpunct<wchar_t> >(1u));
208 install(&make<num_get<char> >(1u));
209 install(&make<num_get<wchar_t> >(1u));
210 install(&make<num_put<char> >(1u));
211 install(&make<num_put<wchar_t> >(1u));
212 install(&make<moneypunct<char, false> >(1u));
213 install(&make<moneypunct<char, true> >(1u));
214 install(&make<moneypunct<wchar_t, false> >(1u));
215 install(&make<moneypunct<wchar_t, true> >(1u));
216 install(&make<money_get<char> >(1u));
217 install(&make<money_get<wchar_t> >(1u));
218 install(&make<money_put<char> >(1u));
219 install(&make<money_put<wchar_t> >(1u));
220 install(&make<time_get<char> >(1u));
221 install(&make<time_get<wchar_t> >(1u));
222 install(&make<time_put<char> >(1u));
223 install(&make<time_put<wchar_t> >(1u));
224 install(&make<_VSTD::messages<char> >(1u));
225 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000226}
227
228locale::__imp::__imp(const string& name, size_t refs)
229 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000230 facets_(N),
231 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000232{
Howard Hinnant72f73582010-08-11 17:04:31 +0000233#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000234 try
235 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000236#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000237 facets_ = locale::classic().__locale_->facets_;
238 for (unsigned i = 0; i < facets_.size(); ++i)
239 if (facets_[i])
240 facets_[i]->__add_shared();
241 install(new collate_byname<char>(name_));
242 install(new collate_byname<wchar_t>(name_));
243 install(new ctype_byname<char>(name_));
244 install(new ctype_byname<wchar_t>(name_));
245 install(new codecvt_byname<char, char, mbstate_t>(name_));
246 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
247 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
248 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
249 install(new numpunct_byname<char>(name_));
250 install(new numpunct_byname<wchar_t>(name_));
251 install(new moneypunct_byname<char, false>(name_));
252 install(new moneypunct_byname<char, true>(name_));
253 install(new moneypunct_byname<wchar_t, false>(name_));
254 install(new moneypunct_byname<wchar_t, true>(name_));
255 install(new time_get_byname<char>(name_));
256 install(new time_get_byname<wchar_t>(name_));
257 install(new time_put_byname<char>(name_));
258 install(new time_put_byname<wchar_t>(name_));
259 install(new messages_byname<char>(name_));
260 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000261#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000262 }
263 catch (...)
264 {
265 for (unsigned i = 0; i < facets_.size(); ++i)
266 if (facets_[i])
267 facets_[i]->__release_shared();
268 throw;
269 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000270#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000271}
272
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000273// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000274// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000275#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000276#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000277#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000278#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000279
Howard Hinnantc51e1022010-05-11 19:42:16 +0000280locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000281 : facets_(max<size_t>(N, other.facets_.size())),
282 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000283{
284 facets_ = other.facets_;
285 for (unsigned i = 0; i < facets_.size(); ++i)
286 if (facets_[i])
287 facets_[i]->__add_shared();
288}
289
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000290#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000291#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000292#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000293
Howard Hinnantc51e1022010-05-11 19:42:16 +0000294locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000295 : facets_(N),
296 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000297{
298 facets_ = other.facets_;
299 for (unsigned i = 0; i < facets_.size(); ++i)
300 if (facets_[i])
301 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000302#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000303 try
304 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000305#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000306 if (c & locale::collate)
307 {
308 install(new collate_byname<char>(name));
309 install(new collate_byname<wchar_t>(name));
310 }
311 if (c & locale::ctype)
312 {
313 install(new ctype_byname<char>(name));
314 install(new ctype_byname<wchar_t>(name));
315 install(new codecvt_byname<char, char, mbstate_t>(name));
316 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
317 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
318 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
319 }
320 if (c & locale::monetary)
321 {
322 install(new moneypunct_byname<char, false>(name));
323 install(new moneypunct_byname<char, true>(name));
324 install(new moneypunct_byname<wchar_t, false>(name));
325 install(new moneypunct_byname<wchar_t, true>(name));
326 }
327 if (c & locale::numeric)
328 {
329 install(new numpunct_byname<char>(name));
330 install(new numpunct_byname<wchar_t>(name));
331 }
332 if (c & locale::time)
333 {
334 install(new time_get_byname<char>(name));
335 install(new time_get_byname<wchar_t>(name));
336 install(new time_put_byname<char>(name));
337 install(new time_put_byname<wchar_t>(name));
338 }
339 if (c & locale::messages)
340 {
341 install(new messages_byname<char>(name));
342 install(new messages_byname<wchar_t>(name));
343 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000344#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000345 }
346 catch (...)
347 {
348 for (unsigned i = 0; i < facets_.size(); ++i)
349 if (facets_[i])
350 facets_[i]->__release_shared();
351 throw;
352 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000353#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000354}
355
356template<class F>
357inline
358void
359locale::__imp::install_from(const locale::__imp& one)
360{
361 long id = F::id.__get();
362 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
363}
364
365locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000366 : facets_(N),
367 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000368{
369 facets_ = other.facets_;
370 for (unsigned i = 0; i < facets_.size(); ++i)
371 if (facets_[i])
372 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000373#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000374 try
375 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000376#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000377 if (c & locale::collate)
378 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000379 install_from<_VSTD::collate<char> >(one);
380 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000381 }
382 if (c & locale::ctype)
383 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000384 install_from<_VSTD::ctype<char> >(one);
385 install_from<_VSTD::ctype<wchar_t> >(one);
386 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
387 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
388 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
389 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000390 }
391 if (c & locale::monetary)
392 {
393 install_from<moneypunct<char, false> >(one);
394 install_from<moneypunct<char, true> >(one);
395 install_from<moneypunct<wchar_t, false> >(one);
396 install_from<moneypunct<wchar_t, true> >(one);
397 install_from<money_get<char> >(one);
398 install_from<money_get<wchar_t> >(one);
399 install_from<money_put<char> >(one);
400 install_from<money_put<wchar_t> >(one);
401 }
402 if (c & locale::numeric)
403 {
404 install_from<numpunct<char> >(one);
405 install_from<numpunct<wchar_t> >(one);
406 install_from<num_get<char> >(one);
407 install_from<num_get<wchar_t> >(one);
408 install_from<num_put<char> >(one);
409 install_from<num_put<wchar_t> >(one);
410 }
411 if (c & locale::time)
412 {
413 install_from<time_get<char> >(one);
414 install_from<time_get<wchar_t> >(one);
415 install_from<time_put<char> >(one);
416 install_from<time_put<wchar_t> >(one);
417 }
418 if (c & locale::messages)
419 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000420 install_from<_VSTD::messages<char> >(one);
421 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000422 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000423#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000424 }
425 catch (...)
426 {
427 for (unsigned i = 0; i < facets_.size(); ++i)
428 if (facets_[i])
429 facets_[i]->__release_shared();
430 throw;
431 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000432#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000433}
434
435locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000436 : facets_(max<size_t>(N, other.facets_.size()+1)),
437 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000438{
439 f->__add_shared();
440 unique_ptr<facet, release> hold(f);
441 facets_ = other.facets_;
442 for (unsigned i = 0; i < other.facets_.size(); ++i)
443 if (facets_[i])
444 facets_[i]->__add_shared();
445 install(hold.get(), id);
446}
447
448locale::__imp::~__imp()
449{
450 for (unsigned i = 0; i < facets_.size(); ++i)
451 if (facets_[i])
452 facets_[i]->__release_shared();
453}
454
455void
456locale::__imp::install(facet* f, long id)
457{
458 f->__add_shared();
459 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000460 if (static_cast<size_t>(id) >= facets_.size())
461 facets_.resize(static_cast<size_t>(id+1));
462 if (facets_[static_cast<size_t>(id)])
463 facets_[static_cast<size_t>(id)]->__release_shared();
464 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000465}
466
467const locale::facet*
468locale::__imp::use_facet(long id) const
469{
Howard Hinnant72f73582010-08-11 17:04:31 +0000470#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000471 if (!has_facet(id))
472 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000473#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant28b24882011-12-01 20:21:04 +0000474 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000475}
476
477// locale
478
479const locale&
480locale::__imp::make_classic()
481{
482 // only one thread can get in here and it only gets in once
483 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000484 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000485 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000486 return *c;
487}
488
489const locale&
490locale::classic()
491{
492 static const locale& c = __imp::make_classic();
493 return c;
494}
495
496locale&
497locale::__imp::make_global()
498{
499 // only one thread can get in here and it only gets in once
500 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000501 auto *obj = ::new (&buf) locale(locale::classic());
502 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000503}
504
505locale&
506locale::__global()
507{
508 static locale& g = __imp::make_global();
509 return g;
510}
511
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000512locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000513 : __locale_(__global().__locale_)
514{
515 __locale_->__add_shared();
516}
517
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000518locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000519 : __locale_(l.__locale_)
520{
521 __locale_->__add_shared();
522}
523
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000524locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000525{
526 __locale_->__release_shared();
527}
528
529const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000530locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000531{
532 other.__locale_->__add_shared();
533 __locale_->__release_shared();
534 __locale_ = other.__locale_;
535 return *this;
536}
537
538locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000539#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000540 : __locale_(name ? new __imp(name)
541 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000542#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000543 : __locale_(new __imp(name))
544#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000545{
546 __locale_->__add_shared();
547}
548
549locale::locale(const string& name)
550 : __locale_(new __imp(name))
551{
552 __locale_->__add_shared();
553}
554
555locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000556#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000557 : __locale_(name ? new __imp(*other.__locale_, name, c)
558 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000559#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000560 : __locale_(new __imp(*other.__locale_, name, c))
561#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000562{
563 __locale_->__add_shared();
564}
565
566locale::locale(const locale& other, const string& name, category c)
567 : __locale_(new __imp(*other.__locale_, name, c))
568{
569 __locale_->__add_shared();
570}
571
572locale::locale(const locale& other, const locale& one, category c)
573 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
574{
575 __locale_->__add_shared();
576}
577
578string
579locale::name() const
580{
581 return __locale_->name();
582}
583
584void
585locale::__install_ctor(const locale& other, facet* f, long id)
586{
587 if (f)
588 __locale_ = new __imp(*other.__locale_, f, id);
589 else
590 __locale_ = other.__locale_;
591 __locale_->__add_shared();
592}
593
594locale
595locale::global(const locale& loc)
596{
597 locale& g = __global();
598 locale r = g;
599 g = loc;
600 if (g.name() != "*")
601 setlocale(LC_ALL, g.name().c_str());
602 return r;
603}
604
605bool
606locale::has_facet(id& x) const
607{
608 return __locale_->has_facet(x.__get());
609}
610
611const locale::facet*
612locale::use_facet(id& x) const
613{
614 return __locale_->use_facet(x.__get());
615}
616
617bool
618locale::operator==(const locale& y) const
619{
620 return (__locale_ == y.__locale_)
621 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
622}
623
624// locale::facet
625
626locale::facet::~facet()
627{
628}
629
630void
Howard Hinnant719bda32011-05-28 14:41:13 +0000631locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000632{
633 delete this;
634}
635
636// locale::id
637
638int32_t locale::id::__next_id = 0;
639
640namespace
641{
642
643class __fake_bind
644{
645 locale::id* id_;
646 void (locale::id::* pmf_)();
647public:
648 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
649 : id_(id), pmf_(pmf) {}
650
651 void operator()() const
652 {
653 (id_->*pmf_)();
654 }
655};
656
657}
658
659long
660locale::id::__get()
661{
662 call_once(__flag_, __fake_bind(&locale::id::__init, this));
663 return __id_ - 1;
664}
665
666void
667locale::id::__init()
668{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000669 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000670}
671
672// template <> class collate_byname<char>
673
674collate_byname<char>::collate_byname(const char* n, size_t refs)
675 : collate<char>(refs),
676 __l(newlocale(LC_ALL_MASK, n, 0))
677{
678 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000679 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000680 " failed to construct for " + string(n));
681}
682
683collate_byname<char>::collate_byname(const string& name, size_t refs)
684 : collate<char>(refs),
685 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
686{
687 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000688 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000689 " failed to construct for " + name);
690}
691
692collate_byname<char>::~collate_byname()
693{
694 freelocale(__l);
695}
696
697int
698collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
699 const char_type* __lo2, const char_type* __hi2) const
700{
701 string_type lhs(__lo1, __hi1);
702 string_type rhs(__lo2, __hi2);
703 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
704 if (r < 0)
705 return -1;
706 if (r > 0)
707 return 1;
708 return r;
709}
710
711collate_byname<char>::string_type
712collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
713{
714 const string_type in(lo, hi);
715 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
716 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
717 return out;
718}
719
720// template <> class collate_byname<wchar_t>
721
722collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
723 : collate<wchar_t>(refs),
724 __l(newlocale(LC_ALL_MASK, n, 0))
725{
726 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000727 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000728 " failed to construct for " + string(n));
729}
730
731collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
732 : collate<wchar_t>(refs),
733 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
734{
735 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000736 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000737 " failed to construct for " + name);
738}
739
740collate_byname<wchar_t>::~collate_byname()
741{
742 freelocale(__l);
743}
744
745int
746collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
747 const char_type* __lo2, const char_type* __hi2) const
748{
749 string_type lhs(__lo1, __hi1);
750 string_type rhs(__lo2, __hi2);
751 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
752 if (r < 0)
753 return -1;
754 if (r > 0)
755 return 1;
756 return r;
757}
758
759collate_byname<wchar_t>::string_type
760collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
761{
762 const string_type in(lo, hi);
763 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
764 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
765 return out;
766}
767
768// template <> class ctype<wchar_t>;
769
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000770const ctype_base::mask ctype_base::space;
771const ctype_base::mask ctype_base::print;
772const ctype_base::mask ctype_base::cntrl;
773const ctype_base::mask ctype_base::upper;
774const ctype_base::mask ctype_base::lower;
775const ctype_base::mask ctype_base::alpha;
776const ctype_base::mask ctype_base::digit;
777const ctype_base::mask ctype_base::punct;
778const ctype_base::mask ctype_base::xdigit;
779const ctype_base::mask ctype_base::blank;
780const ctype_base::mask ctype_base::alnum;
781const ctype_base::mask ctype_base::graph;
782
Howard Hinnantc51e1022010-05-11 19:42:16 +0000783locale::id ctype<wchar_t>::id;
784
785ctype<wchar_t>::~ctype()
786{
787}
788
789bool
790ctype<wchar_t>::do_is(mask m, char_type c) const
791{
Marshall Clowd920eea2013-10-21 15:07:28 +0000792 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000793}
794
795const wchar_t*
796ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
797{
798 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000799 *vec = static_cast<mask>(isascii(*low) ?
800 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000801 return low;
802}
803
804const wchar_t*
805ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
806{
807 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000808 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000809 break;
810 return low;
811}
812
813const wchar_t*
814ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
815{
816 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000817 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000818 break;
819 return low;
820}
821
822wchar_t
823ctype<wchar_t>::do_toupper(char_type c) const
824{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000825#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
826 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000827#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000828 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000829 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000830#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000831 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000832#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000833}
834
835const wchar_t*
836ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
837{
838 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000839#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
840 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000841#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000842 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000843 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
844 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000845#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000846 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000847#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000848 return low;
849}
850
851wchar_t
852ctype<wchar_t>::do_tolower(char_type c) const
853{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000854#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
855 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000856#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000857 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000858 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000859#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000860 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000861#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000862}
863
864const wchar_t*
865ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
866{
867 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000868#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
869 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000870#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000871 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000872 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
873 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000874#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000875 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000876#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000877 return low;
878}
879
880wchar_t
881ctype<wchar_t>::do_widen(char c) const
882{
883 return c;
884}
885
886const char*
887ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
888{
889 for (; low != high; ++low, ++dest)
890 *dest = *low;
891 return low;
892}
893
894char
895ctype<wchar_t>::do_narrow(char_type c, char dfault) const
896{
897 if (isascii(c))
898 return static_cast<char>(c);
899 return dfault;
900}
901
902const wchar_t*
903ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
904{
905 for (; low != high; ++low, ++dest)
906 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000907 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000908 else
909 *dest = dfault;
910 return low;
911}
912
913// template <> class ctype<char>;
914
915locale::id ctype<char>::id;
916
917ctype<char>::ctype(const mask* tab, bool del, size_t refs)
918 : locale::facet(refs),
919 __tab_(tab),
920 __del_(del)
921{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000922 if (__tab_ == 0)
923 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000924}
925
926ctype<char>::~ctype()
927{
928 if (__tab_ && __del_)
929 delete [] __tab_;
930}
931
932char
933ctype<char>::do_toupper(char_type c) const
934{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000935#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000936 return isascii(c) ?
937 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000938#elif defined(__NetBSD__)
939 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000940#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000941 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000942 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000943#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000944 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000945#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000946}
947
948const char*
949ctype<char>::do_toupper(char_type* low, const char_type* high) const
950{
951 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000952#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000953 *low = isascii(*low) ?
954 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000955#elif defined(__NetBSD__)
956 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000957#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000958 *low = isascii(*low) ?
959 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000960#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000961 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000962#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000963 return low;
964}
965
966char
967ctype<char>::do_tolower(char_type c) const
968{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000969#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000970 return isascii(c) ?
971 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000972#elif defined(__NetBSD__)
973 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000974#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000975 return isascii(c) ?
976 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000977#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000978 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000979#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000980}
981
982const char*
983ctype<char>::do_tolower(char_type* low, const char_type* high) const
984{
985 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000986#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000987 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000988#elif defined(__NetBSD__)
989 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000990#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000991 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000992#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000993 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000994#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000995 return low;
996}
997
998char
999ctype<char>::do_widen(char c) const
1000{
1001 return c;
1002}
1003
1004const char*
1005ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1006{
1007 for (; low != high; ++low, ++dest)
1008 *dest = *low;
1009 return low;
1010}
1011
1012char
1013ctype<char>::do_narrow(char_type c, char dfault) const
1014{
1015 if (isascii(c))
1016 return static_cast<char>(c);
1017 return dfault;
1018}
1019
1020const char*
1021ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1022{
1023 for (; low != high; ++low, ++dest)
1024 if (isascii(*low))
1025 *dest = *low;
1026 else
1027 *dest = dfault;
1028 return low;
1029}
1030
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001031#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001032extern "C" const unsigned short ** __ctype_b_loc();
1033extern "C" const int ** __ctype_tolower_loc();
1034extern "C" const int ** __ctype_toupper_loc();
1035#endif
1036
Marshall Clow8f870232015-03-04 16:50:02 +00001037#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001038const ctype<char>::mask*
1039ctype<char>::classic_table() _NOEXCEPT
1040{
1041 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1042 cntrl, cntrl,
1043 cntrl, cntrl,
1044 cntrl, cntrl,
1045 cntrl, cntrl,
1046 cntrl, cntrl | space | blank,
1047 cntrl | space, cntrl | space,
1048 cntrl | space, cntrl | space,
1049 cntrl, cntrl,
1050 cntrl, cntrl,
1051 cntrl, cntrl,
1052 cntrl, cntrl,
1053 cntrl, cntrl,
1054 cntrl, cntrl,
1055 cntrl, cntrl,
1056 cntrl, cntrl,
1057 cntrl, cntrl,
1058 space | blank | print, punct | print,
1059 punct | print, punct | print,
1060 punct | print, punct | print,
1061 punct | print, punct | print,
1062 punct | print, punct | print,
1063 punct | print, punct | print,
1064 punct | print, punct | print,
1065 punct | print, punct | print,
1066 digit | print | xdigit, digit | print | xdigit,
1067 digit | print | xdigit, digit | print | xdigit,
1068 digit | print | xdigit, digit | print | xdigit,
1069 digit | print | xdigit, digit | print | xdigit,
1070 digit | print | xdigit, digit | print | xdigit,
1071 punct | print, punct | print,
1072 punct | print, punct | print,
1073 punct | print, punct | print,
1074 punct | print, upper | xdigit | print | alpha,
1075 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1076 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1077 upper | xdigit | print | alpha, upper | print | alpha,
1078 upper | print | alpha, upper | print | alpha,
1079 upper | print | alpha, upper | print | alpha,
1080 upper | print | alpha, upper | print | alpha,
1081 upper | print | alpha, upper | print | alpha,
1082 upper | print | alpha, upper | print | alpha,
1083 upper | print | alpha, upper | print | alpha,
1084 upper | print | alpha, upper | print | alpha,
1085 upper | print | alpha, upper | print | alpha,
1086 upper | print | alpha, upper | print | alpha,
1087 upper | print | alpha, punct | print,
1088 punct | print, punct | print,
1089 punct | print, punct | print,
1090 punct | print, lower | xdigit | print | alpha,
1091 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1092 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1093 lower | xdigit | print | alpha, lower | print | alpha,
1094 lower | print | alpha, lower | print | alpha,
1095 lower | print | alpha, lower | print | alpha,
1096 lower | print | alpha, lower | print | alpha,
1097 lower | print | alpha, lower | print | alpha,
1098 lower | print | alpha, lower | print | alpha,
1099 lower | print | alpha, lower | print | alpha,
1100 lower | print | alpha, lower | print | alpha,
1101 lower | print | alpha, lower | print | alpha,
1102 lower | print | alpha, lower | print | alpha,
1103 lower | print | alpha, punct | print,
1104 punct | print, punct | print,
1105 punct | print, cntrl,
1106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1114 };
1115 return builtin_table;
1116}
1117#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001118const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001119ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001120{
David Chisnall1d581062011-09-21 08:39:44 +00001121#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001122 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001123#elif defined(__NetBSD__)
1124 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001125#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001126 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001127#elif __sun__
1128 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001129#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001130 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001131#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001132 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001133#elif defined(_NEWLIB_VERSION)
1134 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1135 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001136#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001137 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001138#else
David Chisnall8074c342012-02-29 13:05:08 +00001139 // Platform not supported: abort so the person doing the port knows what to
1140 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001141# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001142 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001143 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001144 return NULL;
1145#endif
1146}
Marshall Clowb3f62842015-03-04 16:10:14 +00001147#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001148
Howard Hinnantd7a78632011-09-29 13:33:15 +00001149#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001150const int*
1151ctype<char>::__classic_lower_table() _NOEXCEPT
1152{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001153 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001154}
1155
1156const int*
1157ctype<char>::__classic_upper_table() _NOEXCEPT
1158{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001159 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001160}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001161#elif __NetBSD__
1162const short*
1163ctype<char>::__classic_lower_table() _NOEXCEPT
1164{
1165 return _C_tolower_tab_ + 1;
1166}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001167
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001168const short*
1169ctype<char>::__classic_upper_table() _NOEXCEPT
1170{
1171 return _C_toupper_tab_ + 1;
1172}
1173
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001174#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001175const int*
1176ctype<char>::__classic_lower_table() _NOEXCEPT
1177{
1178 return *__ctype_tolower_loc();
1179}
1180
1181const int*
1182ctype<char>::__classic_upper_table() _NOEXCEPT
1183{
1184 return *__ctype_toupper_loc();
1185}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001186#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001187
Howard Hinnantc51e1022010-05-11 19:42:16 +00001188// template <> class ctype_byname<char>
1189
1190ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1191 : ctype<char>(0, false, refs),
1192 __l(newlocale(LC_ALL_MASK, name, 0))
1193{
1194 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001195 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001196 " failed to construct for " + string(name));
1197}
1198
1199ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1200 : ctype<char>(0, false, refs),
1201 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1202{
1203 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001204 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001205 " failed to construct for " + name);
1206}
1207
1208ctype_byname<char>::~ctype_byname()
1209{
1210 freelocale(__l);
1211}
1212
1213char
1214ctype_byname<char>::do_toupper(char_type c) const
1215{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001216 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001217}
1218
1219const char*
1220ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1221{
1222 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001223 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001224 return low;
1225}
1226
1227char
1228ctype_byname<char>::do_tolower(char_type c) const
1229{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001230 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001231}
1232
1233const char*
1234ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1235{
1236 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001237 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001238 return low;
1239}
1240
1241// template <> class ctype_byname<wchar_t>
1242
1243ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1244 : ctype<wchar_t>(refs),
1245 __l(newlocale(LC_ALL_MASK, name, 0))
1246{
1247 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001248 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001249 " failed to construct for " + string(name));
1250}
1251
1252ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1253 : ctype<wchar_t>(refs),
1254 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1255{
1256 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001257 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001258 " failed to construct for " + name);
1259}
1260
1261ctype_byname<wchar_t>::~ctype_byname()
1262{
1263 freelocale(__l);
1264}
1265
1266bool
1267ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1268{
Alexis Huntc2017f12011-07-09 03:40:04 +00001269#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001270 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001271#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001272 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001273 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001274 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1275 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1276 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1277 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1278 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1279 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1280 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1281 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1282 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1283 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001284 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001285#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001286}
1287
1288const wchar_t*
1289ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1290{
1291 for (; low != high; ++low, ++vec)
1292 {
1293 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001294 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001295 else
1296 {
1297 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001298 wint_t ch = static_cast<wint_t>(*low);
1299 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001301#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001302 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001303 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001304#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001305 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001306 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001307 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001308 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001309 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001310 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001311#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001312 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001313 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001314#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001315 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001316 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001317 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001318 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001319#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001320 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001321 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001322#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001323#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001324 if (iswblank_l(ch, __l))
1325 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001326#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001327 }
1328 }
1329 return low;
1330}
1331
1332const wchar_t*
1333ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1334{
1335 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001336 {
1337#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001338 if (iswctype_l(*low, m, __l))
1339 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001340#else
Marshall Clowada0f732013-02-07 14:22:51 +00001341 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001342 if ((m & space) == space && iswspace_l(ch, __l)) break;
1343 if ((m & print) == print && iswprint_l(ch, __l)) break;
1344 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1345 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1346 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1347 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1348 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1349 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1350 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1351 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001352#endif
1353 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001354 return low;
1355}
1356
1357const wchar_t*
1358ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1359{
1360 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001361 {
1362#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001363 if (!iswctype_l(*low, m, __l))
1364 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001365#else
Marshall Clowada0f732013-02-07 14:22:51 +00001366 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001367 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1368 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1369 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1370 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1371 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1372 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1373 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1374 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1375 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1376 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001377 break;
1378#endif
1379 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001380 return low;
1381}
1382
1383wchar_t
1384ctype_byname<wchar_t>::do_toupper(char_type c) const
1385{
1386 return towupper_l(c, __l);
1387}
1388
1389const wchar_t*
1390ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1391{
1392 for (; low != high; ++low)
1393 *low = towupper_l(*low, __l);
1394 return low;
1395}
1396
1397wchar_t
1398ctype_byname<wchar_t>::do_tolower(char_type c) const
1399{
1400 return towlower_l(c, __l);
1401}
1402
1403const wchar_t*
1404ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1405{
1406 for (; low != high; ++low)
1407 *low = towlower_l(*low, __l);
1408 return low;
1409}
1410
1411wchar_t
1412ctype_byname<wchar_t>::do_widen(char c) const
1413{
Ben Craig3756b922016-03-09 15:39:39 +00001414 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001415}
1416
1417const char*
1418ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1419{
1420 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001421 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001422 return low;
1423}
1424
1425char
1426ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1427{
Ben Craig3756b922016-03-09 15:39:39 +00001428 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001429 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001430}
1431
1432const wchar_t*
1433ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1434{
1435 for (; low != high; ++low, ++dest)
1436 {
Ben Craig3756b922016-03-09 15:39:39 +00001437 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001438 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001439 }
1440 return low;
1441}
1442
1443// template <> class codecvt<char, char, mbstate_t>
1444
Howard Hinnantffb308e2010-08-22 00:03:27 +00001445locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001446
1447codecvt<char, char, mbstate_t>::~codecvt()
1448{
1449}
1450
1451codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001452codecvt<char, char, mbstate_t>::do_out(state_type&,
1453 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001454 extern_type* to, extern_type*, extern_type*& to_nxt) const
1455{
1456 frm_nxt = frm;
1457 to_nxt = to;
1458 return noconv;
1459}
1460
1461codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001462codecvt<char, char, mbstate_t>::do_in(state_type&,
1463 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001464 intern_type* to, intern_type*, intern_type*& to_nxt) const
1465{
1466 frm_nxt = frm;
1467 to_nxt = to;
1468 return noconv;
1469}
1470
1471codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001472codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001473 extern_type* to, extern_type*, extern_type*& to_nxt) const
1474{
1475 to_nxt = to;
1476 return noconv;
1477}
1478
1479int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001480codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001481{
1482 return 1;
1483}
1484
1485bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001486codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001487{
1488 return true;
1489}
1490
1491int
1492codecvt<char, char, mbstate_t>::do_length(state_type&,
1493 const extern_type* frm, const extern_type* end, size_t mx) const
1494{
Howard Hinnant28b24882011-12-01 20:21:04 +00001495 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001496}
1497
1498int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001499codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001500{
1501 return 1;
1502}
1503
1504// template <> class codecvt<wchar_t, char, mbstate_t>
1505
Howard Hinnantffb308e2010-08-22 00:03:27 +00001506locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001507
1508codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1509 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001510 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001511{
1512}
1513
1514codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1515 : locale::facet(refs),
1516 __l(newlocale(LC_ALL_MASK, nm, 0))
1517{
1518 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001519 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001520 " failed to construct for " + string(nm));
1521}
1522
1523codecvt<wchar_t, char, mbstate_t>::~codecvt()
1524{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001525 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001526 freelocale(__l);
1527}
1528
1529codecvt<wchar_t, char, mbstate_t>::result
1530codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001531 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001532 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1533{
1534 // look for first internal null in frm
1535 const intern_type* fend = frm;
1536 for (; fend != frm_end; ++fend)
1537 if (*fend == 0)
1538 break;
1539 // loop over all null-terminated sequences in frm
1540 to_nxt = to;
1541 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1542 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001543 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001544 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001545 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1546 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001547 if (n == size_t(-1))
1548 {
1549 // need to recover to_nxt
1550 for (to_nxt = to; frm != frm_nxt; ++frm)
1551 {
Ben Craig3756b922016-03-09 15:39:39 +00001552 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001553 if (n == size_t(-1))
1554 break;
1555 to_nxt += n;
1556 }
1557 frm_nxt = frm;
1558 return error;
1559 }
1560 if (n == 0)
1561 return partial;
1562 to_nxt += n;
1563 if (to_nxt == to_end)
1564 break;
1565 if (fend != frm_end) // set up next null terminated sequence
1566 {
1567 // Try to write the terminating null
1568 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001569 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001570 if (n == size_t(-1)) // on error
1571 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001572 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001573 return partial;
1574 for (extern_type* p = tmp; n; --n) // write it
1575 *to_nxt++ = *p++;
1576 ++frm_nxt;
1577 // look for next null in frm
1578 for (fend = frm_nxt; fend != frm_end; ++fend)
1579 if (*fend == 0)
1580 break;
1581 }
1582 }
1583 return frm_nxt == frm_end ? ok : partial;
1584}
1585
1586codecvt<wchar_t, char, mbstate_t>::result
1587codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001588 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001589 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1590{
1591 // look for first internal null in frm
1592 const extern_type* fend = frm;
1593 for (; fend != frm_end; ++fend)
1594 if (*fend == 0)
1595 break;
1596 // loop over all null-terminated sequences in frm
1597 to_nxt = to;
1598 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1599 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001600 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001601 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001602 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1603 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001604 if (n == size_t(-1))
1605 {
1606 // need to recover to_nxt
1607 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1608 {
Ben Craig3756b922016-03-09 15:39:39 +00001609 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1610 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001611 switch (n)
1612 {
1613 case 0:
1614 ++frm;
1615 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001616 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001617 frm_nxt = frm;
1618 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001619 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001620 frm_nxt = frm;
1621 return partial;
1622 default:
1623 frm += n;
1624 break;
1625 }
1626 }
1627 frm_nxt = frm;
1628 return frm_nxt == frm_end ? ok : partial;
1629 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001630 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001631 return error;
1632 to_nxt += n;
1633 if (to_nxt == to_end)
1634 break;
1635 if (fend != frm_end) // set up next null terminated sequence
1636 {
1637 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001638 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001639 if (n != 0) // on error
1640 return error;
1641 ++to_nxt;
1642 ++frm_nxt;
1643 // look for next null in frm
1644 for (fend = frm_nxt; fend != frm_end; ++fend)
1645 if (*fend == 0)
1646 break;
1647 }
1648 }
1649 return frm_nxt == frm_end ? ok : partial;
1650}
1651
1652codecvt<wchar_t, char, mbstate_t>::result
1653codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1654 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1655{
1656 to_nxt = to;
1657 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001658 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001659 if (n == size_t(-1) || n == 0) // on error
1660 return error;
1661 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001662 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001663 return partial;
1664 for (extern_type* p = tmp; n; --n) // write it
1665 *to_nxt++ = *p++;
1666 return ok;
1667}
1668
1669int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001670codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001671{
Ben Craig3756b922016-03-09 15:39:39 +00001672 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001673 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001674
1675 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001676 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001677 return 1; // which take more than 1 char to form a wchar_t
1678 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001679}
1680
1681bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001682codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001683{
1684 return false;
1685}
1686
1687int
1688codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1689 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1690{
1691 int nbytes = 0;
1692 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1693 {
Ben Craig3756b922016-03-09 15:39:39 +00001694 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001695 switch (n)
1696 {
1697 case 0:
1698 ++nbytes;
1699 ++frm;
1700 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001701 case size_t(-1):
1702 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001703 return nbytes;
1704 default:
1705 nbytes += n;
1706 frm += n;
1707 break;
1708 }
1709 }
1710 return nbytes;
1711}
1712
1713int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001714codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001715{
Ben Craig3756b922016-03-09 15:39:39 +00001716 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001717}
1718
1719// Valid UTF ranges
1720// UTF-32 UTF-16 UTF-8 # of code points
1721// first second first second third fourth
1722// 000000 - 00007F 0000 - 007F 00 - 7F 127
1723// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1724// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1725// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1726// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1727// 00D800 - 00DFFF invalid
1728// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1729// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1730// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1731// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1732
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001733static
1734codecvt_base::result
1735utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1736 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1737 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1738{
1739 frm_nxt = frm;
1740 to_nxt = to;
1741 if (mode & generate_header)
1742 {
1743 if (to_end-to_nxt < 3)
1744 return codecvt_base::partial;
1745 *to_nxt++ = static_cast<uint8_t>(0xEF);
1746 *to_nxt++ = static_cast<uint8_t>(0xBB);
1747 *to_nxt++ = static_cast<uint8_t>(0xBF);
1748 }
1749 for (; frm_nxt < frm_end; ++frm_nxt)
1750 {
1751 uint16_t wc1 = *frm_nxt;
1752 if (wc1 > Maxcode)
1753 return codecvt_base::error;
1754 if (wc1 < 0x0080)
1755 {
1756 if (to_end-to_nxt < 1)
1757 return codecvt_base::partial;
1758 *to_nxt++ = static_cast<uint8_t>(wc1);
1759 }
1760 else if (wc1 < 0x0800)
1761 {
1762 if (to_end-to_nxt < 2)
1763 return codecvt_base::partial;
1764 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1765 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1766 }
1767 else if (wc1 < 0xD800)
1768 {
1769 if (to_end-to_nxt < 3)
1770 return codecvt_base::partial;
1771 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1772 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1773 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1774 }
1775 else if (wc1 < 0xDC00)
1776 {
1777 if (frm_end-frm_nxt < 2)
1778 return codecvt_base::partial;
1779 uint16_t wc2 = frm_nxt[1];
1780 if ((wc2 & 0xFC00) != 0xDC00)
1781 return codecvt_base::error;
1782 if (to_end-to_nxt < 4)
1783 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001784 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1785 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001786 return codecvt_base::error;
1787 ++frm_nxt;
1788 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1789 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1790 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1791 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1792 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1793 }
1794 else if (wc1 < 0xE000)
1795 {
1796 return codecvt_base::error;
1797 }
1798 else
1799 {
1800 if (to_end-to_nxt < 3)
1801 return codecvt_base::partial;
1802 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1803 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1804 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1805 }
1806 }
1807 return codecvt_base::ok;
1808}
1809
1810static
1811codecvt_base::result
1812utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1813 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1814 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1815{
1816 frm_nxt = frm;
1817 to_nxt = to;
1818 if (mode & generate_header)
1819 {
1820 if (to_end-to_nxt < 3)
1821 return codecvt_base::partial;
1822 *to_nxt++ = static_cast<uint8_t>(0xEF);
1823 *to_nxt++ = static_cast<uint8_t>(0xBB);
1824 *to_nxt++ = static_cast<uint8_t>(0xBF);
1825 }
1826 for (; frm_nxt < frm_end; ++frm_nxt)
1827 {
1828 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1829 if (wc1 > Maxcode)
1830 return codecvt_base::error;
1831 if (wc1 < 0x0080)
1832 {
1833 if (to_end-to_nxt < 1)
1834 return codecvt_base::partial;
1835 *to_nxt++ = static_cast<uint8_t>(wc1);
1836 }
1837 else if (wc1 < 0x0800)
1838 {
1839 if (to_end-to_nxt < 2)
1840 return codecvt_base::partial;
1841 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1842 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1843 }
1844 else if (wc1 < 0xD800)
1845 {
1846 if (to_end-to_nxt < 3)
1847 return codecvt_base::partial;
1848 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1849 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1851 }
1852 else if (wc1 < 0xDC00)
1853 {
1854 if (frm_end-frm_nxt < 2)
1855 return codecvt_base::partial;
1856 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1857 if ((wc2 & 0xFC00) != 0xDC00)
1858 return codecvt_base::error;
1859 if (to_end-to_nxt < 4)
1860 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001861 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1862 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001863 return codecvt_base::error;
1864 ++frm_nxt;
1865 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1866 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1867 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1868 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1869 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1870 }
1871 else if (wc1 < 0xE000)
1872 {
1873 return codecvt_base::error;
1874 }
1875 else
1876 {
1877 if (to_end-to_nxt < 3)
1878 return codecvt_base::partial;
1879 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1880 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1881 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1882 }
1883 }
1884 return codecvt_base::ok;
1885}
1886
1887static
1888codecvt_base::result
1889utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1890 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1891 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1892{
1893 frm_nxt = frm;
1894 to_nxt = to;
1895 if (mode & consume_header)
1896 {
1897 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1898 frm_nxt[2] == 0xBF)
1899 frm_nxt += 3;
1900 }
1901 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1902 {
1903 uint8_t c1 = *frm_nxt;
1904 if (c1 > Maxcode)
1905 return codecvt_base::error;
1906 if (c1 < 0x80)
1907 {
1908 *to_nxt = static_cast<uint16_t>(c1);
1909 ++frm_nxt;
1910 }
1911 else if (c1 < 0xC2)
1912 {
1913 return codecvt_base::error;
1914 }
1915 else if (c1 < 0xE0)
1916 {
1917 if (frm_end-frm_nxt < 2)
1918 return codecvt_base::partial;
1919 uint8_t c2 = frm_nxt[1];
1920 if ((c2 & 0xC0) != 0x80)
1921 return codecvt_base::error;
1922 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1923 if (t > Maxcode)
1924 return codecvt_base::error;
1925 *to_nxt = t;
1926 frm_nxt += 2;
1927 }
1928 else if (c1 < 0xF0)
1929 {
1930 if (frm_end-frm_nxt < 3)
1931 return codecvt_base::partial;
1932 uint8_t c2 = frm_nxt[1];
1933 uint8_t c3 = frm_nxt[2];
1934 switch (c1)
1935 {
1936 case 0xE0:
1937 if ((c2 & 0xE0) != 0xA0)
1938 return codecvt_base::error;
1939 break;
1940 case 0xED:
1941 if ((c2 & 0xE0) != 0x80)
1942 return codecvt_base::error;
1943 break;
1944 default:
1945 if ((c2 & 0xC0) != 0x80)
1946 return codecvt_base::error;
1947 break;
1948 }
1949 if ((c3 & 0xC0) != 0x80)
1950 return codecvt_base::error;
1951 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1952 | ((c2 & 0x3F) << 6)
1953 | (c3 & 0x3F));
1954 if (t > Maxcode)
1955 return codecvt_base::error;
1956 *to_nxt = t;
1957 frm_nxt += 3;
1958 }
1959 else if (c1 < 0xF5)
1960 {
1961 if (frm_end-frm_nxt < 4)
1962 return codecvt_base::partial;
1963 uint8_t c2 = frm_nxt[1];
1964 uint8_t c3 = frm_nxt[2];
1965 uint8_t c4 = frm_nxt[3];
1966 switch (c1)
1967 {
1968 case 0xF0:
1969 if (!(0x90 <= c2 && c2 <= 0xBF))
1970 return codecvt_base::error;
1971 break;
1972 case 0xF4:
1973 if ((c2 & 0xF0) != 0x80)
1974 return codecvt_base::error;
1975 break;
1976 default:
1977 if ((c2 & 0xC0) != 0x80)
1978 return codecvt_base::error;
1979 break;
1980 }
1981 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1982 return codecvt_base::error;
1983 if (to_end-to_nxt < 2)
1984 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001985 if ((((c1 & 7UL) << 18) +
1986 ((c2 & 0x3FUL) << 12) +
1987 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001988 return codecvt_base::error;
1989 *to_nxt = static_cast<uint16_t>(
1990 0xD800
1991 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1992 | ((c2 & 0x0F) << 2)
1993 | ((c3 & 0x30) >> 4));
1994 *++to_nxt = static_cast<uint16_t>(
1995 0xDC00
1996 | ((c3 & 0x0F) << 6)
1997 | (c4 & 0x3F));
1998 frm_nxt += 4;
1999 }
2000 else
2001 {
2002 return codecvt_base::error;
2003 }
2004 }
2005 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2006}
2007
2008static
2009codecvt_base::result
2010utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2011 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2012 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2013{
2014 frm_nxt = frm;
2015 to_nxt = to;
2016 if (mode & consume_header)
2017 {
2018 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2019 frm_nxt[2] == 0xBF)
2020 frm_nxt += 3;
2021 }
2022 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2023 {
2024 uint8_t c1 = *frm_nxt;
2025 if (c1 > Maxcode)
2026 return codecvt_base::error;
2027 if (c1 < 0x80)
2028 {
2029 *to_nxt = static_cast<uint32_t>(c1);
2030 ++frm_nxt;
2031 }
2032 else if (c1 < 0xC2)
2033 {
2034 return codecvt_base::error;
2035 }
2036 else if (c1 < 0xE0)
2037 {
2038 if (frm_end-frm_nxt < 2)
2039 return codecvt_base::partial;
2040 uint8_t c2 = frm_nxt[1];
2041 if ((c2 & 0xC0) != 0x80)
2042 return codecvt_base::error;
2043 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2044 if (t > Maxcode)
2045 return codecvt_base::error;
2046 *to_nxt = static_cast<uint32_t>(t);
2047 frm_nxt += 2;
2048 }
2049 else if (c1 < 0xF0)
2050 {
2051 if (frm_end-frm_nxt < 3)
2052 return codecvt_base::partial;
2053 uint8_t c2 = frm_nxt[1];
2054 uint8_t c3 = frm_nxt[2];
2055 switch (c1)
2056 {
2057 case 0xE0:
2058 if ((c2 & 0xE0) != 0xA0)
2059 return codecvt_base::error;
2060 break;
2061 case 0xED:
2062 if ((c2 & 0xE0) != 0x80)
2063 return codecvt_base::error;
2064 break;
2065 default:
2066 if ((c2 & 0xC0) != 0x80)
2067 return codecvt_base::error;
2068 break;
2069 }
2070 if ((c3 & 0xC0) != 0x80)
2071 return codecvt_base::error;
2072 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2073 | ((c2 & 0x3F) << 6)
2074 | (c3 & 0x3F));
2075 if (t > Maxcode)
2076 return codecvt_base::error;
2077 *to_nxt = static_cast<uint32_t>(t);
2078 frm_nxt += 3;
2079 }
2080 else if (c1 < 0xF5)
2081 {
2082 if (frm_end-frm_nxt < 4)
2083 return codecvt_base::partial;
2084 uint8_t c2 = frm_nxt[1];
2085 uint8_t c3 = frm_nxt[2];
2086 uint8_t c4 = frm_nxt[3];
2087 switch (c1)
2088 {
2089 case 0xF0:
2090 if (!(0x90 <= c2 && c2 <= 0xBF))
2091 return codecvt_base::error;
2092 break;
2093 case 0xF4:
2094 if ((c2 & 0xF0) != 0x80)
2095 return codecvt_base::error;
2096 break;
2097 default:
2098 if ((c2 & 0xC0) != 0x80)
2099 return codecvt_base::error;
2100 break;
2101 }
2102 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2103 return codecvt_base::error;
2104 if (to_end-to_nxt < 2)
2105 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002106 if ((((c1 & 7UL) << 18) +
2107 ((c2 & 0x3FUL) << 12) +
2108 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002109 return codecvt_base::error;
2110 *to_nxt = static_cast<uint32_t>(
2111 0xD800
2112 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2113 | ((c2 & 0x0F) << 2)
2114 | ((c3 & 0x30) >> 4));
2115 *++to_nxt = static_cast<uint32_t>(
2116 0xDC00
2117 | ((c3 & 0x0F) << 6)
2118 | (c4 & 0x3F));
2119 frm_nxt += 4;
2120 }
2121 else
2122 {
2123 return codecvt_base::error;
2124 }
2125 }
2126 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2127}
2128
2129static
2130int
2131utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2132 size_t mx, unsigned long Maxcode = 0x10FFFF,
2133 codecvt_mode mode = codecvt_mode(0))
2134{
2135 const uint8_t* frm_nxt = frm;
2136 if (mode & consume_header)
2137 {
2138 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2139 frm_nxt[2] == 0xBF)
2140 frm_nxt += 3;
2141 }
2142 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2143 {
2144 uint8_t c1 = *frm_nxt;
2145 if (c1 > Maxcode)
2146 break;
2147 if (c1 < 0x80)
2148 {
2149 ++frm_nxt;
2150 }
2151 else if (c1 < 0xC2)
2152 {
2153 break;
2154 }
2155 else if (c1 < 0xE0)
2156 {
2157 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2158 break;
2159 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2160 if (t > Maxcode)
2161 break;
2162 frm_nxt += 2;
2163 }
2164 else if (c1 < 0xF0)
2165 {
2166 if (frm_end-frm_nxt < 3)
2167 break;
2168 uint8_t c2 = frm_nxt[1];
2169 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002170 switch (c1)
2171 {
2172 case 0xE0:
2173 if ((c2 & 0xE0) != 0xA0)
2174 return static_cast<int>(frm_nxt - frm);
2175 break;
2176 case 0xED:
2177 if ((c2 & 0xE0) != 0x80)
2178 return static_cast<int>(frm_nxt - frm);
2179 break;
2180 default:
2181 if ((c2 & 0xC0) != 0x80)
2182 return static_cast<int>(frm_nxt - frm);
2183 break;
2184 }
2185 if ((c3 & 0xC0) != 0x80)
2186 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002187 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002188 break;
2189 frm_nxt += 3;
2190 }
2191 else if (c1 < 0xF5)
2192 {
2193 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2194 break;
2195 uint8_t c2 = frm_nxt[1];
2196 uint8_t c3 = frm_nxt[2];
2197 uint8_t c4 = frm_nxt[3];
2198 switch (c1)
2199 {
2200 case 0xF0:
2201 if (!(0x90 <= c2 && c2 <= 0xBF))
2202 return static_cast<int>(frm_nxt - frm);
2203 break;
2204 case 0xF4:
2205 if ((c2 & 0xF0) != 0x80)
2206 return static_cast<int>(frm_nxt - frm);
2207 break;
2208 default:
2209 if ((c2 & 0xC0) != 0x80)
2210 return static_cast<int>(frm_nxt - frm);
2211 break;
2212 }
2213 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2214 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002215 if ((((c1 & 7UL) << 18) +
2216 ((c2 & 0x3FUL) << 12) +
2217 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002218 break;
2219 ++nchar16_t;
2220 frm_nxt += 4;
2221 }
2222 else
2223 {
2224 break;
2225 }
2226 }
2227 return static_cast<int>(frm_nxt - frm);
2228}
2229
2230static
2231codecvt_base::result
2232ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2233 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2234 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2235{
2236 frm_nxt = frm;
2237 to_nxt = to;
2238 if (mode & generate_header)
2239 {
2240 if (to_end-to_nxt < 3)
2241 return codecvt_base::partial;
2242 *to_nxt++ = static_cast<uint8_t>(0xEF);
2243 *to_nxt++ = static_cast<uint8_t>(0xBB);
2244 *to_nxt++ = static_cast<uint8_t>(0xBF);
2245 }
2246 for (; frm_nxt < frm_end; ++frm_nxt)
2247 {
2248 uint32_t wc = *frm_nxt;
2249 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2250 return codecvt_base::error;
2251 if (wc < 0x000080)
2252 {
2253 if (to_end-to_nxt < 1)
2254 return codecvt_base::partial;
2255 *to_nxt++ = static_cast<uint8_t>(wc);
2256 }
2257 else if (wc < 0x000800)
2258 {
2259 if (to_end-to_nxt < 2)
2260 return codecvt_base::partial;
2261 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2262 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2263 }
2264 else if (wc < 0x010000)
2265 {
2266 if (to_end-to_nxt < 3)
2267 return codecvt_base::partial;
2268 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2269 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2270 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2271 }
2272 else // if (wc < 0x110000)
2273 {
2274 if (to_end-to_nxt < 4)
2275 return codecvt_base::partial;
2276 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2277 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2278 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2279 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2280 }
2281 }
2282 return codecvt_base::ok;
2283}
2284
2285static
2286codecvt_base::result
2287utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2288 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2289 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2290{
2291 frm_nxt = frm;
2292 to_nxt = to;
2293 if (mode & consume_header)
2294 {
2295 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2296 frm_nxt[2] == 0xBF)
2297 frm_nxt += 3;
2298 }
2299 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2300 {
2301 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2302 if (c1 < 0x80)
2303 {
2304 if (c1 > Maxcode)
2305 return codecvt_base::error;
2306 *to_nxt = static_cast<uint32_t>(c1);
2307 ++frm_nxt;
2308 }
2309 else if (c1 < 0xC2)
2310 {
2311 return codecvt_base::error;
2312 }
2313 else if (c1 < 0xE0)
2314 {
2315 if (frm_end-frm_nxt < 2)
2316 return codecvt_base::partial;
2317 uint8_t c2 = frm_nxt[1];
2318 if ((c2 & 0xC0) != 0x80)
2319 return codecvt_base::error;
2320 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2321 | (c2 & 0x3F));
2322 if (t > Maxcode)
2323 return codecvt_base::error;
2324 *to_nxt = t;
2325 frm_nxt += 2;
2326 }
2327 else if (c1 < 0xF0)
2328 {
2329 if (frm_end-frm_nxt < 3)
2330 return codecvt_base::partial;
2331 uint8_t c2 = frm_nxt[1];
2332 uint8_t c3 = frm_nxt[2];
2333 switch (c1)
2334 {
2335 case 0xE0:
2336 if ((c2 & 0xE0) != 0xA0)
2337 return codecvt_base::error;
2338 break;
2339 case 0xED:
2340 if ((c2 & 0xE0) != 0x80)
2341 return codecvt_base::error;
2342 break;
2343 default:
2344 if ((c2 & 0xC0) != 0x80)
2345 return codecvt_base::error;
2346 break;
2347 }
2348 if ((c3 & 0xC0) != 0x80)
2349 return codecvt_base::error;
2350 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2351 | ((c2 & 0x3F) << 6)
2352 | (c3 & 0x3F));
2353 if (t > Maxcode)
2354 return codecvt_base::error;
2355 *to_nxt = t;
2356 frm_nxt += 3;
2357 }
2358 else if (c1 < 0xF5)
2359 {
2360 if (frm_end-frm_nxt < 4)
2361 return codecvt_base::partial;
2362 uint8_t c2 = frm_nxt[1];
2363 uint8_t c3 = frm_nxt[2];
2364 uint8_t c4 = frm_nxt[3];
2365 switch (c1)
2366 {
2367 case 0xF0:
2368 if (!(0x90 <= c2 && c2 <= 0xBF))
2369 return codecvt_base::error;
2370 break;
2371 case 0xF4:
2372 if ((c2 & 0xF0) != 0x80)
2373 return codecvt_base::error;
2374 break;
2375 default:
2376 if ((c2 & 0xC0) != 0x80)
2377 return codecvt_base::error;
2378 break;
2379 }
2380 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2381 return codecvt_base::error;
2382 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2383 | ((c2 & 0x3F) << 12)
2384 | ((c3 & 0x3F) << 6)
2385 | (c4 & 0x3F));
2386 if (t > Maxcode)
2387 return codecvt_base::error;
2388 *to_nxt = t;
2389 frm_nxt += 4;
2390 }
2391 else
2392 {
2393 return codecvt_base::error;
2394 }
2395 }
2396 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2397}
2398
2399static
2400int
2401utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2402 size_t mx, unsigned long Maxcode = 0x10FFFF,
2403 codecvt_mode mode = codecvt_mode(0))
2404{
2405 const uint8_t* frm_nxt = frm;
2406 if (mode & consume_header)
2407 {
2408 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2409 frm_nxt[2] == 0xBF)
2410 frm_nxt += 3;
2411 }
2412 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2413 {
2414 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2415 if (c1 < 0x80)
2416 {
2417 if (c1 > Maxcode)
2418 break;
2419 ++frm_nxt;
2420 }
2421 else if (c1 < 0xC2)
2422 {
2423 break;
2424 }
2425 else if (c1 < 0xE0)
2426 {
2427 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2428 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002429 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002430 break;
2431 frm_nxt += 2;
2432 }
2433 else if (c1 < 0xF0)
2434 {
2435 if (frm_end-frm_nxt < 3)
2436 break;
2437 uint8_t c2 = frm_nxt[1];
2438 uint8_t c3 = frm_nxt[2];
2439 switch (c1)
2440 {
2441 case 0xE0:
2442 if ((c2 & 0xE0) != 0xA0)
2443 return static_cast<int>(frm_nxt - frm);
2444 break;
2445 case 0xED:
2446 if ((c2 & 0xE0) != 0x80)
2447 return static_cast<int>(frm_nxt - frm);
2448 break;
2449 default:
2450 if ((c2 & 0xC0) != 0x80)
2451 return static_cast<int>(frm_nxt - frm);
2452 break;
2453 }
2454 if ((c3 & 0xC0) != 0x80)
2455 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002456 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002457 break;
2458 frm_nxt += 3;
2459 }
2460 else if (c1 < 0xF5)
2461 {
2462 if (frm_end-frm_nxt < 4)
2463 break;
2464 uint8_t c2 = frm_nxt[1];
2465 uint8_t c3 = frm_nxt[2];
2466 uint8_t c4 = frm_nxt[3];
2467 switch (c1)
2468 {
2469 case 0xF0:
2470 if (!(0x90 <= c2 && c2 <= 0xBF))
2471 return static_cast<int>(frm_nxt - frm);
2472 break;
2473 case 0xF4:
2474 if ((c2 & 0xF0) != 0x80)
2475 return static_cast<int>(frm_nxt - frm);
2476 break;
2477 default:
2478 if ((c2 & 0xC0) != 0x80)
2479 return static_cast<int>(frm_nxt - frm);
2480 break;
2481 }
2482 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2483 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002484 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2485 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002486 break;
2487 frm_nxt += 4;
2488 }
2489 else
2490 {
2491 break;
2492 }
2493 }
2494 return static_cast<int>(frm_nxt - frm);
2495}
2496
2497static
2498codecvt_base::result
2499ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2500 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2501 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2502{
2503 frm_nxt = frm;
2504 to_nxt = to;
2505 if (mode & generate_header)
2506 {
2507 if (to_end-to_nxt < 3)
2508 return codecvt_base::partial;
2509 *to_nxt++ = static_cast<uint8_t>(0xEF);
2510 *to_nxt++ = static_cast<uint8_t>(0xBB);
2511 *to_nxt++ = static_cast<uint8_t>(0xBF);
2512 }
2513 for (; frm_nxt < frm_end; ++frm_nxt)
2514 {
2515 uint16_t wc = *frm_nxt;
2516 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2517 return codecvt_base::error;
2518 if (wc < 0x0080)
2519 {
2520 if (to_end-to_nxt < 1)
2521 return codecvt_base::partial;
2522 *to_nxt++ = static_cast<uint8_t>(wc);
2523 }
2524 else if (wc < 0x0800)
2525 {
2526 if (to_end-to_nxt < 2)
2527 return codecvt_base::partial;
2528 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2529 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2530 }
2531 else // if (wc <= 0xFFFF)
2532 {
2533 if (to_end-to_nxt < 3)
2534 return codecvt_base::partial;
2535 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2536 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2537 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2538 }
2539 }
2540 return codecvt_base::ok;
2541}
2542
2543static
2544codecvt_base::result
2545utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2546 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2547 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2548{
2549 frm_nxt = frm;
2550 to_nxt = to;
2551 if (mode & consume_header)
2552 {
2553 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2554 frm_nxt[2] == 0xBF)
2555 frm_nxt += 3;
2556 }
2557 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2558 {
2559 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2560 if (c1 < 0x80)
2561 {
2562 if (c1 > Maxcode)
2563 return codecvt_base::error;
2564 *to_nxt = static_cast<uint16_t>(c1);
2565 ++frm_nxt;
2566 }
2567 else if (c1 < 0xC2)
2568 {
2569 return codecvt_base::error;
2570 }
2571 else if (c1 < 0xE0)
2572 {
2573 if (frm_end-frm_nxt < 2)
2574 return codecvt_base::partial;
2575 uint8_t c2 = frm_nxt[1];
2576 if ((c2 & 0xC0) != 0x80)
2577 return codecvt_base::error;
2578 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2579 | (c2 & 0x3F));
2580 if (t > Maxcode)
2581 return codecvt_base::error;
2582 *to_nxt = t;
2583 frm_nxt += 2;
2584 }
2585 else if (c1 < 0xF0)
2586 {
2587 if (frm_end-frm_nxt < 3)
2588 return codecvt_base::partial;
2589 uint8_t c2 = frm_nxt[1];
2590 uint8_t c3 = frm_nxt[2];
2591 switch (c1)
2592 {
2593 case 0xE0:
2594 if ((c2 & 0xE0) != 0xA0)
2595 return codecvt_base::error;
2596 break;
2597 case 0xED:
2598 if ((c2 & 0xE0) != 0x80)
2599 return codecvt_base::error;
2600 break;
2601 default:
2602 if ((c2 & 0xC0) != 0x80)
2603 return codecvt_base::error;
2604 break;
2605 }
2606 if ((c3 & 0xC0) != 0x80)
2607 return codecvt_base::error;
2608 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2609 | ((c2 & 0x3F) << 6)
2610 | (c3 & 0x3F));
2611 if (t > Maxcode)
2612 return codecvt_base::error;
2613 *to_nxt = t;
2614 frm_nxt += 3;
2615 }
2616 else
2617 {
2618 return codecvt_base::error;
2619 }
2620 }
2621 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2622}
2623
2624static
2625int
2626utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2627 size_t mx, unsigned long Maxcode = 0x10FFFF,
2628 codecvt_mode mode = codecvt_mode(0))
2629{
2630 const uint8_t* frm_nxt = frm;
2631 if (mode & consume_header)
2632 {
2633 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2634 frm_nxt[2] == 0xBF)
2635 frm_nxt += 3;
2636 }
2637 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2638 {
2639 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2640 if (c1 < 0x80)
2641 {
2642 if (c1 > Maxcode)
2643 break;
2644 ++frm_nxt;
2645 }
2646 else if (c1 < 0xC2)
2647 {
2648 break;
2649 }
2650 else if (c1 < 0xE0)
2651 {
2652 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2653 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002654 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002655 break;
2656 frm_nxt += 2;
2657 }
2658 else if (c1 < 0xF0)
2659 {
2660 if (frm_end-frm_nxt < 3)
2661 break;
2662 uint8_t c2 = frm_nxt[1];
2663 uint8_t c3 = frm_nxt[2];
2664 switch (c1)
2665 {
2666 case 0xE0:
2667 if ((c2 & 0xE0) != 0xA0)
2668 return static_cast<int>(frm_nxt - frm);
2669 break;
2670 case 0xED:
2671 if ((c2 & 0xE0) != 0x80)
2672 return static_cast<int>(frm_nxt - frm);
2673 break;
2674 default:
2675 if ((c2 & 0xC0) != 0x80)
2676 return static_cast<int>(frm_nxt - frm);
2677 break;
2678 }
2679 if ((c3 & 0xC0) != 0x80)
2680 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002681 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002682 break;
2683 frm_nxt += 3;
2684 }
2685 else
2686 {
2687 break;
2688 }
2689 }
2690 return static_cast<int>(frm_nxt - frm);
2691}
2692
2693static
2694codecvt_base::result
2695ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2696 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2697 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2698{
2699 frm_nxt = frm;
2700 to_nxt = to;
2701 if (mode & generate_header)
2702 {
2703 if (to_end-to_nxt < 2)
2704 return codecvt_base::partial;
2705 *to_nxt++ = static_cast<uint8_t>(0xFE);
2706 *to_nxt++ = static_cast<uint8_t>(0xFF);
2707 }
2708 for (; frm_nxt < frm_end; ++frm_nxt)
2709 {
2710 uint32_t wc = *frm_nxt;
2711 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2712 return codecvt_base::error;
2713 if (wc < 0x010000)
2714 {
2715 if (to_end-to_nxt < 2)
2716 return codecvt_base::partial;
2717 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2718 *to_nxt++ = static_cast<uint8_t>(wc);
2719 }
2720 else
2721 {
2722 if (to_end-to_nxt < 4)
2723 return codecvt_base::partial;
2724 uint16_t t = static_cast<uint16_t>(
2725 0xD800
2726 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2727 | ((wc & 0x00FC00) >> 10));
2728 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2729 *to_nxt++ = static_cast<uint8_t>(t);
2730 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2731 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2732 *to_nxt++ = static_cast<uint8_t>(t);
2733 }
2734 }
2735 return codecvt_base::ok;
2736}
2737
2738static
2739codecvt_base::result
2740utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2741 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2742 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2743{
2744 frm_nxt = frm;
2745 to_nxt = to;
2746 if (mode & consume_header)
2747 {
2748 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2749 frm_nxt += 2;
2750 }
2751 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2752 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002753 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002754 if ((c1 & 0xFC00) == 0xDC00)
2755 return codecvt_base::error;
2756 if ((c1 & 0xFC00) != 0xD800)
2757 {
2758 if (c1 > Maxcode)
2759 return codecvt_base::error;
2760 *to_nxt = static_cast<uint32_t>(c1);
2761 frm_nxt += 2;
2762 }
2763 else
2764 {
2765 if (frm_end-frm_nxt < 4)
2766 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002767 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002768 if ((c2 & 0xFC00) != 0xDC00)
2769 return codecvt_base::error;
2770 uint32_t t = static_cast<uint32_t>(
2771 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2772 | ((c1 & 0x003F) << 10)
2773 | (c2 & 0x03FF));
2774 if (t > Maxcode)
2775 return codecvt_base::error;
2776 *to_nxt = t;
2777 frm_nxt += 4;
2778 }
2779 }
2780 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2781}
2782
2783static
2784int
2785utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2786 size_t mx, unsigned long Maxcode = 0x10FFFF,
2787 codecvt_mode mode = codecvt_mode(0))
2788{
2789 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002790 if (mode & consume_header)
2791 {
2792 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2793 frm_nxt += 2;
2794 }
2795 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2796 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002797 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002798 if ((c1 & 0xFC00) == 0xDC00)
2799 break;
2800 if ((c1 & 0xFC00) != 0xD800)
2801 {
2802 if (c1 > Maxcode)
2803 break;
2804 frm_nxt += 2;
2805 }
2806 else
2807 {
2808 if (frm_end-frm_nxt < 4)
2809 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002810 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002811 if ((c2 & 0xFC00) != 0xDC00)
2812 break;
2813 uint32_t t = static_cast<uint32_t>(
2814 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2815 | ((c1 & 0x003F) << 10)
2816 | (c2 & 0x03FF));
2817 if (t > Maxcode)
2818 break;
2819 frm_nxt += 4;
2820 }
2821 }
2822 return static_cast<int>(frm_nxt - frm);
2823}
2824
2825static
2826codecvt_base::result
2827ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2828 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2829 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2830{
2831 frm_nxt = frm;
2832 to_nxt = to;
2833 if (mode & generate_header)
2834 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002835 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002836 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002837 *to_nxt++ = static_cast<uint8_t>(0xFF);
2838 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002839 }
2840 for (; frm_nxt < frm_end; ++frm_nxt)
2841 {
2842 uint32_t wc = *frm_nxt;
2843 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2844 return codecvt_base::error;
2845 if (wc < 0x010000)
2846 {
2847 if (to_end-to_nxt < 2)
2848 return codecvt_base::partial;
2849 *to_nxt++ = static_cast<uint8_t>(wc);
2850 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2851 }
2852 else
2853 {
2854 if (to_end-to_nxt < 4)
2855 return codecvt_base::partial;
2856 uint16_t t = static_cast<uint16_t>(
2857 0xD800
2858 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2859 | ((wc & 0x00FC00) >> 10));
2860 *to_nxt++ = static_cast<uint8_t>(t);
2861 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2862 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2863 *to_nxt++ = static_cast<uint8_t>(t);
2864 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2865 }
2866 }
2867 return codecvt_base::ok;
2868}
2869
2870static
2871codecvt_base::result
2872utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2873 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2874 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2875{
2876 frm_nxt = frm;
2877 to_nxt = to;
2878 if (mode & consume_header)
2879 {
2880 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2881 frm_nxt += 2;
2882 }
2883 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2884 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002885 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002886 if ((c1 & 0xFC00) == 0xDC00)
2887 return codecvt_base::error;
2888 if ((c1 & 0xFC00) != 0xD800)
2889 {
2890 if (c1 > Maxcode)
2891 return codecvt_base::error;
2892 *to_nxt = static_cast<uint32_t>(c1);
2893 frm_nxt += 2;
2894 }
2895 else
2896 {
2897 if (frm_end-frm_nxt < 4)
2898 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002899 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002900 if ((c2 & 0xFC00) != 0xDC00)
2901 return codecvt_base::error;
2902 uint32_t t = static_cast<uint32_t>(
2903 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2904 | ((c1 & 0x003F) << 10)
2905 | (c2 & 0x03FF));
2906 if (t > Maxcode)
2907 return codecvt_base::error;
2908 *to_nxt = t;
2909 frm_nxt += 4;
2910 }
2911 }
2912 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2913}
2914
2915static
2916int
2917utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2918 size_t mx, unsigned long Maxcode = 0x10FFFF,
2919 codecvt_mode mode = codecvt_mode(0))
2920{
2921 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002922 if (mode & consume_header)
2923 {
2924 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2925 frm_nxt += 2;
2926 }
2927 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2928 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002929 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002930 if ((c1 & 0xFC00) == 0xDC00)
2931 break;
2932 if ((c1 & 0xFC00) != 0xD800)
2933 {
2934 if (c1 > Maxcode)
2935 break;
2936 frm_nxt += 2;
2937 }
2938 else
2939 {
2940 if (frm_end-frm_nxt < 4)
2941 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002942 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002943 if ((c2 & 0xFC00) != 0xDC00)
2944 break;
2945 uint32_t t = static_cast<uint32_t>(
2946 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2947 | ((c1 & 0x003F) << 10)
2948 | (c2 & 0x03FF));
2949 if (t > Maxcode)
2950 break;
2951 frm_nxt += 4;
2952 }
2953 }
2954 return static_cast<int>(frm_nxt - frm);
2955}
2956
2957static
2958codecvt_base::result
2959ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2960 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2961 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2962{
2963 frm_nxt = frm;
2964 to_nxt = to;
2965 if (mode & generate_header)
2966 {
2967 if (to_end-to_nxt < 2)
2968 return codecvt_base::partial;
2969 *to_nxt++ = static_cast<uint8_t>(0xFE);
2970 *to_nxt++ = static_cast<uint8_t>(0xFF);
2971 }
2972 for (; frm_nxt < frm_end; ++frm_nxt)
2973 {
2974 uint16_t wc = *frm_nxt;
2975 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2976 return codecvt_base::error;
2977 if (to_end-to_nxt < 2)
2978 return codecvt_base::partial;
2979 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2980 *to_nxt++ = static_cast<uint8_t>(wc);
2981 }
2982 return codecvt_base::ok;
2983}
2984
2985static
2986codecvt_base::result
2987utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2988 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2989 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2990{
2991 frm_nxt = frm;
2992 to_nxt = to;
2993 if (mode & consume_header)
2994 {
2995 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2996 frm_nxt += 2;
2997 }
2998 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2999 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003000 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003001 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3002 return codecvt_base::error;
3003 *to_nxt = c1;
3004 frm_nxt += 2;
3005 }
3006 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3007}
3008
3009static
3010int
3011utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3012 size_t mx, unsigned long Maxcode = 0x10FFFF,
3013 codecvt_mode mode = codecvt_mode(0))
3014{
3015 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003016 if (mode & consume_header)
3017 {
3018 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3019 frm_nxt += 2;
3020 }
3021 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3022 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003023 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003024 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3025 break;
3026 frm_nxt += 2;
3027 }
3028 return static_cast<int>(frm_nxt - frm);
3029}
3030
3031static
3032codecvt_base::result
3033ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3034 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3035 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3036{
3037 frm_nxt = frm;
3038 to_nxt = to;
3039 if (mode & generate_header)
3040 {
3041 if (to_end-to_nxt < 2)
3042 return codecvt_base::partial;
3043 *to_nxt++ = static_cast<uint8_t>(0xFF);
3044 *to_nxt++ = static_cast<uint8_t>(0xFE);
3045 }
3046 for (; frm_nxt < frm_end; ++frm_nxt)
3047 {
3048 uint16_t wc = *frm_nxt;
3049 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3050 return codecvt_base::error;
3051 if (to_end-to_nxt < 2)
3052 return codecvt_base::partial;
3053 *to_nxt++ = static_cast<uint8_t>(wc);
3054 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3055 }
3056 return codecvt_base::ok;
3057}
3058
3059static
3060codecvt_base::result
3061utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3062 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3063 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3064{
3065 frm_nxt = frm;
3066 to_nxt = to;
3067 if (mode & consume_header)
3068 {
3069 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3070 frm_nxt += 2;
3071 }
3072 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3073 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003074 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003075 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3076 return codecvt_base::error;
3077 *to_nxt = c1;
3078 frm_nxt += 2;
3079 }
3080 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3081}
3082
3083static
3084int
3085utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3086 size_t mx, unsigned long Maxcode = 0x10FFFF,
3087 codecvt_mode mode = codecvt_mode(0))
3088{
3089 const uint8_t* frm_nxt = frm;
3090 frm_nxt = frm;
3091 if (mode & consume_header)
3092 {
3093 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3094 frm_nxt += 2;
3095 }
3096 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3097 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003098 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003099 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3100 break;
3101 frm_nxt += 2;
3102 }
3103 return static_cast<int>(frm_nxt - frm);
3104}
3105
Howard Hinnantc51e1022010-05-11 19:42:16 +00003106// template <> class codecvt<char16_t, char, mbstate_t>
3107
Howard Hinnantffb308e2010-08-22 00:03:27 +00003108locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003109
3110codecvt<char16_t, char, mbstate_t>::~codecvt()
3111{
3112}
3113
3114codecvt<char16_t, char, mbstate_t>::result
3115codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003116 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003117 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3118{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003119 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3120 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3121 const uint16_t* _frm_nxt = _frm;
3122 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3123 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3124 uint8_t* _to_nxt = _to;
3125 result r = utf16_to_utf8(_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_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003133 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003134 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3135{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003136 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3137 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3138 const uint8_t* _frm_nxt = _frm;
3139 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3140 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3141 uint16_t* _to_nxt = _to;
3142 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3143 frm_nxt = frm + (_frm_nxt - _frm);
3144 to_nxt = to + (_to_nxt - _to);
3145 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003146}
3147
3148codecvt<char16_t, char, mbstate_t>::result
3149codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3150 extern_type* to, extern_type*, extern_type*& to_nxt) const
3151{
3152 to_nxt = to;
3153 return noconv;
3154}
3155
3156int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003157codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003158{
3159 return 0;
3160}
3161
3162bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003163codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003164{
3165 return false;
3166}
3167
3168int
3169codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3170 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3171{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003172 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3173 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3174 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003175}
3176
3177int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003178codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003179{
3180 return 4;
3181}
3182
3183// template <> class codecvt<char32_t, char, mbstate_t>
3184
Howard Hinnantffb308e2010-08-22 00:03:27 +00003185locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003186
3187codecvt<char32_t, char, mbstate_t>::~codecvt()
3188{
3189}
3190
3191codecvt<char32_t, char, mbstate_t>::result
3192codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003193 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003194 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3195{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003196 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3197 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3198 const uint32_t* _frm_nxt = _frm;
3199 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3200 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3201 uint8_t* _to_nxt = _to;
3202 result r = ucs4_to_utf8(_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_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003210 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003211 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3212{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003213 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3214 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3215 const uint8_t* _frm_nxt = _frm;
3216 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3217 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3218 uint32_t* _to_nxt = _to;
3219 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3220 frm_nxt = frm + (_frm_nxt - _frm);
3221 to_nxt = to + (_to_nxt - _to);
3222 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003223}
3224
3225codecvt<char32_t, char, mbstate_t>::result
3226codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3227 extern_type* to, extern_type*, extern_type*& to_nxt) const
3228{
3229 to_nxt = to;
3230 return noconv;
3231}
3232
3233int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003234codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003235{
3236 return 0;
3237}
3238
3239bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003240codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003241{
3242 return false;
3243}
3244
3245int
3246codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3247 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3248{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003249 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3250 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3251 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003252}
3253
3254int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003255codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003256{
3257 return 4;
3258}
3259
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003260// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003261
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003262__codecvt_utf8<wchar_t>::result
3263__codecvt_utf8<wchar_t>::do_out(state_type&,
3264 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003265 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3266{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003267#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003268 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3269 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3270 const uint16_t* _frm_nxt = _frm;
3271#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003272 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3273 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3274 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003275#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003276 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3277 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3278 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003279#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003280 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3281 _Maxcode_, _Mode_);
3282#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003283 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3284 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003285#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003286 frm_nxt = frm + (_frm_nxt - _frm);
3287 to_nxt = to + (_to_nxt - _to);
3288 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003289}
3290
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003291__codecvt_utf8<wchar_t>::result
3292__codecvt_utf8<wchar_t>::do_in(state_type&,
3293 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003294 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3295{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003296 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3297 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3298 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003299#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003300 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3301 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3302 uint16_t* _to_nxt = _to;
3303 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3304 _Maxcode_, _Mode_);
3305#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003306 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3307 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3308 uint32_t* _to_nxt = _to;
3309 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3310 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003311#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003312 frm_nxt = frm + (_frm_nxt - _frm);
3313 to_nxt = to + (_to_nxt - _to);
3314 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003315}
3316
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003317__codecvt_utf8<wchar_t>::result
3318__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003319 extern_type* to, extern_type*, extern_type*& to_nxt) const
3320{
3321 to_nxt = to;
3322 return noconv;
3323}
3324
3325int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003326__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003327{
3328 return 0;
3329}
3330
3331bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003332__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003333{
3334 return false;
3335}
3336
3337int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003338__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003339 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3340{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003341 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3342 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3343 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003344}
3345
3346int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003347__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003348{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003349 if (_Mode_ & consume_header)
3350 return 7;
3351 return 4;
3352}
3353
3354// __codecvt_utf8<char16_t>
3355
3356__codecvt_utf8<char16_t>::result
3357__codecvt_utf8<char16_t>::do_out(state_type&,
3358 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3359 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3360{
3361 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3362 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3363 const uint16_t* _frm_nxt = _frm;
3364 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3365 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3366 uint8_t* _to_nxt = _to;
3367 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3368 _Maxcode_, _Mode_);
3369 frm_nxt = frm + (_frm_nxt - _frm);
3370 to_nxt = to + (_to_nxt - _to);
3371 return r;
3372}
3373
3374__codecvt_utf8<char16_t>::result
3375__codecvt_utf8<char16_t>::do_in(state_type&,
3376 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3377 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3378{
3379 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3380 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3381 const uint8_t* _frm_nxt = _frm;
3382 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3383 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3384 uint16_t* _to_nxt = _to;
3385 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3386 _Maxcode_, _Mode_);
3387 frm_nxt = frm + (_frm_nxt - _frm);
3388 to_nxt = to + (_to_nxt - _to);
3389 return r;
3390}
3391
3392__codecvt_utf8<char16_t>::result
3393__codecvt_utf8<char16_t>::do_unshift(state_type&,
3394 extern_type* to, extern_type*, extern_type*& to_nxt) const
3395{
3396 to_nxt = to;
3397 return noconv;
3398}
3399
3400int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003401__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003402{
3403 return 0;
3404}
3405
3406bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003407__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003408{
3409 return false;
3410}
3411
3412int
3413__codecvt_utf8<char16_t>::do_length(state_type&,
3414 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3415{
3416 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3417 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3418 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3419}
3420
3421int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003422__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003423{
3424 if (_Mode_ & consume_header)
3425 return 6;
3426 return 3;
3427}
3428
3429// __codecvt_utf8<char32_t>
3430
3431__codecvt_utf8<char32_t>::result
3432__codecvt_utf8<char32_t>::do_out(state_type&,
3433 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3434 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3435{
3436 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3437 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3438 const uint32_t* _frm_nxt = _frm;
3439 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3440 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3441 uint8_t* _to_nxt = _to;
3442 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3443 _Maxcode_, _Mode_);
3444 frm_nxt = frm + (_frm_nxt - _frm);
3445 to_nxt = to + (_to_nxt - _to);
3446 return r;
3447}
3448
3449__codecvt_utf8<char32_t>::result
3450__codecvt_utf8<char32_t>::do_in(state_type&,
3451 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3452 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3453{
3454 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3455 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3456 const uint8_t* _frm_nxt = _frm;
3457 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3458 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3459 uint32_t* _to_nxt = _to;
3460 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3461 _Maxcode_, _Mode_);
3462 frm_nxt = frm + (_frm_nxt - _frm);
3463 to_nxt = to + (_to_nxt - _to);
3464 return r;
3465}
3466
3467__codecvt_utf8<char32_t>::result
3468__codecvt_utf8<char32_t>::do_unshift(state_type&,
3469 extern_type* to, extern_type*, extern_type*& to_nxt) const
3470{
3471 to_nxt = to;
3472 return noconv;
3473}
3474
3475int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003476__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003477{
3478 return 0;
3479}
3480
3481bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003482__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003483{
3484 return false;
3485}
3486
3487int
3488__codecvt_utf8<char32_t>::do_length(state_type&,
3489 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3490{
3491 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3492 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3493 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3494}
3495
3496int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003497__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003498{
3499 if (_Mode_ & consume_header)
3500 return 7;
3501 return 4;
3502}
3503
3504// __codecvt_utf16<wchar_t, false>
3505
3506__codecvt_utf16<wchar_t, false>::result
3507__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3508 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3509 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3510{
3511 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3512 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3513 const uint32_t* _frm_nxt = _frm;
3514 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3515 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3516 uint8_t* _to_nxt = _to;
3517 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3518 _Maxcode_, _Mode_);
3519 frm_nxt = frm + (_frm_nxt - _frm);
3520 to_nxt = to + (_to_nxt - _to);
3521 return r;
3522}
3523
3524__codecvt_utf16<wchar_t, false>::result
3525__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3526 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3527 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3528{
3529 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3530 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3531 const uint8_t* _frm_nxt = _frm;
3532 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3533 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3534 uint32_t* _to_nxt = _to;
3535 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3536 _Maxcode_, _Mode_);
3537 frm_nxt = frm + (_frm_nxt - _frm);
3538 to_nxt = to + (_to_nxt - _to);
3539 return r;
3540}
3541
3542__codecvt_utf16<wchar_t, false>::result
3543__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3544 extern_type* to, extern_type*, extern_type*& to_nxt) const
3545{
3546 to_nxt = to;
3547 return noconv;
3548}
3549
3550int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003551__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003552{
3553 return 0;
3554}
3555
3556bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003557__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003558{
3559 return false;
3560}
3561
3562int
3563__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3564 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3565{
3566 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3567 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3568 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3569}
3570
3571int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003572__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003573{
3574 if (_Mode_ & consume_header)
3575 return 6;
3576 return 4;
3577}
3578
3579// __codecvt_utf16<wchar_t, true>
3580
3581__codecvt_utf16<wchar_t, true>::result
3582__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3583 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3584 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3585{
3586 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3587 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3588 const uint32_t* _frm_nxt = _frm;
3589 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3590 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3591 uint8_t* _to_nxt = _to;
3592 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3593 _Maxcode_, _Mode_);
3594 frm_nxt = frm + (_frm_nxt - _frm);
3595 to_nxt = to + (_to_nxt - _to);
3596 return r;
3597}
3598
3599__codecvt_utf16<wchar_t, true>::result
3600__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3601 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3602 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3603{
3604 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3605 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3606 const uint8_t* _frm_nxt = _frm;
3607 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3608 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3609 uint32_t* _to_nxt = _to;
3610 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3611 _Maxcode_, _Mode_);
3612 frm_nxt = frm + (_frm_nxt - _frm);
3613 to_nxt = to + (_to_nxt - _to);
3614 return r;
3615}
3616
3617__codecvt_utf16<wchar_t, true>::result
3618__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3619 extern_type* to, extern_type*, extern_type*& to_nxt) const
3620{
3621 to_nxt = to;
3622 return noconv;
3623}
3624
3625int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003626__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003627{
3628 return 0;
3629}
3630
3631bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003632__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003633{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003634 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003635}
3636
3637int
3638__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3639 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3640{
3641 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3642 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3643 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3644}
3645
3646int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003647__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003648{
3649 if (_Mode_ & consume_header)
3650 return 6;
3651 return 4;
3652}
3653
3654// __codecvt_utf16<char16_t, false>
3655
3656__codecvt_utf16<char16_t, false>::result
3657__codecvt_utf16<char16_t, false>::do_out(state_type&,
3658 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3659 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3660{
3661 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3662 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3663 const uint16_t* _frm_nxt = _frm;
3664 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3665 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3666 uint8_t* _to_nxt = _to;
3667 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3668 _Maxcode_, _Mode_);
3669 frm_nxt = frm + (_frm_nxt - _frm);
3670 to_nxt = to + (_to_nxt - _to);
3671 return r;
3672}
3673
3674__codecvt_utf16<char16_t, false>::result
3675__codecvt_utf16<char16_t, false>::do_in(state_type&,
3676 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3677 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3678{
3679 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3680 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3681 const uint8_t* _frm_nxt = _frm;
3682 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3683 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3684 uint16_t* _to_nxt = _to;
3685 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3686 _Maxcode_, _Mode_);
3687 frm_nxt = frm + (_frm_nxt - _frm);
3688 to_nxt = to + (_to_nxt - _to);
3689 return r;
3690}
3691
3692__codecvt_utf16<char16_t, false>::result
3693__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3694 extern_type* to, extern_type*, extern_type*& to_nxt) const
3695{
3696 to_nxt = to;
3697 return noconv;
3698}
3699
3700int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003701__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003702{
3703 return 0;
3704}
3705
3706bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003707__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003708{
3709 return false;
3710}
3711
3712int
3713__codecvt_utf16<char16_t, false>::do_length(state_type&,
3714 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3715{
3716 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3717 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3718 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3719}
3720
3721int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003722__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003723{
3724 if (_Mode_ & consume_header)
3725 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003726 return 2;
3727}
3728
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003729// __codecvt_utf16<char16_t, true>
3730
3731__codecvt_utf16<char16_t, true>::result
3732__codecvt_utf16<char16_t, true>::do_out(state_type&,
3733 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3734 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3735{
3736 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3737 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3738 const uint16_t* _frm_nxt = _frm;
3739 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3740 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3741 uint8_t* _to_nxt = _to;
3742 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3743 _Maxcode_, _Mode_);
3744 frm_nxt = frm + (_frm_nxt - _frm);
3745 to_nxt = to + (_to_nxt - _to);
3746 return r;
3747}
3748
3749__codecvt_utf16<char16_t, true>::result
3750__codecvt_utf16<char16_t, true>::do_in(state_type&,
3751 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3752 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3753{
3754 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3755 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3756 const uint8_t* _frm_nxt = _frm;
3757 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3758 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3759 uint16_t* _to_nxt = _to;
3760 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3761 _Maxcode_, _Mode_);
3762 frm_nxt = frm + (_frm_nxt - _frm);
3763 to_nxt = to + (_to_nxt - _to);
3764 return r;
3765}
3766
3767__codecvt_utf16<char16_t, true>::result
3768__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3769 extern_type* to, extern_type*, extern_type*& to_nxt) const
3770{
3771 to_nxt = to;
3772 return noconv;
3773}
3774
3775int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003776__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003777{
3778 return 0;
3779}
3780
3781bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003782__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003783{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003784 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003785}
3786
3787int
3788__codecvt_utf16<char16_t, true>::do_length(state_type&,
3789 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3790{
3791 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3792 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3793 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3794}
3795
3796int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003797__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003798{
3799 if (_Mode_ & consume_header)
3800 return 4;
3801 return 2;
3802}
3803
3804// __codecvt_utf16<char32_t, false>
3805
3806__codecvt_utf16<char32_t, false>::result
3807__codecvt_utf16<char32_t, false>::do_out(state_type&,
3808 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3809 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3810{
3811 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3812 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3813 const uint32_t* _frm_nxt = _frm;
3814 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3815 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3816 uint8_t* _to_nxt = _to;
3817 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3818 _Maxcode_, _Mode_);
3819 frm_nxt = frm + (_frm_nxt - _frm);
3820 to_nxt = to + (_to_nxt - _to);
3821 return r;
3822}
3823
3824__codecvt_utf16<char32_t, false>::result
3825__codecvt_utf16<char32_t, false>::do_in(state_type&,
3826 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3827 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3828{
3829 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3830 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3831 const uint8_t* _frm_nxt = _frm;
3832 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3833 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3834 uint32_t* _to_nxt = _to;
3835 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3836 _Maxcode_, _Mode_);
3837 frm_nxt = frm + (_frm_nxt - _frm);
3838 to_nxt = to + (_to_nxt - _to);
3839 return r;
3840}
3841
3842__codecvt_utf16<char32_t, false>::result
3843__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3844 extern_type* to, extern_type*, extern_type*& to_nxt) const
3845{
3846 to_nxt = to;
3847 return noconv;
3848}
3849
3850int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003851__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003852{
3853 return 0;
3854}
3855
3856bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003857__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003858{
3859 return false;
3860}
3861
3862int
3863__codecvt_utf16<char32_t, false>::do_length(state_type&,
3864 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3865{
3866 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3867 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3868 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3869}
3870
3871int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003872__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003873{
3874 if (_Mode_ & consume_header)
3875 return 6;
3876 return 4;
3877}
3878
3879// __codecvt_utf16<char32_t, true>
3880
3881__codecvt_utf16<char32_t, true>::result
3882__codecvt_utf16<char32_t, true>::do_out(state_type&,
3883 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3884 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3885{
3886 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3887 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3888 const uint32_t* _frm_nxt = _frm;
3889 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3890 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3891 uint8_t* _to_nxt = _to;
3892 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3893 _Maxcode_, _Mode_);
3894 frm_nxt = frm + (_frm_nxt - _frm);
3895 to_nxt = to + (_to_nxt - _to);
3896 return r;
3897}
3898
3899__codecvt_utf16<char32_t, true>::result
3900__codecvt_utf16<char32_t, true>::do_in(state_type&,
3901 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3902 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3903{
3904 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3905 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3906 const uint8_t* _frm_nxt = _frm;
3907 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3908 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3909 uint32_t* _to_nxt = _to;
3910 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3911 _Maxcode_, _Mode_);
3912 frm_nxt = frm + (_frm_nxt - _frm);
3913 to_nxt = to + (_to_nxt - _to);
3914 return r;
3915}
3916
3917__codecvt_utf16<char32_t, true>::result
3918__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3919 extern_type* to, extern_type*, extern_type*& to_nxt) const
3920{
3921 to_nxt = to;
3922 return noconv;
3923}
3924
3925int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003926__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003927{
3928 return 0;
3929}
3930
3931bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003932__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003933{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003934 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003935}
3936
3937int
3938__codecvt_utf16<char32_t, true>::do_length(state_type&,
3939 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3940{
3941 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3942 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3943 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3944}
3945
3946int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003947__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003948{
3949 if (_Mode_ & consume_header)
3950 return 6;
3951 return 4;
3952}
3953
3954// __codecvt_utf8_utf16<wchar_t>
3955
3956__codecvt_utf8_utf16<wchar_t>::result
3957__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3958 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3959 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3960{
3961 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3962 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3963 const uint32_t* _frm_nxt = _frm;
3964 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3965 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3966 uint8_t* _to_nxt = _to;
3967 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3968 _Maxcode_, _Mode_);
3969 frm_nxt = frm + (_frm_nxt - _frm);
3970 to_nxt = to + (_to_nxt - _to);
3971 return r;
3972}
3973
3974__codecvt_utf8_utf16<wchar_t>::result
3975__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3976 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3977 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3978{
3979 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3980 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3981 const uint8_t* _frm_nxt = _frm;
3982 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3983 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3984 uint32_t* _to_nxt = _to;
3985 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3986 _Maxcode_, _Mode_);
3987 frm_nxt = frm + (_frm_nxt - _frm);
3988 to_nxt = to + (_to_nxt - _to);
3989 return r;
3990}
3991
3992__codecvt_utf8_utf16<wchar_t>::result
3993__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3994 extern_type* to, extern_type*, extern_type*& to_nxt) const
3995{
3996 to_nxt = to;
3997 return noconv;
3998}
3999
4000int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004001__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004002{
4003 return 0;
4004}
4005
4006bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004007__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004008{
4009 return false;
4010}
4011
4012int
4013__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4014 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4015{
4016 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4017 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4018 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4019}
4020
4021int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004022__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004023{
4024 if (_Mode_ & consume_header)
4025 return 7;
4026 return 4;
4027}
4028
4029// __codecvt_utf8_utf16<char16_t>
4030
4031__codecvt_utf8_utf16<char16_t>::result
4032__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4033 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4034 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4035{
4036 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4037 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4038 const uint16_t* _frm_nxt = _frm;
4039 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4040 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4041 uint8_t* _to_nxt = _to;
4042 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4043 _Maxcode_, _Mode_);
4044 frm_nxt = frm + (_frm_nxt - _frm);
4045 to_nxt = to + (_to_nxt - _to);
4046 return r;
4047}
4048
4049__codecvt_utf8_utf16<char16_t>::result
4050__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4051 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4052 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4053{
4054 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4055 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4056 const uint8_t* _frm_nxt = _frm;
4057 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4058 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4059 uint16_t* _to_nxt = _to;
4060 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4061 _Maxcode_, _Mode_);
4062 frm_nxt = frm + (_frm_nxt - _frm);
4063 to_nxt = to + (_to_nxt - _to);
4064 return r;
4065}
4066
4067__codecvt_utf8_utf16<char16_t>::result
4068__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4069 extern_type* to, extern_type*, extern_type*& to_nxt) const
4070{
4071 to_nxt = to;
4072 return noconv;
4073}
4074
4075int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004076__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004077{
4078 return 0;
4079}
4080
4081bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004082__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004083{
4084 return false;
4085}
4086
4087int
4088__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4089 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4090{
4091 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4092 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4093 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4094}
4095
4096int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004097__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004098{
4099 if (_Mode_ & consume_header)
4100 return 7;
4101 return 4;
4102}
4103
4104// __codecvt_utf8_utf16<char32_t>
4105
4106__codecvt_utf8_utf16<char32_t>::result
4107__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4108 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4109 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4110{
4111 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4112 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4113 const uint32_t* _frm_nxt = _frm;
4114 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4115 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4116 uint8_t* _to_nxt = _to;
4117 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4118 _Maxcode_, _Mode_);
4119 frm_nxt = frm + (_frm_nxt - _frm);
4120 to_nxt = to + (_to_nxt - _to);
4121 return r;
4122}
4123
4124__codecvt_utf8_utf16<char32_t>::result
4125__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4126 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4127 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4128{
4129 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4130 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4131 const uint8_t* _frm_nxt = _frm;
4132 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4133 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4134 uint32_t* _to_nxt = _to;
4135 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4136 _Maxcode_, _Mode_);
4137 frm_nxt = frm + (_frm_nxt - _frm);
4138 to_nxt = to + (_to_nxt - _to);
4139 return r;
4140}
4141
4142__codecvt_utf8_utf16<char32_t>::result
4143__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4144 extern_type* to, extern_type*, extern_type*& to_nxt) const
4145{
4146 to_nxt = to;
4147 return noconv;
4148}
4149
4150int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004151__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004152{
4153 return 0;
4154}
4155
4156bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004157__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004158{
4159 return false;
4160}
4161
4162int
4163__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4164 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4165{
4166 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4167 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4168 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4169}
4170
4171int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004172__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004173{
4174 if (_Mode_ & consume_header)
4175 return 7;
4176 return 4;
4177}
4178
Howard Hinnantc51e1022010-05-11 19:42:16 +00004179// __narrow_to_utf8<16>
4180
4181__narrow_to_utf8<16>::~__narrow_to_utf8()
4182{
4183}
4184
4185// __narrow_to_utf8<32>
4186
4187__narrow_to_utf8<32>::~__narrow_to_utf8()
4188{
4189}
4190
4191// __widen_from_utf8<16>
4192
4193__widen_from_utf8<16>::~__widen_from_utf8()
4194{
4195}
4196
4197// __widen_from_utf8<32>
4198
4199__widen_from_utf8<32>::~__widen_from_utf8()
4200{
4201}
4202
Eric Fiselierbf945a22016-12-11 00:20:59 +00004203
4204static bool checked_string_to_wchar_convert(wchar_t& dest,
4205 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004206 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004207 if (*ptr == '\0')
4208 return false;
4209 mbstate_t mb = {};
4210 wchar_t out;
4211 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4212 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4213 return false;
4214 }
4215 dest = out;
4216 return true;
4217}
4218
4219static bool checked_string_to_char_convert(char& dest,
4220 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004221 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004222 if (*ptr == '\0')
4223 return false;
4224 if (!ptr[1]) {
4225 dest = *ptr;
4226 return true;
4227 }
4228 // First convert the MBS into a wide char then attempt to narrow it using
4229 // wctob_l.
4230 wchar_t wout;
4231 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4232 return false;
4233 int res;
4234 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4235 dest = res;
4236 return true;
4237 }
4238 // FIXME: Work around specific multibyte sequences that we can reasonable
4239 // translate into a different single byte.
4240 switch (wout) {
4241 case L'\u00A0': // non-breaking space
4242 dest = ' ';
4243 return true;
4244 default:
4245 return false;
4246 }
4247 _LIBCPP_UNREACHABLE();
4248}
4249
4250
Howard Hinnantc51e1022010-05-11 19:42:16 +00004251// numpunct<char> && numpunct<wchar_t>
4252
4253locale::id numpunct< char >::id;
4254locale::id numpunct<wchar_t>::id;
4255
4256numpunct<char>::numpunct(size_t refs)
4257 : locale::facet(refs),
4258 __decimal_point_('.'),
4259 __thousands_sep_(',')
4260{
4261}
4262
4263numpunct<wchar_t>::numpunct(size_t refs)
4264 : locale::facet(refs),
4265 __decimal_point_(L'.'),
4266 __thousands_sep_(L',')
4267{
4268}
4269
4270numpunct<char>::~numpunct()
4271{
4272}
4273
4274numpunct<wchar_t>::~numpunct()
4275{
4276}
4277
4278 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4279wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4280
4281 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4282wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4283
4284string numpunct< char >::do_grouping() const {return __grouping_;}
4285string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4286
4287 string numpunct< char >::do_truename() const {return "true";}
4288wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4289
4290 string numpunct< char >::do_falsename() const {return "false";}
4291wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4292
4293// numpunct_byname<char>
4294
4295numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4296 : numpunct<char>(refs)
4297{
4298 __init(nm);
4299}
4300
4301numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4302 : numpunct<char>(refs)
4303{
4304 __init(nm.c_str());
4305}
4306
4307numpunct_byname<char>::~numpunct_byname()
4308{
4309}
4310
4311void
4312numpunct_byname<char>::__init(const char* nm)
4313{
4314 if (strcmp(nm, "C") != 0)
4315 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004316 __libcpp_unique_locale loc(nm);
4317 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004318 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004319 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004320
Ben Craig3756b922016-03-09 15:39:39 +00004321 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004322 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4323 loc.get());
4324 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4325 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004326 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004327 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004328 }
4329}
4330
4331// numpunct_byname<wchar_t>
4332
4333numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4334 : numpunct<wchar_t>(refs)
4335{
4336 __init(nm);
4337}
4338
4339numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4340 : numpunct<wchar_t>(refs)
4341{
4342 __init(nm.c_str());
4343}
4344
4345numpunct_byname<wchar_t>::~numpunct_byname()
4346{
4347}
4348
4349void
4350numpunct_byname<wchar_t>::__init(const char* nm)
4351{
4352 if (strcmp(nm, "C") != 0)
4353 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004354 __libcpp_unique_locale loc(nm);
4355 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004356 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004357 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004358
Ben Craig3756b922016-03-09 15:39:39 +00004359 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004360 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4361 loc.get());
4362 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4363 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004364 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004365 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004366 }
4367}
4368
4369// num_get helpers
4370
4371int
4372__num_get_base::__get_base(ios_base& iob)
4373{
4374 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4375 if (__basefield == ios_base::oct)
4376 return 8;
4377 else if (__basefield == ios_base::hex)
4378 return 16;
4379 else if (__basefield == 0)
4380 return 0;
4381 return 10;
4382}
4383
4384const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4385
4386void
4387__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4388 ios_base::iostate& __err)
4389{
4390 if (__grouping.size() != 0)
4391 {
4392 reverse(__g, __g_end);
4393 const char* __ig = __grouping.data();
4394 const char* __eg = __ig + __grouping.size();
4395 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4396 {
4397 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4398 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004399 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004400 {
4401 __err = ios_base::failbit;
4402 return;
4403 }
4404 }
4405 if (__eg - __ig > 1)
4406 ++__ig;
4407 }
4408 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4409 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004410 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004411 __err = ios_base::failbit;
4412 }
4413 }
4414}
4415
4416void
4417__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4418 ios_base::fmtflags __flags)
4419{
4420 if (__flags & ios_base::showpos)
4421 *__fmtp++ = '+';
4422 if (__flags & ios_base::showbase)
4423 *__fmtp++ = '#';
4424 while(*__len)
4425 *__fmtp++ = *__len++;
4426 if ((__flags & ios_base::basefield) == ios_base::oct)
4427 *__fmtp = 'o';
4428 else if ((__flags & ios_base::basefield) == ios_base::hex)
4429 {
4430 if (__flags & ios_base::uppercase)
4431 *__fmtp = 'X';
4432 else
4433 *__fmtp = 'x';
4434 }
4435 else if (__signd)
4436 *__fmtp = 'd';
4437 else
4438 *__fmtp = 'u';
4439}
4440
4441bool
4442__num_put_base::__format_float(char* __fmtp, const char* __len,
4443 ios_base::fmtflags __flags)
4444{
4445 bool specify_precision = true;
4446 if (__flags & ios_base::showpos)
4447 *__fmtp++ = '+';
4448 if (__flags & ios_base::showpoint)
4449 *__fmtp++ = '#';
4450 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004451 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004452 if (floatfield == (ios_base::fixed | ios_base::scientific))
4453 specify_precision = false;
4454 else
4455 {
4456 *__fmtp++ = '.';
4457 *__fmtp++ = '*';
4458 }
4459 while(*__len)
4460 *__fmtp++ = *__len++;
4461 if (floatfield == ios_base::fixed)
4462 {
4463 if (uppercase)
4464 *__fmtp = 'F';
4465 else
4466 *__fmtp = 'f';
4467 }
4468 else if (floatfield == ios_base::scientific)
4469 {
4470 if (uppercase)
4471 *__fmtp = 'E';
4472 else
4473 *__fmtp = 'e';
4474 }
4475 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4476 {
4477 if (uppercase)
4478 *__fmtp = 'A';
4479 else
4480 *__fmtp = 'a';
4481 }
4482 else
4483 {
4484 if (uppercase)
4485 *__fmtp = 'G';
4486 else
4487 *__fmtp = 'g';
4488 }
4489 return specify_precision;
4490}
4491
4492char*
4493__num_put_base::__identify_padding(char* __nb, char* __ne,
4494 const ios_base& __iob)
4495{
4496 switch (__iob.flags() & ios_base::adjustfield)
4497 {
4498 case ios_base::internal:
4499 if (__nb[0] == '-' || __nb[0] == '+')
4500 return __nb+1;
4501 if (__ne - __nb >= 2 && __nb[0] == '0'
4502 && (__nb[1] == 'x' || __nb[1] == 'X'))
4503 return __nb+2;
4504 break;
4505 case ios_base::left:
4506 return __ne;
4507 case ios_base::right:
4508 default:
4509 break;
4510 }
4511 return __nb;
4512}
4513
4514// time_get
4515
4516static
4517string*
4518init_weeks()
4519{
4520 static string weeks[14];
4521 weeks[0] = "Sunday";
4522 weeks[1] = "Monday";
4523 weeks[2] = "Tuesday";
4524 weeks[3] = "Wednesday";
4525 weeks[4] = "Thursday";
4526 weeks[5] = "Friday";
4527 weeks[6] = "Saturday";
4528 weeks[7] = "Sun";
4529 weeks[8] = "Mon";
4530 weeks[9] = "Tue";
4531 weeks[10] = "Wed";
4532 weeks[11] = "Thu";
4533 weeks[12] = "Fri";
4534 weeks[13] = "Sat";
4535 return weeks;
4536}
4537
4538static
4539wstring*
4540init_wweeks()
4541{
4542 static wstring weeks[14];
4543 weeks[0] = L"Sunday";
4544 weeks[1] = L"Monday";
4545 weeks[2] = L"Tuesday";
4546 weeks[3] = L"Wednesday";
4547 weeks[4] = L"Thursday";
4548 weeks[5] = L"Friday";
4549 weeks[6] = L"Saturday";
4550 weeks[7] = L"Sun";
4551 weeks[8] = L"Mon";
4552 weeks[9] = L"Tue";
4553 weeks[10] = L"Wed";
4554 weeks[11] = L"Thu";
4555 weeks[12] = L"Fri";
4556 weeks[13] = L"Sat";
4557 return weeks;
4558}
4559
4560template <>
4561const string*
4562__time_get_c_storage<char>::__weeks() const
4563{
4564 static const string* weeks = init_weeks();
4565 return weeks;
4566}
4567
4568template <>
4569const wstring*
4570__time_get_c_storage<wchar_t>::__weeks() const
4571{
4572 static const wstring* weeks = init_wweeks();
4573 return weeks;
4574}
4575
4576static
4577string*
4578init_months()
4579{
4580 static string months[24];
4581 months[0] = "January";
4582 months[1] = "February";
4583 months[2] = "March";
4584 months[3] = "April";
4585 months[4] = "May";
4586 months[5] = "June";
4587 months[6] = "July";
4588 months[7] = "August";
4589 months[8] = "September";
4590 months[9] = "October";
4591 months[10] = "November";
4592 months[11] = "December";
4593 months[12] = "Jan";
4594 months[13] = "Feb";
4595 months[14] = "Mar";
4596 months[15] = "Apr";
4597 months[16] = "May";
4598 months[17] = "Jun";
4599 months[18] = "Jul";
4600 months[19] = "Aug";
4601 months[20] = "Sep";
4602 months[21] = "Oct";
4603 months[22] = "Nov";
4604 months[23] = "Dec";
4605 return months;
4606}
4607
4608static
4609wstring*
4610init_wmonths()
4611{
4612 static wstring months[24];
4613 months[0] = L"January";
4614 months[1] = L"February";
4615 months[2] = L"March";
4616 months[3] = L"April";
4617 months[4] = L"May";
4618 months[5] = L"June";
4619 months[6] = L"July";
4620 months[7] = L"August";
4621 months[8] = L"September";
4622 months[9] = L"October";
4623 months[10] = L"November";
4624 months[11] = L"December";
4625 months[12] = L"Jan";
4626 months[13] = L"Feb";
4627 months[14] = L"Mar";
4628 months[15] = L"Apr";
4629 months[16] = L"May";
4630 months[17] = L"Jun";
4631 months[18] = L"Jul";
4632 months[19] = L"Aug";
4633 months[20] = L"Sep";
4634 months[21] = L"Oct";
4635 months[22] = L"Nov";
4636 months[23] = L"Dec";
4637 return months;
4638}
4639
4640template <>
4641const string*
4642__time_get_c_storage<char>::__months() const
4643{
4644 static const string* months = init_months();
4645 return months;
4646}
4647
4648template <>
4649const wstring*
4650__time_get_c_storage<wchar_t>::__months() const
4651{
4652 static const wstring* months = init_wmonths();
4653 return months;
4654}
4655
4656static
4657string*
4658init_am_pm()
4659{
4660 static string am_pm[24];
4661 am_pm[0] = "AM";
4662 am_pm[1] = "PM";
4663 return am_pm;
4664}
4665
4666static
4667wstring*
4668init_wam_pm()
4669{
4670 static wstring am_pm[24];
4671 am_pm[0] = L"AM";
4672 am_pm[1] = L"PM";
4673 return am_pm;
4674}
4675
4676template <>
4677const string*
4678__time_get_c_storage<char>::__am_pm() const
4679{
4680 static const string* am_pm = init_am_pm();
4681 return am_pm;
4682}
4683
4684template <>
4685const wstring*
4686__time_get_c_storage<wchar_t>::__am_pm() const
4687{
4688 static const wstring* am_pm = init_wam_pm();
4689 return am_pm;
4690}
4691
4692template <>
4693const string&
4694__time_get_c_storage<char>::__x() const
4695{
4696 static string s("%m/%d/%y");
4697 return s;
4698}
4699
4700template <>
4701const wstring&
4702__time_get_c_storage<wchar_t>::__x() const
4703{
4704 static wstring s(L"%m/%d/%y");
4705 return s;
4706}
4707
4708template <>
4709const string&
4710__time_get_c_storage<char>::__X() const
4711{
4712 static string s("%H:%M:%S");
4713 return s;
4714}
4715
4716template <>
4717const wstring&
4718__time_get_c_storage<wchar_t>::__X() const
4719{
4720 static wstring s(L"%H:%M:%S");
4721 return s;
4722}
4723
4724template <>
4725const string&
4726__time_get_c_storage<char>::__c() const
4727{
4728 static string s("%a %b %d %H:%M:%S %Y");
4729 return s;
4730}
4731
4732template <>
4733const wstring&
4734__time_get_c_storage<wchar_t>::__c() const
4735{
4736 static wstring s(L"%a %b %d %H:%M:%S %Y");
4737 return s;
4738}
4739
4740template <>
4741const string&
4742__time_get_c_storage<char>::__r() const
4743{
4744 static string s("%I:%M:%S %p");
4745 return s;
4746}
4747
4748template <>
4749const wstring&
4750__time_get_c_storage<wchar_t>::__r() const
4751{
4752 static wstring s(L"%I:%M:%S %p");
4753 return s;
4754}
4755
4756// time_get_byname
4757
4758__time_get::__time_get(const char* nm)
4759 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4760{
4761 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004762 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004763 " failed to construct for " + string(nm));
4764}
4765
4766__time_get::__time_get(const string& nm)
4767 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4768{
4769 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004770 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004771 " failed to construct for " + nm);
4772}
4773
4774__time_get::~__time_get()
4775{
4776 freelocale(__loc_);
4777}
Marshall Clowd920eea2013-10-21 15:07:28 +00004778#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004779#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004780#endif
4781#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004782#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004783#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004784
Howard Hinnantc51e1022010-05-11 19:42:16 +00004785template <>
4786string
4787__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4788{
Howard Hinnant990207c2012-02-19 14:55:32 +00004789 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004790 t.tm_sec = 59;
4791 t.tm_min = 55;
4792 t.tm_hour = 23;
4793 t.tm_mday = 31;
4794 t.tm_mon = 11;
4795 t.tm_year = 161;
4796 t.tm_wday = 6;
4797 t.tm_yday = 364;
4798 t.tm_isdst = -1;
4799 char buf[100];
4800 char f[3] = {0};
4801 f[0] = '%';
4802 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004803 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004804 char* bb = buf;
4805 char* be = buf + n;
4806 string result;
4807 while (bb != be)
4808 {
4809 if (ct.is(ctype_base::space, *bb))
4810 {
4811 result.push_back(' ');
4812 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4813 ;
4814 continue;
4815 }
4816 char* w = bb;
4817 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004818 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004819 ct, err, false)
4820 - this->__weeks_;
4821 if (i < 14)
4822 {
4823 result.push_back('%');
4824 if (i < 7)
4825 result.push_back('A');
4826 else
4827 result.push_back('a');
4828 bb = w;
4829 continue;
4830 }
4831 w = bb;
4832 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4833 ct, err, false)
4834 - this->__months_;
4835 if (i < 24)
4836 {
4837 result.push_back('%');
4838 if (i < 12)
4839 result.push_back('B');
4840 else
4841 result.push_back('b');
4842 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4843 result.back() = 'm';
4844 bb = w;
4845 continue;
4846 }
4847 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4848 {
4849 w = bb;
4850 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4851 ct, err, false) - this->__am_pm_;
4852 if (i < 2)
4853 {
4854 result.push_back('%');
4855 result.push_back('p');
4856 bb = w;
4857 continue;
4858 }
4859 }
4860 w = bb;
4861 if (ct.is(ctype_base::digit, *bb))
4862 {
4863 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4864 {
4865 case 6:
4866 result.push_back('%');
4867 result.push_back('w');
4868 break;
4869 case 7:
4870 result.push_back('%');
4871 result.push_back('u');
4872 break;
4873 case 11:
4874 result.push_back('%');
4875 result.push_back('I');
4876 break;
4877 case 12:
4878 result.push_back('%');
4879 result.push_back('m');
4880 break;
4881 case 23:
4882 result.push_back('%');
4883 result.push_back('H');
4884 break;
4885 case 31:
4886 result.push_back('%');
4887 result.push_back('d');
4888 break;
4889 case 55:
4890 result.push_back('%');
4891 result.push_back('M');
4892 break;
4893 case 59:
4894 result.push_back('%');
4895 result.push_back('S');
4896 break;
4897 case 61:
4898 result.push_back('%');
4899 result.push_back('y');
4900 break;
4901 case 364:
4902 result.push_back('%');
4903 result.push_back('j');
4904 break;
4905 case 2061:
4906 result.push_back('%');
4907 result.push_back('Y');
4908 break;
4909 default:
4910 for (; w != bb; ++w)
4911 result.push_back(*w);
4912 break;
4913 }
4914 continue;
4915 }
4916 if (*bb == '%')
4917 {
4918 result.push_back('%');
4919 result.push_back('%');
4920 ++bb;
4921 continue;
4922 }
4923 result.push_back(*bb);
4924 ++bb;
4925 }
4926 return result;
4927}
4928
Marshall Clowd920eea2013-10-21 15:07:28 +00004929#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004930#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004931#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004932
Howard Hinnantc51e1022010-05-11 19:42:16 +00004933template <>
4934wstring
4935__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4936{
Howard Hinnant990207c2012-02-19 14:55:32 +00004937 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004938 t.tm_sec = 59;
4939 t.tm_min = 55;
4940 t.tm_hour = 23;
4941 t.tm_mday = 31;
4942 t.tm_mon = 11;
4943 t.tm_year = 161;
4944 t.tm_wday = 6;
4945 t.tm_yday = 364;
4946 t.tm_isdst = -1;
4947 char buf[100];
4948 char f[3] = {0};
4949 f[0] = '%';
4950 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004951 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004952 wchar_t wbuf[100];
4953 wchar_t* wbb = wbuf;
4954 mbstate_t mb = {0};
4955 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004956 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004957 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004958 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004959 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004960 wstring result;
4961 while (wbb != wbe)
4962 {
4963 if (ct.is(ctype_base::space, *wbb))
4964 {
4965 result.push_back(L' ');
4966 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4967 ;
4968 continue;
4969 }
4970 wchar_t* w = wbb;
4971 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004972 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004973 ct, err, false)
4974 - this->__weeks_;
4975 if (i < 14)
4976 {
4977 result.push_back(L'%');
4978 if (i < 7)
4979 result.push_back(L'A');
4980 else
4981 result.push_back(L'a');
4982 wbb = w;
4983 continue;
4984 }
4985 w = wbb;
4986 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4987 ct, err, false)
4988 - this->__months_;
4989 if (i < 24)
4990 {
4991 result.push_back(L'%');
4992 if (i < 12)
4993 result.push_back(L'B');
4994 else
4995 result.push_back(L'b');
4996 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4997 result.back() = L'm';
4998 wbb = w;
4999 continue;
5000 }
5001 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5002 {
5003 w = wbb;
5004 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5005 ct, err, false) - this->__am_pm_;
5006 if (i < 2)
5007 {
5008 result.push_back(L'%');
5009 result.push_back(L'p');
5010 wbb = w;
5011 continue;
5012 }
5013 }
5014 w = wbb;
5015 if (ct.is(ctype_base::digit, *wbb))
5016 {
5017 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5018 {
5019 case 6:
5020 result.push_back(L'%');
5021 result.push_back(L'w');
5022 break;
5023 case 7:
5024 result.push_back(L'%');
5025 result.push_back(L'u');
5026 break;
5027 case 11:
5028 result.push_back(L'%');
5029 result.push_back(L'I');
5030 break;
5031 case 12:
5032 result.push_back(L'%');
5033 result.push_back(L'm');
5034 break;
5035 case 23:
5036 result.push_back(L'%');
5037 result.push_back(L'H');
5038 break;
5039 case 31:
5040 result.push_back(L'%');
5041 result.push_back(L'd');
5042 break;
5043 case 55:
5044 result.push_back(L'%');
5045 result.push_back(L'M');
5046 break;
5047 case 59:
5048 result.push_back(L'%');
5049 result.push_back(L'S');
5050 break;
5051 case 61:
5052 result.push_back(L'%');
5053 result.push_back(L'y');
5054 break;
5055 case 364:
5056 result.push_back(L'%');
5057 result.push_back(L'j');
5058 break;
5059 case 2061:
5060 result.push_back(L'%');
5061 result.push_back(L'Y');
5062 break;
5063 default:
5064 for (; w != wbb; ++w)
5065 result.push_back(*w);
5066 break;
5067 }
5068 continue;
5069 }
5070 if (ct.narrow(*wbb, 0) == '%')
5071 {
5072 result.push_back(L'%');
5073 result.push_back(L'%');
5074 ++wbb;
5075 continue;
5076 }
5077 result.push_back(*wbb);
5078 ++wbb;
5079 }
5080 return result;
5081}
5082
5083template <>
5084void
5085__time_get_storage<char>::init(const ctype<char>& ct)
5086{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005087 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005088 char buf[100];
5089 // __weeks_
5090 for (int i = 0; i < 7; ++i)
5091 {
5092 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005093 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005094 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005095 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005096 __weeks_[i+7] = buf;
5097 }
5098 // __months_
5099 for (int i = 0; i < 12; ++i)
5100 {
5101 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005102 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005103 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005104 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005105 __months_[i+12] = buf;
5106 }
5107 // __am_pm_
5108 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005109 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005110 __am_pm_[0] = buf;
5111 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005112 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005113 __am_pm_[1] = buf;
5114 __c_ = __analyze('c', ct);
5115 __r_ = __analyze('r', ct);
5116 __x_ = __analyze('x', ct);
5117 __X_ = __analyze('X', ct);
5118}
5119
5120template <>
5121void
5122__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5123{
5124 tm t = {0};
5125 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005126 wchar_t wbuf[100];
5127 wchar_t* wbe;
5128 mbstate_t mb = {0};
5129 // __weeks_
5130 for (int i = 0; i < 7; ++i)
5131 {
5132 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005133 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005134 mb = mbstate_t();
5135 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005136 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005137 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005138 __throw_runtime_error("locale not supported");
5139 wbe = wbuf + j;
5140 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005141 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005142 mb = mbstate_t();
5143 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005144 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005145 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005146 __throw_runtime_error("locale not supported");
5147 wbe = wbuf + j;
5148 __weeks_[i+7].assign(wbuf, wbe);
5149 }
5150 // __months_
5151 for (int i = 0; i < 12; ++i)
5152 {
5153 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005154 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005155 mb = mbstate_t();
5156 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005157 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005158 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005159 __throw_runtime_error("locale not supported");
5160 wbe = wbuf + j;
5161 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005162 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005163 mb = mbstate_t();
5164 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005165 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005166 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005167 __throw_runtime_error("locale not supported");
5168 wbe = wbuf + j;
5169 __months_[i+12].assign(wbuf, wbe);
5170 }
5171 // __am_pm_
5172 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005173 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005174 mb = mbstate_t();
5175 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005176 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005177 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005178 __throw_runtime_error("locale not supported");
5179 wbe = wbuf + j;
5180 __am_pm_[0].assign(wbuf, wbe);
5181 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005182 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005183 mb = mbstate_t();
5184 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005185 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005186 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005187 __throw_runtime_error("locale not supported");
5188 wbe = wbuf + j;
5189 __am_pm_[1].assign(wbuf, wbe);
5190 __c_ = __analyze('c', ct);
5191 __r_ = __analyze('r', ct);
5192 __x_ = __analyze('x', ct);
5193 __X_ = __analyze('X', ct);
5194}
5195
5196template <class CharT>
5197struct _LIBCPP_HIDDEN __time_get_temp
5198 : public ctype_byname<CharT>
5199{
5200 explicit __time_get_temp(const char* nm)
5201 : ctype_byname<CharT>(nm, 1) {}
5202 explicit __time_get_temp(const string& nm)
5203 : ctype_byname<CharT>(nm, 1) {}
5204};
5205
5206template <>
5207__time_get_storage<char>::__time_get_storage(const char* __nm)
5208 : __time_get(__nm)
5209{
5210 const __time_get_temp<char> ct(__nm);
5211 init(ct);
5212}
5213
5214template <>
5215__time_get_storage<char>::__time_get_storage(const string& __nm)
5216 : __time_get(__nm)
5217{
5218 const __time_get_temp<char> ct(__nm);
5219 init(ct);
5220}
5221
5222template <>
5223__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5224 : __time_get(__nm)
5225{
5226 const __time_get_temp<wchar_t> ct(__nm);
5227 init(ct);
5228}
5229
5230template <>
5231__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5232 : __time_get(__nm)
5233{
5234 const __time_get_temp<wchar_t> ct(__nm);
5235 init(ct);
5236}
5237
5238template <>
5239time_base::dateorder
5240__time_get_storage<char>::__do_date_order() const
5241{
5242 unsigned i;
5243 for (i = 0; i < __x_.size(); ++i)
5244 if (__x_[i] == '%')
5245 break;
5246 ++i;
5247 switch (__x_[i])
5248 {
5249 case 'y':
5250 case 'Y':
5251 for (++i; i < __x_.size(); ++i)
5252 if (__x_[i] == '%')
5253 break;
5254 if (i == __x_.size())
5255 break;
5256 ++i;
5257 switch (__x_[i])
5258 {
5259 case 'm':
5260 for (++i; i < __x_.size(); ++i)
5261 if (__x_[i] == '%')
5262 break;
5263 if (i == __x_.size())
5264 break;
5265 ++i;
5266 if (__x_[i] == 'd')
5267 return time_base::ymd;
5268 break;
5269 case 'd':
5270 for (++i; i < __x_.size(); ++i)
5271 if (__x_[i] == '%')
5272 break;
5273 if (i == __x_.size())
5274 break;
5275 ++i;
5276 if (__x_[i] == 'm')
5277 return time_base::ydm;
5278 break;
5279 }
5280 break;
5281 case 'm':
5282 for (++i; i < __x_.size(); ++i)
5283 if (__x_[i] == '%')
5284 break;
5285 if (i == __x_.size())
5286 break;
5287 ++i;
5288 if (__x_[i] == 'd')
5289 {
5290 for (++i; i < __x_.size(); ++i)
5291 if (__x_[i] == '%')
5292 break;
5293 if (i == __x_.size())
5294 break;
5295 ++i;
5296 if (__x_[i] == 'y' || __x_[i] == 'Y')
5297 return time_base::mdy;
5298 break;
5299 }
5300 break;
5301 case 'd':
5302 for (++i; i < __x_.size(); ++i)
5303 if (__x_[i] == '%')
5304 break;
5305 if (i == __x_.size())
5306 break;
5307 ++i;
5308 if (__x_[i] == 'm')
5309 {
5310 for (++i; i < __x_.size(); ++i)
5311 if (__x_[i] == '%')
5312 break;
5313 if (i == __x_.size())
5314 break;
5315 ++i;
5316 if (__x_[i] == 'y' || __x_[i] == 'Y')
5317 return time_base::dmy;
5318 break;
5319 }
5320 break;
5321 }
5322 return time_base::no_order;
5323}
5324
5325template <>
5326time_base::dateorder
5327__time_get_storage<wchar_t>::__do_date_order() const
5328{
5329 unsigned i;
5330 for (i = 0; i < __x_.size(); ++i)
5331 if (__x_[i] == L'%')
5332 break;
5333 ++i;
5334 switch (__x_[i])
5335 {
5336 case L'y':
5337 case L'Y':
5338 for (++i; i < __x_.size(); ++i)
5339 if (__x_[i] == L'%')
5340 break;
5341 if (i == __x_.size())
5342 break;
5343 ++i;
5344 switch (__x_[i])
5345 {
5346 case L'm':
5347 for (++i; i < __x_.size(); ++i)
5348 if (__x_[i] == L'%')
5349 break;
5350 if (i == __x_.size())
5351 break;
5352 ++i;
5353 if (__x_[i] == L'd')
5354 return time_base::ymd;
5355 break;
5356 case L'd':
5357 for (++i; i < __x_.size(); ++i)
5358 if (__x_[i] == L'%')
5359 break;
5360 if (i == __x_.size())
5361 break;
5362 ++i;
5363 if (__x_[i] == L'm')
5364 return time_base::ydm;
5365 break;
5366 }
5367 break;
5368 case L'm':
5369 for (++i; i < __x_.size(); ++i)
5370 if (__x_[i] == L'%')
5371 break;
5372 if (i == __x_.size())
5373 break;
5374 ++i;
5375 if (__x_[i] == L'd')
5376 {
5377 for (++i; i < __x_.size(); ++i)
5378 if (__x_[i] == L'%')
5379 break;
5380 if (i == __x_.size())
5381 break;
5382 ++i;
5383 if (__x_[i] == L'y' || __x_[i] == L'Y')
5384 return time_base::mdy;
5385 break;
5386 }
5387 break;
5388 case L'd':
5389 for (++i; i < __x_.size(); ++i)
5390 if (__x_[i] == L'%')
5391 break;
5392 if (i == __x_.size())
5393 break;
5394 ++i;
5395 if (__x_[i] == L'm')
5396 {
5397 for (++i; i < __x_.size(); ++i)
5398 if (__x_[i] == L'%')
5399 break;
5400 if (i == __x_.size())
5401 break;
5402 ++i;
5403 if (__x_[i] == L'y' || __x_[i] == L'Y')
5404 return time_base::dmy;
5405 break;
5406 }
5407 break;
5408 }
5409 return time_base::no_order;
5410}
5411
5412// time_put
5413
5414__time_put::__time_put(const char* nm)
5415 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5416{
5417 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005418 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005419 " failed to construct for " + string(nm));
5420}
5421
5422__time_put::__time_put(const string& nm)
5423 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5424{
5425 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005426 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005427 " failed to construct for " + nm);
5428}
5429
5430__time_put::~__time_put()
5431{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005432 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005433 freelocale(__loc_);
5434}
5435
5436void
5437__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5438 char __fmt, char __mod) const
5439{
5440 char fmt[] = {'%', __fmt, __mod, 0};
5441 if (__mod != 0)
5442 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005443 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005444 __ne = __nb + n;
5445}
5446
5447void
5448__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5449 char __fmt, char __mod) const
5450{
5451 char __nar[100];
5452 char* __ne = __nar + 100;
5453 __do_put(__nar, __ne, __tm, __fmt, __mod);
5454 mbstate_t mb = {0};
5455 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005456 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005457 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005458 __throw_runtime_error("locale not supported");
5459 __we = __wb + j;
5460}
5461
5462// moneypunct_byname
5463
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005464template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005465static
5466void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005467__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5468 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5469 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005470{
5471 const char sign = static_cast<char>(money_base::sign);
5472 const char space = static_cast<char>(money_base::space);
5473 const char none = static_cast<char>(money_base::none);
5474 const char symbol = static_cast<char>(money_base::symbol);
5475 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005476 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5477
5478 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5479 // function'. "Space between sign and symbol or value" means that
5480 // if the sign is adjacent to the symbol, there's a space between
5481 // them, and otherwise there's a space between the sign and value.
5482 //
5483 // C11's localeconv specifies that the fourth character of an
5484 // international curr_symbol is used to separate the sign and
5485 // value when sep_by_space says to do so. C++ can't represent
5486 // that, so we just use a space. When sep_by_space says to
5487 // separate the symbol and value-or-sign with a space, we rearrange the
5488 // curr_symbol to put its spacing character on the correct side of
5489 // the symbol.
5490 //
5491 // We also need to avoid adding an extra space between the sign
5492 // and value when the currency symbol is suppressed (by not
5493 // setting showbase). We match glibc's strfmon by interpreting
5494 // sep_by_space==1 as "omit the space when the currency symbol is
5495 // absent".
5496 //
5497 // Users who want to get this right should use ICU instead.
5498
Howard Hinnantc51e1022010-05-11 19:42:16 +00005499 switch (cs_precedes)
5500 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005501 case 0: // value before curr_symbol
5502 if (symbol_contains_sep) {
5503 // Move the separator to before the symbol, to place it
5504 // between the value and symbol.
5505 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5506 __curr_symbol_.end());
5507 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005508 switch (sign_posn)
5509 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005510 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005511 pat.field[0] = sign;
5512 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005513 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005514 pat.field[3] = symbol;
5515 switch (sep_by_space)
5516 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005517 case 0: // No space separates the currency symbol and value.
5518 // This case may have changed between C99 and C11;
5519 // assume the currency symbol matches the intention.
5520 case 2: // Space between sign and currency or value.
5521 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005522 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005523 case 1: // Space between currency-and-sign or currency and value.
5524 if (!symbol_contains_sep) {
5525 // We insert the space into the symbol instead of
5526 // setting pat.field[2]=space so that when
5527 // showbase is not set, the space goes away too.
5528 __curr_symbol_.insert(0, 1, space_char);
5529 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005530 return;
5531 default:
5532 break;
5533 }
5534 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005535 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005536 pat.field[0] = sign;
5537 pat.field[3] = symbol;
5538 switch (sep_by_space)
5539 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005540 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005541 pat.field[1] = value;
5542 pat.field[2] = none;
5543 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005544 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005545 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005546 pat.field[2] = none;
5547 if (!symbol_contains_sep) {
5548 // We insert the space into the symbol instead of
5549 // setting pat.field[2]=space so that when
5550 // showbase is not set, the space goes away too.
5551 __curr_symbol_.insert(0, 1, space_char);
5552 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005553 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005554 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005555 pat.field[1] = space;
5556 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005557 if (symbol_contains_sep) {
5558 // Remove the separator from the symbol, since it
5559 // has already appeared after the sign.
5560 __curr_symbol_.erase(__curr_symbol_.begin());
5561 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005562 return;
5563 default:
5564 break;
5565 }
5566 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005567 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005568 pat.field[0] = value;
5569 pat.field[3] = sign;
5570 switch (sep_by_space)
5571 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005572 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005573 pat.field[1] = none;
5574 pat.field[2] = symbol;
5575 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005576 case 1: // Space between currency-and-sign or currency and value.
5577 if (!symbol_contains_sep) {
5578 // We insert the space into the symbol instead of
5579 // setting pat.field[1]=space so that when
5580 // showbase is not set, the space goes away too.
5581 __curr_symbol_.insert(0, 1, space_char);
5582 }
5583 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005584 pat.field[2] = symbol;
5585 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005586 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005587 pat.field[1] = symbol;
5588 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005589 if (symbol_contains_sep) {
5590 // Remove the separator from the symbol, since it
5591 // should not be removed if showbase is absent.
5592 __curr_symbol_.erase(__curr_symbol_.begin());
5593 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005594 return;
5595 default:
5596 break;
5597 }
5598 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005599 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005600 pat.field[0] = value;
5601 pat.field[3] = symbol;
5602 switch (sep_by_space)
5603 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005604 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005605 pat.field[1] = none;
5606 pat.field[2] = sign;
5607 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005608 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005609 pat.field[1] = space;
5610 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005611 if (symbol_contains_sep) {
5612 // Remove the separator from the symbol, since it
5613 // has already appeared before the sign.
5614 __curr_symbol_.erase(__curr_symbol_.begin());
5615 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005616 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005617 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005618 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005619 pat.field[2] = none;
5620 if (!symbol_contains_sep) {
5621 // We insert the space into the symbol instead of
5622 // setting pat.field[2]=space so that when
5623 // showbase is not set, the space goes away too.
5624 __curr_symbol_.insert(0, 1, space_char);
5625 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005626 return;
5627 default:
5628 break;
5629 }
5630 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005631 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005632 pat.field[0] = value;
5633 pat.field[3] = sign;
5634 switch (sep_by_space)
5635 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005636 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005637 pat.field[1] = none;
5638 pat.field[2] = symbol;
5639 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005640 case 1: // Space between currency-and-sign or currency and value.
5641 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005642 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005643 if (!symbol_contains_sep) {
5644 // We insert the space into the symbol instead of
5645 // setting pat.field[1]=space so that when
5646 // showbase is not set, the space goes away too.
5647 __curr_symbol_.insert(0, 1, space_char);
5648 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005649 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005650 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005651 pat.field[1] = symbol;
5652 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005653 if (symbol_contains_sep) {
5654 // Remove the separator from the symbol, since it
5655 // should not disappear when showbase is absent.
5656 __curr_symbol_.erase(__curr_symbol_.begin());
5657 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005658 return;
5659 default:
5660 break;
5661 }
5662 break;
5663 default:
5664 break;
5665 }
5666 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005667 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005668 switch (sign_posn)
5669 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005670 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005671 pat.field[0] = sign;
5672 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005673 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005674 pat.field[3] = value;
5675 switch (sep_by_space)
5676 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005677 case 0: // No space separates the currency symbol and value.
5678 // This case may have changed between C99 and C11;
5679 // assume the currency symbol matches the intention.
5680 case 2: // Space between sign and currency or value.
5681 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005682 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005683 case 1: // Space between currency-and-sign or currency and value.
5684 if (!symbol_contains_sep) {
5685 // We insert the space into the symbol instead of
5686 // setting pat.field[2]=space so that when
5687 // showbase is not set, the space goes away too.
5688 __curr_symbol_.insert(0, 1, space_char);
5689 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005690 return;
5691 default:
5692 break;
5693 }
5694 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005695 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005696 pat.field[0] = sign;
5697 pat.field[3] = value;
5698 switch (sep_by_space)
5699 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005700 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005701 pat.field[1] = symbol;
5702 pat.field[2] = none;
5703 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005704 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005705 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005706 pat.field[2] = none;
5707 if (!symbol_contains_sep) {
5708 // We insert the space into the symbol instead of
5709 // setting pat.field[2]=space so that when
5710 // showbase is not set, the space goes away too.
5711 __curr_symbol_.push_back(space_char);
5712 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005713 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005714 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005715 pat.field[1] = space;
5716 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005717 if (symbol_contains_sep) {
5718 // Remove the separator from the symbol, since it
5719 // has already appeared after the sign.
5720 __curr_symbol_.pop_back();
5721 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005722 return;
5723 default:
5724 break;
5725 }
5726 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005727 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005728 pat.field[0] = symbol;
5729 pat.field[3] = sign;
5730 switch (sep_by_space)
5731 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005732 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005733 pat.field[1] = none;
5734 pat.field[2] = value;
5735 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005736 case 1: // Space between currency-and-sign or currency and value.
5737 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005738 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005739 if (!symbol_contains_sep) {
5740 // We insert the space into the symbol instead of
5741 // setting pat.field[1]=space so that when
5742 // showbase is not set, the space goes away too.
5743 __curr_symbol_.push_back(space_char);
5744 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005745 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005746 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005747 pat.field[1] = value;
5748 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005749 if (symbol_contains_sep) {
5750 // Remove the separator from the symbol, since it
5751 // will appear before the sign.
5752 __curr_symbol_.pop_back();
5753 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005754 return;
5755 default:
5756 break;
5757 }
5758 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005759 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005760 pat.field[0] = sign;
5761 pat.field[3] = value;
5762 switch (sep_by_space)
5763 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005764 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005765 pat.field[1] = symbol;
5766 pat.field[2] = none;
5767 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005768 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005769 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005770 pat.field[2] = none;
5771 if (!symbol_contains_sep) {
5772 // We insert the space into the symbol instead of
5773 // setting pat.field[2]=space so that when
5774 // showbase is not set, the space goes away too.
5775 __curr_symbol_.push_back(space_char);
5776 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005777 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005778 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005779 pat.field[1] = space;
5780 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005781 if (symbol_contains_sep) {
5782 // Remove the separator from the symbol, since it
5783 // has already appeared after the sign.
5784 __curr_symbol_.pop_back();
5785 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005786 return;
5787 default:
5788 break;
5789 }
5790 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005791 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005792 pat.field[0] = symbol;
5793 pat.field[3] = value;
5794 switch (sep_by_space)
5795 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005796 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005797 pat.field[1] = sign;
5798 pat.field[2] = none;
5799 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005800 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005801 pat.field[1] = sign;
5802 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005803 if (symbol_contains_sep) {
5804 // Remove the separator from the symbol, since it
5805 // should not disappear when showbase is absent.
5806 __curr_symbol_.pop_back();
5807 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005808 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005809 case 2: // Space between sign and currency or value.
5810 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005811 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005812 if (!symbol_contains_sep) {
5813 // We insert the space into the symbol instead of
5814 // setting pat.field[1]=space so that when
5815 // showbase is not set, the space goes away too.
5816 __curr_symbol_.push_back(space_char);
5817 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005818 return;
5819 default:
5820 break;
5821 }
5822 break;
5823 default:
5824 break;
5825 }
5826 break;
5827 default:
5828 break;
5829 }
5830 pat.field[0] = symbol;
5831 pat.field[1] = sign;
5832 pat.field[2] = none;
5833 pat.field[3] = value;
5834}
5835
5836template<>
5837void
5838moneypunct_byname<char, false>::init(const char* nm)
5839{
5840 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005841 __libcpp_unique_locale loc(nm);
5842 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005843 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005844 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005845
Ben Craig3756b922016-03-09 15:39:39 +00005846 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005847 if (!checked_string_to_char_convert(__decimal_point_,
5848 lc->mon_decimal_point,
5849 loc.get()))
5850 __decimal_point_ = base::do_decimal_point();
5851 if (!checked_string_to_char_convert(__thousands_sep_,
5852 lc->mon_thousands_sep,
5853 loc.get()))
5854 __thousands_sep_ = base::do_thousands_sep();
5855
Howard Hinnantc51e1022010-05-11 19:42:16 +00005856 __grouping_ = lc->mon_grouping;
5857 __curr_symbol_ = lc->currency_symbol;
5858 if (lc->frac_digits != CHAR_MAX)
5859 __frac_digits_ = lc->frac_digits;
5860 else
5861 __frac_digits_ = base::do_frac_digits();
5862 if (lc->p_sign_posn == 0)
5863 __positive_sign_ = "()";
5864 else
5865 __positive_sign_ = lc->positive_sign;
5866 if (lc->n_sign_posn == 0)
5867 __negative_sign_ = "()";
5868 else
5869 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005870 // Assume the positive and negative formats will want spaces in
5871 // the same places in curr_symbol since there's no way to
5872 // represent anything else.
5873 string_type __dummy_curr_symbol = __curr_symbol_;
5874 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5875 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5876 __init_pat(__neg_format_, __curr_symbol_, false,
5877 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005878}
5879
5880template<>
5881void
5882moneypunct_byname<char, true>::init(const char* nm)
5883{
5884 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005885 __libcpp_unique_locale loc(nm);
5886 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005887 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005888 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005889
Ben Craig3756b922016-03-09 15:39:39 +00005890 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005891 if (!checked_string_to_char_convert(__decimal_point_,
5892 lc->mon_decimal_point,
5893 loc.get()))
5894 __decimal_point_ = base::do_decimal_point();
5895 if (!checked_string_to_char_convert(__thousands_sep_,
5896 lc->mon_thousands_sep,
5897 loc.get()))
5898 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005899 __grouping_ = lc->mon_grouping;
5900 __curr_symbol_ = lc->int_curr_symbol;
5901 if (lc->int_frac_digits != CHAR_MAX)
5902 __frac_digits_ = lc->int_frac_digits;
5903 else
5904 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005905#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005906 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005907#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005908 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005909#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005910 __positive_sign_ = "()";
5911 else
5912 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005913#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005914 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005915#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005916 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005917#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005918 __negative_sign_ = "()";
5919 else
5920 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005921 // Assume the positive and negative formats will want spaces in
5922 // the same places in curr_symbol since there's no way to
5923 // represent anything else.
5924 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005925#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005926 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5927 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5928 __init_pat(__neg_format_, __curr_symbol_, true,
5929 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005930#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005931 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5932 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5933 lc->int_p_sign_posn, ' ');
5934 __init_pat(__neg_format_, __curr_symbol_, true,
5935 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5936 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005937#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005938}
5939
5940template<>
5941void
5942moneypunct_byname<wchar_t, false>::init(const char* nm)
5943{
5944 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005945 __libcpp_unique_locale loc(nm);
5946 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005947 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005948 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00005949 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005950 if (!checked_string_to_wchar_convert(__decimal_point_,
5951 lc->mon_decimal_point,
5952 loc.get()))
5953 __decimal_point_ = base::do_decimal_point();
5954 if (!checked_string_to_wchar_convert(__thousands_sep_,
5955 lc->mon_thousands_sep,
5956 loc.get()))
5957 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005958 __grouping_ = lc->mon_grouping;
5959 wchar_t wbuf[100];
5960 mbstate_t mb = {0};
5961 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005962 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005963 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005964 __throw_runtime_error("locale not supported");
5965 wchar_t* wbe = wbuf + j;
5966 __curr_symbol_.assign(wbuf, wbe);
5967 if (lc->frac_digits != CHAR_MAX)
5968 __frac_digits_ = lc->frac_digits;
5969 else
5970 __frac_digits_ = base::do_frac_digits();
5971 if (lc->p_sign_posn == 0)
5972 __positive_sign_ = L"()";
5973 else
5974 {
5975 mb = mbstate_t();
5976 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005977 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005978 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005979 __throw_runtime_error("locale not supported");
5980 wbe = wbuf + j;
5981 __positive_sign_.assign(wbuf, wbe);
5982 }
5983 if (lc->n_sign_posn == 0)
5984 __negative_sign_ = L"()";
5985 else
5986 {
5987 mb = mbstate_t();
5988 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005989 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005990 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005991 __throw_runtime_error("locale not supported");
5992 wbe = wbuf + j;
5993 __negative_sign_.assign(wbuf, wbe);
5994 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005995 // Assume the positive and negative formats will want spaces in
5996 // the same places in curr_symbol since there's no way to
5997 // represent anything else.
5998 string_type __dummy_curr_symbol = __curr_symbol_;
5999 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6000 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6001 __init_pat(__neg_format_, __curr_symbol_, false,
6002 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006003}
6004
6005template<>
6006void
6007moneypunct_byname<wchar_t, true>::init(const char* nm)
6008{
6009 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006010 __libcpp_unique_locale loc(nm);
6011 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006012 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006013 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006014
Ben Craig3756b922016-03-09 15:39:39 +00006015 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006016 if (!checked_string_to_wchar_convert(__decimal_point_,
6017 lc->mon_decimal_point,
6018 loc.get()))
6019 __decimal_point_ = base::do_decimal_point();
6020 if (!checked_string_to_wchar_convert(__thousands_sep_,
6021 lc->mon_thousands_sep,
6022 loc.get()))
6023 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006024 __grouping_ = lc->mon_grouping;
6025 wchar_t wbuf[100];
6026 mbstate_t mb = {0};
6027 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006028 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006029 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006030 __throw_runtime_error("locale not supported");
6031 wchar_t* wbe = wbuf + j;
6032 __curr_symbol_.assign(wbuf, wbe);
6033 if (lc->int_frac_digits != CHAR_MAX)
6034 __frac_digits_ = lc->int_frac_digits;
6035 else
6036 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006037#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006038 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006039#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006040 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006041#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006042 __positive_sign_ = L"()";
6043 else
6044 {
6045 mb = mbstate_t();
6046 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006047 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006048 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006049 __throw_runtime_error("locale not supported");
6050 wbe = wbuf + j;
6051 __positive_sign_.assign(wbuf, wbe);
6052 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006053#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006054 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006055#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006056 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006057#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006058 __negative_sign_ = L"()";
6059 else
6060 {
6061 mb = mbstate_t();
6062 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006063 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006064 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006065 __throw_runtime_error("locale not supported");
6066 wbe = wbuf + j;
6067 __negative_sign_.assign(wbuf, wbe);
6068 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006069 // Assume the positive and negative formats will want spaces in
6070 // the same places in curr_symbol since there's no way to
6071 // represent anything else.
6072 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006073#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006074 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6075 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6076 __init_pat(__neg_format_, __curr_symbol_, true,
6077 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006078#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006079 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6080 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6081 lc->int_p_sign_posn, L' ');
6082 __init_pat(__neg_format_, __curr_symbol_, true,
6083 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6084 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006085#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006086}
6087
6088void __do_nothing(void*) {}
6089
6090void __throw_runtime_error(const char* msg)
6091{
Howard Hinnant72f73582010-08-11 17:04:31 +00006092#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006093 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006094#else
6095 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006096 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006097#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006098}
6099
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006100template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6101template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006102
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006103template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6104template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006105
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006106template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6107template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006108
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006109template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6110template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006111
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006112template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6113template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006114
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006115template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6116template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006117
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006118template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6119template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006120
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006121template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6122template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006123
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006124template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6125template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006126
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006127template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6128template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6129template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6130template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006131
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006132template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6133template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6134template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6135template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006136
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006137template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6138template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006139
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006140template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6141template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006142
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006143template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6144template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006145
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006146template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6147template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006148
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006149template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6150template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006151
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006152template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6153template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006154
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006155template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6156template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
6157template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6158template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006159
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006160template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006161
6162_LIBCPP_END_NAMESPACE_STD