blob: 49ffd8e0246005deb7fdf620c733a50a0afabebc [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
Howard Hinnantf9260592013-08-29 20:56:53 +000010#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
11
David Chisnall8074c342012-02-29 13:05:08 +000012// On Solaris, we need to define something to make the C99 parts of localeconv
13// visible.
14#ifdef __sun__
15#define _LCONV_C99
16#endif
17
Howard Hinnantc51e1022010-05-11 19:42:16 +000018#include "string"
19#include "locale"
Howard Hinnant7282c5a2010-05-30 21:39:41 +000020#include "codecvt"
Howard Hinnantc51e1022010-05-11 19:42:16 +000021#include "vector"
22#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000023#include "typeinfo"
Howard Hinnant718dae32013-07-28 18:20:00 +000024#ifndef _LIBCPP_NO_EXCEPTIONS
25# include "type_traits"
26#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000027#include "clocale"
28#include "cstring"
29#include "cwctype"
30#include "__sso_allocator"
Howard Hinnant13d8bc12013-08-01 18:17:34 +000031#ifdef _LIBCPP_MSVCRT
Howard Hinnantae0f80b2011-09-29 20:33:10 +000032#include <support/win32/locale_win32.h>
Howard Hinnant13d8bc12013-08-01 18:17:34 +000033#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +000034#include <langinfo.h>
Howard Hinnant13d8bc12013-08-01 18:17:34 +000035#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +000036#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000037#include <stdio.h>
Howard Hinnantc51e1022010-05-11 19:42:16 +000038
Marshall Clowab9c1772013-02-07 17:20:56 +000039// On Linux, wint_t and wchar_t have different signed-ness, and this causes
40// lots of noise in the build log, but no bugs that I know of.
41#pragma clang diagnostic ignored "-Wsign-conversion"
42
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);
69 return *(T*)&buf;
70}
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);
79 return *(T*)&buf;
80}
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);
89 return *(T*)&buf;
90}
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 Hinnant2c45cb42012-12-12 21:14:28 +0000112const locale::category locale::none;
113const locale::category locale::collate;
114const locale::category locale::ctype;
115const locale::category locale::monetary;
116const locale::category locale::numeric;
117const locale::category locale::time;
118const locale::category locale::messages;
119const locale::category locale::all;
120
Howard Hinnant28b24882011-12-01 20:21:04 +0000121#pragma clang diagnostic push
122#pragma clang diagnostic ignored "-Wpadded"
123
Howard Hinnantc51e1022010-05-11 19:42:16 +0000124class _LIBCPP_HIDDEN locale::__imp
125 : public facet
126{
127 enum {N = 28};
Howard Hinnantc51e1022010-05-11 19:42:16 +0000128 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnant28b24882011-12-01 20:21:04 +0000129 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000130public:
131 explicit __imp(size_t refs = 0);
132 explicit __imp(const string& name, size_t refs = 0);
133 __imp(const __imp&);
134 __imp(const __imp&, const string&, locale::category c);
135 __imp(const __imp& other, const __imp& one, locale::category c);
136 __imp(const __imp&, facet* f, long id);
137 ~__imp();
138
139 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000140 bool has_facet(long id) const
141 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000142 const locale::facet* use_facet(long id) const;
143
144 static const locale& make_classic();
145 static locale& make_global();
146private:
147 void install(facet* f, long id);
148 template <class F> void install(F* f) {install(f, f->id.__get());}
149 template <class F> void install_from(const __imp& other);
150};
151
Howard Hinnant28b24882011-12-01 20:21:04 +0000152#pragma clang diagnostic pop
153
Howard Hinnantc51e1022010-05-11 19:42:16 +0000154locale::__imp::__imp(size_t refs)
155 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000156 facets_(N),
157 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000158{
159 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000160 install(&make<_VSTD::collate<char> >(1u));
161 install(&make<_VSTD::collate<wchar_t> >(1u));
162 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
163 install(&make<_VSTD::ctype<wchar_t> >(1u));
164 install(&make<codecvt<char, char, mbstate_t> >(1u));
165 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
166 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
167 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
168 install(&make<numpunct<char> >(1u));
169 install(&make<numpunct<wchar_t> >(1u));
170 install(&make<num_get<char> >(1u));
171 install(&make<num_get<wchar_t> >(1u));
172 install(&make<num_put<char> >(1u));
173 install(&make<num_put<wchar_t> >(1u));
174 install(&make<moneypunct<char, false> >(1u));
175 install(&make<moneypunct<char, true> >(1u));
176 install(&make<moneypunct<wchar_t, false> >(1u));
177 install(&make<moneypunct<wchar_t, true> >(1u));
178 install(&make<money_get<char> >(1u));
179 install(&make<money_get<wchar_t> >(1u));
180 install(&make<money_put<char> >(1u));
181 install(&make<money_put<wchar_t> >(1u));
182 install(&make<time_get<char> >(1u));
183 install(&make<time_get<wchar_t> >(1u));
184 install(&make<time_put<char> >(1u));
185 install(&make<time_put<wchar_t> >(1u));
186 install(&make<_VSTD::messages<char> >(1u));
187 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000188}
189
190locale::__imp::__imp(const string& name, size_t refs)
191 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000192 facets_(N),
193 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000194{
Howard Hinnant72f73582010-08-11 17:04:31 +0000195#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000196 try
197 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000198#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000199 facets_ = locale::classic().__locale_->facets_;
200 for (unsigned i = 0; i < facets_.size(); ++i)
201 if (facets_[i])
202 facets_[i]->__add_shared();
203 install(new collate_byname<char>(name_));
204 install(new collate_byname<wchar_t>(name_));
205 install(new ctype_byname<char>(name_));
206 install(new ctype_byname<wchar_t>(name_));
207 install(new codecvt_byname<char, char, mbstate_t>(name_));
208 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
209 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
210 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
211 install(new numpunct_byname<char>(name_));
212 install(new numpunct_byname<wchar_t>(name_));
213 install(new moneypunct_byname<char, false>(name_));
214 install(new moneypunct_byname<char, true>(name_));
215 install(new moneypunct_byname<wchar_t, false>(name_));
216 install(new moneypunct_byname<wchar_t, true>(name_));
217 install(new time_get_byname<char>(name_));
218 install(new time_get_byname<wchar_t>(name_));
219 install(new time_put_byname<char>(name_));
220 install(new time_put_byname<wchar_t>(name_));
221 install(new messages_byname<char>(name_));
222 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000223#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000224 }
225 catch (...)
226 {
227 for (unsigned i = 0; i < facets_.size(); ++i)
228 if (facets_[i])
229 facets_[i]->__release_shared();
230 throw;
231 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000232#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000233}
234
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000235// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000236// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000237#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000238#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000239#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000240#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000241
Howard Hinnantc51e1022010-05-11 19:42:16 +0000242locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000243 : facets_(max<size_t>(N, other.facets_.size())),
244 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000245{
246 facets_ = other.facets_;
247 for (unsigned i = 0; i < facets_.size(); ++i)
248 if (facets_[i])
249 facets_[i]->__add_shared();
250}
251
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000252#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000253#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000254#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000255
Howard Hinnantc51e1022010-05-11 19:42:16 +0000256locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000257 : facets_(N),
258 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000259{
260 facets_ = other.facets_;
261 for (unsigned i = 0; i < facets_.size(); ++i)
262 if (facets_[i])
263 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000264#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000265 try
266 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000267#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000268 if (c & locale::collate)
269 {
270 install(new collate_byname<char>(name));
271 install(new collate_byname<wchar_t>(name));
272 }
273 if (c & locale::ctype)
274 {
275 install(new ctype_byname<char>(name));
276 install(new ctype_byname<wchar_t>(name));
277 install(new codecvt_byname<char, char, mbstate_t>(name));
278 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
279 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
280 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
281 }
282 if (c & locale::monetary)
283 {
284 install(new moneypunct_byname<char, false>(name));
285 install(new moneypunct_byname<char, true>(name));
286 install(new moneypunct_byname<wchar_t, false>(name));
287 install(new moneypunct_byname<wchar_t, true>(name));
288 }
289 if (c & locale::numeric)
290 {
291 install(new numpunct_byname<char>(name));
292 install(new numpunct_byname<wchar_t>(name));
293 }
294 if (c & locale::time)
295 {
296 install(new time_get_byname<char>(name));
297 install(new time_get_byname<wchar_t>(name));
298 install(new time_put_byname<char>(name));
299 install(new time_put_byname<wchar_t>(name));
300 }
301 if (c & locale::messages)
302 {
303 install(new messages_byname<char>(name));
304 install(new messages_byname<wchar_t>(name));
305 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000306#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000307 }
308 catch (...)
309 {
310 for (unsigned i = 0; i < facets_.size(); ++i)
311 if (facets_[i])
312 facets_[i]->__release_shared();
313 throw;
314 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000315#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000316}
317
318template<class F>
319inline
320void
321locale::__imp::install_from(const locale::__imp& one)
322{
323 long id = F::id.__get();
324 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
325}
326
327locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000328 : facets_(N),
329 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000330{
331 facets_ = other.facets_;
332 for (unsigned i = 0; i < facets_.size(); ++i)
333 if (facets_[i])
334 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000335#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000336 try
337 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000338#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000339 if (c & locale::collate)
340 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000341 install_from<_VSTD::collate<char> >(one);
342 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000343 }
344 if (c & locale::ctype)
345 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000346 install_from<_VSTD::ctype<char> >(one);
347 install_from<_VSTD::ctype<wchar_t> >(one);
348 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
349 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
350 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
351 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000352 }
353 if (c & locale::monetary)
354 {
355 install_from<moneypunct<char, false> >(one);
356 install_from<moneypunct<char, true> >(one);
357 install_from<moneypunct<wchar_t, false> >(one);
358 install_from<moneypunct<wchar_t, true> >(one);
359 install_from<money_get<char> >(one);
360 install_from<money_get<wchar_t> >(one);
361 install_from<money_put<char> >(one);
362 install_from<money_put<wchar_t> >(one);
363 }
364 if (c & locale::numeric)
365 {
366 install_from<numpunct<char> >(one);
367 install_from<numpunct<wchar_t> >(one);
368 install_from<num_get<char> >(one);
369 install_from<num_get<wchar_t> >(one);
370 install_from<num_put<char> >(one);
371 install_from<num_put<wchar_t> >(one);
372 }
373 if (c & locale::time)
374 {
375 install_from<time_get<char> >(one);
376 install_from<time_get<wchar_t> >(one);
377 install_from<time_put<char> >(one);
378 install_from<time_put<wchar_t> >(one);
379 }
380 if (c & locale::messages)
381 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000382 install_from<_VSTD::messages<char> >(one);
383 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000384 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000385#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000386 }
387 catch (...)
388 {
389 for (unsigned i = 0; i < facets_.size(); ++i)
390 if (facets_[i])
391 facets_[i]->__release_shared();
392 throw;
393 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000394#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000395}
396
397locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000398 : facets_(max<size_t>(N, other.facets_.size()+1)),
399 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000400{
401 f->__add_shared();
402 unique_ptr<facet, release> hold(f);
403 facets_ = other.facets_;
404 for (unsigned i = 0; i < other.facets_.size(); ++i)
405 if (facets_[i])
406 facets_[i]->__add_shared();
407 install(hold.get(), id);
408}
409
410locale::__imp::~__imp()
411{
412 for (unsigned i = 0; i < facets_.size(); ++i)
413 if (facets_[i])
414 facets_[i]->__release_shared();
415}
416
417void
418locale::__imp::install(facet* f, long id)
419{
420 f->__add_shared();
421 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000422 if (static_cast<size_t>(id) >= facets_.size())
423 facets_.resize(static_cast<size_t>(id+1));
424 if (facets_[static_cast<size_t>(id)])
425 facets_[static_cast<size_t>(id)]->__release_shared();
426 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000427}
428
429const locale::facet*
430locale::__imp::use_facet(long id) const
431{
Howard Hinnant72f73582010-08-11 17:04:31 +0000432#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000433 if (!has_facet(id))
434 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000435#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant28b24882011-12-01 20:21:04 +0000436 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000437}
438
439// locale
440
441const locale&
442locale::__imp::make_classic()
443{
444 // only one thread can get in here and it only gets in once
445 static aligned_storage<sizeof(locale)>::type buf;
446 locale* c = (locale*)&buf;
Howard Hinnant28b24882011-12-01 20:21:04 +0000447 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000448 return *c;
449}
450
451const locale&
452locale::classic()
453{
454 static const locale& c = __imp::make_classic();
455 return c;
456}
457
458locale&
459locale::__imp::make_global()
460{
461 // only one thread can get in here and it only gets in once
462 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000463 ::new (&buf) locale(locale::classic());
464 return *(locale*)&buf;
465}
466
467locale&
468locale::__global()
469{
470 static locale& g = __imp::make_global();
471 return g;
472}
473
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000474locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000475 : __locale_(__global().__locale_)
476{
477 __locale_->__add_shared();
478}
479
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000480locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000481 : __locale_(l.__locale_)
482{
483 __locale_->__add_shared();
484}
485
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000486locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000487{
488 __locale_->__release_shared();
489}
490
491const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000492locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000493{
494 other.__locale_->__add_shared();
495 __locale_->__release_shared();
496 __locale_ = other.__locale_;
497 return *this;
498}
499
500locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000501#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000502 : __locale_(name ? new __imp(name)
503 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000504#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000505 : __locale_(new __imp(name))
506#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000507{
508 __locale_->__add_shared();
509}
510
511locale::locale(const string& name)
512 : __locale_(new __imp(name))
513{
514 __locale_->__add_shared();
515}
516
517locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000518#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000519 : __locale_(name ? new __imp(*other.__locale_, name, c)
520 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000521#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000522 : __locale_(new __imp(*other.__locale_, name, c))
523#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000524{
525 __locale_->__add_shared();
526}
527
528locale::locale(const locale& other, const string& name, category c)
529 : __locale_(new __imp(*other.__locale_, name, c))
530{
531 __locale_->__add_shared();
532}
533
534locale::locale(const locale& other, const locale& one, category c)
535 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
536{
537 __locale_->__add_shared();
538}
539
540string
541locale::name() const
542{
543 return __locale_->name();
544}
545
546void
547locale::__install_ctor(const locale& other, facet* f, long id)
548{
549 if (f)
550 __locale_ = new __imp(*other.__locale_, f, id);
551 else
552 __locale_ = other.__locale_;
553 __locale_->__add_shared();
554}
555
556locale
557locale::global(const locale& loc)
558{
559 locale& g = __global();
560 locale r = g;
561 g = loc;
562 if (g.name() != "*")
563 setlocale(LC_ALL, g.name().c_str());
564 return r;
565}
566
567bool
568locale::has_facet(id& x) const
569{
570 return __locale_->has_facet(x.__get());
571}
572
573const locale::facet*
574locale::use_facet(id& x) const
575{
576 return __locale_->use_facet(x.__get());
577}
578
579bool
580locale::operator==(const locale& y) const
581{
582 return (__locale_ == y.__locale_)
583 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
584}
585
586// locale::facet
587
588locale::facet::~facet()
589{
590}
591
592void
Howard Hinnant719bda32011-05-28 14:41:13 +0000593locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000594{
595 delete this;
596}
597
598// locale::id
599
600int32_t locale::id::__next_id = 0;
601
602namespace
603{
604
605class __fake_bind
606{
607 locale::id* id_;
608 void (locale::id::* pmf_)();
609public:
610 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
611 : id_(id), pmf_(pmf) {}
612
613 void operator()() const
614 {
615 (id_->*pmf_)();
616 }
617};
618
619}
620
621long
622locale::id::__get()
623{
624 call_once(__flag_, __fake_bind(&locale::id::__init, this));
625 return __id_ - 1;
626}
627
628void
629locale::id::__init()
630{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000631 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000632}
633
634// template <> class collate_byname<char>
635
636collate_byname<char>::collate_byname(const char* n, size_t refs)
637 : collate<char>(refs),
638 __l(newlocale(LC_ALL_MASK, n, 0))
639{
Howard Hinnant72f73582010-08-11 17:04:31 +0000640#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000641 if (__l == 0)
642 throw runtime_error("collate_byname<char>::collate_byname"
643 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000644#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000645}
646
647collate_byname<char>::collate_byname(const string& name, size_t refs)
648 : collate<char>(refs),
649 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
650{
Howard Hinnant72f73582010-08-11 17:04:31 +0000651#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000652 if (__l == 0)
653 throw runtime_error("collate_byname<char>::collate_byname"
654 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000655#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000656}
657
658collate_byname<char>::~collate_byname()
659{
660 freelocale(__l);
661}
662
663int
664collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
665 const char_type* __lo2, const char_type* __hi2) const
666{
667 string_type lhs(__lo1, __hi1);
668 string_type rhs(__lo2, __hi2);
669 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
670 if (r < 0)
671 return -1;
672 if (r > 0)
673 return 1;
674 return r;
675}
676
677collate_byname<char>::string_type
678collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
679{
680 const string_type in(lo, hi);
681 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
682 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
683 return out;
684}
685
686// template <> class collate_byname<wchar_t>
687
688collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
689 : collate<wchar_t>(refs),
690 __l(newlocale(LC_ALL_MASK, n, 0))
691{
Howard Hinnant72f73582010-08-11 17:04:31 +0000692#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000693 if (__l == 0)
694 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
695 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000696#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000697}
698
699collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
700 : collate<wchar_t>(refs),
701 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
702{
Howard Hinnant72f73582010-08-11 17:04:31 +0000703#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000704 if (__l == 0)
705 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
706 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000707#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000708}
709
710collate_byname<wchar_t>::~collate_byname()
711{
712 freelocale(__l);
713}
714
715int
716collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
717 const char_type* __lo2, const char_type* __hi2) const
718{
719 string_type lhs(__lo1, __hi1);
720 string_type rhs(__lo2, __hi2);
721 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
722 if (r < 0)
723 return -1;
724 if (r > 0)
725 return 1;
726 return r;
727}
728
729collate_byname<wchar_t>::string_type
730collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
731{
732 const string_type in(lo, hi);
733 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
734 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
735 return out;
736}
737
738// template <> class ctype<wchar_t>;
739
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000740const ctype_base::mask ctype_base::space;
741const ctype_base::mask ctype_base::print;
742const ctype_base::mask ctype_base::cntrl;
743const ctype_base::mask ctype_base::upper;
744const ctype_base::mask ctype_base::lower;
745const ctype_base::mask ctype_base::alpha;
746const ctype_base::mask ctype_base::digit;
747const ctype_base::mask ctype_base::punct;
748const ctype_base::mask ctype_base::xdigit;
749const ctype_base::mask ctype_base::blank;
750const ctype_base::mask ctype_base::alnum;
751const ctype_base::mask ctype_base::graph;
752
Howard Hinnantc51e1022010-05-11 19:42:16 +0000753locale::id ctype<wchar_t>::id;
754
755ctype<wchar_t>::~ctype()
756{
757}
758
759bool
760ctype<wchar_t>::do_is(mask m, char_type c) const
761{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000762 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000763}
764
765const wchar_t*
766ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
767{
768 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000769 *vec = static_cast<mask>(isascii(*low) ?
770 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000771 return low;
772}
773
774const wchar_t*
775ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
776{
777 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000778 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000779 break;
780 return low;
781}
782
783const wchar_t*
784ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
785{
786 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000787 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000788 break;
789 return low;
790}
791
792wchar_t
793ctype<wchar_t>::do_toupper(char_type c) const
794{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000795#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
796 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000797#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000798 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000799#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000800 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000801#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000802}
803
804const wchar_t*
805ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
806{
807 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000808#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
809 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000810#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000811 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
812 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000813#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000814 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000815#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000816 return low;
817}
818
819wchar_t
820ctype<wchar_t>::do_tolower(char_type c) const
821{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000822#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
823 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000824#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000825 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000826#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000827 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000828#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000829}
830
831const wchar_t*
832ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
833{
834 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000835#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
836 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000837#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000838 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
839 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000840#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000841 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000842#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000843 return low;
844}
845
846wchar_t
847ctype<wchar_t>::do_widen(char c) const
848{
849 return c;
850}
851
852const char*
853ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
854{
855 for (; low != high; ++low, ++dest)
856 *dest = *low;
857 return low;
858}
859
860char
861ctype<wchar_t>::do_narrow(char_type c, char dfault) const
862{
863 if (isascii(c))
864 return static_cast<char>(c);
865 return dfault;
866}
867
868const wchar_t*
869ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
870{
871 for (; low != high; ++low, ++dest)
872 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000873 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000874 else
875 *dest = dfault;
876 return low;
877}
878
879// template <> class ctype<char>;
880
881locale::id ctype<char>::id;
882
883ctype<char>::ctype(const mask* tab, bool del, size_t refs)
884 : locale::facet(refs),
885 __tab_(tab),
886 __del_(del)
887{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000888 if (__tab_ == 0)
889 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000890}
891
892ctype<char>::~ctype()
893{
894 if (__tab_ && __del_)
895 delete [] __tab_;
896}
897
898char
899ctype<char>::do_toupper(char_type c) const
900{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000901#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000902 return isascii(c) ?
903 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000904#elif defined(__NetBSD__)
905 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Howard Hinnant942dbd22013-03-29 18:27:28 +0000906#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clowada0f732013-02-07 14:22:51 +0000907 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000908 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000909#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000910 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000911#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000912}
913
914const char*
915ctype<char>::do_toupper(char_type* low, const char_type* high) const
916{
917 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000918#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000919 *low = isascii(*low) ?
920 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000921#elif defined(__NetBSD__)
922 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Howard Hinnant942dbd22013-03-29 18:27:28 +0000923#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clowada0f732013-02-07 14:22:51 +0000924 *low = isascii(*low) ?
925 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000926#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000927 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000928#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000929 return low;
930}
931
932char
933ctype<char>::do_tolower(char_type c) const
934{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000935#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000936 return isascii(c) ?
937 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000938#elif defined(__NetBSD__)
939 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
940#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
Marshall Clowada0f732013-02-07 14:22:51 +0000941 return isascii(c) ?
942 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000943#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000944 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000945#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000946}
947
948const char*
949ctype<char>::do_tolower(char_type* low, const char_type* high) const
950{
951 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000952#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000953 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000954#elif defined(__NetBSD__)
955 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Howard Hinnant942dbd22013-03-29 18:27:28 +0000956#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
Marshall Clowada0f732013-02-07 14:22:51 +0000957 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000958#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000959 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000960#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000961 return low;
962}
963
964char
965ctype<char>::do_widen(char c) const
966{
967 return c;
968}
969
970const char*
971ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
972{
973 for (; low != high; ++low, ++dest)
974 *dest = *low;
975 return low;
976}
977
978char
979ctype<char>::do_narrow(char_type c, char dfault) const
980{
981 if (isascii(c))
982 return static_cast<char>(c);
983 return dfault;
984}
985
986const char*
987ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
988{
989 for (; low != high; ++low, ++dest)
990 if (isascii(*low))
991 *dest = *low;
992 else
993 *dest = dfault;
994 return low;
995}
996
Howard Hinnant942dbd22013-03-29 18:27:28 +0000997#ifdef EMSCRIPTEN
998extern "C" const unsigned short ** __ctype_b_loc();
999extern "C" const int ** __ctype_tolower_loc();
1000extern "C" const int ** __ctype_toupper_loc();
1001#endif
1002
Howard Hinnantc51e1022010-05-11 19:42:16 +00001003const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001004ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001005{
David Chisnall1d581062011-09-21 08:39:44 +00001006#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001007 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001008#elif defined(__NetBSD__)
1009 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001010#elif defined(__GLIBC__)
1011 return __cloc()->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001012#elif __sun__
1013 return __ctype_mask;
Howard Hinnant13d8bc12013-08-01 18:17:34 +00001014#elif defined(_LIBCPP_MSVCRT)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001015 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnall1d581062011-09-21 08:39:44 +00001016// This is assumed to be safe, which is a nonsense assumption because we're
1017// going to end up dereferencing it later...
Howard Hinnant942dbd22013-03-29 18:27:28 +00001018#elif defined(EMSCRIPTEN)
1019 return *__ctype_b_loc();
Howard Hinnantea382952013-08-14 18:00:20 +00001020#elif defined(_AIX)
1021 return (const unsigned long *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001022#else
David Chisnall8074c342012-02-29 13:05:08 +00001023 // Platform not supported: abort so the person doing the port knows what to
1024 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001025# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001026 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001027 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001028 return NULL;
1029#endif
1030}
1031
Howard Hinnantd7a78632011-09-29 13:33:15 +00001032#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001033const int*
1034ctype<char>::__classic_lower_table() _NOEXCEPT
1035{
Alexis Hunt92b0c812011-07-09 00:56:23 +00001036 return __cloc()->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001037}
1038
1039const int*
1040ctype<char>::__classic_upper_table() _NOEXCEPT
1041{
Alexis Hunt92b0c812011-07-09 00:56:23 +00001042 return __cloc()->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001043}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001044#elif __NetBSD__
1045const short*
1046ctype<char>::__classic_lower_table() _NOEXCEPT
1047{
1048 return _C_tolower_tab_ + 1;
1049}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001050
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001051const short*
1052ctype<char>::__classic_upper_table() _NOEXCEPT
1053{
1054 return _C_toupper_tab_ + 1;
1055}
1056
1057#elif defined(EMSCRIPTEN)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001058const int*
1059ctype<char>::__classic_lower_table() _NOEXCEPT
1060{
1061 return *__ctype_tolower_loc();
1062}
1063
1064const int*
1065ctype<char>::__classic_upper_table() _NOEXCEPT
1066{
1067 return *__ctype_toupper_loc();
1068}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001069#endif // __GLIBC__ || EMSCRIPTEN || __NETBSD__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001070
Howard Hinnantc51e1022010-05-11 19:42:16 +00001071// template <> class ctype_byname<char>
1072
1073ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1074 : ctype<char>(0, false, refs),
1075 __l(newlocale(LC_ALL_MASK, name, 0))
1076{
Howard Hinnant72f73582010-08-11 17:04:31 +00001077#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001078 if (__l == 0)
1079 throw runtime_error("ctype_byname<char>::ctype_byname"
1080 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001081#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001082}
1083
1084ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1085 : ctype<char>(0, false, refs),
1086 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1087{
Howard Hinnant72f73582010-08-11 17:04:31 +00001088#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001089 if (__l == 0)
1090 throw runtime_error("ctype_byname<char>::ctype_byname"
1091 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001092#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001093}
1094
1095ctype_byname<char>::~ctype_byname()
1096{
1097 freelocale(__l);
1098}
1099
1100char
1101ctype_byname<char>::do_toupper(char_type c) const
1102{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001103 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001104}
1105
1106const char*
1107ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1108{
1109 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001110 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001111 return low;
1112}
1113
1114char
1115ctype_byname<char>::do_tolower(char_type c) const
1116{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001117 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001118}
1119
1120const char*
1121ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1122{
1123 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001124 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001125 return low;
1126}
1127
1128// template <> class ctype_byname<wchar_t>
1129
1130ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1131 : ctype<wchar_t>(refs),
1132 __l(newlocale(LC_ALL_MASK, name, 0))
1133{
Howard Hinnant72f73582010-08-11 17:04:31 +00001134#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001135 if (__l == 0)
1136 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1137 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001138#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001139}
1140
1141ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1142 : ctype<wchar_t>(refs),
1143 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1144{
Howard Hinnant72f73582010-08-11 17:04:31 +00001145#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001146 if (__l == 0)
1147 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1148 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001149#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001150}
1151
1152ctype_byname<wchar_t>::~ctype_byname()
1153{
1154 freelocale(__l);
1155}
1156
1157bool
1158ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1159{
Alexis Huntc2017f12011-07-09 03:40:04 +00001160#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001161 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001162#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001163 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001164 wint_t ch = static_cast<wint_t>(c);
1165 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1166 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1167 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1168 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1169 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1170 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1171 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1172 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1173 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1174 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001175 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001176#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001177}
1178
1179const wchar_t*
1180ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1181{
1182 for (; low != high; ++low, ++vec)
1183 {
1184 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001185 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001186 else
1187 {
1188 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001189 wint_t ch = static_cast<wint_t>(*low);
1190 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001191 *vec |= space;
Marshall Clowada0f732013-02-07 14:22:51 +00001192 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001193 *vec |= print;
Marshall Clowada0f732013-02-07 14:22:51 +00001194 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001195 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001196 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001197 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001198 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001199 *vec |= lower;
Marshall Clowada0f732013-02-07 14:22:51 +00001200 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001201 *vec |= alpha;
Marshall Clowada0f732013-02-07 14:22:51 +00001202 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001203 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001204 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001205 *vec |= punct;
Marshall Clowada0f732013-02-07 14:22:51 +00001206 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001207 *vec |= xdigit;
1208 }
1209 }
1210 return low;
1211}
1212
1213const wchar_t*
1214ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1215{
1216 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001217 {
1218#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001219 if (iswctype_l(*low, m, __l))
1220 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001221#else
Marshall Clowada0f732013-02-07 14:22:51 +00001222 wint_t ch = static_cast<wint_t>(*low);
1223 if (m & space && iswspace_l(ch, __l)) break;
1224 if (m & print && iswprint_l(ch, __l)) break;
1225 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1226 if (m & upper && iswupper_l(ch, __l)) break;
1227 if (m & lower && iswlower_l(ch, __l)) break;
1228 if (m & alpha && iswalpha_l(ch, __l)) break;
1229 if (m & digit && iswdigit_l(ch, __l)) break;
1230 if (m & punct && iswpunct_l(ch, __l)) break;
1231 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1232 if (m & blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001233#endif
1234 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001235 return low;
1236}
1237
1238const wchar_t*
1239ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1240{
1241 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001242 {
1243#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001244 if (!iswctype_l(*low, m, __l))
1245 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001246#else
Marshall Clowada0f732013-02-07 14:22:51 +00001247 wint_t ch = static_cast<wint_t>(*low);
1248 if (m & space && iswspace_l(ch, __l)) continue;
1249 if (m & print && iswprint_l(ch, __l)) continue;
1250 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1251 if (m & upper && iswupper_l(ch, __l)) continue;
1252 if (m & lower && iswlower_l(ch, __l)) continue;
1253 if (m & alpha && iswalpha_l(ch, __l)) continue;
1254 if (m & digit && iswdigit_l(ch, __l)) continue;
1255 if (m & punct && iswpunct_l(ch, __l)) continue;
1256 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1257 if (m & blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001258 break;
1259#endif
1260 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001261 return low;
1262}
1263
1264wchar_t
1265ctype_byname<wchar_t>::do_toupper(char_type c) const
1266{
1267 return towupper_l(c, __l);
1268}
1269
1270const wchar_t*
1271ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1272{
1273 for (; low != high; ++low)
1274 *low = towupper_l(*low, __l);
1275 return low;
1276}
1277
1278wchar_t
1279ctype_byname<wchar_t>::do_tolower(char_type c) const
1280{
1281 return towlower_l(c, __l);
1282}
1283
1284const wchar_t*
1285ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1286{
1287 for (; low != high; ++low)
1288 *low = towlower_l(*low, __l);
1289 return low;
1290}
1291
1292wchar_t
1293ctype_byname<wchar_t>::do_widen(char c) const
1294{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001295#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001296 return btowc_l(c, __l);
1297#else
1298 return __btowc_l(c, __l);
1299#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300}
1301
1302const char*
1303ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1304{
1305 for (; low != high; ++low, ++dest)
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001306#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001307 *dest = btowc_l(*low, __l);
1308#else
1309 *dest = __btowc_l(*low, __l);
1310#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001311 return low;
1312}
1313
1314char
1315ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1316{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001317#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001318 int r = wctob_l(c, __l);
1319#else
1320 int r = __wctob_l(c, __l);
1321#endif
Howard Hinnant434ebf72012-12-27 18:46:00 +00001322 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001323}
1324
1325const wchar_t*
1326ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1327{
1328 for (; low != high; ++low, ++dest)
1329 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001330#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001331 int r = wctob_l(*low, __l);
1332#else
1333 int r = __wctob_l(*low, __l);
1334#endif
Howard Hinnant434ebf72012-12-27 18:46:00 +00001335 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001336 }
1337 return low;
1338}
1339
1340// template <> class codecvt<char, char, mbstate_t>
1341
Howard Hinnantffb308e2010-08-22 00:03:27 +00001342locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001343
1344codecvt<char, char, mbstate_t>::~codecvt()
1345{
1346}
1347
1348codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001349codecvt<char, char, mbstate_t>::do_out(state_type&,
1350 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001351 extern_type* to, extern_type*, extern_type*& to_nxt) const
1352{
1353 frm_nxt = frm;
1354 to_nxt = to;
1355 return noconv;
1356}
1357
1358codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001359codecvt<char, char, mbstate_t>::do_in(state_type&,
1360 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001361 intern_type* to, intern_type*, intern_type*& to_nxt) const
1362{
1363 frm_nxt = frm;
1364 to_nxt = to;
1365 return noconv;
1366}
1367
1368codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001369codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001370 extern_type* to, extern_type*, extern_type*& to_nxt) const
1371{
1372 to_nxt = to;
1373 return noconv;
1374}
1375
1376int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001377codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001378{
1379 return 1;
1380}
1381
1382bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001383codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001384{
1385 return true;
1386}
1387
1388int
1389codecvt<char, char, mbstate_t>::do_length(state_type&,
1390 const extern_type* frm, const extern_type* end, size_t mx) const
1391{
Howard Hinnant28b24882011-12-01 20:21:04 +00001392 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001393}
1394
1395int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001396codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001397{
1398 return 1;
1399}
1400
1401// template <> class codecvt<wchar_t, char, mbstate_t>
1402
Howard Hinnantffb308e2010-08-22 00:03:27 +00001403locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001404
1405codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1406 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001407 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001408{
1409}
1410
1411codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1412 : locale::facet(refs),
1413 __l(newlocale(LC_ALL_MASK, nm, 0))
1414{
Howard Hinnant72f73582010-08-11 17:04:31 +00001415#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001416 if (__l == 0)
1417 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1418 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001419#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001420}
1421
1422codecvt<wchar_t, char, mbstate_t>::~codecvt()
1423{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001424 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001425 freelocale(__l);
1426}
1427
1428codecvt<wchar_t, char, mbstate_t>::result
1429codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001430 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001431 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1432{
1433 // look for first internal null in frm
1434 const intern_type* fend = frm;
1435 for (; fend != frm_end; ++fend)
1436 if (*fend == 0)
1437 break;
1438 // loop over all null-terminated sequences in frm
1439 to_nxt = to;
1440 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1441 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001442 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001443 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001444#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001445 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1446 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001447#else
1448 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1449#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001450 if (n == size_t(-1))
1451 {
1452 // need to recover to_nxt
1453 for (to_nxt = to; frm != frm_nxt; ++frm)
1454 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001455#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001456 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1457#else
1458 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1459#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001460 if (n == size_t(-1))
1461 break;
1462 to_nxt += n;
1463 }
1464 frm_nxt = frm;
1465 return error;
1466 }
1467 if (n == 0)
1468 return partial;
1469 to_nxt += n;
1470 if (to_nxt == to_end)
1471 break;
1472 if (fend != frm_end) // set up next null terminated sequence
1473 {
1474 // Try to write the terminating null
1475 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001476#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001477 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1478#else
1479 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1480#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001481 if (n == size_t(-1)) // on error
1482 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001483 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001484 return partial;
1485 for (extern_type* p = tmp; n; --n) // write it
1486 *to_nxt++ = *p++;
1487 ++frm_nxt;
1488 // look for next null in frm
1489 for (fend = frm_nxt; fend != frm_end; ++fend)
1490 if (*fend == 0)
1491 break;
1492 }
1493 }
1494 return frm_nxt == frm_end ? ok : partial;
1495}
1496
1497codecvt<wchar_t, char, mbstate_t>::result
1498codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001499 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001500 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1501{
1502 // look for first internal null in frm
1503 const extern_type* fend = frm;
1504 for (; fend != frm_end; ++fend)
1505 if (*fend == 0)
1506 break;
1507 // loop over all null-terminated sequences in frm
1508 to_nxt = to;
1509 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1510 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001511 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001512 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001513#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001514 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1515 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001516#else
1517 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1518#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001519 if (n == size_t(-1))
1520 {
1521 // need to recover to_nxt
1522 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1523 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001524#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001525 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1526 &save_state, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001527#else
1528 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1529#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001530 switch (n)
1531 {
1532 case 0:
1533 ++frm;
1534 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001535 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001536 frm_nxt = frm;
1537 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001538 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001539 frm_nxt = frm;
1540 return partial;
1541 default:
1542 frm += n;
1543 break;
1544 }
1545 }
1546 frm_nxt = frm;
1547 return frm_nxt == frm_end ? ok : partial;
1548 }
1549 if (n == 0)
1550 return error;
1551 to_nxt += n;
1552 if (to_nxt == to_end)
1553 break;
1554 if (fend != frm_end) // set up next null terminated sequence
1555 {
1556 // Try to write the terminating null
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001557#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001558 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1559#else
1560 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1561#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001562 if (n != 0) // on error
1563 return error;
1564 ++to_nxt;
1565 ++frm_nxt;
1566 // look for next null in frm
1567 for (fend = frm_nxt; fend != frm_end; ++fend)
1568 if (*fend == 0)
1569 break;
1570 }
1571 }
1572 return frm_nxt == frm_end ? ok : partial;
1573}
1574
1575codecvt<wchar_t, char, mbstate_t>::result
1576codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1577 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1578{
1579 to_nxt = to;
1580 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001581#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001582 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1583#else
1584 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1585#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001586 if (n == size_t(-1) || n == 0) // on error
1587 return error;
1588 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001589 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001590 return partial;
1591 for (extern_type* p = tmp; n; --n) // write it
1592 *to_nxt++ = *p++;
1593 return ok;
1594}
1595
1596int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001597codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001598{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001599#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001600 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1601#else
1602 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1603#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001604 {
1605 // stateless encoding
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001606#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001607 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1608#else
1609 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1610#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001611 return 1; // which take more than 1 char to form a wchar_t
1612 return 0;
1613 }
1614 return -1;
1615}
1616
1617bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001618codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001619{
1620 return false;
1621}
1622
1623int
1624codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1625 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1626{
1627 int nbytes = 0;
1628 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1629 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001630#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001631 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001632#else
1633 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1634#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001635 switch (n)
1636 {
1637 case 0:
1638 ++nbytes;
1639 ++frm;
1640 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001641 case size_t(-1):
1642 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001643 return nbytes;
1644 default:
1645 nbytes += n;
1646 frm += n;
1647 break;
1648 }
1649 }
1650 return nbytes;
1651}
1652
1653int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001654codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001655{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001656#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clowab9c1772013-02-07 17:20:56 +00001657 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001658#else
Marshall Clowab9c1772013-02-07 17:20:56 +00001659 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001660#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001661}
1662
1663// Valid UTF ranges
1664// UTF-32 UTF-16 UTF-8 # of code points
1665// first second first second third fourth
1666// 000000 - 00007F 0000 - 007F 00 - 7F 127
1667// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1668// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1669// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1670// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1671// 00D800 - 00DFFF invalid
1672// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1673// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1674// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1675// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1676
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001677static
1678codecvt_base::result
1679utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1680 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1681 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1682{
1683 frm_nxt = frm;
1684 to_nxt = to;
1685 if (mode & generate_header)
1686 {
1687 if (to_end-to_nxt < 3)
1688 return codecvt_base::partial;
1689 *to_nxt++ = static_cast<uint8_t>(0xEF);
1690 *to_nxt++ = static_cast<uint8_t>(0xBB);
1691 *to_nxt++ = static_cast<uint8_t>(0xBF);
1692 }
1693 for (; frm_nxt < frm_end; ++frm_nxt)
1694 {
1695 uint16_t wc1 = *frm_nxt;
1696 if (wc1 > Maxcode)
1697 return codecvt_base::error;
1698 if (wc1 < 0x0080)
1699 {
1700 if (to_end-to_nxt < 1)
1701 return codecvt_base::partial;
1702 *to_nxt++ = static_cast<uint8_t>(wc1);
1703 }
1704 else if (wc1 < 0x0800)
1705 {
1706 if (to_end-to_nxt < 2)
1707 return codecvt_base::partial;
1708 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1709 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1710 }
1711 else if (wc1 < 0xD800)
1712 {
1713 if (to_end-to_nxt < 3)
1714 return codecvt_base::partial;
1715 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1716 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1717 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1718 }
1719 else if (wc1 < 0xDC00)
1720 {
1721 if (frm_end-frm_nxt < 2)
1722 return codecvt_base::partial;
1723 uint16_t wc2 = frm_nxt[1];
1724 if ((wc2 & 0xFC00) != 0xDC00)
1725 return codecvt_base::error;
1726 if (to_end-to_nxt < 4)
1727 return codecvt_base::partial;
1728 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1729 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1730 return codecvt_base::error;
1731 ++frm_nxt;
1732 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1733 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1734 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1735 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1736 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1737 }
1738 else if (wc1 < 0xE000)
1739 {
1740 return codecvt_base::error;
1741 }
1742 else
1743 {
1744 if (to_end-to_nxt < 3)
1745 return codecvt_base::partial;
1746 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1747 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1748 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1749 }
1750 }
1751 return codecvt_base::ok;
1752}
1753
1754static
1755codecvt_base::result
1756utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1757 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1758 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1759{
1760 frm_nxt = frm;
1761 to_nxt = to;
1762 if (mode & generate_header)
1763 {
1764 if (to_end-to_nxt < 3)
1765 return codecvt_base::partial;
1766 *to_nxt++ = static_cast<uint8_t>(0xEF);
1767 *to_nxt++ = static_cast<uint8_t>(0xBB);
1768 *to_nxt++ = static_cast<uint8_t>(0xBF);
1769 }
1770 for (; frm_nxt < frm_end; ++frm_nxt)
1771 {
1772 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1773 if (wc1 > Maxcode)
1774 return codecvt_base::error;
1775 if (wc1 < 0x0080)
1776 {
1777 if (to_end-to_nxt < 1)
1778 return codecvt_base::partial;
1779 *to_nxt++ = static_cast<uint8_t>(wc1);
1780 }
1781 else if (wc1 < 0x0800)
1782 {
1783 if (to_end-to_nxt < 2)
1784 return codecvt_base::partial;
1785 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1786 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1787 }
1788 else if (wc1 < 0xD800)
1789 {
1790 if (to_end-to_nxt < 3)
1791 return codecvt_base::partial;
1792 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1793 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1794 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1795 }
1796 else if (wc1 < 0xDC00)
1797 {
1798 if (frm_end-frm_nxt < 2)
1799 return codecvt_base::partial;
1800 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1801 if ((wc2 & 0xFC00) != 0xDC00)
1802 return codecvt_base::error;
1803 if (to_end-to_nxt < 4)
1804 return codecvt_base::partial;
1805 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1806 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1807 return codecvt_base::error;
1808 ++frm_nxt;
1809 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1810 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1811 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1812 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1813 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1814 }
1815 else if (wc1 < 0xE000)
1816 {
1817 return codecvt_base::error;
1818 }
1819 else
1820 {
1821 if (to_end-to_nxt < 3)
1822 return codecvt_base::partial;
1823 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1824 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1825 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1826 }
1827 }
1828 return codecvt_base::ok;
1829}
1830
1831static
1832codecvt_base::result
1833utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1834 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1835 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1836{
1837 frm_nxt = frm;
1838 to_nxt = to;
1839 if (mode & consume_header)
1840 {
1841 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1842 frm_nxt[2] == 0xBF)
1843 frm_nxt += 3;
1844 }
1845 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1846 {
1847 uint8_t c1 = *frm_nxt;
1848 if (c1 > Maxcode)
1849 return codecvt_base::error;
1850 if (c1 < 0x80)
1851 {
1852 *to_nxt = static_cast<uint16_t>(c1);
1853 ++frm_nxt;
1854 }
1855 else if (c1 < 0xC2)
1856 {
1857 return codecvt_base::error;
1858 }
1859 else if (c1 < 0xE0)
1860 {
1861 if (frm_end-frm_nxt < 2)
1862 return codecvt_base::partial;
1863 uint8_t c2 = frm_nxt[1];
1864 if ((c2 & 0xC0) != 0x80)
1865 return codecvt_base::error;
1866 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1867 if (t > Maxcode)
1868 return codecvt_base::error;
1869 *to_nxt = t;
1870 frm_nxt += 2;
1871 }
1872 else if (c1 < 0xF0)
1873 {
1874 if (frm_end-frm_nxt < 3)
1875 return codecvt_base::partial;
1876 uint8_t c2 = frm_nxt[1];
1877 uint8_t c3 = frm_nxt[2];
1878 switch (c1)
1879 {
1880 case 0xE0:
1881 if ((c2 & 0xE0) != 0xA0)
1882 return codecvt_base::error;
1883 break;
1884 case 0xED:
1885 if ((c2 & 0xE0) != 0x80)
1886 return codecvt_base::error;
1887 break;
1888 default:
1889 if ((c2 & 0xC0) != 0x80)
1890 return codecvt_base::error;
1891 break;
1892 }
1893 if ((c3 & 0xC0) != 0x80)
1894 return codecvt_base::error;
1895 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1896 | ((c2 & 0x3F) << 6)
1897 | (c3 & 0x3F));
1898 if (t > Maxcode)
1899 return codecvt_base::error;
1900 *to_nxt = t;
1901 frm_nxt += 3;
1902 }
1903 else if (c1 < 0xF5)
1904 {
1905 if (frm_end-frm_nxt < 4)
1906 return codecvt_base::partial;
1907 uint8_t c2 = frm_nxt[1];
1908 uint8_t c3 = frm_nxt[2];
1909 uint8_t c4 = frm_nxt[3];
1910 switch (c1)
1911 {
1912 case 0xF0:
1913 if (!(0x90 <= c2 && c2 <= 0xBF))
1914 return codecvt_base::error;
1915 break;
1916 case 0xF4:
1917 if ((c2 & 0xF0) != 0x80)
1918 return codecvt_base::error;
1919 break;
1920 default:
1921 if ((c2 & 0xC0) != 0x80)
1922 return codecvt_base::error;
1923 break;
1924 }
1925 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1926 return codecvt_base::error;
1927 if (to_end-to_nxt < 2)
1928 return codecvt_base::partial;
1929 if (((((unsigned long)c1 & 7) << 18) +
1930 (((unsigned long)c2 & 0x3F) << 12) +
1931 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1932 return codecvt_base::error;
1933 *to_nxt = static_cast<uint16_t>(
1934 0xD800
1935 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1936 | ((c2 & 0x0F) << 2)
1937 | ((c3 & 0x30) >> 4));
1938 *++to_nxt = static_cast<uint16_t>(
1939 0xDC00
1940 | ((c3 & 0x0F) << 6)
1941 | (c4 & 0x3F));
1942 frm_nxt += 4;
1943 }
1944 else
1945 {
1946 return codecvt_base::error;
1947 }
1948 }
1949 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1950}
1951
1952static
1953codecvt_base::result
1954utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1955 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1956 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1957{
1958 frm_nxt = frm;
1959 to_nxt = to;
1960 if (mode & consume_header)
1961 {
1962 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1963 frm_nxt[2] == 0xBF)
1964 frm_nxt += 3;
1965 }
1966 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1967 {
1968 uint8_t c1 = *frm_nxt;
1969 if (c1 > Maxcode)
1970 return codecvt_base::error;
1971 if (c1 < 0x80)
1972 {
1973 *to_nxt = static_cast<uint32_t>(c1);
1974 ++frm_nxt;
1975 }
1976 else if (c1 < 0xC2)
1977 {
1978 return codecvt_base::error;
1979 }
1980 else if (c1 < 0xE0)
1981 {
1982 if (frm_end-frm_nxt < 2)
1983 return codecvt_base::partial;
1984 uint8_t c2 = frm_nxt[1];
1985 if ((c2 & 0xC0) != 0x80)
1986 return codecvt_base::error;
1987 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1988 if (t > Maxcode)
1989 return codecvt_base::error;
1990 *to_nxt = static_cast<uint32_t>(t);
1991 frm_nxt += 2;
1992 }
1993 else if (c1 < 0xF0)
1994 {
1995 if (frm_end-frm_nxt < 3)
1996 return codecvt_base::partial;
1997 uint8_t c2 = frm_nxt[1];
1998 uint8_t c3 = frm_nxt[2];
1999 switch (c1)
2000 {
2001 case 0xE0:
2002 if ((c2 & 0xE0) != 0xA0)
2003 return codecvt_base::error;
2004 break;
2005 case 0xED:
2006 if ((c2 & 0xE0) != 0x80)
2007 return codecvt_base::error;
2008 break;
2009 default:
2010 if ((c2 & 0xC0) != 0x80)
2011 return codecvt_base::error;
2012 break;
2013 }
2014 if ((c3 & 0xC0) != 0x80)
2015 return codecvt_base::error;
2016 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2017 | ((c2 & 0x3F) << 6)
2018 | (c3 & 0x3F));
2019 if (t > Maxcode)
2020 return codecvt_base::error;
2021 *to_nxt = static_cast<uint32_t>(t);
2022 frm_nxt += 3;
2023 }
2024 else if (c1 < 0xF5)
2025 {
2026 if (frm_end-frm_nxt < 4)
2027 return codecvt_base::partial;
2028 uint8_t c2 = frm_nxt[1];
2029 uint8_t c3 = frm_nxt[2];
2030 uint8_t c4 = frm_nxt[3];
2031 switch (c1)
2032 {
2033 case 0xF0:
2034 if (!(0x90 <= c2 && c2 <= 0xBF))
2035 return codecvt_base::error;
2036 break;
2037 case 0xF4:
2038 if ((c2 & 0xF0) != 0x80)
2039 return codecvt_base::error;
2040 break;
2041 default:
2042 if ((c2 & 0xC0) != 0x80)
2043 return codecvt_base::error;
2044 break;
2045 }
2046 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2047 return codecvt_base::error;
2048 if (to_end-to_nxt < 2)
2049 return codecvt_base::partial;
2050 if (((((unsigned long)c1 & 7) << 18) +
2051 (((unsigned long)c2 & 0x3F) << 12) +
2052 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2053 return codecvt_base::error;
2054 *to_nxt = static_cast<uint32_t>(
2055 0xD800
2056 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2057 | ((c2 & 0x0F) << 2)
2058 | ((c3 & 0x30) >> 4));
2059 *++to_nxt = static_cast<uint32_t>(
2060 0xDC00
2061 | ((c3 & 0x0F) << 6)
2062 | (c4 & 0x3F));
2063 frm_nxt += 4;
2064 }
2065 else
2066 {
2067 return codecvt_base::error;
2068 }
2069 }
2070 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2071}
2072
2073static
2074int
2075utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2076 size_t mx, unsigned long Maxcode = 0x10FFFF,
2077 codecvt_mode mode = codecvt_mode(0))
2078{
2079 const uint8_t* frm_nxt = frm;
2080 if (mode & consume_header)
2081 {
2082 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2083 frm_nxt[2] == 0xBF)
2084 frm_nxt += 3;
2085 }
2086 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2087 {
2088 uint8_t c1 = *frm_nxt;
2089 if (c1 > Maxcode)
2090 break;
2091 if (c1 < 0x80)
2092 {
2093 ++frm_nxt;
2094 }
2095 else if (c1 < 0xC2)
2096 {
2097 break;
2098 }
2099 else if (c1 < 0xE0)
2100 {
2101 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2102 break;
2103 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2104 if (t > Maxcode)
2105 break;
2106 frm_nxt += 2;
2107 }
2108 else if (c1 < 0xF0)
2109 {
2110 if (frm_end-frm_nxt < 3)
2111 break;
2112 uint8_t c2 = frm_nxt[1];
2113 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002114 switch (c1)
2115 {
2116 case 0xE0:
2117 if ((c2 & 0xE0) != 0xA0)
2118 return static_cast<int>(frm_nxt - frm);
2119 break;
2120 case 0xED:
2121 if ((c2 & 0xE0) != 0x80)
2122 return static_cast<int>(frm_nxt - frm);
2123 break;
2124 default:
2125 if ((c2 & 0xC0) != 0x80)
2126 return static_cast<int>(frm_nxt - frm);
2127 break;
2128 }
2129 if ((c3 & 0xC0) != 0x80)
2130 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002131 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002132 break;
2133 frm_nxt += 3;
2134 }
2135 else if (c1 < 0xF5)
2136 {
2137 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2138 break;
2139 uint8_t c2 = frm_nxt[1];
2140 uint8_t c3 = frm_nxt[2];
2141 uint8_t c4 = frm_nxt[3];
2142 switch (c1)
2143 {
2144 case 0xF0:
2145 if (!(0x90 <= c2 && c2 <= 0xBF))
2146 return static_cast<int>(frm_nxt - frm);
2147 break;
2148 case 0xF4:
2149 if ((c2 & 0xF0) != 0x80)
2150 return static_cast<int>(frm_nxt - frm);
2151 break;
2152 default:
2153 if ((c2 & 0xC0) != 0x80)
2154 return static_cast<int>(frm_nxt - frm);
2155 break;
2156 }
2157 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2158 break;
2159 if (((((unsigned long)c1 & 7) << 18) +
2160 (((unsigned long)c2 & 0x3F) << 12) +
2161 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2162 break;
2163 ++nchar16_t;
2164 frm_nxt += 4;
2165 }
2166 else
2167 {
2168 break;
2169 }
2170 }
2171 return static_cast<int>(frm_nxt - frm);
2172}
2173
2174static
2175codecvt_base::result
2176ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2177 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2178 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2179{
2180 frm_nxt = frm;
2181 to_nxt = to;
2182 if (mode & generate_header)
2183 {
2184 if (to_end-to_nxt < 3)
2185 return codecvt_base::partial;
2186 *to_nxt++ = static_cast<uint8_t>(0xEF);
2187 *to_nxt++ = static_cast<uint8_t>(0xBB);
2188 *to_nxt++ = static_cast<uint8_t>(0xBF);
2189 }
2190 for (; frm_nxt < frm_end; ++frm_nxt)
2191 {
2192 uint32_t wc = *frm_nxt;
2193 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2194 return codecvt_base::error;
2195 if (wc < 0x000080)
2196 {
2197 if (to_end-to_nxt < 1)
2198 return codecvt_base::partial;
2199 *to_nxt++ = static_cast<uint8_t>(wc);
2200 }
2201 else if (wc < 0x000800)
2202 {
2203 if (to_end-to_nxt < 2)
2204 return codecvt_base::partial;
2205 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2206 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2207 }
2208 else if (wc < 0x010000)
2209 {
2210 if (to_end-to_nxt < 3)
2211 return codecvt_base::partial;
2212 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2213 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2214 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2215 }
2216 else // if (wc < 0x110000)
2217 {
2218 if (to_end-to_nxt < 4)
2219 return codecvt_base::partial;
2220 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2221 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2222 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2223 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2224 }
2225 }
2226 return codecvt_base::ok;
2227}
2228
2229static
2230codecvt_base::result
2231utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2232 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2233 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2234{
2235 frm_nxt = frm;
2236 to_nxt = to;
2237 if (mode & consume_header)
2238 {
2239 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2240 frm_nxt[2] == 0xBF)
2241 frm_nxt += 3;
2242 }
2243 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2244 {
2245 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2246 if (c1 < 0x80)
2247 {
2248 if (c1 > Maxcode)
2249 return codecvt_base::error;
2250 *to_nxt = static_cast<uint32_t>(c1);
2251 ++frm_nxt;
2252 }
2253 else if (c1 < 0xC2)
2254 {
2255 return codecvt_base::error;
2256 }
2257 else if (c1 < 0xE0)
2258 {
2259 if (frm_end-frm_nxt < 2)
2260 return codecvt_base::partial;
2261 uint8_t c2 = frm_nxt[1];
2262 if ((c2 & 0xC0) != 0x80)
2263 return codecvt_base::error;
2264 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2265 | (c2 & 0x3F));
2266 if (t > Maxcode)
2267 return codecvt_base::error;
2268 *to_nxt = t;
2269 frm_nxt += 2;
2270 }
2271 else if (c1 < 0xF0)
2272 {
2273 if (frm_end-frm_nxt < 3)
2274 return codecvt_base::partial;
2275 uint8_t c2 = frm_nxt[1];
2276 uint8_t c3 = frm_nxt[2];
2277 switch (c1)
2278 {
2279 case 0xE0:
2280 if ((c2 & 0xE0) != 0xA0)
2281 return codecvt_base::error;
2282 break;
2283 case 0xED:
2284 if ((c2 & 0xE0) != 0x80)
2285 return codecvt_base::error;
2286 break;
2287 default:
2288 if ((c2 & 0xC0) != 0x80)
2289 return codecvt_base::error;
2290 break;
2291 }
2292 if ((c3 & 0xC0) != 0x80)
2293 return codecvt_base::error;
2294 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2295 | ((c2 & 0x3F) << 6)
2296 | (c3 & 0x3F));
2297 if (t > Maxcode)
2298 return codecvt_base::error;
2299 *to_nxt = t;
2300 frm_nxt += 3;
2301 }
2302 else if (c1 < 0xF5)
2303 {
2304 if (frm_end-frm_nxt < 4)
2305 return codecvt_base::partial;
2306 uint8_t c2 = frm_nxt[1];
2307 uint8_t c3 = frm_nxt[2];
2308 uint8_t c4 = frm_nxt[3];
2309 switch (c1)
2310 {
2311 case 0xF0:
2312 if (!(0x90 <= c2 && c2 <= 0xBF))
2313 return codecvt_base::error;
2314 break;
2315 case 0xF4:
2316 if ((c2 & 0xF0) != 0x80)
2317 return codecvt_base::error;
2318 break;
2319 default:
2320 if ((c2 & 0xC0) != 0x80)
2321 return codecvt_base::error;
2322 break;
2323 }
2324 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2325 return codecvt_base::error;
2326 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2327 | ((c2 & 0x3F) << 12)
2328 | ((c3 & 0x3F) << 6)
2329 | (c4 & 0x3F));
2330 if (t > Maxcode)
2331 return codecvt_base::error;
2332 *to_nxt = t;
2333 frm_nxt += 4;
2334 }
2335 else
2336 {
2337 return codecvt_base::error;
2338 }
2339 }
2340 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2341}
2342
2343static
2344int
2345utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2346 size_t mx, unsigned long Maxcode = 0x10FFFF,
2347 codecvt_mode mode = codecvt_mode(0))
2348{
2349 const uint8_t* frm_nxt = frm;
2350 if (mode & consume_header)
2351 {
2352 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2353 frm_nxt[2] == 0xBF)
2354 frm_nxt += 3;
2355 }
2356 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2357 {
2358 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2359 if (c1 < 0x80)
2360 {
2361 if (c1 > Maxcode)
2362 break;
2363 ++frm_nxt;
2364 }
2365 else if (c1 < 0xC2)
2366 {
2367 break;
2368 }
2369 else if (c1 < 0xE0)
2370 {
2371 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2372 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002373 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002374 break;
2375 frm_nxt += 2;
2376 }
2377 else if (c1 < 0xF0)
2378 {
2379 if (frm_end-frm_nxt < 3)
2380 break;
2381 uint8_t c2 = frm_nxt[1];
2382 uint8_t c3 = frm_nxt[2];
2383 switch (c1)
2384 {
2385 case 0xE0:
2386 if ((c2 & 0xE0) != 0xA0)
2387 return static_cast<int>(frm_nxt - frm);
2388 break;
2389 case 0xED:
2390 if ((c2 & 0xE0) != 0x80)
2391 return static_cast<int>(frm_nxt - frm);
2392 break;
2393 default:
2394 if ((c2 & 0xC0) != 0x80)
2395 return static_cast<int>(frm_nxt - frm);
2396 break;
2397 }
2398 if ((c3 & 0xC0) != 0x80)
2399 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002400 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002401 break;
2402 frm_nxt += 3;
2403 }
2404 else if (c1 < 0xF5)
2405 {
2406 if (frm_end-frm_nxt < 4)
2407 break;
2408 uint8_t c2 = frm_nxt[1];
2409 uint8_t c3 = frm_nxt[2];
2410 uint8_t c4 = frm_nxt[3];
2411 switch (c1)
2412 {
2413 case 0xF0:
2414 if (!(0x90 <= c2 && c2 <= 0xBF))
2415 return static_cast<int>(frm_nxt - frm);
2416 break;
2417 case 0xF4:
2418 if ((c2 & 0xF0) != 0x80)
2419 return static_cast<int>(frm_nxt - frm);
2420 break;
2421 default:
2422 if ((c2 & 0xC0) != 0x80)
2423 return static_cast<int>(frm_nxt - frm);
2424 break;
2425 }
2426 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2427 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002428 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2429 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002430 break;
2431 frm_nxt += 4;
2432 }
2433 else
2434 {
2435 break;
2436 }
2437 }
2438 return static_cast<int>(frm_nxt - frm);
2439}
2440
2441static
2442codecvt_base::result
2443ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2444 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2445 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2446{
2447 frm_nxt = frm;
2448 to_nxt = to;
2449 if (mode & generate_header)
2450 {
2451 if (to_end-to_nxt < 3)
2452 return codecvt_base::partial;
2453 *to_nxt++ = static_cast<uint8_t>(0xEF);
2454 *to_nxt++ = static_cast<uint8_t>(0xBB);
2455 *to_nxt++ = static_cast<uint8_t>(0xBF);
2456 }
2457 for (; frm_nxt < frm_end; ++frm_nxt)
2458 {
2459 uint16_t wc = *frm_nxt;
2460 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2461 return codecvt_base::error;
2462 if (wc < 0x0080)
2463 {
2464 if (to_end-to_nxt < 1)
2465 return codecvt_base::partial;
2466 *to_nxt++ = static_cast<uint8_t>(wc);
2467 }
2468 else if (wc < 0x0800)
2469 {
2470 if (to_end-to_nxt < 2)
2471 return codecvt_base::partial;
2472 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2473 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2474 }
2475 else // if (wc <= 0xFFFF)
2476 {
2477 if (to_end-to_nxt < 3)
2478 return codecvt_base::partial;
2479 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2480 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2481 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2482 }
2483 }
2484 return codecvt_base::ok;
2485}
2486
2487static
2488codecvt_base::result
2489utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2490 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2491 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2492{
2493 frm_nxt = frm;
2494 to_nxt = to;
2495 if (mode & consume_header)
2496 {
2497 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2498 frm_nxt[2] == 0xBF)
2499 frm_nxt += 3;
2500 }
2501 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2502 {
2503 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2504 if (c1 < 0x80)
2505 {
2506 if (c1 > Maxcode)
2507 return codecvt_base::error;
2508 *to_nxt = static_cast<uint16_t>(c1);
2509 ++frm_nxt;
2510 }
2511 else if (c1 < 0xC2)
2512 {
2513 return codecvt_base::error;
2514 }
2515 else if (c1 < 0xE0)
2516 {
2517 if (frm_end-frm_nxt < 2)
2518 return codecvt_base::partial;
2519 uint8_t c2 = frm_nxt[1];
2520 if ((c2 & 0xC0) != 0x80)
2521 return codecvt_base::error;
2522 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2523 | (c2 & 0x3F));
2524 if (t > Maxcode)
2525 return codecvt_base::error;
2526 *to_nxt = t;
2527 frm_nxt += 2;
2528 }
2529 else if (c1 < 0xF0)
2530 {
2531 if (frm_end-frm_nxt < 3)
2532 return codecvt_base::partial;
2533 uint8_t c2 = frm_nxt[1];
2534 uint8_t c3 = frm_nxt[2];
2535 switch (c1)
2536 {
2537 case 0xE0:
2538 if ((c2 & 0xE0) != 0xA0)
2539 return codecvt_base::error;
2540 break;
2541 case 0xED:
2542 if ((c2 & 0xE0) != 0x80)
2543 return codecvt_base::error;
2544 break;
2545 default:
2546 if ((c2 & 0xC0) != 0x80)
2547 return codecvt_base::error;
2548 break;
2549 }
2550 if ((c3 & 0xC0) != 0x80)
2551 return codecvt_base::error;
2552 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2553 | ((c2 & 0x3F) << 6)
2554 | (c3 & 0x3F));
2555 if (t > Maxcode)
2556 return codecvt_base::error;
2557 *to_nxt = t;
2558 frm_nxt += 3;
2559 }
2560 else
2561 {
2562 return codecvt_base::error;
2563 }
2564 }
2565 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2566}
2567
2568static
2569int
2570utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2571 size_t mx, unsigned long Maxcode = 0x10FFFF,
2572 codecvt_mode mode = codecvt_mode(0))
2573{
2574 const uint8_t* frm_nxt = frm;
2575 if (mode & consume_header)
2576 {
2577 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2578 frm_nxt[2] == 0xBF)
2579 frm_nxt += 3;
2580 }
2581 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2582 {
2583 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2584 if (c1 < 0x80)
2585 {
2586 if (c1 > Maxcode)
2587 break;
2588 ++frm_nxt;
2589 }
2590 else if (c1 < 0xC2)
2591 {
2592 break;
2593 }
2594 else if (c1 < 0xE0)
2595 {
2596 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2597 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002598 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002599 break;
2600 frm_nxt += 2;
2601 }
2602 else if (c1 < 0xF0)
2603 {
2604 if (frm_end-frm_nxt < 3)
2605 break;
2606 uint8_t c2 = frm_nxt[1];
2607 uint8_t c3 = frm_nxt[2];
2608 switch (c1)
2609 {
2610 case 0xE0:
2611 if ((c2 & 0xE0) != 0xA0)
2612 return static_cast<int>(frm_nxt - frm);
2613 break;
2614 case 0xED:
2615 if ((c2 & 0xE0) != 0x80)
2616 return static_cast<int>(frm_nxt - frm);
2617 break;
2618 default:
2619 if ((c2 & 0xC0) != 0x80)
2620 return static_cast<int>(frm_nxt - frm);
2621 break;
2622 }
2623 if ((c3 & 0xC0) != 0x80)
2624 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002625 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002626 break;
2627 frm_nxt += 3;
2628 }
2629 else
2630 {
2631 break;
2632 }
2633 }
2634 return static_cast<int>(frm_nxt - frm);
2635}
2636
2637static
2638codecvt_base::result
2639ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2640 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2641 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2642{
2643 frm_nxt = frm;
2644 to_nxt = to;
2645 if (mode & generate_header)
2646 {
2647 if (to_end-to_nxt < 2)
2648 return codecvt_base::partial;
2649 *to_nxt++ = static_cast<uint8_t>(0xFE);
2650 *to_nxt++ = static_cast<uint8_t>(0xFF);
2651 }
2652 for (; frm_nxt < frm_end; ++frm_nxt)
2653 {
2654 uint32_t wc = *frm_nxt;
2655 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2656 return codecvt_base::error;
2657 if (wc < 0x010000)
2658 {
2659 if (to_end-to_nxt < 2)
2660 return codecvt_base::partial;
2661 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2662 *to_nxt++ = static_cast<uint8_t>(wc);
2663 }
2664 else
2665 {
2666 if (to_end-to_nxt < 4)
2667 return codecvt_base::partial;
2668 uint16_t t = static_cast<uint16_t>(
2669 0xD800
2670 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2671 | ((wc & 0x00FC00) >> 10));
2672 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2673 *to_nxt++ = static_cast<uint8_t>(t);
2674 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2675 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2676 *to_nxt++ = static_cast<uint8_t>(t);
2677 }
2678 }
2679 return codecvt_base::ok;
2680}
2681
2682static
2683codecvt_base::result
2684utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2685 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2686 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2687{
2688 frm_nxt = frm;
2689 to_nxt = to;
2690 if (mode & consume_header)
2691 {
2692 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2693 frm_nxt += 2;
2694 }
2695 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2696 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002697 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002698 if ((c1 & 0xFC00) == 0xDC00)
2699 return codecvt_base::error;
2700 if ((c1 & 0xFC00) != 0xD800)
2701 {
2702 if (c1 > Maxcode)
2703 return codecvt_base::error;
2704 *to_nxt = static_cast<uint32_t>(c1);
2705 frm_nxt += 2;
2706 }
2707 else
2708 {
2709 if (frm_end-frm_nxt < 4)
2710 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002711 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002712 if ((c2 & 0xFC00) != 0xDC00)
2713 return codecvt_base::error;
2714 uint32_t t = static_cast<uint32_t>(
2715 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2716 | ((c1 & 0x003F) << 10)
2717 | (c2 & 0x03FF));
2718 if (t > Maxcode)
2719 return codecvt_base::error;
2720 *to_nxt = t;
2721 frm_nxt += 4;
2722 }
2723 }
2724 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2725}
2726
2727static
2728int
2729utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2730 size_t mx, unsigned long Maxcode = 0x10FFFF,
2731 codecvt_mode mode = codecvt_mode(0))
2732{
2733 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002734 if (mode & consume_header)
2735 {
2736 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2737 frm_nxt += 2;
2738 }
2739 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2740 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002741 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002742 if ((c1 & 0xFC00) == 0xDC00)
2743 break;
2744 if ((c1 & 0xFC00) != 0xD800)
2745 {
2746 if (c1 > Maxcode)
2747 break;
2748 frm_nxt += 2;
2749 }
2750 else
2751 {
2752 if (frm_end-frm_nxt < 4)
2753 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002754 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002755 if ((c2 & 0xFC00) != 0xDC00)
2756 break;
2757 uint32_t t = static_cast<uint32_t>(
2758 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2759 | ((c1 & 0x003F) << 10)
2760 | (c2 & 0x03FF));
2761 if (t > Maxcode)
2762 break;
2763 frm_nxt += 4;
2764 }
2765 }
2766 return static_cast<int>(frm_nxt - frm);
2767}
2768
2769static
2770codecvt_base::result
2771ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2772 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2773 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2774{
2775 frm_nxt = frm;
2776 to_nxt = to;
2777 if (mode & generate_header)
2778 {
2779 if (to_end-to_nxt < 2)
2780 return codecvt_base::partial;
2781 *to_nxt++ = static_cast<uint8_t>(0xFF);
2782 *to_nxt++ = static_cast<uint8_t>(0xFE);
2783 }
2784 for (; frm_nxt < frm_end; ++frm_nxt)
2785 {
2786 uint32_t wc = *frm_nxt;
2787 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2788 return codecvt_base::error;
2789 if (wc < 0x010000)
2790 {
2791 if (to_end-to_nxt < 2)
2792 return codecvt_base::partial;
2793 *to_nxt++ = static_cast<uint8_t>(wc);
2794 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2795 }
2796 else
2797 {
2798 if (to_end-to_nxt < 4)
2799 return codecvt_base::partial;
2800 uint16_t t = static_cast<uint16_t>(
2801 0xD800
2802 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2803 | ((wc & 0x00FC00) >> 10));
2804 *to_nxt++ = static_cast<uint8_t>(t);
2805 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2806 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2807 *to_nxt++ = static_cast<uint8_t>(t);
2808 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2809 }
2810 }
2811 return codecvt_base::ok;
2812}
2813
2814static
2815codecvt_base::result
2816utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2817 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2818 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2819{
2820 frm_nxt = frm;
2821 to_nxt = to;
2822 if (mode & consume_header)
2823 {
2824 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2825 frm_nxt += 2;
2826 }
2827 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2828 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002829 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002830 if ((c1 & 0xFC00) == 0xDC00)
2831 return codecvt_base::error;
2832 if ((c1 & 0xFC00) != 0xD800)
2833 {
2834 if (c1 > Maxcode)
2835 return codecvt_base::error;
2836 *to_nxt = static_cast<uint32_t>(c1);
2837 frm_nxt += 2;
2838 }
2839 else
2840 {
2841 if (frm_end-frm_nxt < 4)
2842 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002843 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002844 if ((c2 & 0xFC00) != 0xDC00)
2845 return codecvt_base::error;
2846 uint32_t t = static_cast<uint32_t>(
2847 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2848 | ((c1 & 0x003F) << 10)
2849 | (c2 & 0x03FF));
2850 if (t > Maxcode)
2851 return codecvt_base::error;
2852 *to_nxt = t;
2853 frm_nxt += 4;
2854 }
2855 }
2856 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2857}
2858
2859static
2860int
2861utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2862 size_t mx, unsigned long Maxcode = 0x10FFFF,
2863 codecvt_mode mode = codecvt_mode(0))
2864{
2865 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002866 if (mode & consume_header)
2867 {
2868 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2869 frm_nxt += 2;
2870 }
2871 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2872 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002873 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002874 if ((c1 & 0xFC00) == 0xDC00)
2875 break;
2876 if ((c1 & 0xFC00) != 0xD800)
2877 {
2878 if (c1 > Maxcode)
2879 break;
2880 frm_nxt += 2;
2881 }
2882 else
2883 {
2884 if (frm_end-frm_nxt < 4)
2885 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002886 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002887 if ((c2 & 0xFC00) != 0xDC00)
2888 break;
2889 uint32_t t = static_cast<uint32_t>(
2890 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2891 | ((c1 & 0x003F) << 10)
2892 | (c2 & 0x03FF));
2893 if (t > Maxcode)
2894 break;
2895 frm_nxt += 4;
2896 }
2897 }
2898 return static_cast<int>(frm_nxt - frm);
2899}
2900
2901static
2902codecvt_base::result
2903ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2904 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2905 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2906{
2907 frm_nxt = frm;
2908 to_nxt = to;
2909 if (mode & generate_header)
2910 {
2911 if (to_end-to_nxt < 2)
2912 return codecvt_base::partial;
2913 *to_nxt++ = static_cast<uint8_t>(0xFE);
2914 *to_nxt++ = static_cast<uint8_t>(0xFF);
2915 }
2916 for (; frm_nxt < frm_end; ++frm_nxt)
2917 {
2918 uint16_t wc = *frm_nxt;
2919 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2920 return codecvt_base::error;
2921 if (to_end-to_nxt < 2)
2922 return codecvt_base::partial;
2923 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2924 *to_nxt++ = static_cast<uint8_t>(wc);
2925 }
2926 return codecvt_base::ok;
2927}
2928
2929static
2930codecvt_base::result
2931utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2932 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2933 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2934{
2935 frm_nxt = frm;
2936 to_nxt = to;
2937 if (mode & consume_header)
2938 {
2939 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2940 frm_nxt += 2;
2941 }
2942 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2943 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002944 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002945 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2946 return codecvt_base::error;
2947 *to_nxt = c1;
2948 frm_nxt += 2;
2949 }
2950 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2951}
2952
2953static
2954int
2955utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2956 size_t mx, unsigned long Maxcode = 0x10FFFF,
2957 codecvt_mode mode = codecvt_mode(0))
2958{
2959 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002960 if (mode & consume_header)
2961 {
2962 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2963 frm_nxt += 2;
2964 }
2965 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2966 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002967 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002968 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2969 break;
2970 frm_nxt += 2;
2971 }
2972 return static_cast<int>(frm_nxt - frm);
2973}
2974
2975static
2976codecvt_base::result
2977ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2978 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2979 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2980{
2981 frm_nxt = frm;
2982 to_nxt = to;
2983 if (mode & generate_header)
2984 {
2985 if (to_end-to_nxt < 2)
2986 return codecvt_base::partial;
2987 *to_nxt++ = static_cast<uint8_t>(0xFF);
2988 *to_nxt++ = static_cast<uint8_t>(0xFE);
2989 }
2990 for (; frm_nxt < frm_end; ++frm_nxt)
2991 {
2992 uint16_t wc = *frm_nxt;
2993 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2994 return codecvt_base::error;
2995 if (to_end-to_nxt < 2)
2996 return codecvt_base::partial;
2997 *to_nxt++ = static_cast<uint8_t>(wc);
2998 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2999 }
3000 return codecvt_base::ok;
3001}
3002
3003static
3004codecvt_base::result
3005utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3006 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3007 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3008{
3009 frm_nxt = frm;
3010 to_nxt = to;
3011 if (mode & consume_header)
3012 {
3013 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3014 frm_nxt += 2;
3015 }
3016 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3017 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003018 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003019 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3020 return codecvt_base::error;
3021 *to_nxt = c1;
3022 frm_nxt += 2;
3023 }
3024 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3025}
3026
3027static
3028int
3029utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3030 size_t mx, unsigned long Maxcode = 0x10FFFF,
3031 codecvt_mode mode = codecvt_mode(0))
3032{
3033 const uint8_t* frm_nxt = frm;
3034 frm_nxt = frm;
3035 if (mode & consume_header)
3036 {
3037 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3038 frm_nxt += 2;
3039 }
3040 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3041 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003042 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003043 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3044 break;
3045 frm_nxt += 2;
3046 }
3047 return static_cast<int>(frm_nxt - frm);
3048}
3049
Howard Hinnantc51e1022010-05-11 19:42:16 +00003050// template <> class codecvt<char16_t, char, mbstate_t>
3051
Howard Hinnantffb308e2010-08-22 00:03:27 +00003052locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003053
3054codecvt<char16_t, char, mbstate_t>::~codecvt()
3055{
3056}
3057
3058codecvt<char16_t, char, mbstate_t>::result
3059codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003060 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003061 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3062{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003063 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3064 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3065 const uint16_t* _frm_nxt = _frm;
3066 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3067 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3068 uint8_t* _to_nxt = _to;
3069 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3070 frm_nxt = frm + (_frm_nxt - _frm);
3071 to_nxt = to + (_to_nxt - _to);
3072 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003073}
3074
3075codecvt<char16_t, char, mbstate_t>::result
3076codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003077 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003078 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3079{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003080 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3081 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3082 const uint8_t* _frm_nxt = _frm;
3083 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3084 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3085 uint16_t* _to_nxt = _to;
3086 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3087 frm_nxt = frm + (_frm_nxt - _frm);
3088 to_nxt = to + (_to_nxt - _to);
3089 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003090}
3091
3092codecvt<char16_t, char, mbstate_t>::result
3093codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3094 extern_type* to, extern_type*, extern_type*& to_nxt) const
3095{
3096 to_nxt = to;
3097 return noconv;
3098}
3099
3100int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003101codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003102{
3103 return 0;
3104}
3105
3106bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003107codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003108{
3109 return false;
3110}
3111
3112int
3113codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3114 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3115{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003116 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3117 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3118 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003119}
3120
3121int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003122codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003123{
3124 return 4;
3125}
3126
3127// template <> class codecvt<char32_t, char, mbstate_t>
3128
Howard Hinnantffb308e2010-08-22 00:03:27 +00003129locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003130
3131codecvt<char32_t, char, mbstate_t>::~codecvt()
3132{
3133}
3134
3135codecvt<char32_t, char, mbstate_t>::result
3136codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003137 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003138 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3139{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003140 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3141 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3142 const uint32_t* _frm_nxt = _frm;
3143 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3144 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3145 uint8_t* _to_nxt = _to;
3146 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3147 frm_nxt = frm + (_frm_nxt - _frm);
3148 to_nxt = to + (_to_nxt - _to);
3149 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003150}
3151
3152codecvt<char32_t, char, mbstate_t>::result
3153codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003154 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003155 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3156{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003157 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3158 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3159 const uint8_t* _frm_nxt = _frm;
3160 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3161 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3162 uint32_t* _to_nxt = _to;
3163 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3164 frm_nxt = frm + (_frm_nxt - _frm);
3165 to_nxt = to + (_to_nxt - _to);
3166 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003167}
3168
3169codecvt<char32_t, char, mbstate_t>::result
3170codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3171 extern_type* to, extern_type*, extern_type*& to_nxt) const
3172{
3173 to_nxt = to;
3174 return noconv;
3175}
3176
3177int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003178codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003179{
3180 return 0;
3181}
3182
3183bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003184codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003185{
3186 return false;
3187}
3188
3189int
3190codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3191 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3192{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003193 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3194 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3195 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003196}
3197
3198int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003199codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003200{
3201 return 4;
3202}
3203
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003204// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003205
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003206__codecvt_utf8<wchar_t>::result
3207__codecvt_utf8<wchar_t>::do_out(state_type&,
3208 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003209 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3210{
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003211#if _WIN32
3212 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3213 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3214 const uint16_t* _frm_nxt = _frm;
3215#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003216 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3217 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3218 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003219#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003220 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3221 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3222 uint8_t* _to_nxt = _to;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003223#if _WIN32
3224 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3225 _Maxcode_, _Mode_);
3226#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003227 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3228 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003229#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003230 frm_nxt = frm + (_frm_nxt - _frm);
3231 to_nxt = to + (_to_nxt - _to);
3232 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003233}
3234
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003235__codecvt_utf8<wchar_t>::result
3236__codecvt_utf8<wchar_t>::do_in(state_type&,
3237 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003238 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3239{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003240 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3241 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3242 const uint8_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003243#if _WIN32
3244 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3245 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3246 uint16_t* _to_nxt = _to;
3247 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3248 _Maxcode_, _Mode_);
3249#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003250 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3251 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3252 uint32_t* _to_nxt = _to;
3253 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3254 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003255#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003256 frm_nxt = frm + (_frm_nxt - _frm);
3257 to_nxt = to + (_to_nxt - _to);
3258 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003259}
3260
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003261__codecvt_utf8<wchar_t>::result
3262__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003263 extern_type* to, extern_type*, extern_type*& to_nxt) const
3264{
3265 to_nxt = to;
3266 return noconv;
3267}
3268
3269int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003270__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003271{
3272 return 0;
3273}
3274
3275bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003276__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003277{
3278 return false;
3279}
3280
3281int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003282__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003283 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3284{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003285 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3286 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3287 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003288}
3289
3290int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003291__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003292{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003293 if (_Mode_ & consume_header)
3294 return 7;
3295 return 4;
3296}
3297
3298// __codecvt_utf8<char16_t>
3299
3300__codecvt_utf8<char16_t>::result
3301__codecvt_utf8<char16_t>::do_out(state_type&,
3302 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3303 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3304{
3305 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3306 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3307 const uint16_t* _frm_nxt = _frm;
3308 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3309 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3310 uint8_t* _to_nxt = _to;
3311 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3312 _Maxcode_, _Mode_);
3313 frm_nxt = frm + (_frm_nxt - _frm);
3314 to_nxt = to + (_to_nxt - _to);
3315 return r;
3316}
3317
3318__codecvt_utf8<char16_t>::result
3319__codecvt_utf8<char16_t>::do_in(state_type&,
3320 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3321 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3322{
3323 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3324 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3325 const uint8_t* _frm_nxt = _frm;
3326 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3327 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3328 uint16_t* _to_nxt = _to;
3329 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3330 _Maxcode_, _Mode_);
3331 frm_nxt = frm + (_frm_nxt - _frm);
3332 to_nxt = to + (_to_nxt - _to);
3333 return r;
3334}
3335
3336__codecvt_utf8<char16_t>::result
3337__codecvt_utf8<char16_t>::do_unshift(state_type&,
3338 extern_type* to, extern_type*, extern_type*& to_nxt) const
3339{
3340 to_nxt = to;
3341 return noconv;
3342}
3343
3344int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003345__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003346{
3347 return 0;
3348}
3349
3350bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003351__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003352{
3353 return false;
3354}
3355
3356int
3357__codecvt_utf8<char16_t>::do_length(state_type&,
3358 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3359{
3360 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3361 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3362 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3363}
3364
3365int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003366__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003367{
3368 if (_Mode_ & consume_header)
3369 return 6;
3370 return 3;
3371}
3372
3373// __codecvt_utf8<char32_t>
3374
3375__codecvt_utf8<char32_t>::result
3376__codecvt_utf8<char32_t>::do_out(state_type&,
3377 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3378 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3379{
3380 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3381 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3382 const uint32_t* _frm_nxt = _frm;
3383 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3384 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3385 uint8_t* _to_nxt = _to;
3386 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3387 _Maxcode_, _Mode_);
3388 frm_nxt = frm + (_frm_nxt - _frm);
3389 to_nxt = to + (_to_nxt - _to);
3390 return r;
3391}
3392
3393__codecvt_utf8<char32_t>::result
3394__codecvt_utf8<char32_t>::do_in(state_type&,
3395 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3396 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3397{
3398 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3399 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3400 const uint8_t* _frm_nxt = _frm;
3401 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3402 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3403 uint32_t* _to_nxt = _to;
3404 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3405 _Maxcode_, _Mode_);
3406 frm_nxt = frm + (_frm_nxt - _frm);
3407 to_nxt = to + (_to_nxt - _to);
3408 return r;
3409}
3410
3411__codecvt_utf8<char32_t>::result
3412__codecvt_utf8<char32_t>::do_unshift(state_type&,
3413 extern_type* to, extern_type*, extern_type*& to_nxt) const
3414{
3415 to_nxt = to;
3416 return noconv;
3417}
3418
3419int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003420__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003421{
3422 return 0;
3423}
3424
3425bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003426__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003427{
3428 return false;
3429}
3430
3431int
3432__codecvt_utf8<char32_t>::do_length(state_type&,
3433 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3434{
3435 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3436 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3437 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3438}
3439
3440int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003441__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003442{
3443 if (_Mode_ & consume_header)
3444 return 7;
3445 return 4;
3446}
3447
3448// __codecvt_utf16<wchar_t, false>
3449
3450__codecvt_utf16<wchar_t, false>::result
3451__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3452 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3453 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3454{
3455 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3456 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3457 const uint32_t* _frm_nxt = _frm;
3458 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3459 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3460 uint8_t* _to_nxt = _to;
3461 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3462 _Maxcode_, _Mode_);
3463 frm_nxt = frm + (_frm_nxt - _frm);
3464 to_nxt = to + (_to_nxt - _to);
3465 return r;
3466}
3467
3468__codecvt_utf16<wchar_t, false>::result
3469__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3470 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3471 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3472{
3473 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3474 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3475 const uint8_t* _frm_nxt = _frm;
3476 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3477 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3478 uint32_t* _to_nxt = _to;
3479 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3480 _Maxcode_, _Mode_);
3481 frm_nxt = frm + (_frm_nxt - _frm);
3482 to_nxt = to + (_to_nxt - _to);
3483 return r;
3484}
3485
3486__codecvt_utf16<wchar_t, false>::result
3487__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3488 extern_type* to, extern_type*, extern_type*& to_nxt) const
3489{
3490 to_nxt = to;
3491 return noconv;
3492}
3493
3494int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003495__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003496{
3497 return 0;
3498}
3499
3500bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003501__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003502{
3503 return false;
3504}
3505
3506int
3507__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3508 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3509{
3510 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3511 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3512 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3513}
3514
3515int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003516__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003517{
3518 if (_Mode_ & consume_header)
3519 return 6;
3520 return 4;
3521}
3522
3523// __codecvt_utf16<wchar_t, true>
3524
3525__codecvt_utf16<wchar_t, true>::result
3526__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3527 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3528 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3529{
3530 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3531 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3532 const uint32_t* _frm_nxt = _frm;
3533 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3534 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3535 uint8_t* _to_nxt = _to;
3536 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3537 _Maxcode_, _Mode_);
3538 frm_nxt = frm + (_frm_nxt - _frm);
3539 to_nxt = to + (_to_nxt - _to);
3540 return r;
3541}
3542
3543__codecvt_utf16<wchar_t, true>::result
3544__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3545 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3546 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3547{
3548 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3549 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3550 const uint8_t* _frm_nxt = _frm;
3551 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3552 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3553 uint32_t* _to_nxt = _to;
3554 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3555 _Maxcode_, _Mode_);
3556 frm_nxt = frm + (_frm_nxt - _frm);
3557 to_nxt = to + (_to_nxt - _to);
3558 return r;
3559}
3560
3561__codecvt_utf16<wchar_t, true>::result
3562__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3563 extern_type* to, extern_type*, extern_type*& to_nxt) const
3564{
3565 to_nxt = to;
3566 return noconv;
3567}
3568
3569int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003570__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003571{
3572 return 0;
3573}
3574
3575bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003576__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003577{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003578 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003579}
3580
3581int
3582__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3583 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3584{
3585 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3586 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3587 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3588}
3589
3590int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003591__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003592{
3593 if (_Mode_ & consume_header)
3594 return 6;
3595 return 4;
3596}
3597
3598// __codecvt_utf16<char16_t, false>
3599
3600__codecvt_utf16<char16_t, false>::result
3601__codecvt_utf16<char16_t, false>::do_out(state_type&,
3602 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3603 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3604{
3605 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3606 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3607 const uint16_t* _frm_nxt = _frm;
3608 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3609 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3610 uint8_t* _to_nxt = _to;
3611 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3612 _Maxcode_, _Mode_);
3613 frm_nxt = frm + (_frm_nxt - _frm);
3614 to_nxt = to + (_to_nxt - _to);
3615 return r;
3616}
3617
3618__codecvt_utf16<char16_t, false>::result
3619__codecvt_utf16<char16_t, false>::do_in(state_type&,
3620 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3621 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3622{
3623 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3624 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3625 const uint8_t* _frm_nxt = _frm;
3626 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3627 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3628 uint16_t* _to_nxt = _to;
3629 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3630 _Maxcode_, _Mode_);
3631 frm_nxt = frm + (_frm_nxt - _frm);
3632 to_nxt = to + (_to_nxt - _to);
3633 return r;
3634}
3635
3636__codecvt_utf16<char16_t, false>::result
3637__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3638 extern_type* to, extern_type*, extern_type*& to_nxt) const
3639{
3640 to_nxt = to;
3641 return noconv;
3642}
3643
3644int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003645__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003646{
3647 return 0;
3648}
3649
3650bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003651__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003652{
3653 return false;
3654}
3655
3656int
3657__codecvt_utf16<char16_t, false>::do_length(state_type&,
3658 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3659{
3660 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3661 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3662 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3663}
3664
3665int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003666__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003667{
3668 if (_Mode_ & consume_header)
3669 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003670 return 2;
3671}
3672
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003673// __codecvt_utf16<char16_t, true>
3674
3675__codecvt_utf16<char16_t, true>::result
3676__codecvt_utf16<char16_t, true>::do_out(state_type&,
3677 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3678 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3679{
3680 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3681 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3682 const uint16_t* _frm_nxt = _frm;
3683 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3684 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3685 uint8_t* _to_nxt = _to;
3686 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3687 _Maxcode_, _Mode_);
3688 frm_nxt = frm + (_frm_nxt - _frm);
3689 to_nxt = to + (_to_nxt - _to);
3690 return r;
3691}
3692
3693__codecvt_utf16<char16_t, true>::result
3694__codecvt_utf16<char16_t, true>::do_in(state_type&,
3695 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3696 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3697{
3698 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3699 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3700 const uint8_t* _frm_nxt = _frm;
3701 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3702 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3703 uint16_t* _to_nxt = _to;
3704 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3705 _Maxcode_, _Mode_);
3706 frm_nxt = frm + (_frm_nxt - _frm);
3707 to_nxt = to + (_to_nxt - _to);
3708 return r;
3709}
3710
3711__codecvt_utf16<char16_t, true>::result
3712__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3713 extern_type* to, extern_type*, extern_type*& to_nxt) const
3714{
3715 to_nxt = to;
3716 return noconv;
3717}
3718
3719int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003720__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003721{
3722 return 0;
3723}
3724
3725bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003726__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003727{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003728 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003729}
3730
3731int
3732__codecvt_utf16<char16_t, true>::do_length(state_type&,
3733 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3734{
3735 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3736 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3737 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3738}
3739
3740int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003741__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003742{
3743 if (_Mode_ & consume_header)
3744 return 4;
3745 return 2;
3746}
3747
3748// __codecvt_utf16<char32_t, false>
3749
3750__codecvt_utf16<char32_t, false>::result
3751__codecvt_utf16<char32_t, false>::do_out(state_type&,
3752 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3753 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3754{
3755 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3756 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3757 const uint32_t* _frm_nxt = _frm;
3758 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3759 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3760 uint8_t* _to_nxt = _to;
3761 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3762 _Maxcode_, _Mode_);
3763 frm_nxt = frm + (_frm_nxt - _frm);
3764 to_nxt = to + (_to_nxt - _to);
3765 return r;
3766}
3767
3768__codecvt_utf16<char32_t, false>::result
3769__codecvt_utf16<char32_t, false>::do_in(state_type&,
3770 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3771 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3772{
3773 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3774 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3775 const uint8_t* _frm_nxt = _frm;
3776 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3777 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3778 uint32_t* _to_nxt = _to;
3779 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3780 _Maxcode_, _Mode_);
3781 frm_nxt = frm + (_frm_nxt - _frm);
3782 to_nxt = to + (_to_nxt - _to);
3783 return r;
3784}
3785
3786__codecvt_utf16<char32_t, false>::result
3787__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3788 extern_type* to, extern_type*, extern_type*& to_nxt) const
3789{
3790 to_nxt = to;
3791 return noconv;
3792}
3793
3794int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003795__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003796{
3797 return 0;
3798}
3799
3800bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003801__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003802{
3803 return false;
3804}
3805
3806int
3807__codecvt_utf16<char32_t, false>::do_length(state_type&,
3808 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3809{
3810 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3811 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3812 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3813}
3814
3815int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003816__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003817{
3818 if (_Mode_ & consume_header)
3819 return 6;
3820 return 4;
3821}
3822
3823// __codecvt_utf16<char32_t, true>
3824
3825__codecvt_utf16<char32_t, true>::result
3826__codecvt_utf16<char32_t, true>::do_out(state_type&,
3827 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3828 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3829{
3830 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3831 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3832 const uint32_t* _frm_nxt = _frm;
3833 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3834 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3835 uint8_t* _to_nxt = _to;
3836 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3837 _Maxcode_, _Mode_);
3838 frm_nxt = frm + (_frm_nxt - _frm);
3839 to_nxt = to + (_to_nxt - _to);
3840 return r;
3841}
3842
3843__codecvt_utf16<char32_t, true>::result
3844__codecvt_utf16<char32_t, true>::do_in(state_type&,
3845 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3846 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3847{
3848 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3849 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3850 const uint8_t* _frm_nxt = _frm;
3851 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3852 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3853 uint32_t* _to_nxt = _to;
3854 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3855 _Maxcode_, _Mode_);
3856 frm_nxt = frm + (_frm_nxt - _frm);
3857 to_nxt = to + (_to_nxt - _to);
3858 return r;
3859}
3860
3861__codecvt_utf16<char32_t, true>::result
3862__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3863 extern_type* to, extern_type*, extern_type*& to_nxt) const
3864{
3865 to_nxt = to;
3866 return noconv;
3867}
3868
3869int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003870__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003871{
3872 return 0;
3873}
3874
3875bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003876__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003877{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003878 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003879}
3880
3881int
3882__codecvt_utf16<char32_t, true>::do_length(state_type&,
3883 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3884{
3885 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3886 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3887 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3888}
3889
3890int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003891__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003892{
3893 if (_Mode_ & consume_header)
3894 return 6;
3895 return 4;
3896}
3897
3898// __codecvt_utf8_utf16<wchar_t>
3899
3900__codecvt_utf8_utf16<wchar_t>::result
3901__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3902 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3903 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3904{
3905 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3906 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3907 const uint32_t* _frm_nxt = _frm;
3908 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3909 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3910 uint8_t* _to_nxt = _to;
3911 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3912 _Maxcode_, _Mode_);
3913 frm_nxt = frm + (_frm_nxt - _frm);
3914 to_nxt = to + (_to_nxt - _to);
3915 return r;
3916}
3917
3918__codecvt_utf8_utf16<wchar_t>::result
3919__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3920 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3921 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3922{
3923 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3924 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3925 const uint8_t* _frm_nxt = _frm;
3926 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3927 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3928 uint32_t* _to_nxt = _to;
3929 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3930 _Maxcode_, _Mode_);
3931 frm_nxt = frm + (_frm_nxt - _frm);
3932 to_nxt = to + (_to_nxt - _to);
3933 return r;
3934}
3935
3936__codecvt_utf8_utf16<wchar_t>::result
3937__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3938 extern_type* to, extern_type*, extern_type*& to_nxt) const
3939{
3940 to_nxt = to;
3941 return noconv;
3942}
3943
3944int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003945__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003946{
3947 return 0;
3948}
3949
3950bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003951__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003952{
3953 return false;
3954}
3955
3956int
3957__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3958 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3959{
3960 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3961 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3962 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3963}
3964
3965int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003966__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003967{
3968 if (_Mode_ & consume_header)
3969 return 7;
3970 return 4;
3971}
3972
3973// __codecvt_utf8_utf16<char16_t>
3974
3975__codecvt_utf8_utf16<char16_t>::result
3976__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3977 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3978 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3979{
3980 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3981 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3982 const uint16_t* _frm_nxt = _frm;
3983 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3984 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3985 uint8_t* _to_nxt = _to;
3986 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3987 _Maxcode_, _Mode_);
3988 frm_nxt = frm + (_frm_nxt - _frm);
3989 to_nxt = to + (_to_nxt - _to);
3990 return r;
3991}
3992
3993__codecvt_utf8_utf16<char16_t>::result
3994__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3995 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3996 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3997{
3998 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3999 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4000 const uint8_t* _frm_nxt = _frm;
4001 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4002 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4003 uint16_t* _to_nxt = _to;
4004 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4005 _Maxcode_, _Mode_);
4006 frm_nxt = frm + (_frm_nxt - _frm);
4007 to_nxt = to + (_to_nxt - _to);
4008 return r;
4009}
4010
4011__codecvt_utf8_utf16<char16_t>::result
4012__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4013 extern_type* to, extern_type*, extern_type*& to_nxt) const
4014{
4015 to_nxt = to;
4016 return noconv;
4017}
4018
4019int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004020__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004021{
4022 return 0;
4023}
4024
4025bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004026__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004027{
4028 return false;
4029}
4030
4031int
4032__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4033 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4034{
4035 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4036 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4037 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4038}
4039
4040int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004041__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004042{
4043 if (_Mode_ & consume_header)
4044 return 7;
4045 return 4;
4046}
4047
4048// __codecvt_utf8_utf16<char32_t>
4049
4050__codecvt_utf8_utf16<char32_t>::result
4051__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4052 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4053 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4054{
4055 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4056 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4057 const uint32_t* _frm_nxt = _frm;
4058 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4059 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4060 uint8_t* _to_nxt = _to;
4061 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4062 _Maxcode_, _Mode_);
4063 frm_nxt = frm + (_frm_nxt - _frm);
4064 to_nxt = to + (_to_nxt - _to);
4065 return r;
4066}
4067
4068__codecvt_utf8_utf16<char32_t>::result
4069__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4070 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4071 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4072{
4073 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4074 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4075 const uint8_t* _frm_nxt = _frm;
4076 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4077 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4078 uint32_t* _to_nxt = _to;
4079 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4080 _Maxcode_, _Mode_);
4081 frm_nxt = frm + (_frm_nxt - _frm);
4082 to_nxt = to + (_to_nxt - _to);
4083 return r;
4084}
4085
4086__codecvt_utf8_utf16<char32_t>::result
4087__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4088 extern_type* to, extern_type*, extern_type*& to_nxt) const
4089{
4090 to_nxt = to;
4091 return noconv;
4092}
4093
4094int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004095__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004096{
4097 return 0;
4098}
4099
4100bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004101__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004102{
4103 return false;
4104}
4105
4106int
4107__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4108 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4109{
4110 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4111 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4112 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4113}
4114
4115int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004116__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004117{
4118 if (_Mode_ & consume_header)
4119 return 7;
4120 return 4;
4121}
4122
Howard Hinnantc51e1022010-05-11 19:42:16 +00004123// __narrow_to_utf8<16>
4124
4125__narrow_to_utf8<16>::~__narrow_to_utf8()
4126{
4127}
4128
4129// __narrow_to_utf8<32>
4130
4131__narrow_to_utf8<32>::~__narrow_to_utf8()
4132{
4133}
4134
4135// __widen_from_utf8<16>
4136
4137__widen_from_utf8<16>::~__widen_from_utf8()
4138{
4139}
4140
4141// __widen_from_utf8<32>
4142
4143__widen_from_utf8<32>::~__widen_from_utf8()
4144{
4145}
4146
4147// numpunct<char> && numpunct<wchar_t>
4148
4149locale::id numpunct< char >::id;
4150locale::id numpunct<wchar_t>::id;
4151
4152numpunct<char>::numpunct(size_t refs)
4153 : locale::facet(refs),
4154 __decimal_point_('.'),
4155 __thousands_sep_(',')
4156{
4157}
4158
4159numpunct<wchar_t>::numpunct(size_t refs)
4160 : locale::facet(refs),
4161 __decimal_point_(L'.'),
4162 __thousands_sep_(L',')
4163{
4164}
4165
4166numpunct<char>::~numpunct()
4167{
4168}
4169
4170numpunct<wchar_t>::~numpunct()
4171{
4172}
4173
4174 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4175wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4176
4177 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4178wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4179
4180string numpunct< char >::do_grouping() const {return __grouping_;}
4181string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4182
4183 string numpunct< char >::do_truename() const {return "true";}
4184wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4185
4186 string numpunct< char >::do_falsename() const {return "false";}
4187wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4188
4189// numpunct_byname<char>
4190
4191numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4192 : numpunct<char>(refs)
4193{
4194 __init(nm);
4195}
4196
4197numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4198 : numpunct<char>(refs)
4199{
4200 __init(nm.c_str());
4201}
4202
4203numpunct_byname<char>::~numpunct_byname()
4204{
4205}
4206
4207void
4208numpunct_byname<char>::__init(const char* nm)
4209{
4210 if (strcmp(nm, "C") != 0)
4211 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004212 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004213#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004214 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004215 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4216 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004217#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004218#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004219 lconv* lc = localeconv_l(loc.get());
4220#else
4221 lconv* lc = __localeconv_l(loc.get());
4222#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004223 if (*lc->decimal_point)
4224 __decimal_point_ = *lc->decimal_point;
4225 if (*lc->thousands_sep)
4226 __thousands_sep_ = *lc->thousands_sep;
4227 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004228 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004229 }
4230}
4231
4232// numpunct_byname<wchar_t>
4233
4234numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4235 : numpunct<wchar_t>(refs)
4236{
4237 __init(nm);
4238}
4239
4240numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4241 : numpunct<wchar_t>(refs)
4242{
4243 __init(nm.c_str());
4244}
4245
4246numpunct_byname<wchar_t>::~numpunct_byname()
4247{
4248}
4249
4250void
4251numpunct_byname<wchar_t>::__init(const char* nm)
4252{
4253 if (strcmp(nm, "C") != 0)
4254 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004255 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004256#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004257 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004258 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4259 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004260#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004261#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004262 lconv* lc = localeconv_l(loc.get());
4263#else
4264 lconv* lc = __localeconv_l(loc.get());
4265#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004266 if (*lc->decimal_point)
4267 __decimal_point_ = *lc->decimal_point;
4268 if (*lc->thousands_sep)
4269 __thousands_sep_ = *lc->thousands_sep;
4270 __grouping_ = lc->grouping;
4271 // locallization for truename and falsename is not available
4272 }
4273}
4274
4275// num_get helpers
4276
4277int
4278__num_get_base::__get_base(ios_base& iob)
4279{
4280 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4281 if (__basefield == ios_base::oct)
4282 return 8;
4283 else if (__basefield == ios_base::hex)
4284 return 16;
4285 else if (__basefield == 0)
4286 return 0;
4287 return 10;
4288}
4289
4290const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4291
4292void
4293__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4294 ios_base::iostate& __err)
4295{
4296 if (__grouping.size() != 0)
4297 {
4298 reverse(__g, __g_end);
4299 const char* __ig = __grouping.data();
4300 const char* __eg = __ig + __grouping.size();
4301 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4302 {
4303 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4304 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004305 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004306 {
4307 __err = ios_base::failbit;
4308 return;
4309 }
4310 }
4311 if (__eg - __ig > 1)
4312 ++__ig;
4313 }
4314 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4315 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004316 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004317 __err = ios_base::failbit;
4318 }
4319 }
4320}
4321
4322void
4323__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4324 ios_base::fmtflags __flags)
4325{
4326 if (__flags & ios_base::showpos)
4327 *__fmtp++ = '+';
4328 if (__flags & ios_base::showbase)
4329 *__fmtp++ = '#';
4330 while(*__len)
4331 *__fmtp++ = *__len++;
4332 if ((__flags & ios_base::basefield) == ios_base::oct)
4333 *__fmtp = 'o';
4334 else if ((__flags & ios_base::basefield) == ios_base::hex)
4335 {
4336 if (__flags & ios_base::uppercase)
4337 *__fmtp = 'X';
4338 else
4339 *__fmtp = 'x';
4340 }
4341 else if (__signd)
4342 *__fmtp = 'd';
4343 else
4344 *__fmtp = 'u';
4345}
4346
4347bool
4348__num_put_base::__format_float(char* __fmtp, const char* __len,
4349 ios_base::fmtflags __flags)
4350{
4351 bool specify_precision = true;
4352 if (__flags & ios_base::showpos)
4353 *__fmtp++ = '+';
4354 if (__flags & ios_base::showpoint)
4355 *__fmtp++ = '#';
4356 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4357 bool uppercase = __flags & ios_base::uppercase;
4358 if (floatfield == (ios_base::fixed | ios_base::scientific))
4359 specify_precision = false;
4360 else
4361 {
4362 *__fmtp++ = '.';
4363 *__fmtp++ = '*';
4364 }
4365 while(*__len)
4366 *__fmtp++ = *__len++;
4367 if (floatfield == ios_base::fixed)
4368 {
4369 if (uppercase)
4370 *__fmtp = 'F';
4371 else
4372 *__fmtp = 'f';
4373 }
4374 else if (floatfield == ios_base::scientific)
4375 {
4376 if (uppercase)
4377 *__fmtp = 'E';
4378 else
4379 *__fmtp = 'e';
4380 }
4381 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4382 {
4383 if (uppercase)
4384 *__fmtp = 'A';
4385 else
4386 *__fmtp = 'a';
4387 }
4388 else
4389 {
4390 if (uppercase)
4391 *__fmtp = 'G';
4392 else
4393 *__fmtp = 'g';
4394 }
4395 return specify_precision;
4396}
4397
4398char*
4399__num_put_base::__identify_padding(char* __nb, char* __ne,
4400 const ios_base& __iob)
4401{
4402 switch (__iob.flags() & ios_base::adjustfield)
4403 {
4404 case ios_base::internal:
4405 if (__nb[0] == '-' || __nb[0] == '+')
4406 return __nb+1;
4407 if (__ne - __nb >= 2 && __nb[0] == '0'
4408 && (__nb[1] == 'x' || __nb[1] == 'X'))
4409 return __nb+2;
4410 break;
4411 case ios_base::left:
4412 return __ne;
4413 case ios_base::right:
4414 default:
4415 break;
4416 }
4417 return __nb;
4418}
4419
4420// time_get
4421
4422static
4423string*
4424init_weeks()
4425{
4426 static string weeks[14];
4427 weeks[0] = "Sunday";
4428 weeks[1] = "Monday";
4429 weeks[2] = "Tuesday";
4430 weeks[3] = "Wednesday";
4431 weeks[4] = "Thursday";
4432 weeks[5] = "Friday";
4433 weeks[6] = "Saturday";
4434 weeks[7] = "Sun";
4435 weeks[8] = "Mon";
4436 weeks[9] = "Tue";
4437 weeks[10] = "Wed";
4438 weeks[11] = "Thu";
4439 weeks[12] = "Fri";
4440 weeks[13] = "Sat";
4441 return weeks;
4442}
4443
4444static
4445wstring*
4446init_wweeks()
4447{
4448 static wstring weeks[14];
4449 weeks[0] = L"Sunday";
4450 weeks[1] = L"Monday";
4451 weeks[2] = L"Tuesday";
4452 weeks[3] = L"Wednesday";
4453 weeks[4] = L"Thursday";
4454 weeks[5] = L"Friday";
4455 weeks[6] = L"Saturday";
4456 weeks[7] = L"Sun";
4457 weeks[8] = L"Mon";
4458 weeks[9] = L"Tue";
4459 weeks[10] = L"Wed";
4460 weeks[11] = L"Thu";
4461 weeks[12] = L"Fri";
4462 weeks[13] = L"Sat";
4463 return weeks;
4464}
4465
4466template <>
4467const string*
4468__time_get_c_storage<char>::__weeks() const
4469{
4470 static const string* weeks = init_weeks();
4471 return weeks;
4472}
4473
4474template <>
4475const wstring*
4476__time_get_c_storage<wchar_t>::__weeks() const
4477{
4478 static const wstring* weeks = init_wweeks();
4479 return weeks;
4480}
4481
4482static
4483string*
4484init_months()
4485{
4486 static string months[24];
4487 months[0] = "January";
4488 months[1] = "February";
4489 months[2] = "March";
4490 months[3] = "April";
4491 months[4] = "May";
4492 months[5] = "June";
4493 months[6] = "July";
4494 months[7] = "August";
4495 months[8] = "September";
4496 months[9] = "October";
4497 months[10] = "November";
4498 months[11] = "December";
4499 months[12] = "Jan";
4500 months[13] = "Feb";
4501 months[14] = "Mar";
4502 months[15] = "Apr";
4503 months[16] = "May";
4504 months[17] = "Jun";
4505 months[18] = "Jul";
4506 months[19] = "Aug";
4507 months[20] = "Sep";
4508 months[21] = "Oct";
4509 months[22] = "Nov";
4510 months[23] = "Dec";
4511 return months;
4512}
4513
4514static
4515wstring*
4516init_wmonths()
4517{
4518 static wstring months[24];
4519 months[0] = L"January";
4520 months[1] = L"February";
4521 months[2] = L"March";
4522 months[3] = L"April";
4523 months[4] = L"May";
4524 months[5] = L"June";
4525 months[6] = L"July";
4526 months[7] = L"August";
4527 months[8] = L"September";
4528 months[9] = L"October";
4529 months[10] = L"November";
4530 months[11] = L"December";
4531 months[12] = L"Jan";
4532 months[13] = L"Feb";
4533 months[14] = L"Mar";
4534 months[15] = L"Apr";
4535 months[16] = L"May";
4536 months[17] = L"Jun";
4537 months[18] = L"Jul";
4538 months[19] = L"Aug";
4539 months[20] = L"Sep";
4540 months[21] = L"Oct";
4541 months[22] = L"Nov";
4542 months[23] = L"Dec";
4543 return months;
4544}
4545
4546template <>
4547const string*
4548__time_get_c_storage<char>::__months() const
4549{
4550 static const string* months = init_months();
4551 return months;
4552}
4553
4554template <>
4555const wstring*
4556__time_get_c_storage<wchar_t>::__months() const
4557{
4558 static const wstring* months = init_wmonths();
4559 return months;
4560}
4561
4562static
4563string*
4564init_am_pm()
4565{
4566 static string am_pm[24];
4567 am_pm[0] = "AM";
4568 am_pm[1] = "PM";
4569 return am_pm;
4570}
4571
4572static
4573wstring*
4574init_wam_pm()
4575{
4576 static wstring am_pm[24];
4577 am_pm[0] = L"AM";
4578 am_pm[1] = L"PM";
4579 return am_pm;
4580}
4581
4582template <>
4583const string*
4584__time_get_c_storage<char>::__am_pm() const
4585{
4586 static const string* am_pm = init_am_pm();
4587 return am_pm;
4588}
4589
4590template <>
4591const wstring*
4592__time_get_c_storage<wchar_t>::__am_pm() const
4593{
4594 static const wstring* am_pm = init_wam_pm();
4595 return am_pm;
4596}
4597
4598template <>
4599const string&
4600__time_get_c_storage<char>::__x() const
4601{
4602 static string s("%m/%d/%y");
4603 return s;
4604}
4605
4606template <>
4607const wstring&
4608__time_get_c_storage<wchar_t>::__x() const
4609{
4610 static wstring s(L"%m/%d/%y");
4611 return s;
4612}
4613
4614template <>
4615const string&
4616__time_get_c_storage<char>::__X() const
4617{
4618 static string s("%H:%M:%S");
4619 return s;
4620}
4621
4622template <>
4623const wstring&
4624__time_get_c_storage<wchar_t>::__X() const
4625{
4626 static wstring s(L"%H:%M:%S");
4627 return s;
4628}
4629
4630template <>
4631const string&
4632__time_get_c_storage<char>::__c() const
4633{
4634 static string s("%a %b %d %H:%M:%S %Y");
4635 return s;
4636}
4637
4638template <>
4639const wstring&
4640__time_get_c_storage<wchar_t>::__c() const
4641{
4642 static wstring s(L"%a %b %d %H:%M:%S %Y");
4643 return s;
4644}
4645
4646template <>
4647const string&
4648__time_get_c_storage<char>::__r() const
4649{
4650 static string s("%I:%M:%S %p");
4651 return s;
4652}
4653
4654template <>
4655const wstring&
4656__time_get_c_storage<wchar_t>::__r() const
4657{
4658 static wstring s(L"%I:%M:%S %p");
4659 return s;
4660}
4661
4662// time_get_byname
4663
4664__time_get::__time_get(const char* nm)
4665 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4666{
Howard Hinnant72f73582010-08-11 17:04:31 +00004667#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004668 if (__loc_ == 0)
4669 throw runtime_error("time_get_byname"
4670 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004671#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004672}
4673
4674__time_get::__time_get(const string& nm)
4675 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4676{
Howard Hinnant72f73582010-08-11 17:04:31 +00004677#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004678 if (__loc_ == 0)
4679 throw runtime_error("time_get_byname"
4680 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00004681#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004682}
4683
4684__time_get::~__time_get()
4685{
4686 freelocale(__loc_);
4687}
4688
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004689#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004690#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004691
Howard Hinnantc51e1022010-05-11 19:42:16 +00004692template <>
4693string
4694__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4695{
Howard Hinnant990207c2012-02-19 14:55:32 +00004696 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004697 t.tm_sec = 59;
4698 t.tm_min = 55;
4699 t.tm_hour = 23;
4700 t.tm_mday = 31;
4701 t.tm_mon = 11;
4702 t.tm_year = 161;
4703 t.tm_wday = 6;
4704 t.tm_yday = 364;
4705 t.tm_isdst = -1;
4706 char buf[100];
4707 char f[3] = {0};
4708 f[0] = '%';
4709 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004710 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004711 char* bb = buf;
4712 char* be = buf + n;
4713 string result;
4714 while (bb != be)
4715 {
4716 if (ct.is(ctype_base::space, *bb))
4717 {
4718 result.push_back(' ');
4719 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4720 ;
4721 continue;
4722 }
4723 char* w = bb;
4724 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004725 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004726 ct, err, false)
4727 - this->__weeks_;
4728 if (i < 14)
4729 {
4730 result.push_back('%');
4731 if (i < 7)
4732 result.push_back('A');
4733 else
4734 result.push_back('a');
4735 bb = w;
4736 continue;
4737 }
4738 w = bb;
4739 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4740 ct, err, false)
4741 - this->__months_;
4742 if (i < 24)
4743 {
4744 result.push_back('%');
4745 if (i < 12)
4746 result.push_back('B');
4747 else
4748 result.push_back('b');
4749 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4750 result.back() = 'm';
4751 bb = w;
4752 continue;
4753 }
4754 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4755 {
4756 w = bb;
4757 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4758 ct, err, false) - this->__am_pm_;
4759 if (i < 2)
4760 {
4761 result.push_back('%');
4762 result.push_back('p');
4763 bb = w;
4764 continue;
4765 }
4766 }
4767 w = bb;
4768 if (ct.is(ctype_base::digit, *bb))
4769 {
4770 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4771 {
4772 case 6:
4773 result.push_back('%');
4774 result.push_back('w');
4775 break;
4776 case 7:
4777 result.push_back('%');
4778 result.push_back('u');
4779 break;
4780 case 11:
4781 result.push_back('%');
4782 result.push_back('I');
4783 break;
4784 case 12:
4785 result.push_back('%');
4786 result.push_back('m');
4787 break;
4788 case 23:
4789 result.push_back('%');
4790 result.push_back('H');
4791 break;
4792 case 31:
4793 result.push_back('%');
4794 result.push_back('d');
4795 break;
4796 case 55:
4797 result.push_back('%');
4798 result.push_back('M');
4799 break;
4800 case 59:
4801 result.push_back('%');
4802 result.push_back('S');
4803 break;
4804 case 61:
4805 result.push_back('%');
4806 result.push_back('y');
4807 break;
4808 case 364:
4809 result.push_back('%');
4810 result.push_back('j');
4811 break;
4812 case 2061:
4813 result.push_back('%');
4814 result.push_back('Y');
4815 break;
4816 default:
4817 for (; w != bb; ++w)
4818 result.push_back(*w);
4819 break;
4820 }
4821 continue;
4822 }
4823 if (*bb == '%')
4824 {
4825 result.push_back('%');
4826 result.push_back('%');
4827 ++bb;
4828 continue;
4829 }
4830 result.push_back(*bb);
4831 ++bb;
4832 }
4833 return result;
4834}
4835
Howard Hinnant28b24882011-12-01 20:21:04 +00004836#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnant28b24882011-12-01 20:21:04 +00004837
Howard Hinnantc51e1022010-05-11 19:42:16 +00004838template <>
4839wstring
4840__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4841{
Howard Hinnant990207c2012-02-19 14:55:32 +00004842 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004843 t.tm_sec = 59;
4844 t.tm_min = 55;
4845 t.tm_hour = 23;
4846 t.tm_mday = 31;
4847 t.tm_mon = 11;
4848 t.tm_year = 161;
4849 t.tm_wday = 6;
4850 t.tm_yday = 364;
4851 t.tm_isdst = -1;
4852 char buf[100];
4853 char f[3] = {0};
4854 f[0] = '%';
4855 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004856 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004857 wchar_t wbuf[100];
4858 wchar_t* wbb = wbuf;
4859 mbstate_t mb = {0};
4860 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004861#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004862 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004863#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004864 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004865#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004866 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004867 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004868 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004869 wstring result;
4870 while (wbb != wbe)
4871 {
4872 if (ct.is(ctype_base::space, *wbb))
4873 {
4874 result.push_back(L' ');
4875 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4876 ;
4877 continue;
4878 }
4879 wchar_t* w = wbb;
4880 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004881 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004882 ct, err, false)
4883 - this->__weeks_;
4884 if (i < 14)
4885 {
4886 result.push_back(L'%');
4887 if (i < 7)
4888 result.push_back(L'A');
4889 else
4890 result.push_back(L'a');
4891 wbb = w;
4892 continue;
4893 }
4894 w = wbb;
4895 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4896 ct, err, false)
4897 - this->__months_;
4898 if (i < 24)
4899 {
4900 result.push_back(L'%');
4901 if (i < 12)
4902 result.push_back(L'B');
4903 else
4904 result.push_back(L'b');
4905 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4906 result.back() = L'm';
4907 wbb = w;
4908 continue;
4909 }
4910 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4911 {
4912 w = wbb;
4913 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4914 ct, err, false) - this->__am_pm_;
4915 if (i < 2)
4916 {
4917 result.push_back(L'%');
4918 result.push_back(L'p');
4919 wbb = w;
4920 continue;
4921 }
4922 }
4923 w = wbb;
4924 if (ct.is(ctype_base::digit, *wbb))
4925 {
4926 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4927 {
4928 case 6:
4929 result.push_back(L'%');
4930 result.push_back(L'w');
4931 break;
4932 case 7:
4933 result.push_back(L'%');
4934 result.push_back(L'u');
4935 break;
4936 case 11:
4937 result.push_back(L'%');
4938 result.push_back(L'I');
4939 break;
4940 case 12:
4941 result.push_back(L'%');
4942 result.push_back(L'm');
4943 break;
4944 case 23:
4945 result.push_back(L'%');
4946 result.push_back(L'H');
4947 break;
4948 case 31:
4949 result.push_back(L'%');
4950 result.push_back(L'd');
4951 break;
4952 case 55:
4953 result.push_back(L'%');
4954 result.push_back(L'M');
4955 break;
4956 case 59:
4957 result.push_back(L'%');
4958 result.push_back(L'S');
4959 break;
4960 case 61:
4961 result.push_back(L'%');
4962 result.push_back(L'y');
4963 break;
4964 case 364:
4965 result.push_back(L'%');
4966 result.push_back(L'j');
4967 break;
4968 case 2061:
4969 result.push_back(L'%');
4970 result.push_back(L'Y');
4971 break;
4972 default:
4973 for (; w != wbb; ++w)
4974 result.push_back(*w);
4975 break;
4976 }
4977 continue;
4978 }
4979 if (ct.narrow(*wbb, 0) == '%')
4980 {
4981 result.push_back(L'%');
4982 result.push_back(L'%');
4983 ++wbb;
4984 continue;
4985 }
4986 result.push_back(*wbb);
4987 ++wbb;
4988 }
4989 return result;
4990}
4991
4992template <>
4993void
4994__time_get_storage<char>::init(const ctype<char>& ct)
4995{
Howard Hinnant1796ab12012-08-02 18:44:17 +00004996 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004997 char buf[100];
4998 // __weeks_
4999 for (int i = 0; i < 7; ++i)
5000 {
5001 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005002 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005003 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005004 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005005 __weeks_[i+7] = buf;
5006 }
5007 // __months_
5008 for (int i = 0; i < 12; ++i)
5009 {
5010 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005011 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005012 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005013 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005014 __months_[i+12] = buf;
5015 }
5016 // __am_pm_
5017 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005018 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005019 __am_pm_[0] = buf;
5020 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005021 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005022 __am_pm_[1] = buf;
5023 __c_ = __analyze('c', ct);
5024 __r_ = __analyze('r', ct);
5025 __x_ = __analyze('x', ct);
5026 __X_ = __analyze('X', ct);
5027}
5028
5029template <>
5030void
5031__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5032{
5033 tm t = {0};
5034 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005035 wchar_t wbuf[100];
5036 wchar_t* wbe;
5037 mbstate_t mb = {0};
5038 // __weeks_
5039 for (int i = 0; i < 7; ++i)
5040 {
5041 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005042 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005043 mb = mbstate_t();
5044 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005045#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005046 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005047#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005048 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005049#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005050 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005051 __throw_runtime_error("locale not supported");
5052 wbe = wbuf + j;
5053 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005054 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005055 mb = mbstate_t();
5056 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005057#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005058 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005059#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005060 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005061#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005062 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005063 __throw_runtime_error("locale not supported");
5064 wbe = wbuf + j;
5065 __weeks_[i+7].assign(wbuf, wbe);
5066 }
5067 // __months_
5068 for (int i = 0; i < 12; ++i)
5069 {
5070 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005071 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005072 mb = mbstate_t();
5073 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005074#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005075 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005076#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005077 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005078#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005079 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005080 __throw_runtime_error("locale not supported");
5081 wbe = wbuf + j;
5082 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005083 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005084 mb = mbstate_t();
5085 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005086#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005087 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005088#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005089 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005090#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005091 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005092 __throw_runtime_error("locale not supported");
5093 wbe = wbuf + j;
5094 __months_[i+12].assign(wbuf, wbe);
5095 }
5096 // __am_pm_
5097 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005098 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005099 mb = mbstate_t();
5100 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005101#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005102 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005103#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005104 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005105#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005106 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005107 __throw_runtime_error("locale not supported");
5108 wbe = wbuf + j;
5109 __am_pm_[0].assign(wbuf, wbe);
5110 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005111 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005112 mb = mbstate_t();
5113 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005114#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005115 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005116#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005117 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005118#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005119 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005120 __throw_runtime_error("locale not supported");
5121 wbe = wbuf + j;
5122 __am_pm_[1].assign(wbuf, wbe);
5123 __c_ = __analyze('c', ct);
5124 __r_ = __analyze('r', ct);
5125 __x_ = __analyze('x', ct);
5126 __X_ = __analyze('X', ct);
5127}
5128
5129template <class CharT>
5130struct _LIBCPP_HIDDEN __time_get_temp
5131 : public ctype_byname<CharT>
5132{
5133 explicit __time_get_temp(const char* nm)
5134 : ctype_byname<CharT>(nm, 1) {}
5135 explicit __time_get_temp(const string& nm)
5136 : ctype_byname<CharT>(nm, 1) {}
5137};
5138
5139template <>
5140__time_get_storage<char>::__time_get_storage(const char* __nm)
5141 : __time_get(__nm)
5142{
5143 const __time_get_temp<char> ct(__nm);
5144 init(ct);
5145}
5146
5147template <>
5148__time_get_storage<char>::__time_get_storage(const string& __nm)
5149 : __time_get(__nm)
5150{
5151 const __time_get_temp<char> ct(__nm);
5152 init(ct);
5153}
5154
5155template <>
5156__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5157 : __time_get(__nm)
5158{
5159 const __time_get_temp<wchar_t> ct(__nm);
5160 init(ct);
5161}
5162
5163template <>
5164__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5165 : __time_get(__nm)
5166{
5167 const __time_get_temp<wchar_t> ct(__nm);
5168 init(ct);
5169}
5170
5171template <>
5172time_base::dateorder
5173__time_get_storage<char>::__do_date_order() const
5174{
5175 unsigned i;
5176 for (i = 0; i < __x_.size(); ++i)
5177 if (__x_[i] == '%')
5178 break;
5179 ++i;
5180 switch (__x_[i])
5181 {
5182 case 'y':
5183 case 'Y':
5184 for (++i; i < __x_.size(); ++i)
5185 if (__x_[i] == '%')
5186 break;
5187 if (i == __x_.size())
5188 break;
5189 ++i;
5190 switch (__x_[i])
5191 {
5192 case 'm':
5193 for (++i; i < __x_.size(); ++i)
5194 if (__x_[i] == '%')
5195 break;
5196 if (i == __x_.size())
5197 break;
5198 ++i;
5199 if (__x_[i] == 'd')
5200 return time_base::ymd;
5201 break;
5202 case 'd':
5203 for (++i; i < __x_.size(); ++i)
5204 if (__x_[i] == '%')
5205 break;
5206 if (i == __x_.size())
5207 break;
5208 ++i;
5209 if (__x_[i] == 'm')
5210 return time_base::ydm;
5211 break;
5212 }
5213 break;
5214 case 'm':
5215 for (++i; i < __x_.size(); ++i)
5216 if (__x_[i] == '%')
5217 break;
5218 if (i == __x_.size())
5219 break;
5220 ++i;
5221 if (__x_[i] == 'd')
5222 {
5223 for (++i; i < __x_.size(); ++i)
5224 if (__x_[i] == '%')
5225 break;
5226 if (i == __x_.size())
5227 break;
5228 ++i;
5229 if (__x_[i] == 'y' || __x_[i] == 'Y')
5230 return time_base::mdy;
5231 break;
5232 }
5233 break;
5234 case 'd':
5235 for (++i; i < __x_.size(); ++i)
5236 if (__x_[i] == '%')
5237 break;
5238 if (i == __x_.size())
5239 break;
5240 ++i;
5241 if (__x_[i] == 'm')
5242 {
5243 for (++i; i < __x_.size(); ++i)
5244 if (__x_[i] == '%')
5245 break;
5246 if (i == __x_.size())
5247 break;
5248 ++i;
5249 if (__x_[i] == 'y' || __x_[i] == 'Y')
5250 return time_base::dmy;
5251 break;
5252 }
5253 break;
5254 }
5255 return time_base::no_order;
5256}
5257
5258template <>
5259time_base::dateorder
5260__time_get_storage<wchar_t>::__do_date_order() const
5261{
5262 unsigned i;
5263 for (i = 0; i < __x_.size(); ++i)
5264 if (__x_[i] == L'%')
5265 break;
5266 ++i;
5267 switch (__x_[i])
5268 {
5269 case L'y':
5270 case L'Y':
5271 for (++i; i < __x_.size(); ++i)
5272 if (__x_[i] == L'%')
5273 break;
5274 if (i == __x_.size())
5275 break;
5276 ++i;
5277 switch (__x_[i])
5278 {
5279 case L'm':
5280 for (++i; i < __x_.size(); ++i)
5281 if (__x_[i] == L'%')
5282 break;
5283 if (i == __x_.size())
5284 break;
5285 ++i;
5286 if (__x_[i] == L'd')
5287 return time_base::ymd;
5288 break;
5289 case L'd':
5290 for (++i; i < __x_.size(); ++i)
5291 if (__x_[i] == L'%')
5292 break;
5293 if (i == __x_.size())
5294 break;
5295 ++i;
5296 if (__x_[i] == L'm')
5297 return time_base::ydm;
5298 break;
5299 }
5300 break;
5301 case L'm':
5302 for (++i; i < __x_.size(); ++i)
5303 if (__x_[i] == L'%')
5304 break;
5305 if (i == __x_.size())
5306 break;
5307 ++i;
5308 if (__x_[i] == L'd')
5309 {
5310 for (++i; i < __x_.size(); ++i)
5311 if (__x_[i] == L'%')
5312 break;
5313 if (i == __x_.size())
5314 break;
5315 ++i;
5316 if (__x_[i] == L'y' || __x_[i] == L'Y')
5317 return time_base::mdy;
5318 break;
5319 }
5320 break;
5321 case L'd':
5322 for (++i; i < __x_.size(); ++i)
5323 if (__x_[i] == L'%')
5324 break;
5325 if (i == __x_.size())
5326 break;
5327 ++i;
5328 if (__x_[i] == L'm')
5329 {
5330 for (++i; i < __x_.size(); ++i)
5331 if (__x_[i] == L'%')
5332 break;
5333 if (i == __x_.size())
5334 break;
5335 ++i;
5336 if (__x_[i] == L'y' || __x_[i] == L'Y')
5337 return time_base::dmy;
5338 break;
5339 }
5340 break;
5341 }
5342 return time_base::no_order;
5343}
5344
5345// time_put
5346
5347__time_put::__time_put(const char* nm)
5348 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5349{
Howard Hinnant72f73582010-08-11 17:04:31 +00005350#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005351 if (__loc_ == 0)
5352 throw runtime_error("time_put_byname"
5353 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005354#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005355}
5356
5357__time_put::__time_put(const string& nm)
5358 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5359{
Howard Hinnant72f73582010-08-11 17:04:31 +00005360#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005361 if (__loc_ == 0)
5362 throw runtime_error("time_put_byname"
5363 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00005364#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005365}
5366
5367__time_put::~__time_put()
5368{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005369 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005370 freelocale(__loc_);
5371}
5372
5373void
5374__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5375 char __fmt, char __mod) const
5376{
5377 char fmt[] = {'%', __fmt, __mod, 0};
5378 if (__mod != 0)
5379 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005380 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005381 __ne = __nb + n;
5382}
5383
5384void
5385__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5386 char __fmt, char __mod) const
5387{
5388 char __nar[100];
5389 char* __ne = __nar + 100;
5390 __do_put(__nar, __ne, __tm, __fmt, __mod);
5391 mbstate_t mb = {0};
5392 const char* __nb = __nar;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005393#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005394 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005395#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005396 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005397#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005398 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005399 __throw_runtime_error("locale not supported");
5400 __we = __wb + j;
5401}
5402
5403// moneypunct_byname
5404
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005405template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005406static
5407void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005408__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5409 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5410 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005411{
5412 const char sign = static_cast<char>(money_base::sign);
5413 const char space = static_cast<char>(money_base::space);
5414 const char none = static_cast<char>(money_base::none);
5415 const char symbol = static_cast<char>(money_base::symbol);
5416 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005417 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5418
5419 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5420 // function'. "Space between sign and symbol or value" means that
5421 // if the sign is adjacent to the symbol, there's a space between
5422 // them, and otherwise there's a space between the sign and value.
5423 //
5424 // C11's localeconv specifies that the fourth character of an
5425 // international curr_symbol is used to separate the sign and
5426 // value when sep_by_space says to do so. C++ can't represent
5427 // that, so we just use a space. When sep_by_space says to
5428 // separate the symbol and value-or-sign with a space, we rearrange the
5429 // curr_symbol to put its spacing character on the correct side of
5430 // the symbol.
5431 //
5432 // We also need to avoid adding an extra space between the sign
5433 // and value when the currency symbol is suppressed (by not
5434 // setting showbase). We match glibc's strfmon by interpreting
5435 // sep_by_space==1 as "omit the space when the currency symbol is
5436 // absent".
5437 //
5438 // Users who want to get this right should use ICU instead.
5439
Howard Hinnantc51e1022010-05-11 19:42:16 +00005440 switch (cs_precedes)
5441 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005442 case 0: // value before curr_symbol
5443 if (symbol_contains_sep) {
5444 // Move the separator to before the symbol, to place it
5445 // between the value and symbol.
5446 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5447 __curr_symbol_.end());
5448 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005449 switch (sign_posn)
5450 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005451 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005452 pat.field[0] = sign;
5453 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005454 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005455 pat.field[3] = symbol;
5456 switch (sep_by_space)
5457 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005458 case 0: // No space separates the currency symbol and value.
5459 // This case may have changed between C99 and C11;
5460 // assume the currency symbol matches the intention.
5461 case 2: // Space between sign and currency or value.
5462 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005463 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005464 case 1: // Space between currency-and-sign or currency and value.
5465 if (!symbol_contains_sep) {
5466 // We insert the space into the symbol instead of
5467 // setting pat.field[2]=space so that when
5468 // showbase is not set, the space goes away too.
5469 __curr_symbol_.insert(0, 1, space_char);
5470 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005471 return;
5472 default:
5473 break;
5474 }
5475 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005476 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005477 pat.field[0] = sign;
5478 pat.field[3] = symbol;
5479 switch (sep_by_space)
5480 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005481 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005482 pat.field[1] = value;
5483 pat.field[2] = none;
5484 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005485 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005486 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005487 pat.field[2] = none;
5488 if (!symbol_contains_sep) {
5489 // We insert the space into the symbol instead of
5490 // setting pat.field[2]=space so that when
5491 // showbase is not set, the space goes away too.
5492 __curr_symbol_.insert(0, 1, space_char);
5493 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005494 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005495 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005496 pat.field[1] = space;
5497 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005498 if (symbol_contains_sep) {
5499 // Remove the separator from the symbol, since it
5500 // has already appeared after the sign.
5501 __curr_symbol_.erase(__curr_symbol_.begin());
5502 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005503 return;
5504 default:
5505 break;
5506 }
5507 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005508 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005509 pat.field[0] = value;
5510 pat.field[3] = sign;
5511 switch (sep_by_space)
5512 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005513 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005514 pat.field[1] = none;
5515 pat.field[2] = symbol;
5516 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005517 case 1: // Space between currency-and-sign or currency and value.
5518 if (!symbol_contains_sep) {
5519 // We insert the space into the symbol instead of
5520 // setting pat.field[1]=space so that when
5521 // showbase is not set, the space goes away too.
5522 __curr_symbol_.insert(0, 1, space_char);
5523 }
5524 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005525 pat.field[2] = symbol;
5526 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005527 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005528 pat.field[1] = symbol;
5529 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005530 if (symbol_contains_sep) {
5531 // Remove the separator from the symbol, since it
5532 // should not be removed if showbase is absent.
5533 __curr_symbol_.erase(__curr_symbol_.begin());
5534 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005535 return;
5536 default:
5537 break;
5538 }
5539 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005540 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005541 pat.field[0] = value;
5542 pat.field[3] = symbol;
5543 switch (sep_by_space)
5544 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005545 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005546 pat.field[1] = none;
5547 pat.field[2] = sign;
5548 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005549 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005550 pat.field[1] = space;
5551 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005552 if (symbol_contains_sep) {
5553 // Remove the separator from the symbol, since it
5554 // has already appeared before the sign.
5555 __curr_symbol_.erase(__curr_symbol_.begin());
5556 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005557 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005558 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005559 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005560 pat.field[2] = none;
5561 if (!symbol_contains_sep) {
5562 // We insert the space into the symbol instead of
5563 // setting pat.field[2]=space so that when
5564 // showbase is not set, the space goes away too.
5565 __curr_symbol_.insert(0, 1, space_char);
5566 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005567 return;
5568 default:
5569 break;
5570 }
5571 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005572 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005573 pat.field[0] = value;
5574 pat.field[3] = sign;
5575 switch (sep_by_space)
5576 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005577 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005578 pat.field[1] = none;
5579 pat.field[2] = symbol;
5580 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005581 case 1: // Space between currency-and-sign or currency and value.
5582 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005583 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005584 if (!symbol_contains_sep) {
5585 // We insert the space into the symbol instead of
5586 // setting pat.field[1]=space so that when
5587 // showbase is not set, the space goes away too.
5588 __curr_symbol_.insert(0, 1, space_char);
5589 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005590 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005591 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005592 pat.field[1] = symbol;
5593 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005594 if (symbol_contains_sep) {
5595 // Remove the separator from the symbol, since it
5596 // should not disappear when showbase is absent.
5597 __curr_symbol_.erase(__curr_symbol_.begin());
5598 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005599 return;
5600 default:
5601 break;
5602 }
5603 break;
5604 default:
5605 break;
5606 }
5607 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005608 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005609 switch (sign_posn)
5610 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005611 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005612 pat.field[0] = sign;
5613 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005614 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005615 pat.field[3] = value;
5616 switch (sep_by_space)
5617 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005618 case 0: // No space separates the currency symbol and value.
5619 // This case may have changed between C99 and C11;
5620 // assume the currency symbol matches the intention.
5621 case 2: // Space between sign and currency or value.
5622 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005623 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005624 case 1: // Space between currency-and-sign or currency and value.
5625 if (!symbol_contains_sep) {
5626 // We insert the space into the symbol instead of
5627 // setting pat.field[2]=space so that when
5628 // showbase is not set, the space goes away too.
5629 __curr_symbol_.insert(0, 1, space_char);
5630 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005631 return;
5632 default:
5633 break;
5634 }
5635 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005636 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005637 pat.field[0] = sign;
5638 pat.field[3] = value;
5639 switch (sep_by_space)
5640 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005641 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005642 pat.field[1] = symbol;
5643 pat.field[2] = none;
5644 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005645 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005646 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005647 pat.field[2] = none;
5648 if (!symbol_contains_sep) {
5649 // We insert the space into the symbol instead of
5650 // setting pat.field[2]=space so that when
5651 // showbase is not set, the space goes away too.
5652 __curr_symbol_.push_back(space_char);
5653 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005654 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005655 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005656 pat.field[1] = space;
5657 pat.field[2] = symbol;
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 after the sign.
5661 __curr_symbol_.pop_back();
5662 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005663 return;
5664 default:
5665 break;
5666 }
5667 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005668 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005669 pat.field[0] = symbol;
5670 pat.field[3] = sign;
5671 switch (sep_by_space)
5672 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005673 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005674 pat.field[1] = none;
5675 pat.field[2] = value;
5676 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005677 case 1: // Space between currency-and-sign or currency and value.
5678 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005679 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005680 if (!symbol_contains_sep) {
5681 // We insert the space into the symbol instead of
5682 // setting pat.field[1]=space so that when
5683 // showbase is not set, the space goes away too.
5684 __curr_symbol_.push_back(space_char);
5685 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005686 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005687 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005688 pat.field[1] = value;
5689 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005690 if (symbol_contains_sep) {
5691 // Remove the separator from the symbol, since it
5692 // will appear before the sign.
5693 __curr_symbol_.pop_back();
5694 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005695 return;
5696 default:
5697 break;
5698 }
5699 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005700 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005701 pat.field[0] = sign;
5702 pat.field[3] = value;
5703 switch (sep_by_space)
5704 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005705 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005706 pat.field[1] = symbol;
5707 pat.field[2] = none;
5708 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005709 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005710 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005711 pat.field[2] = none;
5712 if (!symbol_contains_sep) {
5713 // We insert the space into the symbol instead of
5714 // setting pat.field[2]=space so that when
5715 // showbase is not set, the space goes away too.
5716 __curr_symbol_.push_back(space_char);
5717 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005718 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005719 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005720 pat.field[1] = space;
5721 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005722 if (symbol_contains_sep) {
5723 // Remove the separator from the symbol, since it
5724 // has already appeared after the sign.
5725 __curr_symbol_.pop_back();
5726 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005727 return;
5728 default:
5729 break;
5730 }
5731 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005732 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005733 pat.field[0] = symbol;
5734 pat.field[3] = value;
5735 switch (sep_by_space)
5736 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005737 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005738 pat.field[1] = sign;
5739 pat.field[2] = none;
5740 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005741 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005742 pat.field[1] = sign;
5743 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005744 if (symbol_contains_sep) {
5745 // Remove the separator from the symbol, since it
5746 // should not disappear when showbase is absent.
5747 __curr_symbol_.pop_back();
5748 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005749 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005750 case 2: // Space between sign and currency or value.
5751 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005752 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005753 if (!symbol_contains_sep) {
5754 // We insert the space into the symbol instead of
5755 // setting pat.field[1]=space so that when
5756 // showbase is not set, the space goes away too.
5757 __curr_symbol_.push_back(space_char);
5758 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005759 return;
5760 default:
5761 break;
5762 }
5763 break;
5764 default:
5765 break;
5766 }
5767 break;
5768 default:
5769 break;
5770 }
5771 pat.field[0] = symbol;
5772 pat.field[1] = sign;
5773 pat.field[2] = none;
5774 pat.field[3] = value;
5775}
5776
5777template<>
5778void
5779moneypunct_byname<char, false>::init(const char* nm)
5780{
5781 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005782 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005783#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005784 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005785 throw runtime_error("moneypunct_byname"
5786 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005787#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005788#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005789 lconv* lc = localeconv_l(loc.get());
5790#else
5791 lconv* lc = __localeconv_l(loc.get());
5792#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005793 if (*lc->mon_decimal_point)
5794 __decimal_point_ = *lc->mon_decimal_point;
5795 else
5796 __decimal_point_ = base::do_decimal_point();
5797 if (*lc->mon_thousands_sep)
5798 __thousands_sep_ = *lc->mon_thousands_sep;
5799 else
5800 __thousands_sep_ = base::do_thousands_sep();
5801 __grouping_ = lc->mon_grouping;
5802 __curr_symbol_ = lc->currency_symbol;
5803 if (lc->frac_digits != CHAR_MAX)
5804 __frac_digits_ = lc->frac_digits;
5805 else
5806 __frac_digits_ = base::do_frac_digits();
5807 if (lc->p_sign_posn == 0)
5808 __positive_sign_ = "()";
5809 else
5810 __positive_sign_ = lc->positive_sign;
5811 if (lc->n_sign_posn == 0)
5812 __negative_sign_ = "()";
5813 else
5814 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005815 // Assume the positive and negative formats will want spaces in
5816 // the same places in curr_symbol since there's no way to
5817 // represent anything else.
5818 string_type __dummy_curr_symbol = __curr_symbol_;
5819 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5820 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5821 __init_pat(__neg_format_, __curr_symbol_, false,
5822 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005823}
5824
5825template<>
5826void
5827moneypunct_byname<char, true>::init(const char* nm)
5828{
5829 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005830 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005831#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005832 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005833 throw runtime_error("moneypunct_byname"
5834 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005835#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005836#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005837 lconv* lc = localeconv_l(loc.get());
5838#else
5839 lconv* lc = __localeconv_l(loc.get());
5840#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005841 if (*lc->mon_decimal_point)
5842 __decimal_point_ = *lc->mon_decimal_point;
5843 else
5844 __decimal_point_ = base::do_decimal_point();
5845 if (*lc->mon_thousands_sep)
5846 __thousands_sep_ = *lc->mon_thousands_sep;
5847 else
5848 __thousands_sep_ = base::do_thousands_sep();
5849 __grouping_ = lc->mon_grouping;
5850 __curr_symbol_ = lc->int_curr_symbol;
5851 if (lc->int_frac_digits != CHAR_MAX)
5852 __frac_digits_ = lc->int_frac_digits;
5853 else
5854 __frac_digits_ = base::do_frac_digits();
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005855#ifdef _LIBCPP_MSVCRT
Howard Hinnanteb505f62011-09-23 16:11:27 +00005856 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005857#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005858 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005859#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005860 __positive_sign_ = "()";
5861 else
5862 __positive_sign_ = lc->positive_sign;
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005863#ifdef _LIBCPP_MSVCRT
Howard Hinnanteb505f62011-09-23 16:11:27 +00005864 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005865#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005866 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005867#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005868 __negative_sign_ = "()";
5869 else
5870 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005871 // Assume the positive and negative formats will want spaces in
5872 // the same places in curr_symbol since there's no way to
5873 // represent anything else.
5874 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005875#ifdef _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005876 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5877 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5878 __init_pat(__neg_format_, __curr_symbol_, true,
5879 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005880#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005881 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5882 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5883 lc->int_p_sign_posn, ' ');
5884 __init_pat(__neg_format_, __curr_symbol_, true,
5885 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5886 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005887#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005888}
5889
5890template<>
5891void
5892moneypunct_byname<wchar_t, false>::init(const char* nm)
5893{
5894 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005895 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005896#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005897 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005898 throw runtime_error("moneypunct_byname"
5899 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005900#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005901#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005902 lconv* lc = localeconv_l(loc.get());
5903#else
5904 lconv* lc = __localeconv_l(loc.get());
5905#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005906 if (*lc->mon_decimal_point)
5907 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5908 else
5909 __decimal_point_ = base::do_decimal_point();
5910 if (*lc->mon_thousands_sep)
5911 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5912 else
5913 __thousands_sep_ = base::do_thousands_sep();
5914 __grouping_ = lc->mon_grouping;
5915 wchar_t wbuf[100];
5916 mbstate_t mb = {0};
5917 const char* bb = lc->currency_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005918#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005919 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005920#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005921 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005922#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005923 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005924 __throw_runtime_error("locale not supported");
5925 wchar_t* wbe = wbuf + j;
5926 __curr_symbol_.assign(wbuf, wbe);
5927 if (lc->frac_digits != CHAR_MAX)
5928 __frac_digits_ = lc->frac_digits;
5929 else
5930 __frac_digits_ = base::do_frac_digits();
5931 if (lc->p_sign_posn == 0)
5932 __positive_sign_ = L"()";
5933 else
5934 {
5935 mb = mbstate_t();
5936 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005937#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005938 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005939#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005940 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005941#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005942 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005943 __throw_runtime_error("locale not supported");
5944 wbe = wbuf + j;
5945 __positive_sign_.assign(wbuf, wbe);
5946 }
5947 if (lc->n_sign_posn == 0)
5948 __negative_sign_ = L"()";
5949 else
5950 {
5951 mb = mbstate_t();
5952 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005953#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005954 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005955#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005956 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005957#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005958 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005959 __throw_runtime_error("locale not supported");
5960 wbe = wbuf + j;
5961 __negative_sign_.assign(wbuf, wbe);
5962 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005963 // Assume the positive and negative formats will want spaces in
5964 // the same places in curr_symbol since there's no way to
5965 // represent anything else.
5966 string_type __dummy_curr_symbol = __curr_symbol_;
5967 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5968 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5969 __init_pat(__neg_format_, __curr_symbol_, false,
5970 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005971}
5972
5973template<>
5974void
5975moneypunct_byname<wchar_t, true>::init(const char* nm)
5976{
5977 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005978 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005979#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005980 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005981 throw runtime_error("moneypunct_byname"
5982 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005983#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005984#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005985 lconv* lc = localeconv_l(loc.get());
5986#else
5987 lconv* lc = __localeconv_l(loc.get());
5988#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005989 if (*lc->mon_decimal_point)
5990 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5991 else
5992 __decimal_point_ = base::do_decimal_point();
5993 if (*lc->mon_thousands_sep)
5994 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5995 else
5996 __thousands_sep_ = base::do_thousands_sep();
5997 __grouping_ = lc->mon_grouping;
5998 wchar_t wbuf[100];
5999 mbstate_t mb = {0};
6000 const char* bb = lc->int_curr_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006001#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006002 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006003#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006004 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006005#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006006 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006007 __throw_runtime_error("locale not supported");
6008 wchar_t* wbe = wbuf + j;
6009 __curr_symbol_.assign(wbuf, wbe);
6010 if (lc->int_frac_digits != CHAR_MAX)
6011 __frac_digits_ = lc->int_frac_digits;
6012 else
6013 __frac_digits_ = base::do_frac_digits();
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006014#ifdef _LIBCPP_MSVCRT
Howard Hinnanteb505f62011-09-23 16:11:27 +00006015 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006016#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006017 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006018#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006019 __positive_sign_ = L"()";
6020 else
6021 {
6022 mb = mbstate_t();
6023 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006024#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006025 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 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 wbe = wbuf + j;
6032 __positive_sign_.assign(wbuf, wbe);
6033 }
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006034#ifdef _LIBCPP_MSVCRT
Howard Hinnanteb505f62011-09-23 16:11:27 +00006035 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006036#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006037 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006038#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006039 __negative_sign_ = L"()";
6040 else
6041 {
6042 mb = mbstate_t();
6043 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006044#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006045 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006046#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006047 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006048#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006049 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006050 __throw_runtime_error("locale not supported");
6051 wbe = wbuf + j;
6052 __negative_sign_.assign(wbuf, wbe);
6053 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006054 // Assume the positive and negative formats will want spaces in
6055 // the same places in curr_symbol since there's no way to
6056 // represent anything else.
6057 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006058#ifdef _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006059 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6060 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6061 __init_pat(__neg_format_, __curr_symbol_, true,
6062 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006063#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006064 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6065 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6066 lc->int_p_sign_posn, L' ');
6067 __init_pat(__neg_format_, __curr_symbol_, true,
6068 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6069 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006070#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006071}
6072
6073void __do_nothing(void*) {}
6074
6075void __throw_runtime_error(const char* msg)
6076{
Howard Hinnant72f73582010-08-11 17:04:31 +00006077#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006078 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006079#else
6080 (void)msg;
Howard Hinnant72f73582010-08-11 17:04:31 +00006081#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006082}
6083
6084template class collate<char>;
6085template class collate<wchar_t>;
6086
6087template class num_get<char>;
6088template class num_get<wchar_t>;
6089
Howard Hinnant28b24882011-12-01 20:21:04 +00006090template struct __num_get<char>;
6091template struct __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006092
6093template class num_put<char>;
6094template class num_put<wchar_t>;
6095
Howard Hinnant28b24882011-12-01 20:21:04 +00006096template struct __num_put<char>;
6097template struct __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006098
6099template class time_get<char>;
6100template class time_get<wchar_t>;
6101
6102template class time_get_byname<char>;
6103template class time_get_byname<wchar_t>;
6104
6105template class time_put<char>;
6106template class time_put<wchar_t>;
6107
6108template class time_put_byname<char>;
6109template class time_put_byname<wchar_t>;
6110
6111template class moneypunct<char, false>;
6112template class moneypunct<char, true>;
6113template class moneypunct<wchar_t, false>;
6114template class moneypunct<wchar_t, true>;
6115
6116template class moneypunct_byname<char, false>;
6117template class moneypunct_byname<char, true>;
6118template class moneypunct_byname<wchar_t, false>;
6119template class moneypunct_byname<wchar_t, true>;
6120
6121template class money_get<char>;
6122template class money_get<wchar_t>;
6123
6124template class __money_get<char>;
6125template class __money_get<wchar_t>;
6126
6127template class money_put<char>;
6128template class money_put<wchar_t>;
6129
6130template class __money_put<char>;
6131template class __money_put<wchar_t>;
6132
6133template class messages<char>;
6134template class messages<wchar_t>;
6135
6136template class messages_byname<char>;
6137template class messages_byname<wchar_t>;
6138
6139template class codecvt_byname<char, char, mbstate_t>;
6140template class codecvt_byname<wchar_t, char, mbstate_t>;
6141template class codecvt_byname<char16_t, char, mbstate_t>;
6142template class codecvt_byname<char32_t, char, mbstate_t>;
6143
6144template class __vector_base_common<true>;
6145
6146_LIBCPP_END_NAMESPACE_STD