blob: 729022689adfe0797655f929019620b3d3ed1da3 [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;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001122#else
David Chisnall8074c342012-02-29 13:05:08 +00001123 // Platform not supported: abort so the person doing the port knows what to
1124 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001125# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001126 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001127 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001128 return NULL;
1129#endif
1130}
Marshall Clowb3f62842015-03-04 16:10:14 +00001131#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001132
Howard Hinnantd7a78632011-09-29 13:33:15 +00001133#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001134const int*
1135ctype<char>::__classic_lower_table() _NOEXCEPT
1136{
Alexis Hunt92b0c812011-07-09 00:56:23 +00001137 return __cloc()->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001138}
1139
1140const int*
1141ctype<char>::__classic_upper_table() _NOEXCEPT
1142{
Alexis Hunt92b0c812011-07-09 00:56:23 +00001143 return __cloc()->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001144}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001145#elif __NetBSD__
1146const short*
1147ctype<char>::__classic_lower_table() _NOEXCEPT
1148{
1149 return _C_tolower_tab_ + 1;
1150}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001151
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001152const short*
1153ctype<char>::__classic_upper_table() _NOEXCEPT
1154{
1155 return _C_toupper_tab_ + 1;
1156}
1157
Marshall Cloweae03f62013-11-19 18:05:03 +00001158#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001159const int*
1160ctype<char>::__classic_lower_table() _NOEXCEPT
1161{
1162 return *__ctype_tolower_loc();
1163}
1164
1165const int*
1166ctype<char>::__classic_upper_table() _NOEXCEPT
1167{
1168 return *__ctype_toupper_loc();
1169}
Marshall Cloweae03f62013-11-19 18:05:03 +00001170#endif // __GLIBC__ || __EMSCRIPTEN__ || __NETBSD__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001171
Howard Hinnantc51e1022010-05-11 19:42:16 +00001172// template <> class ctype_byname<char>
1173
1174ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1175 : ctype<char>(0, false, refs),
1176 __l(newlocale(LC_ALL_MASK, name, 0))
1177{
Howard Hinnant72f73582010-08-11 17:04:31 +00001178#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001179 if (__l == 0)
1180 throw runtime_error("ctype_byname<char>::ctype_byname"
1181 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001182#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001183}
1184
1185ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1186 : ctype<char>(0, false, refs),
1187 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1188{
Howard Hinnant72f73582010-08-11 17:04:31 +00001189#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001190 if (__l == 0)
1191 throw runtime_error("ctype_byname<char>::ctype_byname"
1192 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001193#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001194}
1195
1196ctype_byname<char>::~ctype_byname()
1197{
1198 freelocale(__l);
1199}
1200
1201char
1202ctype_byname<char>::do_toupper(char_type c) const
1203{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001204 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001205}
1206
1207const char*
1208ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1209{
1210 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001211 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001212 return low;
1213}
1214
1215char
1216ctype_byname<char>::do_tolower(char_type c) const
1217{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001218 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001219}
1220
1221const char*
1222ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1223{
1224 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001225 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001226 return low;
1227}
1228
1229// template <> class ctype_byname<wchar_t>
1230
1231ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1232 : ctype<wchar_t>(refs),
1233 __l(newlocale(LC_ALL_MASK, name, 0))
1234{
Howard Hinnant72f73582010-08-11 17:04:31 +00001235#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001236 if (__l == 0)
1237 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1238 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001239#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001240}
1241
1242ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1243 : ctype<wchar_t>(refs),
1244 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1245{
Howard Hinnant72f73582010-08-11 17:04:31 +00001246#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001247 if (__l == 0)
1248 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1249 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001250#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001251}
1252
1253ctype_byname<wchar_t>::~ctype_byname()
1254{
1255 freelocale(__l);
1256}
1257
1258bool
1259ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1260{
Alexis Huntc2017f12011-07-09 03:40:04 +00001261#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001262 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001263#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001264 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001265 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofs60570512014-08-27 00:39:47 +00001266 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1267 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1268 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1269 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1270 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1271 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1272 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1273 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1274 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1275 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001276 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001277#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001278}
1279
1280const wchar_t*
1281ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1282{
1283 for (; low != high; ++low, ++vec)
1284 {
1285 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001286 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001287 else
1288 {
1289 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001290 wint_t ch = static_cast<wint_t>(*low);
1291 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001292 *vec |= space;
Marshall Clowada0f732013-02-07 14:22:51 +00001293 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001294 *vec |= print;
Marshall Clowada0f732013-02-07 14:22:51 +00001295 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001296 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001297 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001298 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001299 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300 *vec |= lower;
Marshall Clowada0f732013-02-07 14:22:51 +00001301 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001302 *vec |= alpha;
Marshall Clowada0f732013-02-07 14:22:51 +00001303 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001304 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001305 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001306 *vec |= punct;
Marshall Clowada0f732013-02-07 14:22:51 +00001307 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001308 *vec |= xdigit;
1309 }
1310 }
1311 return low;
1312}
1313
1314const wchar_t*
1315ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1316{
1317 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001318 {
1319#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001320 if (iswctype_l(*low, m, __l))
1321 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001322#else
Marshall Clowada0f732013-02-07 14:22:51 +00001323 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs60570512014-08-27 00:39:47 +00001324 if (m & space && iswspace_l(ch, __l)) break;
1325 if (m & print && iswprint_l(ch, __l)) break;
1326 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1327 if (m & upper && iswupper_l(ch, __l)) break;
1328 if (m & lower && iswlower_l(ch, __l)) break;
1329 if (m & alpha && iswalpha_l(ch, __l)) break;
1330 if (m & digit && iswdigit_l(ch, __l)) break;
1331 if (m & punct && iswpunct_l(ch, __l)) break;
1332 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1333 if (m & blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001334#endif
1335 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001336 return low;
1337}
1338
1339const wchar_t*
1340ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1341{
1342 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001343 {
1344#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001345 if (!iswctype_l(*low, m, __l))
1346 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001347#else
Marshall Clowada0f732013-02-07 14:22:51 +00001348 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs60570512014-08-27 00:39:47 +00001349 if (m & space && iswspace_l(ch, __l)) continue;
1350 if (m & print && iswprint_l(ch, __l)) continue;
1351 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1352 if (m & upper && iswupper_l(ch, __l)) continue;
1353 if (m & lower && iswlower_l(ch, __l)) continue;
1354 if (m & alpha && iswalpha_l(ch, __l)) continue;
1355 if (m & digit && iswdigit_l(ch, __l)) continue;
1356 if (m & punct && iswpunct_l(ch, __l)) continue;
1357 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1358 if (m & blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001359 break;
1360#endif
1361 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001362 return low;
1363}
1364
1365wchar_t
1366ctype_byname<wchar_t>::do_toupper(char_type c) const
1367{
1368 return towupper_l(c, __l);
1369}
1370
1371const wchar_t*
1372ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1373{
1374 for (; low != high; ++low)
1375 *low = towupper_l(*low, __l);
1376 return low;
1377}
1378
1379wchar_t
1380ctype_byname<wchar_t>::do_tolower(char_type c) const
1381{
1382 return towlower_l(c, __l);
1383}
1384
1385const wchar_t*
1386ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1387{
1388 for (; low != high; ++low)
1389 *low = towlower_l(*low, __l);
1390 return low;
1391}
1392
1393wchar_t
1394ctype_byname<wchar_t>::do_widen(char c) const
1395{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001396#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001397 return btowc_l(c, __l);
1398#else
1399 return __btowc_l(c, __l);
1400#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001401}
1402
1403const char*
1404ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1405{
1406 for (; low != high; ++low, ++dest)
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001407#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001408 *dest = btowc_l(*low, __l);
1409#else
1410 *dest = __btowc_l(*low, __l);
1411#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001412 return low;
1413}
1414
1415char
1416ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1417{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001418#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001419 int r = wctob_l(c, __l);
1420#else
1421 int r = __wctob_l(c, __l);
1422#endif
Howard Hinnant434ebf72012-12-27 18:46:00 +00001423 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001424}
1425
1426const wchar_t*
1427ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1428{
1429 for (; low != high; ++low, ++dest)
1430 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001431#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001432 int r = wctob_l(*low, __l);
1433#else
1434 int r = __wctob_l(*low, __l);
1435#endif
Howard Hinnant434ebf72012-12-27 18:46:00 +00001436 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001437 }
1438 return low;
1439}
1440
1441// template <> class codecvt<char, char, mbstate_t>
1442
Howard Hinnantffb308e2010-08-22 00:03:27 +00001443locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001444
1445codecvt<char, char, mbstate_t>::~codecvt()
1446{
1447}
1448
1449codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001450codecvt<char, char, mbstate_t>::do_out(state_type&,
1451 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001452 extern_type* to, extern_type*, extern_type*& to_nxt) const
1453{
1454 frm_nxt = frm;
1455 to_nxt = to;
1456 return noconv;
1457}
1458
1459codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001460codecvt<char, char, mbstate_t>::do_in(state_type&,
1461 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001462 intern_type* to, intern_type*, intern_type*& to_nxt) const
1463{
1464 frm_nxt = frm;
1465 to_nxt = to;
1466 return noconv;
1467}
1468
1469codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001470codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001471 extern_type* to, extern_type*, extern_type*& to_nxt) const
1472{
1473 to_nxt = to;
1474 return noconv;
1475}
1476
1477int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001478codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001479{
1480 return 1;
1481}
1482
1483bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001484codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001485{
1486 return true;
1487}
1488
1489int
1490codecvt<char, char, mbstate_t>::do_length(state_type&,
1491 const extern_type* frm, const extern_type* end, size_t mx) const
1492{
Howard Hinnant28b24882011-12-01 20:21:04 +00001493 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001494}
1495
1496int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001497codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001498{
1499 return 1;
1500}
1501
1502// template <> class codecvt<wchar_t, char, mbstate_t>
1503
Howard Hinnantffb308e2010-08-22 00:03:27 +00001504locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001505
1506codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1507 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001508 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001509{
1510}
1511
1512codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1513 : locale::facet(refs),
1514 __l(newlocale(LC_ALL_MASK, nm, 0))
1515{
Howard Hinnant72f73582010-08-11 17:04:31 +00001516#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001517 if (__l == 0)
1518 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1519 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001520#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001521}
1522
1523codecvt<wchar_t, char, mbstate_t>::~codecvt()
1524{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001525 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001526 freelocale(__l);
1527}
1528
1529codecvt<wchar_t, char, mbstate_t>::result
1530codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001531 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001532 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1533{
1534 // look for first internal null in frm
1535 const intern_type* fend = frm;
1536 for (; fend != frm_end; ++fend)
1537 if (*fend == 0)
1538 break;
1539 // loop over all null-terminated sequences in frm
1540 to_nxt = to;
1541 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1542 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001543 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001544 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001545#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001546 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1547 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001548#else
1549 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1550#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001551 if (n == size_t(-1))
1552 {
1553 // need to recover to_nxt
1554 for (to_nxt = to; frm != frm_nxt; ++frm)
1555 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001556#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001557 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1558#else
1559 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1560#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001561 if (n == size_t(-1))
1562 break;
1563 to_nxt += n;
1564 }
1565 frm_nxt = frm;
1566 return error;
1567 }
1568 if (n == 0)
1569 return partial;
1570 to_nxt += n;
1571 if (to_nxt == to_end)
1572 break;
1573 if (fend != frm_end) // set up next null terminated sequence
1574 {
1575 // Try to write the terminating null
1576 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001577#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001578 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1579#else
1580 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1581#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001582 if (n == size_t(-1)) // on error
1583 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001584 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001585 return partial;
1586 for (extern_type* p = tmp; n; --n) // write it
1587 *to_nxt++ = *p++;
1588 ++frm_nxt;
1589 // look for next null in frm
1590 for (fend = frm_nxt; fend != frm_end; ++fend)
1591 if (*fend == 0)
1592 break;
1593 }
1594 }
1595 return frm_nxt == frm_end ? ok : partial;
1596}
1597
1598codecvt<wchar_t, char, mbstate_t>::result
1599codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001600 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001601 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1602{
1603 // look for first internal null in frm
1604 const extern_type* fend = frm;
1605 for (; fend != frm_end; ++fend)
1606 if (*fend == 0)
1607 break;
1608 // loop over all null-terminated sequences in frm
1609 to_nxt = to;
1610 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1611 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001612 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001613 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001614#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001615 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1616 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001617#else
1618 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1619#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001620 if (n == size_t(-1))
1621 {
1622 // need to recover to_nxt
1623 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1624 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001625#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001626 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1627 &save_state, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001628#else
1629 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1630#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001631 switch (n)
1632 {
1633 case 0:
1634 ++frm;
1635 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001636 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001637 frm_nxt = frm;
1638 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001639 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001640 frm_nxt = frm;
1641 return partial;
1642 default:
1643 frm += n;
1644 break;
1645 }
1646 }
1647 frm_nxt = frm;
1648 return frm_nxt == frm_end ? ok : partial;
1649 }
1650 if (n == 0)
1651 return error;
1652 to_nxt += n;
1653 if (to_nxt == to_end)
1654 break;
1655 if (fend != frm_end) // set up next null terminated sequence
1656 {
1657 // Try to write the terminating null
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001658#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001659 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1660#else
1661 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1662#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001663 if (n != 0) // on error
1664 return error;
1665 ++to_nxt;
1666 ++frm_nxt;
1667 // look for next null in frm
1668 for (fend = frm_nxt; fend != frm_end; ++fend)
1669 if (*fend == 0)
1670 break;
1671 }
1672 }
1673 return frm_nxt == frm_end ? ok : partial;
1674}
1675
1676codecvt<wchar_t, char, mbstate_t>::result
1677codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1678 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1679{
1680 to_nxt = to;
1681 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001682#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001683 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1684#else
1685 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1686#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001687 if (n == size_t(-1) || n == 0) // on error
1688 return error;
1689 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001690 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001691 return partial;
1692 for (extern_type* p = tmp; n; --n) // write it
1693 *to_nxt++ = *p++;
1694 return ok;
1695}
1696
1697int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001698codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001699{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001700#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001701 if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001702#else
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#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001705 {
1706 // stateless encoding
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001707#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001708 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1709#else
1710 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1711#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001712 return 1; // which take more than 1 char to form a wchar_t
1713 return 0;
1714 }
1715 return -1;
1716}
1717
1718bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001719codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001720{
1721 return false;
1722}
1723
1724int
1725codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1726 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1727{
1728 int nbytes = 0;
1729 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1730 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001731#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001732 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001733#else
1734 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1735#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001736 switch (n)
1737 {
1738 case 0:
1739 ++nbytes;
1740 ++frm;
1741 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001742 case size_t(-1):
1743 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001744 return nbytes;
1745 default:
1746 nbytes += n;
1747 frm += n;
1748 break;
1749 }
1750 }
1751 return nbytes;
1752}
1753
1754int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001755codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001756{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001757#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clowab9c1772013-02-07 17:20:56 +00001758 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001759#else
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#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001762}
1763
1764// Valid UTF ranges
1765// UTF-32 UTF-16 UTF-8 # of code points
1766// first second first second third fourth
1767// 000000 - 00007F 0000 - 007F 00 - 7F 127
1768// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1769// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1770// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1771// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1772// 00D800 - 00DFFF invalid
1773// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1774// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1775// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1776// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1777
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001778static
1779codecvt_base::result
1780utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1781 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1782 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1783{
1784 frm_nxt = frm;
1785 to_nxt = to;
1786 if (mode & generate_header)
1787 {
1788 if (to_end-to_nxt < 3)
1789 return codecvt_base::partial;
1790 *to_nxt++ = static_cast<uint8_t>(0xEF);
1791 *to_nxt++ = static_cast<uint8_t>(0xBB);
1792 *to_nxt++ = static_cast<uint8_t>(0xBF);
1793 }
1794 for (; frm_nxt < frm_end; ++frm_nxt)
1795 {
1796 uint16_t wc1 = *frm_nxt;
1797 if (wc1 > Maxcode)
1798 return codecvt_base::error;
1799 if (wc1 < 0x0080)
1800 {
1801 if (to_end-to_nxt < 1)
1802 return codecvt_base::partial;
1803 *to_nxt++ = static_cast<uint8_t>(wc1);
1804 }
1805 else if (wc1 < 0x0800)
1806 {
1807 if (to_end-to_nxt < 2)
1808 return codecvt_base::partial;
1809 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1810 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1811 }
1812 else if (wc1 < 0xD800)
1813 {
1814 if (to_end-to_nxt < 3)
1815 return codecvt_base::partial;
1816 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1817 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1818 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1819 }
1820 else if (wc1 < 0xDC00)
1821 {
1822 if (frm_end-frm_nxt < 2)
1823 return codecvt_base::partial;
1824 uint16_t wc2 = frm_nxt[1];
1825 if ((wc2 & 0xFC00) != 0xDC00)
1826 return codecvt_base::error;
1827 if (to_end-to_nxt < 4)
1828 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001829 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1830 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001831 return codecvt_base::error;
1832 ++frm_nxt;
1833 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1834 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1835 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1836 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1837 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1838 }
1839 else if (wc1 < 0xE000)
1840 {
1841 return codecvt_base::error;
1842 }
1843 else
1844 {
1845 if (to_end-to_nxt < 3)
1846 return codecvt_base::partial;
1847 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1848 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1849 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1850 }
1851 }
1852 return codecvt_base::ok;
1853}
1854
1855static
1856codecvt_base::result
1857utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1858 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1859 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1860{
1861 frm_nxt = frm;
1862 to_nxt = to;
1863 if (mode & generate_header)
1864 {
1865 if (to_end-to_nxt < 3)
1866 return codecvt_base::partial;
1867 *to_nxt++ = static_cast<uint8_t>(0xEF);
1868 *to_nxt++ = static_cast<uint8_t>(0xBB);
1869 *to_nxt++ = static_cast<uint8_t>(0xBF);
1870 }
1871 for (; frm_nxt < frm_end; ++frm_nxt)
1872 {
1873 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1874 if (wc1 > Maxcode)
1875 return codecvt_base::error;
1876 if (wc1 < 0x0080)
1877 {
1878 if (to_end-to_nxt < 1)
1879 return codecvt_base::partial;
1880 *to_nxt++ = static_cast<uint8_t>(wc1);
1881 }
1882 else if (wc1 < 0x0800)
1883 {
1884 if (to_end-to_nxt < 2)
1885 return codecvt_base::partial;
1886 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1887 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1888 }
1889 else if (wc1 < 0xD800)
1890 {
1891 if (to_end-to_nxt < 3)
1892 return codecvt_base::partial;
1893 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1894 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1895 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1896 }
1897 else if (wc1 < 0xDC00)
1898 {
1899 if (frm_end-frm_nxt < 2)
1900 return codecvt_base::partial;
1901 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1902 if ((wc2 & 0xFC00) != 0xDC00)
1903 return codecvt_base::error;
1904 if (to_end-to_nxt < 4)
1905 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001906 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1907 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001908 return codecvt_base::error;
1909 ++frm_nxt;
1910 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1911 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1912 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1913 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1914 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1915 }
1916 else if (wc1 < 0xE000)
1917 {
1918 return codecvt_base::error;
1919 }
1920 else
1921 {
1922 if (to_end-to_nxt < 3)
1923 return codecvt_base::partial;
1924 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1925 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1926 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1927 }
1928 }
1929 return codecvt_base::ok;
1930}
1931
1932static
1933codecvt_base::result
1934utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1935 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1936 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1937{
1938 frm_nxt = frm;
1939 to_nxt = to;
1940 if (mode & consume_header)
1941 {
1942 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1943 frm_nxt[2] == 0xBF)
1944 frm_nxt += 3;
1945 }
1946 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1947 {
1948 uint8_t c1 = *frm_nxt;
1949 if (c1 > Maxcode)
1950 return codecvt_base::error;
1951 if (c1 < 0x80)
1952 {
1953 *to_nxt = static_cast<uint16_t>(c1);
1954 ++frm_nxt;
1955 }
1956 else if (c1 < 0xC2)
1957 {
1958 return codecvt_base::error;
1959 }
1960 else if (c1 < 0xE0)
1961 {
1962 if (frm_end-frm_nxt < 2)
1963 return codecvt_base::partial;
1964 uint8_t c2 = frm_nxt[1];
1965 if ((c2 & 0xC0) != 0x80)
1966 return codecvt_base::error;
1967 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1968 if (t > Maxcode)
1969 return codecvt_base::error;
1970 *to_nxt = t;
1971 frm_nxt += 2;
1972 }
1973 else if (c1 < 0xF0)
1974 {
1975 if (frm_end-frm_nxt < 3)
1976 return codecvt_base::partial;
1977 uint8_t c2 = frm_nxt[1];
1978 uint8_t c3 = frm_nxt[2];
1979 switch (c1)
1980 {
1981 case 0xE0:
1982 if ((c2 & 0xE0) != 0xA0)
1983 return codecvt_base::error;
1984 break;
1985 case 0xED:
1986 if ((c2 & 0xE0) != 0x80)
1987 return codecvt_base::error;
1988 break;
1989 default:
1990 if ((c2 & 0xC0) != 0x80)
1991 return codecvt_base::error;
1992 break;
1993 }
1994 if ((c3 & 0xC0) != 0x80)
1995 return codecvt_base::error;
1996 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1997 | ((c2 & 0x3F) << 6)
1998 | (c3 & 0x3F));
1999 if (t > Maxcode)
2000 return codecvt_base::error;
2001 *to_nxt = t;
2002 frm_nxt += 3;
2003 }
2004 else if (c1 < 0xF5)
2005 {
2006 if (frm_end-frm_nxt < 4)
2007 return codecvt_base::partial;
2008 uint8_t c2 = frm_nxt[1];
2009 uint8_t c3 = frm_nxt[2];
2010 uint8_t c4 = frm_nxt[3];
2011 switch (c1)
2012 {
2013 case 0xF0:
2014 if (!(0x90 <= c2 && c2 <= 0xBF))
2015 return codecvt_base::error;
2016 break;
2017 case 0xF4:
2018 if ((c2 & 0xF0) != 0x80)
2019 return codecvt_base::error;
2020 break;
2021 default:
2022 if ((c2 & 0xC0) != 0x80)
2023 return codecvt_base::error;
2024 break;
2025 }
2026 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2027 return codecvt_base::error;
2028 if (to_end-to_nxt < 2)
2029 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002030 if ((((c1 & 7UL) << 18) +
2031 ((c2 & 0x3FUL) << 12) +
2032 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002033 return codecvt_base::error;
2034 *to_nxt = static_cast<uint16_t>(
2035 0xD800
2036 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2037 | ((c2 & 0x0F) << 2)
2038 | ((c3 & 0x30) >> 4));
2039 *++to_nxt = static_cast<uint16_t>(
2040 0xDC00
2041 | ((c3 & 0x0F) << 6)
2042 | (c4 & 0x3F));
2043 frm_nxt += 4;
2044 }
2045 else
2046 {
2047 return codecvt_base::error;
2048 }
2049 }
2050 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2051}
2052
2053static
2054codecvt_base::result
2055utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2056 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2057 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2058{
2059 frm_nxt = frm;
2060 to_nxt = to;
2061 if (mode & consume_header)
2062 {
2063 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2064 frm_nxt[2] == 0xBF)
2065 frm_nxt += 3;
2066 }
2067 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2068 {
2069 uint8_t c1 = *frm_nxt;
2070 if (c1 > Maxcode)
2071 return codecvt_base::error;
2072 if (c1 < 0x80)
2073 {
2074 *to_nxt = static_cast<uint32_t>(c1);
2075 ++frm_nxt;
2076 }
2077 else if (c1 < 0xC2)
2078 {
2079 return codecvt_base::error;
2080 }
2081 else if (c1 < 0xE0)
2082 {
2083 if (frm_end-frm_nxt < 2)
2084 return codecvt_base::partial;
2085 uint8_t c2 = frm_nxt[1];
2086 if ((c2 & 0xC0) != 0x80)
2087 return codecvt_base::error;
2088 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2089 if (t > Maxcode)
2090 return codecvt_base::error;
2091 *to_nxt = static_cast<uint32_t>(t);
2092 frm_nxt += 2;
2093 }
2094 else if (c1 < 0xF0)
2095 {
2096 if (frm_end-frm_nxt < 3)
2097 return codecvt_base::partial;
2098 uint8_t c2 = frm_nxt[1];
2099 uint8_t c3 = frm_nxt[2];
2100 switch (c1)
2101 {
2102 case 0xE0:
2103 if ((c2 & 0xE0) != 0xA0)
2104 return codecvt_base::error;
2105 break;
2106 case 0xED:
2107 if ((c2 & 0xE0) != 0x80)
2108 return codecvt_base::error;
2109 break;
2110 default:
2111 if ((c2 & 0xC0) != 0x80)
2112 return codecvt_base::error;
2113 break;
2114 }
2115 if ((c3 & 0xC0) != 0x80)
2116 return codecvt_base::error;
2117 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2118 | ((c2 & 0x3F) << 6)
2119 | (c3 & 0x3F));
2120 if (t > Maxcode)
2121 return codecvt_base::error;
2122 *to_nxt = static_cast<uint32_t>(t);
2123 frm_nxt += 3;
2124 }
2125 else if (c1 < 0xF5)
2126 {
2127 if (frm_end-frm_nxt < 4)
2128 return codecvt_base::partial;
2129 uint8_t c2 = frm_nxt[1];
2130 uint8_t c3 = frm_nxt[2];
2131 uint8_t c4 = frm_nxt[3];
2132 switch (c1)
2133 {
2134 case 0xF0:
2135 if (!(0x90 <= c2 && c2 <= 0xBF))
2136 return codecvt_base::error;
2137 break;
2138 case 0xF4:
2139 if ((c2 & 0xF0) != 0x80)
2140 return codecvt_base::error;
2141 break;
2142 default:
2143 if ((c2 & 0xC0) != 0x80)
2144 return codecvt_base::error;
2145 break;
2146 }
2147 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2148 return codecvt_base::error;
2149 if (to_end-to_nxt < 2)
2150 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002151 if ((((c1 & 7UL) << 18) +
2152 ((c2 & 0x3FUL) << 12) +
2153 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002154 return codecvt_base::error;
2155 *to_nxt = static_cast<uint32_t>(
2156 0xD800
2157 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2158 | ((c2 & 0x0F) << 2)
2159 | ((c3 & 0x30) >> 4));
2160 *++to_nxt = static_cast<uint32_t>(
2161 0xDC00
2162 | ((c3 & 0x0F) << 6)
2163 | (c4 & 0x3F));
2164 frm_nxt += 4;
2165 }
2166 else
2167 {
2168 return codecvt_base::error;
2169 }
2170 }
2171 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2172}
2173
2174static
2175int
2176utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2177 size_t mx, unsigned long Maxcode = 0x10FFFF,
2178 codecvt_mode mode = codecvt_mode(0))
2179{
2180 const uint8_t* frm_nxt = frm;
2181 if (mode & consume_header)
2182 {
2183 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2184 frm_nxt[2] == 0xBF)
2185 frm_nxt += 3;
2186 }
2187 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2188 {
2189 uint8_t c1 = *frm_nxt;
2190 if (c1 > Maxcode)
2191 break;
2192 if (c1 < 0x80)
2193 {
2194 ++frm_nxt;
2195 }
2196 else if (c1 < 0xC2)
2197 {
2198 break;
2199 }
2200 else if (c1 < 0xE0)
2201 {
2202 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2203 break;
2204 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2205 if (t > Maxcode)
2206 break;
2207 frm_nxt += 2;
2208 }
2209 else if (c1 < 0xF0)
2210 {
2211 if (frm_end-frm_nxt < 3)
2212 break;
2213 uint8_t c2 = frm_nxt[1];
2214 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002215 switch (c1)
2216 {
2217 case 0xE0:
2218 if ((c2 & 0xE0) != 0xA0)
2219 return static_cast<int>(frm_nxt - frm);
2220 break;
2221 case 0xED:
2222 if ((c2 & 0xE0) != 0x80)
2223 return static_cast<int>(frm_nxt - frm);
2224 break;
2225 default:
2226 if ((c2 & 0xC0) != 0x80)
2227 return static_cast<int>(frm_nxt - frm);
2228 break;
2229 }
2230 if ((c3 & 0xC0) != 0x80)
2231 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002232 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002233 break;
2234 frm_nxt += 3;
2235 }
2236 else if (c1 < 0xF5)
2237 {
2238 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2239 break;
2240 uint8_t c2 = frm_nxt[1];
2241 uint8_t c3 = frm_nxt[2];
2242 uint8_t c4 = frm_nxt[3];
2243 switch (c1)
2244 {
2245 case 0xF0:
2246 if (!(0x90 <= c2 && c2 <= 0xBF))
2247 return static_cast<int>(frm_nxt - frm);
2248 break;
2249 case 0xF4:
2250 if ((c2 & 0xF0) != 0x80)
2251 return static_cast<int>(frm_nxt - frm);
2252 break;
2253 default:
2254 if ((c2 & 0xC0) != 0x80)
2255 return static_cast<int>(frm_nxt - frm);
2256 break;
2257 }
2258 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2259 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002260 if ((((c1 & 7UL) << 18) +
2261 ((c2 & 0x3FUL) << 12) +
2262 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002263 break;
2264 ++nchar16_t;
2265 frm_nxt += 4;
2266 }
2267 else
2268 {
2269 break;
2270 }
2271 }
2272 return static_cast<int>(frm_nxt - frm);
2273}
2274
2275static
2276codecvt_base::result
2277ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2278 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2279 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2280{
2281 frm_nxt = frm;
2282 to_nxt = to;
2283 if (mode & generate_header)
2284 {
2285 if (to_end-to_nxt < 3)
2286 return codecvt_base::partial;
2287 *to_nxt++ = static_cast<uint8_t>(0xEF);
2288 *to_nxt++ = static_cast<uint8_t>(0xBB);
2289 *to_nxt++ = static_cast<uint8_t>(0xBF);
2290 }
2291 for (; frm_nxt < frm_end; ++frm_nxt)
2292 {
2293 uint32_t wc = *frm_nxt;
2294 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2295 return codecvt_base::error;
2296 if (wc < 0x000080)
2297 {
2298 if (to_end-to_nxt < 1)
2299 return codecvt_base::partial;
2300 *to_nxt++ = static_cast<uint8_t>(wc);
2301 }
2302 else if (wc < 0x000800)
2303 {
2304 if (to_end-to_nxt < 2)
2305 return codecvt_base::partial;
2306 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2307 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2308 }
2309 else if (wc < 0x010000)
2310 {
2311 if (to_end-to_nxt < 3)
2312 return codecvt_base::partial;
2313 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2314 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2315 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2316 }
2317 else // if (wc < 0x110000)
2318 {
2319 if (to_end-to_nxt < 4)
2320 return codecvt_base::partial;
2321 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2322 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2323 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2324 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2325 }
2326 }
2327 return codecvt_base::ok;
2328}
2329
2330static
2331codecvt_base::result
2332utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2333 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2334 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2335{
2336 frm_nxt = frm;
2337 to_nxt = to;
2338 if (mode & consume_header)
2339 {
2340 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2341 frm_nxt[2] == 0xBF)
2342 frm_nxt += 3;
2343 }
2344 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2345 {
2346 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2347 if (c1 < 0x80)
2348 {
2349 if (c1 > Maxcode)
2350 return codecvt_base::error;
2351 *to_nxt = static_cast<uint32_t>(c1);
2352 ++frm_nxt;
2353 }
2354 else if (c1 < 0xC2)
2355 {
2356 return codecvt_base::error;
2357 }
2358 else if (c1 < 0xE0)
2359 {
2360 if (frm_end-frm_nxt < 2)
2361 return codecvt_base::partial;
2362 uint8_t c2 = frm_nxt[1];
2363 if ((c2 & 0xC0) != 0x80)
2364 return codecvt_base::error;
2365 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2366 | (c2 & 0x3F));
2367 if (t > Maxcode)
2368 return codecvt_base::error;
2369 *to_nxt = t;
2370 frm_nxt += 2;
2371 }
2372 else if (c1 < 0xF0)
2373 {
2374 if (frm_end-frm_nxt < 3)
2375 return codecvt_base::partial;
2376 uint8_t c2 = frm_nxt[1];
2377 uint8_t c3 = frm_nxt[2];
2378 switch (c1)
2379 {
2380 case 0xE0:
2381 if ((c2 & 0xE0) != 0xA0)
2382 return codecvt_base::error;
2383 break;
2384 case 0xED:
2385 if ((c2 & 0xE0) != 0x80)
2386 return codecvt_base::error;
2387 break;
2388 default:
2389 if ((c2 & 0xC0) != 0x80)
2390 return codecvt_base::error;
2391 break;
2392 }
2393 if ((c3 & 0xC0) != 0x80)
2394 return codecvt_base::error;
2395 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2396 | ((c2 & 0x3F) << 6)
2397 | (c3 & 0x3F));
2398 if (t > Maxcode)
2399 return codecvt_base::error;
2400 *to_nxt = t;
2401 frm_nxt += 3;
2402 }
2403 else if (c1 < 0xF5)
2404 {
2405 if (frm_end-frm_nxt < 4)
2406 return codecvt_base::partial;
2407 uint8_t c2 = frm_nxt[1];
2408 uint8_t c3 = frm_nxt[2];
2409 uint8_t c4 = frm_nxt[3];
2410 switch (c1)
2411 {
2412 case 0xF0:
2413 if (!(0x90 <= c2 && c2 <= 0xBF))
2414 return codecvt_base::error;
2415 break;
2416 case 0xF4:
2417 if ((c2 & 0xF0) != 0x80)
2418 return codecvt_base::error;
2419 break;
2420 default:
2421 if ((c2 & 0xC0) != 0x80)
2422 return codecvt_base::error;
2423 break;
2424 }
2425 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2426 return codecvt_base::error;
2427 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2428 | ((c2 & 0x3F) << 12)
2429 | ((c3 & 0x3F) << 6)
2430 | (c4 & 0x3F));
2431 if (t > Maxcode)
2432 return codecvt_base::error;
2433 *to_nxt = t;
2434 frm_nxt += 4;
2435 }
2436 else
2437 {
2438 return codecvt_base::error;
2439 }
2440 }
2441 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2442}
2443
2444static
2445int
2446utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2447 size_t mx, unsigned long Maxcode = 0x10FFFF,
2448 codecvt_mode mode = codecvt_mode(0))
2449{
2450 const uint8_t* frm_nxt = frm;
2451 if (mode & consume_header)
2452 {
2453 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2454 frm_nxt[2] == 0xBF)
2455 frm_nxt += 3;
2456 }
2457 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2458 {
2459 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2460 if (c1 < 0x80)
2461 {
2462 if (c1 > Maxcode)
2463 break;
2464 ++frm_nxt;
2465 }
2466 else if (c1 < 0xC2)
2467 {
2468 break;
2469 }
2470 else if (c1 < 0xE0)
2471 {
2472 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2473 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002474 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002475 break;
2476 frm_nxt += 2;
2477 }
2478 else if (c1 < 0xF0)
2479 {
2480 if (frm_end-frm_nxt < 3)
2481 break;
2482 uint8_t c2 = frm_nxt[1];
2483 uint8_t c3 = frm_nxt[2];
2484 switch (c1)
2485 {
2486 case 0xE0:
2487 if ((c2 & 0xE0) != 0xA0)
2488 return static_cast<int>(frm_nxt - frm);
2489 break;
2490 case 0xED:
2491 if ((c2 & 0xE0) != 0x80)
2492 return static_cast<int>(frm_nxt - frm);
2493 break;
2494 default:
2495 if ((c2 & 0xC0) != 0x80)
2496 return static_cast<int>(frm_nxt - frm);
2497 break;
2498 }
2499 if ((c3 & 0xC0) != 0x80)
2500 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002501 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002502 break;
2503 frm_nxt += 3;
2504 }
2505 else if (c1 < 0xF5)
2506 {
2507 if (frm_end-frm_nxt < 4)
2508 break;
2509 uint8_t c2 = frm_nxt[1];
2510 uint8_t c3 = frm_nxt[2];
2511 uint8_t c4 = frm_nxt[3];
2512 switch (c1)
2513 {
2514 case 0xF0:
2515 if (!(0x90 <= c2 && c2 <= 0xBF))
2516 return static_cast<int>(frm_nxt - frm);
2517 break;
2518 case 0xF4:
2519 if ((c2 & 0xF0) != 0x80)
2520 return static_cast<int>(frm_nxt - frm);
2521 break;
2522 default:
2523 if ((c2 & 0xC0) != 0x80)
2524 return static_cast<int>(frm_nxt - frm);
2525 break;
2526 }
2527 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2528 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002529 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2530 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002531 break;
2532 frm_nxt += 4;
2533 }
2534 else
2535 {
2536 break;
2537 }
2538 }
2539 return static_cast<int>(frm_nxt - frm);
2540}
2541
2542static
2543codecvt_base::result
2544ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2545 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2546 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2547{
2548 frm_nxt = frm;
2549 to_nxt = to;
2550 if (mode & generate_header)
2551 {
2552 if (to_end-to_nxt < 3)
2553 return codecvt_base::partial;
2554 *to_nxt++ = static_cast<uint8_t>(0xEF);
2555 *to_nxt++ = static_cast<uint8_t>(0xBB);
2556 *to_nxt++ = static_cast<uint8_t>(0xBF);
2557 }
2558 for (; frm_nxt < frm_end; ++frm_nxt)
2559 {
2560 uint16_t wc = *frm_nxt;
2561 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2562 return codecvt_base::error;
2563 if (wc < 0x0080)
2564 {
2565 if (to_end-to_nxt < 1)
2566 return codecvt_base::partial;
2567 *to_nxt++ = static_cast<uint8_t>(wc);
2568 }
2569 else if (wc < 0x0800)
2570 {
2571 if (to_end-to_nxt < 2)
2572 return codecvt_base::partial;
2573 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2574 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2575 }
2576 else // if (wc <= 0xFFFF)
2577 {
2578 if (to_end-to_nxt < 3)
2579 return codecvt_base::partial;
2580 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2581 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2582 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2583 }
2584 }
2585 return codecvt_base::ok;
2586}
2587
2588static
2589codecvt_base::result
2590utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2591 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2592 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2593{
2594 frm_nxt = frm;
2595 to_nxt = to;
2596 if (mode & consume_header)
2597 {
2598 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2599 frm_nxt[2] == 0xBF)
2600 frm_nxt += 3;
2601 }
2602 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2603 {
2604 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2605 if (c1 < 0x80)
2606 {
2607 if (c1 > Maxcode)
2608 return codecvt_base::error;
2609 *to_nxt = static_cast<uint16_t>(c1);
2610 ++frm_nxt;
2611 }
2612 else if (c1 < 0xC2)
2613 {
2614 return codecvt_base::error;
2615 }
2616 else if (c1 < 0xE0)
2617 {
2618 if (frm_end-frm_nxt < 2)
2619 return codecvt_base::partial;
2620 uint8_t c2 = frm_nxt[1];
2621 if ((c2 & 0xC0) != 0x80)
2622 return codecvt_base::error;
2623 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2624 | (c2 & 0x3F));
2625 if (t > Maxcode)
2626 return codecvt_base::error;
2627 *to_nxt = t;
2628 frm_nxt += 2;
2629 }
2630 else if (c1 < 0xF0)
2631 {
2632 if (frm_end-frm_nxt < 3)
2633 return codecvt_base::partial;
2634 uint8_t c2 = frm_nxt[1];
2635 uint8_t c3 = frm_nxt[2];
2636 switch (c1)
2637 {
2638 case 0xE0:
2639 if ((c2 & 0xE0) != 0xA0)
2640 return codecvt_base::error;
2641 break;
2642 case 0xED:
2643 if ((c2 & 0xE0) != 0x80)
2644 return codecvt_base::error;
2645 break;
2646 default:
2647 if ((c2 & 0xC0) != 0x80)
2648 return codecvt_base::error;
2649 break;
2650 }
2651 if ((c3 & 0xC0) != 0x80)
2652 return codecvt_base::error;
2653 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2654 | ((c2 & 0x3F) << 6)
2655 | (c3 & 0x3F));
2656 if (t > Maxcode)
2657 return codecvt_base::error;
2658 *to_nxt = t;
2659 frm_nxt += 3;
2660 }
2661 else
2662 {
2663 return codecvt_base::error;
2664 }
2665 }
2666 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2667}
2668
2669static
2670int
2671utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2672 size_t mx, unsigned long Maxcode = 0x10FFFF,
2673 codecvt_mode mode = codecvt_mode(0))
2674{
2675 const uint8_t* frm_nxt = frm;
2676 if (mode & consume_header)
2677 {
2678 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2679 frm_nxt[2] == 0xBF)
2680 frm_nxt += 3;
2681 }
2682 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2683 {
2684 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2685 if (c1 < 0x80)
2686 {
2687 if (c1 > Maxcode)
2688 break;
2689 ++frm_nxt;
2690 }
2691 else if (c1 < 0xC2)
2692 {
2693 break;
2694 }
2695 else if (c1 < 0xE0)
2696 {
2697 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2698 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002699 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002700 break;
2701 frm_nxt += 2;
2702 }
2703 else if (c1 < 0xF0)
2704 {
2705 if (frm_end-frm_nxt < 3)
2706 break;
2707 uint8_t c2 = frm_nxt[1];
2708 uint8_t c3 = frm_nxt[2];
2709 switch (c1)
2710 {
2711 case 0xE0:
2712 if ((c2 & 0xE0) != 0xA0)
2713 return static_cast<int>(frm_nxt - frm);
2714 break;
2715 case 0xED:
2716 if ((c2 & 0xE0) != 0x80)
2717 return static_cast<int>(frm_nxt - frm);
2718 break;
2719 default:
2720 if ((c2 & 0xC0) != 0x80)
2721 return static_cast<int>(frm_nxt - frm);
2722 break;
2723 }
2724 if ((c3 & 0xC0) != 0x80)
2725 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002726 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002727 break;
2728 frm_nxt += 3;
2729 }
2730 else
2731 {
2732 break;
2733 }
2734 }
2735 return static_cast<int>(frm_nxt - frm);
2736}
2737
2738static
2739codecvt_base::result
2740ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2741 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2742 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2743{
2744 frm_nxt = frm;
2745 to_nxt = to;
2746 if (mode & generate_header)
2747 {
2748 if (to_end-to_nxt < 2)
2749 return codecvt_base::partial;
2750 *to_nxt++ = static_cast<uint8_t>(0xFE);
2751 *to_nxt++ = static_cast<uint8_t>(0xFF);
2752 }
2753 for (; frm_nxt < frm_end; ++frm_nxt)
2754 {
2755 uint32_t wc = *frm_nxt;
2756 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2757 return codecvt_base::error;
2758 if (wc < 0x010000)
2759 {
2760 if (to_end-to_nxt < 2)
2761 return codecvt_base::partial;
2762 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2763 *to_nxt++ = static_cast<uint8_t>(wc);
2764 }
2765 else
2766 {
2767 if (to_end-to_nxt < 4)
2768 return codecvt_base::partial;
2769 uint16_t t = static_cast<uint16_t>(
2770 0xD800
2771 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2772 | ((wc & 0x00FC00) >> 10));
2773 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2774 *to_nxt++ = static_cast<uint8_t>(t);
2775 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2776 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2777 *to_nxt++ = static_cast<uint8_t>(t);
2778 }
2779 }
2780 return codecvt_base::ok;
2781}
2782
2783static
2784codecvt_base::result
2785utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2786 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2787 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2788{
2789 frm_nxt = frm;
2790 to_nxt = to;
2791 if (mode & consume_header)
2792 {
2793 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2794 frm_nxt += 2;
2795 }
2796 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2797 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002798 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002799 if ((c1 & 0xFC00) == 0xDC00)
2800 return codecvt_base::error;
2801 if ((c1 & 0xFC00) != 0xD800)
2802 {
2803 if (c1 > Maxcode)
2804 return codecvt_base::error;
2805 *to_nxt = static_cast<uint32_t>(c1);
2806 frm_nxt += 2;
2807 }
2808 else
2809 {
2810 if (frm_end-frm_nxt < 4)
2811 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002812 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002813 if ((c2 & 0xFC00) != 0xDC00)
2814 return codecvt_base::error;
2815 uint32_t t = static_cast<uint32_t>(
2816 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2817 | ((c1 & 0x003F) << 10)
2818 | (c2 & 0x03FF));
2819 if (t > Maxcode)
2820 return codecvt_base::error;
2821 *to_nxt = t;
2822 frm_nxt += 4;
2823 }
2824 }
2825 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2826}
2827
2828static
2829int
2830utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2831 size_t mx, unsigned long Maxcode = 0x10FFFF,
2832 codecvt_mode mode = codecvt_mode(0))
2833{
2834 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002835 if (mode & consume_header)
2836 {
2837 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2838 frm_nxt += 2;
2839 }
2840 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2841 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002842 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002843 if ((c1 & 0xFC00) == 0xDC00)
2844 break;
2845 if ((c1 & 0xFC00) != 0xD800)
2846 {
2847 if (c1 > Maxcode)
2848 break;
2849 frm_nxt += 2;
2850 }
2851 else
2852 {
2853 if (frm_end-frm_nxt < 4)
2854 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002855 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002856 if ((c2 & 0xFC00) != 0xDC00)
2857 break;
2858 uint32_t t = static_cast<uint32_t>(
2859 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2860 | ((c1 & 0x003F) << 10)
2861 | (c2 & 0x03FF));
2862 if (t > Maxcode)
2863 break;
2864 frm_nxt += 4;
2865 }
2866 }
2867 return static_cast<int>(frm_nxt - frm);
2868}
2869
2870static
2871codecvt_base::result
2872ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2873 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2874 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2875{
2876 frm_nxt = frm;
2877 to_nxt = to;
2878 if (mode & generate_header)
2879 {
2880 if (to_end-to_nxt < 2)
2881 return codecvt_base::partial;
2882 *to_nxt++ = static_cast<uint8_t>(0xFF);
2883 *to_nxt++ = static_cast<uint8_t>(0xFE);
2884 }
2885 for (; frm_nxt < frm_end; ++frm_nxt)
2886 {
2887 uint32_t wc = *frm_nxt;
2888 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2889 return codecvt_base::error;
2890 if (wc < 0x010000)
2891 {
2892 if (to_end-to_nxt < 2)
2893 return codecvt_base::partial;
2894 *to_nxt++ = static_cast<uint8_t>(wc);
2895 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2896 }
2897 else
2898 {
2899 if (to_end-to_nxt < 4)
2900 return codecvt_base::partial;
2901 uint16_t t = static_cast<uint16_t>(
2902 0xD800
2903 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2904 | ((wc & 0x00FC00) >> 10));
2905 *to_nxt++ = static_cast<uint8_t>(t);
2906 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2907 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2908 *to_nxt++ = static_cast<uint8_t>(t);
2909 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2910 }
2911 }
2912 return codecvt_base::ok;
2913}
2914
2915static
2916codecvt_base::result
2917utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2918 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2919 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2920{
2921 frm_nxt = frm;
2922 to_nxt = to;
2923 if (mode & consume_header)
2924 {
2925 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2926 frm_nxt += 2;
2927 }
2928 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2929 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002930 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002931 if ((c1 & 0xFC00) == 0xDC00)
2932 return codecvt_base::error;
2933 if ((c1 & 0xFC00) != 0xD800)
2934 {
2935 if (c1 > Maxcode)
2936 return codecvt_base::error;
2937 *to_nxt = static_cast<uint32_t>(c1);
2938 frm_nxt += 2;
2939 }
2940 else
2941 {
2942 if (frm_end-frm_nxt < 4)
2943 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002944 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002945 if ((c2 & 0xFC00) != 0xDC00)
2946 return codecvt_base::error;
2947 uint32_t t = static_cast<uint32_t>(
2948 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2949 | ((c1 & 0x003F) << 10)
2950 | (c2 & 0x03FF));
2951 if (t > Maxcode)
2952 return codecvt_base::error;
2953 *to_nxt = t;
2954 frm_nxt += 4;
2955 }
2956 }
2957 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2958}
2959
2960static
2961int
2962utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2963 size_t mx, unsigned long Maxcode = 0x10FFFF,
2964 codecvt_mode mode = codecvt_mode(0))
2965{
2966 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002967 if (mode & consume_header)
2968 {
2969 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2970 frm_nxt += 2;
2971 }
2972 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2973 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002974 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002975 if ((c1 & 0xFC00) == 0xDC00)
2976 break;
2977 if ((c1 & 0xFC00) != 0xD800)
2978 {
2979 if (c1 > Maxcode)
2980 break;
2981 frm_nxt += 2;
2982 }
2983 else
2984 {
2985 if (frm_end-frm_nxt < 4)
2986 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002987 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002988 if ((c2 & 0xFC00) != 0xDC00)
2989 break;
2990 uint32_t t = static_cast<uint32_t>(
2991 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2992 | ((c1 & 0x003F) << 10)
2993 | (c2 & 0x03FF));
2994 if (t > Maxcode)
2995 break;
2996 frm_nxt += 4;
2997 }
2998 }
2999 return static_cast<int>(frm_nxt - frm);
3000}
3001
3002static
3003codecvt_base::result
3004ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3005 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3006 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3007{
3008 frm_nxt = frm;
3009 to_nxt = to;
3010 if (mode & generate_header)
3011 {
3012 if (to_end-to_nxt < 2)
3013 return codecvt_base::partial;
3014 *to_nxt++ = static_cast<uint8_t>(0xFE);
3015 *to_nxt++ = static_cast<uint8_t>(0xFF);
3016 }
3017 for (; frm_nxt < frm_end; ++frm_nxt)
3018 {
3019 uint16_t wc = *frm_nxt;
3020 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3021 return codecvt_base::error;
3022 if (to_end-to_nxt < 2)
3023 return codecvt_base::partial;
3024 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3025 *to_nxt++ = static_cast<uint8_t>(wc);
3026 }
3027 return codecvt_base::ok;
3028}
3029
3030static
3031codecvt_base::result
3032utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3033 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3034 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3035{
3036 frm_nxt = frm;
3037 to_nxt = to;
3038 if (mode & consume_header)
3039 {
3040 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3041 frm_nxt += 2;
3042 }
3043 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3044 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003045 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003046 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3047 return codecvt_base::error;
3048 *to_nxt = c1;
3049 frm_nxt += 2;
3050 }
3051 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3052}
3053
3054static
3055int
3056utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3057 size_t mx, unsigned long Maxcode = 0x10FFFF,
3058 codecvt_mode mode = codecvt_mode(0))
3059{
3060 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003061 if (mode & consume_header)
3062 {
3063 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3064 frm_nxt += 2;
3065 }
3066 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3067 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003068 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003069 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3070 break;
3071 frm_nxt += 2;
3072 }
3073 return static_cast<int>(frm_nxt - frm);
3074}
3075
3076static
3077codecvt_base::result
3078ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3079 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3080 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3081{
3082 frm_nxt = frm;
3083 to_nxt = to;
3084 if (mode & generate_header)
3085 {
3086 if (to_end-to_nxt < 2)
3087 return codecvt_base::partial;
3088 *to_nxt++ = static_cast<uint8_t>(0xFF);
3089 *to_nxt++ = static_cast<uint8_t>(0xFE);
3090 }
3091 for (; frm_nxt < frm_end; ++frm_nxt)
3092 {
3093 uint16_t wc = *frm_nxt;
3094 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3095 return codecvt_base::error;
3096 if (to_end-to_nxt < 2)
3097 return codecvt_base::partial;
3098 *to_nxt++ = static_cast<uint8_t>(wc);
3099 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3100 }
3101 return codecvt_base::ok;
3102}
3103
3104static
3105codecvt_base::result
3106utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3107 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3108 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3109{
3110 frm_nxt = frm;
3111 to_nxt = to;
3112 if (mode & consume_header)
3113 {
3114 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3115 frm_nxt += 2;
3116 }
3117 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3118 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003119 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003120 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3121 return codecvt_base::error;
3122 *to_nxt = c1;
3123 frm_nxt += 2;
3124 }
3125 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3126}
3127
3128static
3129int
3130utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3131 size_t mx, unsigned long Maxcode = 0x10FFFF,
3132 codecvt_mode mode = codecvt_mode(0))
3133{
3134 const uint8_t* frm_nxt = frm;
3135 frm_nxt = frm;
3136 if (mode & consume_header)
3137 {
3138 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3139 frm_nxt += 2;
3140 }
3141 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3142 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003143 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003144 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3145 break;
3146 frm_nxt += 2;
3147 }
3148 return static_cast<int>(frm_nxt - frm);
3149}
3150
Howard Hinnantc51e1022010-05-11 19:42:16 +00003151// template <> class codecvt<char16_t, char, mbstate_t>
3152
Howard Hinnantffb308e2010-08-22 00:03:27 +00003153locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003154
3155codecvt<char16_t, char, mbstate_t>::~codecvt()
3156{
3157}
3158
3159codecvt<char16_t, char, mbstate_t>::result
3160codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003161 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003162 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3163{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003164 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3165 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3166 const uint16_t* _frm_nxt = _frm;
3167 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3168 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3169 uint8_t* _to_nxt = _to;
3170 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3171 frm_nxt = frm + (_frm_nxt - _frm);
3172 to_nxt = to + (_to_nxt - _to);
3173 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003174}
3175
3176codecvt<char16_t, char, mbstate_t>::result
3177codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003178 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003179 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3180{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003181 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3182 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3183 const uint8_t* _frm_nxt = _frm;
3184 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3185 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3186 uint16_t* _to_nxt = _to;
3187 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3188 frm_nxt = frm + (_frm_nxt - _frm);
3189 to_nxt = to + (_to_nxt - _to);
3190 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003191}
3192
3193codecvt<char16_t, char, mbstate_t>::result
3194codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3195 extern_type* to, extern_type*, extern_type*& to_nxt) const
3196{
3197 to_nxt = to;
3198 return noconv;
3199}
3200
3201int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003202codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003203{
3204 return 0;
3205}
3206
3207bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003208codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003209{
3210 return false;
3211}
3212
3213int
3214codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3215 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3216{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003217 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3218 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3219 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003220}
3221
3222int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003223codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003224{
3225 return 4;
3226}
3227
3228// template <> class codecvt<char32_t, char, mbstate_t>
3229
Howard Hinnantffb308e2010-08-22 00:03:27 +00003230locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003231
3232codecvt<char32_t, char, mbstate_t>::~codecvt()
3233{
3234}
3235
3236codecvt<char32_t, char, mbstate_t>::result
3237codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003238 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003239 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3240{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003241 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3242 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3243 const uint32_t* _frm_nxt = _frm;
3244 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3245 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3246 uint8_t* _to_nxt = _to;
3247 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3248 frm_nxt = frm + (_frm_nxt - _frm);
3249 to_nxt = to + (_to_nxt - _to);
3250 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003251}
3252
3253codecvt<char32_t, char, mbstate_t>::result
3254codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003255 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003256 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3257{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003258 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3259 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3260 const uint8_t* _frm_nxt = _frm;
3261 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3262 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3263 uint32_t* _to_nxt = _to;
3264 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3265 frm_nxt = frm + (_frm_nxt - _frm);
3266 to_nxt = to + (_to_nxt - _to);
3267 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003268}
3269
3270codecvt<char32_t, char, mbstate_t>::result
3271codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3272 extern_type* to, extern_type*, extern_type*& to_nxt) const
3273{
3274 to_nxt = to;
3275 return noconv;
3276}
3277
3278int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003279codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003280{
3281 return 0;
3282}
3283
3284bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003285codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003286{
3287 return false;
3288}
3289
3290int
3291codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3292 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3293{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003294 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3295 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3296 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003297}
3298
3299int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003300codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003301{
3302 return 4;
3303}
3304
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003305// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003306
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003307__codecvt_utf8<wchar_t>::result
3308__codecvt_utf8<wchar_t>::do_out(state_type&,
3309 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003310 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3311{
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003312#if _WIN32
3313 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3314 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3315 const uint16_t* _frm_nxt = _frm;
3316#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003317 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3318 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3319 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003320#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003321 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3322 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3323 uint8_t* _to_nxt = _to;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003324#if _WIN32
3325 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3326 _Maxcode_, _Mode_);
3327#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003328 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3329 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003330#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003331 frm_nxt = frm + (_frm_nxt - _frm);
3332 to_nxt = to + (_to_nxt - _to);
3333 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003334}
3335
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003336__codecvt_utf8<wchar_t>::result
3337__codecvt_utf8<wchar_t>::do_in(state_type&,
3338 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003339 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3340{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003341 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3342 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3343 const uint8_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003344#if _WIN32
3345 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3346 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3347 uint16_t* _to_nxt = _to;
3348 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3349 _Maxcode_, _Mode_);
3350#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003351 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3352 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3353 uint32_t* _to_nxt = _to;
3354 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3355 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003356#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003357 frm_nxt = frm + (_frm_nxt - _frm);
3358 to_nxt = to + (_to_nxt - _to);
3359 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003360}
3361
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003362__codecvt_utf8<wchar_t>::result
3363__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003364 extern_type* to, extern_type*, extern_type*& to_nxt) const
3365{
3366 to_nxt = to;
3367 return noconv;
3368}
3369
3370int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003371__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003372{
3373 return 0;
3374}
3375
3376bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003377__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003378{
3379 return false;
3380}
3381
3382int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003383__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003384 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3385{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003386 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3387 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3388 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003389}
3390
3391int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003392__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003393{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003394 if (_Mode_ & consume_header)
3395 return 7;
3396 return 4;
3397}
3398
3399// __codecvt_utf8<char16_t>
3400
3401__codecvt_utf8<char16_t>::result
3402__codecvt_utf8<char16_t>::do_out(state_type&,
3403 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3404 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3405{
3406 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3407 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3408 const uint16_t* _frm_nxt = _frm;
3409 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3410 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3411 uint8_t* _to_nxt = _to;
3412 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3413 _Maxcode_, _Mode_);
3414 frm_nxt = frm + (_frm_nxt - _frm);
3415 to_nxt = to + (_to_nxt - _to);
3416 return r;
3417}
3418
3419__codecvt_utf8<char16_t>::result
3420__codecvt_utf8<char16_t>::do_in(state_type&,
3421 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3422 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3423{
3424 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3425 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3426 const uint8_t* _frm_nxt = _frm;
3427 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3428 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3429 uint16_t* _to_nxt = _to;
3430 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3431 _Maxcode_, _Mode_);
3432 frm_nxt = frm + (_frm_nxt - _frm);
3433 to_nxt = to + (_to_nxt - _to);
3434 return r;
3435}
3436
3437__codecvt_utf8<char16_t>::result
3438__codecvt_utf8<char16_t>::do_unshift(state_type&,
3439 extern_type* to, extern_type*, extern_type*& to_nxt) const
3440{
3441 to_nxt = to;
3442 return noconv;
3443}
3444
3445int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003446__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003447{
3448 return 0;
3449}
3450
3451bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003452__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003453{
3454 return false;
3455}
3456
3457int
3458__codecvt_utf8<char16_t>::do_length(state_type&,
3459 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3460{
3461 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3462 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3463 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3464}
3465
3466int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003467__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003468{
3469 if (_Mode_ & consume_header)
3470 return 6;
3471 return 3;
3472}
3473
3474// __codecvt_utf8<char32_t>
3475
3476__codecvt_utf8<char32_t>::result
3477__codecvt_utf8<char32_t>::do_out(state_type&,
3478 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3479 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3480{
3481 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3482 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3483 const uint32_t* _frm_nxt = _frm;
3484 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3485 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3486 uint8_t* _to_nxt = _to;
3487 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3488 _Maxcode_, _Mode_);
3489 frm_nxt = frm + (_frm_nxt - _frm);
3490 to_nxt = to + (_to_nxt - _to);
3491 return r;
3492}
3493
3494__codecvt_utf8<char32_t>::result
3495__codecvt_utf8<char32_t>::do_in(state_type&,
3496 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3497 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3498{
3499 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3500 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3501 const uint8_t* _frm_nxt = _frm;
3502 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3503 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3504 uint32_t* _to_nxt = _to;
3505 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3506 _Maxcode_, _Mode_);
3507 frm_nxt = frm + (_frm_nxt - _frm);
3508 to_nxt = to + (_to_nxt - _to);
3509 return r;
3510}
3511
3512__codecvt_utf8<char32_t>::result
3513__codecvt_utf8<char32_t>::do_unshift(state_type&,
3514 extern_type* to, extern_type*, extern_type*& to_nxt) const
3515{
3516 to_nxt = to;
3517 return noconv;
3518}
3519
3520int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003521__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003522{
3523 return 0;
3524}
3525
3526bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003527__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003528{
3529 return false;
3530}
3531
3532int
3533__codecvt_utf8<char32_t>::do_length(state_type&,
3534 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3535{
3536 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3537 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3538 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3539}
3540
3541int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003542__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003543{
3544 if (_Mode_ & consume_header)
3545 return 7;
3546 return 4;
3547}
3548
3549// __codecvt_utf16<wchar_t, false>
3550
3551__codecvt_utf16<wchar_t, false>::result
3552__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3553 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3554 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3555{
3556 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3557 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3558 const uint32_t* _frm_nxt = _frm;
3559 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3560 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3561 uint8_t* _to_nxt = _to;
3562 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3563 _Maxcode_, _Mode_);
3564 frm_nxt = frm + (_frm_nxt - _frm);
3565 to_nxt = to + (_to_nxt - _to);
3566 return r;
3567}
3568
3569__codecvt_utf16<wchar_t, false>::result
3570__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3571 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3572 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3573{
3574 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3575 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3576 const uint8_t* _frm_nxt = _frm;
3577 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3578 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3579 uint32_t* _to_nxt = _to;
3580 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3581 _Maxcode_, _Mode_);
3582 frm_nxt = frm + (_frm_nxt - _frm);
3583 to_nxt = to + (_to_nxt - _to);
3584 return r;
3585}
3586
3587__codecvt_utf16<wchar_t, false>::result
3588__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3589 extern_type* to, extern_type*, extern_type*& to_nxt) const
3590{
3591 to_nxt = to;
3592 return noconv;
3593}
3594
3595int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003596__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003597{
3598 return 0;
3599}
3600
3601bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003602__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003603{
3604 return false;
3605}
3606
3607int
3608__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3609 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3610{
3611 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3612 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3613 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3614}
3615
3616int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003617__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003618{
3619 if (_Mode_ & consume_header)
3620 return 6;
3621 return 4;
3622}
3623
3624// __codecvt_utf16<wchar_t, true>
3625
3626__codecvt_utf16<wchar_t, true>::result
3627__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3628 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3629 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3630{
3631 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3632 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3633 const uint32_t* _frm_nxt = _frm;
3634 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3635 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3636 uint8_t* _to_nxt = _to;
3637 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3638 _Maxcode_, _Mode_);
3639 frm_nxt = frm + (_frm_nxt - _frm);
3640 to_nxt = to + (_to_nxt - _to);
3641 return r;
3642}
3643
3644__codecvt_utf16<wchar_t, true>::result
3645__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3646 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3647 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3648{
3649 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3650 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3651 const uint8_t* _frm_nxt = _frm;
3652 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3653 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3654 uint32_t* _to_nxt = _to;
3655 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3656 _Maxcode_, _Mode_);
3657 frm_nxt = frm + (_frm_nxt - _frm);
3658 to_nxt = to + (_to_nxt - _to);
3659 return r;
3660}
3661
3662__codecvt_utf16<wchar_t, true>::result
3663__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3664 extern_type* to, extern_type*, extern_type*& to_nxt) const
3665{
3666 to_nxt = to;
3667 return noconv;
3668}
3669
3670int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003671__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003672{
3673 return 0;
3674}
3675
3676bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003677__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003678{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003679 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003680}
3681
3682int
3683__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3684 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3685{
3686 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3687 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3688 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3689}
3690
3691int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003692__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003693{
3694 if (_Mode_ & consume_header)
3695 return 6;
3696 return 4;
3697}
3698
3699// __codecvt_utf16<char16_t, false>
3700
3701__codecvt_utf16<char16_t, false>::result
3702__codecvt_utf16<char16_t, false>::do_out(state_type&,
3703 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3704 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3705{
3706 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3707 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3708 const uint16_t* _frm_nxt = _frm;
3709 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3710 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3711 uint8_t* _to_nxt = _to;
3712 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3713 _Maxcode_, _Mode_);
3714 frm_nxt = frm + (_frm_nxt - _frm);
3715 to_nxt = to + (_to_nxt - _to);
3716 return r;
3717}
3718
3719__codecvt_utf16<char16_t, false>::result
3720__codecvt_utf16<char16_t, false>::do_in(state_type&,
3721 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3722 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3723{
3724 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3725 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3726 const uint8_t* _frm_nxt = _frm;
3727 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3728 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3729 uint16_t* _to_nxt = _to;
3730 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3731 _Maxcode_, _Mode_);
3732 frm_nxt = frm + (_frm_nxt - _frm);
3733 to_nxt = to + (_to_nxt - _to);
3734 return r;
3735}
3736
3737__codecvt_utf16<char16_t, false>::result
3738__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3739 extern_type* to, extern_type*, extern_type*& to_nxt) const
3740{
3741 to_nxt = to;
3742 return noconv;
3743}
3744
3745int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003746__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003747{
3748 return 0;
3749}
3750
3751bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003752__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003753{
3754 return false;
3755}
3756
3757int
3758__codecvt_utf16<char16_t, false>::do_length(state_type&,
3759 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3760{
3761 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3762 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3763 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3764}
3765
3766int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003767__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003768{
3769 if (_Mode_ & consume_header)
3770 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003771 return 2;
3772}
3773
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003774// __codecvt_utf16<char16_t, true>
3775
3776__codecvt_utf16<char16_t, true>::result
3777__codecvt_utf16<char16_t, true>::do_out(state_type&,
3778 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3779 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3780{
3781 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3782 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3783 const uint16_t* _frm_nxt = _frm;
3784 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3785 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3786 uint8_t* _to_nxt = _to;
3787 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3788 _Maxcode_, _Mode_);
3789 frm_nxt = frm + (_frm_nxt - _frm);
3790 to_nxt = to + (_to_nxt - _to);
3791 return r;
3792}
3793
3794__codecvt_utf16<char16_t, true>::result
3795__codecvt_utf16<char16_t, true>::do_in(state_type&,
3796 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3797 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3798{
3799 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3800 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3801 const uint8_t* _frm_nxt = _frm;
3802 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3803 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3804 uint16_t* _to_nxt = _to;
3805 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3806 _Maxcode_, _Mode_);
3807 frm_nxt = frm + (_frm_nxt - _frm);
3808 to_nxt = to + (_to_nxt - _to);
3809 return r;
3810}
3811
3812__codecvt_utf16<char16_t, true>::result
3813__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3814 extern_type* to, extern_type*, extern_type*& to_nxt) const
3815{
3816 to_nxt = to;
3817 return noconv;
3818}
3819
3820int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003821__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003822{
3823 return 0;
3824}
3825
3826bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003827__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003828{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003829 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003830}
3831
3832int
3833__codecvt_utf16<char16_t, true>::do_length(state_type&,
3834 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3835{
3836 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3837 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3838 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3839}
3840
3841int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003842__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003843{
3844 if (_Mode_ & consume_header)
3845 return 4;
3846 return 2;
3847}
3848
3849// __codecvt_utf16<char32_t, false>
3850
3851__codecvt_utf16<char32_t, false>::result
3852__codecvt_utf16<char32_t, false>::do_out(state_type&,
3853 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3854 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3855{
3856 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3857 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3858 const uint32_t* _frm_nxt = _frm;
3859 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3860 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3861 uint8_t* _to_nxt = _to;
3862 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3863 _Maxcode_, _Mode_);
3864 frm_nxt = frm + (_frm_nxt - _frm);
3865 to_nxt = to + (_to_nxt - _to);
3866 return r;
3867}
3868
3869__codecvt_utf16<char32_t, false>::result
3870__codecvt_utf16<char32_t, false>::do_in(state_type&,
3871 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3872 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3873{
3874 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3875 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3876 const uint8_t* _frm_nxt = _frm;
3877 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3878 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3879 uint32_t* _to_nxt = _to;
3880 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3881 _Maxcode_, _Mode_);
3882 frm_nxt = frm + (_frm_nxt - _frm);
3883 to_nxt = to + (_to_nxt - _to);
3884 return r;
3885}
3886
3887__codecvt_utf16<char32_t, false>::result
3888__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3889 extern_type* to, extern_type*, extern_type*& to_nxt) const
3890{
3891 to_nxt = to;
3892 return noconv;
3893}
3894
3895int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003896__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003897{
3898 return 0;
3899}
3900
3901bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003902__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003903{
3904 return false;
3905}
3906
3907int
3908__codecvt_utf16<char32_t, false>::do_length(state_type&,
3909 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3910{
3911 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3912 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3913 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3914}
3915
3916int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003917__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003918{
3919 if (_Mode_ & consume_header)
3920 return 6;
3921 return 4;
3922}
3923
3924// __codecvt_utf16<char32_t, true>
3925
3926__codecvt_utf16<char32_t, true>::result
3927__codecvt_utf16<char32_t, true>::do_out(state_type&,
3928 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3929 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3930{
3931 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3932 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3933 const uint32_t* _frm_nxt = _frm;
3934 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3935 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3936 uint8_t* _to_nxt = _to;
3937 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3938 _Maxcode_, _Mode_);
3939 frm_nxt = frm + (_frm_nxt - _frm);
3940 to_nxt = to + (_to_nxt - _to);
3941 return r;
3942}
3943
3944__codecvt_utf16<char32_t, true>::result
3945__codecvt_utf16<char32_t, true>::do_in(state_type&,
3946 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3947 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3948{
3949 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3950 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3951 const uint8_t* _frm_nxt = _frm;
3952 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3953 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3954 uint32_t* _to_nxt = _to;
3955 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3956 _Maxcode_, _Mode_);
3957 frm_nxt = frm + (_frm_nxt - _frm);
3958 to_nxt = to + (_to_nxt - _to);
3959 return r;
3960}
3961
3962__codecvt_utf16<char32_t, true>::result
3963__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3964 extern_type* to, extern_type*, extern_type*& to_nxt) const
3965{
3966 to_nxt = to;
3967 return noconv;
3968}
3969
3970int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003971__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003972{
3973 return 0;
3974}
3975
3976bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003977__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003978{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003979 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003980}
3981
3982int
3983__codecvt_utf16<char32_t, true>::do_length(state_type&,
3984 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3985{
3986 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3987 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3988 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3989}
3990
3991int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003992__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003993{
3994 if (_Mode_ & consume_header)
3995 return 6;
3996 return 4;
3997}
3998
3999// __codecvt_utf8_utf16<wchar_t>
4000
4001__codecvt_utf8_utf16<wchar_t>::result
4002__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4003 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4004 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4005{
4006 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4007 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4008 const uint32_t* _frm_nxt = _frm;
4009 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4010 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4011 uint8_t* _to_nxt = _to;
4012 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4013 _Maxcode_, _Mode_);
4014 frm_nxt = frm + (_frm_nxt - _frm);
4015 to_nxt = to + (_to_nxt - _to);
4016 return r;
4017}
4018
4019__codecvt_utf8_utf16<wchar_t>::result
4020__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4021 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4022 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4023{
4024 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4025 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4026 const uint8_t* _frm_nxt = _frm;
4027 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4028 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4029 uint32_t* _to_nxt = _to;
4030 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4031 _Maxcode_, _Mode_);
4032 frm_nxt = frm + (_frm_nxt - _frm);
4033 to_nxt = to + (_to_nxt - _to);
4034 return r;
4035}
4036
4037__codecvt_utf8_utf16<wchar_t>::result
4038__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4039 extern_type* to, extern_type*, extern_type*& to_nxt) const
4040{
4041 to_nxt = to;
4042 return noconv;
4043}
4044
4045int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004046__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004047{
4048 return 0;
4049}
4050
4051bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004052__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004053{
4054 return false;
4055}
4056
4057int
4058__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4059 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4060{
4061 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4062 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4063 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4064}
4065
4066int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004067__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004068{
4069 if (_Mode_ & consume_header)
4070 return 7;
4071 return 4;
4072}
4073
4074// __codecvt_utf8_utf16<char16_t>
4075
4076__codecvt_utf8_utf16<char16_t>::result
4077__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4078 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4079 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4080{
4081 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4082 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4083 const uint16_t* _frm_nxt = _frm;
4084 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4085 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4086 uint8_t* _to_nxt = _to;
4087 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4088 _Maxcode_, _Mode_);
4089 frm_nxt = frm + (_frm_nxt - _frm);
4090 to_nxt = to + (_to_nxt - _to);
4091 return r;
4092}
4093
4094__codecvt_utf8_utf16<char16_t>::result
4095__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4096 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4097 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4098{
4099 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4100 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4101 const uint8_t* _frm_nxt = _frm;
4102 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4103 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4104 uint16_t* _to_nxt = _to;
4105 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4106 _Maxcode_, _Mode_);
4107 frm_nxt = frm + (_frm_nxt - _frm);
4108 to_nxt = to + (_to_nxt - _to);
4109 return r;
4110}
4111
4112__codecvt_utf8_utf16<char16_t>::result
4113__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4114 extern_type* to, extern_type*, extern_type*& to_nxt) const
4115{
4116 to_nxt = to;
4117 return noconv;
4118}
4119
4120int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004121__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004122{
4123 return 0;
4124}
4125
4126bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004127__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004128{
4129 return false;
4130}
4131
4132int
4133__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4134 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4135{
4136 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4137 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4138 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4139}
4140
4141int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004142__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004143{
4144 if (_Mode_ & consume_header)
4145 return 7;
4146 return 4;
4147}
4148
4149// __codecvt_utf8_utf16<char32_t>
4150
4151__codecvt_utf8_utf16<char32_t>::result
4152__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4153 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4154 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4155{
4156 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4157 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4158 const uint32_t* _frm_nxt = _frm;
4159 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4160 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4161 uint8_t* _to_nxt = _to;
4162 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4163 _Maxcode_, _Mode_);
4164 frm_nxt = frm + (_frm_nxt - _frm);
4165 to_nxt = to + (_to_nxt - _to);
4166 return r;
4167}
4168
4169__codecvt_utf8_utf16<char32_t>::result
4170__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4171 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4172 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4173{
4174 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4175 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4176 const uint8_t* _frm_nxt = _frm;
4177 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4178 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4179 uint32_t* _to_nxt = _to;
4180 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4181 _Maxcode_, _Mode_);
4182 frm_nxt = frm + (_frm_nxt - _frm);
4183 to_nxt = to + (_to_nxt - _to);
4184 return r;
4185}
4186
4187__codecvt_utf8_utf16<char32_t>::result
4188__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4189 extern_type* to, extern_type*, extern_type*& to_nxt) const
4190{
4191 to_nxt = to;
4192 return noconv;
4193}
4194
4195int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004196__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004197{
4198 return 0;
4199}
4200
4201bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004202__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004203{
4204 return false;
4205}
4206
4207int
4208__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4209 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4210{
4211 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4212 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4213 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4214}
4215
4216int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004217__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004218{
4219 if (_Mode_ & consume_header)
4220 return 7;
4221 return 4;
4222}
4223
Howard Hinnantc51e1022010-05-11 19:42:16 +00004224// __narrow_to_utf8<16>
4225
4226__narrow_to_utf8<16>::~__narrow_to_utf8()
4227{
4228}
4229
4230// __narrow_to_utf8<32>
4231
4232__narrow_to_utf8<32>::~__narrow_to_utf8()
4233{
4234}
4235
4236// __widen_from_utf8<16>
4237
4238__widen_from_utf8<16>::~__widen_from_utf8()
4239{
4240}
4241
4242// __widen_from_utf8<32>
4243
4244__widen_from_utf8<32>::~__widen_from_utf8()
4245{
4246}
4247
4248// numpunct<char> && numpunct<wchar_t>
4249
4250locale::id numpunct< char >::id;
4251locale::id numpunct<wchar_t>::id;
4252
4253numpunct<char>::numpunct(size_t refs)
4254 : locale::facet(refs),
4255 __decimal_point_('.'),
4256 __thousands_sep_(',')
4257{
4258}
4259
4260numpunct<wchar_t>::numpunct(size_t refs)
4261 : locale::facet(refs),
4262 __decimal_point_(L'.'),
4263 __thousands_sep_(L',')
4264{
4265}
4266
4267numpunct<char>::~numpunct()
4268{
4269}
4270
4271numpunct<wchar_t>::~numpunct()
4272{
4273}
4274
4275 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4276wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4277
4278 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4279wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4280
4281string numpunct< char >::do_grouping() const {return __grouping_;}
4282string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4283
4284 string numpunct< char >::do_truename() const {return "true";}
4285wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4286
4287 string numpunct< char >::do_falsename() const {return "false";}
4288wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4289
4290// numpunct_byname<char>
4291
4292numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4293 : numpunct<char>(refs)
4294{
4295 __init(nm);
4296}
4297
4298numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4299 : numpunct<char>(refs)
4300{
4301 __init(nm.c_str());
4302}
4303
4304numpunct_byname<char>::~numpunct_byname()
4305{
4306}
4307
4308void
4309numpunct_byname<char>::__init(const char* nm)
4310{
4311 if (strcmp(nm, "C") != 0)
4312 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004313 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004314#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004315 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004316 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4317 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004318#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004319#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004320 lconv* lc = localeconv_l(loc.get());
4321#else
4322 lconv* lc = __localeconv_l(loc.get());
4323#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004324 if (*lc->decimal_point)
4325 __decimal_point_ = *lc->decimal_point;
4326 if (*lc->thousands_sep)
4327 __thousands_sep_ = *lc->thousands_sep;
4328 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004329 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004330 }
4331}
4332
4333// numpunct_byname<wchar_t>
4334
4335numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4336 : numpunct<wchar_t>(refs)
4337{
4338 __init(nm);
4339}
4340
4341numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4342 : numpunct<wchar_t>(refs)
4343{
4344 __init(nm.c_str());
4345}
4346
4347numpunct_byname<wchar_t>::~numpunct_byname()
4348{
4349}
4350
4351void
4352numpunct_byname<wchar_t>::__init(const char* nm)
4353{
4354 if (strcmp(nm, "C") != 0)
4355 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004356 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004357#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004358 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004359 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4360 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004361#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004362#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004363 lconv* lc = localeconv_l(loc.get());
4364#else
4365 lconv* lc = __localeconv_l(loc.get());
4366#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004367 if (*lc->decimal_point)
4368 __decimal_point_ = *lc->decimal_point;
4369 if (*lc->thousands_sep)
4370 __thousands_sep_ = *lc->thousands_sep;
4371 __grouping_ = lc->grouping;
4372 // locallization for truename and falsename is not available
4373 }
4374}
4375
4376// num_get helpers
4377
4378int
4379__num_get_base::__get_base(ios_base& iob)
4380{
4381 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4382 if (__basefield == ios_base::oct)
4383 return 8;
4384 else if (__basefield == ios_base::hex)
4385 return 16;
4386 else if (__basefield == 0)
4387 return 0;
4388 return 10;
4389}
4390
4391const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4392
4393void
4394__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4395 ios_base::iostate& __err)
4396{
4397 if (__grouping.size() != 0)
4398 {
4399 reverse(__g, __g_end);
4400 const char* __ig = __grouping.data();
4401 const char* __eg = __ig + __grouping.size();
4402 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4403 {
4404 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4405 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004406 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004407 {
4408 __err = ios_base::failbit;
4409 return;
4410 }
4411 }
4412 if (__eg - __ig > 1)
4413 ++__ig;
4414 }
4415 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4416 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004417 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004418 __err = ios_base::failbit;
4419 }
4420 }
4421}
4422
4423void
4424__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4425 ios_base::fmtflags __flags)
4426{
4427 if (__flags & ios_base::showpos)
4428 *__fmtp++ = '+';
4429 if (__flags & ios_base::showbase)
4430 *__fmtp++ = '#';
4431 while(*__len)
4432 *__fmtp++ = *__len++;
4433 if ((__flags & ios_base::basefield) == ios_base::oct)
4434 *__fmtp = 'o';
4435 else if ((__flags & ios_base::basefield) == ios_base::hex)
4436 {
4437 if (__flags & ios_base::uppercase)
4438 *__fmtp = 'X';
4439 else
4440 *__fmtp = 'x';
4441 }
4442 else if (__signd)
4443 *__fmtp = 'd';
4444 else
4445 *__fmtp = 'u';
4446}
4447
4448bool
4449__num_put_base::__format_float(char* __fmtp, const char* __len,
4450 ios_base::fmtflags __flags)
4451{
4452 bool specify_precision = true;
4453 if (__flags & ios_base::showpos)
4454 *__fmtp++ = '+';
4455 if (__flags & ios_base::showpoint)
4456 *__fmtp++ = '#';
4457 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004458 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004459 if (floatfield == (ios_base::fixed | ios_base::scientific))
4460 specify_precision = false;
4461 else
4462 {
4463 *__fmtp++ = '.';
4464 *__fmtp++ = '*';
4465 }
4466 while(*__len)
4467 *__fmtp++ = *__len++;
4468 if (floatfield == ios_base::fixed)
4469 {
4470 if (uppercase)
4471 *__fmtp = 'F';
4472 else
4473 *__fmtp = 'f';
4474 }
4475 else if (floatfield == ios_base::scientific)
4476 {
4477 if (uppercase)
4478 *__fmtp = 'E';
4479 else
4480 *__fmtp = 'e';
4481 }
4482 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4483 {
4484 if (uppercase)
4485 *__fmtp = 'A';
4486 else
4487 *__fmtp = 'a';
4488 }
4489 else
4490 {
4491 if (uppercase)
4492 *__fmtp = 'G';
4493 else
4494 *__fmtp = 'g';
4495 }
4496 return specify_precision;
4497}
4498
4499char*
4500__num_put_base::__identify_padding(char* __nb, char* __ne,
4501 const ios_base& __iob)
4502{
4503 switch (__iob.flags() & ios_base::adjustfield)
4504 {
4505 case ios_base::internal:
4506 if (__nb[0] == '-' || __nb[0] == '+')
4507 return __nb+1;
4508 if (__ne - __nb >= 2 && __nb[0] == '0'
4509 && (__nb[1] == 'x' || __nb[1] == 'X'))
4510 return __nb+2;
4511 break;
4512 case ios_base::left:
4513 return __ne;
4514 case ios_base::right:
4515 default:
4516 break;
4517 }
4518 return __nb;
4519}
4520
4521// time_get
4522
4523static
4524string*
4525init_weeks()
4526{
4527 static string weeks[14];
4528 weeks[0] = "Sunday";
4529 weeks[1] = "Monday";
4530 weeks[2] = "Tuesday";
4531 weeks[3] = "Wednesday";
4532 weeks[4] = "Thursday";
4533 weeks[5] = "Friday";
4534 weeks[6] = "Saturday";
4535 weeks[7] = "Sun";
4536 weeks[8] = "Mon";
4537 weeks[9] = "Tue";
4538 weeks[10] = "Wed";
4539 weeks[11] = "Thu";
4540 weeks[12] = "Fri";
4541 weeks[13] = "Sat";
4542 return weeks;
4543}
4544
4545static
4546wstring*
4547init_wweeks()
4548{
4549 static wstring weeks[14];
4550 weeks[0] = L"Sunday";
4551 weeks[1] = L"Monday";
4552 weeks[2] = L"Tuesday";
4553 weeks[3] = L"Wednesday";
4554 weeks[4] = L"Thursday";
4555 weeks[5] = L"Friday";
4556 weeks[6] = L"Saturday";
4557 weeks[7] = L"Sun";
4558 weeks[8] = L"Mon";
4559 weeks[9] = L"Tue";
4560 weeks[10] = L"Wed";
4561 weeks[11] = L"Thu";
4562 weeks[12] = L"Fri";
4563 weeks[13] = L"Sat";
4564 return weeks;
4565}
4566
4567template <>
4568const string*
4569__time_get_c_storage<char>::__weeks() const
4570{
4571 static const string* weeks = init_weeks();
4572 return weeks;
4573}
4574
4575template <>
4576const wstring*
4577__time_get_c_storage<wchar_t>::__weeks() const
4578{
4579 static const wstring* weeks = init_wweeks();
4580 return weeks;
4581}
4582
4583static
4584string*
4585init_months()
4586{
4587 static string months[24];
4588 months[0] = "January";
4589 months[1] = "February";
4590 months[2] = "March";
4591 months[3] = "April";
4592 months[4] = "May";
4593 months[5] = "June";
4594 months[6] = "July";
4595 months[7] = "August";
4596 months[8] = "September";
4597 months[9] = "October";
4598 months[10] = "November";
4599 months[11] = "December";
4600 months[12] = "Jan";
4601 months[13] = "Feb";
4602 months[14] = "Mar";
4603 months[15] = "Apr";
4604 months[16] = "May";
4605 months[17] = "Jun";
4606 months[18] = "Jul";
4607 months[19] = "Aug";
4608 months[20] = "Sep";
4609 months[21] = "Oct";
4610 months[22] = "Nov";
4611 months[23] = "Dec";
4612 return months;
4613}
4614
4615static
4616wstring*
4617init_wmonths()
4618{
4619 static wstring months[24];
4620 months[0] = L"January";
4621 months[1] = L"February";
4622 months[2] = L"March";
4623 months[3] = L"April";
4624 months[4] = L"May";
4625 months[5] = L"June";
4626 months[6] = L"July";
4627 months[7] = L"August";
4628 months[8] = L"September";
4629 months[9] = L"October";
4630 months[10] = L"November";
4631 months[11] = L"December";
4632 months[12] = L"Jan";
4633 months[13] = L"Feb";
4634 months[14] = L"Mar";
4635 months[15] = L"Apr";
4636 months[16] = L"May";
4637 months[17] = L"Jun";
4638 months[18] = L"Jul";
4639 months[19] = L"Aug";
4640 months[20] = L"Sep";
4641 months[21] = L"Oct";
4642 months[22] = L"Nov";
4643 months[23] = L"Dec";
4644 return months;
4645}
4646
4647template <>
4648const string*
4649__time_get_c_storage<char>::__months() const
4650{
4651 static const string* months = init_months();
4652 return months;
4653}
4654
4655template <>
4656const wstring*
4657__time_get_c_storage<wchar_t>::__months() const
4658{
4659 static const wstring* months = init_wmonths();
4660 return months;
4661}
4662
4663static
4664string*
4665init_am_pm()
4666{
4667 static string am_pm[24];
4668 am_pm[0] = "AM";
4669 am_pm[1] = "PM";
4670 return am_pm;
4671}
4672
4673static
4674wstring*
4675init_wam_pm()
4676{
4677 static wstring am_pm[24];
4678 am_pm[0] = L"AM";
4679 am_pm[1] = L"PM";
4680 return am_pm;
4681}
4682
4683template <>
4684const string*
4685__time_get_c_storage<char>::__am_pm() const
4686{
4687 static const string* am_pm = init_am_pm();
4688 return am_pm;
4689}
4690
4691template <>
4692const wstring*
4693__time_get_c_storage<wchar_t>::__am_pm() const
4694{
4695 static const wstring* am_pm = init_wam_pm();
4696 return am_pm;
4697}
4698
4699template <>
4700const string&
4701__time_get_c_storage<char>::__x() const
4702{
4703 static string s("%m/%d/%y");
4704 return s;
4705}
4706
4707template <>
4708const wstring&
4709__time_get_c_storage<wchar_t>::__x() const
4710{
4711 static wstring s(L"%m/%d/%y");
4712 return s;
4713}
4714
4715template <>
4716const string&
4717__time_get_c_storage<char>::__X() const
4718{
4719 static string s("%H:%M:%S");
4720 return s;
4721}
4722
4723template <>
4724const wstring&
4725__time_get_c_storage<wchar_t>::__X() const
4726{
4727 static wstring s(L"%H:%M:%S");
4728 return s;
4729}
4730
4731template <>
4732const string&
4733__time_get_c_storage<char>::__c() const
4734{
4735 static string s("%a %b %d %H:%M:%S %Y");
4736 return s;
4737}
4738
4739template <>
4740const wstring&
4741__time_get_c_storage<wchar_t>::__c() const
4742{
4743 static wstring s(L"%a %b %d %H:%M:%S %Y");
4744 return s;
4745}
4746
4747template <>
4748const string&
4749__time_get_c_storage<char>::__r() const
4750{
4751 static string s("%I:%M:%S %p");
4752 return s;
4753}
4754
4755template <>
4756const wstring&
4757__time_get_c_storage<wchar_t>::__r() const
4758{
4759 static wstring s(L"%I:%M:%S %p");
4760 return s;
4761}
4762
4763// time_get_byname
4764
4765__time_get::__time_get(const char* nm)
4766 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4767{
Howard Hinnant72f73582010-08-11 17:04:31 +00004768#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004769 if (__loc_ == 0)
4770 throw runtime_error("time_get_byname"
4771 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004772#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004773}
4774
4775__time_get::__time_get(const string& nm)
4776 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4777{
Howard Hinnant72f73582010-08-11 17:04:31 +00004778#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004779 if (__loc_ == 0)
4780 throw runtime_error("time_get_byname"
4781 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00004782#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004783}
4784
4785__time_get::~__time_get()
4786{
4787 freelocale(__loc_);
4788}
Marshall Clowd920eea2013-10-21 15:07:28 +00004789#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004790#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004791#endif
4792#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004793#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004794#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004795
Howard Hinnantc51e1022010-05-11 19:42:16 +00004796template <>
4797string
4798__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4799{
Howard Hinnant990207c2012-02-19 14:55:32 +00004800 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004801 t.tm_sec = 59;
4802 t.tm_min = 55;
4803 t.tm_hour = 23;
4804 t.tm_mday = 31;
4805 t.tm_mon = 11;
4806 t.tm_year = 161;
4807 t.tm_wday = 6;
4808 t.tm_yday = 364;
4809 t.tm_isdst = -1;
4810 char buf[100];
4811 char f[3] = {0};
4812 f[0] = '%';
4813 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004814 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004815 char* bb = buf;
4816 char* be = buf + n;
4817 string result;
4818 while (bb != be)
4819 {
4820 if (ct.is(ctype_base::space, *bb))
4821 {
4822 result.push_back(' ');
4823 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4824 ;
4825 continue;
4826 }
4827 char* w = bb;
4828 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004829 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004830 ct, err, false)
4831 - this->__weeks_;
4832 if (i < 14)
4833 {
4834 result.push_back('%');
4835 if (i < 7)
4836 result.push_back('A');
4837 else
4838 result.push_back('a');
4839 bb = w;
4840 continue;
4841 }
4842 w = bb;
4843 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4844 ct, err, false)
4845 - this->__months_;
4846 if (i < 24)
4847 {
4848 result.push_back('%');
4849 if (i < 12)
4850 result.push_back('B');
4851 else
4852 result.push_back('b');
4853 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4854 result.back() = 'm';
4855 bb = w;
4856 continue;
4857 }
4858 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4859 {
4860 w = bb;
4861 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4862 ct, err, false) - this->__am_pm_;
4863 if (i < 2)
4864 {
4865 result.push_back('%');
4866 result.push_back('p');
4867 bb = w;
4868 continue;
4869 }
4870 }
4871 w = bb;
4872 if (ct.is(ctype_base::digit, *bb))
4873 {
4874 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4875 {
4876 case 6:
4877 result.push_back('%');
4878 result.push_back('w');
4879 break;
4880 case 7:
4881 result.push_back('%');
4882 result.push_back('u');
4883 break;
4884 case 11:
4885 result.push_back('%');
4886 result.push_back('I');
4887 break;
4888 case 12:
4889 result.push_back('%');
4890 result.push_back('m');
4891 break;
4892 case 23:
4893 result.push_back('%');
4894 result.push_back('H');
4895 break;
4896 case 31:
4897 result.push_back('%');
4898 result.push_back('d');
4899 break;
4900 case 55:
4901 result.push_back('%');
4902 result.push_back('M');
4903 break;
4904 case 59:
4905 result.push_back('%');
4906 result.push_back('S');
4907 break;
4908 case 61:
4909 result.push_back('%');
4910 result.push_back('y');
4911 break;
4912 case 364:
4913 result.push_back('%');
4914 result.push_back('j');
4915 break;
4916 case 2061:
4917 result.push_back('%');
4918 result.push_back('Y');
4919 break;
4920 default:
4921 for (; w != bb; ++w)
4922 result.push_back(*w);
4923 break;
4924 }
4925 continue;
4926 }
4927 if (*bb == '%')
4928 {
4929 result.push_back('%');
4930 result.push_back('%');
4931 ++bb;
4932 continue;
4933 }
4934 result.push_back(*bb);
4935 ++bb;
4936 }
4937 return result;
4938}
4939
Marshall Clowd920eea2013-10-21 15:07:28 +00004940#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004941#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004942#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004943
Howard Hinnantc51e1022010-05-11 19:42:16 +00004944template <>
4945wstring
4946__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4947{
Howard Hinnant990207c2012-02-19 14:55:32 +00004948 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004949 t.tm_sec = 59;
4950 t.tm_min = 55;
4951 t.tm_hour = 23;
4952 t.tm_mday = 31;
4953 t.tm_mon = 11;
4954 t.tm_year = 161;
4955 t.tm_wday = 6;
4956 t.tm_yday = 364;
4957 t.tm_isdst = -1;
4958 char buf[100];
4959 char f[3] = {0};
4960 f[0] = '%';
4961 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004962 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004963 wchar_t wbuf[100];
4964 wchar_t* wbb = wbuf;
4965 mbstate_t mb = {0};
4966 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004967#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004968 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004969#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004972 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004973 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004974 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004975 wstring result;
4976 while (wbb != wbe)
4977 {
4978 if (ct.is(ctype_base::space, *wbb))
4979 {
4980 result.push_back(L' ');
4981 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4982 ;
4983 continue;
4984 }
4985 wchar_t* w = wbb;
4986 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004987 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004988 ct, err, false)
4989 - this->__weeks_;
4990 if (i < 14)
4991 {
4992 result.push_back(L'%');
4993 if (i < 7)
4994 result.push_back(L'A');
4995 else
4996 result.push_back(L'a');
4997 wbb = w;
4998 continue;
4999 }
5000 w = wbb;
5001 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5002 ct, err, false)
5003 - this->__months_;
5004 if (i < 24)
5005 {
5006 result.push_back(L'%');
5007 if (i < 12)
5008 result.push_back(L'B');
5009 else
5010 result.push_back(L'b');
5011 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5012 result.back() = L'm';
5013 wbb = w;
5014 continue;
5015 }
5016 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5017 {
5018 w = wbb;
5019 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5020 ct, err, false) - this->__am_pm_;
5021 if (i < 2)
5022 {
5023 result.push_back(L'%');
5024 result.push_back(L'p');
5025 wbb = w;
5026 continue;
5027 }
5028 }
5029 w = wbb;
5030 if (ct.is(ctype_base::digit, *wbb))
5031 {
5032 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5033 {
5034 case 6:
5035 result.push_back(L'%');
5036 result.push_back(L'w');
5037 break;
5038 case 7:
5039 result.push_back(L'%');
5040 result.push_back(L'u');
5041 break;
5042 case 11:
5043 result.push_back(L'%');
5044 result.push_back(L'I');
5045 break;
5046 case 12:
5047 result.push_back(L'%');
5048 result.push_back(L'm');
5049 break;
5050 case 23:
5051 result.push_back(L'%');
5052 result.push_back(L'H');
5053 break;
5054 case 31:
5055 result.push_back(L'%');
5056 result.push_back(L'd');
5057 break;
5058 case 55:
5059 result.push_back(L'%');
5060 result.push_back(L'M');
5061 break;
5062 case 59:
5063 result.push_back(L'%');
5064 result.push_back(L'S');
5065 break;
5066 case 61:
5067 result.push_back(L'%');
5068 result.push_back(L'y');
5069 break;
5070 case 364:
5071 result.push_back(L'%');
5072 result.push_back(L'j');
5073 break;
5074 case 2061:
5075 result.push_back(L'%');
5076 result.push_back(L'Y');
5077 break;
5078 default:
5079 for (; w != wbb; ++w)
5080 result.push_back(*w);
5081 break;
5082 }
5083 continue;
5084 }
5085 if (ct.narrow(*wbb, 0) == '%')
5086 {
5087 result.push_back(L'%');
5088 result.push_back(L'%');
5089 ++wbb;
5090 continue;
5091 }
5092 result.push_back(*wbb);
5093 ++wbb;
5094 }
5095 return result;
5096}
5097
5098template <>
5099void
5100__time_get_storage<char>::init(const ctype<char>& ct)
5101{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005102 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005103 char buf[100];
5104 // __weeks_
5105 for (int i = 0; i < 7; ++i)
5106 {
5107 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005108 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005109 __weeks_[i] = buf;
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+7] = buf;
5112 }
5113 // __months_
5114 for (int i = 0; i < 12; ++i)
5115 {
5116 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005117 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005118 __months_[i] = buf;
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+12] = buf;
5121 }
5122 // __am_pm_
5123 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005124 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005125 __am_pm_[0] = buf;
5126 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005127 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005128 __am_pm_[1] = buf;
5129 __c_ = __analyze('c', ct);
5130 __r_ = __analyze('r', ct);
5131 __x_ = __analyze('x', ct);
5132 __X_ = __analyze('X', ct);
5133}
5134
5135template <>
5136void
5137__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5138{
5139 tm t = {0};
5140 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005141 wchar_t wbuf[100];
5142 wchar_t* wbe;
5143 mbstate_t mb = {0};
5144 // __weeks_
5145 for (int i = 0; i < 7; ++i)
5146 {
5147 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005148 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005149 mb = mbstate_t();
5150 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005151#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005152 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005153#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005156 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005157 __throw_runtime_error("locale not supported");
5158 wbe = wbuf + j;
5159 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005160 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005161 mb = mbstate_t();
5162 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005163#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005164 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005165#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005168 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005169 __throw_runtime_error("locale not supported");
5170 wbe = wbuf + j;
5171 __weeks_[i+7].assign(wbuf, wbe);
5172 }
5173 // __months_
5174 for (int i = 0; i < 12; ++i)
5175 {
5176 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005177 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005178 mb = mbstate_t();
5179 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005180#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005181 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005182#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005185 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005186 __throw_runtime_error("locale not supported");
5187 wbe = wbuf + j;
5188 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005189 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005190 mb = mbstate_t();
5191 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005192#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005193 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005194#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005197 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005198 __throw_runtime_error("locale not supported");
5199 wbe = wbuf + j;
5200 __months_[i+12].assign(wbuf, wbe);
5201 }
5202 // __am_pm_
5203 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005204 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005205 mb = mbstate_t();
5206 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005207#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005208 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005209#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005212 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005213 __throw_runtime_error("locale not supported");
5214 wbe = wbuf + j;
5215 __am_pm_[0].assign(wbuf, wbe);
5216 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005217 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005218 mb = mbstate_t();
5219 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005220#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005221 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005222#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005225 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005226 __throw_runtime_error("locale not supported");
5227 wbe = wbuf + j;
5228 __am_pm_[1].assign(wbuf, wbe);
5229 __c_ = __analyze('c', ct);
5230 __r_ = __analyze('r', ct);
5231 __x_ = __analyze('x', ct);
5232 __X_ = __analyze('X', ct);
5233}
5234
5235template <class CharT>
5236struct _LIBCPP_HIDDEN __time_get_temp
5237 : public ctype_byname<CharT>
5238{
5239 explicit __time_get_temp(const char* nm)
5240 : ctype_byname<CharT>(nm, 1) {}
5241 explicit __time_get_temp(const string& nm)
5242 : ctype_byname<CharT>(nm, 1) {}
5243};
5244
5245template <>
5246__time_get_storage<char>::__time_get_storage(const char* __nm)
5247 : __time_get(__nm)
5248{
5249 const __time_get_temp<char> ct(__nm);
5250 init(ct);
5251}
5252
5253template <>
5254__time_get_storage<char>::__time_get_storage(const string& __nm)
5255 : __time_get(__nm)
5256{
5257 const __time_get_temp<char> ct(__nm);
5258 init(ct);
5259}
5260
5261template <>
5262__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5263 : __time_get(__nm)
5264{
5265 const __time_get_temp<wchar_t> ct(__nm);
5266 init(ct);
5267}
5268
5269template <>
5270__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5271 : __time_get(__nm)
5272{
5273 const __time_get_temp<wchar_t> ct(__nm);
5274 init(ct);
5275}
5276
5277template <>
5278time_base::dateorder
5279__time_get_storage<char>::__do_date_order() const
5280{
5281 unsigned i;
5282 for (i = 0; i < __x_.size(); ++i)
5283 if (__x_[i] == '%')
5284 break;
5285 ++i;
5286 switch (__x_[i])
5287 {
5288 case 'y':
5289 case 'Y':
5290 for (++i; i < __x_.size(); ++i)
5291 if (__x_[i] == '%')
5292 break;
5293 if (i == __x_.size())
5294 break;
5295 ++i;
5296 switch (__x_[i])
5297 {
5298 case 'm':
5299 for (++i; i < __x_.size(); ++i)
5300 if (__x_[i] == '%')
5301 break;
5302 if (i == __x_.size())
5303 break;
5304 ++i;
5305 if (__x_[i] == 'd')
5306 return time_base::ymd;
5307 break;
5308 case 'd':
5309 for (++i; i < __x_.size(); ++i)
5310 if (__x_[i] == '%')
5311 break;
5312 if (i == __x_.size())
5313 break;
5314 ++i;
5315 if (__x_[i] == 'm')
5316 return time_base::ydm;
5317 break;
5318 }
5319 break;
5320 case 'm':
5321 for (++i; i < __x_.size(); ++i)
5322 if (__x_[i] == '%')
5323 break;
5324 if (i == __x_.size())
5325 break;
5326 ++i;
5327 if (__x_[i] == 'd')
5328 {
5329 for (++i; i < __x_.size(); ++i)
5330 if (__x_[i] == '%')
5331 break;
5332 if (i == __x_.size())
5333 break;
5334 ++i;
5335 if (__x_[i] == 'y' || __x_[i] == 'Y')
5336 return time_base::mdy;
5337 break;
5338 }
5339 break;
5340 case 'd':
5341 for (++i; i < __x_.size(); ++i)
5342 if (__x_[i] == '%')
5343 break;
5344 if (i == __x_.size())
5345 break;
5346 ++i;
5347 if (__x_[i] == 'm')
5348 {
5349 for (++i; i < __x_.size(); ++i)
5350 if (__x_[i] == '%')
5351 break;
5352 if (i == __x_.size())
5353 break;
5354 ++i;
5355 if (__x_[i] == 'y' || __x_[i] == 'Y')
5356 return time_base::dmy;
5357 break;
5358 }
5359 break;
5360 }
5361 return time_base::no_order;
5362}
5363
5364template <>
5365time_base::dateorder
5366__time_get_storage<wchar_t>::__do_date_order() const
5367{
5368 unsigned i;
5369 for (i = 0; i < __x_.size(); ++i)
5370 if (__x_[i] == L'%')
5371 break;
5372 ++i;
5373 switch (__x_[i])
5374 {
5375 case L'y':
5376 case L'Y':
5377 for (++i; i < __x_.size(); ++i)
5378 if (__x_[i] == L'%')
5379 break;
5380 if (i == __x_.size())
5381 break;
5382 ++i;
5383 switch (__x_[i])
5384 {
5385 case L'm':
5386 for (++i; i < __x_.size(); ++i)
5387 if (__x_[i] == L'%')
5388 break;
5389 if (i == __x_.size())
5390 break;
5391 ++i;
5392 if (__x_[i] == L'd')
5393 return time_base::ymd;
5394 break;
5395 case L'd':
5396 for (++i; i < __x_.size(); ++i)
5397 if (__x_[i] == L'%')
5398 break;
5399 if (i == __x_.size())
5400 break;
5401 ++i;
5402 if (__x_[i] == L'm')
5403 return time_base::ydm;
5404 break;
5405 }
5406 break;
5407 case L'm':
5408 for (++i; i < __x_.size(); ++i)
5409 if (__x_[i] == L'%')
5410 break;
5411 if (i == __x_.size())
5412 break;
5413 ++i;
5414 if (__x_[i] == L'd')
5415 {
5416 for (++i; i < __x_.size(); ++i)
5417 if (__x_[i] == L'%')
5418 break;
5419 if (i == __x_.size())
5420 break;
5421 ++i;
5422 if (__x_[i] == L'y' || __x_[i] == L'Y')
5423 return time_base::mdy;
5424 break;
5425 }
5426 break;
5427 case L'd':
5428 for (++i; i < __x_.size(); ++i)
5429 if (__x_[i] == L'%')
5430 break;
5431 if (i == __x_.size())
5432 break;
5433 ++i;
5434 if (__x_[i] == L'm')
5435 {
5436 for (++i; i < __x_.size(); ++i)
5437 if (__x_[i] == L'%')
5438 break;
5439 if (i == __x_.size())
5440 break;
5441 ++i;
5442 if (__x_[i] == L'y' || __x_[i] == L'Y')
5443 return time_base::dmy;
5444 break;
5445 }
5446 break;
5447 }
5448 return time_base::no_order;
5449}
5450
5451// time_put
5452
5453__time_put::__time_put(const char* nm)
5454 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5455{
Howard Hinnant72f73582010-08-11 17:04:31 +00005456#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005457 if (__loc_ == 0)
5458 throw runtime_error("time_put_byname"
5459 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005460#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005461}
5462
5463__time_put::__time_put(const string& nm)
5464 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5465{
Howard Hinnant72f73582010-08-11 17:04:31 +00005466#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005467 if (__loc_ == 0)
5468 throw runtime_error("time_put_byname"
5469 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00005470#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005471}
5472
5473__time_put::~__time_put()
5474{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005475 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005476 freelocale(__loc_);
5477}
5478
5479void
5480__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5481 char __fmt, char __mod) const
5482{
5483 char fmt[] = {'%', __fmt, __mod, 0};
5484 if (__mod != 0)
5485 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005486 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005487 __ne = __nb + n;
5488}
5489
5490void
5491__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5492 char __fmt, char __mod) const
5493{
5494 char __nar[100];
5495 char* __ne = __nar + 100;
5496 __do_put(__nar, __ne, __tm, __fmt, __mod);
5497 mbstate_t mb = {0};
5498 const char* __nb = __nar;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005499#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005500 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005501#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005504 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005505 __throw_runtime_error("locale not supported");
5506 __we = __wb + j;
5507}
5508
5509// moneypunct_byname
5510
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005511template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005512static
5513void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005514__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5515 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5516 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005517{
5518 const char sign = static_cast<char>(money_base::sign);
5519 const char space = static_cast<char>(money_base::space);
5520 const char none = static_cast<char>(money_base::none);
5521 const char symbol = static_cast<char>(money_base::symbol);
5522 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005523 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5524
5525 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5526 // function'. "Space between sign and symbol or value" means that
5527 // if the sign is adjacent to the symbol, there's a space between
5528 // them, and otherwise there's a space between the sign and value.
5529 //
5530 // C11's localeconv specifies that the fourth character of an
5531 // international curr_symbol is used to separate the sign and
5532 // value when sep_by_space says to do so. C++ can't represent
5533 // that, so we just use a space. When sep_by_space says to
5534 // separate the symbol and value-or-sign with a space, we rearrange the
5535 // curr_symbol to put its spacing character on the correct side of
5536 // the symbol.
5537 //
5538 // We also need to avoid adding an extra space between the sign
5539 // and value when the currency symbol is suppressed (by not
5540 // setting showbase). We match glibc's strfmon by interpreting
5541 // sep_by_space==1 as "omit the space when the currency symbol is
5542 // absent".
5543 //
5544 // Users who want to get this right should use ICU instead.
5545
Howard Hinnantc51e1022010-05-11 19:42:16 +00005546 switch (cs_precedes)
5547 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005548 case 0: // value before curr_symbol
5549 if (symbol_contains_sep) {
5550 // Move the separator to before the symbol, to place it
5551 // between the value and symbol.
5552 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5553 __curr_symbol_.end());
5554 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005555 switch (sign_posn)
5556 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005557 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005558 pat.field[0] = sign;
5559 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005560 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005561 pat.field[3] = symbol;
5562 switch (sep_by_space)
5563 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005564 case 0: // No space separates the currency symbol and value.
5565 // This case may have changed between C99 and C11;
5566 // assume the currency symbol matches the intention.
5567 case 2: // Space between sign and currency or value.
5568 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005569 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005570 case 1: // Space between currency-and-sign or currency and value.
5571 if (!symbol_contains_sep) {
5572 // We insert the space into the symbol instead of
5573 // setting pat.field[2]=space so that when
5574 // showbase is not set, the space goes away too.
5575 __curr_symbol_.insert(0, 1, space_char);
5576 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005577 return;
5578 default:
5579 break;
5580 }
5581 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005582 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005583 pat.field[0] = sign;
5584 pat.field[3] = symbol;
5585 switch (sep_by_space)
5586 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005587 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005588 pat.field[1] = value;
5589 pat.field[2] = none;
5590 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005591 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005592 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005593 pat.field[2] = none;
5594 if (!symbol_contains_sep) {
5595 // We insert the space into the symbol instead of
5596 // setting pat.field[2]=space so that when
5597 // showbase is not set, the space goes away too.
5598 __curr_symbol_.insert(0, 1, space_char);
5599 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005600 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005601 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005602 pat.field[1] = space;
5603 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005604 if (symbol_contains_sep) {
5605 // Remove the separator from the symbol, since it
5606 // has already appeared after the sign.
5607 __curr_symbol_.erase(__curr_symbol_.begin());
5608 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005609 return;
5610 default:
5611 break;
5612 }
5613 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005614 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005615 pat.field[0] = value;
5616 pat.field[3] = sign;
5617 switch (sep_by_space)
5618 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005619 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005620 pat.field[1] = none;
5621 pat.field[2] = symbol;
5622 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005623 case 1: // Space between currency-and-sign or currency and value.
5624 if (!symbol_contains_sep) {
5625 // We insert the space into the symbol instead of
5626 // setting pat.field[1]=space so that when
5627 // showbase is not set, the space goes away too.
5628 __curr_symbol_.insert(0, 1, space_char);
5629 }
5630 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005631 pat.field[2] = symbol;
5632 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005633 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005634 pat.field[1] = symbol;
5635 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005636 if (symbol_contains_sep) {
5637 // Remove the separator from the symbol, since it
5638 // should not be removed if showbase is absent.
5639 __curr_symbol_.erase(__curr_symbol_.begin());
5640 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005641 return;
5642 default:
5643 break;
5644 }
5645 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005646 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005647 pat.field[0] = value;
5648 pat.field[3] = symbol;
5649 switch (sep_by_space)
5650 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005651 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005652 pat.field[1] = none;
5653 pat.field[2] = sign;
5654 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005655 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005656 pat.field[1] = space;
5657 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005658 if (symbol_contains_sep) {
5659 // Remove the separator from the symbol, since it
5660 // has already appeared before the sign.
5661 __curr_symbol_.erase(__curr_symbol_.begin());
5662 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005663 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005664 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005665 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005666 pat.field[2] = none;
5667 if (!symbol_contains_sep) {
5668 // We insert the space into the symbol instead of
5669 // setting pat.field[2]=space so that when
5670 // showbase is not set, the space goes away too.
5671 __curr_symbol_.insert(0, 1, space_char);
5672 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005673 return;
5674 default:
5675 break;
5676 }
5677 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005678 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005679 pat.field[0] = value;
5680 pat.field[3] = sign;
5681 switch (sep_by_space)
5682 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005683 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005684 pat.field[1] = none;
5685 pat.field[2] = symbol;
5686 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005687 case 1: // Space between currency-and-sign or currency and value.
5688 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005689 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005690 if (!symbol_contains_sep) {
5691 // We insert the space into the symbol instead of
5692 // setting pat.field[1]=space so that when
5693 // showbase is not set, the space goes away too.
5694 __curr_symbol_.insert(0, 1, space_char);
5695 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005696 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005697 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005698 pat.field[1] = symbol;
5699 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005700 if (symbol_contains_sep) {
5701 // Remove the separator from the symbol, since it
5702 // should not disappear when showbase is absent.
5703 __curr_symbol_.erase(__curr_symbol_.begin());
5704 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005705 return;
5706 default:
5707 break;
5708 }
5709 break;
5710 default:
5711 break;
5712 }
5713 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005714 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005715 switch (sign_posn)
5716 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005717 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005718 pat.field[0] = sign;
5719 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005720 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005721 pat.field[3] = value;
5722 switch (sep_by_space)
5723 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005724 case 0: // No space separates the currency symbol and value.
5725 // This case may have changed between C99 and C11;
5726 // assume the currency symbol matches the intention.
5727 case 2: // Space between sign and currency or value.
5728 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005729 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005730 case 1: // Space between currency-and-sign or currency and value.
5731 if (!symbol_contains_sep) {
5732 // We insert the space into the symbol instead of
5733 // setting pat.field[2]=space so that when
5734 // showbase is not set, the space goes away too.
5735 __curr_symbol_.insert(0, 1, space_char);
5736 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005737 return;
5738 default:
5739 break;
5740 }
5741 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005742 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005743 pat.field[0] = sign;
5744 pat.field[3] = value;
5745 switch (sep_by_space)
5746 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005747 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005748 pat.field[1] = symbol;
5749 pat.field[2] = none;
5750 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005751 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005752 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005753 pat.field[2] = none;
5754 if (!symbol_contains_sep) {
5755 // We insert the space into the symbol instead of
5756 // setting pat.field[2]=space so that when
5757 // showbase is not set, the space goes away too.
5758 __curr_symbol_.push_back(space_char);
5759 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005760 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005761 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005762 pat.field[1] = space;
5763 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005764 if (symbol_contains_sep) {
5765 // Remove the separator from the symbol, since it
5766 // has already appeared after the sign.
5767 __curr_symbol_.pop_back();
5768 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005769 return;
5770 default:
5771 break;
5772 }
5773 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005774 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005775 pat.field[0] = symbol;
5776 pat.field[3] = sign;
5777 switch (sep_by_space)
5778 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005779 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005780 pat.field[1] = none;
5781 pat.field[2] = value;
5782 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005783 case 1: // Space between currency-and-sign or currency and value.
5784 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005785 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005786 if (!symbol_contains_sep) {
5787 // We insert the space into the symbol instead of
5788 // setting pat.field[1]=space so that when
5789 // showbase is not set, the space goes away too.
5790 __curr_symbol_.push_back(space_char);
5791 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005792 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005793 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005794 pat.field[1] = value;
5795 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005796 if (symbol_contains_sep) {
5797 // Remove the separator from the symbol, since it
5798 // will appear before the sign.
5799 __curr_symbol_.pop_back();
5800 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005801 return;
5802 default:
5803 break;
5804 }
5805 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005806 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005807 pat.field[0] = sign;
5808 pat.field[3] = value;
5809 switch (sep_by_space)
5810 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005811 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005812 pat.field[1] = symbol;
5813 pat.field[2] = none;
5814 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005815 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005816 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005817 pat.field[2] = none;
5818 if (!symbol_contains_sep) {
5819 // We insert the space into the symbol instead of
5820 // setting pat.field[2]=space so that when
5821 // showbase is not set, the space goes away too.
5822 __curr_symbol_.push_back(space_char);
5823 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005824 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005825 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005826 pat.field[1] = space;
5827 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005828 if (symbol_contains_sep) {
5829 // Remove the separator from the symbol, since it
5830 // has already appeared after the sign.
5831 __curr_symbol_.pop_back();
5832 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005833 return;
5834 default:
5835 break;
5836 }
5837 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005838 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005839 pat.field[0] = symbol;
5840 pat.field[3] = value;
5841 switch (sep_by_space)
5842 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005843 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005844 pat.field[1] = sign;
5845 pat.field[2] = none;
5846 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005847 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005848 pat.field[1] = sign;
5849 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005850 if (symbol_contains_sep) {
5851 // Remove the separator from the symbol, since it
5852 // should not disappear when showbase is absent.
5853 __curr_symbol_.pop_back();
5854 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005855 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005856 case 2: // Space between sign and currency or value.
5857 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005858 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005859 if (!symbol_contains_sep) {
5860 // We insert the space into the symbol instead of
5861 // setting pat.field[1]=space so that when
5862 // showbase is not set, the space goes away too.
5863 __curr_symbol_.push_back(space_char);
5864 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005865 return;
5866 default:
5867 break;
5868 }
5869 break;
5870 default:
5871 break;
5872 }
5873 break;
5874 default:
5875 break;
5876 }
5877 pat.field[0] = symbol;
5878 pat.field[1] = sign;
5879 pat.field[2] = none;
5880 pat.field[3] = value;
5881}
5882
5883template<>
5884void
5885moneypunct_byname<char, false>::init(const char* nm)
5886{
5887 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005888 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005889#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005890 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005891 throw runtime_error("moneypunct_byname"
5892 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005893#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005894#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005895 lconv* lc = localeconv_l(loc.get());
5896#else
5897 lconv* lc = __localeconv_l(loc.get());
5898#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005899 if (*lc->mon_decimal_point)
5900 __decimal_point_ = *lc->mon_decimal_point;
5901 else
5902 __decimal_point_ = base::do_decimal_point();
5903 if (*lc->mon_thousands_sep)
5904 __thousands_sep_ = *lc->mon_thousands_sep;
5905 else
5906 __thousands_sep_ = base::do_thousands_sep();
5907 __grouping_ = lc->mon_grouping;
5908 __curr_symbol_ = lc->currency_symbol;
5909 if (lc->frac_digits != CHAR_MAX)
5910 __frac_digits_ = lc->frac_digits;
5911 else
5912 __frac_digits_ = base::do_frac_digits();
5913 if (lc->p_sign_posn == 0)
5914 __positive_sign_ = "()";
5915 else
5916 __positive_sign_ = lc->positive_sign;
5917 if (lc->n_sign_posn == 0)
5918 __negative_sign_ = "()";
5919 else
5920 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005921 // Assume the positive and negative formats will want spaces in
5922 // the same places in curr_symbol since there's no way to
5923 // represent anything else.
5924 string_type __dummy_curr_symbol = __curr_symbol_;
5925 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5926 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5927 __init_pat(__neg_format_, __curr_symbol_, false,
5928 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005929}
5930
5931template<>
5932void
5933moneypunct_byname<char, true>::init(const char* nm)
5934{
5935 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005936 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005937#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005938 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005939 throw runtime_error("moneypunct_byname"
5940 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005941#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005942#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005943 lconv* lc = localeconv_l(loc.get());
5944#else
5945 lconv* lc = __localeconv_l(loc.get());
5946#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005947 if (*lc->mon_decimal_point)
5948 __decimal_point_ = *lc->mon_decimal_point;
5949 else
5950 __decimal_point_ = base::do_decimal_point();
5951 if (*lc->mon_thousands_sep)
5952 __thousands_sep_ = *lc->mon_thousands_sep;
5953 else
5954 __thousands_sep_ = base::do_thousands_sep();
5955 __grouping_ = lc->mon_grouping;
5956 __curr_symbol_ = lc->int_curr_symbol;
5957 if (lc->int_frac_digits != CHAR_MAX)
5958 __frac_digits_ = lc->int_frac_digits;
5959 else
5960 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005961#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005962 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005963#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005964 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005965#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005966 __positive_sign_ = "()";
5967 else
5968 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005969#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005970 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005971#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005972 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005973#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005974 __negative_sign_ = "()";
5975 else
5976 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005977 // Assume the positive and negative formats will want spaces in
5978 // the same places in curr_symbol since there's no way to
5979 // represent anything else.
5980 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005981#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005982 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5983 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5984 __init_pat(__neg_format_, __curr_symbol_, true,
5985 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005986#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005987 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5988 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5989 lc->int_p_sign_posn, ' ');
5990 __init_pat(__neg_format_, __curr_symbol_, true,
5991 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5992 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005993#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005994}
5995
5996template<>
5997void
5998moneypunct_byname<wchar_t, false>::init(const char* nm)
5999{
6000 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006001 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00006002#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00006003 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006004 throw runtime_error("moneypunct_byname"
6005 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00006006#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006007#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006008 lconv* lc = localeconv_l(loc.get());
6009#else
6010 lconv* lc = __localeconv_l(loc.get());
6011#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006012 if (*lc->mon_decimal_point)
6013 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6014 else
6015 __decimal_point_ = base::do_decimal_point();
6016 if (*lc->mon_thousands_sep)
6017 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6018 else
6019 __thousands_sep_ = base::do_thousands_sep();
6020 __grouping_ = lc->mon_grouping;
6021 wchar_t wbuf[100];
6022 mbstate_t mb = {0};
6023 const char* bb = lc->currency_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006024#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006025 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006026#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006029 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006030 __throw_runtime_error("locale not supported");
6031 wchar_t* wbe = wbuf + j;
6032 __curr_symbol_.assign(wbuf, wbe);
6033 if (lc->frac_digits != CHAR_MAX)
6034 __frac_digits_ = lc->frac_digits;
6035 else
6036 __frac_digits_ = base::do_frac_digits();
6037 if (lc->p_sign_posn == 0)
6038 __positive_sign_ = L"()";
6039 else
6040 {
6041 mb = mbstate_t();
6042 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006043#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006044 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006045#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006048 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006049 __throw_runtime_error("locale not supported");
6050 wbe = wbuf + j;
6051 __positive_sign_.assign(wbuf, wbe);
6052 }
6053 if (lc->n_sign_posn == 0)
6054 __negative_sign_ = L"()";
6055 else
6056 {
6057 mb = mbstate_t();
6058 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006059#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006060 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006061#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006064 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006065 __throw_runtime_error("locale not supported");
6066 wbe = wbuf + j;
6067 __negative_sign_.assign(wbuf, wbe);
6068 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006069 // Assume the positive and negative formats will want spaces in
6070 // the same places in curr_symbol since there's no way to
6071 // represent anything else.
6072 string_type __dummy_curr_symbol = __curr_symbol_;
6073 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6074 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6075 __init_pat(__neg_format_, __curr_symbol_, false,
6076 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006077}
6078
6079template<>
6080void
6081moneypunct_byname<wchar_t, true>::init(const char* nm)
6082{
6083 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006084 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00006085#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00006086 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006087 throw runtime_error("moneypunct_byname"
6088 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00006089#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006090#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006091 lconv* lc = localeconv_l(loc.get());
6092#else
6093 lconv* lc = __localeconv_l(loc.get());
6094#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006095 if (*lc->mon_decimal_point)
6096 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6097 else
6098 __decimal_point_ = base::do_decimal_point();
6099 if (*lc->mon_thousands_sep)
6100 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6101 else
6102 __thousands_sep_ = base::do_thousands_sep();
6103 __grouping_ = lc->mon_grouping;
6104 wchar_t wbuf[100];
6105 mbstate_t mb = {0};
6106 const char* bb = lc->int_curr_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006107#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006108 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006109#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006112 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006113 __throw_runtime_error("locale not supported");
6114 wchar_t* wbe = wbuf + j;
6115 __curr_symbol_.assign(wbuf, wbe);
6116 if (lc->int_frac_digits != CHAR_MAX)
6117 __frac_digits_ = lc->int_frac_digits;
6118 else
6119 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006120#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006121 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006122#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006123 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006124#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006125 __positive_sign_ = L"()";
6126 else
6127 {
6128 mb = mbstate_t();
6129 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006130#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006131 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006132#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006135 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006136 __throw_runtime_error("locale not supported");
6137 wbe = wbuf + j;
6138 __positive_sign_.assign(wbuf, wbe);
6139 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006140#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006141 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006142#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006143 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006144#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006145 __negative_sign_ = L"()";
6146 else
6147 {
6148 mb = mbstate_t();
6149 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006150#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006151 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006152#else
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#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006155 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006156 __throw_runtime_error("locale not supported");
6157 wbe = wbuf + j;
6158 __negative_sign_.assign(wbuf, wbe);
6159 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006160 // Assume the positive and negative formats will want spaces in
6161 // the same places in curr_symbol since there's no way to
6162 // represent anything else.
6163 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006164#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006165 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6166 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6167 __init_pat(__neg_format_, __curr_symbol_, true,
6168 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006169#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006170 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6171 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6172 lc->int_p_sign_posn, L' ');
6173 __init_pat(__neg_format_, __curr_symbol_, true,
6174 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6175 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006176#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006177}
6178
6179void __do_nothing(void*) {}
6180
6181void __throw_runtime_error(const char* msg)
6182{
Howard Hinnant72f73582010-08-11 17:04:31 +00006183#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006184 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006185#else
6186 (void)msg;
Howard Hinnant72f73582010-08-11 17:04:31 +00006187#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006188}
6189
6190template class collate<char>;
6191template class collate<wchar_t>;
6192
6193template class num_get<char>;
6194template class num_get<wchar_t>;
6195
Howard Hinnant28b24882011-12-01 20:21:04 +00006196template struct __num_get<char>;
6197template struct __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006198
6199template class num_put<char>;
6200template class num_put<wchar_t>;
6201
Howard Hinnant28b24882011-12-01 20:21:04 +00006202template struct __num_put<char>;
6203template struct __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006204
6205template class time_get<char>;
6206template class time_get<wchar_t>;
6207
6208template class time_get_byname<char>;
6209template class time_get_byname<wchar_t>;
6210
6211template class time_put<char>;
6212template class time_put<wchar_t>;
6213
6214template class time_put_byname<char>;
6215template class time_put_byname<wchar_t>;
6216
6217template class moneypunct<char, false>;
6218template class moneypunct<char, true>;
6219template class moneypunct<wchar_t, false>;
6220template class moneypunct<wchar_t, true>;
6221
6222template class moneypunct_byname<char, false>;
6223template class moneypunct_byname<char, true>;
6224template class moneypunct_byname<wchar_t, false>;
6225template class moneypunct_byname<wchar_t, true>;
6226
6227template class money_get<char>;
6228template class money_get<wchar_t>;
6229
6230template class __money_get<char>;
6231template class __money_get<wchar_t>;
6232
6233template class money_put<char>;
6234template class money_put<wchar_t>;
6235
6236template class __money_put<char>;
6237template class __money_put<wchar_t>;
6238
6239template class messages<char>;
6240template class messages<wchar_t>;
6241
6242template class messages_byname<char>;
6243template class messages_byname<wchar_t>;
6244
6245template class codecvt_byname<char, char, mbstate_t>;
6246template class codecvt_byname<wchar_t, char, mbstate_t>;
6247template class codecvt_byname<char16_t, char, mbstate_t>;
6248template class codecvt_byname<char32_t, char, mbstate_t>;
6249
6250template class __vector_base_common<true>;
6251
6252_LIBCPP_END_NAMESPACE_STD