blob: 34afe8c82e81d413afa21730464a2c5d931bd234 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-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 Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
David Chisnall997e4542012-02-29 13:05:08 +000010// On Solaris, we need to define something to make the C99 parts of localeconv
11// visible.
12#ifdef __sun__
13#define _LCONV_C99
14#endif
15
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000016#include "string"
17#include "locale"
Howard Hinnant87d1a8a2010-05-30 21:39:41 +000018#include "codecvt"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000019#include "vector"
20#include "algorithm"
21#include "algorithm"
22#include "typeinfo"
Howard Hinnantd318d492011-06-30 14:21:55 +000023#include "type_traits"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024#include "clocale"
25#include "cstring"
26#include "cwctype"
27#include "__sso_allocator"
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000028#if _WIN32
Howard Hinnant14fa9f92011-09-29 20:33:10 +000029#include <support/win32/locale_win32.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000030#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031#include <langinfo.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000032#endif // _!WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000033#include <stdlib.h>
34
35_LIBCPP_BEGIN_NAMESPACE_STD
36
Howard Hinnant866569b2011-09-28 23:39:33 +000037#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000038locale_t __cloc() {
39 // In theory this could create a race condition. In practice
40 // the race condition is non-fatal since it will just create
41 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000042 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
43 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000044}
Howard Hinnant866569b2011-09-28 23:39:33 +000045#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000046
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000047namespace {
48
49struct release
50{
51 void operator()(locale::facet* p) {p->__release_shared();}
52};
53
54template <class T, class A0>
55inline
56T&
57make(A0 a0)
58{
59 static typename aligned_storage<sizeof(T)>::type buf;
60 ::new (&buf) T(a0);
61 return *(T*)&buf;
62}
63
64template <class T, class A0, class A1>
65inline
66T&
67make(A0 a0, A1 a1)
68{
69 static typename aligned_storage<sizeof(T)>::type buf;
70 ::new (&buf) T(a0, a1);
71 return *(T*)&buf;
72}
73
74template <class T, class A0, class A1, class A2>
75inline
76T&
77make(A0 a0, A1 a1, A2 a2)
78{
79 static typename aligned_storage<sizeof(T)>::type buf;
80 ::new (&buf) T(a0, a1, a2);
81 return *(T*)&buf;
82}
83
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000084template <typename T, size_t N>
85_LIBCPP_ALWAYS_INLINE
86_LIBCPP_CONSTEXPR
87size_t
88countof(const T (&)[N])
89{
90 return N;
91}
92
93template <typename T>
94_LIBCPP_ALWAYS_INLINE
95_LIBCPP_CONSTEXPR
96size_t
97countof(const T * const begin, const T * const end)
98{
99 return static_cast<size_t>(end - begin);
100}
101
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000102}
103
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000104const locale::category locale::none;
105const locale::category locale::collate;
106const locale::category locale::ctype;
107const locale::category locale::monetary;
108const locale::category locale::numeric;
109const locale::category locale::time;
110const locale::category locale::messages;
111const locale::category locale::all;
112
Howard Hinnantec3773c2011-12-01 20:21:04 +0000113#pragma clang diagnostic push
114#pragma clang diagnostic ignored "-Wpadded"
115
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116class _LIBCPP_HIDDEN locale::__imp
117 : public facet
118{
119 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000121 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000122public:
123 explicit __imp(size_t refs = 0);
124 explicit __imp(const string& name, size_t refs = 0);
125 __imp(const __imp&);
126 __imp(const __imp&, const string&, locale::category c);
127 __imp(const __imp& other, const __imp& one, locale::category c);
128 __imp(const __imp&, facet* f, long id);
129 ~__imp();
130
131 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000132 bool has_facet(long id) const
133 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000134 const locale::facet* use_facet(long id) const;
135
136 static const locale& make_classic();
137 static locale& make_global();
138private:
139 void install(facet* f, long id);
140 template <class F> void install(F* f) {install(f, f->id.__get());}
141 template <class F> void install_from(const __imp& other);
142};
143
Howard Hinnantec3773c2011-12-01 20:21:04 +0000144#pragma clang diagnostic pop
145
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000146locale::__imp::__imp(size_t refs)
147 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000148 facets_(N),
149 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000150{
151 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000152 install(&make<_VSTD::collate<char> >(1u));
153 install(&make<_VSTD::collate<wchar_t> >(1u));
154 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
155 install(&make<_VSTD::ctype<wchar_t> >(1u));
156 install(&make<codecvt<char, char, mbstate_t> >(1u));
157 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
158 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
159 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
160 install(&make<numpunct<char> >(1u));
161 install(&make<numpunct<wchar_t> >(1u));
162 install(&make<num_get<char> >(1u));
163 install(&make<num_get<wchar_t> >(1u));
164 install(&make<num_put<char> >(1u));
165 install(&make<num_put<wchar_t> >(1u));
166 install(&make<moneypunct<char, false> >(1u));
167 install(&make<moneypunct<char, true> >(1u));
168 install(&make<moneypunct<wchar_t, false> >(1u));
169 install(&make<moneypunct<wchar_t, true> >(1u));
170 install(&make<money_get<char> >(1u));
171 install(&make<money_get<wchar_t> >(1u));
172 install(&make<money_put<char> >(1u));
173 install(&make<money_put<wchar_t> >(1u));
174 install(&make<time_get<char> >(1u));
175 install(&make<time_get<wchar_t> >(1u));
176 install(&make<time_put<char> >(1u));
177 install(&make<time_put<wchar_t> >(1u));
178 install(&make<_VSTD::messages<char> >(1u));
179 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000180}
181
182locale::__imp::__imp(const string& name, size_t refs)
183 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000184 facets_(N),
185 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000186{
Howard Hinnantd4444702010-08-11 17:04:31 +0000187#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000188 try
189 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000190#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000191 facets_ = locale::classic().__locale_->facets_;
192 for (unsigned i = 0; i < facets_.size(); ++i)
193 if (facets_[i])
194 facets_[i]->__add_shared();
195 install(new collate_byname<char>(name_));
196 install(new collate_byname<wchar_t>(name_));
197 install(new ctype_byname<char>(name_));
198 install(new ctype_byname<wchar_t>(name_));
199 install(new codecvt_byname<char, char, mbstate_t>(name_));
200 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
201 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
202 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
203 install(new numpunct_byname<char>(name_));
204 install(new numpunct_byname<wchar_t>(name_));
205 install(new moneypunct_byname<char, false>(name_));
206 install(new moneypunct_byname<char, true>(name_));
207 install(new moneypunct_byname<wchar_t, false>(name_));
208 install(new moneypunct_byname<wchar_t, true>(name_));
209 install(new time_get_byname<char>(name_));
210 install(new time_get_byname<wchar_t>(name_));
211 install(new time_put_byname<char>(name_));
212 install(new time_put_byname<wchar_t>(name_));
213 install(new messages_byname<char>(name_));
214 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000215#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000216 }
217 catch (...)
218 {
219 for (unsigned i = 0; i < facets_.size(); ++i)
220 if (facets_[i])
221 facets_[i]->__release_shared();
222 throw;
223 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000224#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000225}
226
227locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000228 : facets_(max<size_t>(N, other.facets_.size())),
229 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000230{
231 facets_ = other.facets_;
232 for (unsigned i = 0; i < facets_.size(); ++i)
233 if (facets_[i])
234 facets_[i]->__add_shared();
235}
236
237locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000238 : facets_(N),
239 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000240{
241 facets_ = other.facets_;
242 for (unsigned i = 0; i < facets_.size(); ++i)
243 if (facets_[i])
244 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000245#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000246 try
247 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000248#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000249 if (c & locale::collate)
250 {
251 install(new collate_byname<char>(name));
252 install(new collate_byname<wchar_t>(name));
253 }
254 if (c & locale::ctype)
255 {
256 install(new ctype_byname<char>(name));
257 install(new ctype_byname<wchar_t>(name));
258 install(new codecvt_byname<char, char, mbstate_t>(name));
259 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
260 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
261 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
262 }
263 if (c & locale::monetary)
264 {
265 install(new moneypunct_byname<char, false>(name));
266 install(new moneypunct_byname<char, true>(name));
267 install(new moneypunct_byname<wchar_t, false>(name));
268 install(new moneypunct_byname<wchar_t, true>(name));
269 }
270 if (c & locale::numeric)
271 {
272 install(new numpunct_byname<char>(name));
273 install(new numpunct_byname<wchar_t>(name));
274 }
275 if (c & locale::time)
276 {
277 install(new time_get_byname<char>(name));
278 install(new time_get_byname<wchar_t>(name));
279 install(new time_put_byname<char>(name));
280 install(new time_put_byname<wchar_t>(name));
281 }
282 if (c & locale::messages)
283 {
284 install(new messages_byname<char>(name));
285 install(new messages_byname<wchar_t>(name));
286 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000287#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000288 }
289 catch (...)
290 {
291 for (unsigned i = 0; i < facets_.size(); ++i)
292 if (facets_[i])
293 facets_[i]->__release_shared();
294 throw;
295 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000296#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000297}
298
299template<class F>
300inline
301void
302locale::__imp::install_from(const locale::__imp& one)
303{
304 long id = F::id.__get();
305 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
306}
307
308locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000309 : facets_(N),
310 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000311{
312 facets_ = other.facets_;
313 for (unsigned i = 0; i < facets_.size(); ++i)
314 if (facets_[i])
315 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000316#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000317 try
318 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000319#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000320 if (c & locale::collate)
321 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000322 install_from<_VSTD::collate<char> >(one);
323 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000324 }
325 if (c & locale::ctype)
326 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000327 install_from<_VSTD::ctype<char> >(one);
328 install_from<_VSTD::ctype<wchar_t> >(one);
329 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
330 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
331 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
332 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000333 }
334 if (c & locale::monetary)
335 {
336 install_from<moneypunct<char, false> >(one);
337 install_from<moneypunct<char, true> >(one);
338 install_from<moneypunct<wchar_t, false> >(one);
339 install_from<moneypunct<wchar_t, true> >(one);
340 install_from<money_get<char> >(one);
341 install_from<money_get<wchar_t> >(one);
342 install_from<money_put<char> >(one);
343 install_from<money_put<wchar_t> >(one);
344 }
345 if (c & locale::numeric)
346 {
347 install_from<numpunct<char> >(one);
348 install_from<numpunct<wchar_t> >(one);
349 install_from<num_get<char> >(one);
350 install_from<num_get<wchar_t> >(one);
351 install_from<num_put<char> >(one);
352 install_from<num_put<wchar_t> >(one);
353 }
354 if (c & locale::time)
355 {
356 install_from<time_get<char> >(one);
357 install_from<time_get<wchar_t> >(one);
358 install_from<time_put<char> >(one);
359 install_from<time_put<wchar_t> >(one);
360 }
361 if (c & locale::messages)
362 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000363 install_from<_VSTD::messages<char> >(one);
364 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000365 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000366#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000367 }
368 catch (...)
369 {
370 for (unsigned i = 0; i < facets_.size(); ++i)
371 if (facets_[i])
372 facets_[i]->__release_shared();
373 throw;
374 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000375#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000376}
377
378locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000379 : facets_(max<size_t>(N, other.facets_.size()+1)),
380 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000381{
382 f->__add_shared();
383 unique_ptr<facet, release> hold(f);
384 facets_ = other.facets_;
385 for (unsigned i = 0; i < other.facets_.size(); ++i)
386 if (facets_[i])
387 facets_[i]->__add_shared();
388 install(hold.get(), id);
389}
390
391locale::__imp::~__imp()
392{
393 for (unsigned i = 0; i < facets_.size(); ++i)
394 if (facets_[i])
395 facets_[i]->__release_shared();
396}
397
398void
399locale::__imp::install(facet* f, long id)
400{
401 f->__add_shared();
402 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000403 if (static_cast<size_t>(id) >= facets_.size())
404 facets_.resize(static_cast<size_t>(id+1));
405 if (facets_[static_cast<size_t>(id)])
406 facets_[static_cast<size_t>(id)]->__release_shared();
407 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000408}
409
410const locale::facet*
411locale::__imp::use_facet(long id) const
412{
Howard Hinnantd4444702010-08-11 17:04:31 +0000413#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000414 if (!has_facet(id))
415 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000416#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000417 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000418}
419
420// locale
421
422const locale&
423locale::__imp::make_classic()
424{
425 // only one thread can get in here and it only gets in once
426 static aligned_storage<sizeof(locale)>::type buf;
427 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000428 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000429 return *c;
430}
431
432const locale&
433locale::classic()
434{
435 static const locale& c = __imp::make_classic();
436 return c;
437}
438
439locale&
440locale::__imp::make_global()
441{
442 // only one thread can get in here and it only gets in once
443 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000444 ::new (&buf) locale(locale::classic());
445 return *(locale*)&buf;
446}
447
448locale&
449locale::__global()
450{
451 static locale& g = __imp::make_global();
452 return g;
453}
454
Howard Hinnantc9834542011-05-31 15:34:58 +0000455locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000456 : __locale_(__global().__locale_)
457{
458 __locale_->__add_shared();
459}
460
Howard Hinnantc9834542011-05-31 15:34:58 +0000461locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000462 : __locale_(l.__locale_)
463{
464 __locale_->__add_shared();
465}
466
Howard Hinnantc9834542011-05-31 15:34:58 +0000467locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000468{
469 __locale_->__release_shared();
470}
471
472const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000473locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000474{
475 other.__locale_->__add_shared();
476 __locale_->__release_shared();
477 __locale_ = other.__locale_;
478 return *this;
479}
480
481locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000482#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000483 : __locale_(name ? new __imp(name)
484 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000485#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000486 : __locale_(new __imp(name))
487#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000488{
489 __locale_->__add_shared();
490}
491
492locale::locale(const string& name)
493 : __locale_(new __imp(name))
494{
495 __locale_->__add_shared();
496}
497
498locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000499#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000500 : __locale_(name ? new __imp(*other.__locale_, name, c)
501 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000502#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000503 : __locale_(new __imp(*other.__locale_, name, c))
504#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000505{
506 __locale_->__add_shared();
507}
508
509locale::locale(const locale& other, const string& name, category c)
510 : __locale_(new __imp(*other.__locale_, name, c))
511{
512 __locale_->__add_shared();
513}
514
515locale::locale(const locale& other, const locale& one, category c)
516 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
517{
518 __locale_->__add_shared();
519}
520
521string
522locale::name() const
523{
524 return __locale_->name();
525}
526
527void
528locale::__install_ctor(const locale& other, facet* f, long id)
529{
530 if (f)
531 __locale_ = new __imp(*other.__locale_, f, id);
532 else
533 __locale_ = other.__locale_;
534 __locale_->__add_shared();
535}
536
537locale
538locale::global(const locale& loc)
539{
540 locale& g = __global();
541 locale r = g;
542 g = loc;
543 if (g.name() != "*")
544 setlocale(LC_ALL, g.name().c_str());
545 return r;
546}
547
548bool
549locale::has_facet(id& x) const
550{
551 return __locale_->has_facet(x.__get());
552}
553
554const locale::facet*
555locale::use_facet(id& x) const
556{
557 return __locale_->use_facet(x.__get());
558}
559
560bool
561locale::operator==(const locale& y) const
562{
563 return (__locale_ == y.__locale_)
564 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
565}
566
567// locale::facet
568
569locale::facet::~facet()
570{
571}
572
573void
Howard Hinnant1694d232011-05-28 14:41:13 +0000574locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000575{
576 delete this;
577}
578
579// locale::id
580
581int32_t locale::id::__next_id = 0;
582
583namespace
584{
585
586class __fake_bind
587{
588 locale::id* id_;
589 void (locale::id::* pmf_)();
590public:
591 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
592 : id_(id), pmf_(pmf) {}
593
594 void operator()() const
595 {
596 (id_->*pmf_)();
597 }
598};
599
600}
601
602long
603locale::id::__get()
604{
605 call_once(__flag_, __fake_bind(&locale::id::__init, this));
606 return __id_ - 1;
607}
608
609void
610locale::id::__init()
611{
Howard Hinnantadff4892010-05-24 17:49:41 +0000612 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000613}
614
615// template <> class collate_byname<char>
616
617collate_byname<char>::collate_byname(const char* n, size_t refs)
618 : collate<char>(refs),
619 __l(newlocale(LC_ALL_MASK, n, 0))
620{
Howard Hinnantd4444702010-08-11 17:04:31 +0000621#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000622 if (__l == 0)
623 throw runtime_error("collate_byname<char>::collate_byname"
624 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000625#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000626}
627
628collate_byname<char>::collate_byname(const string& name, size_t refs)
629 : collate<char>(refs),
630 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
631{
Howard Hinnantd4444702010-08-11 17:04:31 +0000632#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000633 if (__l == 0)
634 throw runtime_error("collate_byname<char>::collate_byname"
635 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000636#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000637}
638
639collate_byname<char>::~collate_byname()
640{
641 freelocale(__l);
642}
643
644int
645collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
646 const char_type* __lo2, const char_type* __hi2) const
647{
648 string_type lhs(__lo1, __hi1);
649 string_type rhs(__lo2, __hi2);
650 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
651 if (r < 0)
652 return -1;
653 if (r > 0)
654 return 1;
655 return r;
656}
657
658collate_byname<char>::string_type
659collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
660{
661 const string_type in(lo, hi);
662 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
663 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
664 return out;
665}
666
667// template <> class collate_byname<wchar_t>
668
669collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
670 : collate<wchar_t>(refs),
671 __l(newlocale(LC_ALL_MASK, n, 0))
672{
Howard Hinnantd4444702010-08-11 17:04:31 +0000673#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000674 if (__l == 0)
675 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
676 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000677#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000678}
679
680collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
681 : collate<wchar_t>(refs),
682 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
683{
Howard Hinnantd4444702010-08-11 17:04:31 +0000684#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000685 if (__l == 0)
686 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
687 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000688#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000689}
690
691collate_byname<wchar_t>::~collate_byname()
692{
693 freelocale(__l);
694}
695
696int
697collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
698 const char_type* __lo2, const char_type* __hi2) const
699{
700 string_type lhs(__lo1, __hi1);
701 string_type rhs(__lo2, __hi2);
702 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
703 if (r < 0)
704 return -1;
705 if (r > 0)
706 return 1;
707 return r;
708}
709
710collate_byname<wchar_t>::string_type
711collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
712{
713 const string_type in(lo, hi);
714 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
715 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
716 return out;
717}
718
719// template <> class ctype<wchar_t>;
720
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000721const ctype_base::mask ctype_base::space;
722const ctype_base::mask ctype_base::print;
723const ctype_base::mask ctype_base::cntrl;
724const ctype_base::mask ctype_base::upper;
725const ctype_base::mask ctype_base::lower;
726const ctype_base::mask ctype_base::alpha;
727const ctype_base::mask ctype_base::digit;
728const ctype_base::mask ctype_base::punct;
729const ctype_base::mask ctype_base::xdigit;
730const ctype_base::mask ctype_base::blank;
731const ctype_base::mask ctype_base::alnum;
732const ctype_base::mask ctype_base::graph;
733
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000734locale::id ctype<wchar_t>::id;
735
736ctype<wchar_t>::~ctype()
737{
738}
739
740bool
741ctype<wchar_t>::do_is(mask m, char_type c) const
742{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000743 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000744}
745
746const wchar_t*
747ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
748{
749 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000750 *vec = static_cast<mask>(isascii(*low) ?
751 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000752 return low;
753}
754
755const wchar_t*
756ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
757{
758 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000759 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000760 break;
761 return low;
762}
763
764const wchar_t*
765ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
766{
767 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000768 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000769 break;
770 return low;
771}
772
773wchar_t
774ctype<wchar_t>::do_toupper(char_type c) const
775{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000776#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
777 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
778#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000779 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000780#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000781 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000782#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000783}
784
785const wchar_t*
786ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
787{
788 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000789#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
790 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
791#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000792 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
793 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000794#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000795 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000796#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000797 return low;
798}
799
800wchar_t
801ctype<wchar_t>::do_tolower(char_type c) const
802{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000803#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
804 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
805#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000806 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000807#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000808 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000809#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000810}
811
812const wchar_t*
813ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
814{
815 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000816#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
817 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
818#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000819 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
820 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000821#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000822 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000823#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000824 return low;
825}
826
827wchar_t
828ctype<wchar_t>::do_widen(char c) const
829{
830 return c;
831}
832
833const char*
834ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
835{
836 for (; low != high; ++low, ++dest)
837 *dest = *low;
838 return low;
839}
840
841char
842ctype<wchar_t>::do_narrow(char_type c, char dfault) const
843{
844 if (isascii(c))
845 return static_cast<char>(c);
846 return dfault;
847}
848
849const wchar_t*
850ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
851{
852 for (; low != high; ++low, ++dest)
853 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000854 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000855 else
856 *dest = dfault;
857 return low;
858}
859
860// template <> class ctype<char>;
861
862locale::id ctype<char>::id;
863
864ctype<char>::ctype(const mask* tab, bool del, size_t refs)
865 : locale::facet(refs),
866 __tab_(tab),
867 __del_(del)
868{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000869 if (__tab_ == 0)
870 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000871}
872
873ctype<char>::~ctype()
874{
875 if (__tab_ && __del_)
876 delete [] __tab_;
877}
878
879char
880ctype<char>::do_toupper(char_type c) const
881{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000882#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000883 return isascii(c) ?
884 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000885#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000886 return isascii(c) ? __classic_upper_table()[static_cast<size_t>(c)] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000887#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000888 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000889#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000890}
891
892const char*
893ctype<char>::do_toupper(char_type* low, const char_type* high) const
894{
895 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000896#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000897 *low = isascii(*low) ?
898 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000899#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000900 *low = isascii(*low) ? __classic_upper_table()[static_cast<size_t>(*low)] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000901#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000902 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000903#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000904 return low;
905}
906
907char
908ctype<char>::do_tolower(char_type c) const
909{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000910#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000911 return isascii(c) ?
912 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000913#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000914 return isascii(c) ? __classic_lower_table()[static_cast<size_t>(c)] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000915#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000916 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000917#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000918}
919
920const char*
921ctype<char>::do_tolower(char_type* low, const char_type* high) const
922{
923 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000924#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000925 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000926#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000927 *low = isascii(*low) ? __classic_lower_table()[static_cast<size_t>(*low)] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000928#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000929 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000930#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000931 return low;
932}
933
934char
935ctype<char>::do_widen(char c) const
936{
937 return c;
938}
939
940const char*
941ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
942{
943 for (; low != high; ++low, ++dest)
944 *dest = *low;
945 return low;
946}
947
948char
949ctype<char>::do_narrow(char_type c, char dfault) const
950{
951 if (isascii(c))
952 return static_cast<char>(c);
953 return dfault;
954}
955
956const char*
957ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
958{
959 for (; low != high; ++low, ++dest)
960 if (isascii(*low))
961 *dest = *low;
962 else
963 *dest = dfault;
964 return low;
965}
966
967const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000968ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000969{
David Chisnallc512df12011-09-21 08:39:44 +0000970#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000971 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000972#elif defined(__GLIBC__)
973 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +0000974#elif __sun__
975 return __ctype_mask;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000976#elif _WIN32
977 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +0000978// This is assumed to be safe, which is a nonsense assumption because we're
979// going to end up dereferencing it later...
Sean Hunt62a6ac32011-07-09 00:56:23 +0000980#else
David Chisnall997e4542012-02-29 13:05:08 +0000981 // Platform not supported: abort so the person doing the port knows what to
982 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +0000983# warning ctype<char>::classic_table() is not implemented
David Chisnall997e4542012-02-29 13:05:08 +0000984 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +0000985 return NULL;
986#endif
987}
988
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000989#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000990const int*
991ctype<char>::__classic_lower_table() _NOEXCEPT
992{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000993 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000994}
995
996const int*
997ctype<char>::__classic_upper_table() _NOEXCEPT
998{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000999 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001000}
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001001#endif // __GLIBC__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001002
1003// template <> class ctype_byname<char>
1004
1005ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1006 : ctype<char>(0, false, refs),
1007 __l(newlocale(LC_ALL_MASK, name, 0))
1008{
Howard Hinnantd4444702010-08-11 17:04:31 +00001009#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001010 if (__l == 0)
1011 throw runtime_error("ctype_byname<char>::ctype_byname"
1012 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001013#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001014}
1015
1016ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1017 : ctype<char>(0, false, refs),
1018 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1019{
Howard Hinnantd4444702010-08-11 17:04:31 +00001020#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001021 if (__l == 0)
1022 throw runtime_error("ctype_byname<char>::ctype_byname"
1023 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001024#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025}
1026
1027ctype_byname<char>::~ctype_byname()
1028{
1029 freelocale(__l);
1030}
1031
1032char
1033ctype_byname<char>::do_toupper(char_type c) const
1034{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001035 return static_cast<char>(toupper_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001036}
1037
1038const char*
1039ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1040{
1041 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001042 *low = static_cast<char>(toupper_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043 return low;
1044}
1045
1046char
1047ctype_byname<char>::do_tolower(char_type c) const
1048{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001049 return static_cast<char>(tolower_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001050}
1051
1052const char*
1053ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1054{
1055 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001056 *low = static_cast<char>(tolower_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001057 return low;
1058}
1059
1060// template <> class ctype_byname<wchar_t>
1061
1062ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1063 : ctype<wchar_t>(refs),
1064 __l(newlocale(LC_ALL_MASK, name, 0))
1065{
Howard Hinnantd4444702010-08-11 17:04:31 +00001066#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001067 if (__l == 0)
1068 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1069 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001070#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001071}
1072
1073ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1074 : ctype<wchar_t>(refs),
1075 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1076{
Howard Hinnantd4444702010-08-11 17:04:31 +00001077#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001078 if (__l == 0)
1079 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1080 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001081#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001082}
1083
1084ctype_byname<wchar_t>::~ctype_byname()
1085{
1086 freelocale(__l);
1087}
1088
1089bool
1090ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1091{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001092#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001093 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001094#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001095 bool result = false;
1096 if (m & space) result |= (iswspace_l(c, __l) != 0);
1097 if (m & print) result |= (iswprint_l(c, __l) != 0);
1098 if (m & cntrl) result |= (iswcntrl_l(c, __l) != 0);
1099 if (m & upper) result |= (iswupper_l(c, __l) != 0);
1100 if (m & lower) result |= (iswlower_l(c, __l) != 0);
1101 if (m & alpha) result |= (iswalpha_l(c, __l) != 0);
1102 if (m & digit) result |= (iswdigit_l(c, __l) != 0);
1103 if (m & punct) result |= (iswpunct_l(c, __l) != 0);
1104 if (m & xdigit) result |= (iswxdigit_l(c, __l) != 0);
1105 if (m & blank) result |= (iswblank_l(c, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001106 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001107#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001108}
1109
1110const wchar_t*
1111ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1112{
1113 for (; low != high; ++low, ++vec)
1114 {
1115 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001116 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001117 else
1118 {
1119 *vec = 0;
1120 if (iswspace_l(*low, __l))
1121 *vec |= space;
1122 if (iswprint_l(*low, __l))
1123 *vec |= print;
1124 if (iswcntrl_l(*low, __l))
1125 *vec |= cntrl;
1126 if (iswupper_l(*low, __l))
1127 *vec |= upper;
1128 if (iswlower_l(*low, __l))
1129 *vec |= lower;
1130 if (iswalpha_l(*low, __l))
1131 *vec |= alpha;
1132 if (iswdigit_l(*low, __l))
1133 *vec |= digit;
1134 if (iswpunct_l(*low, __l))
1135 *vec |= punct;
1136 if (iswxdigit_l(*low, __l))
1137 *vec |= xdigit;
1138 }
1139 }
1140 return low;
1141}
1142
1143const wchar_t*
1144ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1145{
1146 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001147 {
1148#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001149 if (iswctype_l(*low, m, __l))
1150 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001151#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001152 if (m & space && iswspace_l(*low, __l)) break;
1153 if (m & print && iswprint_l(*low, __l)) break;
1154 if (m & cntrl && iswcntrl_l(*low, __l)) break;
1155 if (m & upper && iswupper_l(*low, __l)) break;
1156 if (m & lower && iswlower_l(*low, __l)) break;
1157 if (m & alpha && iswalpha_l(*low, __l)) break;
1158 if (m & digit && iswdigit_l(*low, __l)) break;
1159 if (m & punct && iswpunct_l(*low, __l)) break;
1160 if (m & xdigit && iswxdigit_l(*low, __l)) break;
1161 if (m & blank && iswblank_l(*low, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001162#endif
1163 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001164 return low;
1165}
1166
1167const wchar_t*
1168ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1169{
1170 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001171 {
1172#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001173 if (!iswctype_l(*low, m, __l))
1174 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001175#else
1176 if (m & space && iswspace_l(*low, __l)) continue;
1177 if (m & print && iswprint_l(*low, __l)) continue;
1178 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1179 if (m & upper && iswupper_l(*low, __l)) continue;
1180 if (m & lower && iswlower_l(*low, __l)) continue;
1181 if (m & alpha && iswalpha_l(*low, __l)) continue;
1182 if (m & digit && iswdigit_l(*low, __l)) continue;
1183 if (m & punct && iswpunct_l(*low, __l)) continue;
1184 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1185 if (m & blank && iswblank_l(*low, __l)) continue;
1186 break;
1187#endif
1188 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001189 return low;
1190}
1191
1192wchar_t
1193ctype_byname<wchar_t>::do_toupper(char_type c) const
1194{
1195 return towupper_l(c, __l);
1196}
1197
1198const wchar_t*
1199ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1200{
1201 for (; low != high; ++low)
1202 *low = towupper_l(*low, __l);
1203 return low;
1204}
1205
1206wchar_t
1207ctype_byname<wchar_t>::do_tolower(char_type c) const
1208{
1209 return towlower_l(c, __l);
1210}
1211
1212const wchar_t*
1213ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1214{
1215 for (; low != high; ++low)
1216 *low = towlower_l(*low, __l);
1217 return low;
1218}
1219
1220wchar_t
1221ctype_byname<wchar_t>::do_widen(char c) const
1222{
Howard Hinnant866569b2011-09-28 23:39:33 +00001223#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001224 return btowc_l(c, __l);
1225#else
1226 return __btowc_l(c, __l);
1227#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001228}
1229
1230const char*
1231ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1232{
1233 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001234#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001235 *dest = btowc_l(*low, __l);
1236#else
1237 *dest = __btowc_l(*low, __l);
1238#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001239 return low;
1240}
1241
1242char
1243ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1244{
Howard Hinnant866569b2011-09-28 23:39:33 +00001245#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001246 int r = wctob_l(c, __l);
1247#else
1248 int r = __wctob_l(c, __l);
1249#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001250 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001251}
1252
1253const wchar_t*
1254ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1255{
1256 for (; low != high; ++low, ++dest)
1257 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001258#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001259 int r = wctob_l(*low, __l);
1260#else
1261 int r = __wctob_l(*low, __l);
1262#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001263 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001264 }
1265 return low;
1266}
1267
1268// template <> class codecvt<char, char, mbstate_t>
1269
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001270locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001271
1272codecvt<char, char, mbstate_t>::~codecvt()
1273{
1274}
1275
1276codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001277codecvt<char, char, mbstate_t>::do_out(state_type&,
1278 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001279 extern_type* to, extern_type*, extern_type*& to_nxt) const
1280{
1281 frm_nxt = frm;
1282 to_nxt = to;
1283 return noconv;
1284}
1285
1286codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001287codecvt<char, char, mbstate_t>::do_in(state_type&,
1288 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001289 intern_type* to, intern_type*, intern_type*& to_nxt) const
1290{
1291 frm_nxt = frm;
1292 to_nxt = to;
1293 return noconv;
1294}
1295
1296codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001297codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001298 extern_type* to, extern_type*, extern_type*& to_nxt) const
1299{
1300 to_nxt = to;
1301 return noconv;
1302}
1303
1304int
Howard Hinnantc9834542011-05-31 15:34:58 +00001305codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001306{
1307 return 1;
1308}
1309
1310bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001311codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001312{
1313 return true;
1314}
1315
1316int
1317codecvt<char, char, mbstate_t>::do_length(state_type&,
1318 const extern_type* frm, const extern_type* end, size_t mx) const
1319{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001320 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001321}
1322
1323int
Howard Hinnantc9834542011-05-31 15:34:58 +00001324codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001325{
1326 return 1;
1327}
1328
1329// template <> class codecvt<wchar_t, char, mbstate_t>
1330
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001331locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001332
1333codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1334 : locale::facet(refs),
1335 __l(0)
1336{
1337}
1338
1339codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1340 : locale::facet(refs),
1341 __l(newlocale(LC_ALL_MASK, nm, 0))
1342{
Howard Hinnantd4444702010-08-11 17:04:31 +00001343#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001344 if (__l == 0)
1345 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1346 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001347#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001348}
1349
1350codecvt<wchar_t, char, mbstate_t>::~codecvt()
1351{
1352 if (__l != 0)
1353 freelocale(__l);
1354}
1355
1356codecvt<wchar_t, char, mbstate_t>::result
1357codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001358 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001359 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1360{
1361 // look for first internal null in frm
1362 const intern_type* fend = frm;
1363 for (; fend != frm_end; ++fend)
1364 if (*fend == 0)
1365 break;
1366 // loop over all null-terminated sequences in frm
1367 to_nxt = to;
1368 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1369 {
1370 // save state in case needed to reover to_nxt on error
1371 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001372#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001373 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1374 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001375#else
1376 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1377#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001378 if (n == size_t(-1))
1379 {
1380 // need to recover to_nxt
1381 for (to_nxt = to; frm != frm_nxt; ++frm)
1382 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001383#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001384 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1385#else
1386 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1387#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001388 if (n == size_t(-1))
1389 break;
1390 to_nxt += n;
1391 }
1392 frm_nxt = frm;
1393 return error;
1394 }
1395 if (n == 0)
1396 return partial;
1397 to_nxt += n;
1398 if (to_nxt == to_end)
1399 break;
1400 if (fend != frm_end) // set up next null terminated sequence
1401 {
1402 // Try to write the terminating null
1403 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001404#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001405 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1406#else
1407 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1408#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001409 if (n == size_t(-1)) // on error
1410 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001411 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001412 return partial;
1413 for (extern_type* p = tmp; n; --n) // write it
1414 *to_nxt++ = *p++;
1415 ++frm_nxt;
1416 // look for next null in frm
1417 for (fend = frm_nxt; fend != frm_end; ++fend)
1418 if (*fend == 0)
1419 break;
1420 }
1421 }
1422 return frm_nxt == frm_end ? ok : partial;
1423}
1424
1425codecvt<wchar_t, char, mbstate_t>::result
1426codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001427 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001428 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1429{
1430 // look for first internal null in frm
1431 const extern_type* fend = frm;
1432 for (; fend != frm_end; ++fend)
1433 if (*fend == 0)
1434 break;
1435 // loop over all null-terminated sequences in frm
1436 to_nxt = to;
1437 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1438 {
1439 // save state in case needed to reover to_nxt on error
1440 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001441#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001442 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1443 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001444#else
1445 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1446#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001447 if (n == size_t(-1))
1448 {
1449 // need to recover to_nxt
1450 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1451 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001452#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001453 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1454 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001455#else
1456 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1457#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458 switch (n)
1459 {
1460 case 0:
1461 ++frm;
1462 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001463 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001464 frm_nxt = frm;
1465 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001466 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001467 frm_nxt = frm;
1468 return partial;
1469 default:
1470 frm += n;
1471 break;
1472 }
1473 }
1474 frm_nxt = frm;
1475 return frm_nxt == frm_end ? ok : partial;
1476 }
1477 if (n == 0)
1478 return error;
1479 to_nxt += n;
1480 if (to_nxt == to_end)
1481 break;
1482 if (fend != frm_end) // set up next null terminated sequence
1483 {
1484 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001485#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001486 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1487#else
1488 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1489#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001490 if (n != 0) // on error
1491 return error;
1492 ++to_nxt;
1493 ++frm_nxt;
1494 // look for next null in frm
1495 for (fend = frm_nxt; fend != frm_end; ++fend)
1496 if (*fend == 0)
1497 break;
1498 }
1499 }
1500 return frm_nxt == frm_end ? ok : partial;
1501}
1502
1503codecvt<wchar_t, char, mbstate_t>::result
1504codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1505 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1506{
1507 to_nxt = to;
1508 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001509#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001510 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1511#else
1512 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1513#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001514 if (n == size_t(-1) || n == 0) // on error
1515 return error;
1516 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001517 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001518 return partial;
1519 for (extern_type* p = tmp; n; --n) // write it
1520 *to_nxt++ = *p++;
1521 return ok;
1522}
1523
1524int
Howard Hinnantc9834542011-05-31 15:34:58 +00001525codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001526{
Howard Hinnant866569b2011-09-28 23:39:33 +00001527#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001528 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1529#else
1530 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1531#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 {
1533 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001534#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001535 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1536#else
1537 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1538#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001539 return 1; // which take more than 1 char to form a wchar_t
1540 return 0;
1541 }
1542 return -1;
1543}
1544
1545bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001546codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001547{
1548 return false;
1549}
1550
1551int
1552codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1553 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1554{
1555 int nbytes = 0;
1556 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1557 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001558#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001559 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001560#else
1561 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1562#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001563 switch (n)
1564 {
1565 case 0:
1566 ++nbytes;
1567 ++frm;
1568 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001569 case size_t(-1):
1570 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001571 return nbytes;
1572 default:
1573 nbytes += n;
1574 frm += n;
1575 break;
1576 }
1577 }
1578 return nbytes;
1579}
1580
1581int
Howard Hinnantc9834542011-05-31 15:34:58 +00001582codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001583{
Howard Hinnant866569b2011-09-28 23:39:33 +00001584#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001585 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1586#else
1587 return __l == 0 ? 1 : __mb_cur_max_l(__l);
1588#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001589}
1590
1591// Valid UTF ranges
1592// UTF-32 UTF-16 UTF-8 # of code points
1593// first second first second third fourth
1594// 000000 - 00007F 0000 - 007F 00 - 7F 127
1595// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1596// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1597// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1598// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1599// 00D800 - 00DFFF invalid
1600// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1601// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1602// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1603// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1604
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001605static
1606codecvt_base::result
1607utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1608 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1609 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1610{
1611 frm_nxt = frm;
1612 to_nxt = to;
1613 if (mode & generate_header)
1614 {
1615 if (to_end-to_nxt < 3)
1616 return codecvt_base::partial;
1617 *to_nxt++ = static_cast<uint8_t>(0xEF);
1618 *to_nxt++ = static_cast<uint8_t>(0xBB);
1619 *to_nxt++ = static_cast<uint8_t>(0xBF);
1620 }
1621 for (; frm_nxt < frm_end; ++frm_nxt)
1622 {
1623 uint16_t wc1 = *frm_nxt;
1624 if (wc1 > Maxcode)
1625 return codecvt_base::error;
1626 if (wc1 < 0x0080)
1627 {
1628 if (to_end-to_nxt < 1)
1629 return codecvt_base::partial;
1630 *to_nxt++ = static_cast<uint8_t>(wc1);
1631 }
1632 else if (wc1 < 0x0800)
1633 {
1634 if (to_end-to_nxt < 2)
1635 return codecvt_base::partial;
1636 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1637 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1638 }
1639 else if (wc1 < 0xD800)
1640 {
1641 if (to_end-to_nxt < 3)
1642 return codecvt_base::partial;
1643 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1644 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1645 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1646 }
1647 else if (wc1 < 0xDC00)
1648 {
1649 if (frm_end-frm_nxt < 2)
1650 return codecvt_base::partial;
1651 uint16_t wc2 = frm_nxt[1];
1652 if ((wc2 & 0xFC00) != 0xDC00)
1653 return codecvt_base::error;
1654 if (to_end-to_nxt < 4)
1655 return codecvt_base::partial;
1656 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1657 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1658 return codecvt_base::error;
1659 ++frm_nxt;
1660 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1661 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1662 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1663 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1664 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1665 }
1666 else if (wc1 < 0xE000)
1667 {
1668 return codecvt_base::error;
1669 }
1670 else
1671 {
1672 if (to_end-to_nxt < 3)
1673 return codecvt_base::partial;
1674 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1675 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1676 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1677 }
1678 }
1679 return codecvt_base::ok;
1680}
1681
1682static
1683codecvt_base::result
1684utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1685 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1686 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1687{
1688 frm_nxt = frm;
1689 to_nxt = to;
1690 if (mode & generate_header)
1691 {
1692 if (to_end-to_nxt < 3)
1693 return codecvt_base::partial;
1694 *to_nxt++ = static_cast<uint8_t>(0xEF);
1695 *to_nxt++ = static_cast<uint8_t>(0xBB);
1696 *to_nxt++ = static_cast<uint8_t>(0xBF);
1697 }
1698 for (; frm_nxt < frm_end; ++frm_nxt)
1699 {
1700 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1701 if (wc1 > Maxcode)
1702 return codecvt_base::error;
1703 if (wc1 < 0x0080)
1704 {
1705 if (to_end-to_nxt < 1)
1706 return codecvt_base::partial;
1707 *to_nxt++ = static_cast<uint8_t>(wc1);
1708 }
1709 else if (wc1 < 0x0800)
1710 {
1711 if (to_end-to_nxt < 2)
1712 return codecvt_base::partial;
1713 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1714 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1715 }
1716 else if (wc1 < 0xD800)
1717 {
1718 if (to_end-to_nxt < 3)
1719 return codecvt_base::partial;
1720 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1721 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1722 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1723 }
1724 else if (wc1 < 0xDC00)
1725 {
1726 if (frm_end-frm_nxt < 2)
1727 return codecvt_base::partial;
1728 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1729 if ((wc2 & 0xFC00) != 0xDC00)
1730 return codecvt_base::error;
1731 if (to_end-to_nxt < 4)
1732 return codecvt_base::partial;
1733 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1734 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1735 return codecvt_base::error;
1736 ++frm_nxt;
1737 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1738 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1739 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1740 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1741 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1742 }
1743 else if (wc1 < 0xE000)
1744 {
1745 return codecvt_base::error;
1746 }
1747 else
1748 {
1749 if (to_end-to_nxt < 3)
1750 return codecvt_base::partial;
1751 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1752 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1753 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1754 }
1755 }
1756 return codecvt_base::ok;
1757}
1758
1759static
1760codecvt_base::result
1761utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1762 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1763 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1764{
1765 frm_nxt = frm;
1766 to_nxt = to;
1767 if (mode & consume_header)
1768 {
1769 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1770 frm_nxt[2] == 0xBF)
1771 frm_nxt += 3;
1772 }
1773 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1774 {
1775 uint8_t c1 = *frm_nxt;
1776 if (c1 > Maxcode)
1777 return codecvt_base::error;
1778 if (c1 < 0x80)
1779 {
1780 *to_nxt = static_cast<uint16_t>(c1);
1781 ++frm_nxt;
1782 }
1783 else if (c1 < 0xC2)
1784 {
1785 return codecvt_base::error;
1786 }
1787 else if (c1 < 0xE0)
1788 {
1789 if (frm_end-frm_nxt < 2)
1790 return codecvt_base::partial;
1791 uint8_t c2 = frm_nxt[1];
1792 if ((c2 & 0xC0) != 0x80)
1793 return codecvt_base::error;
1794 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1795 if (t > Maxcode)
1796 return codecvt_base::error;
1797 *to_nxt = t;
1798 frm_nxt += 2;
1799 }
1800 else if (c1 < 0xF0)
1801 {
1802 if (frm_end-frm_nxt < 3)
1803 return codecvt_base::partial;
1804 uint8_t c2 = frm_nxt[1];
1805 uint8_t c3 = frm_nxt[2];
1806 switch (c1)
1807 {
1808 case 0xE0:
1809 if ((c2 & 0xE0) != 0xA0)
1810 return codecvt_base::error;
1811 break;
1812 case 0xED:
1813 if ((c2 & 0xE0) != 0x80)
1814 return codecvt_base::error;
1815 break;
1816 default:
1817 if ((c2 & 0xC0) != 0x80)
1818 return codecvt_base::error;
1819 break;
1820 }
1821 if ((c3 & 0xC0) != 0x80)
1822 return codecvt_base::error;
1823 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1824 | ((c2 & 0x3F) << 6)
1825 | (c3 & 0x3F));
1826 if (t > Maxcode)
1827 return codecvt_base::error;
1828 *to_nxt = t;
1829 frm_nxt += 3;
1830 }
1831 else if (c1 < 0xF5)
1832 {
1833 if (frm_end-frm_nxt < 4)
1834 return codecvt_base::partial;
1835 uint8_t c2 = frm_nxt[1];
1836 uint8_t c3 = frm_nxt[2];
1837 uint8_t c4 = frm_nxt[3];
1838 switch (c1)
1839 {
1840 case 0xF0:
1841 if (!(0x90 <= c2 && c2 <= 0xBF))
1842 return codecvt_base::error;
1843 break;
1844 case 0xF4:
1845 if ((c2 & 0xF0) != 0x80)
1846 return codecvt_base::error;
1847 break;
1848 default:
1849 if ((c2 & 0xC0) != 0x80)
1850 return codecvt_base::error;
1851 break;
1852 }
1853 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1854 return codecvt_base::error;
1855 if (to_end-to_nxt < 2)
1856 return codecvt_base::partial;
1857 if (((((unsigned long)c1 & 7) << 18) +
1858 (((unsigned long)c2 & 0x3F) << 12) +
1859 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1860 return codecvt_base::error;
1861 *to_nxt = static_cast<uint16_t>(
1862 0xD800
1863 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1864 | ((c2 & 0x0F) << 2)
1865 | ((c3 & 0x30) >> 4));
1866 *++to_nxt = static_cast<uint16_t>(
1867 0xDC00
1868 | ((c3 & 0x0F) << 6)
1869 | (c4 & 0x3F));
1870 frm_nxt += 4;
1871 }
1872 else
1873 {
1874 return codecvt_base::error;
1875 }
1876 }
1877 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1878}
1879
1880static
1881codecvt_base::result
1882utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1883 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1884 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1885{
1886 frm_nxt = frm;
1887 to_nxt = to;
1888 if (mode & consume_header)
1889 {
1890 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1891 frm_nxt[2] == 0xBF)
1892 frm_nxt += 3;
1893 }
1894 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1895 {
1896 uint8_t c1 = *frm_nxt;
1897 if (c1 > Maxcode)
1898 return codecvt_base::error;
1899 if (c1 < 0x80)
1900 {
1901 *to_nxt = static_cast<uint32_t>(c1);
1902 ++frm_nxt;
1903 }
1904 else if (c1 < 0xC2)
1905 {
1906 return codecvt_base::error;
1907 }
1908 else if (c1 < 0xE0)
1909 {
1910 if (frm_end-frm_nxt < 2)
1911 return codecvt_base::partial;
1912 uint8_t c2 = frm_nxt[1];
1913 if ((c2 & 0xC0) != 0x80)
1914 return codecvt_base::error;
1915 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1916 if (t > Maxcode)
1917 return codecvt_base::error;
1918 *to_nxt = static_cast<uint32_t>(t);
1919 frm_nxt += 2;
1920 }
1921 else if (c1 < 0xF0)
1922 {
1923 if (frm_end-frm_nxt < 3)
1924 return codecvt_base::partial;
1925 uint8_t c2 = frm_nxt[1];
1926 uint8_t c3 = frm_nxt[2];
1927 switch (c1)
1928 {
1929 case 0xE0:
1930 if ((c2 & 0xE0) != 0xA0)
1931 return codecvt_base::error;
1932 break;
1933 case 0xED:
1934 if ((c2 & 0xE0) != 0x80)
1935 return codecvt_base::error;
1936 break;
1937 default:
1938 if ((c2 & 0xC0) != 0x80)
1939 return codecvt_base::error;
1940 break;
1941 }
1942 if ((c3 & 0xC0) != 0x80)
1943 return codecvt_base::error;
1944 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1945 | ((c2 & 0x3F) << 6)
1946 | (c3 & 0x3F));
1947 if (t > Maxcode)
1948 return codecvt_base::error;
1949 *to_nxt = static_cast<uint32_t>(t);
1950 frm_nxt += 3;
1951 }
1952 else if (c1 < 0xF5)
1953 {
1954 if (frm_end-frm_nxt < 4)
1955 return codecvt_base::partial;
1956 uint8_t c2 = frm_nxt[1];
1957 uint8_t c3 = frm_nxt[2];
1958 uint8_t c4 = frm_nxt[3];
1959 switch (c1)
1960 {
1961 case 0xF0:
1962 if (!(0x90 <= c2 && c2 <= 0xBF))
1963 return codecvt_base::error;
1964 break;
1965 case 0xF4:
1966 if ((c2 & 0xF0) != 0x80)
1967 return codecvt_base::error;
1968 break;
1969 default:
1970 if ((c2 & 0xC0) != 0x80)
1971 return codecvt_base::error;
1972 break;
1973 }
1974 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1975 return codecvt_base::error;
1976 if (to_end-to_nxt < 2)
1977 return codecvt_base::partial;
1978 if (((((unsigned long)c1 & 7) << 18) +
1979 (((unsigned long)c2 & 0x3F) << 12) +
1980 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1981 return codecvt_base::error;
1982 *to_nxt = static_cast<uint32_t>(
1983 0xD800
1984 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1985 | ((c2 & 0x0F) << 2)
1986 | ((c3 & 0x30) >> 4));
1987 *++to_nxt = static_cast<uint32_t>(
1988 0xDC00
1989 | ((c3 & 0x0F) << 6)
1990 | (c4 & 0x3F));
1991 frm_nxt += 4;
1992 }
1993 else
1994 {
1995 return codecvt_base::error;
1996 }
1997 }
1998 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1999}
2000
2001static
2002int
2003utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2004 size_t mx, unsigned long Maxcode = 0x10FFFF,
2005 codecvt_mode mode = codecvt_mode(0))
2006{
2007 const uint8_t* frm_nxt = frm;
2008 if (mode & consume_header)
2009 {
2010 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2011 frm_nxt[2] == 0xBF)
2012 frm_nxt += 3;
2013 }
2014 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2015 {
2016 uint8_t c1 = *frm_nxt;
2017 if (c1 > Maxcode)
2018 break;
2019 if (c1 < 0x80)
2020 {
2021 ++frm_nxt;
2022 }
2023 else if (c1 < 0xC2)
2024 {
2025 break;
2026 }
2027 else if (c1 < 0xE0)
2028 {
2029 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2030 break;
2031 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2032 if (t > Maxcode)
2033 break;
2034 frm_nxt += 2;
2035 }
2036 else if (c1 < 0xF0)
2037 {
2038 if (frm_end-frm_nxt < 3)
2039 break;
2040 uint8_t c2 = frm_nxt[1];
2041 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002042 switch (c1)
2043 {
2044 case 0xE0:
2045 if ((c2 & 0xE0) != 0xA0)
2046 return static_cast<int>(frm_nxt - frm);
2047 break;
2048 case 0xED:
2049 if ((c2 & 0xE0) != 0x80)
2050 return static_cast<int>(frm_nxt - frm);
2051 break;
2052 default:
2053 if ((c2 & 0xC0) != 0x80)
2054 return static_cast<int>(frm_nxt - frm);
2055 break;
2056 }
2057 if ((c3 & 0xC0) != 0x80)
2058 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002059 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002060 break;
2061 frm_nxt += 3;
2062 }
2063 else if (c1 < 0xF5)
2064 {
2065 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2066 break;
2067 uint8_t c2 = frm_nxt[1];
2068 uint8_t c3 = frm_nxt[2];
2069 uint8_t c4 = frm_nxt[3];
2070 switch (c1)
2071 {
2072 case 0xF0:
2073 if (!(0x90 <= c2 && c2 <= 0xBF))
2074 return static_cast<int>(frm_nxt - frm);
2075 break;
2076 case 0xF4:
2077 if ((c2 & 0xF0) != 0x80)
2078 return static_cast<int>(frm_nxt - frm);
2079 break;
2080 default:
2081 if ((c2 & 0xC0) != 0x80)
2082 return static_cast<int>(frm_nxt - frm);
2083 break;
2084 }
2085 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2086 break;
2087 if (((((unsigned long)c1 & 7) << 18) +
2088 (((unsigned long)c2 & 0x3F) << 12) +
2089 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2090 break;
2091 ++nchar16_t;
2092 frm_nxt += 4;
2093 }
2094 else
2095 {
2096 break;
2097 }
2098 }
2099 return static_cast<int>(frm_nxt - frm);
2100}
2101
2102static
2103codecvt_base::result
2104ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2105 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2106 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2107{
2108 frm_nxt = frm;
2109 to_nxt = to;
2110 if (mode & generate_header)
2111 {
2112 if (to_end-to_nxt < 3)
2113 return codecvt_base::partial;
2114 *to_nxt++ = static_cast<uint8_t>(0xEF);
2115 *to_nxt++ = static_cast<uint8_t>(0xBB);
2116 *to_nxt++ = static_cast<uint8_t>(0xBF);
2117 }
2118 for (; frm_nxt < frm_end; ++frm_nxt)
2119 {
2120 uint32_t wc = *frm_nxt;
2121 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2122 return codecvt_base::error;
2123 if (wc < 0x000080)
2124 {
2125 if (to_end-to_nxt < 1)
2126 return codecvt_base::partial;
2127 *to_nxt++ = static_cast<uint8_t>(wc);
2128 }
2129 else if (wc < 0x000800)
2130 {
2131 if (to_end-to_nxt < 2)
2132 return codecvt_base::partial;
2133 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2134 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2135 }
2136 else if (wc < 0x010000)
2137 {
2138 if (to_end-to_nxt < 3)
2139 return codecvt_base::partial;
2140 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2141 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2142 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2143 }
2144 else // if (wc < 0x110000)
2145 {
2146 if (to_end-to_nxt < 4)
2147 return codecvt_base::partial;
2148 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2149 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2150 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2151 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2152 }
2153 }
2154 return codecvt_base::ok;
2155}
2156
2157static
2158codecvt_base::result
2159utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2160 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2161 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2162{
2163 frm_nxt = frm;
2164 to_nxt = to;
2165 if (mode & consume_header)
2166 {
2167 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2168 frm_nxt[2] == 0xBF)
2169 frm_nxt += 3;
2170 }
2171 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2172 {
2173 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2174 if (c1 < 0x80)
2175 {
2176 if (c1 > Maxcode)
2177 return codecvt_base::error;
2178 *to_nxt = static_cast<uint32_t>(c1);
2179 ++frm_nxt;
2180 }
2181 else if (c1 < 0xC2)
2182 {
2183 return codecvt_base::error;
2184 }
2185 else if (c1 < 0xE0)
2186 {
2187 if (frm_end-frm_nxt < 2)
2188 return codecvt_base::partial;
2189 uint8_t c2 = frm_nxt[1];
2190 if ((c2 & 0xC0) != 0x80)
2191 return codecvt_base::error;
2192 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2193 | (c2 & 0x3F));
2194 if (t > Maxcode)
2195 return codecvt_base::error;
2196 *to_nxt = t;
2197 frm_nxt += 2;
2198 }
2199 else if (c1 < 0xF0)
2200 {
2201 if (frm_end-frm_nxt < 3)
2202 return codecvt_base::partial;
2203 uint8_t c2 = frm_nxt[1];
2204 uint8_t c3 = frm_nxt[2];
2205 switch (c1)
2206 {
2207 case 0xE0:
2208 if ((c2 & 0xE0) != 0xA0)
2209 return codecvt_base::error;
2210 break;
2211 case 0xED:
2212 if ((c2 & 0xE0) != 0x80)
2213 return codecvt_base::error;
2214 break;
2215 default:
2216 if ((c2 & 0xC0) != 0x80)
2217 return codecvt_base::error;
2218 break;
2219 }
2220 if ((c3 & 0xC0) != 0x80)
2221 return codecvt_base::error;
2222 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2223 | ((c2 & 0x3F) << 6)
2224 | (c3 & 0x3F));
2225 if (t > Maxcode)
2226 return codecvt_base::error;
2227 *to_nxt = t;
2228 frm_nxt += 3;
2229 }
2230 else if (c1 < 0xF5)
2231 {
2232 if (frm_end-frm_nxt < 4)
2233 return codecvt_base::partial;
2234 uint8_t c2 = frm_nxt[1];
2235 uint8_t c3 = frm_nxt[2];
2236 uint8_t c4 = frm_nxt[3];
2237 switch (c1)
2238 {
2239 case 0xF0:
2240 if (!(0x90 <= c2 && c2 <= 0xBF))
2241 return codecvt_base::error;
2242 break;
2243 case 0xF4:
2244 if ((c2 & 0xF0) != 0x80)
2245 return codecvt_base::error;
2246 break;
2247 default:
2248 if ((c2 & 0xC0) != 0x80)
2249 return codecvt_base::error;
2250 break;
2251 }
2252 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2253 return codecvt_base::error;
2254 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2255 | ((c2 & 0x3F) << 12)
2256 | ((c3 & 0x3F) << 6)
2257 | (c4 & 0x3F));
2258 if (t > Maxcode)
2259 return codecvt_base::error;
2260 *to_nxt = t;
2261 frm_nxt += 4;
2262 }
2263 else
2264 {
2265 return codecvt_base::error;
2266 }
2267 }
2268 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2269}
2270
2271static
2272int
2273utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2274 size_t mx, unsigned long Maxcode = 0x10FFFF,
2275 codecvt_mode mode = codecvt_mode(0))
2276{
2277 const uint8_t* frm_nxt = frm;
2278 if (mode & consume_header)
2279 {
2280 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2281 frm_nxt[2] == 0xBF)
2282 frm_nxt += 3;
2283 }
2284 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2285 {
2286 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2287 if (c1 < 0x80)
2288 {
2289 if (c1 > Maxcode)
2290 break;
2291 ++frm_nxt;
2292 }
2293 else if (c1 < 0xC2)
2294 {
2295 break;
2296 }
2297 else if (c1 < 0xE0)
2298 {
2299 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2300 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002301 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002302 break;
2303 frm_nxt += 2;
2304 }
2305 else if (c1 < 0xF0)
2306 {
2307 if (frm_end-frm_nxt < 3)
2308 break;
2309 uint8_t c2 = frm_nxt[1];
2310 uint8_t c3 = frm_nxt[2];
2311 switch (c1)
2312 {
2313 case 0xE0:
2314 if ((c2 & 0xE0) != 0xA0)
2315 return static_cast<int>(frm_nxt - frm);
2316 break;
2317 case 0xED:
2318 if ((c2 & 0xE0) != 0x80)
2319 return static_cast<int>(frm_nxt - frm);
2320 break;
2321 default:
2322 if ((c2 & 0xC0) != 0x80)
2323 return static_cast<int>(frm_nxt - frm);
2324 break;
2325 }
2326 if ((c3 & 0xC0) != 0x80)
2327 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002328 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002329 break;
2330 frm_nxt += 3;
2331 }
2332 else if (c1 < 0xF5)
2333 {
2334 if (frm_end-frm_nxt < 4)
2335 break;
2336 uint8_t c2 = frm_nxt[1];
2337 uint8_t c3 = frm_nxt[2];
2338 uint8_t c4 = frm_nxt[3];
2339 switch (c1)
2340 {
2341 case 0xF0:
2342 if (!(0x90 <= c2 && c2 <= 0xBF))
2343 return static_cast<int>(frm_nxt - frm);
2344 break;
2345 case 0xF4:
2346 if ((c2 & 0xF0) != 0x80)
2347 return static_cast<int>(frm_nxt - frm);
2348 break;
2349 default:
2350 if ((c2 & 0xC0) != 0x80)
2351 return static_cast<int>(frm_nxt - frm);
2352 break;
2353 }
2354 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2355 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002356 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2357 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002358 break;
2359 frm_nxt += 4;
2360 }
2361 else
2362 {
2363 break;
2364 }
2365 }
2366 return static_cast<int>(frm_nxt - frm);
2367}
2368
2369static
2370codecvt_base::result
2371ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2372 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2373 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2374{
2375 frm_nxt = frm;
2376 to_nxt = to;
2377 if (mode & generate_header)
2378 {
2379 if (to_end-to_nxt < 3)
2380 return codecvt_base::partial;
2381 *to_nxt++ = static_cast<uint8_t>(0xEF);
2382 *to_nxt++ = static_cast<uint8_t>(0xBB);
2383 *to_nxt++ = static_cast<uint8_t>(0xBF);
2384 }
2385 for (; frm_nxt < frm_end; ++frm_nxt)
2386 {
2387 uint16_t wc = *frm_nxt;
2388 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2389 return codecvt_base::error;
2390 if (wc < 0x0080)
2391 {
2392 if (to_end-to_nxt < 1)
2393 return codecvt_base::partial;
2394 *to_nxt++ = static_cast<uint8_t>(wc);
2395 }
2396 else if (wc < 0x0800)
2397 {
2398 if (to_end-to_nxt < 2)
2399 return codecvt_base::partial;
2400 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2401 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2402 }
2403 else // if (wc <= 0xFFFF)
2404 {
2405 if (to_end-to_nxt < 3)
2406 return codecvt_base::partial;
2407 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2408 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2409 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2410 }
2411 }
2412 return codecvt_base::ok;
2413}
2414
2415static
2416codecvt_base::result
2417utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2418 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2419 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2420{
2421 frm_nxt = frm;
2422 to_nxt = to;
2423 if (mode & consume_header)
2424 {
2425 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2426 frm_nxt[2] == 0xBF)
2427 frm_nxt += 3;
2428 }
2429 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2430 {
2431 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2432 if (c1 < 0x80)
2433 {
2434 if (c1 > Maxcode)
2435 return codecvt_base::error;
2436 *to_nxt = static_cast<uint16_t>(c1);
2437 ++frm_nxt;
2438 }
2439 else if (c1 < 0xC2)
2440 {
2441 return codecvt_base::error;
2442 }
2443 else if (c1 < 0xE0)
2444 {
2445 if (frm_end-frm_nxt < 2)
2446 return codecvt_base::partial;
2447 uint8_t c2 = frm_nxt[1];
2448 if ((c2 & 0xC0) != 0x80)
2449 return codecvt_base::error;
2450 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2451 | (c2 & 0x3F));
2452 if (t > Maxcode)
2453 return codecvt_base::error;
2454 *to_nxt = t;
2455 frm_nxt += 2;
2456 }
2457 else if (c1 < 0xF0)
2458 {
2459 if (frm_end-frm_nxt < 3)
2460 return codecvt_base::partial;
2461 uint8_t c2 = frm_nxt[1];
2462 uint8_t c3 = frm_nxt[2];
2463 switch (c1)
2464 {
2465 case 0xE0:
2466 if ((c2 & 0xE0) != 0xA0)
2467 return codecvt_base::error;
2468 break;
2469 case 0xED:
2470 if ((c2 & 0xE0) != 0x80)
2471 return codecvt_base::error;
2472 break;
2473 default:
2474 if ((c2 & 0xC0) != 0x80)
2475 return codecvt_base::error;
2476 break;
2477 }
2478 if ((c3 & 0xC0) != 0x80)
2479 return codecvt_base::error;
2480 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2481 | ((c2 & 0x3F) << 6)
2482 | (c3 & 0x3F));
2483 if (t > Maxcode)
2484 return codecvt_base::error;
2485 *to_nxt = t;
2486 frm_nxt += 3;
2487 }
2488 else
2489 {
2490 return codecvt_base::error;
2491 }
2492 }
2493 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2494}
2495
2496static
2497int
2498utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2499 size_t mx, unsigned long Maxcode = 0x10FFFF,
2500 codecvt_mode mode = codecvt_mode(0))
2501{
2502 const uint8_t* frm_nxt = frm;
2503 if (mode & consume_header)
2504 {
2505 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2506 frm_nxt[2] == 0xBF)
2507 frm_nxt += 3;
2508 }
2509 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2510 {
2511 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2512 if (c1 < 0x80)
2513 {
2514 if (c1 > Maxcode)
2515 break;
2516 ++frm_nxt;
2517 }
2518 else if (c1 < 0xC2)
2519 {
2520 break;
2521 }
2522 else if (c1 < 0xE0)
2523 {
2524 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2525 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002526 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002527 break;
2528 frm_nxt += 2;
2529 }
2530 else if (c1 < 0xF0)
2531 {
2532 if (frm_end-frm_nxt < 3)
2533 break;
2534 uint8_t c2 = frm_nxt[1];
2535 uint8_t c3 = frm_nxt[2];
2536 switch (c1)
2537 {
2538 case 0xE0:
2539 if ((c2 & 0xE0) != 0xA0)
2540 return static_cast<int>(frm_nxt - frm);
2541 break;
2542 case 0xED:
2543 if ((c2 & 0xE0) != 0x80)
2544 return static_cast<int>(frm_nxt - frm);
2545 break;
2546 default:
2547 if ((c2 & 0xC0) != 0x80)
2548 return static_cast<int>(frm_nxt - frm);
2549 break;
2550 }
2551 if ((c3 & 0xC0) != 0x80)
2552 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002553 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002554 break;
2555 frm_nxt += 3;
2556 }
2557 else
2558 {
2559 break;
2560 }
2561 }
2562 return static_cast<int>(frm_nxt - frm);
2563}
2564
2565static
2566codecvt_base::result
2567ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2568 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2569 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2570{
2571 frm_nxt = frm;
2572 to_nxt = to;
2573 if (mode & generate_header)
2574 {
2575 if (to_end-to_nxt < 2)
2576 return codecvt_base::partial;
2577 *to_nxt++ = static_cast<uint8_t>(0xFE);
2578 *to_nxt++ = static_cast<uint8_t>(0xFF);
2579 }
2580 for (; frm_nxt < frm_end; ++frm_nxt)
2581 {
2582 uint32_t wc = *frm_nxt;
2583 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2584 return codecvt_base::error;
2585 if (wc < 0x010000)
2586 {
2587 if (to_end-to_nxt < 2)
2588 return codecvt_base::partial;
2589 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2590 *to_nxt++ = static_cast<uint8_t>(wc);
2591 }
2592 else
2593 {
2594 if (to_end-to_nxt < 4)
2595 return codecvt_base::partial;
2596 uint16_t t = static_cast<uint16_t>(
2597 0xD800
2598 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2599 | ((wc & 0x00FC00) >> 10));
2600 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2601 *to_nxt++ = static_cast<uint8_t>(t);
2602 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2603 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2604 *to_nxt++ = static_cast<uint8_t>(t);
2605 }
2606 }
2607 return codecvt_base::ok;
2608}
2609
2610static
2611codecvt_base::result
2612utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2613 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2614 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2615{
2616 frm_nxt = frm;
2617 to_nxt = to;
2618 if (mode & consume_header)
2619 {
2620 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2621 frm_nxt += 2;
2622 }
2623 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2624 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002625 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002626 if ((c1 & 0xFC00) == 0xDC00)
2627 return codecvt_base::error;
2628 if ((c1 & 0xFC00) != 0xD800)
2629 {
2630 if (c1 > Maxcode)
2631 return codecvt_base::error;
2632 *to_nxt = static_cast<uint32_t>(c1);
2633 frm_nxt += 2;
2634 }
2635 else
2636 {
2637 if (frm_end-frm_nxt < 4)
2638 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002639 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002640 if ((c2 & 0xFC00) != 0xDC00)
2641 return codecvt_base::error;
2642 uint32_t t = static_cast<uint32_t>(
2643 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2644 | ((c1 & 0x003F) << 10)
2645 | (c2 & 0x03FF));
2646 if (t > Maxcode)
2647 return codecvt_base::error;
2648 *to_nxt = t;
2649 frm_nxt += 4;
2650 }
2651 }
2652 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2653}
2654
2655static
2656int
2657utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2658 size_t mx, unsigned long Maxcode = 0x10FFFF,
2659 codecvt_mode mode = codecvt_mode(0))
2660{
2661 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002662 if (mode & consume_header)
2663 {
2664 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2665 frm_nxt += 2;
2666 }
2667 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2668 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002669 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002670 if ((c1 & 0xFC00) == 0xDC00)
2671 break;
2672 if ((c1 & 0xFC00) != 0xD800)
2673 {
2674 if (c1 > Maxcode)
2675 break;
2676 frm_nxt += 2;
2677 }
2678 else
2679 {
2680 if (frm_end-frm_nxt < 4)
2681 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002682 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002683 if ((c2 & 0xFC00) != 0xDC00)
2684 break;
2685 uint32_t t = static_cast<uint32_t>(
2686 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2687 | ((c1 & 0x003F) << 10)
2688 | (c2 & 0x03FF));
2689 if (t > Maxcode)
2690 break;
2691 frm_nxt += 4;
2692 }
2693 }
2694 return static_cast<int>(frm_nxt - frm);
2695}
2696
2697static
2698codecvt_base::result
2699ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2700 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2701 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2702{
2703 frm_nxt = frm;
2704 to_nxt = to;
2705 if (mode & generate_header)
2706 {
2707 if (to_end-to_nxt < 2)
2708 return codecvt_base::partial;
2709 *to_nxt++ = static_cast<uint8_t>(0xFF);
2710 *to_nxt++ = static_cast<uint8_t>(0xFE);
2711 }
2712 for (; frm_nxt < frm_end; ++frm_nxt)
2713 {
2714 uint32_t wc = *frm_nxt;
2715 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2716 return codecvt_base::error;
2717 if (wc < 0x010000)
2718 {
2719 if (to_end-to_nxt < 2)
2720 return codecvt_base::partial;
2721 *to_nxt++ = static_cast<uint8_t>(wc);
2722 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2723 }
2724 else
2725 {
2726 if (to_end-to_nxt < 4)
2727 return codecvt_base::partial;
2728 uint16_t t = static_cast<uint16_t>(
2729 0xD800
2730 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2731 | ((wc & 0x00FC00) >> 10));
2732 *to_nxt++ = static_cast<uint8_t>(t);
2733 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2734 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2735 *to_nxt++ = static_cast<uint8_t>(t);
2736 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2737 }
2738 }
2739 return codecvt_base::ok;
2740}
2741
2742static
2743codecvt_base::result
2744utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2745 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2746 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2747{
2748 frm_nxt = frm;
2749 to_nxt = to;
2750 if (mode & consume_header)
2751 {
2752 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2753 frm_nxt += 2;
2754 }
2755 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2756 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002757 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002758 if ((c1 & 0xFC00) == 0xDC00)
2759 return codecvt_base::error;
2760 if ((c1 & 0xFC00) != 0xD800)
2761 {
2762 if (c1 > Maxcode)
2763 return codecvt_base::error;
2764 *to_nxt = static_cast<uint32_t>(c1);
2765 frm_nxt += 2;
2766 }
2767 else
2768 {
2769 if (frm_end-frm_nxt < 4)
2770 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002771 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002772 if ((c2 & 0xFC00) != 0xDC00)
2773 return codecvt_base::error;
2774 uint32_t t = static_cast<uint32_t>(
2775 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2776 | ((c1 & 0x003F) << 10)
2777 | (c2 & 0x03FF));
2778 if (t > Maxcode)
2779 return codecvt_base::error;
2780 *to_nxt = t;
2781 frm_nxt += 4;
2782 }
2783 }
2784 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2785}
2786
2787static
2788int
2789utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2790 size_t mx, unsigned long Maxcode = 0x10FFFF,
2791 codecvt_mode mode = codecvt_mode(0))
2792{
2793 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002794 if (mode & consume_header)
2795 {
2796 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2797 frm_nxt += 2;
2798 }
2799 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2800 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002801 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002802 if ((c1 & 0xFC00) == 0xDC00)
2803 break;
2804 if ((c1 & 0xFC00) != 0xD800)
2805 {
2806 if (c1 > Maxcode)
2807 break;
2808 frm_nxt += 2;
2809 }
2810 else
2811 {
2812 if (frm_end-frm_nxt < 4)
2813 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002814 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002815 if ((c2 & 0xFC00) != 0xDC00)
2816 break;
2817 uint32_t t = static_cast<uint32_t>(
2818 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2819 | ((c1 & 0x003F) << 10)
2820 | (c2 & 0x03FF));
2821 if (t > Maxcode)
2822 break;
2823 frm_nxt += 4;
2824 }
2825 }
2826 return static_cast<int>(frm_nxt - frm);
2827}
2828
2829static
2830codecvt_base::result
2831ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2832 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2833 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2834{
2835 frm_nxt = frm;
2836 to_nxt = to;
2837 if (mode & generate_header)
2838 {
2839 if (to_end-to_nxt < 2)
2840 return codecvt_base::partial;
2841 *to_nxt++ = static_cast<uint8_t>(0xFE);
2842 *to_nxt++ = static_cast<uint8_t>(0xFF);
2843 }
2844 for (; frm_nxt < frm_end; ++frm_nxt)
2845 {
2846 uint16_t wc = *frm_nxt;
2847 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2848 return codecvt_base::error;
2849 if (to_end-to_nxt < 2)
2850 return codecvt_base::partial;
2851 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2852 *to_nxt++ = static_cast<uint8_t>(wc);
2853 }
2854 return codecvt_base::ok;
2855}
2856
2857static
2858codecvt_base::result
2859utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2860 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2861 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2862{
2863 frm_nxt = frm;
2864 to_nxt = to;
2865 if (mode & consume_header)
2866 {
2867 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2868 frm_nxt += 2;
2869 }
2870 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2871 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002872 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002873 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2874 return codecvt_base::error;
2875 *to_nxt = c1;
2876 frm_nxt += 2;
2877 }
2878 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2879}
2880
2881static
2882int
2883utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2884 size_t mx, unsigned long Maxcode = 0x10FFFF,
2885 codecvt_mode mode = codecvt_mode(0))
2886{
2887 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002888 if (mode & consume_header)
2889 {
2890 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2891 frm_nxt += 2;
2892 }
2893 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2894 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002895 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002896 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2897 break;
2898 frm_nxt += 2;
2899 }
2900 return static_cast<int>(frm_nxt - frm);
2901}
2902
2903static
2904codecvt_base::result
2905ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2906 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2907 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2908{
2909 frm_nxt = frm;
2910 to_nxt = to;
2911 if (mode & generate_header)
2912 {
2913 if (to_end-to_nxt < 2)
2914 return codecvt_base::partial;
2915 *to_nxt++ = static_cast<uint8_t>(0xFF);
2916 *to_nxt++ = static_cast<uint8_t>(0xFE);
2917 }
2918 for (; frm_nxt < frm_end; ++frm_nxt)
2919 {
2920 uint16_t wc = *frm_nxt;
2921 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2922 return codecvt_base::error;
2923 if (to_end-to_nxt < 2)
2924 return codecvt_base::partial;
2925 *to_nxt++ = static_cast<uint8_t>(wc);
2926 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2927 }
2928 return codecvt_base::ok;
2929}
2930
2931static
2932codecvt_base::result
2933utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2934 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2935 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2936{
2937 frm_nxt = frm;
2938 to_nxt = to;
2939 if (mode & consume_header)
2940 {
2941 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2942 frm_nxt += 2;
2943 }
2944 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2945 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002946 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002947 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2948 return codecvt_base::error;
2949 *to_nxt = c1;
2950 frm_nxt += 2;
2951 }
2952 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2953}
2954
2955static
2956int
2957utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2958 size_t mx, unsigned long Maxcode = 0x10FFFF,
2959 codecvt_mode mode = codecvt_mode(0))
2960{
2961 const uint8_t* frm_nxt = frm;
2962 frm_nxt = frm;
2963 if (mode & consume_header)
2964 {
2965 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2966 frm_nxt += 2;
2967 }
2968 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2969 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002970 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002971 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2972 break;
2973 frm_nxt += 2;
2974 }
2975 return static_cast<int>(frm_nxt - frm);
2976}
2977
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002978// template <> class codecvt<char16_t, char, mbstate_t>
2979
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002980locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002981
2982codecvt<char16_t, char, mbstate_t>::~codecvt()
2983{
2984}
2985
2986codecvt<char16_t, char, mbstate_t>::result
2987codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002988 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002989 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2990{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002991 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2992 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2993 const uint16_t* _frm_nxt = _frm;
2994 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2995 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2996 uint8_t* _to_nxt = _to;
2997 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2998 frm_nxt = frm + (_frm_nxt - _frm);
2999 to_nxt = to + (_to_nxt - _to);
3000 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003001}
3002
3003codecvt<char16_t, char, mbstate_t>::result
3004codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003005 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003006 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3007{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003008 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3009 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3010 const uint8_t* _frm_nxt = _frm;
3011 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3012 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3013 uint16_t* _to_nxt = _to;
3014 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3015 frm_nxt = frm + (_frm_nxt - _frm);
3016 to_nxt = to + (_to_nxt - _to);
3017 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003018}
3019
3020codecvt<char16_t, char, mbstate_t>::result
3021codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3022 extern_type* to, extern_type*, extern_type*& to_nxt) const
3023{
3024 to_nxt = to;
3025 return noconv;
3026}
3027
3028int
Howard Hinnantc9834542011-05-31 15:34:58 +00003029codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003030{
3031 return 0;
3032}
3033
3034bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003035codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003036{
3037 return false;
3038}
3039
3040int
3041codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3042 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3043{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003044 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3045 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3046 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003047}
3048
3049int
Howard Hinnantc9834542011-05-31 15:34:58 +00003050codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003051{
3052 return 4;
3053}
3054
3055// template <> class codecvt<char32_t, char, mbstate_t>
3056
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003057locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003058
3059codecvt<char32_t, char, mbstate_t>::~codecvt()
3060{
3061}
3062
3063codecvt<char32_t, char, mbstate_t>::result
3064codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003065 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003066 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3067{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003068 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3069 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3070 const uint32_t* _frm_nxt = _frm;
3071 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3072 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3073 uint8_t* _to_nxt = _to;
3074 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3075 frm_nxt = frm + (_frm_nxt - _frm);
3076 to_nxt = to + (_to_nxt - _to);
3077 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003078}
3079
3080codecvt<char32_t, char, mbstate_t>::result
3081codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003082 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003083 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3084{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003085 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3086 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3087 const uint8_t* _frm_nxt = _frm;
3088 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3089 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3090 uint32_t* _to_nxt = _to;
3091 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3092 frm_nxt = frm + (_frm_nxt - _frm);
3093 to_nxt = to + (_to_nxt - _to);
3094 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003095}
3096
3097codecvt<char32_t, char, mbstate_t>::result
3098codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3099 extern_type* to, extern_type*, extern_type*& to_nxt) const
3100{
3101 to_nxt = to;
3102 return noconv;
3103}
3104
3105int
Howard Hinnantc9834542011-05-31 15:34:58 +00003106codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003107{
3108 return 0;
3109}
3110
3111bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003112codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003113{
3114 return false;
3115}
3116
3117int
3118codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3119 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3120{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003121 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3122 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3123 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003124}
3125
3126int
Howard Hinnantc9834542011-05-31 15:34:58 +00003127codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003128{
3129 return 4;
3130}
3131
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003132// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003133
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003134__codecvt_utf8<wchar_t>::result
3135__codecvt_utf8<wchar_t>::do_out(state_type&,
3136 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003137 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3138{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003139 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3140 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3141 const uint32_t* _frm_nxt = _frm;
3142 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3143 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3144 uint8_t* _to_nxt = _to;
3145 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3146 _Maxcode_, _Mode_);
3147 frm_nxt = frm + (_frm_nxt - _frm);
3148 to_nxt = to + (_to_nxt - _to);
3149 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003150}
3151
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003152__codecvt_utf8<wchar_t>::result
3153__codecvt_utf8<wchar_t>::do_in(state_type&,
3154 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003155 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3156{
Howard Hinnant87d1a8a2010-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 _Maxcode_, _Mode_);
3165 frm_nxt = frm + (_frm_nxt - _frm);
3166 to_nxt = to + (_to_nxt - _to);
3167 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003168}
3169
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003170__codecvt_utf8<wchar_t>::result
3171__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003172 extern_type* to, extern_type*, extern_type*& to_nxt) const
3173{
3174 to_nxt = to;
3175 return noconv;
3176}
3177
3178int
Howard Hinnantc9834542011-05-31 15:34:58 +00003179__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003180{
3181 return 0;
3182}
3183
3184bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003185__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003186{
3187 return false;
3188}
3189
3190int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003191__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003192 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3193{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003194 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3195 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3196 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003197}
3198
3199int
Howard Hinnantc9834542011-05-31 15:34:58 +00003200__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003201{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003202 if (_Mode_ & consume_header)
3203 return 7;
3204 return 4;
3205}
3206
3207// __codecvt_utf8<char16_t>
3208
3209__codecvt_utf8<char16_t>::result
3210__codecvt_utf8<char16_t>::do_out(state_type&,
3211 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3212 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3213{
3214 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3215 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3216 const uint16_t* _frm_nxt = _frm;
3217 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3218 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3219 uint8_t* _to_nxt = _to;
3220 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3221 _Maxcode_, _Mode_);
3222 frm_nxt = frm + (_frm_nxt - _frm);
3223 to_nxt = to + (_to_nxt - _to);
3224 return r;
3225}
3226
3227__codecvt_utf8<char16_t>::result
3228__codecvt_utf8<char16_t>::do_in(state_type&,
3229 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3230 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3231{
3232 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3233 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3234 const uint8_t* _frm_nxt = _frm;
3235 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3236 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3237 uint16_t* _to_nxt = _to;
3238 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3239 _Maxcode_, _Mode_);
3240 frm_nxt = frm + (_frm_nxt - _frm);
3241 to_nxt = to + (_to_nxt - _to);
3242 return r;
3243}
3244
3245__codecvt_utf8<char16_t>::result
3246__codecvt_utf8<char16_t>::do_unshift(state_type&,
3247 extern_type* to, extern_type*, extern_type*& to_nxt) const
3248{
3249 to_nxt = to;
3250 return noconv;
3251}
3252
3253int
Howard Hinnantc9834542011-05-31 15:34:58 +00003254__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003255{
3256 return 0;
3257}
3258
3259bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003260__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003261{
3262 return false;
3263}
3264
3265int
3266__codecvt_utf8<char16_t>::do_length(state_type&,
3267 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3268{
3269 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3270 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3271 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3272}
3273
3274int
Howard Hinnantc9834542011-05-31 15:34:58 +00003275__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003276{
3277 if (_Mode_ & consume_header)
3278 return 6;
3279 return 3;
3280}
3281
3282// __codecvt_utf8<char32_t>
3283
3284__codecvt_utf8<char32_t>::result
3285__codecvt_utf8<char32_t>::do_out(state_type&,
3286 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3287 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3288{
3289 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3290 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3291 const uint32_t* _frm_nxt = _frm;
3292 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3293 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3294 uint8_t* _to_nxt = _to;
3295 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3296 _Maxcode_, _Mode_);
3297 frm_nxt = frm + (_frm_nxt - _frm);
3298 to_nxt = to + (_to_nxt - _to);
3299 return r;
3300}
3301
3302__codecvt_utf8<char32_t>::result
3303__codecvt_utf8<char32_t>::do_in(state_type&,
3304 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3305 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3306{
3307 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3308 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3309 const uint8_t* _frm_nxt = _frm;
3310 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3311 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3312 uint32_t* _to_nxt = _to;
3313 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3314 _Maxcode_, _Mode_);
3315 frm_nxt = frm + (_frm_nxt - _frm);
3316 to_nxt = to + (_to_nxt - _to);
3317 return r;
3318}
3319
3320__codecvt_utf8<char32_t>::result
3321__codecvt_utf8<char32_t>::do_unshift(state_type&,
3322 extern_type* to, extern_type*, extern_type*& to_nxt) const
3323{
3324 to_nxt = to;
3325 return noconv;
3326}
3327
3328int
Howard Hinnantc9834542011-05-31 15:34:58 +00003329__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003330{
3331 return 0;
3332}
3333
3334bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003335__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003336{
3337 return false;
3338}
3339
3340int
3341__codecvt_utf8<char32_t>::do_length(state_type&,
3342 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3343{
3344 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3345 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3346 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3347}
3348
3349int
Howard Hinnantc9834542011-05-31 15:34:58 +00003350__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003351{
3352 if (_Mode_ & consume_header)
3353 return 7;
3354 return 4;
3355}
3356
3357// __codecvt_utf16<wchar_t, false>
3358
3359__codecvt_utf16<wchar_t, false>::result
3360__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3361 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3362 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3363{
3364 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3365 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3366 const uint32_t* _frm_nxt = _frm;
3367 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3368 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3369 uint8_t* _to_nxt = _to;
3370 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3371 _Maxcode_, _Mode_);
3372 frm_nxt = frm + (_frm_nxt - _frm);
3373 to_nxt = to + (_to_nxt - _to);
3374 return r;
3375}
3376
3377__codecvt_utf16<wchar_t, false>::result
3378__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3379 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3380 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3381{
3382 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3383 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3384 const uint8_t* _frm_nxt = _frm;
3385 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3386 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3387 uint32_t* _to_nxt = _to;
3388 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3389 _Maxcode_, _Mode_);
3390 frm_nxt = frm + (_frm_nxt - _frm);
3391 to_nxt = to + (_to_nxt - _to);
3392 return r;
3393}
3394
3395__codecvt_utf16<wchar_t, false>::result
3396__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3397 extern_type* to, extern_type*, extern_type*& to_nxt) const
3398{
3399 to_nxt = to;
3400 return noconv;
3401}
3402
3403int
Howard Hinnantc9834542011-05-31 15:34:58 +00003404__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003405{
3406 return 0;
3407}
3408
3409bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003410__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003411{
3412 return false;
3413}
3414
3415int
3416__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3417 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3418{
3419 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3420 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3421 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3422}
3423
3424int
Howard Hinnantc9834542011-05-31 15:34:58 +00003425__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003426{
3427 if (_Mode_ & consume_header)
3428 return 6;
3429 return 4;
3430}
3431
3432// __codecvt_utf16<wchar_t, true>
3433
3434__codecvt_utf16<wchar_t, true>::result
3435__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3436 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3437 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3438{
3439 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3440 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3441 const uint32_t* _frm_nxt = _frm;
3442 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3443 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3444 uint8_t* _to_nxt = _to;
3445 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3446 _Maxcode_, _Mode_);
3447 frm_nxt = frm + (_frm_nxt - _frm);
3448 to_nxt = to + (_to_nxt - _to);
3449 return r;
3450}
3451
3452__codecvt_utf16<wchar_t, true>::result
3453__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3454 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3455 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3456{
3457 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3458 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3459 const uint8_t* _frm_nxt = _frm;
3460 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3461 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3462 uint32_t* _to_nxt = _to;
3463 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3464 _Maxcode_, _Mode_);
3465 frm_nxt = frm + (_frm_nxt - _frm);
3466 to_nxt = to + (_to_nxt - _to);
3467 return r;
3468}
3469
3470__codecvt_utf16<wchar_t, true>::result
3471__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3472 extern_type* to, extern_type*, extern_type*& to_nxt) const
3473{
3474 to_nxt = to;
3475 return noconv;
3476}
3477
3478int
Howard Hinnantc9834542011-05-31 15:34:58 +00003479__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003480{
3481 return 0;
3482}
3483
3484bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003485__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003486{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003487 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003488}
3489
3490int
3491__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3492 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3493{
3494 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3495 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3496 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3497}
3498
3499int
Howard Hinnantc9834542011-05-31 15:34:58 +00003500__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003501{
3502 if (_Mode_ & consume_header)
3503 return 6;
3504 return 4;
3505}
3506
3507// __codecvt_utf16<char16_t, false>
3508
3509__codecvt_utf16<char16_t, false>::result
3510__codecvt_utf16<char16_t, false>::do_out(state_type&,
3511 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3512 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3513{
3514 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3515 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3516 const uint16_t* _frm_nxt = _frm;
3517 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3518 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3519 uint8_t* _to_nxt = _to;
3520 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3521 _Maxcode_, _Mode_);
3522 frm_nxt = frm + (_frm_nxt - _frm);
3523 to_nxt = to + (_to_nxt - _to);
3524 return r;
3525}
3526
3527__codecvt_utf16<char16_t, false>::result
3528__codecvt_utf16<char16_t, false>::do_in(state_type&,
3529 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3530 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3531{
3532 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3533 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3534 const uint8_t* _frm_nxt = _frm;
3535 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3536 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3537 uint16_t* _to_nxt = _to;
3538 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3539 _Maxcode_, _Mode_);
3540 frm_nxt = frm + (_frm_nxt - _frm);
3541 to_nxt = to + (_to_nxt - _to);
3542 return r;
3543}
3544
3545__codecvt_utf16<char16_t, false>::result
3546__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3547 extern_type* to, extern_type*, extern_type*& to_nxt) const
3548{
3549 to_nxt = to;
3550 return noconv;
3551}
3552
3553int
Howard Hinnantc9834542011-05-31 15:34:58 +00003554__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003555{
3556 return 0;
3557}
3558
3559bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003560__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003561{
3562 return false;
3563}
3564
3565int
3566__codecvt_utf16<char16_t, false>::do_length(state_type&,
3567 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3568{
3569 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3570 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3571 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3572}
3573
3574int
Howard Hinnantc9834542011-05-31 15:34:58 +00003575__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003576{
3577 if (_Mode_ & consume_header)
3578 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003579 return 2;
3580}
3581
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003582// __codecvt_utf16<char16_t, true>
3583
3584__codecvt_utf16<char16_t, true>::result
3585__codecvt_utf16<char16_t, true>::do_out(state_type&,
3586 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3587 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3588{
3589 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3590 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3591 const uint16_t* _frm_nxt = _frm;
3592 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3593 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3594 uint8_t* _to_nxt = _to;
3595 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3596 _Maxcode_, _Mode_);
3597 frm_nxt = frm + (_frm_nxt - _frm);
3598 to_nxt = to + (_to_nxt - _to);
3599 return r;
3600}
3601
3602__codecvt_utf16<char16_t, true>::result
3603__codecvt_utf16<char16_t, true>::do_in(state_type&,
3604 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3605 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3606{
3607 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3608 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3609 const uint8_t* _frm_nxt = _frm;
3610 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3611 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3612 uint16_t* _to_nxt = _to;
3613 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3614 _Maxcode_, _Mode_);
3615 frm_nxt = frm + (_frm_nxt - _frm);
3616 to_nxt = to + (_to_nxt - _to);
3617 return r;
3618}
3619
3620__codecvt_utf16<char16_t, true>::result
3621__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3622 extern_type* to, extern_type*, extern_type*& to_nxt) const
3623{
3624 to_nxt = to;
3625 return noconv;
3626}
3627
3628int
Howard Hinnantc9834542011-05-31 15:34:58 +00003629__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003630{
3631 return 0;
3632}
3633
3634bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003635__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003636{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003637 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003638}
3639
3640int
3641__codecvt_utf16<char16_t, true>::do_length(state_type&,
3642 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3643{
3644 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3645 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3646 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3647}
3648
3649int
Howard Hinnantc9834542011-05-31 15:34:58 +00003650__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003651{
3652 if (_Mode_ & consume_header)
3653 return 4;
3654 return 2;
3655}
3656
3657// __codecvt_utf16<char32_t, false>
3658
3659__codecvt_utf16<char32_t, false>::result
3660__codecvt_utf16<char32_t, false>::do_out(state_type&,
3661 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3662 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3663{
3664 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3665 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3666 const uint32_t* _frm_nxt = _frm;
3667 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3668 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3669 uint8_t* _to_nxt = _to;
3670 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3671 _Maxcode_, _Mode_);
3672 frm_nxt = frm + (_frm_nxt - _frm);
3673 to_nxt = to + (_to_nxt - _to);
3674 return r;
3675}
3676
3677__codecvt_utf16<char32_t, false>::result
3678__codecvt_utf16<char32_t, false>::do_in(state_type&,
3679 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3680 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3681{
3682 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3683 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3684 const uint8_t* _frm_nxt = _frm;
3685 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3686 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3687 uint32_t* _to_nxt = _to;
3688 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3689 _Maxcode_, _Mode_);
3690 frm_nxt = frm + (_frm_nxt - _frm);
3691 to_nxt = to + (_to_nxt - _to);
3692 return r;
3693}
3694
3695__codecvt_utf16<char32_t, false>::result
3696__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3697 extern_type* to, extern_type*, extern_type*& to_nxt) const
3698{
3699 to_nxt = to;
3700 return noconv;
3701}
3702
3703int
Howard Hinnantc9834542011-05-31 15:34:58 +00003704__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003705{
3706 return 0;
3707}
3708
3709bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003710__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003711{
3712 return false;
3713}
3714
3715int
3716__codecvt_utf16<char32_t, false>::do_length(state_type&,
3717 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3718{
3719 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3720 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3721 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3722}
3723
3724int
Howard Hinnantc9834542011-05-31 15:34:58 +00003725__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003726{
3727 if (_Mode_ & consume_header)
3728 return 6;
3729 return 4;
3730}
3731
3732// __codecvt_utf16<char32_t, true>
3733
3734__codecvt_utf16<char32_t, true>::result
3735__codecvt_utf16<char32_t, true>::do_out(state_type&,
3736 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3737 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3738{
3739 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3740 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3741 const uint32_t* _frm_nxt = _frm;
3742 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3743 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3744 uint8_t* _to_nxt = _to;
3745 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3746 _Maxcode_, _Mode_);
3747 frm_nxt = frm + (_frm_nxt - _frm);
3748 to_nxt = to + (_to_nxt - _to);
3749 return r;
3750}
3751
3752__codecvt_utf16<char32_t, true>::result
3753__codecvt_utf16<char32_t, true>::do_in(state_type&,
3754 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3755 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3756{
3757 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3758 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3759 const uint8_t* _frm_nxt = _frm;
3760 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3761 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3762 uint32_t* _to_nxt = _to;
3763 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3764 _Maxcode_, _Mode_);
3765 frm_nxt = frm + (_frm_nxt - _frm);
3766 to_nxt = to + (_to_nxt - _to);
3767 return r;
3768}
3769
3770__codecvt_utf16<char32_t, true>::result
3771__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3772 extern_type* to, extern_type*, extern_type*& to_nxt) const
3773{
3774 to_nxt = to;
3775 return noconv;
3776}
3777
3778int
Howard Hinnantc9834542011-05-31 15:34:58 +00003779__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003780{
3781 return 0;
3782}
3783
3784bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003785__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003786{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003787 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003788}
3789
3790int
3791__codecvt_utf16<char32_t, true>::do_length(state_type&,
3792 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3793{
3794 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3795 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3796 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3797}
3798
3799int
Howard Hinnantc9834542011-05-31 15:34:58 +00003800__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003801{
3802 if (_Mode_ & consume_header)
3803 return 6;
3804 return 4;
3805}
3806
3807// __codecvt_utf8_utf16<wchar_t>
3808
3809__codecvt_utf8_utf16<wchar_t>::result
3810__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3811 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3812 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3813{
3814 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3815 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3816 const uint32_t* _frm_nxt = _frm;
3817 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3818 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3819 uint8_t* _to_nxt = _to;
3820 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3821 _Maxcode_, _Mode_);
3822 frm_nxt = frm + (_frm_nxt - _frm);
3823 to_nxt = to + (_to_nxt - _to);
3824 return r;
3825}
3826
3827__codecvt_utf8_utf16<wchar_t>::result
3828__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3829 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3830 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3831{
3832 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3833 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3834 const uint8_t* _frm_nxt = _frm;
3835 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3836 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3837 uint32_t* _to_nxt = _to;
3838 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3839 _Maxcode_, _Mode_);
3840 frm_nxt = frm + (_frm_nxt - _frm);
3841 to_nxt = to + (_to_nxt - _to);
3842 return r;
3843}
3844
3845__codecvt_utf8_utf16<wchar_t>::result
3846__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3847 extern_type* to, extern_type*, extern_type*& to_nxt) const
3848{
3849 to_nxt = to;
3850 return noconv;
3851}
3852
3853int
Howard Hinnantc9834542011-05-31 15:34:58 +00003854__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003855{
3856 return 0;
3857}
3858
3859bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003860__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003861{
3862 return false;
3863}
3864
3865int
3866__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3867 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3868{
3869 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3870 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3871 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3872}
3873
3874int
Howard Hinnantc9834542011-05-31 15:34:58 +00003875__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003876{
3877 if (_Mode_ & consume_header)
3878 return 7;
3879 return 4;
3880}
3881
3882// __codecvt_utf8_utf16<char16_t>
3883
3884__codecvt_utf8_utf16<char16_t>::result
3885__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3886 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3887 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3888{
3889 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3890 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3891 const uint16_t* _frm_nxt = _frm;
3892 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3893 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3894 uint8_t* _to_nxt = _to;
3895 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3896 _Maxcode_, _Mode_);
3897 frm_nxt = frm + (_frm_nxt - _frm);
3898 to_nxt = to + (_to_nxt - _to);
3899 return r;
3900}
3901
3902__codecvt_utf8_utf16<char16_t>::result
3903__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3904 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3905 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3906{
3907 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3908 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3909 const uint8_t* _frm_nxt = _frm;
3910 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3911 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3912 uint16_t* _to_nxt = _to;
3913 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3914 _Maxcode_, _Mode_);
3915 frm_nxt = frm + (_frm_nxt - _frm);
3916 to_nxt = to + (_to_nxt - _to);
3917 return r;
3918}
3919
3920__codecvt_utf8_utf16<char16_t>::result
3921__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3922 extern_type* to, extern_type*, extern_type*& to_nxt) const
3923{
3924 to_nxt = to;
3925 return noconv;
3926}
3927
3928int
Howard Hinnantc9834542011-05-31 15:34:58 +00003929__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003930{
3931 return 0;
3932}
3933
3934bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003935__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003936{
3937 return false;
3938}
3939
3940int
3941__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3942 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3943{
3944 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3945 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3946 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3947}
3948
3949int
Howard Hinnantc9834542011-05-31 15:34:58 +00003950__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003951{
3952 if (_Mode_ & consume_header)
3953 return 7;
3954 return 4;
3955}
3956
3957// __codecvt_utf8_utf16<char32_t>
3958
3959__codecvt_utf8_utf16<char32_t>::result
3960__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3961 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3962 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3963{
3964 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3965 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3966 const uint32_t* _frm_nxt = _frm;
3967 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3968 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3969 uint8_t* _to_nxt = _to;
3970 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3971 _Maxcode_, _Mode_);
3972 frm_nxt = frm + (_frm_nxt - _frm);
3973 to_nxt = to + (_to_nxt - _to);
3974 return r;
3975}
3976
3977__codecvt_utf8_utf16<char32_t>::result
3978__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3979 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3980 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3981{
3982 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3983 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3984 const uint8_t* _frm_nxt = _frm;
3985 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3986 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3987 uint32_t* _to_nxt = _to;
3988 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3989 _Maxcode_, _Mode_);
3990 frm_nxt = frm + (_frm_nxt - _frm);
3991 to_nxt = to + (_to_nxt - _to);
3992 return r;
3993}
3994
3995__codecvt_utf8_utf16<char32_t>::result
3996__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3997 extern_type* to, extern_type*, extern_type*& to_nxt) const
3998{
3999 to_nxt = to;
4000 return noconv;
4001}
4002
4003int
Howard Hinnantc9834542011-05-31 15:34:58 +00004004__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004005{
4006 return 0;
4007}
4008
4009bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004010__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004011{
4012 return false;
4013}
4014
4015int
4016__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4017 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4018{
4019 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4020 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4021 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4022}
4023
4024int
Howard Hinnantc9834542011-05-31 15:34:58 +00004025__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004026{
4027 if (_Mode_ & consume_header)
4028 return 7;
4029 return 4;
4030}
4031
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004032// __narrow_to_utf8<16>
4033
4034__narrow_to_utf8<16>::~__narrow_to_utf8()
4035{
4036}
4037
4038// __narrow_to_utf8<32>
4039
4040__narrow_to_utf8<32>::~__narrow_to_utf8()
4041{
4042}
4043
4044// __widen_from_utf8<16>
4045
4046__widen_from_utf8<16>::~__widen_from_utf8()
4047{
4048}
4049
4050// __widen_from_utf8<32>
4051
4052__widen_from_utf8<32>::~__widen_from_utf8()
4053{
4054}
4055
4056// numpunct<char> && numpunct<wchar_t>
4057
4058locale::id numpunct< char >::id;
4059locale::id numpunct<wchar_t>::id;
4060
4061numpunct<char>::numpunct(size_t refs)
4062 : locale::facet(refs),
4063 __decimal_point_('.'),
4064 __thousands_sep_(',')
4065{
4066}
4067
4068numpunct<wchar_t>::numpunct(size_t refs)
4069 : locale::facet(refs),
4070 __decimal_point_(L'.'),
4071 __thousands_sep_(L',')
4072{
4073}
4074
4075numpunct<char>::~numpunct()
4076{
4077}
4078
4079numpunct<wchar_t>::~numpunct()
4080{
4081}
4082
4083 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4084wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4085
4086 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4087wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4088
4089string numpunct< char >::do_grouping() const {return __grouping_;}
4090string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4091
4092 string numpunct< char >::do_truename() const {return "true";}
4093wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4094
4095 string numpunct< char >::do_falsename() const {return "false";}
4096wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4097
4098// numpunct_byname<char>
4099
4100numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4101 : numpunct<char>(refs)
4102{
4103 __init(nm);
4104}
4105
4106numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4107 : numpunct<char>(refs)
4108{
4109 __init(nm.c_str());
4110}
4111
4112numpunct_byname<char>::~numpunct_byname()
4113{
4114}
4115
4116void
4117numpunct_byname<char>::__init(const char* nm)
4118{
4119 if (strcmp(nm, "C") != 0)
4120 {
Sean Huntf3907e62011-07-15 05:40:33 +00004121 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004122#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004123 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004124 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4125 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004126#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004127#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004128 lconv* lc = localeconv_l(loc.get());
4129#else
4130 lconv* lc = __localeconv_l(loc.get());
4131#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004132 if (*lc->decimal_point)
4133 __decimal_point_ = *lc->decimal_point;
4134 if (*lc->thousands_sep)
4135 __thousands_sep_ = *lc->thousands_sep;
4136 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004137 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004138 }
4139}
4140
4141// numpunct_byname<wchar_t>
4142
4143numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4144 : numpunct<wchar_t>(refs)
4145{
4146 __init(nm);
4147}
4148
4149numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4150 : numpunct<wchar_t>(refs)
4151{
4152 __init(nm.c_str());
4153}
4154
4155numpunct_byname<wchar_t>::~numpunct_byname()
4156{
4157}
4158
4159void
4160numpunct_byname<wchar_t>::__init(const char* nm)
4161{
4162 if (strcmp(nm, "C") != 0)
4163 {
Sean Huntf3907e62011-07-15 05:40:33 +00004164 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004165#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004166 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004167 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4168 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004169#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004170#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004171 lconv* lc = localeconv_l(loc.get());
4172#else
4173 lconv* lc = __localeconv_l(loc.get());
4174#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004175 if (*lc->decimal_point)
4176 __decimal_point_ = *lc->decimal_point;
4177 if (*lc->thousands_sep)
4178 __thousands_sep_ = *lc->thousands_sep;
4179 __grouping_ = lc->grouping;
4180 // locallization for truename and falsename is not available
4181 }
4182}
4183
4184// num_get helpers
4185
4186int
4187__num_get_base::__get_base(ios_base& iob)
4188{
4189 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4190 if (__basefield == ios_base::oct)
4191 return 8;
4192 else if (__basefield == ios_base::hex)
4193 return 16;
4194 else if (__basefield == 0)
4195 return 0;
4196 return 10;
4197}
4198
4199const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4200
4201void
4202__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4203 ios_base::iostate& __err)
4204{
4205 if (__grouping.size() != 0)
4206 {
4207 reverse(__g, __g_end);
4208 const char* __ig = __grouping.data();
4209 const char* __eg = __ig + __grouping.size();
4210 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4211 {
4212 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4213 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004214 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004215 {
4216 __err = ios_base::failbit;
4217 return;
4218 }
4219 }
4220 if (__eg - __ig > 1)
4221 ++__ig;
4222 }
4223 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4224 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004225 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004226 __err = ios_base::failbit;
4227 }
4228 }
4229}
4230
4231void
4232__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4233 ios_base::fmtflags __flags)
4234{
4235 if (__flags & ios_base::showpos)
4236 *__fmtp++ = '+';
4237 if (__flags & ios_base::showbase)
4238 *__fmtp++ = '#';
4239 while(*__len)
4240 *__fmtp++ = *__len++;
4241 if ((__flags & ios_base::basefield) == ios_base::oct)
4242 *__fmtp = 'o';
4243 else if ((__flags & ios_base::basefield) == ios_base::hex)
4244 {
4245 if (__flags & ios_base::uppercase)
4246 *__fmtp = 'X';
4247 else
4248 *__fmtp = 'x';
4249 }
4250 else if (__signd)
4251 *__fmtp = 'd';
4252 else
4253 *__fmtp = 'u';
4254}
4255
4256bool
4257__num_put_base::__format_float(char* __fmtp, const char* __len,
4258 ios_base::fmtflags __flags)
4259{
4260 bool specify_precision = true;
4261 if (__flags & ios_base::showpos)
4262 *__fmtp++ = '+';
4263 if (__flags & ios_base::showpoint)
4264 *__fmtp++ = '#';
4265 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4266 bool uppercase = __flags & ios_base::uppercase;
4267 if (floatfield == (ios_base::fixed | ios_base::scientific))
4268 specify_precision = false;
4269 else
4270 {
4271 *__fmtp++ = '.';
4272 *__fmtp++ = '*';
4273 }
4274 while(*__len)
4275 *__fmtp++ = *__len++;
4276 if (floatfield == ios_base::fixed)
4277 {
4278 if (uppercase)
4279 *__fmtp = 'F';
4280 else
4281 *__fmtp = 'f';
4282 }
4283 else if (floatfield == ios_base::scientific)
4284 {
4285 if (uppercase)
4286 *__fmtp = 'E';
4287 else
4288 *__fmtp = 'e';
4289 }
4290 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4291 {
4292 if (uppercase)
4293 *__fmtp = 'A';
4294 else
4295 *__fmtp = 'a';
4296 }
4297 else
4298 {
4299 if (uppercase)
4300 *__fmtp = 'G';
4301 else
4302 *__fmtp = 'g';
4303 }
4304 return specify_precision;
4305}
4306
4307char*
4308__num_put_base::__identify_padding(char* __nb, char* __ne,
4309 const ios_base& __iob)
4310{
4311 switch (__iob.flags() & ios_base::adjustfield)
4312 {
4313 case ios_base::internal:
4314 if (__nb[0] == '-' || __nb[0] == '+')
4315 return __nb+1;
4316 if (__ne - __nb >= 2 && __nb[0] == '0'
4317 && (__nb[1] == 'x' || __nb[1] == 'X'))
4318 return __nb+2;
4319 break;
4320 case ios_base::left:
4321 return __ne;
4322 case ios_base::right:
4323 default:
4324 break;
4325 }
4326 return __nb;
4327}
4328
4329// time_get
4330
4331static
4332string*
4333init_weeks()
4334{
4335 static string weeks[14];
4336 weeks[0] = "Sunday";
4337 weeks[1] = "Monday";
4338 weeks[2] = "Tuesday";
4339 weeks[3] = "Wednesday";
4340 weeks[4] = "Thursday";
4341 weeks[5] = "Friday";
4342 weeks[6] = "Saturday";
4343 weeks[7] = "Sun";
4344 weeks[8] = "Mon";
4345 weeks[9] = "Tue";
4346 weeks[10] = "Wed";
4347 weeks[11] = "Thu";
4348 weeks[12] = "Fri";
4349 weeks[13] = "Sat";
4350 return weeks;
4351}
4352
4353static
4354wstring*
4355init_wweeks()
4356{
4357 static wstring weeks[14];
4358 weeks[0] = L"Sunday";
4359 weeks[1] = L"Monday";
4360 weeks[2] = L"Tuesday";
4361 weeks[3] = L"Wednesday";
4362 weeks[4] = L"Thursday";
4363 weeks[5] = L"Friday";
4364 weeks[6] = L"Saturday";
4365 weeks[7] = L"Sun";
4366 weeks[8] = L"Mon";
4367 weeks[9] = L"Tue";
4368 weeks[10] = L"Wed";
4369 weeks[11] = L"Thu";
4370 weeks[12] = L"Fri";
4371 weeks[13] = L"Sat";
4372 return weeks;
4373}
4374
4375template <>
4376const string*
4377__time_get_c_storage<char>::__weeks() const
4378{
4379 static const string* weeks = init_weeks();
4380 return weeks;
4381}
4382
4383template <>
4384const wstring*
4385__time_get_c_storage<wchar_t>::__weeks() const
4386{
4387 static const wstring* weeks = init_wweeks();
4388 return weeks;
4389}
4390
4391static
4392string*
4393init_months()
4394{
4395 static string months[24];
4396 months[0] = "January";
4397 months[1] = "February";
4398 months[2] = "March";
4399 months[3] = "April";
4400 months[4] = "May";
4401 months[5] = "June";
4402 months[6] = "July";
4403 months[7] = "August";
4404 months[8] = "September";
4405 months[9] = "October";
4406 months[10] = "November";
4407 months[11] = "December";
4408 months[12] = "Jan";
4409 months[13] = "Feb";
4410 months[14] = "Mar";
4411 months[15] = "Apr";
4412 months[16] = "May";
4413 months[17] = "Jun";
4414 months[18] = "Jul";
4415 months[19] = "Aug";
4416 months[20] = "Sep";
4417 months[21] = "Oct";
4418 months[22] = "Nov";
4419 months[23] = "Dec";
4420 return months;
4421}
4422
4423static
4424wstring*
4425init_wmonths()
4426{
4427 static wstring months[24];
4428 months[0] = L"January";
4429 months[1] = L"February";
4430 months[2] = L"March";
4431 months[3] = L"April";
4432 months[4] = L"May";
4433 months[5] = L"June";
4434 months[6] = L"July";
4435 months[7] = L"August";
4436 months[8] = L"September";
4437 months[9] = L"October";
4438 months[10] = L"November";
4439 months[11] = L"December";
4440 months[12] = L"Jan";
4441 months[13] = L"Feb";
4442 months[14] = L"Mar";
4443 months[15] = L"Apr";
4444 months[16] = L"May";
4445 months[17] = L"Jun";
4446 months[18] = L"Jul";
4447 months[19] = L"Aug";
4448 months[20] = L"Sep";
4449 months[21] = L"Oct";
4450 months[22] = L"Nov";
4451 months[23] = L"Dec";
4452 return months;
4453}
4454
4455template <>
4456const string*
4457__time_get_c_storage<char>::__months() const
4458{
4459 static const string* months = init_months();
4460 return months;
4461}
4462
4463template <>
4464const wstring*
4465__time_get_c_storage<wchar_t>::__months() const
4466{
4467 static const wstring* months = init_wmonths();
4468 return months;
4469}
4470
4471static
4472string*
4473init_am_pm()
4474{
4475 static string am_pm[24];
4476 am_pm[0] = "AM";
4477 am_pm[1] = "PM";
4478 return am_pm;
4479}
4480
4481static
4482wstring*
4483init_wam_pm()
4484{
4485 static wstring am_pm[24];
4486 am_pm[0] = L"AM";
4487 am_pm[1] = L"PM";
4488 return am_pm;
4489}
4490
4491template <>
4492const string*
4493__time_get_c_storage<char>::__am_pm() const
4494{
4495 static const string* am_pm = init_am_pm();
4496 return am_pm;
4497}
4498
4499template <>
4500const wstring*
4501__time_get_c_storage<wchar_t>::__am_pm() const
4502{
4503 static const wstring* am_pm = init_wam_pm();
4504 return am_pm;
4505}
4506
4507template <>
4508const string&
4509__time_get_c_storage<char>::__x() const
4510{
4511 static string s("%m/%d/%y");
4512 return s;
4513}
4514
4515template <>
4516const wstring&
4517__time_get_c_storage<wchar_t>::__x() const
4518{
4519 static wstring s(L"%m/%d/%y");
4520 return s;
4521}
4522
4523template <>
4524const string&
4525__time_get_c_storage<char>::__X() const
4526{
4527 static string s("%H:%M:%S");
4528 return s;
4529}
4530
4531template <>
4532const wstring&
4533__time_get_c_storage<wchar_t>::__X() const
4534{
4535 static wstring s(L"%H:%M:%S");
4536 return s;
4537}
4538
4539template <>
4540const string&
4541__time_get_c_storage<char>::__c() const
4542{
4543 static string s("%a %b %d %H:%M:%S %Y");
4544 return s;
4545}
4546
4547template <>
4548const wstring&
4549__time_get_c_storage<wchar_t>::__c() const
4550{
4551 static wstring s(L"%a %b %d %H:%M:%S %Y");
4552 return s;
4553}
4554
4555template <>
4556const string&
4557__time_get_c_storage<char>::__r() const
4558{
4559 static string s("%I:%M:%S %p");
4560 return s;
4561}
4562
4563template <>
4564const wstring&
4565__time_get_c_storage<wchar_t>::__r() const
4566{
4567 static wstring s(L"%I:%M:%S %p");
4568 return s;
4569}
4570
4571// time_get_byname
4572
4573__time_get::__time_get(const char* nm)
4574 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4575{
Howard Hinnantd4444702010-08-11 17:04:31 +00004576#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004577 if (__loc_ == 0)
4578 throw runtime_error("time_get_byname"
4579 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004580#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004581}
4582
4583__time_get::__time_get(const string& nm)
4584 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4585{
Howard Hinnantd4444702010-08-11 17:04:31 +00004586#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004587 if (__loc_ == 0)
4588 throw runtime_error("time_get_byname"
4589 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004590#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004591}
4592
4593__time_get::~__time_get()
4594{
4595 freelocale(__loc_);
4596}
4597
Howard Hinnant335b1512012-02-20 16:51:43 +00004598#pragma clang diagnostic ignored "-Wmissing-field-initializers"
4599
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004600template <>
4601string
4602__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4603{
Howard Hinnant3074a052012-02-19 14:55:32 +00004604 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004605 t.tm_sec = 59;
4606 t.tm_min = 55;
4607 t.tm_hour = 23;
4608 t.tm_mday = 31;
4609 t.tm_mon = 11;
4610 t.tm_year = 161;
4611 t.tm_wday = 6;
4612 t.tm_yday = 364;
4613 t.tm_isdst = -1;
4614 char buf[100];
4615 char f[3] = {0};
4616 f[0] = '%';
4617 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004618 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004619 char* bb = buf;
4620 char* be = buf + n;
4621 string result;
4622 while (bb != be)
4623 {
4624 if (ct.is(ctype_base::space, *bb))
4625 {
4626 result.push_back(' ');
4627 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4628 ;
4629 continue;
4630 }
4631 char* w = bb;
4632 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004633 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004634 ct, err, false)
4635 - this->__weeks_;
4636 if (i < 14)
4637 {
4638 result.push_back('%');
4639 if (i < 7)
4640 result.push_back('A');
4641 else
4642 result.push_back('a');
4643 bb = w;
4644 continue;
4645 }
4646 w = bb;
4647 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4648 ct, err, false)
4649 - this->__months_;
4650 if (i < 24)
4651 {
4652 result.push_back('%');
4653 if (i < 12)
4654 result.push_back('B');
4655 else
4656 result.push_back('b');
4657 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4658 result.back() = 'm';
4659 bb = w;
4660 continue;
4661 }
4662 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4663 {
4664 w = bb;
4665 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4666 ct, err, false) - this->__am_pm_;
4667 if (i < 2)
4668 {
4669 result.push_back('%');
4670 result.push_back('p');
4671 bb = w;
4672 continue;
4673 }
4674 }
4675 w = bb;
4676 if (ct.is(ctype_base::digit, *bb))
4677 {
4678 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4679 {
4680 case 6:
4681 result.push_back('%');
4682 result.push_back('w');
4683 break;
4684 case 7:
4685 result.push_back('%');
4686 result.push_back('u');
4687 break;
4688 case 11:
4689 result.push_back('%');
4690 result.push_back('I');
4691 break;
4692 case 12:
4693 result.push_back('%');
4694 result.push_back('m');
4695 break;
4696 case 23:
4697 result.push_back('%');
4698 result.push_back('H');
4699 break;
4700 case 31:
4701 result.push_back('%');
4702 result.push_back('d');
4703 break;
4704 case 55:
4705 result.push_back('%');
4706 result.push_back('M');
4707 break;
4708 case 59:
4709 result.push_back('%');
4710 result.push_back('S');
4711 break;
4712 case 61:
4713 result.push_back('%');
4714 result.push_back('y');
4715 break;
4716 case 364:
4717 result.push_back('%');
4718 result.push_back('j');
4719 break;
4720 case 2061:
4721 result.push_back('%');
4722 result.push_back('Y');
4723 break;
4724 default:
4725 for (; w != bb; ++w)
4726 result.push_back(*w);
4727 break;
4728 }
4729 continue;
4730 }
4731 if (*bb == '%')
4732 {
4733 result.push_back('%');
4734 result.push_back('%');
4735 ++bb;
4736 continue;
4737 }
4738 result.push_back(*bb);
4739 ++bb;
4740 }
4741 return result;
4742}
4743
Howard Hinnantec3773c2011-12-01 20:21:04 +00004744#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004745
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004746template <>
4747wstring
4748__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4749{
Howard Hinnant3074a052012-02-19 14:55:32 +00004750 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004751 t.tm_sec = 59;
4752 t.tm_min = 55;
4753 t.tm_hour = 23;
4754 t.tm_mday = 31;
4755 t.tm_mon = 11;
4756 t.tm_year = 161;
4757 t.tm_wday = 6;
4758 t.tm_yday = 364;
4759 t.tm_isdst = -1;
4760 char buf[100];
4761 char f[3] = {0};
4762 f[0] = '%';
4763 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004764 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004765 wchar_t wbuf[100];
4766 wchar_t* wbb = wbuf;
4767 mbstate_t mb = {0};
4768 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004769#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004770 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004771#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004772 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004773#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004774 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004775 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004776 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004777 wstring result;
4778 while (wbb != wbe)
4779 {
4780 if (ct.is(ctype_base::space, *wbb))
4781 {
4782 result.push_back(L' ');
4783 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4784 ;
4785 continue;
4786 }
4787 wchar_t* w = wbb;
4788 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004789 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004790 ct, err, false)
4791 - this->__weeks_;
4792 if (i < 14)
4793 {
4794 result.push_back(L'%');
4795 if (i < 7)
4796 result.push_back(L'A');
4797 else
4798 result.push_back(L'a');
4799 wbb = w;
4800 continue;
4801 }
4802 w = wbb;
4803 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4804 ct, err, false)
4805 - this->__months_;
4806 if (i < 24)
4807 {
4808 result.push_back(L'%');
4809 if (i < 12)
4810 result.push_back(L'B');
4811 else
4812 result.push_back(L'b');
4813 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4814 result.back() = L'm';
4815 wbb = w;
4816 continue;
4817 }
4818 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4819 {
4820 w = wbb;
4821 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4822 ct, err, false) - this->__am_pm_;
4823 if (i < 2)
4824 {
4825 result.push_back(L'%');
4826 result.push_back(L'p');
4827 wbb = w;
4828 continue;
4829 }
4830 }
4831 w = wbb;
4832 if (ct.is(ctype_base::digit, *wbb))
4833 {
4834 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4835 {
4836 case 6:
4837 result.push_back(L'%');
4838 result.push_back(L'w');
4839 break;
4840 case 7:
4841 result.push_back(L'%');
4842 result.push_back(L'u');
4843 break;
4844 case 11:
4845 result.push_back(L'%');
4846 result.push_back(L'I');
4847 break;
4848 case 12:
4849 result.push_back(L'%');
4850 result.push_back(L'm');
4851 break;
4852 case 23:
4853 result.push_back(L'%');
4854 result.push_back(L'H');
4855 break;
4856 case 31:
4857 result.push_back(L'%');
4858 result.push_back(L'd');
4859 break;
4860 case 55:
4861 result.push_back(L'%');
4862 result.push_back(L'M');
4863 break;
4864 case 59:
4865 result.push_back(L'%');
4866 result.push_back(L'S');
4867 break;
4868 case 61:
4869 result.push_back(L'%');
4870 result.push_back(L'y');
4871 break;
4872 case 364:
4873 result.push_back(L'%');
4874 result.push_back(L'j');
4875 break;
4876 case 2061:
4877 result.push_back(L'%');
4878 result.push_back(L'Y');
4879 break;
4880 default:
4881 for (; w != wbb; ++w)
4882 result.push_back(*w);
4883 break;
4884 }
4885 continue;
4886 }
4887 if (ct.narrow(*wbb, 0) == '%')
4888 {
4889 result.push_back(L'%');
4890 result.push_back(L'%');
4891 ++wbb;
4892 continue;
4893 }
4894 result.push_back(*wbb);
4895 ++wbb;
4896 }
4897 return result;
4898}
4899
4900template <>
4901void
4902__time_get_storage<char>::init(const ctype<char>& ct)
4903{
Howard Hinnantcd992362012-08-02 18:44:17 +00004904 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004905 char buf[100];
4906 // __weeks_
4907 for (int i = 0; i < 7; ++i)
4908 {
4909 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004910 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004911 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004912 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004913 __weeks_[i+7] = buf;
4914 }
4915 // __months_
4916 for (int i = 0; i < 12; ++i)
4917 {
4918 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004919 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004920 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004921 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004922 __months_[i+12] = buf;
4923 }
4924 // __am_pm_
4925 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004926 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004927 __am_pm_[0] = buf;
4928 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004929 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004930 __am_pm_[1] = buf;
4931 __c_ = __analyze('c', ct);
4932 __r_ = __analyze('r', ct);
4933 __x_ = __analyze('x', ct);
4934 __X_ = __analyze('X', ct);
4935}
4936
4937template <>
4938void
4939__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4940{
4941 tm t = {0};
4942 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004943 wchar_t wbuf[100];
4944 wchar_t* wbe;
4945 mbstate_t mb = {0};
4946 // __weeks_
4947 for (int i = 0; i < 7; ++i)
4948 {
4949 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004950 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004951 mb = mbstate_t();
4952 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004953#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004954 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004955#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004956 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004957#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004958 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004959 __throw_runtime_error("locale not supported");
4960 wbe = wbuf + j;
4961 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004962 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004963 mb = mbstate_t();
4964 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004965#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004966 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004967#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004968 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004969#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004970 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004971 __throw_runtime_error("locale not supported");
4972 wbe = wbuf + j;
4973 __weeks_[i+7].assign(wbuf, wbe);
4974 }
4975 // __months_
4976 for (int i = 0; i < 12; ++i)
4977 {
4978 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004979 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004980 mb = mbstate_t();
4981 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004982#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004983 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004984#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004985 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004986#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004987 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004988 __throw_runtime_error("locale not supported");
4989 wbe = wbuf + j;
4990 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004991 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004992 mb = mbstate_t();
4993 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004994#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004995 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004996#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004997 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004998#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004999 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005000 __throw_runtime_error("locale not supported");
5001 wbe = wbuf + j;
5002 __months_[i+12].assign(wbuf, wbe);
5003 }
5004 // __am_pm_
5005 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005006 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005007 mb = mbstate_t();
5008 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005009#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005010 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005011#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005012 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005013#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005014 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005015 __throw_runtime_error("locale not supported");
5016 wbe = wbuf + j;
5017 __am_pm_[0].assign(wbuf, wbe);
5018 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005019 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005020 mb = mbstate_t();
5021 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005022#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005023 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005024#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005025 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005026#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005027 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005028 __throw_runtime_error("locale not supported");
5029 wbe = wbuf + j;
5030 __am_pm_[1].assign(wbuf, wbe);
5031 __c_ = __analyze('c', ct);
5032 __r_ = __analyze('r', ct);
5033 __x_ = __analyze('x', ct);
5034 __X_ = __analyze('X', ct);
5035}
5036
5037template <class CharT>
5038struct _LIBCPP_HIDDEN __time_get_temp
5039 : public ctype_byname<CharT>
5040{
5041 explicit __time_get_temp(const char* nm)
5042 : ctype_byname<CharT>(nm, 1) {}
5043 explicit __time_get_temp(const string& nm)
5044 : ctype_byname<CharT>(nm, 1) {}
5045};
5046
5047template <>
5048__time_get_storage<char>::__time_get_storage(const char* __nm)
5049 : __time_get(__nm)
5050{
5051 const __time_get_temp<char> ct(__nm);
5052 init(ct);
5053}
5054
5055template <>
5056__time_get_storage<char>::__time_get_storage(const string& __nm)
5057 : __time_get(__nm)
5058{
5059 const __time_get_temp<char> ct(__nm);
5060 init(ct);
5061}
5062
5063template <>
5064__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5065 : __time_get(__nm)
5066{
5067 const __time_get_temp<wchar_t> ct(__nm);
5068 init(ct);
5069}
5070
5071template <>
5072__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5073 : __time_get(__nm)
5074{
5075 const __time_get_temp<wchar_t> ct(__nm);
5076 init(ct);
5077}
5078
5079template <>
5080time_base::dateorder
5081__time_get_storage<char>::__do_date_order() const
5082{
5083 unsigned i;
5084 for (i = 0; i < __x_.size(); ++i)
5085 if (__x_[i] == '%')
5086 break;
5087 ++i;
5088 switch (__x_[i])
5089 {
5090 case 'y':
5091 case 'Y':
5092 for (++i; i < __x_.size(); ++i)
5093 if (__x_[i] == '%')
5094 break;
5095 if (i == __x_.size())
5096 break;
5097 ++i;
5098 switch (__x_[i])
5099 {
5100 case 'm':
5101 for (++i; i < __x_.size(); ++i)
5102 if (__x_[i] == '%')
5103 break;
5104 if (i == __x_.size())
5105 break;
5106 ++i;
5107 if (__x_[i] == 'd')
5108 return time_base::ymd;
5109 break;
5110 case 'd':
5111 for (++i; i < __x_.size(); ++i)
5112 if (__x_[i] == '%')
5113 break;
5114 if (i == __x_.size())
5115 break;
5116 ++i;
5117 if (__x_[i] == 'm')
5118 return time_base::ydm;
5119 break;
5120 }
5121 break;
5122 case 'm':
5123 for (++i; i < __x_.size(); ++i)
5124 if (__x_[i] == '%')
5125 break;
5126 if (i == __x_.size())
5127 break;
5128 ++i;
5129 if (__x_[i] == 'd')
5130 {
5131 for (++i; i < __x_.size(); ++i)
5132 if (__x_[i] == '%')
5133 break;
5134 if (i == __x_.size())
5135 break;
5136 ++i;
5137 if (__x_[i] == 'y' || __x_[i] == 'Y')
5138 return time_base::mdy;
5139 break;
5140 }
5141 break;
5142 case 'd':
5143 for (++i; i < __x_.size(); ++i)
5144 if (__x_[i] == '%')
5145 break;
5146 if (i == __x_.size())
5147 break;
5148 ++i;
5149 if (__x_[i] == 'm')
5150 {
5151 for (++i; i < __x_.size(); ++i)
5152 if (__x_[i] == '%')
5153 break;
5154 if (i == __x_.size())
5155 break;
5156 ++i;
5157 if (__x_[i] == 'y' || __x_[i] == 'Y')
5158 return time_base::dmy;
5159 break;
5160 }
5161 break;
5162 }
5163 return time_base::no_order;
5164}
5165
5166template <>
5167time_base::dateorder
5168__time_get_storage<wchar_t>::__do_date_order() const
5169{
5170 unsigned i;
5171 for (i = 0; i < __x_.size(); ++i)
5172 if (__x_[i] == L'%')
5173 break;
5174 ++i;
5175 switch (__x_[i])
5176 {
5177 case L'y':
5178 case L'Y':
5179 for (++i; i < __x_.size(); ++i)
5180 if (__x_[i] == L'%')
5181 break;
5182 if (i == __x_.size())
5183 break;
5184 ++i;
5185 switch (__x_[i])
5186 {
5187 case L'm':
5188 for (++i; i < __x_.size(); ++i)
5189 if (__x_[i] == L'%')
5190 break;
5191 if (i == __x_.size())
5192 break;
5193 ++i;
5194 if (__x_[i] == L'd')
5195 return time_base::ymd;
5196 break;
5197 case L'd':
5198 for (++i; i < __x_.size(); ++i)
5199 if (__x_[i] == L'%')
5200 break;
5201 if (i == __x_.size())
5202 break;
5203 ++i;
5204 if (__x_[i] == L'm')
5205 return time_base::ydm;
5206 break;
5207 }
5208 break;
5209 case L'm':
5210 for (++i; i < __x_.size(); ++i)
5211 if (__x_[i] == L'%')
5212 break;
5213 if (i == __x_.size())
5214 break;
5215 ++i;
5216 if (__x_[i] == L'd')
5217 {
5218 for (++i; i < __x_.size(); ++i)
5219 if (__x_[i] == L'%')
5220 break;
5221 if (i == __x_.size())
5222 break;
5223 ++i;
5224 if (__x_[i] == L'y' || __x_[i] == L'Y')
5225 return time_base::mdy;
5226 break;
5227 }
5228 break;
5229 case L'd':
5230 for (++i; i < __x_.size(); ++i)
5231 if (__x_[i] == L'%')
5232 break;
5233 if (i == __x_.size())
5234 break;
5235 ++i;
5236 if (__x_[i] == L'm')
5237 {
5238 for (++i; i < __x_.size(); ++i)
5239 if (__x_[i] == L'%')
5240 break;
5241 if (i == __x_.size())
5242 break;
5243 ++i;
5244 if (__x_[i] == L'y' || __x_[i] == L'Y')
5245 return time_base::dmy;
5246 break;
5247 }
5248 break;
5249 }
5250 return time_base::no_order;
5251}
5252
5253// time_put
5254
5255__time_put::__time_put(const char* nm)
5256 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5257{
Howard Hinnantd4444702010-08-11 17:04:31 +00005258#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005259 if (__loc_ == 0)
5260 throw runtime_error("time_put_byname"
5261 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005262#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005263}
5264
5265__time_put::__time_put(const string& nm)
5266 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5267{
Howard Hinnantd4444702010-08-11 17:04:31 +00005268#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005269 if (__loc_ == 0)
5270 throw runtime_error("time_put_byname"
5271 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005272#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005273}
5274
5275__time_put::~__time_put()
5276{
5277 if (__loc_)
5278 freelocale(__loc_);
5279}
5280
5281void
5282__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5283 char __fmt, char __mod) const
5284{
5285 char fmt[] = {'%', __fmt, __mod, 0};
5286 if (__mod != 0)
5287 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005288 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005289 __ne = __nb + n;
5290}
5291
5292void
5293__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5294 char __fmt, char __mod) const
5295{
5296 char __nar[100];
5297 char* __ne = __nar + 100;
5298 __do_put(__nar, __ne, __tm, __fmt, __mod);
5299 mbstate_t mb = {0};
5300 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005301#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005302 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005303#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005304 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005305#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005306 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005307 __throw_runtime_error("locale not supported");
5308 __we = __wb + j;
5309}
5310
5311// moneypunct_byname
5312
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005313template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005314static
5315void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005316__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5317 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5318 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005319{
5320 const char sign = static_cast<char>(money_base::sign);
5321 const char space = static_cast<char>(money_base::space);
5322 const char none = static_cast<char>(money_base::none);
5323 const char symbol = static_cast<char>(money_base::symbol);
5324 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005325 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5326
5327 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5328 // function'. "Space between sign and symbol or value" means that
5329 // if the sign is adjacent to the symbol, there's a space between
5330 // them, and otherwise there's a space between the sign and value.
5331 //
5332 // C11's localeconv specifies that the fourth character of an
5333 // international curr_symbol is used to separate the sign and
5334 // value when sep_by_space says to do so. C++ can't represent
5335 // that, so we just use a space. When sep_by_space says to
5336 // separate the symbol and value-or-sign with a space, we rearrange the
5337 // curr_symbol to put its spacing character on the correct side of
5338 // the symbol.
5339 //
5340 // We also need to avoid adding an extra space between the sign
5341 // and value when the currency symbol is suppressed (by not
5342 // setting showbase). We match glibc's strfmon by interpreting
5343 // sep_by_space==1 as "omit the space when the currency symbol is
5344 // absent".
5345 //
5346 // Users who want to get this right should use ICU instead.
5347
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005348 switch (cs_precedes)
5349 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005350 case 0: // value before curr_symbol
5351 if (symbol_contains_sep) {
5352 // Move the separator to before the symbol, to place it
5353 // between the value and symbol.
5354 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5355 __curr_symbol_.end());
5356 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005357 switch (sign_posn)
5358 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005359 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005360 pat.field[0] = sign;
5361 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005362 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005363 pat.field[3] = symbol;
5364 switch (sep_by_space)
5365 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005366 case 0: // No space separates the currency symbol and value.
5367 // This case may have changed between C99 and C11;
5368 // assume the currency symbol matches the intention.
5369 case 2: // Space between sign and currency or value.
5370 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005371 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005372 case 1: // Space between currency-and-sign or currency and value.
5373 if (!symbol_contains_sep) {
5374 // We insert the space into the symbol instead of
5375 // setting pat.field[2]=space so that when
5376 // showbase is not set, the space goes away too.
5377 __curr_symbol_.insert(0, 1, space_char);
5378 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005379 return;
5380 default:
5381 break;
5382 }
5383 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005384 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005385 pat.field[0] = sign;
5386 pat.field[3] = symbol;
5387 switch (sep_by_space)
5388 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005389 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005390 pat.field[1] = value;
5391 pat.field[2] = none;
5392 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005393 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005394 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005395 pat.field[2] = none;
5396 if (!symbol_contains_sep) {
5397 // We insert the space into the symbol instead of
5398 // setting pat.field[2]=space so that when
5399 // showbase is not set, the space goes away too.
5400 __curr_symbol_.insert(0, 1, space_char);
5401 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005402 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005403 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005404 pat.field[1] = space;
5405 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005406 if (symbol_contains_sep) {
5407 // Remove the separator from the symbol, since it
5408 // has already appeared after the sign.
5409 __curr_symbol_.erase(__curr_symbol_.begin());
5410 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005411 return;
5412 default:
5413 break;
5414 }
5415 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005416 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005417 pat.field[0] = value;
5418 pat.field[3] = sign;
5419 switch (sep_by_space)
5420 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005421 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005422 pat.field[1] = none;
5423 pat.field[2] = symbol;
5424 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005425 case 1: // Space between currency-and-sign or currency and value.
5426 if (!symbol_contains_sep) {
5427 // We insert the space into the symbol instead of
5428 // setting pat.field[1]=space so that when
5429 // showbase is not set, the space goes away too.
5430 __curr_symbol_.insert(0, 1, space_char);
5431 }
5432 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005433 pat.field[2] = symbol;
5434 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005435 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005436 pat.field[1] = symbol;
5437 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005438 if (symbol_contains_sep) {
5439 // Remove the separator from the symbol, since it
5440 // should not be removed if showbase is absent.
5441 __curr_symbol_.erase(__curr_symbol_.begin());
5442 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005443 return;
5444 default:
5445 break;
5446 }
5447 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005448 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005449 pat.field[0] = value;
5450 pat.field[3] = symbol;
5451 switch (sep_by_space)
5452 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005453 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005454 pat.field[1] = none;
5455 pat.field[2] = sign;
5456 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005457 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005458 pat.field[1] = space;
5459 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005460 if (symbol_contains_sep) {
5461 // Remove the separator from the symbol, since it
5462 // has already appeared before the sign.
5463 __curr_symbol_.erase(__curr_symbol_.begin());
5464 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005465 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005466 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005467 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005468 pat.field[2] = none;
5469 if (!symbol_contains_sep) {
5470 // We insert the space into the symbol instead of
5471 // setting pat.field[2]=space so that when
5472 // showbase is not set, the space goes away too.
5473 __curr_symbol_.insert(0, 1, space_char);
5474 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005475 return;
5476 default:
5477 break;
5478 }
5479 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005480 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005481 pat.field[0] = value;
5482 pat.field[3] = sign;
5483 switch (sep_by_space)
5484 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005485 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005486 pat.field[1] = none;
5487 pat.field[2] = symbol;
5488 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005489 case 1: // Space between currency-and-sign or currency and value.
5490 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005491 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005492 if (!symbol_contains_sep) {
5493 // We insert the space into the symbol instead of
5494 // setting pat.field[1]=space so that when
5495 // showbase is not set, the space goes away too.
5496 __curr_symbol_.insert(0, 1, space_char);
5497 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005498 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005499 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005500 pat.field[1] = symbol;
5501 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005502 if (symbol_contains_sep) {
5503 // Remove the separator from the symbol, since it
5504 // should not disappear when showbase is absent.
5505 __curr_symbol_.erase(__curr_symbol_.begin());
5506 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005507 return;
5508 default:
5509 break;
5510 }
5511 break;
5512 default:
5513 break;
5514 }
5515 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005516 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005517 switch (sign_posn)
5518 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005519 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005520 pat.field[0] = sign;
5521 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005522 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005523 pat.field[3] = value;
5524 switch (sep_by_space)
5525 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005526 case 0: // No space separates the currency symbol and value.
5527 // This case may have changed between C99 and C11;
5528 // assume the currency symbol matches the intention.
5529 case 2: // Space between sign and currency or value.
5530 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005531 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005532 case 1: // Space between currency-and-sign or currency and value.
5533 if (!symbol_contains_sep) {
5534 // We insert the space into the symbol instead of
5535 // setting pat.field[2]=space so that when
5536 // showbase is not set, the space goes away too.
5537 __curr_symbol_.insert(0, 1, space_char);
5538 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005539 return;
5540 default:
5541 break;
5542 }
5543 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005544 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005545 pat.field[0] = sign;
5546 pat.field[3] = value;
5547 switch (sep_by_space)
5548 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005549 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005550 pat.field[1] = symbol;
5551 pat.field[2] = none;
5552 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005553 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005554 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005555 pat.field[2] = none;
5556 if (!symbol_contains_sep) {
5557 // We insert the space into the symbol instead of
5558 // setting pat.field[2]=space so that when
5559 // showbase is not set, the space goes away too.
5560 __curr_symbol_.push_back(space_char);
5561 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005562 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005563 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005564 pat.field[1] = space;
5565 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005566 if (symbol_contains_sep) {
5567 // Remove the separator from the symbol, since it
5568 // has already appeared after the sign.
5569 __curr_symbol_.pop_back();
5570 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005571 return;
5572 default:
5573 break;
5574 }
5575 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005576 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005577 pat.field[0] = symbol;
5578 pat.field[3] = sign;
5579 switch (sep_by_space)
5580 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005581 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005582 pat.field[1] = none;
5583 pat.field[2] = value;
5584 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005585 case 1: // Space between currency-and-sign or currency and value.
5586 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005587 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005588 if (!symbol_contains_sep) {
5589 // We insert the space into the symbol instead of
5590 // setting pat.field[1]=space so that when
5591 // showbase is not set, the space goes away too.
5592 __curr_symbol_.push_back(space_char);
5593 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005594 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005595 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005596 pat.field[1] = value;
5597 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005598 if (symbol_contains_sep) {
5599 // Remove the separator from the symbol, since it
5600 // will appear before the sign.
5601 __curr_symbol_.pop_back();
5602 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005603 return;
5604 default:
5605 break;
5606 }
5607 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005608 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005609 pat.field[0] = sign;
5610 pat.field[3] = value;
5611 switch (sep_by_space)
5612 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005613 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005614 pat.field[1] = symbol;
5615 pat.field[2] = none;
5616 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005617 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005618 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005619 pat.field[2] = none;
5620 if (!symbol_contains_sep) {
5621 // We insert the space into the symbol instead of
5622 // setting pat.field[2]=space so that when
5623 // showbase is not set, the space goes away too.
5624 __curr_symbol_.push_back(space_char);
5625 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005626 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005627 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005628 pat.field[1] = space;
5629 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005630 if (symbol_contains_sep) {
5631 // Remove the separator from the symbol, since it
5632 // has already appeared after the sign.
5633 __curr_symbol_.pop_back();
5634 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005635 return;
5636 default:
5637 break;
5638 }
5639 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005640 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005641 pat.field[0] = symbol;
5642 pat.field[3] = value;
5643 switch (sep_by_space)
5644 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005645 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005646 pat.field[1] = sign;
5647 pat.field[2] = none;
5648 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005649 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005650 pat.field[1] = sign;
5651 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005652 if (symbol_contains_sep) {
5653 // Remove the separator from the symbol, since it
5654 // should not disappear when showbase is absent.
5655 __curr_symbol_.pop_back();
5656 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005657 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005658 case 2: // Space between sign and currency or value.
5659 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005660 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005661 if (!symbol_contains_sep) {
5662 // We insert the space into the symbol instead of
5663 // setting pat.field[1]=space so that when
5664 // showbase is not set, the space goes away too.
5665 __curr_symbol_.push_back(space_char);
5666 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005667 return;
5668 default:
5669 break;
5670 }
5671 break;
5672 default:
5673 break;
5674 }
5675 break;
5676 default:
5677 break;
5678 }
5679 pat.field[0] = symbol;
5680 pat.field[1] = sign;
5681 pat.field[2] = none;
5682 pat.field[3] = value;
5683}
5684
5685template<>
5686void
5687moneypunct_byname<char, false>::init(const char* nm)
5688{
5689 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005690 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005691#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005692 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005693 throw runtime_error("moneypunct_byname"
5694 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005695#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005696#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005697 lconv* lc = localeconv_l(loc.get());
5698#else
5699 lconv* lc = __localeconv_l(loc.get());
5700#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005701 if (*lc->mon_decimal_point)
5702 __decimal_point_ = *lc->mon_decimal_point;
5703 else
5704 __decimal_point_ = base::do_decimal_point();
5705 if (*lc->mon_thousands_sep)
5706 __thousands_sep_ = *lc->mon_thousands_sep;
5707 else
5708 __thousands_sep_ = base::do_thousands_sep();
5709 __grouping_ = lc->mon_grouping;
5710 __curr_symbol_ = lc->currency_symbol;
5711 if (lc->frac_digits != CHAR_MAX)
5712 __frac_digits_ = lc->frac_digits;
5713 else
5714 __frac_digits_ = base::do_frac_digits();
5715 if (lc->p_sign_posn == 0)
5716 __positive_sign_ = "()";
5717 else
5718 __positive_sign_ = lc->positive_sign;
5719 if (lc->n_sign_posn == 0)
5720 __negative_sign_ = "()";
5721 else
5722 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005723 // Assume the positive and negative formats will want spaces in
5724 // the same places in curr_symbol since there's no way to
5725 // represent anything else.
5726 string_type __dummy_curr_symbol = __curr_symbol_;
5727 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5728 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5729 __init_pat(__neg_format_, __curr_symbol_, false,
5730 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005731}
5732
5733template<>
5734void
5735moneypunct_byname<char, true>::init(const char* nm)
5736{
5737 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005738 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005739#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005740 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005741 throw runtime_error("moneypunct_byname"
5742 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005743#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005744#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005745 lconv* lc = localeconv_l(loc.get());
5746#else
5747 lconv* lc = __localeconv_l(loc.get());
5748#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005749 if (*lc->mon_decimal_point)
5750 __decimal_point_ = *lc->mon_decimal_point;
5751 else
5752 __decimal_point_ = base::do_decimal_point();
5753 if (*lc->mon_thousands_sep)
5754 __thousands_sep_ = *lc->mon_thousands_sep;
5755 else
5756 __thousands_sep_ = base::do_thousands_sep();
5757 __grouping_ = lc->mon_grouping;
5758 __curr_symbol_ = lc->int_curr_symbol;
5759 if (lc->int_frac_digits != CHAR_MAX)
5760 __frac_digits_ = lc->int_frac_digits;
5761 else
5762 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005763#if _WIN32
5764 if (lc->p_sign_posn == 0)
5765#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005766 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005767#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005768 __positive_sign_ = "()";
5769 else
5770 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005771#if _WIN32
5772 if(lc->n_sign_posn == 0)
5773#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005774 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005775#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005776 __negative_sign_ = "()";
5777 else
5778 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005779 // Assume the positive and negative formats will want spaces in
5780 // the same places in curr_symbol since there's no way to
5781 // represent anything else.
5782 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005783#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005784 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5785 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5786 __init_pat(__neg_format_, __curr_symbol_, true,
5787 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005788#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005789 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5790 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5791 lc->int_p_sign_posn, ' ');
5792 __init_pat(__neg_format_, __curr_symbol_, true,
5793 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5794 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005795#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005796}
5797
5798template<>
5799void
5800moneypunct_byname<wchar_t, false>::init(const char* nm)
5801{
5802 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005803 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005804#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005805 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005806 throw runtime_error("moneypunct_byname"
5807 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005808#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005809#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005810 lconv* lc = localeconv_l(loc.get());
5811#else
5812 lconv* lc = __localeconv_l(loc.get());
5813#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005814 if (*lc->mon_decimal_point)
5815 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5816 else
5817 __decimal_point_ = base::do_decimal_point();
5818 if (*lc->mon_thousands_sep)
5819 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5820 else
5821 __thousands_sep_ = base::do_thousands_sep();
5822 __grouping_ = lc->mon_grouping;
5823 wchar_t wbuf[100];
5824 mbstate_t mb = {0};
5825 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005826#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005827 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005828#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005829 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005830#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005831 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005832 __throw_runtime_error("locale not supported");
5833 wchar_t* wbe = wbuf + j;
5834 __curr_symbol_.assign(wbuf, wbe);
5835 if (lc->frac_digits != CHAR_MAX)
5836 __frac_digits_ = lc->frac_digits;
5837 else
5838 __frac_digits_ = base::do_frac_digits();
5839 if (lc->p_sign_posn == 0)
5840 __positive_sign_ = L"()";
5841 else
5842 {
5843 mb = mbstate_t();
5844 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005845#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005846 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005847#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005848 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005849#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005850 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005851 __throw_runtime_error("locale not supported");
5852 wbe = wbuf + j;
5853 __positive_sign_.assign(wbuf, wbe);
5854 }
5855 if (lc->n_sign_posn == 0)
5856 __negative_sign_ = L"()";
5857 else
5858 {
5859 mb = mbstate_t();
5860 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005861#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005862 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005863#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005864 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005865#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005866 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005867 __throw_runtime_error("locale not supported");
5868 wbe = wbuf + j;
5869 __negative_sign_.assign(wbuf, wbe);
5870 }
Jeffrey Yasskin558ae172012-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_;
5875 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5876 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5877 __init_pat(__neg_format_, __curr_symbol_, false,
5878 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005879}
5880
5881template<>
5882void
5883moneypunct_byname<wchar_t, true>::init(const char* nm)
5884{
5885 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005886 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005887#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005888 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005889 throw runtime_error("moneypunct_byname"
5890 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005891#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005892#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005893 lconv* lc = localeconv_l(loc.get());
5894#else
5895 lconv* lc = __localeconv_l(loc.get());
5896#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005897 if (*lc->mon_decimal_point)
5898 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5899 else
5900 __decimal_point_ = base::do_decimal_point();
5901 if (*lc->mon_thousands_sep)
5902 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5903 else
5904 __thousands_sep_ = base::do_thousands_sep();
5905 __grouping_ = lc->mon_grouping;
5906 wchar_t wbuf[100];
5907 mbstate_t mb = {0};
5908 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005909#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005910 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005911#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005912 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005913#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005914 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005915 __throw_runtime_error("locale not supported");
5916 wchar_t* wbe = wbuf + j;
5917 __curr_symbol_.assign(wbuf, wbe);
5918 if (lc->int_frac_digits != CHAR_MAX)
5919 __frac_digits_ = lc->int_frac_digits;
5920 else
5921 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005922#if _WIN32
5923 if (lc->p_sign_posn == 0)
5924#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005925 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005926#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005927 __positive_sign_ = L"()";
5928 else
5929 {
5930 mb = mbstate_t();
5931 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005932#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005933 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005934#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005935 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005936#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005937 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005938 __throw_runtime_error("locale not supported");
5939 wbe = wbuf + j;
5940 __positive_sign_.assign(wbuf, wbe);
5941 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005942#if _WIN32
5943 if (lc->n_sign_posn == 0)
5944#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005945 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005946#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005947 __negative_sign_ = L"()";
5948 else
5949 {
5950 mb = mbstate_t();
5951 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005952#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005953 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005954#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005955 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005956#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005957 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005958 __throw_runtime_error("locale not supported");
5959 wbe = wbuf + j;
5960 __negative_sign_.assign(wbuf, wbe);
5961 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005962 // Assume the positive and negative formats will want spaces in
5963 // the same places in curr_symbol since there's no way to
5964 // represent anything else.
5965 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005966#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005967 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5968 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5969 __init_pat(__neg_format_, __curr_symbol_, true,
5970 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005971#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005972 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5973 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5974 lc->int_p_sign_posn, L' ');
5975 __init_pat(__neg_format_, __curr_symbol_, true,
5976 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5977 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005978#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005979}
5980
5981void __do_nothing(void*) {}
5982
5983void __throw_runtime_error(const char* msg)
5984{
Howard Hinnantd4444702010-08-11 17:04:31 +00005985#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005986 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00005987#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005988}
5989
5990template class collate<char>;
5991template class collate<wchar_t>;
5992
5993template class num_get<char>;
5994template class num_get<wchar_t>;
5995
Howard Hinnantec3773c2011-12-01 20:21:04 +00005996template struct __num_get<char>;
5997template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005998
5999template class num_put<char>;
6000template class num_put<wchar_t>;
6001
Howard Hinnantec3773c2011-12-01 20:21:04 +00006002template struct __num_put<char>;
6003template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006004
6005template class time_get<char>;
6006template class time_get<wchar_t>;
6007
6008template class time_get_byname<char>;
6009template class time_get_byname<wchar_t>;
6010
6011template class time_put<char>;
6012template class time_put<wchar_t>;
6013
6014template class time_put_byname<char>;
6015template class time_put_byname<wchar_t>;
6016
6017template class moneypunct<char, false>;
6018template class moneypunct<char, true>;
6019template class moneypunct<wchar_t, false>;
6020template class moneypunct<wchar_t, true>;
6021
6022template class moneypunct_byname<char, false>;
6023template class moneypunct_byname<char, true>;
6024template class moneypunct_byname<wchar_t, false>;
6025template class moneypunct_byname<wchar_t, true>;
6026
6027template class money_get<char>;
6028template class money_get<wchar_t>;
6029
6030template class __money_get<char>;
6031template class __money_get<wchar_t>;
6032
6033template class money_put<char>;
6034template class money_put<wchar_t>;
6035
6036template class __money_put<char>;
6037template class __money_put<wchar_t>;
6038
6039template class messages<char>;
6040template class messages<wchar_t>;
6041
6042template class messages_byname<char>;
6043template class messages_byname<wchar_t>;
6044
6045template class codecvt_byname<char, char, mbstate_t>;
6046template class codecvt_byname<wchar_t, char, mbstate_t>;
6047template class codecvt_byname<char16_t, char, mbstate_t>;
6048template class codecvt_byname<char32_t, char, mbstate_t>;
6049
6050template class __vector_base_common<true>;
6051
6052_LIBCPP_END_NAMESPACE_STD