blob: 2115340f0b55aeea7fe376ff48094380332981af [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Howard Hinnantc566dc32010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00004//
Howard Hinnantee11c312010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantc51e1022010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
David Chisnall8074c342012-02-29 13:05:08 +000010// On Solaris, we need to define something to make the C99 parts of localeconv
11// visible.
12#ifdef __sun__
13#define _LCONV_C99
14#endif
15
Howard Hinnantc51e1022010-05-11 19:42:16 +000016#include "string"
17#include "locale"
Howard Hinnant7282c5a2010-05-30 21:39:41 +000018#include "codecvt"
Howard Hinnantc51e1022010-05-11 19:42:16 +000019#include "vector"
20#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000021#include "typeinfo"
Howard Hinnant718dae32013-07-28 18:20:00 +000022#ifndef _LIBCPP_NO_EXCEPTIONS
23# include "type_traits"
24#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000025#include "clocale"
26#include "cstring"
27#include "cwctype"
28#include "__sso_allocator"
Howard Hinnant8ad70912013-09-17 01:34:47 +000029#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnantae0f80b2011-09-29 20:33:10 +000030#include <support/win32/locale_win32.h>
Marshall Clow3477ec92014-07-10 15:20:28 +000031#elif !defined(__ANDROID__)
Howard Hinnantc51e1022010-05-11 19:42:16 +000032#include <langinfo.h>
Marshall Clow3477ec92014-07-10 15:20:28 +000033#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000034#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000035#include <stdio.h>
Howard Hinnantc51e1022010-05-11 19:42:16 +000036
Marshall Clowab9c1772013-02-07 17:20:56 +000037// On Linux, wint_t and wchar_t have different signed-ness, and this causes
38// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000039#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000040#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000041#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000042
Howard Hinnantc51e1022010-05-11 19:42:16 +000043_LIBCPP_BEGIN_NAMESPACE_STD
44
Howard Hinnantf312e3e2011-09-28 23:39:33 +000045#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000046locale_t __cloc() {
47 // In theory this could create a race condition. In practice
48 // the race condition is non-fatal since it will just create
49 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000050 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
51 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000052}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000053#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000054
Howard Hinnantc51e1022010-05-11 19:42:16 +000055namespace {
56
57struct release
58{
59 void operator()(locale::facet* p) {p->__release_shared();}
60};
61
62template <class T, class A0>
63inline
64T&
65make(A0 a0)
66{
67 static typename aligned_storage<sizeof(T)>::type buf;
68 ::new (&buf) T(a0);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000069 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000070}
71
72template <class T, class A0, class A1>
73inline
74T&
75make(A0 a0, A1 a1)
76{
77 static typename aligned_storage<sizeof(T)>::type buf;
78 ::new (&buf) T(a0, a1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000079 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000080}
81
82template <class T, class A0, class A1, class A2>
83inline
84T&
85make(A0 a0, A1 a1, A2 a2)
86{
87 static typename aligned_storage<sizeof(T)>::type buf;
88 ::new (&buf) T(a0, a1, a2);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000089 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000090}
91
Howard Hinnant3d2417c2012-12-27 21:17:53 +000092template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +000093inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +000094_LIBCPP_CONSTEXPR
95size_t
96countof(const T (&)[N])
97{
98 return N;
99}
100
101template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000102inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000103_LIBCPP_CONSTEXPR
104size_t
105countof(const T * const begin, const T * const end)
106{
107 return static_cast<size_t>(end - begin);
108}
109
Howard Hinnantc51e1022010-05-11 19:42:16 +0000110}
111
Howard Hinnantdd099492013-08-29 23:37:50 +0000112#if defined(_AIX)
113// Set priority to INT_MIN + 256 + 150
114# pragma priority ( -2147483242 )
115#endif
116
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000117const locale::category locale::none;
118const locale::category locale::collate;
119const locale::category locale::ctype;
120const locale::category locale::monetary;
121const locale::category locale::numeric;
122const locale::category locale::time;
123const locale::category locale::messages;
124const locale::category locale::all;
125
Marshall Clowd920eea2013-10-21 15:07:28 +0000126#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +0000127#pragma clang diagnostic push
128#pragma clang diagnostic ignored "-Wpadded"
Marshall Clowd920eea2013-10-21 15:07:28 +0000129#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000130
Howard Hinnantc51e1022010-05-11 19:42:16 +0000131class _LIBCPP_HIDDEN locale::__imp
132 : public facet
133{
134 enum {N = 28};
Marshall Clowd920eea2013-10-21 15:07:28 +0000135#if defined(_LIBCPP_MSVC)
136// FIXME: MSVC doesn't support aligned parameters by value.
137// I can't get the __sso_allocator to work here
138// for MSVC I think for this reason.
139 vector<facet*> facets_;
140#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000141 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000142#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000143 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000144public:
145 explicit __imp(size_t refs = 0);
146 explicit __imp(const string& name, size_t refs = 0);
147 __imp(const __imp&);
148 __imp(const __imp&, const string&, locale::category c);
149 __imp(const __imp& other, const __imp& one, locale::category c);
150 __imp(const __imp&, facet* f, long id);
151 ~__imp();
152
153 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000154 bool has_facet(long id) const
155 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000156 const locale::facet* use_facet(long id) const;
157
158 static const locale& make_classic();
159 static locale& make_global();
160private:
161 void install(facet* f, long id);
162 template <class F> void install(F* f) {install(f, f->id.__get());}
163 template <class F> void install_from(const __imp& other);
164};
165
Marshall Clowd920eea2013-10-21 15:07:28 +0000166#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +0000167#pragma clang diagnostic pop
Marshall Clowd920eea2013-10-21 15:07:28 +0000168#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000169
Howard Hinnantc51e1022010-05-11 19:42:16 +0000170locale::__imp::__imp(size_t refs)
171 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000172 facets_(N),
173 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000174{
175 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000176 install(&make<_VSTD::collate<char> >(1u));
177 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000178 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000179 install(&make<_VSTD::ctype<wchar_t> >(1u));
180 install(&make<codecvt<char, char, mbstate_t> >(1u));
181 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
182 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
183 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
184 install(&make<numpunct<char> >(1u));
185 install(&make<numpunct<wchar_t> >(1u));
186 install(&make<num_get<char> >(1u));
187 install(&make<num_get<wchar_t> >(1u));
188 install(&make<num_put<char> >(1u));
189 install(&make<num_put<wchar_t> >(1u));
190 install(&make<moneypunct<char, false> >(1u));
191 install(&make<moneypunct<char, true> >(1u));
192 install(&make<moneypunct<wchar_t, false> >(1u));
193 install(&make<moneypunct<wchar_t, true> >(1u));
194 install(&make<money_get<char> >(1u));
195 install(&make<money_get<wchar_t> >(1u));
196 install(&make<money_put<char> >(1u));
197 install(&make<money_put<wchar_t> >(1u));
198 install(&make<time_get<char> >(1u));
199 install(&make<time_get<wchar_t> >(1u));
200 install(&make<time_put<char> >(1u));
201 install(&make<time_put<wchar_t> >(1u));
202 install(&make<_VSTD::messages<char> >(1u));
203 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000204}
205
206locale::__imp::__imp(const string& name, size_t refs)
207 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000208 facets_(N),
209 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000210{
Howard Hinnant72f73582010-08-11 17:04:31 +0000211#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000212 try
213 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000214#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000215 facets_ = locale::classic().__locale_->facets_;
216 for (unsigned i = 0; i < facets_.size(); ++i)
217 if (facets_[i])
218 facets_[i]->__add_shared();
219 install(new collate_byname<char>(name_));
220 install(new collate_byname<wchar_t>(name_));
221 install(new ctype_byname<char>(name_));
222 install(new ctype_byname<wchar_t>(name_));
223 install(new codecvt_byname<char, char, mbstate_t>(name_));
224 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
225 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
226 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
227 install(new numpunct_byname<char>(name_));
228 install(new numpunct_byname<wchar_t>(name_));
229 install(new moneypunct_byname<char, false>(name_));
230 install(new moneypunct_byname<char, true>(name_));
231 install(new moneypunct_byname<wchar_t, false>(name_));
232 install(new moneypunct_byname<wchar_t, true>(name_));
233 install(new time_get_byname<char>(name_));
234 install(new time_get_byname<wchar_t>(name_));
235 install(new time_put_byname<char>(name_));
236 install(new time_put_byname<wchar_t>(name_));
237 install(new messages_byname<char>(name_));
238 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000239#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000240 }
241 catch (...)
242 {
243 for (unsigned i = 0; i < facets_.size(); ++i)
244 if (facets_[i])
245 facets_[i]->__release_shared();
246 throw;
247 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000248#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000249}
250
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000251// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000252// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000253#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000254#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000255#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000256#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000257
Howard Hinnantc51e1022010-05-11 19:42:16 +0000258locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000259 : facets_(max<size_t>(N, other.facets_.size())),
260 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000261{
262 facets_ = other.facets_;
263 for (unsigned i = 0; i < facets_.size(); ++i)
264 if (facets_[i])
265 facets_[i]->__add_shared();
266}
267
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000268#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000269#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000270#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000271
Howard Hinnantc51e1022010-05-11 19:42:16 +0000272locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000273 : facets_(N),
274 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000275{
276 facets_ = other.facets_;
277 for (unsigned i = 0; i < facets_.size(); ++i)
278 if (facets_[i])
279 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000280#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000281 try
282 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000283#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000284 if (c & locale::collate)
285 {
286 install(new collate_byname<char>(name));
287 install(new collate_byname<wchar_t>(name));
288 }
289 if (c & locale::ctype)
290 {
291 install(new ctype_byname<char>(name));
292 install(new ctype_byname<wchar_t>(name));
293 install(new codecvt_byname<char, char, mbstate_t>(name));
294 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
295 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
296 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
297 }
298 if (c & locale::monetary)
299 {
300 install(new moneypunct_byname<char, false>(name));
301 install(new moneypunct_byname<char, true>(name));
302 install(new moneypunct_byname<wchar_t, false>(name));
303 install(new moneypunct_byname<wchar_t, true>(name));
304 }
305 if (c & locale::numeric)
306 {
307 install(new numpunct_byname<char>(name));
308 install(new numpunct_byname<wchar_t>(name));
309 }
310 if (c & locale::time)
311 {
312 install(new time_get_byname<char>(name));
313 install(new time_get_byname<wchar_t>(name));
314 install(new time_put_byname<char>(name));
315 install(new time_put_byname<wchar_t>(name));
316 }
317 if (c & locale::messages)
318 {
319 install(new messages_byname<char>(name));
320 install(new messages_byname<wchar_t>(name));
321 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000322#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000323 }
324 catch (...)
325 {
326 for (unsigned i = 0; i < facets_.size(); ++i)
327 if (facets_[i])
328 facets_[i]->__release_shared();
329 throw;
330 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000331#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000332}
333
334template<class F>
335inline
336void
337locale::__imp::install_from(const locale::__imp& one)
338{
339 long id = F::id.__get();
340 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
341}
342
343locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000344 : facets_(N),
345 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000346{
347 facets_ = other.facets_;
348 for (unsigned i = 0; i < facets_.size(); ++i)
349 if (facets_[i])
350 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000351#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000352 try
353 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000354#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000355 if (c & locale::collate)
356 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000357 install_from<_VSTD::collate<char> >(one);
358 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000359 }
360 if (c & locale::ctype)
361 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000362 install_from<_VSTD::ctype<char> >(one);
363 install_from<_VSTD::ctype<wchar_t> >(one);
364 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
365 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
366 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
367 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000368 }
369 if (c & locale::monetary)
370 {
371 install_from<moneypunct<char, false> >(one);
372 install_from<moneypunct<char, true> >(one);
373 install_from<moneypunct<wchar_t, false> >(one);
374 install_from<moneypunct<wchar_t, true> >(one);
375 install_from<money_get<char> >(one);
376 install_from<money_get<wchar_t> >(one);
377 install_from<money_put<char> >(one);
378 install_from<money_put<wchar_t> >(one);
379 }
380 if (c & locale::numeric)
381 {
382 install_from<numpunct<char> >(one);
383 install_from<numpunct<wchar_t> >(one);
384 install_from<num_get<char> >(one);
385 install_from<num_get<wchar_t> >(one);
386 install_from<num_put<char> >(one);
387 install_from<num_put<wchar_t> >(one);
388 }
389 if (c & locale::time)
390 {
391 install_from<time_get<char> >(one);
392 install_from<time_get<wchar_t> >(one);
393 install_from<time_put<char> >(one);
394 install_from<time_put<wchar_t> >(one);
395 }
396 if (c & locale::messages)
397 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000398 install_from<_VSTD::messages<char> >(one);
399 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000400 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000401#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000402 }
403 catch (...)
404 {
405 for (unsigned i = 0; i < facets_.size(); ++i)
406 if (facets_[i])
407 facets_[i]->__release_shared();
408 throw;
409 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000410#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000411}
412
413locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000414 : facets_(max<size_t>(N, other.facets_.size()+1)),
415 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000416{
417 f->__add_shared();
418 unique_ptr<facet, release> hold(f);
419 facets_ = other.facets_;
420 for (unsigned i = 0; i < other.facets_.size(); ++i)
421 if (facets_[i])
422 facets_[i]->__add_shared();
423 install(hold.get(), id);
424}
425
426locale::__imp::~__imp()
427{
428 for (unsigned i = 0; i < facets_.size(); ++i)
429 if (facets_[i])
430 facets_[i]->__release_shared();
431}
432
433void
434locale::__imp::install(facet* f, long id)
435{
436 f->__add_shared();
437 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000438 if (static_cast<size_t>(id) >= facets_.size())
439 facets_.resize(static_cast<size_t>(id+1));
440 if (facets_[static_cast<size_t>(id)])
441 facets_[static_cast<size_t>(id)]->__release_shared();
442 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000443}
444
445const locale::facet*
446locale::__imp::use_facet(long id) const
447{
Howard Hinnant72f73582010-08-11 17:04:31 +0000448#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000449 if (!has_facet(id))
450 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000451#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant28b24882011-12-01 20:21:04 +0000452 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000453}
454
455// locale
456
457const locale&
458locale::__imp::make_classic()
459{
460 // only one thread can get in here and it only gets in once
461 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000462 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000463 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000464 return *c;
465}
466
467const locale&
468locale::classic()
469{
470 static const locale& c = __imp::make_classic();
471 return c;
472}
473
474locale&
475locale::__imp::make_global()
476{
477 // only one thread can get in here and it only gets in once
478 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000479 ::new (&buf) locale(locale::classic());
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000480 return *reinterpret_cast<locale*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000481}
482
483locale&
484locale::__global()
485{
486 static locale& g = __imp::make_global();
487 return g;
488}
489
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000490locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000491 : __locale_(__global().__locale_)
492{
493 __locale_->__add_shared();
494}
495
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000496locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000497 : __locale_(l.__locale_)
498{
499 __locale_->__add_shared();
500}
501
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000502locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000503{
504 __locale_->__release_shared();
505}
506
507const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000508locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509{
510 other.__locale_->__add_shared();
511 __locale_->__release_shared();
512 __locale_ = other.__locale_;
513 return *this;
514}
515
516locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000517#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000518 : __locale_(name ? new __imp(name)
519 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000520#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000521 : __locale_(new __imp(name))
522#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000523{
524 __locale_->__add_shared();
525}
526
527locale::locale(const string& name)
528 : __locale_(new __imp(name))
529{
530 __locale_->__add_shared();
531}
532
533locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000534#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000535 : __locale_(name ? new __imp(*other.__locale_, name, c)
536 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000537#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000538 : __locale_(new __imp(*other.__locale_, name, c))
539#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000540{
541 __locale_->__add_shared();
542}
543
544locale::locale(const locale& other, const string& name, category c)
545 : __locale_(new __imp(*other.__locale_, name, c))
546{
547 __locale_->__add_shared();
548}
549
550locale::locale(const locale& other, const locale& one, category c)
551 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
552{
553 __locale_->__add_shared();
554}
555
556string
557locale::name() const
558{
559 return __locale_->name();
560}
561
562void
563locale::__install_ctor(const locale& other, facet* f, long id)
564{
565 if (f)
566 __locale_ = new __imp(*other.__locale_, f, id);
567 else
568 __locale_ = other.__locale_;
569 __locale_->__add_shared();
570}
571
572locale
573locale::global(const locale& loc)
574{
575 locale& g = __global();
576 locale r = g;
577 g = loc;
578 if (g.name() != "*")
579 setlocale(LC_ALL, g.name().c_str());
580 return r;
581}
582
583bool
584locale::has_facet(id& x) const
585{
586 return __locale_->has_facet(x.__get());
587}
588
589const locale::facet*
590locale::use_facet(id& x) const
591{
592 return __locale_->use_facet(x.__get());
593}
594
595bool
596locale::operator==(const locale& y) const
597{
598 return (__locale_ == y.__locale_)
599 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
600}
601
602// locale::facet
603
604locale::facet::~facet()
605{
606}
607
608void
Howard Hinnant719bda32011-05-28 14:41:13 +0000609locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000610{
611 delete this;
612}
613
614// locale::id
615
616int32_t locale::id::__next_id = 0;
617
618namespace
619{
620
621class __fake_bind
622{
623 locale::id* id_;
624 void (locale::id::* pmf_)();
625public:
626 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
627 : id_(id), pmf_(pmf) {}
628
629 void operator()() const
630 {
631 (id_->*pmf_)();
632 }
633};
634
635}
636
637long
638locale::id::__get()
639{
640 call_once(__flag_, __fake_bind(&locale::id::__init, this));
641 return __id_ - 1;
642}
643
644void
645locale::id::__init()
646{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000647 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000648}
649
650// template <> class collate_byname<char>
651
652collate_byname<char>::collate_byname(const char* n, size_t refs)
653 : collate<char>(refs),
654 __l(newlocale(LC_ALL_MASK, n, 0))
655{
Howard Hinnant72f73582010-08-11 17:04:31 +0000656#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000657 if (__l == 0)
658 throw runtime_error("collate_byname<char>::collate_byname"
659 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000660#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000661}
662
663collate_byname<char>::collate_byname(const string& name, size_t refs)
664 : collate<char>(refs),
665 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
666{
Howard Hinnant72f73582010-08-11 17:04:31 +0000667#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000668 if (__l == 0)
669 throw runtime_error("collate_byname<char>::collate_byname"
670 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000671#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000672}
673
674collate_byname<char>::~collate_byname()
675{
676 freelocale(__l);
677}
678
679int
680collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
681 const char_type* __lo2, const char_type* __hi2) const
682{
683 string_type lhs(__lo1, __hi1);
684 string_type rhs(__lo2, __hi2);
685 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
686 if (r < 0)
687 return -1;
688 if (r > 0)
689 return 1;
690 return r;
691}
692
693collate_byname<char>::string_type
694collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
695{
696 const string_type in(lo, hi);
697 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
698 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
699 return out;
700}
701
702// template <> class collate_byname<wchar_t>
703
704collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
705 : collate<wchar_t>(refs),
706 __l(newlocale(LC_ALL_MASK, n, 0))
707{
Howard Hinnant72f73582010-08-11 17:04:31 +0000708#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000709 if (__l == 0)
710 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
711 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000712#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000713}
714
715collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
716 : collate<wchar_t>(refs),
717 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
718{
Howard Hinnant72f73582010-08-11 17:04:31 +0000719#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000720 if (__l == 0)
721 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
722 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000723#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000724}
725
726collate_byname<wchar_t>::~collate_byname()
727{
728 freelocale(__l);
729}
730
731int
732collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
733 const char_type* __lo2, const char_type* __hi2) const
734{
735 string_type lhs(__lo1, __hi1);
736 string_type rhs(__lo2, __hi2);
737 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
738 if (r < 0)
739 return -1;
740 if (r > 0)
741 return 1;
742 return r;
743}
744
745collate_byname<wchar_t>::string_type
746collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
747{
748 const string_type in(lo, hi);
749 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
750 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
751 return out;
752}
753
754// template <> class ctype<wchar_t>;
755
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000756const ctype_base::mask ctype_base::space;
757const ctype_base::mask ctype_base::print;
758const ctype_base::mask ctype_base::cntrl;
759const ctype_base::mask ctype_base::upper;
760const ctype_base::mask ctype_base::lower;
761const ctype_base::mask ctype_base::alpha;
762const ctype_base::mask ctype_base::digit;
763const ctype_base::mask ctype_base::punct;
764const ctype_base::mask ctype_base::xdigit;
765const ctype_base::mask ctype_base::blank;
766const ctype_base::mask ctype_base::alnum;
767const ctype_base::mask ctype_base::graph;
768
Howard Hinnantc51e1022010-05-11 19:42:16 +0000769locale::id ctype<wchar_t>::id;
770
771ctype<wchar_t>::~ctype()
772{
773}
774
775bool
776ctype<wchar_t>::do_is(mask m, char_type c) const
777{
Marshall Clowd920eea2013-10-21 15:07:28 +0000778 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000779}
780
781const wchar_t*
782ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
783{
784 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000785 *vec = static_cast<mask>(isascii(*low) ?
786 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000787 return low;
788}
789
790const wchar_t*
791ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
792{
793 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000794 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000795 break;
796 return low;
797}
798
799const wchar_t*
800ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
801{
802 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000803 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000804 break;
805 return low;
806}
807
808wchar_t
809ctype<wchar_t>::do_toupper(char_type c) const
810{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000811#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
812 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Marshall Cloweae03f62013-11-19 18:05:03 +0000813#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000814 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000815#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000816 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000817#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000818}
819
820const wchar_t*
821ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
822{
823 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000824#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
825 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Marshall Cloweae03f62013-11-19 18:05:03 +0000826#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000827 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
828 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000829#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000830 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000831#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000832 return low;
833}
834
835wchar_t
836ctype<wchar_t>::do_tolower(char_type c) const
837{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000838#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
839 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Marshall Cloweae03f62013-11-19 18:05:03 +0000840#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000841 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000842#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000843 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000844#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000845}
846
847const wchar_t*
848ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
849{
850 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000851#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
852 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Marshall Cloweae03f62013-11-19 18:05:03 +0000853#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000854 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
855 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000856#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000857 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000858#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000859 return low;
860}
861
862wchar_t
863ctype<wchar_t>::do_widen(char c) const
864{
865 return c;
866}
867
868const char*
869ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
870{
871 for (; low != high; ++low, ++dest)
872 *dest = *low;
873 return low;
874}
875
876char
877ctype<wchar_t>::do_narrow(char_type c, char dfault) const
878{
879 if (isascii(c))
880 return static_cast<char>(c);
881 return dfault;
882}
883
884const wchar_t*
885ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
886{
887 for (; low != high; ++low, ++dest)
888 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000889 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000890 else
891 *dest = dfault;
892 return low;
893}
894
895// template <> class ctype<char>;
896
897locale::id ctype<char>::id;
898
899ctype<char>::ctype(const mask* tab, bool del, size_t refs)
900 : locale::facet(refs),
901 __tab_(tab),
902 __del_(del)
903{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000904 if (__tab_ == 0)
905 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000906}
907
908ctype<char>::~ctype()
909{
910 if (__tab_ && __del_)
911 delete [] __tab_;
912}
913
914char
915ctype<char>::do_toupper(char_type c) const
916{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000917#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000918 return isascii(c) ?
919 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000920#elif defined(__NetBSD__)
921 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Marshall Cloweae03f62013-11-19 18:05:03 +0000922#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000923 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000924 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000925#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000926 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000927#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000928}
929
930const char*
931ctype<char>::do_toupper(char_type* low, const char_type* high) const
932{
933 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000934#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000935 *low = isascii(*low) ?
936 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000937#elif defined(__NetBSD__)
938 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Marshall Cloweae03f62013-11-19 18:05:03 +0000939#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000940 *low = isascii(*low) ?
941 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000942#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000943 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000944#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000945 return low;
946}
947
948char
949ctype<char>::do_tolower(char_type c) const
950{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000951#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000952 return isascii(c) ?
953 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000954#elif defined(__NetBSD__)
955 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Marshall Cloweae03f62013-11-19 18:05:03 +0000956#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Marshall Clowada0f732013-02-07 14:22:51 +0000957 return isascii(c) ?
958 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000959#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000960 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000961#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000962}
963
964const char*
965ctype<char>::do_tolower(char_type* low, const char_type* high) const
966{
967 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000968#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000969 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000970#elif defined(__NetBSD__)
971 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Marshall Cloweae03f62013-11-19 18:05:03 +0000972#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000973 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000974#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000975 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000976#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000977 return low;
978}
979
980char
981ctype<char>::do_widen(char c) const
982{
983 return c;
984}
985
986const char*
987ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
988{
989 for (; low != high; ++low, ++dest)
990 *dest = *low;
991 return low;
992}
993
994char
995ctype<char>::do_narrow(char_type c, char dfault) const
996{
997 if (isascii(c))
998 return static_cast<char>(c);
999 return dfault;
1000}
1001
1002const char*
1003ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1004{
1005 for (; low != high; ++low, ++dest)
1006 if (isascii(*low))
1007 *dest = *low;
1008 else
1009 *dest = dfault;
1010 return low;
1011}
1012
Marshall Cloweae03f62013-11-19 18:05:03 +00001013#ifdef __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001014extern "C" const unsigned short ** __ctype_b_loc();
1015extern "C" const int ** __ctype_tolower_loc();
1016extern "C" const int ** __ctype_toupper_loc();
1017#endif
1018
Marshall Clow8f870232015-03-04 16:50:02 +00001019#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001020const ctype<char>::mask*
1021ctype<char>::classic_table() _NOEXCEPT
1022{
1023 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1024 cntrl, cntrl,
1025 cntrl, cntrl,
1026 cntrl, cntrl,
1027 cntrl, cntrl,
1028 cntrl, cntrl | space | blank,
1029 cntrl | space, cntrl | space,
1030 cntrl | space, cntrl | space,
1031 cntrl, cntrl,
1032 cntrl, cntrl,
1033 cntrl, cntrl,
1034 cntrl, cntrl,
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 cntrl, cntrl,
1038 cntrl, cntrl,
1039 cntrl, cntrl,
1040 space | blank | print, punct | print,
1041 punct | print, punct | print,
1042 punct | print, punct | print,
1043 punct | print, punct | print,
1044 punct | print, punct | print,
1045 punct | print, punct | print,
1046 punct | print, punct | print,
1047 punct | print, punct | print,
1048 digit | print | xdigit, digit | print | xdigit,
1049 digit | print | xdigit, digit | print | xdigit,
1050 digit | print | xdigit, digit | print | xdigit,
1051 digit | print | xdigit, digit | print | xdigit,
1052 digit | print | xdigit, digit | print | xdigit,
1053 punct | print, punct | print,
1054 punct | print, punct | print,
1055 punct | print, punct | print,
1056 punct | print, upper | xdigit | print | alpha,
1057 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1058 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1059 upper | xdigit | print | alpha, upper | print | alpha,
1060 upper | print | alpha, upper | print | alpha,
1061 upper | print | alpha, upper | print | alpha,
1062 upper | print | alpha, upper | print | alpha,
1063 upper | print | alpha, upper | print | alpha,
1064 upper | print | alpha, upper | print | alpha,
1065 upper | print | alpha, upper | print | alpha,
1066 upper | print | alpha, upper | print | alpha,
1067 upper | print | alpha, upper | print | alpha,
1068 upper | print | alpha, upper | print | alpha,
1069 upper | print | alpha, punct | print,
1070 punct | print, punct | print,
1071 punct | print, punct | print,
1072 punct | print, lower | xdigit | print | alpha,
1073 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1074 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1075 lower | xdigit | print | alpha, lower | print | alpha,
1076 lower | print | alpha, lower | print | alpha,
1077 lower | print | alpha, lower | print | alpha,
1078 lower | print | alpha, lower | print | alpha,
1079 lower | print | alpha, lower | print | alpha,
1080 lower | print | alpha, lower | print | alpha,
1081 lower | print | alpha, lower | print | alpha,
1082 lower | print | alpha, lower | print | alpha,
1083 lower | print | alpha, lower | print | alpha,
1084 lower | print | alpha, lower | print | alpha,
1085 lower | print | alpha, punct | print,
1086 punct | print, punct | print,
1087 punct | print, cntrl,
1088 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1089 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1090 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1091 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1092 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1093 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1094 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1095 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1096 };
1097 return builtin_table;
1098}
1099#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001100const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001101ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001102{
David Chisnall1d581062011-09-21 08:39:44 +00001103#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001104 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001105#elif defined(__NetBSD__)
1106 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001107#elif defined(__GLIBC__)
1108 return __cloc()->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001109#elif __sun__
1110 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001111#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001112 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnall1d581062011-09-21 08:39:44 +00001113// This is assumed to be safe, which is a nonsense assumption because we're
1114// going to end up dereferencing it later...
Marshall Cloweae03f62013-11-19 18:05:03 +00001115#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001116 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001117#elif defined(_NEWLIB_VERSION)
1118 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1119 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001120#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001121 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Marshall Clow3477ec92014-07-10 15:20:28 +00001122#elif defined(__ANDROID__)
Dan Albertb380e8c2014-07-31 21:04:08 +00001123 return reinterpret_cast<const unsigned char*>(_ctype_) + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001124#else
David Chisnall8074c342012-02-29 13:05:08 +00001125 // Platform not supported: abort so the person doing the port knows what to
1126 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001127# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001128 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001129 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001130 return NULL;
1131#endif
1132}
Marshall Clowb3f62842015-03-04 16:10:14 +00001133#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001134
Howard Hinnantd7a78632011-09-29 13:33:15 +00001135#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001136const int*
1137ctype<char>::__classic_lower_table() _NOEXCEPT
1138{
Alexis Hunt92b0c812011-07-09 00:56:23 +00001139 return __cloc()->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001140}
1141
1142const int*
1143ctype<char>::__classic_upper_table() _NOEXCEPT
1144{
Alexis Hunt92b0c812011-07-09 00:56:23 +00001145 return __cloc()->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001146}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001147#elif __NetBSD__
1148const short*
1149ctype<char>::__classic_lower_table() _NOEXCEPT
1150{
1151 return _C_tolower_tab_ + 1;
1152}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001153
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001154const short*
1155ctype<char>::__classic_upper_table() _NOEXCEPT
1156{
1157 return _C_toupper_tab_ + 1;
1158}
1159
Marshall Cloweae03f62013-11-19 18:05:03 +00001160#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001161const int*
1162ctype<char>::__classic_lower_table() _NOEXCEPT
1163{
1164 return *__ctype_tolower_loc();
1165}
1166
1167const int*
1168ctype<char>::__classic_upper_table() _NOEXCEPT
1169{
1170 return *__ctype_toupper_loc();
1171}
Marshall Cloweae03f62013-11-19 18:05:03 +00001172#endif // __GLIBC__ || __EMSCRIPTEN__ || __NETBSD__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001173
Howard Hinnantc51e1022010-05-11 19:42:16 +00001174// template <> class ctype_byname<char>
1175
1176ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1177 : ctype<char>(0, false, refs),
1178 __l(newlocale(LC_ALL_MASK, name, 0))
1179{
Howard Hinnant72f73582010-08-11 17:04:31 +00001180#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001181 if (__l == 0)
1182 throw runtime_error("ctype_byname<char>::ctype_byname"
1183 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001184#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001185}
1186
1187ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1188 : ctype<char>(0, false, refs),
1189 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1190{
Howard Hinnant72f73582010-08-11 17:04:31 +00001191#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001192 if (__l == 0)
1193 throw runtime_error("ctype_byname<char>::ctype_byname"
1194 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001195#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001196}
1197
1198ctype_byname<char>::~ctype_byname()
1199{
1200 freelocale(__l);
1201}
1202
1203char
1204ctype_byname<char>::do_toupper(char_type c) const
1205{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001206 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001207}
1208
1209const char*
1210ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1211{
1212 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001213 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001214 return low;
1215}
1216
1217char
1218ctype_byname<char>::do_tolower(char_type c) const
1219{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001220 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001221}
1222
1223const char*
1224ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1225{
1226 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001227 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001228 return low;
1229}
1230
1231// template <> class ctype_byname<wchar_t>
1232
1233ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1234 : ctype<wchar_t>(refs),
1235 __l(newlocale(LC_ALL_MASK, name, 0))
1236{
Howard Hinnant72f73582010-08-11 17:04:31 +00001237#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001238 if (__l == 0)
1239 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1240 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001241#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001242}
1243
1244ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1245 : ctype<wchar_t>(refs),
1246 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1247{
Howard Hinnant72f73582010-08-11 17:04:31 +00001248#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001249 if (__l == 0)
1250 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1251 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001252#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001253}
1254
1255ctype_byname<wchar_t>::~ctype_byname()
1256{
1257 freelocale(__l);
1258}
1259
1260bool
1261ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1262{
Alexis Huntc2017f12011-07-09 03:40:04 +00001263#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001264 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001265#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001266 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001267 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofs60570512014-08-27 00:39:47 +00001268 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1269 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1270 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1271 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1272 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1273 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1274 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1275 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1276 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1277 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001278 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001279#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001280}
1281
1282const wchar_t*
1283ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1284{
1285 for (; low != high; ++low, ++vec)
1286 {
1287 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001288 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001289 else
1290 {
1291 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001292 wint_t ch = static_cast<wint_t>(*low);
1293 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001294 *vec |= space;
Marshall Clowada0f732013-02-07 14:22:51 +00001295 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001296 *vec |= print;
Marshall Clowada0f732013-02-07 14:22:51 +00001297 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001298 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001299 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001301 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001302 *vec |= lower;
Marshall Clowada0f732013-02-07 14:22:51 +00001303 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001304 *vec |= alpha;
Marshall Clowada0f732013-02-07 14:22:51 +00001305 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001306 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001307 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001308 *vec |= punct;
Marshall Clowada0f732013-02-07 14:22:51 +00001309 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001310 *vec |= xdigit;
1311 }
1312 }
1313 return low;
1314}
1315
1316const wchar_t*
1317ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1318{
1319 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001320 {
1321#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001322 if (iswctype_l(*low, m, __l))
1323 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001324#else
Marshall Clowada0f732013-02-07 14:22:51 +00001325 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs60570512014-08-27 00:39:47 +00001326 if (m & space && iswspace_l(ch, __l)) break;
1327 if (m & print && iswprint_l(ch, __l)) break;
1328 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1329 if (m & upper && iswupper_l(ch, __l)) break;
1330 if (m & lower && iswlower_l(ch, __l)) break;
1331 if (m & alpha && iswalpha_l(ch, __l)) break;
1332 if (m & digit && iswdigit_l(ch, __l)) break;
1333 if (m & punct && iswpunct_l(ch, __l)) break;
1334 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1335 if (m & blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001336#endif
1337 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001338 return low;
1339}
1340
1341const wchar_t*
1342ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1343{
1344 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001345 {
1346#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001347 if (!iswctype_l(*low, m, __l))
1348 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001349#else
Marshall Clowada0f732013-02-07 14:22:51 +00001350 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs60570512014-08-27 00:39:47 +00001351 if (m & space && iswspace_l(ch, __l)) continue;
1352 if (m & print && iswprint_l(ch, __l)) continue;
1353 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1354 if (m & upper && iswupper_l(ch, __l)) continue;
1355 if (m & lower && iswlower_l(ch, __l)) continue;
1356 if (m & alpha && iswalpha_l(ch, __l)) continue;
1357 if (m & digit && iswdigit_l(ch, __l)) continue;
1358 if (m & punct && iswpunct_l(ch, __l)) continue;
1359 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1360 if (m & blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001361 break;
1362#endif
1363 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001364 return low;
1365}
1366
1367wchar_t
1368ctype_byname<wchar_t>::do_toupper(char_type c) const
1369{
1370 return towupper_l(c, __l);
1371}
1372
1373const wchar_t*
1374ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1375{
1376 for (; low != high; ++low)
1377 *low = towupper_l(*low, __l);
1378 return low;
1379}
1380
1381wchar_t
1382ctype_byname<wchar_t>::do_tolower(char_type c) const
1383{
1384 return towlower_l(c, __l);
1385}
1386
1387const wchar_t*
1388ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1389{
1390 for (; low != high; ++low)
1391 *low = towlower_l(*low, __l);
1392 return low;
1393}
1394
1395wchar_t
1396ctype_byname<wchar_t>::do_widen(char c) const
1397{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001398#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001399 return btowc_l(c, __l);
1400#else
1401 return __btowc_l(c, __l);
1402#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001403}
1404
1405const char*
1406ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1407{
1408 for (; low != high; ++low, ++dest)
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001409#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001410 *dest = btowc_l(*low, __l);
1411#else
1412 *dest = __btowc_l(*low, __l);
1413#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001414 return low;
1415}
1416
1417char
1418ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1419{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001420#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001421 int r = wctob_l(c, __l);
1422#else
1423 int r = __wctob_l(c, __l);
1424#endif
Howard Hinnant434ebf72012-12-27 18:46:00 +00001425 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001426}
1427
1428const wchar_t*
1429ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1430{
1431 for (; low != high; ++low, ++dest)
1432 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001433#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001434 int r = wctob_l(*low, __l);
1435#else
1436 int r = __wctob_l(*low, __l);
1437#endif
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{
Howard Hinnant72f73582010-08-11 17:04:31 +00001518#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001519 if (__l == 0)
1520 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1521 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001522#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001523}
1524
1525codecvt<wchar_t, char, mbstate_t>::~codecvt()
1526{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001527 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001528 freelocale(__l);
1529}
1530
1531codecvt<wchar_t, char, mbstate_t>::result
1532codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001533 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001534 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1535{
1536 // look for first internal null in frm
1537 const intern_type* fend = frm;
1538 for (; fend != frm_end; ++fend)
1539 if (*fend == 0)
1540 break;
1541 // loop over all null-terminated sequences in frm
1542 to_nxt = to;
1543 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1544 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001545 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001546 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001547#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001548 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1549 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001550#else
1551 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1552#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001553 if (n == size_t(-1))
1554 {
1555 // need to recover to_nxt
1556 for (to_nxt = to; frm != frm_nxt; ++frm)
1557 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001558#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001559 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1560#else
1561 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1562#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001563 if (n == size_t(-1))
1564 break;
1565 to_nxt += n;
1566 }
1567 frm_nxt = frm;
1568 return error;
1569 }
1570 if (n == 0)
1571 return partial;
1572 to_nxt += n;
1573 if (to_nxt == to_end)
1574 break;
1575 if (fend != frm_end) // set up next null terminated sequence
1576 {
1577 // Try to write the terminating null
1578 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001579#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001580 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1581#else
1582 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1583#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001584 if (n == size_t(-1)) // on error
1585 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001586 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001587 return partial;
1588 for (extern_type* p = tmp; n; --n) // write it
1589 *to_nxt++ = *p++;
1590 ++frm_nxt;
1591 // look for next null in frm
1592 for (fend = frm_nxt; fend != frm_end; ++fend)
1593 if (*fend == 0)
1594 break;
1595 }
1596 }
1597 return frm_nxt == frm_end ? ok : partial;
1598}
1599
1600codecvt<wchar_t, char, mbstate_t>::result
1601codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001602 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001603 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1604{
1605 // look for first internal null in frm
1606 const extern_type* fend = frm;
1607 for (; fend != frm_end; ++fend)
1608 if (*fend == 0)
1609 break;
1610 // loop over all null-terminated sequences in frm
1611 to_nxt = to;
1612 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1613 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001614 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001615 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001616#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001617 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1618 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001619#else
1620 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1621#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001622 if (n == size_t(-1))
1623 {
1624 // need to recover to_nxt
1625 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1626 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001627#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001628 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1629 &save_state, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001630#else
1631 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1632#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001633 switch (n)
1634 {
1635 case 0:
1636 ++frm;
1637 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001638 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001639 frm_nxt = frm;
1640 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001641 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001642 frm_nxt = frm;
1643 return partial;
1644 default:
1645 frm += n;
1646 break;
1647 }
1648 }
1649 frm_nxt = frm;
1650 return frm_nxt == frm_end ? ok : partial;
1651 }
1652 if (n == 0)
1653 return error;
1654 to_nxt += n;
1655 if (to_nxt == to_end)
1656 break;
1657 if (fend != frm_end) // set up next null terminated sequence
1658 {
1659 // Try to write the terminating null
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001660#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001661 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1662#else
1663 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1664#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001665 if (n != 0) // on error
1666 return error;
1667 ++to_nxt;
1668 ++frm_nxt;
1669 // look for next null in frm
1670 for (fend = frm_nxt; fend != frm_end; ++fend)
1671 if (*fend == 0)
1672 break;
1673 }
1674 }
1675 return frm_nxt == frm_end ? ok : partial;
1676}
1677
1678codecvt<wchar_t, char, mbstate_t>::result
1679codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1680 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1681{
1682 to_nxt = to;
1683 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001684#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001685 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1686#else
1687 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1688#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001689 if (n == size_t(-1) || n == 0) // on error
1690 return error;
1691 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001692 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001693 return partial;
1694 for (extern_type* p = tmp; n; --n) // write it
1695 *to_nxt++ = *p++;
1696 return ok;
1697}
1698
1699int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001700codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001701{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001702#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001703 if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001704#else
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001705 if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001706#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001707 {
1708 // stateless encoding
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001709#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001710 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1711#else
1712 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1713#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001714 return 1; // which take more than 1 char to form a wchar_t
1715 return 0;
1716 }
1717 return -1;
1718}
1719
1720bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001721codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001722{
1723 return false;
1724}
1725
1726int
1727codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1728 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1729{
1730 int nbytes = 0;
1731 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1732 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001733#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001734 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001735#else
1736 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1737#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001738 switch (n)
1739 {
1740 case 0:
1741 ++nbytes;
1742 ++frm;
1743 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001744 case size_t(-1):
1745 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001746 return nbytes;
1747 default:
1748 nbytes += n;
1749 frm += n;
1750 break;
1751 }
1752 }
1753 return nbytes;
1754}
1755
1756int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001757codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001758{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001759#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clowab9c1772013-02-07 17:20:56 +00001760 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001761#else
Marshall Clowab9c1772013-02-07 17:20:56 +00001762 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001763#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001764}
1765
1766// Valid UTF ranges
1767// UTF-32 UTF-16 UTF-8 # of code points
1768// first second first second third fourth
1769// 000000 - 00007F 0000 - 007F 00 - 7F 127
1770// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1771// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1772// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1773// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1774// 00D800 - 00DFFF invalid
1775// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1776// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1777// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1778// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1779
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001780static
1781codecvt_base::result
1782utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1783 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1784 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1785{
1786 frm_nxt = frm;
1787 to_nxt = to;
1788 if (mode & generate_header)
1789 {
1790 if (to_end-to_nxt < 3)
1791 return codecvt_base::partial;
1792 *to_nxt++ = static_cast<uint8_t>(0xEF);
1793 *to_nxt++ = static_cast<uint8_t>(0xBB);
1794 *to_nxt++ = static_cast<uint8_t>(0xBF);
1795 }
1796 for (; frm_nxt < frm_end; ++frm_nxt)
1797 {
1798 uint16_t wc1 = *frm_nxt;
1799 if (wc1 > Maxcode)
1800 return codecvt_base::error;
1801 if (wc1 < 0x0080)
1802 {
1803 if (to_end-to_nxt < 1)
1804 return codecvt_base::partial;
1805 *to_nxt++ = static_cast<uint8_t>(wc1);
1806 }
1807 else if (wc1 < 0x0800)
1808 {
1809 if (to_end-to_nxt < 2)
1810 return codecvt_base::partial;
1811 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1812 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1813 }
1814 else if (wc1 < 0xD800)
1815 {
1816 if (to_end-to_nxt < 3)
1817 return codecvt_base::partial;
1818 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1819 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1820 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1821 }
1822 else if (wc1 < 0xDC00)
1823 {
1824 if (frm_end-frm_nxt < 2)
1825 return codecvt_base::partial;
1826 uint16_t wc2 = frm_nxt[1];
1827 if ((wc2 & 0xFC00) != 0xDC00)
1828 return codecvt_base::error;
1829 if (to_end-to_nxt < 4)
1830 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001831 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1832 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001833 return codecvt_base::error;
1834 ++frm_nxt;
1835 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1836 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1837 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1838 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1839 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1840 }
1841 else if (wc1 < 0xE000)
1842 {
1843 return codecvt_base::error;
1844 }
1845 else
1846 {
1847 if (to_end-to_nxt < 3)
1848 return codecvt_base::partial;
1849 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1851 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1852 }
1853 }
1854 return codecvt_base::ok;
1855}
1856
1857static
1858codecvt_base::result
1859utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1860 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1861 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1862{
1863 frm_nxt = frm;
1864 to_nxt = to;
1865 if (mode & generate_header)
1866 {
1867 if (to_end-to_nxt < 3)
1868 return codecvt_base::partial;
1869 *to_nxt++ = static_cast<uint8_t>(0xEF);
1870 *to_nxt++ = static_cast<uint8_t>(0xBB);
1871 *to_nxt++ = static_cast<uint8_t>(0xBF);
1872 }
1873 for (; frm_nxt < frm_end; ++frm_nxt)
1874 {
1875 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1876 if (wc1 > Maxcode)
1877 return codecvt_base::error;
1878 if (wc1 < 0x0080)
1879 {
1880 if (to_end-to_nxt < 1)
1881 return codecvt_base::partial;
1882 *to_nxt++ = static_cast<uint8_t>(wc1);
1883 }
1884 else if (wc1 < 0x0800)
1885 {
1886 if (to_end-to_nxt < 2)
1887 return codecvt_base::partial;
1888 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1889 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1890 }
1891 else if (wc1 < 0xD800)
1892 {
1893 if (to_end-to_nxt < 3)
1894 return codecvt_base::partial;
1895 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1896 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1897 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1898 }
1899 else if (wc1 < 0xDC00)
1900 {
1901 if (frm_end-frm_nxt < 2)
1902 return codecvt_base::partial;
1903 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1904 if ((wc2 & 0xFC00) != 0xDC00)
1905 return codecvt_base::error;
1906 if (to_end-to_nxt < 4)
1907 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001908 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1909 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001910 return codecvt_base::error;
1911 ++frm_nxt;
1912 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1913 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1914 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1915 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1916 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1917 }
1918 else if (wc1 < 0xE000)
1919 {
1920 return codecvt_base::error;
1921 }
1922 else
1923 {
1924 if (to_end-to_nxt < 3)
1925 return codecvt_base::partial;
1926 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1927 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1928 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1929 }
1930 }
1931 return codecvt_base::ok;
1932}
1933
1934static
1935codecvt_base::result
1936utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1937 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1938 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1939{
1940 frm_nxt = frm;
1941 to_nxt = to;
1942 if (mode & consume_header)
1943 {
1944 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1945 frm_nxt[2] == 0xBF)
1946 frm_nxt += 3;
1947 }
1948 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1949 {
1950 uint8_t c1 = *frm_nxt;
1951 if (c1 > Maxcode)
1952 return codecvt_base::error;
1953 if (c1 < 0x80)
1954 {
1955 *to_nxt = static_cast<uint16_t>(c1);
1956 ++frm_nxt;
1957 }
1958 else if (c1 < 0xC2)
1959 {
1960 return codecvt_base::error;
1961 }
1962 else if (c1 < 0xE0)
1963 {
1964 if (frm_end-frm_nxt < 2)
1965 return codecvt_base::partial;
1966 uint8_t c2 = frm_nxt[1];
1967 if ((c2 & 0xC0) != 0x80)
1968 return codecvt_base::error;
1969 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1970 if (t > Maxcode)
1971 return codecvt_base::error;
1972 *to_nxt = t;
1973 frm_nxt += 2;
1974 }
1975 else if (c1 < 0xF0)
1976 {
1977 if (frm_end-frm_nxt < 3)
1978 return codecvt_base::partial;
1979 uint8_t c2 = frm_nxt[1];
1980 uint8_t c3 = frm_nxt[2];
1981 switch (c1)
1982 {
1983 case 0xE0:
1984 if ((c2 & 0xE0) != 0xA0)
1985 return codecvt_base::error;
1986 break;
1987 case 0xED:
1988 if ((c2 & 0xE0) != 0x80)
1989 return codecvt_base::error;
1990 break;
1991 default:
1992 if ((c2 & 0xC0) != 0x80)
1993 return codecvt_base::error;
1994 break;
1995 }
1996 if ((c3 & 0xC0) != 0x80)
1997 return codecvt_base::error;
1998 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1999 | ((c2 & 0x3F) << 6)
2000 | (c3 & 0x3F));
2001 if (t > Maxcode)
2002 return codecvt_base::error;
2003 *to_nxt = t;
2004 frm_nxt += 3;
2005 }
2006 else if (c1 < 0xF5)
2007 {
2008 if (frm_end-frm_nxt < 4)
2009 return codecvt_base::partial;
2010 uint8_t c2 = frm_nxt[1];
2011 uint8_t c3 = frm_nxt[2];
2012 uint8_t c4 = frm_nxt[3];
2013 switch (c1)
2014 {
2015 case 0xF0:
2016 if (!(0x90 <= c2 && c2 <= 0xBF))
2017 return codecvt_base::error;
2018 break;
2019 case 0xF4:
2020 if ((c2 & 0xF0) != 0x80)
2021 return codecvt_base::error;
2022 break;
2023 default:
2024 if ((c2 & 0xC0) != 0x80)
2025 return codecvt_base::error;
2026 break;
2027 }
2028 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2029 return codecvt_base::error;
2030 if (to_end-to_nxt < 2)
2031 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002032 if ((((c1 & 7UL) << 18) +
2033 ((c2 & 0x3FUL) << 12) +
2034 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002035 return codecvt_base::error;
2036 *to_nxt = static_cast<uint16_t>(
2037 0xD800
2038 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2039 | ((c2 & 0x0F) << 2)
2040 | ((c3 & 0x30) >> 4));
2041 *++to_nxt = static_cast<uint16_t>(
2042 0xDC00
2043 | ((c3 & 0x0F) << 6)
2044 | (c4 & 0x3F));
2045 frm_nxt += 4;
2046 }
2047 else
2048 {
2049 return codecvt_base::error;
2050 }
2051 }
2052 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2053}
2054
2055static
2056codecvt_base::result
2057utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2058 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2059 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2060{
2061 frm_nxt = frm;
2062 to_nxt = to;
2063 if (mode & consume_header)
2064 {
2065 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2066 frm_nxt[2] == 0xBF)
2067 frm_nxt += 3;
2068 }
2069 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2070 {
2071 uint8_t c1 = *frm_nxt;
2072 if (c1 > Maxcode)
2073 return codecvt_base::error;
2074 if (c1 < 0x80)
2075 {
2076 *to_nxt = static_cast<uint32_t>(c1);
2077 ++frm_nxt;
2078 }
2079 else if (c1 < 0xC2)
2080 {
2081 return codecvt_base::error;
2082 }
2083 else if (c1 < 0xE0)
2084 {
2085 if (frm_end-frm_nxt < 2)
2086 return codecvt_base::partial;
2087 uint8_t c2 = frm_nxt[1];
2088 if ((c2 & 0xC0) != 0x80)
2089 return codecvt_base::error;
2090 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2091 if (t > Maxcode)
2092 return codecvt_base::error;
2093 *to_nxt = static_cast<uint32_t>(t);
2094 frm_nxt += 2;
2095 }
2096 else if (c1 < 0xF0)
2097 {
2098 if (frm_end-frm_nxt < 3)
2099 return codecvt_base::partial;
2100 uint8_t c2 = frm_nxt[1];
2101 uint8_t c3 = frm_nxt[2];
2102 switch (c1)
2103 {
2104 case 0xE0:
2105 if ((c2 & 0xE0) != 0xA0)
2106 return codecvt_base::error;
2107 break;
2108 case 0xED:
2109 if ((c2 & 0xE0) != 0x80)
2110 return codecvt_base::error;
2111 break;
2112 default:
2113 if ((c2 & 0xC0) != 0x80)
2114 return codecvt_base::error;
2115 break;
2116 }
2117 if ((c3 & 0xC0) != 0x80)
2118 return codecvt_base::error;
2119 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2120 | ((c2 & 0x3F) << 6)
2121 | (c3 & 0x3F));
2122 if (t > Maxcode)
2123 return codecvt_base::error;
2124 *to_nxt = static_cast<uint32_t>(t);
2125 frm_nxt += 3;
2126 }
2127 else if (c1 < 0xF5)
2128 {
2129 if (frm_end-frm_nxt < 4)
2130 return codecvt_base::partial;
2131 uint8_t c2 = frm_nxt[1];
2132 uint8_t c3 = frm_nxt[2];
2133 uint8_t c4 = frm_nxt[3];
2134 switch (c1)
2135 {
2136 case 0xF0:
2137 if (!(0x90 <= c2 && c2 <= 0xBF))
2138 return codecvt_base::error;
2139 break;
2140 case 0xF4:
2141 if ((c2 & 0xF0) != 0x80)
2142 return codecvt_base::error;
2143 break;
2144 default:
2145 if ((c2 & 0xC0) != 0x80)
2146 return codecvt_base::error;
2147 break;
2148 }
2149 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2150 return codecvt_base::error;
2151 if (to_end-to_nxt < 2)
2152 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002153 if ((((c1 & 7UL) << 18) +
2154 ((c2 & 0x3FUL) << 12) +
2155 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002156 return codecvt_base::error;
2157 *to_nxt = static_cast<uint32_t>(
2158 0xD800
2159 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2160 | ((c2 & 0x0F) << 2)
2161 | ((c3 & 0x30) >> 4));
2162 *++to_nxt = static_cast<uint32_t>(
2163 0xDC00
2164 | ((c3 & 0x0F) << 6)
2165 | (c4 & 0x3F));
2166 frm_nxt += 4;
2167 }
2168 else
2169 {
2170 return codecvt_base::error;
2171 }
2172 }
2173 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2174}
2175
2176static
2177int
2178utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2179 size_t mx, unsigned long Maxcode = 0x10FFFF,
2180 codecvt_mode mode = codecvt_mode(0))
2181{
2182 const uint8_t* frm_nxt = frm;
2183 if (mode & consume_header)
2184 {
2185 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2186 frm_nxt[2] == 0xBF)
2187 frm_nxt += 3;
2188 }
2189 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2190 {
2191 uint8_t c1 = *frm_nxt;
2192 if (c1 > Maxcode)
2193 break;
2194 if (c1 < 0x80)
2195 {
2196 ++frm_nxt;
2197 }
2198 else if (c1 < 0xC2)
2199 {
2200 break;
2201 }
2202 else if (c1 < 0xE0)
2203 {
2204 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2205 break;
2206 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2207 if (t > Maxcode)
2208 break;
2209 frm_nxt += 2;
2210 }
2211 else if (c1 < 0xF0)
2212 {
2213 if (frm_end-frm_nxt < 3)
2214 break;
2215 uint8_t c2 = frm_nxt[1];
2216 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002217 switch (c1)
2218 {
2219 case 0xE0:
2220 if ((c2 & 0xE0) != 0xA0)
2221 return static_cast<int>(frm_nxt - frm);
2222 break;
2223 case 0xED:
2224 if ((c2 & 0xE0) != 0x80)
2225 return static_cast<int>(frm_nxt - frm);
2226 break;
2227 default:
2228 if ((c2 & 0xC0) != 0x80)
2229 return static_cast<int>(frm_nxt - frm);
2230 break;
2231 }
2232 if ((c3 & 0xC0) != 0x80)
2233 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002234 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002235 break;
2236 frm_nxt += 3;
2237 }
2238 else if (c1 < 0xF5)
2239 {
2240 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2241 break;
2242 uint8_t c2 = frm_nxt[1];
2243 uint8_t c3 = frm_nxt[2];
2244 uint8_t c4 = frm_nxt[3];
2245 switch (c1)
2246 {
2247 case 0xF0:
2248 if (!(0x90 <= c2 && c2 <= 0xBF))
2249 return static_cast<int>(frm_nxt - frm);
2250 break;
2251 case 0xF4:
2252 if ((c2 & 0xF0) != 0x80)
2253 return static_cast<int>(frm_nxt - frm);
2254 break;
2255 default:
2256 if ((c2 & 0xC0) != 0x80)
2257 return static_cast<int>(frm_nxt - frm);
2258 break;
2259 }
2260 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2261 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002262 if ((((c1 & 7UL) << 18) +
2263 ((c2 & 0x3FUL) << 12) +
2264 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002265 break;
2266 ++nchar16_t;
2267 frm_nxt += 4;
2268 }
2269 else
2270 {
2271 break;
2272 }
2273 }
2274 return static_cast<int>(frm_nxt - frm);
2275}
2276
2277static
2278codecvt_base::result
2279ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2280 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2281 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2282{
2283 frm_nxt = frm;
2284 to_nxt = to;
2285 if (mode & generate_header)
2286 {
2287 if (to_end-to_nxt < 3)
2288 return codecvt_base::partial;
2289 *to_nxt++ = static_cast<uint8_t>(0xEF);
2290 *to_nxt++ = static_cast<uint8_t>(0xBB);
2291 *to_nxt++ = static_cast<uint8_t>(0xBF);
2292 }
2293 for (; frm_nxt < frm_end; ++frm_nxt)
2294 {
2295 uint32_t wc = *frm_nxt;
2296 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2297 return codecvt_base::error;
2298 if (wc < 0x000080)
2299 {
2300 if (to_end-to_nxt < 1)
2301 return codecvt_base::partial;
2302 *to_nxt++ = static_cast<uint8_t>(wc);
2303 }
2304 else if (wc < 0x000800)
2305 {
2306 if (to_end-to_nxt < 2)
2307 return codecvt_base::partial;
2308 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2309 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2310 }
2311 else if (wc < 0x010000)
2312 {
2313 if (to_end-to_nxt < 3)
2314 return codecvt_base::partial;
2315 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2316 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2317 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2318 }
2319 else // if (wc < 0x110000)
2320 {
2321 if (to_end-to_nxt < 4)
2322 return codecvt_base::partial;
2323 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2324 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2325 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2326 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2327 }
2328 }
2329 return codecvt_base::ok;
2330}
2331
2332static
2333codecvt_base::result
2334utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2335 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2336 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2337{
2338 frm_nxt = frm;
2339 to_nxt = to;
2340 if (mode & consume_header)
2341 {
2342 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2343 frm_nxt[2] == 0xBF)
2344 frm_nxt += 3;
2345 }
2346 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2347 {
2348 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2349 if (c1 < 0x80)
2350 {
2351 if (c1 > Maxcode)
2352 return codecvt_base::error;
2353 *to_nxt = static_cast<uint32_t>(c1);
2354 ++frm_nxt;
2355 }
2356 else if (c1 < 0xC2)
2357 {
2358 return codecvt_base::error;
2359 }
2360 else if (c1 < 0xE0)
2361 {
2362 if (frm_end-frm_nxt < 2)
2363 return codecvt_base::partial;
2364 uint8_t c2 = frm_nxt[1];
2365 if ((c2 & 0xC0) != 0x80)
2366 return codecvt_base::error;
2367 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2368 | (c2 & 0x3F));
2369 if (t > Maxcode)
2370 return codecvt_base::error;
2371 *to_nxt = t;
2372 frm_nxt += 2;
2373 }
2374 else if (c1 < 0xF0)
2375 {
2376 if (frm_end-frm_nxt < 3)
2377 return codecvt_base::partial;
2378 uint8_t c2 = frm_nxt[1];
2379 uint8_t c3 = frm_nxt[2];
2380 switch (c1)
2381 {
2382 case 0xE0:
2383 if ((c2 & 0xE0) != 0xA0)
2384 return codecvt_base::error;
2385 break;
2386 case 0xED:
2387 if ((c2 & 0xE0) != 0x80)
2388 return codecvt_base::error;
2389 break;
2390 default:
2391 if ((c2 & 0xC0) != 0x80)
2392 return codecvt_base::error;
2393 break;
2394 }
2395 if ((c3 & 0xC0) != 0x80)
2396 return codecvt_base::error;
2397 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2398 | ((c2 & 0x3F) << 6)
2399 | (c3 & 0x3F));
2400 if (t > Maxcode)
2401 return codecvt_base::error;
2402 *to_nxt = t;
2403 frm_nxt += 3;
2404 }
2405 else if (c1 < 0xF5)
2406 {
2407 if (frm_end-frm_nxt < 4)
2408 return codecvt_base::partial;
2409 uint8_t c2 = frm_nxt[1];
2410 uint8_t c3 = frm_nxt[2];
2411 uint8_t c4 = frm_nxt[3];
2412 switch (c1)
2413 {
2414 case 0xF0:
2415 if (!(0x90 <= c2 && c2 <= 0xBF))
2416 return codecvt_base::error;
2417 break;
2418 case 0xF4:
2419 if ((c2 & 0xF0) != 0x80)
2420 return codecvt_base::error;
2421 break;
2422 default:
2423 if ((c2 & 0xC0) != 0x80)
2424 return codecvt_base::error;
2425 break;
2426 }
2427 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2428 return codecvt_base::error;
2429 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2430 | ((c2 & 0x3F) << 12)
2431 | ((c3 & 0x3F) << 6)
2432 | (c4 & 0x3F));
2433 if (t > Maxcode)
2434 return codecvt_base::error;
2435 *to_nxt = t;
2436 frm_nxt += 4;
2437 }
2438 else
2439 {
2440 return codecvt_base::error;
2441 }
2442 }
2443 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2444}
2445
2446static
2447int
2448utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2449 size_t mx, unsigned long Maxcode = 0x10FFFF,
2450 codecvt_mode mode = codecvt_mode(0))
2451{
2452 const uint8_t* frm_nxt = frm;
2453 if (mode & consume_header)
2454 {
2455 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2456 frm_nxt[2] == 0xBF)
2457 frm_nxt += 3;
2458 }
2459 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2460 {
2461 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2462 if (c1 < 0x80)
2463 {
2464 if (c1 > Maxcode)
2465 break;
2466 ++frm_nxt;
2467 }
2468 else if (c1 < 0xC2)
2469 {
2470 break;
2471 }
2472 else if (c1 < 0xE0)
2473 {
2474 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2475 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002476 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002477 break;
2478 frm_nxt += 2;
2479 }
2480 else if (c1 < 0xF0)
2481 {
2482 if (frm_end-frm_nxt < 3)
2483 break;
2484 uint8_t c2 = frm_nxt[1];
2485 uint8_t c3 = frm_nxt[2];
2486 switch (c1)
2487 {
2488 case 0xE0:
2489 if ((c2 & 0xE0) != 0xA0)
2490 return static_cast<int>(frm_nxt - frm);
2491 break;
2492 case 0xED:
2493 if ((c2 & 0xE0) != 0x80)
2494 return static_cast<int>(frm_nxt - frm);
2495 break;
2496 default:
2497 if ((c2 & 0xC0) != 0x80)
2498 return static_cast<int>(frm_nxt - frm);
2499 break;
2500 }
2501 if ((c3 & 0xC0) != 0x80)
2502 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002503 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002504 break;
2505 frm_nxt += 3;
2506 }
2507 else if (c1 < 0xF5)
2508 {
2509 if (frm_end-frm_nxt < 4)
2510 break;
2511 uint8_t c2 = frm_nxt[1];
2512 uint8_t c3 = frm_nxt[2];
2513 uint8_t c4 = frm_nxt[3];
2514 switch (c1)
2515 {
2516 case 0xF0:
2517 if (!(0x90 <= c2 && c2 <= 0xBF))
2518 return static_cast<int>(frm_nxt - frm);
2519 break;
2520 case 0xF4:
2521 if ((c2 & 0xF0) != 0x80)
2522 return static_cast<int>(frm_nxt - frm);
2523 break;
2524 default:
2525 if ((c2 & 0xC0) != 0x80)
2526 return static_cast<int>(frm_nxt - frm);
2527 break;
2528 }
2529 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2530 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002531 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2532 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002533 break;
2534 frm_nxt += 4;
2535 }
2536 else
2537 {
2538 break;
2539 }
2540 }
2541 return static_cast<int>(frm_nxt - frm);
2542}
2543
2544static
2545codecvt_base::result
2546ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2547 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2548 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2549{
2550 frm_nxt = frm;
2551 to_nxt = to;
2552 if (mode & generate_header)
2553 {
2554 if (to_end-to_nxt < 3)
2555 return codecvt_base::partial;
2556 *to_nxt++ = static_cast<uint8_t>(0xEF);
2557 *to_nxt++ = static_cast<uint8_t>(0xBB);
2558 *to_nxt++ = static_cast<uint8_t>(0xBF);
2559 }
2560 for (; frm_nxt < frm_end; ++frm_nxt)
2561 {
2562 uint16_t wc = *frm_nxt;
2563 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2564 return codecvt_base::error;
2565 if (wc < 0x0080)
2566 {
2567 if (to_end-to_nxt < 1)
2568 return codecvt_base::partial;
2569 *to_nxt++ = static_cast<uint8_t>(wc);
2570 }
2571 else if (wc < 0x0800)
2572 {
2573 if (to_end-to_nxt < 2)
2574 return codecvt_base::partial;
2575 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2576 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2577 }
2578 else // if (wc <= 0xFFFF)
2579 {
2580 if (to_end-to_nxt < 3)
2581 return codecvt_base::partial;
2582 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2583 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2584 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2585 }
2586 }
2587 return codecvt_base::ok;
2588}
2589
2590static
2591codecvt_base::result
2592utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2593 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2594 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2595{
2596 frm_nxt = frm;
2597 to_nxt = to;
2598 if (mode & consume_header)
2599 {
2600 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2601 frm_nxt[2] == 0xBF)
2602 frm_nxt += 3;
2603 }
2604 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2605 {
2606 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2607 if (c1 < 0x80)
2608 {
2609 if (c1 > Maxcode)
2610 return codecvt_base::error;
2611 *to_nxt = static_cast<uint16_t>(c1);
2612 ++frm_nxt;
2613 }
2614 else if (c1 < 0xC2)
2615 {
2616 return codecvt_base::error;
2617 }
2618 else if (c1 < 0xE0)
2619 {
2620 if (frm_end-frm_nxt < 2)
2621 return codecvt_base::partial;
2622 uint8_t c2 = frm_nxt[1];
2623 if ((c2 & 0xC0) != 0x80)
2624 return codecvt_base::error;
2625 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2626 | (c2 & 0x3F));
2627 if (t > Maxcode)
2628 return codecvt_base::error;
2629 *to_nxt = t;
2630 frm_nxt += 2;
2631 }
2632 else if (c1 < 0xF0)
2633 {
2634 if (frm_end-frm_nxt < 3)
2635 return codecvt_base::partial;
2636 uint8_t c2 = frm_nxt[1];
2637 uint8_t c3 = frm_nxt[2];
2638 switch (c1)
2639 {
2640 case 0xE0:
2641 if ((c2 & 0xE0) != 0xA0)
2642 return codecvt_base::error;
2643 break;
2644 case 0xED:
2645 if ((c2 & 0xE0) != 0x80)
2646 return codecvt_base::error;
2647 break;
2648 default:
2649 if ((c2 & 0xC0) != 0x80)
2650 return codecvt_base::error;
2651 break;
2652 }
2653 if ((c3 & 0xC0) != 0x80)
2654 return codecvt_base::error;
2655 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2656 | ((c2 & 0x3F) << 6)
2657 | (c3 & 0x3F));
2658 if (t > Maxcode)
2659 return codecvt_base::error;
2660 *to_nxt = t;
2661 frm_nxt += 3;
2662 }
2663 else
2664 {
2665 return codecvt_base::error;
2666 }
2667 }
2668 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2669}
2670
2671static
2672int
2673utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2674 size_t mx, unsigned long Maxcode = 0x10FFFF,
2675 codecvt_mode mode = codecvt_mode(0))
2676{
2677 const uint8_t* frm_nxt = frm;
2678 if (mode & consume_header)
2679 {
2680 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2681 frm_nxt[2] == 0xBF)
2682 frm_nxt += 3;
2683 }
2684 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2685 {
2686 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2687 if (c1 < 0x80)
2688 {
2689 if (c1 > Maxcode)
2690 break;
2691 ++frm_nxt;
2692 }
2693 else if (c1 < 0xC2)
2694 {
2695 break;
2696 }
2697 else if (c1 < 0xE0)
2698 {
2699 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2700 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002701 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002702 break;
2703 frm_nxt += 2;
2704 }
2705 else if (c1 < 0xF0)
2706 {
2707 if (frm_end-frm_nxt < 3)
2708 break;
2709 uint8_t c2 = frm_nxt[1];
2710 uint8_t c3 = frm_nxt[2];
2711 switch (c1)
2712 {
2713 case 0xE0:
2714 if ((c2 & 0xE0) != 0xA0)
2715 return static_cast<int>(frm_nxt - frm);
2716 break;
2717 case 0xED:
2718 if ((c2 & 0xE0) != 0x80)
2719 return static_cast<int>(frm_nxt - frm);
2720 break;
2721 default:
2722 if ((c2 & 0xC0) != 0x80)
2723 return static_cast<int>(frm_nxt - frm);
2724 break;
2725 }
2726 if ((c3 & 0xC0) != 0x80)
2727 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002728 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002729 break;
2730 frm_nxt += 3;
2731 }
2732 else
2733 {
2734 break;
2735 }
2736 }
2737 return static_cast<int>(frm_nxt - frm);
2738}
2739
2740static
2741codecvt_base::result
2742ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2743 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2744 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2745{
2746 frm_nxt = frm;
2747 to_nxt = to;
2748 if (mode & generate_header)
2749 {
2750 if (to_end-to_nxt < 2)
2751 return codecvt_base::partial;
2752 *to_nxt++ = static_cast<uint8_t>(0xFE);
2753 *to_nxt++ = static_cast<uint8_t>(0xFF);
2754 }
2755 for (; frm_nxt < frm_end; ++frm_nxt)
2756 {
2757 uint32_t wc = *frm_nxt;
2758 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2759 return codecvt_base::error;
2760 if (wc < 0x010000)
2761 {
2762 if (to_end-to_nxt < 2)
2763 return codecvt_base::partial;
2764 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2765 *to_nxt++ = static_cast<uint8_t>(wc);
2766 }
2767 else
2768 {
2769 if (to_end-to_nxt < 4)
2770 return codecvt_base::partial;
2771 uint16_t t = static_cast<uint16_t>(
2772 0xD800
2773 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2774 | ((wc & 0x00FC00) >> 10));
2775 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2776 *to_nxt++ = static_cast<uint8_t>(t);
2777 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2778 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2779 *to_nxt++ = static_cast<uint8_t>(t);
2780 }
2781 }
2782 return codecvt_base::ok;
2783}
2784
2785static
2786codecvt_base::result
2787utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2788 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2789 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2790{
2791 frm_nxt = frm;
2792 to_nxt = to;
2793 if (mode & consume_header)
2794 {
2795 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2796 frm_nxt += 2;
2797 }
2798 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2799 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002800 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002801 if ((c1 & 0xFC00) == 0xDC00)
2802 return codecvt_base::error;
2803 if ((c1 & 0xFC00) != 0xD800)
2804 {
2805 if (c1 > Maxcode)
2806 return codecvt_base::error;
2807 *to_nxt = static_cast<uint32_t>(c1);
2808 frm_nxt += 2;
2809 }
2810 else
2811 {
2812 if (frm_end-frm_nxt < 4)
2813 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002814 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002815 if ((c2 & 0xFC00) != 0xDC00)
2816 return codecvt_base::error;
2817 uint32_t t = static_cast<uint32_t>(
2818 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2819 | ((c1 & 0x003F) << 10)
2820 | (c2 & 0x03FF));
2821 if (t > Maxcode)
2822 return codecvt_base::error;
2823 *to_nxt = t;
2824 frm_nxt += 4;
2825 }
2826 }
2827 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2828}
2829
2830static
2831int
2832utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2833 size_t mx, unsigned long Maxcode = 0x10FFFF,
2834 codecvt_mode mode = codecvt_mode(0))
2835{
2836 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002837 if (mode & consume_header)
2838 {
2839 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2840 frm_nxt += 2;
2841 }
2842 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2843 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002844 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002845 if ((c1 & 0xFC00) == 0xDC00)
2846 break;
2847 if ((c1 & 0xFC00) != 0xD800)
2848 {
2849 if (c1 > Maxcode)
2850 break;
2851 frm_nxt += 2;
2852 }
2853 else
2854 {
2855 if (frm_end-frm_nxt < 4)
2856 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002857 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002858 if ((c2 & 0xFC00) != 0xDC00)
2859 break;
2860 uint32_t t = static_cast<uint32_t>(
2861 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2862 | ((c1 & 0x003F) << 10)
2863 | (c2 & 0x03FF));
2864 if (t > Maxcode)
2865 break;
2866 frm_nxt += 4;
2867 }
2868 }
2869 return static_cast<int>(frm_nxt - frm);
2870}
2871
2872static
2873codecvt_base::result
2874ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2875 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2876 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2877{
2878 frm_nxt = frm;
2879 to_nxt = to;
2880 if (mode & generate_header)
2881 {
2882 if (to_end-to_nxt < 2)
2883 return codecvt_base::partial;
2884 *to_nxt++ = static_cast<uint8_t>(0xFF);
2885 *to_nxt++ = static_cast<uint8_t>(0xFE);
2886 }
2887 for (; frm_nxt < frm_end; ++frm_nxt)
2888 {
2889 uint32_t wc = *frm_nxt;
2890 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2891 return codecvt_base::error;
2892 if (wc < 0x010000)
2893 {
2894 if (to_end-to_nxt < 2)
2895 return codecvt_base::partial;
2896 *to_nxt++ = static_cast<uint8_t>(wc);
2897 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2898 }
2899 else
2900 {
2901 if (to_end-to_nxt < 4)
2902 return codecvt_base::partial;
2903 uint16_t t = static_cast<uint16_t>(
2904 0xD800
2905 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2906 | ((wc & 0x00FC00) >> 10));
2907 *to_nxt++ = static_cast<uint8_t>(t);
2908 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2909 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2910 *to_nxt++ = static_cast<uint8_t>(t);
2911 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2912 }
2913 }
2914 return codecvt_base::ok;
2915}
2916
2917static
2918codecvt_base::result
2919utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2920 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2921 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2922{
2923 frm_nxt = frm;
2924 to_nxt = to;
2925 if (mode & consume_header)
2926 {
2927 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2928 frm_nxt += 2;
2929 }
2930 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2931 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002932 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002933 if ((c1 & 0xFC00) == 0xDC00)
2934 return codecvt_base::error;
2935 if ((c1 & 0xFC00) != 0xD800)
2936 {
2937 if (c1 > Maxcode)
2938 return codecvt_base::error;
2939 *to_nxt = static_cast<uint32_t>(c1);
2940 frm_nxt += 2;
2941 }
2942 else
2943 {
2944 if (frm_end-frm_nxt < 4)
2945 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002946 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002947 if ((c2 & 0xFC00) != 0xDC00)
2948 return codecvt_base::error;
2949 uint32_t t = static_cast<uint32_t>(
2950 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2951 | ((c1 & 0x003F) << 10)
2952 | (c2 & 0x03FF));
2953 if (t > Maxcode)
2954 return codecvt_base::error;
2955 *to_nxt = t;
2956 frm_nxt += 4;
2957 }
2958 }
2959 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2960}
2961
2962static
2963int
2964utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2965 size_t mx, unsigned long Maxcode = 0x10FFFF,
2966 codecvt_mode mode = codecvt_mode(0))
2967{
2968 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002969 if (mode & consume_header)
2970 {
2971 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2972 frm_nxt += 2;
2973 }
2974 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2975 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002976 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002977 if ((c1 & 0xFC00) == 0xDC00)
2978 break;
2979 if ((c1 & 0xFC00) != 0xD800)
2980 {
2981 if (c1 > Maxcode)
2982 break;
2983 frm_nxt += 2;
2984 }
2985 else
2986 {
2987 if (frm_end-frm_nxt < 4)
2988 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002989 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002990 if ((c2 & 0xFC00) != 0xDC00)
2991 break;
2992 uint32_t t = static_cast<uint32_t>(
2993 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2994 | ((c1 & 0x003F) << 10)
2995 | (c2 & 0x03FF));
2996 if (t > Maxcode)
2997 break;
2998 frm_nxt += 4;
2999 }
3000 }
3001 return static_cast<int>(frm_nxt - frm);
3002}
3003
3004static
3005codecvt_base::result
3006ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3007 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3008 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3009{
3010 frm_nxt = frm;
3011 to_nxt = to;
3012 if (mode & generate_header)
3013 {
3014 if (to_end-to_nxt < 2)
3015 return codecvt_base::partial;
3016 *to_nxt++ = static_cast<uint8_t>(0xFE);
3017 *to_nxt++ = static_cast<uint8_t>(0xFF);
3018 }
3019 for (; frm_nxt < frm_end; ++frm_nxt)
3020 {
3021 uint16_t wc = *frm_nxt;
3022 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3023 return codecvt_base::error;
3024 if (to_end-to_nxt < 2)
3025 return codecvt_base::partial;
3026 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3027 *to_nxt++ = static_cast<uint8_t>(wc);
3028 }
3029 return codecvt_base::ok;
3030}
3031
3032static
3033codecvt_base::result
3034utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3035 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3036 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3037{
3038 frm_nxt = frm;
3039 to_nxt = to;
3040 if (mode & consume_header)
3041 {
3042 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3043 frm_nxt += 2;
3044 }
3045 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3046 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003047 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003048 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3049 return codecvt_base::error;
3050 *to_nxt = c1;
3051 frm_nxt += 2;
3052 }
3053 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3054}
3055
3056static
3057int
3058utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3059 size_t mx, unsigned long Maxcode = 0x10FFFF,
3060 codecvt_mode mode = codecvt_mode(0))
3061{
3062 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003063 if (mode & consume_header)
3064 {
3065 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3066 frm_nxt += 2;
3067 }
3068 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3069 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003070 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003071 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3072 break;
3073 frm_nxt += 2;
3074 }
3075 return static_cast<int>(frm_nxt - frm);
3076}
3077
3078static
3079codecvt_base::result
3080ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3081 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3082 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3083{
3084 frm_nxt = frm;
3085 to_nxt = to;
3086 if (mode & generate_header)
3087 {
3088 if (to_end-to_nxt < 2)
3089 return codecvt_base::partial;
3090 *to_nxt++ = static_cast<uint8_t>(0xFF);
3091 *to_nxt++ = static_cast<uint8_t>(0xFE);
3092 }
3093 for (; frm_nxt < frm_end; ++frm_nxt)
3094 {
3095 uint16_t wc = *frm_nxt;
3096 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3097 return codecvt_base::error;
3098 if (to_end-to_nxt < 2)
3099 return codecvt_base::partial;
3100 *to_nxt++ = static_cast<uint8_t>(wc);
3101 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3102 }
3103 return codecvt_base::ok;
3104}
3105
3106static
3107codecvt_base::result
3108utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3109 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3110 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3111{
3112 frm_nxt = frm;
3113 to_nxt = to;
3114 if (mode & consume_header)
3115 {
3116 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3117 frm_nxt += 2;
3118 }
3119 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3120 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003121 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003122 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3123 return codecvt_base::error;
3124 *to_nxt = c1;
3125 frm_nxt += 2;
3126 }
3127 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3128}
3129
3130static
3131int
3132utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3133 size_t mx, unsigned long Maxcode = 0x10FFFF,
3134 codecvt_mode mode = codecvt_mode(0))
3135{
3136 const uint8_t* frm_nxt = frm;
3137 frm_nxt = frm;
3138 if (mode & consume_header)
3139 {
3140 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3141 frm_nxt += 2;
3142 }
3143 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3144 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003145 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003146 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3147 break;
3148 frm_nxt += 2;
3149 }
3150 return static_cast<int>(frm_nxt - frm);
3151}
3152
Howard Hinnantc51e1022010-05-11 19:42:16 +00003153// template <> class codecvt<char16_t, char, mbstate_t>
3154
Howard Hinnantffb308e2010-08-22 00:03:27 +00003155locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003156
3157codecvt<char16_t, char, mbstate_t>::~codecvt()
3158{
3159}
3160
3161codecvt<char16_t, char, mbstate_t>::result
3162codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003163 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003164 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3165{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003166 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3167 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3168 const uint16_t* _frm_nxt = _frm;
3169 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3170 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3171 uint8_t* _to_nxt = _to;
3172 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3173 frm_nxt = frm + (_frm_nxt - _frm);
3174 to_nxt = to + (_to_nxt - _to);
3175 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003176}
3177
3178codecvt<char16_t, char, mbstate_t>::result
3179codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003180 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003181 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3182{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003183 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3184 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3185 const uint8_t* _frm_nxt = _frm;
3186 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3187 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3188 uint16_t* _to_nxt = _to;
3189 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3190 frm_nxt = frm + (_frm_nxt - _frm);
3191 to_nxt = to + (_to_nxt - _to);
3192 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003193}
3194
3195codecvt<char16_t, char, mbstate_t>::result
3196codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3197 extern_type* to, extern_type*, extern_type*& to_nxt) const
3198{
3199 to_nxt = to;
3200 return noconv;
3201}
3202
3203int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003204codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003205{
3206 return 0;
3207}
3208
3209bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003210codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003211{
3212 return false;
3213}
3214
3215int
3216codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3217 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3218{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003219 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3220 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3221 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003222}
3223
3224int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003225codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003226{
3227 return 4;
3228}
3229
3230// template <> class codecvt<char32_t, char, mbstate_t>
3231
Howard Hinnantffb308e2010-08-22 00:03:27 +00003232locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003233
3234codecvt<char32_t, char, mbstate_t>::~codecvt()
3235{
3236}
3237
3238codecvt<char32_t, char, mbstate_t>::result
3239codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003240 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003241 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3242{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003243 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3244 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3245 const uint32_t* _frm_nxt = _frm;
3246 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3247 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3248 uint8_t* _to_nxt = _to;
3249 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3250 frm_nxt = frm + (_frm_nxt - _frm);
3251 to_nxt = to + (_to_nxt - _to);
3252 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003253}
3254
3255codecvt<char32_t, char, mbstate_t>::result
3256codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003257 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003258 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3259{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003260 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3261 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3262 const uint8_t* _frm_nxt = _frm;
3263 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3264 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3265 uint32_t* _to_nxt = _to;
3266 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3267 frm_nxt = frm + (_frm_nxt - _frm);
3268 to_nxt = to + (_to_nxt - _to);
3269 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003270}
3271
3272codecvt<char32_t, char, mbstate_t>::result
3273codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3274 extern_type* to, extern_type*, extern_type*& to_nxt) const
3275{
3276 to_nxt = to;
3277 return noconv;
3278}
3279
3280int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003281codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003282{
3283 return 0;
3284}
3285
3286bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003287codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003288{
3289 return false;
3290}
3291
3292int
3293codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3294 const extern_type* frm, const extern_type* frm_end, size_t mx) 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 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003299}
3300
3301int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003302codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003303{
3304 return 4;
3305}
3306
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003307// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003308
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003309__codecvt_utf8<wchar_t>::result
3310__codecvt_utf8<wchar_t>::do_out(state_type&,
3311 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003312 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3313{
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003314#if _WIN32
3315 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3316 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3317 const uint16_t* _frm_nxt = _frm;
3318#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003319 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3320 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3321 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003322#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003323 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3324 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3325 uint8_t* _to_nxt = _to;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003326#if _WIN32
3327 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3328 _Maxcode_, _Mode_);
3329#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003330 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3331 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003332#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003333 frm_nxt = frm + (_frm_nxt - _frm);
3334 to_nxt = to + (_to_nxt - _to);
3335 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003336}
3337
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003338__codecvt_utf8<wchar_t>::result
3339__codecvt_utf8<wchar_t>::do_in(state_type&,
3340 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003341 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3342{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003343 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3344 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3345 const uint8_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003346#if _WIN32
3347 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3348 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3349 uint16_t* _to_nxt = _to;
3350 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3351 _Maxcode_, _Mode_);
3352#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003353 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3354 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3355 uint32_t* _to_nxt = _to;
3356 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3357 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003358#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003359 frm_nxt = frm + (_frm_nxt - _frm);
3360 to_nxt = to + (_to_nxt - _to);
3361 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003362}
3363
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003364__codecvt_utf8<wchar_t>::result
3365__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003366 extern_type* to, extern_type*, extern_type*& to_nxt) const
3367{
3368 to_nxt = to;
3369 return noconv;
3370}
3371
3372int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003373__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003374{
3375 return 0;
3376}
3377
3378bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003379__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003380{
3381 return false;
3382}
3383
3384int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003385__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003386 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3387{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003388 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3389 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3390 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003391}
3392
3393int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003394__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003395{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003396 if (_Mode_ & consume_header)
3397 return 7;
3398 return 4;
3399}
3400
3401// __codecvt_utf8<char16_t>
3402
3403__codecvt_utf8<char16_t>::result
3404__codecvt_utf8<char16_t>::do_out(state_type&,
3405 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3406 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3407{
3408 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3409 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3410 const uint16_t* _frm_nxt = _frm;
3411 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3412 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3413 uint8_t* _to_nxt = _to;
3414 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3415 _Maxcode_, _Mode_);
3416 frm_nxt = frm + (_frm_nxt - _frm);
3417 to_nxt = to + (_to_nxt - _to);
3418 return r;
3419}
3420
3421__codecvt_utf8<char16_t>::result
3422__codecvt_utf8<char16_t>::do_in(state_type&,
3423 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3424 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3425{
3426 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3427 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3428 const uint8_t* _frm_nxt = _frm;
3429 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3430 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3431 uint16_t* _to_nxt = _to;
3432 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3433 _Maxcode_, _Mode_);
3434 frm_nxt = frm + (_frm_nxt - _frm);
3435 to_nxt = to + (_to_nxt - _to);
3436 return r;
3437}
3438
3439__codecvt_utf8<char16_t>::result
3440__codecvt_utf8<char16_t>::do_unshift(state_type&,
3441 extern_type* to, extern_type*, extern_type*& to_nxt) const
3442{
3443 to_nxt = to;
3444 return noconv;
3445}
3446
3447int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003448__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003449{
3450 return 0;
3451}
3452
3453bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003454__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003455{
3456 return false;
3457}
3458
3459int
3460__codecvt_utf8<char16_t>::do_length(state_type&,
3461 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3462{
3463 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3464 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3465 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3466}
3467
3468int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003469__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003470{
3471 if (_Mode_ & consume_header)
3472 return 6;
3473 return 3;
3474}
3475
3476// __codecvt_utf8<char32_t>
3477
3478__codecvt_utf8<char32_t>::result
3479__codecvt_utf8<char32_t>::do_out(state_type&,
3480 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3481 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3482{
3483 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3484 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3485 const uint32_t* _frm_nxt = _frm;
3486 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3487 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3488 uint8_t* _to_nxt = _to;
3489 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3490 _Maxcode_, _Mode_);
3491 frm_nxt = frm + (_frm_nxt - _frm);
3492 to_nxt = to + (_to_nxt - _to);
3493 return r;
3494}
3495
3496__codecvt_utf8<char32_t>::result
3497__codecvt_utf8<char32_t>::do_in(state_type&,
3498 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3499 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3500{
3501 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3502 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3503 const uint8_t* _frm_nxt = _frm;
3504 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3505 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3506 uint32_t* _to_nxt = _to;
3507 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3508 _Maxcode_, _Mode_);
3509 frm_nxt = frm + (_frm_nxt - _frm);
3510 to_nxt = to + (_to_nxt - _to);
3511 return r;
3512}
3513
3514__codecvt_utf8<char32_t>::result
3515__codecvt_utf8<char32_t>::do_unshift(state_type&,
3516 extern_type* to, extern_type*, extern_type*& to_nxt) const
3517{
3518 to_nxt = to;
3519 return noconv;
3520}
3521
3522int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003523__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003524{
3525 return 0;
3526}
3527
3528bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003529__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003530{
3531 return false;
3532}
3533
3534int
3535__codecvt_utf8<char32_t>::do_length(state_type&,
3536 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3537{
3538 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3539 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3540 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3541}
3542
3543int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003544__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003545{
3546 if (_Mode_ & consume_header)
3547 return 7;
3548 return 4;
3549}
3550
3551// __codecvt_utf16<wchar_t, false>
3552
3553__codecvt_utf16<wchar_t, false>::result
3554__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3555 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3556 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3557{
3558 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3559 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3560 const uint32_t* _frm_nxt = _frm;
3561 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3562 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3563 uint8_t* _to_nxt = _to;
3564 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3565 _Maxcode_, _Mode_);
3566 frm_nxt = frm + (_frm_nxt - _frm);
3567 to_nxt = to + (_to_nxt - _to);
3568 return r;
3569}
3570
3571__codecvt_utf16<wchar_t, false>::result
3572__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3573 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3574 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3575{
3576 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3577 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3578 const uint8_t* _frm_nxt = _frm;
3579 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3580 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3581 uint32_t* _to_nxt = _to;
3582 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3583 _Maxcode_, _Mode_);
3584 frm_nxt = frm + (_frm_nxt - _frm);
3585 to_nxt = to + (_to_nxt - _to);
3586 return r;
3587}
3588
3589__codecvt_utf16<wchar_t, false>::result
3590__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3591 extern_type* to, extern_type*, extern_type*& to_nxt) const
3592{
3593 to_nxt = to;
3594 return noconv;
3595}
3596
3597int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003598__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003599{
3600 return 0;
3601}
3602
3603bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003604__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003605{
3606 return false;
3607}
3608
3609int
3610__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3611 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3612{
3613 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3614 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3615 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3616}
3617
3618int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003619__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003620{
3621 if (_Mode_ & consume_header)
3622 return 6;
3623 return 4;
3624}
3625
3626// __codecvt_utf16<wchar_t, true>
3627
3628__codecvt_utf16<wchar_t, true>::result
3629__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3630 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3631 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3632{
3633 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3634 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3635 const uint32_t* _frm_nxt = _frm;
3636 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3637 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3638 uint8_t* _to_nxt = _to;
3639 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3640 _Maxcode_, _Mode_);
3641 frm_nxt = frm + (_frm_nxt - _frm);
3642 to_nxt = to + (_to_nxt - _to);
3643 return r;
3644}
3645
3646__codecvt_utf16<wchar_t, true>::result
3647__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3648 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3649 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3650{
3651 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3652 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3653 const uint8_t* _frm_nxt = _frm;
3654 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3655 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3656 uint32_t* _to_nxt = _to;
3657 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3658 _Maxcode_, _Mode_);
3659 frm_nxt = frm + (_frm_nxt - _frm);
3660 to_nxt = to + (_to_nxt - _to);
3661 return r;
3662}
3663
3664__codecvt_utf16<wchar_t, true>::result
3665__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3666 extern_type* to, extern_type*, extern_type*& to_nxt) const
3667{
3668 to_nxt = to;
3669 return noconv;
3670}
3671
3672int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003673__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003674{
3675 return 0;
3676}
3677
3678bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003679__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003680{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003681 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003682}
3683
3684int
3685__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3686 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3687{
3688 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3689 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3690 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3691}
3692
3693int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003694__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003695{
3696 if (_Mode_ & consume_header)
3697 return 6;
3698 return 4;
3699}
3700
3701// __codecvt_utf16<char16_t, false>
3702
3703__codecvt_utf16<char16_t, false>::result
3704__codecvt_utf16<char16_t, false>::do_out(state_type&,
3705 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3706 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3707{
3708 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3709 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3710 const uint16_t* _frm_nxt = _frm;
3711 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3712 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3713 uint8_t* _to_nxt = _to;
3714 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3715 _Maxcode_, _Mode_);
3716 frm_nxt = frm + (_frm_nxt - _frm);
3717 to_nxt = to + (_to_nxt - _to);
3718 return r;
3719}
3720
3721__codecvt_utf16<char16_t, false>::result
3722__codecvt_utf16<char16_t, false>::do_in(state_type&,
3723 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3724 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3725{
3726 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3727 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3728 const uint8_t* _frm_nxt = _frm;
3729 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3730 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3731 uint16_t* _to_nxt = _to;
3732 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3733 _Maxcode_, _Mode_);
3734 frm_nxt = frm + (_frm_nxt - _frm);
3735 to_nxt = to + (_to_nxt - _to);
3736 return r;
3737}
3738
3739__codecvt_utf16<char16_t, false>::result
3740__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3741 extern_type* to, extern_type*, extern_type*& to_nxt) const
3742{
3743 to_nxt = to;
3744 return noconv;
3745}
3746
3747int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003748__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003749{
3750 return 0;
3751}
3752
3753bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003754__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003755{
3756 return false;
3757}
3758
3759int
3760__codecvt_utf16<char16_t, false>::do_length(state_type&,
3761 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3762{
3763 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3764 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3765 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3766}
3767
3768int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003769__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003770{
3771 if (_Mode_ & consume_header)
3772 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003773 return 2;
3774}
3775
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003776// __codecvt_utf16<char16_t, true>
3777
3778__codecvt_utf16<char16_t, true>::result
3779__codecvt_utf16<char16_t, true>::do_out(state_type&,
3780 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3781 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3782{
3783 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3784 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3785 const uint16_t* _frm_nxt = _frm;
3786 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3787 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3788 uint8_t* _to_nxt = _to;
3789 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3790 _Maxcode_, _Mode_);
3791 frm_nxt = frm + (_frm_nxt - _frm);
3792 to_nxt = to + (_to_nxt - _to);
3793 return r;
3794}
3795
3796__codecvt_utf16<char16_t, true>::result
3797__codecvt_utf16<char16_t, true>::do_in(state_type&,
3798 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3799 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3800{
3801 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3802 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3803 const uint8_t* _frm_nxt = _frm;
3804 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3805 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3806 uint16_t* _to_nxt = _to;
3807 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3808 _Maxcode_, _Mode_);
3809 frm_nxt = frm + (_frm_nxt - _frm);
3810 to_nxt = to + (_to_nxt - _to);
3811 return r;
3812}
3813
3814__codecvt_utf16<char16_t, true>::result
3815__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3816 extern_type* to, extern_type*, extern_type*& to_nxt) const
3817{
3818 to_nxt = to;
3819 return noconv;
3820}
3821
3822int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003823__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003824{
3825 return 0;
3826}
3827
3828bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003829__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003830{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003831 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003832}
3833
3834int
3835__codecvt_utf16<char16_t, true>::do_length(state_type&,
3836 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3837{
3838 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3839 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3840 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3841}
3842
3843int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003844__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003845{
3846 if (_Mode_ & consume_header)
3847 return 4;
3848 return 2;
3849}
3850
3851// __codecvt_utf16<char32_t, false>
3852
3853__codecvt_utf16<char32_t, false>::result
3854__codecvt_utf16<char32_t, false>::do_out(state_type&,
3855 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3856 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3857{
3858 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3859 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3860 const uint32_t* _frm_nxt = _frm;
3861 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3862 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3863 uint8_t* _to_nxt = _to;
3864 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3865 _Maxcode_, _Mode_);
3866 frm_nxt = frm + (_frm_nxt - _frm);
3867 to_nxt = to + (_to_nxt - _to);
3868 return r;
3869}
3870
3871__codecvt_utf16<char32_t, false>::result
3872__codecvt_utf16<char32_t, false>::do_in(state_type&,
3873 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3874 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3875{
3876 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3877 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3878 const uint8_t* _frm_nxt = _frm;
3879 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3880 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3881 uint32_t* _to_nxt = _to;
3882 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3883 _Maxcode_, _Mode_);
3884 frm_nxt = frm + (_frm_nxt - _frm);
3885 to_nxt = to + (_to_nxt - _to);
3886 return r;
3887}
3888
3889__codecvt_utf16<char32_t, false>::result
3890__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3891 extern_type* to, extern_type*, extern_type*& to_nxt) const
3892{
3893 to_nxt = to;
3894 return noconv;
3895}
3896
3897int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003898__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003899{
3900 return 0;
3901}
3902
3903bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003904__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003905{
3906 return false;
3907}
3908
3909int
3910__codecvt_utf16<char32_t, false>::do_length(state_type&,
3911 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3912{
3913 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3914 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3915 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3916}
3917
3918int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003919__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003920{
3921 if (_Mode_ & consume_header)
3922 return 6;
3923 return 4;
3924}
3925
3926// __codecvt_utf16<char32_t, true>
3927
3928__codecvt_utf16<char32_t, true>::result
3929__codecvt_utf16<char32_t, true>::do_out(state_type&,
3930 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3931 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3932{
3933 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3934 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3935 const uint32_t* _frm_nxt = _frm;
3936 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3937 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3938 uint8_t* _to_nxt = _to;
3939 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3940 _Maxcode_, _Mode_);
3941 frm_nxt = frm + (_frm_nxt - _frm);
3942 to_nxt = to + (_to_nxt - _to);
3943 return r;
3944}
3945
3946__codecvt_utf16<char32_t, true>::result
3947__codecvt_utf16<char32_t, true>::do_in(state_type&,
3948 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3949 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3950{
3951 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3952 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3953 const uint8_t* _frm_nxt = _frm;
3954 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3955 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3956 uint32_t* _to_nxt = _to;
3957 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3958 _Maxcode_, _Mode_);
3959 frm_nxt = frm + (_frm_nxt - _frm);
3960 to_nxt = to + (_to_nxt - _to);
3961 return r;
3962}
3963
3964__codecvt_utf16<char32_t, true>::result
3965__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3966 extern_type* to, extern_type*, extern_type*& to_nxt) const
3967{
3968 to_nxt = to;
3969 return noconv;
3970}
3971
3972int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003973__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003974{
3975 return 0;
3976}
3977
3978bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003979__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003980{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003981 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003982}
3983
3984int
3985__codecvt_utf16<char32_t, true>::do_length(state_type&,
3986 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3987{
3988 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3989 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3990 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3991}
3992
3993int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003994__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003995{
3996 if (_Mode_ & consume_header)
3997 return 6;
3998 return 4;
3999}
4000
4001// __codecvt_utf8_utf16<wchar_t>
4002
4003__codecvt_utf8_utf16<wchar_t>::result
4004__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4005 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4006 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4007{
4008 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4009 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4010 const uint32_t* _frm_nxt = _frm;
4011 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4012 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4013 uint8_t* _to_nxt = _to;
4014 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4015 _Maxcode_, _Mode_);
4016 frm_nxt = frm + (_frm_nxt - _frm);
4017 to_nxt = to + (_to_nxt - _to);
4018 return r;
4019}
4020
4021__codecvt_utf8_utf16<wchar_t>::result
4022__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4023 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4024 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4025{
4026 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4027 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4028 const uint8_t* _frm_nxt = _frm;
4029 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4030 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4031 uint32_t* _to_nxt = _to;
4032 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4033 _Maxcode_, _Mode_);
4034 frm_nxt = frm + (_frm_nxt - _frm);
4035 to_nxt = to + (_to_nxt - _to);
4036 return r;
4037}
4038
4039__codecvt_utf8_utf16<wchar_t>::result
4040__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4041 extern_type* to, extern_type*, extern_type*& to_nxt) const
4042{
4043 to_nxt = to;
4044 return noconv;
4045}
4046
4047int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004048__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004049{
4050 return 0;
4051}
4052
4053bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004054__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004055{
4056 return false;
4057}
4058
4059int
4060__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4061 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4062{
4063 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4064 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4065 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4066}
4067
4068int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004069__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004070{
4071 if (_Mode_ & consume_header)
4072 return 7;
4073 return 4;
4074}
4075
4076// __codecvt_utf8_utf16<char16_t>
4077
4078__codecvt_utf8_utf16<char16_t>::result
4079__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4080 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4081 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4082{
4083 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4084 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4085 const uint16_t* _frm_nxt = _frm;
4086 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4087 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4088 uint8_t* _to_nxt = _to;
4089 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4090 _Maxcode_, _Mode_);
4091 frm_nxt = frm + (_frm_nxt - _frm);
4092 to_nxt = to + (_to_nxt - _to);
4093 return r;
4094}
4095
4096__codecvt_utf8_utf16<char16_t>::result
4097__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4098 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4099 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4100{
4101 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4102 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4103 const uint8_t* _frm_nxt = _frm;
4104 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4105 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4106 uint16_t* _to_nxt = _to;
4107 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4108 _Maxcode_, _Mode_);
4109 frm_nxt = frm + (_frm_nxt - _frm);
4110 to_nxt = to + (_to_nxt - _to);
4111 return r;
4112}
4113
4114__codecvt_utf8_utf16<char16_t>::result
4115__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4116 extern_type* to, extern_type*, extern_type*& to_nxt) const
4117{
4118 to_nxt = to;
4119 return noconv;
4120}
4121
4122int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004123__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004124{
4125 return 0;
4126}
4127
4128bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004129__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004130{
4131 return false;
4132}
4133
4134int
4135__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4136 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4137{
4138 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4139 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4140 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4141}
4142
4143int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004144__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004145{
4146 if (_Mode_ & consume_header)
4147 return 7;
4148 return 4;
4149}
4150
4151// __codecvt_utf8_utf16<char32_t>
4152
4153__codecvt_utf8_utf16<char32_t>::result
4154__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4155 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4156 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4157{
4158 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4159 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4160 const uint32_t* _frm_nxt = _frm;
4161 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4162 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4163 uint8_t* _to_nxt = _to;
4164 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4165 _Maxcode_, _Mode_);
4166 frm_nxt = frm + (_frm_nxt - _frm);
4167 to_nxt = to + (_to_nxt - _to);
4168 return r;
4169}
4170
4171__codecvt_utf8_utf16<char32_t>::result
4172__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4173 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4174 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4175{
4176 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4177 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4178 const uint8_t* _frm_nxt = _frm;
4179 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4180 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4181 uint32_t* _to_nxt = _to;
4182 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4183 _Maxcode_, _Mode_);
4184 frm_nxt = frm + (_frm_nxt - _frm);
4185 to_nxt = to + (_to_nxt - _to);
4186 return r;
4187}
4188
4189__codecvt_utf8_utf16<char32_t>::result
4190__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4191 extern_type* to, extern_type*, extern_type*& to_nxt) const
4192{
4193 to_nxt = to;
4194 return noconv;
4195}
4196
4197int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004198__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004199{
4200 return 0;
4201}
4202
4203bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004204__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004205{
4206 return false;
4207}
4208
4209int
4210__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4211 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4212{
4213 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4214 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4215 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4216}
4217
4218int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004219__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004220{
4221 if (_Mode_ & consume_header)
4222 return 7;
4223 return 4;
4224}
4225
Howard Hinnantc51e1022010-05-11 19:42:16 +00004226// __narrow_to_utf8<16>
4227
4228__narrow_to_utf8<16>::~__narrow_to_utf8()
4229{
4230}
4231
4232// __narrow_to_utf8<32>
4233
4234__narrow_to_utf8<32>::~__narrow_to_utf8()
4235{
4236}
4237
4238// __widen_from_utf8<16>
4239
4240__widen_from_utf8<16>::~__widen_from_utf8()
4241{
4242}
4243
4244// __widen_from_utf8<32>
4245
4246__widen_from_utf8<32>::~__widen_from_utf8()
4247{
4248}
4249
4250// numpunct<char> && numpunct<wchar_t>
4251
4252locale::id numpunct< char >::id;
4253locale::id numpunct<wchar_t>::id;
4254
4255numpunct<char>::numpunct(size_t refs)
4256 : locale::facet(refs),
4257 __decimal_point_('.'),
4258 __thousands_sep_(',')
4259{
4260}
4261
4262numpunct<wchar_t>::numpunct(size_t refs)
4263 : locale::facet(refs),
4264 __decimal_point_(L'.'),
4265 __thousands_sep_(L',')
4266{
4267}
4268
4269numpunct<char>::~numpunct()
4270{
4271}
4272
4273numpunct<wchar_t>::~numpunct()
4274{
4275}
4276
4277 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4278wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4279
4280 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4281wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4282
4283string numpunct< char >::do_grouping() const {return __grouping_;}
4284string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4285
4286 string numpunct< char >::do_truename() const {return "true";}
4287wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4288
4289 string numpunct< char >::do_falsename() const {return "false";}
4290wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4291
4292// numpunct_byname<char>
4293
4294numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4295 : numpunct<char>(refs)
4296{
4297 __init(nm);
4298}
4299
4300numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4301 : numpunct<char>(refs)
4302{
4303 __init(nm.c_str());
4304}
4305
4306numpunct_byname<char>::~numpunct_byname()
4307{
4308}
4309
4310void
4311numpunct_byname<char>::__init(const char* nm)
4312{
4313 if (strcmp(nm, "C") != 0)
4314 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004315 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004316#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004317 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004318 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4319 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004320#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004321#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004322 lconv* lc = localeconv_l(loc.get());
4323#else
4324 lconv* lc = __localeconv_l(loc.get());
4325#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004326 if (*lc->decimal_point)
4327 __decimal_point_ = *lc->decimal_point;
4328 if (*lc->thousands_sep)
4329 __thousands_sep_ = *lc->thousands_sep;
4330 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004331 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004332 }
4333}
4334
4335// numpunct_byname<wchar_t>
4336
4337numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4338 : numpunct<wchar_t>(refs)
4339{
4340 __init(nm);
4341}
4342
4343numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4344 : numpunct<wchar_t>(refs)
4345{
4346 __init(nm.c_str());
4347}
4348
4349numpunct_byname<wchar_t>::~numpunct_byname()
4350{
4351}
4352
4353void
4354numpunct_byname<wchar_t>::__init(const char* nm)
4355{
4356 if (strcmp(nm, "C") != 0)
4357 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004358 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004359#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004360 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004361 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4362 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004363#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004364#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004365 lconv* lc = localeconv_l(loc.get());
4366#else
4367 lconv* lc = __localeconv_l(loc.get());
4368#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004369 if (*lc->decimal_point)
4370 __decimal_point_ = *lc->decimal_point;
4371 if (*lc->thousands_sep)
4372 __thousands_sep_ = *lc->thousands_sep;
4373 __grouping_ = lc->grouping;
4374 // locallization for truename and falsename is not available
4375 }
4376}
4377
4378// num_get helpers
4379
4380int
4381__num_get_base::__get_base(ios_base& iob)
4382{
4383 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4384 if (__basefield == ios_base::oct)
4385 return 8;
4386 else if (__basefield == ios_base::hex)
4387 return 16;
4388 else if (__basefield == 0)
4389 return 0;
4390 return 10;
4391}
4392
4393const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4394
4395void
4396__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4397 ios_base::iostate& __err)
4398{
4399 if (__grouping.size() != 0)
4400 {
4401 reverse(__g, __g_end);
4402 const char* __ig = __grouping.data();
4403 const char* __eg = __ig + __grouping.size();
4404 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4405 {
4406 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4407 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004408 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004409 {
4410 __err = ios_base::failbit;
4411 return;
4412 }
4413 }
4414 if (__eg - __ig > 1)
4415 ++__ig;
4416 }
4417 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4418 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004419 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004420 __err = ios_base::failbit;
4421 }
4422 }
4423}
4424
4425void
4426__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4427 ios_base::fmtflags __flags)
4428{
4429 if (__flags & ios_base::showpos)
4430 *__fmtp++ = '+';
4431 if (__flags & ios_base::showbase)
4432 *__fmtp++ = '#';
4433 while(*__len)
4434 *__fmtp++ = *__len++;
4435 if ((__flags & ios_base::basefield) == ios_base::oct)
4436 *__fmtp = 'o';
4437 else if ((__flags & ios_base::basefield) == ios_base::hex)
4438 {
4439 if (__flags & ios_base::uppercase)
4440 *__fmtp = 'X';
4441 else
4442 *__fmtp = 'x';
4443 }
4444 else if (__signd)
4445 *__fmtp = 'd';
4446 else
4447 *__fmtp = 'u';
4448}
4449
4450bool
4451__num_put_base::__format_float(char* __fmtp, const char* __len,
4452 ios_base::fmtflags __flags)
4453{
4454 bool specify_precision = true;
4455 if (__flags & ios_base::showpos)
4456 *__fmtp++ = '+';
4457 if (__flags & ios_base::showpoint)
4458 *__fmtp++ = '#';
4459 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004460 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004461 if (floatfield == (ios_base::fixed | ios_base::scientific))
4462 specify_precision = false;
4463 else
4464 {
4465 *__fmtp++ = '.';
4466 *__fmtp++ = '*';
4467 }
4468 while(*__len)
4469 *__fmtp++ = *__len++;
4470 if (floatfield == ios_base::fixed)
4471 {
4472 if (uppercase)
4473 *__fmtp = 'F';
4474 else
4475 *__fmtp = 'f';
4476 }
4477 else if (floatfield == ios_base::scientific)
4478 {
4479 if (uppercase)
4480 *__fmtp = 'E';
4481 else
4482 *__fmtp = 'e';
4483 }
4484 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4485 {
4486 if (uppercase)
4487 *__fmtp = 'A';
4488 else
4489 *__fmtp = 'a';
4490 }
4491 else
4492 {
4493 if (uppercase)
4494 *__fmtp = 'G';
4495 else
4496 *__fmtp = 'g';
4497 }
4498 return specify_precision;
4499}
4500
4501char*
4502__num_put_base::__identify_padding(char* __nb, char* __ne,
4503 const ios_base& __iob)
4504{
4505 switch (__iob.flags() & ios_base::adjustfield)
4506 {
4507 case ios_base::internal:
4508 if (__nb[0] == '-' || __nb[0] == '+')
4509 return __nb+1;
4510 if (__ne - __nb >= 2 && __nb[0] == '0'
4511 && (__nb[1] == 'x' || __nb[1] == 'X'))
4512 return __nb+2;
4513 break;
4514 case ios_base::left:
4515 return __ne;
4516 case ios_base::right:
4517 default:
4518 break;
4519 }
4520 return __nb;
4521}
4522
4523// time_get
4524
4525static
4526string*
4527init_weeks()
4528{
4529 static string weeks[14];
4530 weeks[0] = "Sunday";
4531 weeks[1] = "Monday";
4532 weeks[2] = "Tuesday";
4533 weeks[3] = "Wednesday";
4534 weeks[4] = "Thursday";
4535 weeks[5] = "Friday";
4536 weeks[6] = "Saturday";
4537 weeks[7] = "Sun";
4538 weeks[8] = "Mon";
4539 weeks[9] = "Tue";
4540 weeks[10] = "Wed";
4541 weeks[11] = "Thu";
4542 weeks[12] = "Fri";
4543 weeks[13] = "Sat";
4544 return weeks;
4545}
4546
4547static
4548wstring*
4549init_wweeks()
4550{
4551 static wstring weeks[14];
4552 weeks[0] = L"Sunday";
4553 weeks[1] = L"Monday";
4554 weeks[2] = L"Tuesday";
4555 weeks[3] = L"Wednesday";
4556 weeks[4] = L"Thursday";
4557 weeks[5] = L"Friday";
4558 weeks[6] = L"Saturday";
4559 weeks[7] = L"Sun";
4560 weeks[8] = L"Mon";
4561 weeks[9] = L"Tue";
4562 weeks[10] = L"Wed";
4563 weeks[11] = L"Thu";
4564 weeks[12] = L"Fri";
4565 weeks[13] = L"Sat";
4566 return weeks;
4567}
4568
4569template <>
4570const string*
4571__time_get_c_storage<char>::__weeks() const
4572{
4573 static const string* weeks = init_weeks();
4574 return weeks;
4575}
4576
4577template <>
4578const wstring*
4579__time_get_c_storage<wchar_t>::__weeks() const
4580{
4581 static const wstring* weeks = init_wweeks();
4582 return weeks;
4583}
4584
4585static
4586string*
4587init_months()
4588{
4589 static string months[24];
4590 months[0] = "January";
4591 months[1] = "February";
4592 months[2] = "March";
4593 months[3] = "April";
4594 months[4] = "May";
4595 months[5] = "June";
4596 months[6] = "July";
4597 months[7] = "August";
4598 months[8] = "September";
4599 months[9] = "October";
4600 months[10] = "November";
4601 months[11] = "December";
4602 months[12] = "Jan";
4603 months[13] = "Feb";
4604 months[14] = "Mar";
4605 months[15] = "Apr";
4606 months[16] = "May";
4607 months[17] = "Jun";
4608 months[18] = "Jul";
4609 months[19] = "Aug";
4610 months[20] = "Sep";
4611 months[21] = "Oct";
4612 months[22] = "Nov";
4613 months[23] = "Dec";
4614 return months;
4615}
4616
4617static
4618wstring*
4619init_wmonths()
4620{
4621 static wstring months[24];
4622 months[0] = L"January";
4623 months[1] = L"February";
4624 months[2] = L"March";
4625 months[3] = L"April";
4626 months[4] = L"May";
4627 months[5] = L"June";
4628 months[6] = L"July";
4629 months[7] = L"August";
4630 months[8] = L"September";
4631 months[9] = L"October";
4632 months[10] = L"November";
4633 months[11] = L"December";
4634 months[12] = L"Jan";
4635 months[13] = L"Feb";
4636 months[14] = L"Mar";
4637 months[15] = L"Apr";
4638 months[16] = L"May";
4639 months[17] = L"Jun";
4640 months[18] = L"Jul";
4641 months[19] = L"Aug";
4642 months[20] = L"Sep";
4643 months[21] = L"Oct";
4644 months[22] = L"Nov";
4645 months[23] = L"Dec";
4646 return months;
4647}
4648
4649template <>
4650const string*
4651__time_get_c_storage<char>::__months() const
4652{
4653 static const string* months = init_months();
4654 return months;
4655}
4656
4657template <>
4658const wstring*
4659__time_get_c_storage<wchar_t>::__months() const
4660{
4661 static const wstring* months = init_wmonths();
4662 return months;
4663}
4664
4665static
4666string*
4667init_am_pm()
4668{
4669 static string am_pm[24];
4670 am_pm[0] = "AM";
4671 am_pm[1] = "PM";
4672 return am_pm;
4673}
4674
4675static
4676wstring*
4677init_wam_pm()
4678{
4679 static wstring am_pm[24];
4680 am_pm[0] = L"AM";
4681 am_pm[1] = L"PM";
4682 return am_pm;
4683}
4684
4685template <>
4686const string*
4687__time_get_c_storage<char>::__am_pm() const
4688{
4689 static const string* am_pm = init_am_pm();
4690 return am_pm;
4691}
4692
4693template <>
4694const wstring*
4695__time_get_c_storage<wchar_t>::__am_pm() const
4696{
4697 static const wstring* am_pm = init_wam_pm();
4698 return am_pm;
4699}
4700
4701template <>
4702const string&
4703__time_get_c_storage<char>::__x() const
4704{
4705 static string s("%m/%d/%y");
4706 return s;
4707}
4708
4709template <>
4710const wstring&
4711__time_get_c_storage<wchar_t>::__x() const
4712{
4713 static wstring s(L"%m/%d/%y");
4714 return s;
4715}
4716
4717template <>
4718const string&
4719__time_get_c_storage<char>::__X() const
4720{
4721 static string s("%H:%M:%S");
4722 return s;
4723}
4724
4725template <>
4726const wstring&
4727__time_get_c_storage<wchar_t>::__X() const
4728{
4729 static wstring s(L"%H:%M:%S");
4730 return s;
4731}
4732
4733template <>
4734const string&
4735__time_get_c_storage<char>::__c() const
4736{
4737 static string s("%a %b %d %H:%M:%S %Y");
4738 return s;
4739}
4740
4741template <>
4742const wstring&
4743__time_get_c_storage<wchar_t>::__c() const
4744{
4745 static wstring s(L"%a %b %d %H:%M:%S %Y");
4746 return s;
4747}
4748
4749template <>
4750const string&
4751__time_get_c_storage<char>::__r() const
4752{
4753 static string s("%I:%M:%S %p");
4754 return s;
4755}
4756
4757template <>
4758const wstring&
4759__time_get_c_storage<wchar_t>::__r() const
4760{
4761 static wstring s(L"%I:%M:%S %p");
4762 return s;
4763}
4764
4765// time_get_byname
4766
4767__time_get::__time_get(const char* nm)
4768 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4769{
Howard Hinnant72f73582010-08-11 17:04:31 +00004770#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004771 if (__loc_ == 0)
4772 throw runtime_error("time_get_byname"
4773 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004774#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004775}
4776
4777__time_get::__time_get(const string& nm)
4778 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4779{
Howard Hinnant72f73582010-08-11 17:04:31 +00004780#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004781 if (__loc_ == 0)
4782 throw runtime_error("time_get_byname"
4783 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00004784#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004785}
4786
4787__time_get::~__time_get()
4788{
4789 freelocale(__loc_);
4790}
Marshall Clowd920eea2013-10-21 15:07:28 +00004791#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004792#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004793#endif
4794#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004795#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004796#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004797
Howard Hinnantc51e1022010-05-11 19:42:16 +00004798template <>
4799string
4800__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4801{
Howard Hinnant990207c2012-02-19 14:55:32 +00004802 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004803 t.tm_sec = 59;
4804 t.tm_min = 55;
4805 t.tm_hour = 23;
4806 t.tm_mday = 31;
4807 t.tm_mon = 11;
4808 t.tm_year = 161;
4809 t.tm_wday = 6;
4810 t.tm_yday = 364;
4811 t.tm_isdst = -1;
4812 char buf[100];
4813 char f[3] = {0};
4814 f[0] = '%';
4815 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004816 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004817 char* bb = buf;
4818 char* be = buf + n;
4819 string result;
4820 while (bb != be)
4821 {
4822 if (ct.is(ctype_base::space, *bb))
4823 {
4824 result.push_back(' ');
4825 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4826 ;
4827 continue;
4828 }
4829 char* w = bb;
4830 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004831 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004832 ct, err, false)
4833 - this->__weeks_;
4834 if (i < 14)
4835 {
4836 result.push_back('%');
4837 if (i < 7)
4838 result.push_back('A');
4839 else
4840 result.push_back('a');
4841 bb = w;
4842 continue;
4843 }
4844 w = bb;
4845 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4846 ct, err, false)
4847 - this->__months_;
4848 if (i < 24)
4849 {
4850 result.push_back('%');
4851 if (i < 12)
4852 result.push_back('B');
4853 else
4854 result.push_back('b');
4855 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4856 result.back() = 'm';
4857 bb = w;
4858 continue;
4859 }
4860 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4861 {
4862 w = bb;
4863 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4864 ct, err, false) - this->__am_pm_;
4865 if (i < 2)
4866 {
4867 result.push_back('%');
4868 result.push_back('p');
4869 bb = w;
4870 continue;
4871 }
4872 }
4873 w = bb;
4874 if (ct.is(ctype_base::digit, *bb))
4875 {
4876 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4877 {
4878 case 6:
4879 result.push_back('%');
4880 result.push_back('w');
4881 break;
4882 case 7:
4883 result.push_back('%');
4884 result.push_back('u');
4885 break;
4886 case 11:
4887 result.push_back('%');
4888 result.push_back('I');
4889 break;
4890 case 12:
4891 result.push_back('%');
4892 result.push_back('m');
4893 break;
4894 case 23:
4895 result.push_back('%');
4896 result.push_back('H');
4897 break;
4898 case 31:
4899 result.push_back('%');
4900 result.push_back('d');
4901 break;
4902 case 55:
4903 result.push_back('%');
4904 result.push_back('M');
4905 break;
4906 case 59:
4907 result.push_back('%');
4908 result.push_back('S');
4909 break;
4910 case 61:
4911 result.push_back('%');
4912 result.push_back('y');
4913 break;
4914 case 364:
4915 result.push_back('%');
4916 result.push_back('j');
4917 break;
4918 case 2061:
4919 result.push_back('%');
4920 result.push_back('Y');
4921 break;
4922 default:
4923 for (; w != bb; ++w)
4924 result.push_back(*w);
4925 break;
4926 }
4927 continue;
4928 }
4929 if (*bb == '%')
4930 {
4931 result.push_back('%');
4932 result.push_back('%');
4933 ++bb;
4934 continue;
4935 }
4936 result.push_back(*bb);
4937 ++bb;
4938 }
4939 return result;
4940}
4941
Marshall Clowd920eea2013-10-21 15:07:28 +00004942#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004943#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004944#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004945
Howard Hinnantc51e1022010-05-11 19:42:16 +00004946template <>
4947wstring
4948__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4949{
Howard Hinnant990207c2012-02-19 14:55:32 +00004950 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004951 t.tm_sec = 59;
4952 t.tm_min = 55;
4953 t.tm_hour = 23;
4954 t.tm_mday = 31;
4955 t.tm_mon = 11;
4956 t.tm_year = 161;
4957 t.tm_wday = 6;
4958 t.tm_yday = 364;
4959 t.tm_isdst = -1;
4960 char buf[100];
4961 char f[3] = {0};
4962 f[0] = '%';
4963 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004964 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004965 wchar_t wbuf[100];
4966 wchar_t* wbb = wbuf;
4967 mbstate_t mb = {0};
4968 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004969#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004970 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004971#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004972 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004973#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004974 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004975 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004976 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004977 wstring result;
4978 while (wbb != wbe)
4979 {
4980 if (ct.is(ctype_base::space, *wbb))
4981 {
4982 result.push_back(L' ');
4983 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4984 ;
4985 continue;
4986 }
4987 wchar_t* w = wbb;
4988 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004989 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004990 ct, err, false)
4991 - this->__weeks_;
4992 if (i < 14)
4993 {
4994 result.push_back(L'%');
4995 if (i < 7)
4996 result.push_back(L'A');
4997 else
4998 result.push_back(L'a');
4999 wbb = w;
5000 continue;
5001 }
5002 w = wbb;
5003 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5004 ct, err, false)
5005 - this->__months_;
5006 if (i < 24)
5007 {
5008 result.push_back(L'%');
5009 if (i < 12)
5010 result.push_back(L'B');
5011 else
5012 result.push_back(L'b');
5013 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5014 result.back() = L'm';
5015 wbb = w;
5016 continue;
5017 }
5018 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5019 {
5020 w = wbb;
5021 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5022 ct, err, false) - this->__am_pm_;
5023 if (i < 2)
5024 {
5025 result.push_back(L'%');
5026 result.push_back(L'p');
5027 wbb = w;
5028 continue;
5029 }
5030 }
5031 w = wbb;
5032 if (ct.is(ctype_base::digit, *wbb))
5033 {
5034 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5035 {
5036 case 6:
5037 result.push_back(L'%');
5038 result.push_back(L'w');
5039 break;
5040 case 7:
5041 result.push_back(L'%');
5042 result.push_back(L'u');
5043 break;
5044 case 11:
5045 result.push_back(L'%');
5046 result.push_back(L'I');
5047 break;
5048 case 12:
5049 result.push_back(L'%');
5050 result.push_back(L'm');
5051 break;
5052 case 23:
5053 result.push_back(L'%');
5054 result.push_back(L'H');
5055 break;
5056 case 31:
5057 result.push_back(L'%');
5058 result.push_back(L'd');
5059 break;
5060 case 55:
5061 result.push_back(L'%');
5062 result.push_back(L'M');
5063 break;
5064 case 59:
5065 result.push_back(L'%');
5066 result.push_back(L'S');
5067 break;
5068 case 61:
5069 result.push_back(L'%');
5070 result.push_back(L'y');
5071 break;
5072 case 364:
5073 result.push_back(L'%');
5074 result.push_back(L'j');
5075 break;
5076 case 2061:
5077 result.push_back(L'%');
5078 result.push_back(L'Y');
5079 break;
5080 default:
5081 for (; w != wbb; ++w)
5082 result.push_back(*w);
5083 break;
5084 }
5085 continue;
5086 }
5087 if (ct.narrow(*wbb, 0) == '%')
5088 {
5089 result.push_back(L'%');
5090 result.push_back(L'%');
5091 ++wbb;
5092 continue;
5093 }
5094 result.push_back(*wbb);
5095 ++wbb;
5096 }
5097 return result;
5098}
5099
5100template <>
5101void
5102__time_get_storage<char>::init(const ctype<char>& ct)
5103{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005104 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005105 char buf[100];
5106 // __weeks_
5107 for (int i = 0; i < 7; ++i)
5108 {
5109 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005110 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005111 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005112 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005113 __weeks_[i+7] = buf;
5114 }
5115 // __months_
5116 for (int i = 0; i < 12; ++i)
5117 {
5118 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005119 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005120 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005121 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005122 __months_[i+12] = buf;
5123 }
5124 // __am_pm_
5125 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005126 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005127 __am_pm_[0] = buf;
5128 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005129 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005130 __am_pm_[1] = buf;
5131 __c_ = __analyze('c', ct);
5132 __r_ = __analyze('r', ct);
5133 __x_ = __analyze('x', ct);
5134 __X_ = __analyze('X', ct);
5135}
5136
5137template <>
5138void
5139__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5140{
5141 tm t = {0};
5142 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005143 wchar_t wbuf[100];
5144 wchar_t* wbe;
5145 mbstate_t mb = {0};
5146 // __weeks_
5147 for (int i = 0; i < 7; ++i)
5148 {
5149 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005150 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005151 mb = mbstate_t();
5152 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005153#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005154 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005155#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005156 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005157#endif
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 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005162 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005163 mb = mbstate_t();
5164 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005165#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005166 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005167#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005168 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005169#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005170 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005171 __throw_runtime_error("locale not supported");
5172 wbe = wbuf + j;
5173 __weeks_[i+7].assign(wbuf, wbe);
5174 }
5175 // __months_
5176 for (int i = 0; i < 12; ++i)
5177 {
5178 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005179 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005180 mb = mbstate_t();
5181 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005182#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005183 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005184#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005185 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005186#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005187 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005188 __throw_runtime_error("locale not supported");
5189 wbe = wbuf + j;
5190 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005191 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005192 mb = mbstate_t();
5193 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005194#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005195 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005196#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005197 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005198#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005199 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005200 __throw_runtime_error("locale not supported");
5201 wbe = wbuf + j;
5202 __months_[i+12].assign(wbuf, wbe);
5203 }
5204 // __am_pm_
5205 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005206 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005207 mb = mbstate_t();
5208 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005209#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005210 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005211#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005212 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005213#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005214 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005215 __throw_runtime_error("locale not supported");
5216 wbe = wbuf + j;
5217 __am_pm_[0].assign(wbuf, wbe);
5218 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005219 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005220 mb = mbstate_t();
5221 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005222#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005223 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005224#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005225 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005226#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005227 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005228 __throw_runtime_error("locale not supported");
5229 wbe = wbuf + j;
5230 __am_pm_[1].assign(wbuf, wbe);
5231 __c_ = __analyze('c', ct);
5232 __r_ = __analyze('r', ct);
5233 __x_ = __analyze('x', ct);
5234 __X_ = __analyze('X', ct);
5235}
5236
5237template <class CharT>
5238struct _LIBCPP_HIDDEN __time_get_temp
5239 : public ctype_byname<CharT>
5240{
5241 explicit __time_get_temp(const char* nm)
5242 : ctype_byname<CharT>(nm, 1) {}
5243 explicit __time_get_temp(const string& nm)
5244 : ctype_byname<CharT>(nm, 1) {}
5245};
5246
5247template <>
5248__time_get_storage<char>::__time_get_storage(const char* __nm)
5249 : __time_get(__nm)
5250{
5251 const __time_get_temp<char> ct(__nm);
5252 init(ct);
5253}
5254
5255template <>
5256__time_get_storage<char>::__time_get_storage(const string& __nm)
5257 : __time_get(__nm)
5258{
5259 const __time_get_temp<char> ct(__nm);
5260 init(ct);
5261}
5262
5263template <>
5264__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5265 : __time_get(__nm)
5266{
5267 const __time_get_temp<wchar_t> ct(__nm);
5268 init(ct);
5269}
5270
5271template <>
5272__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5273 : __time_get(__nm)
5274{
5275 const __time_get_temp<wchar_t> ct(__nm);
5276 init(ct);
5277}
5278
5279template <>
5280time_base::dateorder
5281__time_get_storage<char>::__do_date_order() const
5282{
5283 unsigned i;
5284 for (i = 0; i < __x_.size(); ++i)
5285 if (__x_[i] == '%')
5286 break;
5287 ++i;
5288 switch (__x_[i])
5289 {
5290 case 'y':
5291 case 'Y':
5292 for (++i; i < __x_.size(); ++i)
5293 if (__x_[i] == '%')
5294 break;
5295 if (i == __x_.size())
5296 break;
5297 ++i;
5298 switch (__x_[i])
5299 {
5300 case 'm':
5301 for (++i; i < __x_.size(); ++i)
5302 if (__x_[i] == '%')
5303 break;
5304 if (i == __x_.size())
5305 break;
5306 ++i;
5307 if (__x_[i] == 'd')
5308 return time_base::ymd;
5309 break;
5310 case 'd':
5311 for (++i; i < __x_.size(); ++i)
5312 if (__x_[i] == '%')
5313 break;
5314 if (i == __x_.size())
5315 break;
5316 ++i;
5317 if (__x_[i] == 'm')
5318 return time_base::ydm;
5319 break;
5320 }
5321 break;
5322 case 'm':
5323 for (++i; i < __x_.size(); ++i)
5324 if (__x_[i] == '%')
5325 break;
5326 if (i == __x_.size())
5327 break;
5328 ++i;
5329 if (__x_[i] == 'd')
5330 {
5331 for (++i; i < __x_.size(); ++i)
5332 if (__x_[i] == '%')
5333 break;
5334 if (i == __x_.size())
5335 break;
5336 ++i;
5337 if (__x_[i] == 'y' || __x_[i] == 'Y')
5338 return time_base::mdy;
5339 break;
5340 }
5341 break;
5342 case 'd':
5343 for (++i; i < __x_.size(); ++i)
5344 if (__x_[i] == '%')
5345 break;
5346 if (i == __x_.size())
5347 break;
5348 ++i;
5349 if (__x_[i] == 'm')
5350 {
5351 for (++i; i < __x_.size(); ++i)
5352 if (__x_[i] == '%')
5353 break;
5354 if (i == __x_.size())
5355 break;
5356 ++i;
5357 if (__x_[i] == 'y' || __x_[i] == 'Y')
5358 return time_base::dmy;
5359 break;
5360 }
5361 break;
5362 }
5363 return time_base::no_order;
5364}
5365
5366template <>
5367time_base::dateorder
5368__time_get_storage<wchar_t>::__do_date_order() const
5369{
5370 unsigned i;
5371 for (i = 0; i < __x_.size(); ++i)
5372 if (__x_[i] == L'%')
5373 break;
5374 ++i;
5375 switch (__x_[i])
5376 {
5377 case L'y':
5378 case L'Y':
5379 for (++i; i < __x_.size(); ++i)
5380 if (__x_[i] == L'%')
5381 break;
5382 if (i == __x_.size())
5383 break;
5384 ++i;
5385 switch (__x_[i])
5386 {
5387 case L'm':
5388 for (++i; i < __x_.size(); ++i)
5389 if (__x_[i] == L'%')
5390 break;
5391 if (i == __x_.size())
5392 break;
5393 ++i;
5394 if (__x_[i] == L'd')
5395 return time_base::ymd;
5396 break;
5397 case L'd':
5398 for (++i; i < __x_.size(); ++i)
5399 if (__x_[i] == L'%')
5400 break;
5401 if (i == __x_.size())
5402 break;
5403 ++i;
5404 if (__x_[i] == L'm')
5405 return time_base::ydm;
5406 break;
5407 }
5408 break;
5409 case L'm':
5410 for (++i; i < __x_.size(); ++i)
5411 if (__x_[i] == L'%')
5412 break;
5413 if (i == __x_.size())
5414 break;
5415 ++i;
5416 if (__x_[i] == L'd')
5417 {
5418 for (++i; i < __x_.size(); ++i)
5419 if (__x_[i] == L'%')
5420 break;
5421 if (i == __x_.size())
5422 break;
5423 ++i;
5424 if (__x_[i] == L'y' || __x_[i] == L'Y')
5425 return time_base::mdy;
5426 break;
5427 }
5428 break;
5429 case L'd':
5430 for (++i; i < __x_.size(); ++i)
5431 if (__x_[i] == L'%')
5432 break;
5433 if (i == __x_.size())
5434 break;
5435 ++i;
5436 if (__x_[i] == L'm')
5437 {
5438 for (++i; i < __x_.size(); ++i)
5439 if (__x_[i] == L'%')
5440 break;
5441 if (i == __x_.size())
5442 break;
5443 ++i;
5444 if (__x_[i] == L'y' || __x_[i] == L'Y')
5445 return time_base::dmy;
5446 break;
5447 }
5448 break;
5449 }
5450 return time_base::no_order;
5451}
5452
5453// time_put
5454
5455__time_put::__time_put(const char* nm)
5456 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5457{
Howard Hinnant72f73582010-08-11 17:04:31 +00005458#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005459 if (__loc_ == 0)
5460 throw runtime_error("time_put_byname"
5461 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005462#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005463}
5464
5465__time_put::__time_put(const string& nm)
5466 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5467{
Howard Hinnant72f73582010-08-11 17:04:31 +00005468#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005469 if (__loc_ == 0)
5470 throw runtime_error("time_put_byname"
5471 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00005472#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005473}
5474
5475__time_put::~__time_put()
5476{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005477 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005478 freelocale(__loc_);
5479}
5480
5481void
5482__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5483 char __fmt, char __mod) const
5484{
5485 char fmt[] = {'%', __fmt, __mod, 0};
5486 if (__mod != 0)
5487 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005488 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005489 __ne = __nb + n;
5490}
5491
5492void
5493__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5494 char __fmt, char __mod) const
5495{
5496 char __nar[100];
5497 char* __ne = __nar + 100;
5498 __do_put(__nar, __ne, __tm, __fmt, __mod);
5499 mbstate_t mb = {0};
5500 const char* __nb = __nar;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005501#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005502 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005503#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005504 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005505#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005506 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005507 __throw_runtime_error("locale not supported");
5508 __we = __wb + j;
5509}
5510
5511// moneypunct_byname
5512
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005513template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005514static
5515void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005516__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5517 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5518 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005519{
5520 const char sign = static_cast<char>(money_base::sign);
5521 const char space = static_cast<char>(money_base::space);
5522 const char none = static_cast<char>(money_base::none);
5523 const char symbol = static_cast<char>(money_base::symbol);
5524 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005525 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5526
5527 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5528 // function'. "Space between sign and symbol or value" means that
5529 // if the sign is adjacent to the symbol, there's a space between
5530 // them, and otherwise there's a space between the sign and value.
5531 //
5532 // C11's localeconv specifies that the fourth character of an
5533 // international curr_symbol is used to separate the sign and
5534 // value when sep_by_space says to do so. C++ can't represent
5535 // that, so we just use a space. When sep_by_space says to
5536 // separate the symbol and value-or-sign with a space, we rearrange the
5537 // curr_symbol to put its spacing character on the correct side of
5538 // the symbol.
5539 //
5540 // We also need to avoid adding an extra space between the sign
5541 // and value when the currency symbol is suppressed (by not
5542 // setting showbase). We match glibc's strfmon by interpreting
5543 // sep_by_space==1 as "omit the space when the currency symbol is
5544 // absent".
5545 //
5546 // Users who want to get this right should use ICU instead.
5547
Howard Hinnantc51e1022010-05-11 19:42:16 +00005548 switch (cs_precedes)
5549 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005550 case 0: // value before curr_symbol
5551 if (symbol_contains_sep) {
5552 // Move the separator to before the symbol, to place it
5553 // between the value and symbol.
5554 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5555 __curr_symbol_.end());
5556 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005557 switch (sign_posn)
5558 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005559 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005560 pat.field[0] = sign;
5561 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005562 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005563 pat.field[3] = symbol;
5564 switch (sep_by_space)
5565 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005566 case 0: // No space separates the currency symbol and value.
5567 // This case may have changed between C99 and C11;
5568 // assume the currency symbol matches the intention.
5569 case 2: // Space between sign and currency or value.
5570 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005571 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005572 case 1: // Space between currency-and-sign or currency and value.
5573 if (!symbol_contains_sep) {
5574 // We insert the space into the symbol instead of
5575 // setting pat.field[2]=space so that when
5576 // showbase is not set, the space goes away too.
5577 __curr_symbol_.insert(0, 1, space_char);
5578 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005579 return;
5580 default:
5581 break;
5582 }
5583 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005584 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005585 pat.field[0] = sign;
5586 pat.field[3] = symbol;
5587 switch (sep_by_space)
5588 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005589 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005590 pat.field[1] = value;
5591 pat.field[2] = none;
5592 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005593 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005594 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005595 pat.field[2] = none;
5596 if (!symbol_contains_sep) {
5597 // We insert the space into the symbol instead of
5598 // setting pat.field[2]=space so that when
5599 // showbase is not set, the space goes away too.
5600 __curr_symbol_.insert(0, 1, space_char);
5601 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005602 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005603 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005604 pat.field[1] = space;
5605 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005606 if (symbol_contains_sep) {
5607 // Remove the separator from the symbol, since it
5608 // has already appeared after the sign.
5609 __curr_symbol_.erase(__curr_symbol_.begin());
5610 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005611 return;
5612 default:
5613 break;
5614 }
5615 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005616 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005617 pat.field[0] = value;
5618 pat.field[3] = sign;
5619 switch (sep_by_space)
5620 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005621 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005622 pat.field[1] = none;
5623 pat.field[2] = symbol;
5624 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005625 case 1: // Space between currency-and-sign or currency and value.
5626 if (!symbol_contains_sep) {
5627 // We insert the space into the symbol instead of
5628 // setting pat.field[1]=space so that when
5629 // showbase is not set, the space goes away too.
5630 __curr_symbol_.insert(0, 1, space_char);
5631 }
5632 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005633 pat.field[2] = symbol;
5634 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005635 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005636 pat.field[1] = symbol;
5637 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005638 if (symbol_contains_sep) {
5639 // Remove the separator from the symbol, since it
5640 // should not be removed if showbase is absent.
5641 __curr_symbol_.erase(__curr_symbol_.begin());
5642 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005643 return;
5644 default:
5645 break;
5646 }
5647 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005648 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005649 pat.field[0] = value;
5650 pat.field[3] = symbol;
5651 switch (sep_by_space)
5652 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005653 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005654 pat.field[1] = none;
5655 pat.field[2] = sign;
5656 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005657 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005658 pat.field[1] = space;
5659 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005660 if (symbol_contains_sep) {
5661 // Remove the separator from the symbol, since it
5662 // has already appeared before the sign.
5663 __curr_symbol_.erase(__curr_symbol_.begin());
5664 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005665 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005666 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005667 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005668 pat.field[2] = none;
5669 if (!symbol_contains_sep) {
5670 // We insert the space into the symbol instead of
5671 // setting pat.field[2]=space so that when
5672 // showbase is not set, the space goes away too.
5673 __curr_symbol_.insert(0, 1, space_char);
5674 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005675 return;
5676 default:
5677 break;
5678 }
5679 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005680 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005681 pat.field[0] = value;
5682 pat.field[3] = sign;
5683 switch (sep_by_space)
5684 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005685 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005686 pat.field[1] = none;
5687 pat.field[2] = symbol;
5688 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005689 case 1: // Space between currency-and-sign or currency and value.
5690 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005691 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005692 if (!symbol_contains_sep) {
5693 // We insert the space into the symbol instead of
5694 // setting pat.field[1]=space so that when
5695 // showbase is not set, the space goes away too.
5696 __curr_symbol_.insert(0, 1, space_char);
5697 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005698 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005699 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005700 pat.field[1] = symbol;
5701 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005702 if (symbol_contains_sep) {
5703 // Remove the separator from the symbol, since it
5704 // should not disappear when showbase is absent.
5705 __curr_symbol_.erase(__curr_symbol_.begin());
5706 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005707 return;
5708 default:
5709 break;
5710 }
5711 break;
5712 default:
5713 break;
5714 }
5715 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005716 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005717 switch (sign_posn)
5718 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005719 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005720 pat.field[0] = sign;
5721 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005722 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005723 pat.field[3] = value;
5724 switch (sep_by_space)
5725 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005726 case 0: // No space separates the currency symbol and value.
5727 // This case may have changed between C99 and C11;
5728 // assume the currency symbol matches the intention.
5729 case 2: // Space between sign and currency or value.
5730 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005731 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005732 case 1: // Space between currency-and-sign or currency and value.
5733 if (!symbol_contains_sep) {
5734 // We insert the space into the symbol instead of
5735 // setting pat.field[2]=space so that when
5736 // showbase is not set, the space goes away too.
5737 __curr_symbol_.insert(0, 1, space_char);
5738 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005739 return;
5740 default:
5741 break;
5742 }
5743 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005744 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005745 pat.field[0] = sign;
5746 pat.field[3] = value;
5747 switch (sep_by_space)
5748 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005749 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005750 pat.field[1] = symbol;
5751 pat.field[2] = none;
5752 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005753 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005754 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005755 pat.field[2] = none;
5756 if (!symbol_contains_sep) {
5757 // We insert the space into the symbol instead of
5758 // setting pat.field[2]=space so that when
5759 // showbase is not set, the space goes away too.
5760 __curr_symbol_.push_back(space_char);
5761 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005762 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005763 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005764 pat.field[1] = space;
5765 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005766 if (symbol_contains_sep) {
5767 // Remove the separator from the symbol, since it
5768 // has already appeared after the sign.
5769 __curr_symbol_.pop_back();
5770 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005771 return;
5772 default:
5773 break;
5774 }
5775 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005776 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005777 pat.field[0] = symbol;
5778 pat.field[3] = sign;
5779 switch (sep_by_space)
5780 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005781 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005782 pat.field[1] = none;
5783 pat.field[2] = value;
5784 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005785 case 1: // Space between currency-and-sign or currency and value.
5786 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005787 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005788 if (!symbol_contains_sep) {
5789 // We insert the space into the symbol instead of
5790 // setting pat.field[1]=space so that when
5791 // showbase is not set, the space goes away too.
5792 __curr_symbol_.push_back(space_char);
5793 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005794 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005795 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005796 pat.field[1] = value;
5797 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005798 if (symbol_contains_sep) {
5799 // Remove the separator from the symbol, since it
5800 // will appear before the sign.
5801 __curr_symbol_.pop_back();
5802 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005803 return;
5804 default:
5805 break;
5806 }
5807 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005808 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005809 pat.field[0] = sign;
5810 pat.field[3] = value;
5811 switch (sep_by_space)
5812 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005813 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005814 pat.field[1] = symbol;
5815 pat.field[2] = none;
5816 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005817 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005818 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005819 pat.field[2] = none;
5820 if (!symbol_contains_sep) {
5821 // We insert the space into the symbol instead of
5822 // setting pat.field[2]=space so that when
5823 // showbase is not set, the space goes away too.
5824 __curr_symbol_.push_back(space_char);
5825 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005826 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005827 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005828 pat.field[1] = space;
5829 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005830 if (symbol_contains_sep) {
5831 // Remove the separator from the symbol, since it
5832 // has already appeared after the sign.
5833 __curr_symbol_.pop_back();
5834 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005835 return;
5836 default:
5837 break;
5838 }
5839 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005840 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005841 pat.field[0] = symbol;
5842 pat.field[3] = value;
5843 switch (sep_by_space)
5844 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005845 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005846 pat.field[1] = sign;
5847 pat.field[2] = none;
5848 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005849 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005850 pat.field[1] = sign;
5851 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005852 if (symbol_contains_sep) {
5853 // Remove the separator from the symbol, since it
5854 // should not disappear when showbase is absent.
5855 __curr_symbol_.pop_back();
5856 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005857 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005858 case 2: // Space between sign and currency or value.
5859 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005860 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005861 if (!symbol_contains_sep) {
5862 // We insert the space into the symbol instead of
5863 // setting pat.field[1]=space so that when
5864 // showbase is not set, the space goes away too.
5865 __curr_symbol_.push_back(space_char);
5866 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005867 return;
5868 default:
5869 break;
5870 }
5871 break;
5872 default:
5873 break;
5874 }
5875 break;
5876 default:
5877 break;
5878 }
5879 pat.field[0] = symbol;
5880 pat.field[1] = sign;
5881 pat.field[2] = none;
5882 pat.field[3] = value;
5883}
5884
5885template<>
5886void
5887moneypunct_byname<char, false>::init(const char* nm)
5888{
5889 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005890 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005891#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005892 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005893 throw runtime_error("moneypunct_byname"
5894 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005895#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005896#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005897 lconv* lc = localeconv_l(loc.get());
5898#else
5899 lconv* lc = __localeconv_l(loc.get());
5900#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005901 if (*lc->mon_decimal_point)
5902 __decimal_point_ = *lc->mon_decimal_point;
5903 else
5904 __decimal_point_ = base::do_decimal_point();
5905 if (*lc->mon_thousands_sep)
5906 __thousands_sep_ = *lc->mon_thousands_sep;
5907 else
5908 __thousands_sep_ = base::do_thousands_sep();
5909 __grouping_ = lc->mon_grouping;
5910 __curr_symbol_ = lc->currency_symbol;
5911 if (lc->frac_digits != CHAR_MAX)
5912 __frac_digits_ = lc->frac_digits;
5913 else
5914 __frac_digits_ = base::do_frac_digits();
5915 if (lc->p_sign_posn == 0)
5916 __positive_sign_ = "()";
5917 else
5918 __positive_sign_ = lc->positive_sign;
5919 if (lc->n_sign_posn == 0)
5920 __negative_sign_ = "()";
5921 else
5922 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005923 // Assume the positive and negative formats will want spaces in
5924 // the same places in curr_symbol since there's no way to
5925 // represent anything else.
5926 string_type __dummy_curr_symbol = __curr_symbol_;
5927 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5928 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5929 __init_pat(__neg_format_, __curr_symbol_, false,
5930 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005931}
5932
5933template<>
5934void
5935moneypunct_byname<char, true>::init(const char* nm)
5936{
5937 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005938 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005939#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005940 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005941 throw runtime_error("moneypunct_byname"
5942 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005943#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005944#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005945 lconv* lc = localeconv_l(loc.get());
5946#else
5947 lconv* lc = __localeconv_l(loc.get());
5948#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005949 if (*lc->mon_decimal_point)
5950 __decimal_point_ = *lc->mon_decimal_point;
5951 else
5952 __decimal_point_ = base::do_decimal_point();
5953 if (*lc->mon_thousands_sep)
5954 __thousands_sep_ = *lc->mon_thousands_sep;
5955 else
5956 __thousands_sep_ = base::do_thousands_sep();
5957 __grouping_ = lc->mon_grouping;
5958 __curr_symbol_ = lc->int_curr_symbol;
5959 if (lc->int_frac_digits != CHAR_MAX)
5960 __frac_digits_ = lc->int_frac_digits;
5961 else
5962 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005963#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005964 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005965#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005966 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005967#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005968 __positive_sign_ = "()";
5969 else
5970 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005971#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005972 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005973#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005974 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005975#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005976 __negative_sign_ = "()";
5977 else
5978 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005979 // Assume the positive and negative formats will want spaces in
5980 // the same places in curr_symbol since there's no way to
5981 // represent anything else.
5982 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005983#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005984 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5985 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5986 __init_pat(__neg_format_, __curr_symbol_, true,
5987 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005988#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005989 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5990 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5991 lc->int_p_sign_posn, ' ');
5992 __init_pat(__neg_format_, __curr_symbol_, true,
5993 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5994 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005995#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005996}
5997
5998template<>
5999void
6000moneypunct_byname<wchar_t, false>::init(const char* nm)
6001{
6002 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006003 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00006004#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00006005 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006006 throw runtime_error("moneypunct_byname"
6007 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00006008#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006009#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006010 lconv* lc = localeconv_l(loc.get());
6011#else
6012 lconv* lc = __localeconv_l(loc.get());
6013#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006014 if (*lc->mon_decimal_point)
6015 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6016 else
6017 __decimal_point_ = base::do_decimal_point();
6018 if (*lc->mon_thousands_sep)
6019 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6020 else
6021 __thousands_sep_ = base::do_thousands_sep();
6022 __grouping_ = lc->mon_grouping;
6023 wchar_t wbuf[100];
6024 mbstate_t mb = {0};
6025 const char* bb = lc->currency_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006026#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006027 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006028#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006029 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006030#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006031 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006032 __throw_runtime_error("locale not supported");
6033 wchar_t* wbe = wbuf + j;
6034 __curr_symbol_.assign(wbuf, wbe);
6035 if (lc->frac_digits != CHAR_MAX)
6036 __frac_digits_ = lc->frac_digits;
6037 else
6038 __frac_digits_ = base::do_frac_digits();
6039 if (lc->p_sign_posn == 0)
6040 __positive_sign_ = L"()";
6041 else
6042 {
6043 mb = mbstate_t();
6044 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006045#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006046 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006047#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006048 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006049#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006050 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006051 __throw_runtime_error("locale not supported");
6052 wbe = wbuf + j;
6053 __positive_sign_.assign(wbuf, wbe);
6054 }
6055 if (lc->n_sign_posn == 0)
6056 __negative_sign_ = L"()";
6057 else
6058 {
6059 mb = mbstate_t();
6060 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006061#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006062 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006063#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006064 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006065#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006066 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006067 __throw_runtime_error("locale not supported");
6068 wbe = wbuf + j;
6069 __negative_sign_.assign(wbuf, wbe);
6070 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006071 // Assume the positive and negative formats will want spaces in
6072 // the same places in curr_symbol since there's no way to
6073 // represent anything else.
6074 string_type __dummy_curr_symbol = __curr_symbol_;
6075 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6076 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6077 __init_pat(__neg_format_, __curr_symbol_, false,
6078 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006079}
6080
6081template<>
6082void
6083moneypunct_byname<wchar_t, true>::init(const char* nm)
6084{
6085 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006086 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00006087#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00006088 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006089 throw runtime_error("moneypunct_byname"
6090 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00006091#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006092#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006093 lconv* lc = localeconv_l(loc.get());
6094#else
6095 lconv* lc = __localeconv_l(loc.get());
6096#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006097 if (*lc->mon_decimal_point)
6098 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6099 else
6100 __decimal_point_ = base::do_decimal_point();
6101 if (*lc->mon_thousands_sep)
6102 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6103 else
6104 __thousands_sep_ = base::do_thousands_sep();
6105 __grouping_ = lc->mon_grouping;
6106 wchar_t wbuf[100];
6107 mbstate_t mb = {0};
6108 const char* bb = lc->int_curr_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006109#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006110 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006111#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006112 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006113#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006114 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006115 __throw_runtime_error("locale not supported");
6116 wchar_t* wbe = wbuf + j;
6117 __curr_symbol_.assign(wbuf, wbe);
6118 if (lc->int_frac_digits != CHAR_MAX)
6119 __frac_digits_ = lc->int_frac_digits;
6120 else
6121 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006122#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006123 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006124#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006125 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006126#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006127 __positive_sign_ = L"()";
6128 else
6129 {
6130 mb = mbstate_t();
6131 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006132#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006133 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006134#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006135 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006136#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006137 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006138 __throw_runtime_error("locale not supported");
6139 wbe = wbuf + j;
6140 __positive_sign_.assign(wbuf, wbe);
6141 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006142#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006143 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006144#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006145 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006146#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006147 __negative_sign_ = L"()";
6148 else
6149 {
6150 mb = mbstate_t();
6151 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006152#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006153 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006154#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006155 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006156#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006157 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006158 __throw_runtime_error("locale not supported");
6159 wbe = wbuf + j;
6160 __negative_sign_.assign(wbuf, wbe);
6161 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006162 // Assume the positive and negative formats will want spaces in
6163 // the same places in curr_symbol since there's no way to
6164 // represent anything else.
6165 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006166#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006167 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6168 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6169 __init_pat(__neg_format_, __curr_symbol_, true,
6170 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006171#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006172 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6173 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6174 lc->int_p_sign_posn, L' ');
6175 __init_pat(__neg_format_, __curr_symbol_, true,
6176 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6177 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006178#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006179}
6180
6181void __do_nothing(void*) {}
6182
6183void __throw_runtime_error(const char* msg)
6184{
Howard Hinnant72f73582010-08-11 17:04:31 +00006185#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006186 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006187#else
6188 (void)msg;
Howard Hinnant72f73582010-08-11 17:04:31 +00006189#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006190}
6191
6192template class collate<char>;
6193template class collate<wchar_t>;
6194
6195template class num_get<char>;
6196template class num_get<wchar_t>;
6197
Howard Hinnant28b24882011-12-01 20:21:04 +00006198template struct __num_get<char>;
6199template struct __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006200
6201template class num_put<char>;
6202template class num_put<wchar_t>;
6203
Howard Hinnant28b24882011-12-01 20:21:04 +00006204template struct __num_put<char>;
6205template struct __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006206
6207template class time_get<char>;
6208template class time_get<wchar_t>;
6209
6210template class time_get_byname<char>;
6211template class time_get_byname<wchar_t>;
6212
6213template class time_put<char>;
6214template class time_put<wchar_t>;
6215
6216template class time_put_byname<char>;
6217template class time_put_byname<wchar_t>;
6218
6219template class moneypunct<char, false>;
6220template class moneypunct<char, true>;
6221template class moneypunct<wchar_t, false>;
6222template class moneypunct<wchar_t, true>;
6223
6224template class moneypunct_byname<char, false>;
6225template class moneypunct_byname<char, true>;
6226template class moneypunct_byname<wchar_t, false>;
6227template class moneypunct_byname<wchar_t, true>;
6228
6229template class money_get<char>;
6230template class money_get<wchar_t>;
6231
6232template class __money_get<char>;
6233template class __money_get<wchar_t>;
6234
6235template class money_put<char>;
6236template class money_put<wchar_t>;
6237
6238template class __money_put<char>;
6239template class __money_put<wchar_t>;
6240
6241template class messages<char>;
6242template class messages<wchar_t>;
6243
6244template class messages_byname<char>;
6245template class messages_byname<wchar_t>;
6246
6247template class codecvt_byname<char, char, mbstate_t>;
6248template class codecvt_byname<wchar_t, char, mbstate_t>;
6249template class codecvt_byname<char16_t, char, mbstate_t>;
6250template class codecvt_byname<char32_t, char, mbstate_t>;
6251
6252template class __vector_base_common<true>;
6253
6254_LIBCPP_END_NAMESPACE_STD