blob: e75f27ff832d38c9285e1142cd79065763ba6971 [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
84}
85
Howard Hinnant0a69fa12012-12-12 21:14:28 +000086const locale::category locale::none;
87const locale::category locale::collate;
88const locale::category locale::ctype;
89const locale::category locale::monetary;
90const locale::category locale::numeric;
91const locale::category locale::time;
92const locale::category locale::messages;
93const locale::category locale::all;
94
Howard Hinnantec3773c2011-12-01 20:21:04 +000095#pragma clang diagnostic push
96#pragma clang diagnostic ignored "-Wpadded"
97
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000098class _LIBCPP_HIDDEN locale::__imp
99 : public facet
100{
101 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000102 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000103 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000104public:
105 explicit __imp(size_t refs = 0);
106 explicit __imp(const string& name, size_t refs = 0);
107 __imp(const __imp&);
108 __imp(const __imp&, const string&, locale::category c);
109 __imp(const __imp& other, const __imp& one, locale::category c);
110 __imp(const __imp&, facet* f, long id);
111 ~__imp();
112
113 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000114 bool has_facet(long id) const
115 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116 const locale::facet* use_facet(long id) const;
117
118 static const locale& make_classic();
119 static locale& make_global();
120private:
121 void install(facet* f, long id);
122 template <class F> void install(F* f) {install(f, f->id.__get());}
123 template <class F> void install_from(const __imp& other);
124};
125
Howard Hinnantec3773c2011-12-01 20:21:04 +0000126#pragma clang diagnostic pop
127
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000128locale::__imp::__imp(size_t refs)
129 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000130 facets_(N),
131 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000132{
133 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000134 install(&make<_VSTD::collate<char> >(1u));
135 install(&make<_VSTD::collate<wchar_t> >(1u));
136 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
137 install(&make<_VSTD::ctype<wchar_t> >(1u));
138 install(&make<codecvt<char, char, mbstate_t> >(1u));
139 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
140 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
141 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
142 install(&make<numpunct<char> >(1u));
143 install(&make<numpunct<wchar_t> >(1u));
144 install(&make<num_get<char> >(1u));
145 install(&make<num_get<wchar_t> >(1u));
146 install(&make<num_put<char> >(1u));
147 install(&make<num_put<wchar_t> >(1u));
148 install(&make<moneypunct<char, false> >(1u));
149 install(&make<moneypunct<char, true> >(1u));
150 install(&make<moneypunct<wchar_t, false> >(1u));
151 install(&make<moneypunct<wchar_t, true> >(1u));
152 install(&make<money_get<char> >(1u));
153 install(&make<money_get<wchar_t> >(1u));
154 install(&make<money_put<char> >(1u));
155 install(&make<money_put<wchar_t> >(1u));
156 install(&make<time_get<char> >(1u));
157 install(&make<time_get<wchar_t> >(1u));
158 install(&make<time_put<char> >(1u));
159 install(&make<time_put<wchar_t> >(1u));
160 install(&make<_VSTD::messages<char> >(1u));
161 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000162}
163
164locale::__imp::__imp(const string& name, size_t refs)
165 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000166 facets_(N),
167 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000168{
Howard Hinnantd4444702010-08-11 17:04:31 +0000169#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000170 try
171 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000172#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000173 facets_ = locale::classic().__locale_->facets_;
174 for (unsigned i = 0; i < facets_.size(); ++i)
175 if (facets_[i])
176 facets_[i]->__add_shared();
177 install(new collate_byname<char>(name_));
178 install(new collate_byname<wchar_t>(name_));
179 install(new ctype_byname<char>(name_));
180 install(new ctype_byname<wchar_t>(name_));
181 install(new codecvt_byname<char, char, mbstate_t>(name_));
182 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
183 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
184 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
185 install(new numpunct_byname<char>(name_));
186 install(new numpunct_byname<wchar_t>(name_));
187 install(new moneypunct_byname<char, false>(name_));
188 install(new moneypunct_byname<char, true>(name_));
189 install(new moneypunct_byname<wchar_t, false>(name_));
190 install(new moneypunct_byname<wchar_t, true>(name_));
191 install(new time_get_byname<char>(name_));
192 install(new time_get_byname<wchar_t>(name_));
193 install(new time_put_byname<char>(name_));
194 install(new time_put_byname<wchar_t>(name_));
195 install(new messages_byname<char>(name_));
196 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000197#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000198 }
199 catch (...)
200 {
201 for (unsigned i = 0; i < facets_.size(); ++i)
202 if (facets_[i])
203 facets_[i]->__release_shared();
204 throw;
205 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000206#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000207}
208
209locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000210 : facets_(max<size_t>(N, other.facets_.size())),
211 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000212{
213 facets_ = other.facets_;
214 for (unsigned i = 0; i < facets_.size(); ++i)
215 if (facets_[i])
216 facets_[i]->__add_shared();
217}
218
219locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000220 : facets_(N),
221 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000222{
223 facets_ = other.facets_;
224 for (unsigned i = 0; i < facets_.size(); ++i)
225 if (facets_[i])
226 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000227#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000228 try
229 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000230#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000231 if (c & locale::collate)
232 {
233 install(new collate_byname<char>(name));
234 install(new collate_byname<wchar_t>(name));
235 }
236 if (c & locale::ctype)
237 {
238 install(new ctype_byname<char>(name));
239 install(new ctype_byname<wchar_t>(name));
240 install(new codecvt_byname<char, char, mbstate_t>(name));
241 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
242 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
243 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
244 }
245 if (c & locale::monetary)
246 {
247 install(new moneypunct_byname<char, false>(name));
248 install(new moneypunct_byname<char, true>(name));
249 install(new moneypunct_byname<wchar_t, false>(name));
250 install(new moneypunct_byname<wchar_t, true>(name));
251 }
252 if (c & locale::numeric)
253 {
254 install(new numpunct_byname<char>(name));
255 install(new numpunct_byname<wchar_t>(name));
256 }
257 if (c & locale::time)
258 {
259 install(new time_get_byname<char>(name));
260 install(new time_get_byname<wchar_t>(name));
261 install(new time_put_byname<char>(name));
262 install(new time_put_byname<wchar_t>(name));
263 }
264 if (c & locale::messages)
265 {
266 install(new messages_byname<char>(name));
267 install(new messages_byname<wchar_t>(name));
268 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000269#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000270 }
271 catch (...)
272 {
273 for (unsigned i = 0; i < facets_.size(); ++i)
274 if (facets_[i])
275 facets_[i]->__release_shared();
276 throw;
277 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000278#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000279}
280
281template<class F>
282inline
283void
284locale::__imp::install_from(const locale::__imp& one)
285{
286 long id = F::id.__get();
287 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
288}
289
290locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000291 : facets_(N),
292 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000293{
294 facets_ = other.facets_;
295 for (unsigned i = 0; i < facets_.size(); ++i)
296 if (facets_[i])
297 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000298#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000299 try
300 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000301#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000302 if (c & locale::collate)
303 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000304 install_from<_VSTD::collate<char> >(one);
305 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000306 }
307 if (c & locale::ctype)
308 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000309 install_from<_VSTD::ctype<char> >(one);
310 install_from<_VSTD::ctype<wchar_t> >(one);
311 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
312 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
313 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
314 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000315 }
316 if (c & locale::monetary)
317 {
318 install_from<moneypunct<char, false> >(one);
319 install_from<moneypunct<char, true> >(one);
320 install_from<moneypunct<wchar_t, false> >(one);
321 install_from<moneypunct<wchar_t, true> >(one);
322 install_from<money_get<char> >(one);
323 install_from<money_get<wchar_t> >(one);
324 install_from<money_put<char> >(one);
325 install_from<money_put<wchar_t> >(one);
326 }
327 if (c & locale::numeric)
328 {
329 install_from<numpunct<char> >(one);
330 install_from<numpunct<wchar_t> >(one);
331 install_from<num_get<char> >(one);
332 install_from<num_get<wchar_t> >(one);
333 install_from<num_put<char> >(one);
334 install_from<num_put<wchar_t> >(one);
335 }
336 if (c & locale::time)
337 {
338 install_from<time_get<char> >(one);
339 install_from<time_get<wchar_t> >(one);
340 install_from<time_put<char> >(one);
341 install_from<time_put<wchar_t> >(one);
342 }
343 if (c & locale::messages)
344 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000345 install_from<_VSTD::messages<char> >(one);
346 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000347 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000348#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000349 }
350 catch (...)
351 {
352 for (unsigned i = 0; i < facets_.size(); ++i)
353 if (facets_[i])
354 facets_[i]->__release_shared();
355 throw;
356 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000357#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000358}
359
360locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000361 : facets_(max<size_t>(N, other.facets_.size()+1)),
362 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000363{
364 f->__add_shared();
365 unique_ptr<facet, release> hold(f);
366 facets_ = other.facets_;
367 for (unsigned i = 0; i < other.facets_.size(); ++i)
368 if (facets_[i])
369 facets_[i]->__add_shared();
370 install(hold.get(), id);
371}
372
373locale::__imp::~__imp()
374{
375 for (unsigned i = 0; i < facets_.size(); ++i)
376 if (facets_[i])
377 facets_[i]->__release_shared();
378}
379
380void
381locale::__imp::install(facet* f, long id)
382{
383 f->__add_shared();
384 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000385 if (static_cast<size_t>(id) >= facets_.size())
386 facets_.resize(static_cast<size_t>(id+1));
387 if (facets_[static_cast<size_t>(id)])
388 facets_[static_cast<size_t>(id)]->__release_shared();
389 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000390}
391
392const locale::facet*
393locale::__imp::use_facet(long id) const
394{
Howard Hinnantd4444702010-08-11 17:04:31 +0000395#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000396 if (!has_facet(id))
397 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000398#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000399 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000400}
401
402// locale
403
404const locale&
405locale::__imp::make_classic()
406{
407 // only one thread can get in here and it only gets in once
408 static aligned_storage<sizeof(locale)>::type buf;
409 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000410 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000411 return *c;
412}
413
414const locale&
415locale::classic()
416{
417 static const locale& c = __imp::make_classic();
418 return c;
419}
420
421locale&
422locale::__imp::make_global()
423{
424 // only one thread can get in here and it only gets in once
425 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000426 ::new (&buf) locale(locale::classic());
427 return *(locale*)&buf;
428}
429
430locale&
431locale::__global()
432{
433 static locale& g = __imp::make_global();
434 return g;
435}
436
Howard Hinnantc9834542011-05-31 15:34:58 +0000437locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000438 : __locale_(__global().__locale_)
439{
440 __locale_->__add_shared();
441}
442
Howard Hinnantc9834542011-05-31 15:34:58 +0000443locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000444 : __locale_(l.__locale_)
445{
446 __locale_->__add_shared();
447}
448
Howard Hinnantc9834542011-05-31 15:34:58 +0000449locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000450{
451 __locale_->__release_shared();
452}
453
454const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000455locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000456{
457 other.__locale_->__add_shared();
458 __locale_->__release_shared();
459 __locale_ = other.__locale_;
460 return *this;
461}
462
463locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000464#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000465 : __locale_(name ? new __imp(name)
466 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000467#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000468 : __locale_(new __imp(name))
469#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000470{
471 __locale_->__add_shared();
472}
473
474locale::locale(const string& name)
475 : __locale_(new __imp(name))
476{
477 __locale_->__add_shared();
478}
479
480locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000481#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000482 : __locale_(name ? new __imp(*other.__locale_, name, c)
483 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000484#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000485 : __locale_(new __imp(*other.__locale_, name, c))
486#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000487{
488 __locale_->__add_shared();
489}
490
491locale::locale(const locale& other, const string& name, category c)
492 : __locale_(new __imp(*other.__locale_, name, c))
493{
494 __locale_->__add_shared();
495}
496
497locale::locale(const locale& other, const locale& one, category c)
498 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
499{
500 __locale_->__add_shared();
501}
502
503string
504locale::name() const
505{
506 return __locale_->name();
507}
508
509void
510locale::__install_ctor(const locale& other, facet* f, long id)
511{
512 if (f)
513 __locale_ = new __imp(*other.__locale_, f, id);
514 else
515 __locale_ = other.__locale_;
516 __locale_->__add_shared();
517}
518
519locale
520locale::global(const locale& loc)
521{
522 locale& g = __global();
523 locale r = g;
524 g = loc;
525 if (g.name() != "*")
526 setlocale(LC_ALL, g.name().c_str());
527 return r;
528}
529
530bool
531locale::has_facet(id& x) const
532{
533 return __locale_->has_facet(x.__get());
534}
535
536const locale::facet*
537locale::use_facet(id& x) const
538{
539 return __locale_->use_facet(x.__get());
540}
541
542bool
543locale::operator==(const locale& y) const
544{
545 return (__locale_ == y.__locale_)
546 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
547}
548
549// locale::facet
550
551locale::facet::~facet()
552{
553}
554
555void
Howard Hinnant1694d232011-05-28 14:41:13 +0000556locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000557{
558 delete this;
559}
560
561// locale::id
562
563int32_t locale::id::__next_id = 0;
564
565namespace
566{
567
568class __fake_bind
569{
570 locale::id* id_;
571 void (locale::id::* pmf_)();
572public:
573 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
574 : id_(id), pmf_(pmf) {}
575
576 void operator()() const
577 {
578 (id_->*pmf_)();
579 }
580};
581
582}
583
584long
585locale::id::__get()
586{
587 call_once(__flag_, __fake_bind(&locale::id::__init, this));
588 return __id_ - 1;
589}
590
591void
592locale::id::__init()
593{
Howard Hinnantadff4892010-05-24 17:49:41 +0000594 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000595}
596
597// template <> class collate_byname<char>
598
599collate_byname<char>::collate_byname(const char* n, size_t refs)
600 : collate<char>(refs),
601 __l(newlocale(LC_ALL_MASK, n, 0))
602{
Howard Hinnantd4444702010-08-11 17:04:31 +0000603#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000604 if (__l == 0)
605 throw runtime_error("collate_byname<char>::collate_byname"
606 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000607#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000608}
609
610collate_byname<char>::collate_byname(const string& name, size_t refs)
611 : collate<char>(refs),
612 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
613{
Howard Hinnantd4444702010-08-11 17:04:31 +0000614#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000615 if (__l == 0)
616 throw runtime_error("collate_byname<char>::collate_byname"
617 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000618#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000619}
620
621collate_byname<char>::~collate_byname()
622{
623 freelocale(__l);
624}
625
626int
627collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
628 const char_type* __lo2, const char_type* __hi2) const
629{
630 string_type lhs(__lo1, __hi1);
631 string_type rhs(__lo2, __hi2);
632 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
633 if (r < 0)
634 return -1;
635 if (r > 0)
636 return 1;
637 return r;
638}
639
640collate_byname<char>::string_type
641collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
642{
643 const string_type in(lo, hi);
644 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
645 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
646 return out;
647}
648
649// template <> class collate_byname<wchar_t>
650
651collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
652 : collate<wchar_t>(refs),
653 __l(newlocale(LC_ALL_MASK, n, 0))
654{
Howard Hinnantd4444702010-08-11 17:04:31 +0000655#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000656 if (__l == 0)
657 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
658 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000659#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000660}
661
662collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
663 : collate<wchar_t>(refs),
664 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
665{
Howard Hinnantd4444702010-08-11 17:04:31 +0000666#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000667 if (__l == 0)
668 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
669 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000670#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000671}
672
673collate_byname<wchar_t>::~collate_byname()
674{
675 freelocale(__l);
676}
677
678int
679collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
680 const char_type* __lo2, const char_type* __hi2) const
681{
682 string_type lhs(__lo1, __hi1);
683 string_type rhs(__lo2, __hi2);
684 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
685 if (r < 0)
686 return -1;
687 if (r > 0)
688 return 1;
689 return r;
690}
691
692collate_byname<wchar_t>::string_type
693collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
694{
695 const string_type in(lo, hi);
696 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
697 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
698 return out;
699}
700
701// template <> class ctype<wchar_t>;
702
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000703const ctype_base::mask ctype_base::space;
704const ctype_base::mask ctype_base::print;
705const ctype_base::mask ctype_base::cntrl;
706const ctype_base::mask ctype_base::upper;
707const ctype_base::mask ctype_base::lower;
708const ctype_base::mask ctype_base::alpha;
709const ctype_base::mask ctype_base::digit;
710const ctype_base::mask ctype_base::punct;
711const ctype_base::mask ctype_base::xdigit;
712const ctype_base::mask ctype_base::blank;
713const ctype_base::mask ctype_base::alnum;
714const ctype_base::mask ctype_base::graph;
715
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000716locale::id ctype<wchar_t>::id;
717
718ctype<wchar_t>::~ctype()
719{
720}
721
722bool
723ctype<wchar_t>::do_is(mask m, char_type c) const
724{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000725 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000726}
727
728const wchar_t*
729ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
730{
731 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000732 *vec = static_cast<mask>(isascii(*low) ?
733 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000734 return low;
735}
736
737const wchar_t*
738ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
739{
740 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000741 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000742 break;
743 return low;
744}
745
746const wchar_t*
747ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
748{
749 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000750 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000751 break;
752 return low;
753}
754
755wchar_t
756ctype<wchar_t>::do_toupper(char_type c) const
757{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000758#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
759 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
760#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000761 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000762#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000763 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000764#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000765}
766
767const wchar_t*
768ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
769{
770 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000771#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
772 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
773#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000774 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
775 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000776#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000777 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000778#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000779 return low;
780}
781
782wchar_t
783ctype<wchar_t>::do_tolower(char_type c) const
784{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000785#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
786 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
787#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000788 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000789#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000790 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000791#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000792}
793
794const wchar_t*
795ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
796{
797 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000798#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
799 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
800#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000801 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
802 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000803#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000804 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000805#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000806 return low;
807}
808
809wchar_t
810ctype<wchar_t>::do_widen(char c) const
811{
812 return c;
813}
814
815const char*
816ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
817{
818 for (; low != high; ++low, ++dest)
819 *dest = *low;
820 return low;
821}
822
823char
824ctype<wchar_t>::do_narrow(char_type c, char dfault) const
825{
826 if (isascii(c))
827 return static_cast<char>(c);
828 return dfault;
829}
830
831const wchar_t*
832ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
833{
834 for (; low != high; ++low, ++dest)
835 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000836 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000837 else
838 *dest = dfault;
839 return low;
840}
841
842// template <> class ctype<char>;
843
844locale::id ctype<char>::id;
845
846ctype<char>::ctype(const mask* tab, bool del, size_t refs)
847 : locale::facet(refs),
848 __tab_(tab),
849 __del_(del)
850{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000851 if (__tab_ == 0)
852 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000853}
854
855ctype<char>::~ctype()
856{
857 if (__tab_ && __del_)
858 delete [] __tab_;
859}
860
861char
862ctype<char>::do_toupper(char_type c) const
863{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000864#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000865 return isascii(c) ?
866 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000867#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000868 return isascii(c) ? __classic_upper_table()[static_cast<size_t>(c)] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000869#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000870 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000871#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000872}
873
874const char*
875ctype<char>::do_toupper(char_type* low, const char_type* high) const
876{
877 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000878#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000879 *low = isascii(*low) ?
880 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000881#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000882 *low = isascii(*low) ? __classic_upper_table()[static_cast<size_t>(*low)] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000883#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000884 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000885#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000886 return low;
887}
888
889char
890ctype<char>::do_tolower(char_type c) const
891{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000892#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000893 return isascii(c) ?
894 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000895#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000896 return isascii(c) ? __classic_lower_table()[static_cast<size_t>(c)] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000897#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000898 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000899#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000900}
901
902const char*
903ctype<char>::do_tolower(char_type* low, const char_type* high) const
904{
905 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000906#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000907 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000908#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000909 *low = isascii(*low) ? __classic_lower_table()[static_cast<size_t>(*low)] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000910#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000911 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000912#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000913 return low;
914}
915
916char
917ctype<char>::do_widen(char c) const
918{
919 return c;
920}
921
922const char*
923ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
924{
925 for (; low != high; ++low, ++dest)
926 *dest = *low;
927 return low;
928}
929
930char
931ctype<char>::do_narrow(char_type c, char dfault) const
932{
933 if (isascii(c))
934 return static_cast<char>(c);
935 return dfault;
936}
937
938const char*
939ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
940{
941 for (; low != high; ++low, ++dest)
942 if (isascii(*low))
943 *dest = *low;
944 else
945 *dest = dfault;
946 return low;
947}
948
949const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000950ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000951{
David Chisnallc512df12011-09-21 08:39:44 +0000952#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000953 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000954#elif defined(__GLIBC__)
955 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +0000956#elif __sun__
957 return __ctype_mask;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000958#elif _WIN32
959 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +0000960// This is assumed to be safe, which is a nonsense assumption because we're
961// going to end up dereferencing it later...
Sean Hunt62a6ac32011-07-09 00:56:23 +0000962#else
David Chisnall997e4542012-02-29 13:05:08 +0000963 // Platform not supported: abort so the person doing the port knows what to
964 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +0000965# warning ctype<char>::classic_table() is not implemented
David Chisnall997e4542012-02-29 13:05:08 +0000966 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +0000967 return NULL;
968#endif
969}
970
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000971#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000972const int*
973ctype<char>::__classic_lower_table() _NOEXCEPT
974{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000975 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000976}
977
978const int*
979ctype<char>::__classic_upper_table() _NOEXCEPT
980{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000981 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000982}
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000983#endif // __GLIBC__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000984
985// template <> class ctype_byname<char>
986
987ctype_byname<char>::ctype_byname(const char* name, size_t refs)
988 : ctype<char>(0, false, refs),
989 __l(newlocale(LC_ALL_MASK, name, 0))
990{
Howard Hinnantd4444702010-08-11 17:04:31 +0000991#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000992 if (__l == 0)
993 throw runtime_error("ctype_byname<char>::ctype_byname"
994 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000995#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000996}
997
998ctype_byname<char>::ctype_byname(const string& name, size_t refs)
999 : ctype<char>(0, false, refs),
1000 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1001{
Howard Hinnantd4444702010-08-11 17:04:31 +00001002#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001003 if (__l == 0)
1004 throw runtime_error("ctype_byname<char>::ctype_byname"
1005 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001006#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001007}
1008
1009ctype_byname<char>::~ctype_byname()
1010{
1011 freelocale(__l);
1012}
1013
1014char
1015ctype_byname<char>::do_toupper(char_type c) const
1016{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001017 return static_cast<char>(toupper_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001018}
1019
1020const char*
1021ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1022{
1023 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001024 *low = static_cast<char>(toupper_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025 return low;
1026}
1027
1028char
1029ctype_byname<char>::do_tolower(char_type c) const
1030{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001031 return static_cast<char>(tolower_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001032}
1033
1034const char*
1035ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1036{
1037 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001038 *low = static_cast<char>(tolower_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001039 return low;
1040}
1041
1042// template <> class ctype_byname<wchar_t>
1043
1044ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1045 : ctype<wchar_t>(refs),
1046 __l(newlocale(LC_ALL_MASK, name, 0))
1047{
Howard Hinnantd4444702010-08-11 17:04:31 +00001048#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001049 if (__l == 0)
1050 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1051 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001052#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001053}
1054
1055ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1056 : ctype<wchar_t>(refs),
1057 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1058{
Howard Hinnantd4444702010-08-11 17:04:31 +00001059#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001060 if (__l == 0)
1061 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1062 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001063#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001064}
1065
1066ctype_byname<wchar_t>::~ctype_byname()
1067{
1068 freelocale(__l);
1069}
1070
1071bool
1072ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1073{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001074#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001075 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001076#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001077 bool result = false;
1078 if (m & space) result |= (iswspace_l(c, __l) != 0);
1079 if (m & print) result |= (iswprint_l(c, __l) != 0);
1080 if (m & cntrl) result |= (iswcntrl_l(c, __l) != 0);
1081 if (m & upper) result |= (iswupper_l(c, __l) != 0);
1082 if (m & lower) result |= (iswlower_l(c, __l) != 0);
1083 if (m & alpha) result |= (iswalpha_l(c, __l) != 0);
1084 if (m & digit) result |= (iswdigit_l(c, __l) != 0);
1085 if (m & punct) result |= (iswpunct_l(c, __l) != 0);
1086 if (m & xdigit) result |= (iswxdigit_l(c, __l) != 0);
1087 if (m & blank) result |= (iswblank_l(c, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001088 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001089#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001090}
1091
1092const wchar_t*
1093ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1094{
1095 for (; low != high; ++low, ++vec)
1096 {
1097 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001098 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001099 else
1100 {
1101 *vec = 0;
1102 if (iswspace_l(*low, __l))
1103 *vec |= space;
1104 if (iswprint_l(*low, __l))
1105 *vec |= print;
1106 if (iswcntrl_l(*low, __l))
1107 *vec |= cntrl;
1108 if (iswupper_l(*low, __l))
1109 *vec |= upper;
1110 if (iswlower_l(*low, __l))
1111 *vec |= lower;
1112 if (iswalpha_l(*low, __l))
1113 *vec |= alpha;
1114 if (iswdigit_l(*low, __l))
1115 *vec |= digit;
1116 if (iswpunct_l(*low, __l))
1117 *vec |= punct;
1118 if (iswxdigit_l(*low, __l))
1119 *vec |= xdigit;
1120 }
1121 }
1122 return low;
1123}
1124
1125const wchar_t*
1126ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1127{
1128 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001129 {
1130#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001131 if (iswctype_l(*low, m, __l))
1132 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001133#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001134 if (m & space && iswspace_l(*low, __l)) break;
1135 if (m & print && iswprint_l(*low, __l)) break;
1136 if (m & cntrl && iswcntrl_l(*low, __l)) break;
1137 if (m & upper && iswupper_l(*low, __l)) break;
1138 if (m & lower && iswlower_l(*low, __l)) break;
1139 if (m & alpha && iswalpha_l(*low, __l)) break;
1140 if (m & digit && iswdigit_l(*low, __l)) break;
1141 if (m & punct && iswpunct_l(*low, __l)) break;
1142 if (m & xdigit && iswxdigit_l(*low, __l)) break;
1143 if (m & blank && iswblank_l(*low, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001144#endif
1145 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001146 return low;
1147}
1148
1149const wchar_t*
1150ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1151{
1152 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001153 {
1154#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001155 if (!iswctype_l(*low, m, __l))
1156 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001157#else
1158 if (m & space && iswspace_l(*low, __l)) continue;
1159 if (m & print && iswprint_l(*low, __l)) continue;
1160 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1161 if (m & upper && iswupper_l(*low, __l)) continue;
1162 if (m & lower && iswlower_l(*low, __l)) continue;
1163 if (m & alpha && iswalpha_l(*low, __l)) continue;
1164 if (m & digit && iswdigit_l(*low, __l)) continue;
1165 if (m & punct && iswpunct_l(*low, __l)) continue;
1166 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1167 if (m & blank && iswblank_l(*low, __l)) continue;
1168 break;
1169#endif
1170 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001171 return low;
1172}
1173
1174wchar_t
1175ctype_byname<wchar_t>::do_toupper(char_type c) const
1176{
1177 return towupper_l(c, __l);
1178}
1179
1180const wchar_t*
1181ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1182{
1183 for (; low != high; ++low)
1184 *low = towupper_l(*low, __l);
1185 return low;
1186}
1187
1188wchar_t
1189ctype_byname<wchar_t>::do_tolower(char_type c) const
1190{
1191 return towlower_l(c, __l);
1192}
1193
1194const wchar_t*
1195ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1196{
1197 for (; low != high; ++low)
1198 *low = towlower_l(*low, __l);
1199 return low;
1200}
1201
1202wchar_t
1203ctype_byname<wchar_t>::do_widen(char c) const
1204{
Howard Hinnant866569b2011-09-28 23:39:33 +00001205#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001206 return btowc_l(c, __l);
1207#else
1208 return __btowc_l(c, __l);
1209#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001210}
1211
1212const char*
1213ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1214{
1215 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001216#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001217 *dest = btowc_l(*low, __l);
1218#else
1219 *dest = __btowc_l(*low, __l);
1220#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001221 return low;
1222}
1223
1224char
1225ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1226{
Howard Hinnant866569b2011-09-28 23:39:33 +00001227#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001228 int r = wctob_l(c, __l);
1229#else
1230 int r = __wctob_l(c, __l);
1231#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001232 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001233}
1234
1235const wchar_t*
1236ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1237{
1238 for (; low != high; ++low, ++dest)
1239 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001240#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001241 int r = wctob_l(*low, __l);
1242#else
1243 int r = __wctob_l(*low, __l);
1244#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001245 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001246 }
1247 return low;
1248}
1249
1250// template <> class codecvt<char, char, mbstate_t>
1251
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001252locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001253
1254codecvt<char, char, mbstate_t>::~codecvt()
1255{
1256}
1257
1258codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001259codecvt<char, char, mbstate_t>::do_out(state_type&,
1260 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001261 extern_type* to, extern_type*, extern_type*& to_nxt) const
1262{
1263 frm_nxt = frm;
1264 to_nxt = to;
1265 return noconv;
1266}
1267
1268codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001269codecvt<char, char, mbstate_t>::do_in(state_type&,
1270 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001271 intern_type* to, intern_type*, intern_type*& to_nxt) const
1272{
1273 frm_nxt = frm;
1274 to_nxt = to;
1275 return noconv;
1276}
1277
1278codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001279codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001280 extern_type* to, extern_type*, extern_type*& to_nxt) const
1281{
1282 to_nxt = to;
1283 return noconv;
1284}
1285
1286int
Howard Hinnantc9834542011-05-31 15:34:58 +00001287codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001288{
1289 return 1;
1290}
1291
1292bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001293codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001294{
1295 return true;
1296}
1297
1298int
1299codecvt<char, char, mbstate_t>::do_length(state_type&,
1300 const extern_type* frm, const extern_type* end, size_t mx) const
1301{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001302 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001303}
1304
1305int
Howard Hinnantc9834542011-05-31 15:34:58 +00001306codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001307{
1308 return 1;
1309}
1310
1311// template <> class codecvt<wchar_t, char, mbstate_t>
1312
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001313locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001314
1315codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1316 : locale::facet(refs),
1317 __l(0)
1318{
1319}
1320
1321codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1322 : locale::facet(refs),
1323 __l(newlocale(LC_ALL_MASK, nm, 0))
1324{
Howard Hinnantd4444702010-08-11 17:04:31 +00001325#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001326 if (__l == 0)
1327 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1328 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001329#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001330}
1331
1332codecvt<wchar_t, char, mbstate_t>::~codecvt()
1333{
1334 if (__l != 0)
1335 freelocale(__l);
1336}
1337
1338codecvt<wchar_t, char, mbstate_t>::result
1339codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001340 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001341 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1342{
1343 // look for first internal null in frm
1344 const intern_type* fend = frm;
1345 for (; fend != frm_end; ++fend)
1346 if (*fend == 0)
1347 break;
1348 // loop over all null-terminated sequences in frm
1349 to_nxt = to;
1350 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1351 {
1352 // save state in case needed to reover to_nxt on error
1353 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001354#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001355 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1356 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001357#else
1358 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1359#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001360 if (n == size_t(-1))
1361 {
1362 // need to recover to_nxt
1363 for (to_nxt = to; frm != frm_nxt; ++frm)
1364 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001365#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001366 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1367#else
1368 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1369#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001370 if (n == size_t(-1))
1371 break;
1372 to_nxt += n;
1373 }
1374 frm_nxt = frm;
1375 return error;
1376 }
1377 if (n == 0)
1378 return partial;
1379 to_nxt += n;
1380 if (to_nxt == to_end)
1381 break;
1382 if (fend != frm_end) // set up next null terminated sequence
1383 {
1384 // Try to write the terminating null
1385 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001386#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001387 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1388#else
1389 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1390#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001391 if (n == size_t(-1)) // on error
1392 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001393 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001394 return partial;
1395 for (extern_type* p = tmp; n; --n) // write it
1396 *to_nxt++ = *p++;
1397 ++frm_nxt;
1398 // look for next null in frm
1399 for (fend = frm_nxt; fend != frm_end; ++fend)
1400 if (*fend == 0)
1401 break;
1402 }
1403 }
1404 return frm_nxt == frm_end ? ok : partial;
1405}
1406
1407codecvt<wchar_t, char, mbstate_t>::result
1408codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001409 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001410 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1411{
1412 // look for first internal null in frm
1413 const extern_type* fend = frm;
1414 for (; fend != frm_end; ++fend)
1415 if (*fend == 0)
1416 break;
1417 // loop over all null-terminated sequences in frm
1418 to_nxt = to;
1419 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1420 {
1421 // save state in case needed to reover to_nxt on error
1422 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001423#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001424 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1425 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001426#else
1427 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1428#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001429 if (n == size_t(-1))
1430 {
1431 // need to recover to_nxt
1432 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1433 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001434#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001435 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1436 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001437#else
1438 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1439#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001440 switch (n)
1441 {
1442 case 0:
1443 ++frm;
1444 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001445 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001446 frm_nxt = frm;
1447 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001448 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001449 frm_nxt = frm;
1450 return partial;
1451 default:
1452 frm += n;
1453 break;
1454 }
1455 }
1456 frm_nxt = frm;
1457 return frm_nxt == frm_end ? ok : partial;
1458 }
1459 if (n == 0)
1460 return error;
1461 to_nxt += n;
1462 if (to_nxt == to_end)
1463 break;
1464 if (fend != frm_end) // set up next null terminated sequence
1465 {
1466 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001467#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001468 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1469#else
1470 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1471#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001472 if (n != 0) // on error
1473 return error;
1474 ++to_nxt;
1475 ++frm_nxt;
1476 // look for next null in frm
1477 for (fend = frm_nxt; fend != frm_end; ++fend)
1478 if (*fend == 0)
1479 break;
1480 }
1481 }
1482 return frm_nxt == frm_end ? ok : partial;
1483}
1484
1485codecvt<wchar_t, char, mbstate_t>::result
1486codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1487 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1488{
1489 to_nxt = to;
1490 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001491#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001492 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1493#else
1494 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1495#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001496 if (n == size_t(-1) || n == 0) // on error
1497 return error;
1498 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001499 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001500 return partial;
1501 for (extern_type* p = tmp; n; --n) // write it
1502 *to_nxt++ = *p++;
1503 return ok;
1504}
1505
1506int
Howard Hinnantc9834542011-05-31 15:34:58 +00001507codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001508{
Howard Hinnant866569b2011-09-28 23:39:33 +00001509#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001510 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1511#else
1512 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1513#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001514 {
1515 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001516#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001517 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1518#else
1519 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1520#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001521 return 1; // which take more than 1 char to form a wchar_t
1522 return 0;
1523 }
1524 return -1;
1525}
1526
1527bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001528codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001529{
1530 return false;
1531}
1532
1533int
1534codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1535 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1536{
1537 int nbytes = 0;
1538 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1539 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001540#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001541 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001542#else
1543 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1544#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001545 switch (n)
1546 {
1547 case 0:
1548 ++nbytes;
1549 ++frm;
1550 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001551 case size_t(-1):
1552 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001553 return nbytes;
1554 default:
1555 nbytes += n;
1556 frm += n;
1557 break;
1558 }
1559 }
1560 return nbytes;
1561}
1562
1563int
Howard Hinnantc9834542011-05-31 15:34:58 +00001564codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001565{
Howard Hinnant866569b2011-09-28 23:39:33 +00001566#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001567 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1568#else
1569 return __l == 0 ? 1 : __mb_cur_max_l(__l);
1570#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001571}
1572
1573// Valid UTF ranges
1574// UTF-32 UTF-16 UTF-8 # of code points
1575// first second first second third fourth
1576// 000000 - 00007F 0000 - 007F 00 - 7F 127
1577// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1578// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1579// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1580// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1581// 00D800 - 00DFFF invalid
1582// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1583// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1584// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1585// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1586
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001587static
1588codecvt_base::result
1589utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1590 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1591 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1592{
1593 frm_nxt = frm;
1594 to_nxt = to;
1595 if (mode & generate_header)
1596 {
1597 if (to_end-to_nxt < 3)
1598 return codecvt_base::partial;
1599 *to_nxt++ = static_cast<uint8_t>(0xEF);
1600 *to_nxt++ = static_cast<uint8_t>(0xBB);
1601 *to_nxt++ = static_cast<uint8_t>(0xBF);
1602 }
1603 for (; frm_nxt < frm_end; ++frm_nxt)
1604 {
1605 uint16_t wc1 = *frm_nxt;
1606 if (wc1 > Maxcode)
1607 return codecvt_base::error;
1608 if (wc1 < 0x0080)
1609 {
1610 if (to_end-to_nxt < 1)
1611 return codecvt_base::partial;
1612 *to_nxt++ = static_cast<uint8_t>(wc1);
1613 }
1614 else if (wc1 < 0x0800)
1615 {
1616 if (to_end-to_nxt < 2)
1617 return codecvt_base::partial;
1618 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1619 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1620 }
1621 else if (wc1 < 0xD800)
1622 {
1623 if (to_end-to_nxt < 3)
1624 return codecvt_base::partial;
1625 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1626 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1627 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1628 }
1629 else if (wc1 < 0xDC00)
1630 {
1631 if (frm_end-frm_nxt < 2)
1632 return codecvt_base::partial;
1633 uint16_t wc2 = frm_nxt[1];
1634 if ((wc2 & 0xFC00) != 0xDC00)
1635 return codecvt_base::error;
1636 if (to_end-to_nxt < 4)
1637 return codecvt_base::partial;
1638 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1639 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1640 return codecvt_base::error;
1641 ++frm_nxt;
1642 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1643 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1644 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1645 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1646 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1647 }
1648 else if (wc1 < 0xE000)
1649 {
1650 return codecvt_base::error;
1651 }
1652 else
1653 {
1654 if (to_end-to_nxt < 3)
1655 return codecvt_base::partial;
1656 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1657 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1658 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1659 }
1660 }
1661 return codecvt_base::ok;
1662}
1663
1664static
1665codecvt_base::result
1666utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1667 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1668 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1669{
1670 frm_nxt = frm;
1671 to_nxt = to;
1672 if (mode & generate_header)
1673 {
1674 if (to_end-to_nxt < 3)
1675 return codecvt_base::partial;
1676 *to_nxt++ = static_cast<uint8_t>(0xEF);
1677 *to_nxt++ = static_cast<uint8_t>(0xBB);
1678 *to_nxt++ = static_cast<uint8_t>(0xBF);
1679 }
1680 for (; frm_nxt < frm_end; ++frm_nxt)
1681 {
1682 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1683 if (wc1 > Maxcode)
1684 return codecvt_base::error;
1685 if (wc1 < 0x0080)
1686 {
1687 if (to_end-to_nxt < 1)
1688 return codecvt_base::partial;
1689 *to_nxt++ = static_cast<uint8_t>(wc1);
1690 }
1691 else if (wc1 < 0x0800)
1692 {
1693 if (to_end-to_nxt < 2)
1694 return codecvt_base::partial;
1695 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1696 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1697 }
1698 else if (wc1 < 0xD800)
1699 {
1700 if (to_end-to_nxt < 3)
1701 return codecvt_base::partial;
1702 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1703 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1704 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1705 }
1706 else if (wc1 < 0xDC00)
1707 {
1708 if (frm_end-frm_nxt < 2)
1709 return codecvt_base::partial;
1710 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1711 if ((wc2 & 0xFC00) != 0xDC00)
1712 return codecvt_base::error;
1713 if (to_end-to_nxt < 4)
1714 return codecvt_base::partial;
1715 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1716 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1717 return codecvt_base::error;
1718 ++frm_nxt;
1719 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1720 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1721 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1722 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1723 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1724 }
1725 else if (wc1 < 0xE000)
1726 {
1727 return codecvt_base::error;
1728 }
1729 else
1730 {
1731 if (to_end-to_nxt < 3)
1732 return codecvt_base::partial;
1733 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1734 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1735 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1736 }
1737 }
1738 return codecvt_base::ok;
1739}
1740
1741static
1742codecvt_base::result
1743utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1744 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1745 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1746{
1747 frm_nxt = frm;
1748 to_nxt = to;
1749 if (mode & consume_header)
1750 {
1751 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1752 frm_nxt[2] == 0xBF)
1753 frm_nxt += 3;
1754 }
1755 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1756 {
1757 uint8_t c1 = *frm_nxt;
1758 if (c1 > Maxcode)
1759 return codecvt_base::error;
1760 if (c1 < 0x80)
1761 {
1762 *to_nxt = static_cast<uint16_t>(c1);
1763 ++frm_nxt;
1764 }
1765 else if (c1 < 0xC2)
1766 {
1767 return codecvt_base::error;
1768 }
1769 else if (c1 < 0xE0)
1770 {
1771 if (frm_end-frm_nxt < 2)
1772 return codecvt_base::partial;
1773 uint8_t c2 = frm_nxt[1];
1774 if ((c2 & 0xC0) != 0x80)
1775 return codecvt_base::error;
1776 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1777 if (t > Maxcode)
1778 return codecvt_base::error;
1779 *to_nxt = t;
1780 frm_nxt += 2;
1781 }
1782 else if (c1 < 0xF0)
1783 {
1784 if (frm_end-frm_nxt < 3)
1785 return codecvt_base::partial;
1786 uint8_t c2 = frm_nxt[1];
1787 uint8_t c3 = frm_nxt[2];
1788 switch (c1)
1789 {
1790 case 0xE0:
1791 if ((c2 & 0xE0) != 0xA0)
1792 return codecvt_base::error;
1793 break;
1794 case 0xED:
1795 if ((c2 & 0xE0) != 0x80)
1796 return codecvt_base::error;
1797 break;
1798 default:
1799 if ((c2 & 0xC0) != 0x80)
1800 return codecvt_base::error;
1801 break;
1802 }
1803 if ((c3 & 0xC0) != 0x80)
1804 return codecvt_base::error;
1805 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1806 | ((c2 & 0x3F) << 6)
1807 | (c3 & 0x3F));
1808 if (t > Maxcode)
1809 return codecvt_base::error;
1810 *to_nxt = t;
1811 frm_nxt += 3;
1812 }
1813 else if (c1 < 0xF5)
1814 {
1815 if (frm_end-frm_nxt < 4)
1816 return codecvt_base::partial;
1817 uint8_t c2 = frm_nxt[1];
1818 uint8_t c3 = frm_nxt[2];
1819 uint8_t c4 = frm_nxt[3];
1820 switch (c1)
1821 {
1822 case 0xF0:
1823 if (!(0x90 <= c2 && c2 <= 0xBF))
1824 return codecvt_base::error;
1825 break;
1826 case 0xF4:
1827 if ((c2 & 0xF0) != 0x80)
1828 return codecvt_base::error;
1829 break;
1830 default:
1831 if ((c2 & 0xC0) != 0x80)
1832 return codecvt_base::error;
1833 break;
1834 }
1835 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1836 return codecvt_base::error;
1837 if (to_end-to_nxt < 2)
1838 return codecvt_base::partial;
1839 if (((((unsigned long)c1 & 7) << 18) +
1840 (((unsigned long)c2 & 0x3F) << 12) +
1841 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1842 return codecvt_base::error;
1843 *to_nxt = static_cast<uint16_t>(
1844 0xD800
1845 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1846 | ((c2 & 0x0F) << 2)
1847 | ((c3 & 0x30) >> 4));
1848 *++to_nxt = static_cast<uint16_t>(
1849 0xDC00
1850 | ((c3 & 0x0F) << 6)
1851 | (c4 & 0x3F));
1852 frm_nxt += 4;
1853 }
1854 else
1855 {
1856 return codecvt_base::error;
1857 }
1858 }
1859 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1860}
1861
1862static
1863codecvt_base::result
1864utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1865 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1866 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1867{
1868 frm_nxt = frm;
1869 to_nxt = to;
1870 if (mode & consume_header)
1871 {
1872 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1873 frm_nxt[2] == 0xBF)
1874 frm_nxt += 3;
1875 }
1876 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1877 {
1878 uint8_t c1 = *frm_nxt;
1879 if (c1 > Maxcode)
1880 return codecvt_base::error;
1881 if (c1 < 0x80)
1882 {
1883 *to_nxt = static_cast<uint32_t>(c1);
1884 ++frm_nxt;
1885 }
1886 else if (c1 < 0xC2)
1887 {
1888 return codecvt_base::error;
1889 }
1890 else if (c1 < 0xE0)
1891 {
1892 if (frm_end-frm_nxt < 2)
1893 return codecvt_base::partial;
1894 uint8_t c2 = frm_nxt[1];
1895 if ((c2 & 0xC0) != 0x80)
1896 return codecvt_base::error;
1897 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1898 if (t > Maxcode)
1899 return codecvt_base::error;
1900 *to_nxt = static_cast<uint32_t>(t);
1901 frm_nxt += 2;
1902 }
1903 else if (c1 < 0xF0)
1904 {
1905 if (frm_end-frm_nxt < 3)
1906 return codecvt_base::partial;
1907 uint8_t c2 = frm_nxt[1];
1908 uint8_t c3 = frm_nxt[2];
1909 switch (c1)
1910 {
1911 case 0xE0:
1912 if ((c2 & 0xE0) != 0xA0)
1913 return codecvt_base::error;
1914 break;
1915 case 0xED:
1916 if ((c2 & 0xE0) != 0x80)
1917 return codecvt_base::error;
1918 break;
1919 default:
1920 if ((c2 & 0xC0) != 0x80)
1921 return codecvt_base::error;
1922 break;
1923 }
1924 if ((c3 & 0xC0) != 0x80)
1925 return codecvt_base::error;
1926 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1927 | ((c2 & 0x3F) << 6)
1928 | (c3 & 0x3F));
1929 if (t > Maxcode)
1930 return codecvt_base::error;
1931 *to_nxt = static_cast<uint32_t>(t);
1932 frm_nxt += 3;
1933 }
1934 else if (c1 < 0xF5)
1935 {
1936 if (frm_end-frm_nxt < 4)
1937 return codecvt_base::partial;
1938 uint8_t c2 = frm_nxt[1];
1939 uint8_t c3 = frm_nxt[2];
1940 uint8_t c4 = frm_nxt[3];
1941 switch (c1)
1942 {
1943 case 0xF0:
1944 if (!(0x90 <= c2 && c2 <= 0xBF))
1945 return codecvt_base::error;
1946 break;
1947 case 0xF4:
1948 if ((c2 & 0xF0) != 0x80)
1949 return codecvt_base::error;
1950 break;
1951 default:
1952 if ((c2 & 0xC0) != 0x80)
1953 return codecvt_base::error;
1954 break;
1955 }
1956 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1957 return codecvt_base::error;
1958 if (to_end-to_nxt < 2)
1959 return codecvt_base::partial;
1960 if (((((unsigned long)c1 & 7) << 18) +
1961 (((unsigned long)c2 & 0x3F) << 12) +
1962 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1963 return codecvt_base::error;
1964 *to_nxt = static_cast<uint32_t>(
1965 0xD800
1966 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1967 | ((c2 & 0x0F) << 2)
1968 | ((c3 & 0x30) >> 4));
1969 *++to_nxt = static_cast<uint32_t>(
1970 0xDC00
1971 | ((c3 & 0x0F) << 6)
1972 | (c4 & 0x3F));
1973 frm_nxt += 4;
1974 }
1975 else
1976 {
1977 return codecvt_base::error;
1978 }
1979 }
1980 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1981}
1982
1983static
1984int
1985utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1986 size_t mx, unsigned long Maxcode = 0x10FFFF,
1987 codecvt_mode mode = codecvt_mode(0))
1988{
1989 const uint8_t* frm_nxt = frm;
1990 if (mode & consume_header)
1991 {
1992 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1993 frm_nxt[2] == 0xBF)
1994 frm_nxt += 3;
1995 }
1996 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1997 {
1998 uint8_t c1 = *frm_nxt;
1999 if (c1 > Maxcode)
2000 break;
2001 if (c1 < 0x80)
2002 {
2003 ++frm_nxt;
2004 }
2005 else if (c1 < 0xC2)
2006 {
2007 break;
2008 }
2009 else if (c1 < 0xE0)
2010 {
2011 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2012 break;
2013 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2014 if (t > Maxcode)
2015 break;
2016 frm_nxt += 2;
2017 }
2018 else if (c1 < 0xF0)
2019 {
2020 if (frm_end-frm_nxt < 3)
2021 break;
2022 uint8_t c2 = frm_nxt[1];
2023 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002024 switch (c1)
2025 {
2026 case 0xE0:
2027 if ((c2 & 0xE0) != 0xA0)
2028 return static_cast<int>(frm_nxt - frm);
2029 break;
2030 case 0xED:
2031 if ((c2 & 0xE0) != 0x80)
2032 return static_cast<int>(frm_nxt - frm);
2033 break;
2034 default:
2035 if ((c2 & 0xC0) != 0x80)
2036 return static_cast<int>(frm_nxt - frm);
2037 break;
2038 }
2039 if ((c3 & 0xC0) != 0x80)
2040 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002041 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002042 break;
2043 frm_nxt += 3;
2044 }
2045 else if (c1 < 0xF5)
2046 {
2047 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2048 break;
2049 uint8_t c2 = frm_nxt[1];
2050 uint8_t c3 = frm_nxt[2];
2051 uint8_t c4 = frm_nxt[3];
2052 switch (c1)
2053 {
2054 case 0xF0:
2055 if (!(0x90 <= c2 && c2 <= 0xBF))
2056 return static_cast<int>(frm_nxt - frm);
2057 break;
2058 case 0xF4:
2059 if ((c2 & 0xF0) != 0x80)
2060 return static_cast<int>(frm_nxt - frm);
2061 break;
2062 default:
2063 if ((c2 & 0xC0) != 0x80)
2064 return static_cast<int>(frm_nxt - frm);
2065 break;
2066 }
2067 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2068 break;
2069 if (((((unsigned long)c1 & 7) << 18) +
2070 (((unsigned long)c2 & 0x3F) << 12) +
2071 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2072 break;
2073 ++nchar16_t;
2074 frm_nxt += 4;
2075 }
2076 else
2077 {
2078 break;
2079 }
2080 }
2081 return static_cast<int>(frm_nxt - frm);
2082}
2083
2084static
2085codecvt_base::result
2086ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2087 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2088 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2089{
2090 frm_nxt = frm;
2091 to_nxt = to;
2092 if (mode & generate_header)
2093 {
2094 if (to_end-to_nxt < 3)
2095 return codecvt_base::partial;
2096 *to_nxt++ = static_cast<uint8_t>(0xEF);
2097 *to_nxt++ = static_cast<uint8_t>(0xBB);
2098 *to_nxt++ = static_cast<uint8_t>(0xBF);
2099 }
2100 for (; frm_nxt < frm_end; ++frm_nxt)
2101 {
2102 uint32_t wc = *frm_nxt;
2103 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2104 return codecvt_base::error;
2105 if (wc < 0x000080)
2106 {
2107 if (to_end-to_nxt < 1)
2108 return codecvt_base::partial;
2109 *to_nxt++ = static_cast<uint8_t>(wc);
2110 }
2111 else if (wc < 0x000800)
2112 {
2113 if (to_end-to_nxt < 2)
2114 return codecvt_base::partial;
2115 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2116 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2117 }
2118 else if (wc < 0x010000)
2119 {
2120 if (to_end-to_nxt < 3)
2121 return codecvt_base::partial;
2122 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2123 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2124 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2125 }
2126 else // if (wc < 0x110000)
2127 {
2128 if (to_end-to_nxt < 4)
2129 return codecvt_base::partial;
2130 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2131 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2132 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2133 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2134 }
2135 }
2136 return codecvt_base::ok;
2137}
2138
2139static
2140codecvt_base::result
2141utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2142 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2143 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2144{
2145 frm_nxt = frm;
2146 to_nxt = to;
2147 if (mode & consume_header)
2148 {
2149 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2150 frm_nxt[2] == 0xBF)
2151 frm_nxt += 3;
2152 }
2153 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2154 {
2155 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2156 if (c1 < 0x80)
2157 {
2158 if (c1 > Maxcode)
2159 return codecvt_base::error;
2160 *to_nxt = static_cast<uint32_t>(c1);
2161 ++frm_nxt;
2162 }
2163 else if (c1 < 0xC2)
2164 {
2165 return codecvt_base::error;
2166 }
2167 else if (c1 < 0xE0)
2168 {
2169 if (frm_end-frm_nxt < 2)
2170 return codecvt_base::partial;
2171 uint8_t c2 = frm_nxt[1];
2172 if ((c2 & 0xC0) != 0x80)
2173 return codecvt_base::error;
2174 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2175 | (c2 & 0x3F));
2176 if (t > Maxcode)
2177 return codecvt_base::error;
2178 *to_nxt = t;
2179 frm_nxt += 2;
2180 }
2181 else if (c1 < 0xF0)
2182 {
2183 if (frm_end-frm_nxt < 3)
2184 return codecvt_base::partial;
2185 uint8_t c2 = frm_nxt[1];
2186 uint8_t c3 = frm_nxt[2];
2187 switch (c1)
2188 {
2189 case 0xE0:
2190 if ((c2 & 0xE0) != 0xA0)
2191 return codecvt_base::error;
2192 break;
2193 case 0xED:
2194 if ((c2 & 0xE0) != 0x80)
2195 return codecvt_base::error;
2196 break;
2197 default:
2198 if ((c2 & 0xC0) != 0x80)
2199 return codecvt_base::error;
2200 break;
2201 }
2202 if ((c3 & 0xC0) != 0x80)
2203 return codecvt_base::error;
2204 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2205 | ((c2 & 0x3F) << 6)
2206 | (c3 & 0x3F));
2207 if (t > Maxcode)
2208 return codecvt_base::error;
2209 *to_nxt = t;
2210 frm_nxt += 3;
2211 }
2212 else if (c1 < 0xF5)
2213 {
2214 if (frm_end-frm_nxt < 4)
2215 return codecvt_base::partial;
2216 uint8_t c2 = frm_nxt[1];
2217 uint8_t c3 = frm_nxt[2];
2218 uint8_t c4 = frm_nxt[3];
2219 switch (c1)
2220 {
2221 case 0xF0:
2222 if (!(0x90 <= c2 && c2 <= 0xBF))
2223 return codecvt_base::error;
2224 break;
2225 case 0xF4:
2226 if ((c2 & 0xF0) != 0x80)
2227 return codecvt_base::error;
2228 break;
2229 default:
2230 if ((c2 & 0xC0) != 0x80)
2231 return codecvt_base::error;
2232 break;
2233 }
2234 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2235 return codecvt_base::error;
2236 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2237 | ((c2 & 0x3F) << 12)
2238 | ((c3 & 0x3F) << 6)
2239 | (c4 & 0x3F));
2240 if (t > Maxcode)
2241 return codecvt_base::error;
2242 *to_nxt = t;
2243 frm_nxt += 4;
2244 }
2245 else
2246 {
2247 return codecvt_base::error;
2248 }
2249 }
2250 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2251}
2252
2253static
2254int
2255utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2256 size_t mx, unsigned long Maxcode = 0x10FFFF,
2257 codecvt_mode mode = codecvt_mode(0))
2258{
2259 const uint8_t* frm_nxt = frm;
2260 if (mode & consume_header)
2261 {
2262 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2263 frm_nxt[2] == 0xBF)
2264 frm_nxt += 3;
2265 }
2266 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2267 {
2268 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2269 if (c1 < 0x80)
2270 {
2271 if (c1 > Maxcode)
2272 break;
2273 ++frm_nxt;
2274 }
2275 else if (c1 < 0xC2)
2276 {
2277 break;
2278 }
2279 else if (c1 < 0xE0)
2280 {
2281 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2282 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002283 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002284 break;
2285 frm_nxt += 2;
2286 }
2287 else if (c1 < 0xF0)
2288 {
2289 if (frm_end-frm_nxt < 3)
2290 break;
2291 uint8_t c2 = frm_nxt[1];
2292 uint8_t c3 = frm_nxt[2];
2293 switch (c1)
2294 {
2295 case 0xE0:
2296 if ((c2 & 0xE0) != 0xA0)
2297 return static_cast<int>(frm_nxt - frm);
2298 break;
2299 case 0xED:
2300 if ((c2 & 0xE0) != 0x80)
2301 return static_cast<int>(frm_nxt - frm);
2302 break;
2303 default:
2304 if ((c2 & 0xC0) != 0x80)
2305 return static_cast<int>(frm_nxt - frm);
2306 break;
2307 }
2308 if ((c3 & 0xC0) != 0x80)
2309 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002310 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002311 break;
2312 frm_nxt += 3;
2313 }
2314 else if (c1 < 0xF5)
2315 {
2316 if (frm_end-frm_nxt < 4)
2317 break;
2318 uint8_t c2 = frm_nxt[1];
2319 uint8_t c3 = frm_nxt[2];
2320 uint8_t c4 = frm_nxt[3];
2321 switch (c1)
2322 {
2323 case 0xF0:
2324 if (!(0x90 <= c2 && c2 <= 0xBF))
2325 return static_cast<int>(frm_nxt - frm);
2326 break;
2327 case 0xF4:
2328 if ((c2 & 0xF0) != 0x80)
2329 return static_cast<int>(frm_nxt - frm);
2330 break;
2331 default:
2332 if ((c2 & 0xC0) != 0x80)
2333 return static_cast<int>(frm_nxt - frm);
2334 break;
2335 }
2336 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2337 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002338 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2339 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002340 break;
2341 frm_nxt += 4;
2342 }
2343 else
2344 {
2345 break;
2346 }
2347 }
2348 return static_cast<int>(frm_nxt - frm);
2349}
2350
2351static
2352codecvt_base::result
2353ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2354 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2355 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2356{
2357 frm_nxt = frm;
2358 to_nxt = to;
2359 if (mode & generate_header)
2360 {
2361 if (to_end-to_nxt < 3)
2362 return codecvt_base::partial;
2363 *to_nxt++ = static_cast<uint8_t>(0xEF);
2364 *to_nxt++ = static_cast<uint8_t>(0xBB);
2365 *to_nxt++ = static_cast<uint8_t>(0xBF);
2366 }
2367 for (; frm_nxt < frm_end; ++frm_nxt)
2368 {
2369 uint16_t wc = *frm_nxt;
2370 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2371 return codecvt_base::error;
2372 if (wc < 0x0080)
2373 {
2374 if (to_end-to_nxt < 1)
2375 return codecvt_base::partial;
2376 *to_nxt++ = static_cast<uint8_t>(wc);
2377 }
2378 else if (wc < 0x0800)
2379 {
2380 if (to_end-to_nxt < 2)
2381 return codecvt_base::partial;
2382 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2383 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2384 }
2385 else // if (wc <= 0xFFFF)
2386 {
2387 if (to_end-to_nxt < 3)
2388 return codecvt_base::partial;
2389 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2390 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2391 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2392 }
2393 }
2394 return codecvt_base::ok;
2395}
2396
2397static
2398codecvt_base::result
2399utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2400 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2401 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2402{
2403 frm_nxt = frm;
2404 to_nxt = to;
2405 if (mode & consume_header)
2406 {
2407 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2408 frm_nxt[2] == 0xBF)
2409 frm_nxt += 3;
2410 }
2411 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2412 {
2413 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2414 if (c1 < 0x80)
2415 {
2416 if (c1 > Maxcode)
2417 return codecvt_base::error;
2418 *to_nxt = static_cast<uint16_t>(c1);
2419 ++frm_nxt;
2420 }
2421 else if (c1 < 0xC2)
2422 {
2423 return codecvt_base::error;
2424 }
2425 else if (c1 < 0xE0)
2426 {
2427 if (frm_end-frm_nxt < 2)
2428 return codecvt_base::partial;
2429 uint8_t c2 = frm_nxt[1];
2430 if ((c2 & 0xC0) != 0x80)
2431 return codecvt_base::error;
2432 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2433 | (c2 & 0x3F));
2434 if (t > Maxcode)
2435 return codecvt_base::error;
2436 *to_nxt = t;
2437 frm_nxt += 2;
2438 }
2439 else if (c1 < 0xF0)
2440 {
2441 if (frm_end-frm_nxt < 3)
2442 return codecvt_base::partial;
2443 uint8_t c2 = frm_nxt[1];
2444 uint8_t c3 = frm_nxt[2];
2445 switch (c1)
2446 {
2447 case 0xE0:
2448 if ((c2 & 0xE0) != 0xA0)
2449 return codecvt_base::error;
2450 break;
2451 case 0xED:
2452 if ((c2 & 0xE0) != 0x80)
2453 return codecvt_base::error;
2454 break;
2455 default:
2456 if ((c2 & 0xC0) != 0x80)
2457 return codecvt_base::error;
2458 break;
2459 }
2460 if ((c3 & 0xC0) != 0x80)
2461 return codecvt_base::error;
2462 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2463 | ((c2 & 0x3F) << 6)
2464 | (c3 & 0x3F));
2465 if (t > Maxcode)
2466 return codecvt_base::error;
2467 *to_nxt = t;
2468 frm_nxt += 3;
2469 }
2470 else
2471 {
2472 return codecvt_base::error;
2473 }
2474 }
2475 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2476}
2477
2478static
2479int
2480utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2481 size_t mx, unsigned long Maxcode = 0x10FFFF,
2482 codecvt_mode mode = codecvt_mode(0))
2483{
2484 const uint8_t* frm_nxt = frm;
2485 if (mode & consume_header)
2486 {
2487 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2488 frm_nxt[2] == 0xBF)
2489 frm_nxt += 3;
2490 }
2491 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2492 {
2493 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2494 if (c1 < 0x80)
2495 {
2496 if (c1 > Maxcode)
2497 break;
2498 ++frm_nxt;
2499 }
2500 else if (c1 < 0xC2)
2501 {
2502 break;
2503 }
2504 else if (c1 < 0xE0)
2505 {
2506 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2507 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002508 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002509 break;
2510 frm_nxt += 2;
2511 }
2512 else if (c1 < 0xF0)
2513 {
2514 if (frm_end-frm_nxt < 3)
2515 break;
2516 uint8_t c2 = frm_nxt[1];
2517 uint8_t c3 = frm_nxt[2];
2518 switch (c1)
2519 {
2520 case 0xE0:
2521 if ((c2 & 0xE0) != 0xA0)
2522 return static_cast<int>(frm_nxt - frm);
2523 break;
2524 case 0xED:
2525 if ((c2 & 0xE0) != 0x80)
2526 return static_cast<int>(frm_nxt - frm);
2527 break;
2528 default:
2529 if ((c2 & 0xC0) != 0x80)
2530 return static_cast<int>(frm_nxt - frm);
2531 break;
2532 }
2533 if ((c3 & 0xC0) != 0x80)
2534 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002535 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002536 break;
2537 frm_nxt += 3;
2538 }
2539 else
2540 {
2541 break;
2542 }
2543 }
2544 return static_cast<int>(frm_nxt - frm);
2545}
2546
2547static
2548codecvt_base::result
2549ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2550 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2551 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2552{
2553 frm_nxt = frm;
2554 to_nxt = to;
2555 if (mode & generate_header)
2556 {
2557 if (to_end-to_nxt < 2)
2558 return codecvt_base::partial;
2559 *to_nxt++ = static_cast<uint8_t>(0xFE);
2560 *to_nxt++ = static_cast<uint8_t>(0xFF);
2561 }
2562 for (; frm_nxt < frm_end; ++frm_nxt)
2563 {
2564 uint32_t wc = *frm_nxt;
2565 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2566 return codecvt_base::error;
2567 if (wc < 0x010000)
2568 {
2569 if (to_end-to_nxt < 2)
2570 return codecvt_base::partial;
2571 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2572 *to_nxt++ = static_cast<uint8_t>(wc);
2573 }
2574 else
2575 {
2576 if (to_end-to_nxt < 4)
2577 return codecvt_base::partial;
2578 uint16_t t = static_cast<uint16_t>(
2579 0xD800
2580 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2581 | ((wc & 0x00FC00) >> 10));
2582 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2583 *to_nxt++ = static_cast<uint8_t>(t);
2584 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2585 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2586 *to_nxt++ = static_cast<uint8_t>(t);
2587 }
2588 }
2589 return codecvt_base::ok;
2590}
2591
2592static
2593codecvt_base::result
2594utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2595 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2596 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2597{
2598 frm_nxt = frm;
2599 to_nxt = to;
2600 if (mode & consume_header)
2601 {
2602 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2603 frm_nxt += 2;
2604 }
2605 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2606 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002607 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002608 if ((c1 & 0xFC00) == 0xDC00)
2609 return codecvt_base::error;
2610 if ((c1 & 0xFC00) != 0xD800)
2611 {
2612 if (c1 > Maxcode)
2613 return codecvt_base::error;
2614 *to_nxt = static_cast<uint32_t>(c1);
2615 frm_nxt += 2;
2616 }
2617 else
2618 {
2619 if (frm_end-frm_nxt < 4)
2620 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002621 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002622 if ((c2 & 0xFC00) != 0xDC00)
2623 return codecvt_base::error;
2624 uint32_t t = static_cast<uint32_t>(
2625 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2626 | ((c1 & 0x003F) << 10)
2627 | (c2 & 0x03FF));
2628 if (t > Maxcode)
2629 return codecvt_base::error;
2630 *to_nxt = t;
2631 frm_nxt += 4;
2632 }
2633 }
2634 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2635}
2636
2637static
2638int
2639utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2640 size_t mx, unsigned long Maxcode = 0x10FFFF,
2641 codecvt_mode mode = codecvt_mode(0))
2642{
2643 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002644 if (mode & consume_header)
2645 {
2646 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2647 frm_nxt += 2;
2648 }
2649 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2650 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002651 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002652 if ((c1 & 0xFC00) == 0xDC00)
2653 break;
2654 if ((c1 & 0xFC00) != 0xD800)
2655 {
2656 if (c1 > Maxcode)
2657 break;
2658 frm_nxt += 2;
2659 }
2660 else
2661 {
2662 if (frm_end-frm_nxt < 4)
2663 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002664 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002665 if ((c2 & 0xFC00) != 0xDC00)
2666 break;
2667 uint32_t t = static_cast<uint32_t>(
2668 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2669 | ((c1 & 0x003F) << 10)
2670 | (c2 & 0x03FF));
2671 if (t > Maxcode)
2672 break;
2673 frm_nxt += 4;
2674 }
2675 }
2676 return static_cast<int>(frm_nxt - frm);
2677}
2678
2679static
2680codecvt_base::result
2681ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2682 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2683 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2684{
2685 frm_nxt = frm;
2686 to_nxt = to;
2687 if (mode & generate_header)
2688 {
2689 if (to_end-to_nxt < 2)
2690 return codecvt_base::partial;
2691 *to_nxt++ = static_cast<uint8_t>(0xFF);
2692 *to_nxt++ = static_cast<uint8_t>(0xFE);
2693 }
2694 for (; frm_nxt < frm_end; ++frm_nxt)
2695 {
2696 uint32_t wc = *frm_nxt;
2697 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2698 return codecvt_base::error;
2699 if (wc < 0x010000)
2700 {
2701 if (to_end-to_nxt < 2)
2702 return codecvt_base::partial;
2703 *to_nxt++ = static_cast<uint8_t>(wc);
2704 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2705 }
2706 else
2707 {
2708 if (to_end-to_nxt < 4)
2709 return codecvt_base::partial;
2710 uint16_t t = static_cast<uint16_t>(
2711 0xD800
2712 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2713 | ((wc & 0x00FC00) >> 10));
2714 *to_nxt++ = static_cast<uint8_t>(t);
2715 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2716 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2717 *to_nxt++ = static_cast<uint8_t>(t);
2718 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2719 }
2720 }
2721 return codecvt_base::ok;
2722}
2723
2724static
2725codecvt_base::result
2726utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2727 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2728 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2729{
2730 frm_nxt = frm;
2731 to_nxt = to;
2732 if (mode & consume_header)
2733 {
2734 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2735 frm_nxt += 2;
2736 }
2737 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2738 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002739 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002740 if ((c1 & 0xFC00) == 0xDC00)
2741 return codecvt_base::error;
2742 if ((c1 & 0xFC00) != 0xD800)
2743 {
2744 if (c1 > Maxcode)
2745 return codecvt_base::error;
2746 *to_nxt = static_cast<uint32_t>(c1);
2747 frm_nxt += 2;
2748 }
2749 else
2750 {
2751 if (frm_end-frm_nxt < 4)
2752 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002753 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002754 if ((c2 & 0xFC00) != 0xDC00)
2755 return codecvt_base::error;
2756 uint32_t t = static_cast<uint32_t>(
2757 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2758 | ((c1 & 0x003F) << 10)
2759 | (c2 & 0x03FF));
2760 if (t > Maxcode)
2761 return codecvt_base::error;
2762 *to_nxt = t;
2763 frm_nxt += 4;
2764 }
2765 }
2766 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2767}
2768
2769static
2770int
2771utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2772 size_t mx, unsigned long Maxcode = 0x10FFFF,
2773 codecvt_mode mode = codecvt_mode(0))
2774{
2775 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002776 if (mode & consume_header)
2777 {
2778 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2779 frm_nxt += 2;
2780 }
2781 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2782 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002783 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002784 if ((c1 & 0xFC00) == 0xDC00)
2785 break;
2786 if ((c1 & 0xFC00) != 0xD800)
2787 {
2788 if (c1 > Maxcode)
2789 break;
2790 frm_nxt += 2;
2791 }
2792 else
2793 {
2794 if (frm_end-frm_nxt < 4)
2795 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002796 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002797 if ((c2 & 0xFC00) != 0xDC00)
2798 break;
2799 uint32_t t = static_cast<uint32_t>(
2800 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2801 | ((c1 & 0x003F) << 10)
2802 | (c2 & 0x03FF));
2803 if (t > Maxcode)
2804 break;
2805 frm_nxt += 4;
2806 }
2807 }
2808 return static_cast<int>(frm_nxt - frm);
2809}
2810
2811static
2812codecvt_base::result
2813ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2814 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2815 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2816{
2817 frm_nxt = frm;
2818 to_nxt = to;
2819 if (mode & generate_header)
2820 {
2821 if (to_end-to_nxt < 2)
2822 return codecvt_base::partial;
2823 *to_nxt++ = static_cast<uint8_t>(0xFE);
2824 *to_nxt++ = static_cast<uint8_t>(0xFF);
2825 }
2826 for (; frm_nxt < frm_end; ++frm_nxt)
2827 {
2828 uint16_t wc = *frm_nxt;
2829 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2830 return codecvt_base::error;
2831 if (to_end-to_nxt < 2)
2832 return codecvt_base::partial;
2833 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2834 *to_nxt++ = static_cast<uint8_t>(wc);
2835 }
2836 return codecvt_base::ok;
2837}
2838
2839static
2840codecvt_base::result
2841utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2842 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2843 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2844{
2845 frm_nxt = frm;
2846 to_nxt = to;
2847 if (mode & consume_header)
2848 {
2849 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2850 frm_nxt += 2;
2851 }
2852 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2853 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002854 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002855 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2856 return codecvt_base::error;
2857 *to_nxt = c1;
2858 frm_nxt += 2;
2859 }
2860 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2861}
2862
2863static
2864int
2865utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2866 size_t mx, unsigned long Maxcode = 0x10FFFF,
2867 codecvt_mode mode = codecvt_mode(0))
2868{
2869 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002870 if (mode & consume_header)
2871 {
2872 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2873 frm_nxt += 2;
2874 }
2875 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2876 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002877 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002878 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2879 break;
2880 frm_nxt += 2;
2881 }
2882 return static_cast<int>(frm_nxt - frm);
2883}
2884
2885static
2886codecvt_base::result
2887ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2888 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2889 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2890{
2891 frm_nxt = frm;
2892 to_nxt = to;
2893 if (mode & generate_header)
2894 {
2895 if (to_end-to_nxt < 2)
2896 return codecvt_base::partial;
2897 *to_nxt++ = static_cast<uint8_t>(0xFF);
2898 *to_nxt++ = static_cast<uint8_t>(0xFE);
2899 }
2900 for (; frm_nxt < frm_end; ++frm_nxt)
2901 {
2902 uint16_t wc = *frm_nxt;
2903 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2904 return codecvt_base::error;
2905 if (to_end-to_nxt < 2)
2906 return codecvt_base::partial;
2907 *to_nxt++ = static_cast<uint8_t>(wc);
2908 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2909 }
2910 return codecvt_base::ok;
2911}
2912
2913static
2914codecvt_base::result
2915utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2916 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2917 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2918{
2919 frm_nxt = frm;
2920 to_nxt = to;
2921 if (mode & consume_header)
2922 {
2923 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2924 frm_nxt += 2;
2925 }
2926 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2927 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002928 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002929 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2930 return codecvt_base::error;
2931 *to_nxt = c1;
2932 frm_nxt += 2;
2933 }
2934 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2935}
2936
2937static
2938int
2939utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2940 size_t mx, unsigned long Maxcode = 0x10FFFF,
2941 codecvt_mode mode = codecvt_mode(0))
2942{
2943 const uint8_t* frm_nxt = frm;
2944 frm_nxt = frm;
2945 if (mode & consume_header)
2946 {
2947 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2948 frm_nxt += 2;
2949 }
2950 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2951 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002952 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002953 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2954 break;
2955 frm_nxt += 2;
2956 }
2957 return static_cast<int>(frm_nxt - frm);
2958}
2959
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002960// template <> class codecvt<char16_t, char, mbstate_t>
2961
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002962locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002963
2964codecvt<char16_t, char, mbstate_t>::~codecvt()
2965{
2966}
2967
2968codecvt<char16_t, char, mbstate_t>::result
2969codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002970 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002971 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2972{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002973 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2974 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2975 const uint16_t* _frm_nxt = _frm;
2976 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2977 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2978 uint8_t* _to_nxt = _to;
2979 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2980 frm_nxt = frm + (_frm_nxt - _frm);
2981 to_nxt = to + (_to_nxt - _to);
2982 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002983}
2984
2985codecvt<char16_t, char, mbstate_t>::result
2986codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002987 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002988 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2989{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002990 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2991 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2992 const uint8_t* _frm_nxt = _frm;
2993 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2994 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2995 uint16_t* _to_nxt = _to;
2996 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2997 frm_nxt = frm + (_frm_nxt - _frm);
2998 to_nxt = to + (_to_nxt - _to);
2999 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003000}
3001
3002codecvt<char16_t, char, mbstate_t>::result
3003codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3004 extern_type* to, extern_type*, extern_type*& to_nxt) const
3005{
3006 to_nxt = to;
3007 return noconv;
3008}
3009
3010int
Howard Hinnantc9834542011-05-31 15:34:58 +00003011codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003012{
3013 return 0;
3014}
3015
3016bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003017codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003018{
3019 return false;
3020}
3021
3022int
3023codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3024 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3025{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003026 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3027 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3028 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003029}
3030
3031int
Howard Hinnantc9834542011-05-31 15:34:58 +00003032codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003033{
3034 return 4;
3035}
3036
3037// template <> class codecvt<char32_t, char, mbstate_t>
3038
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003039locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003040
3041codecvt<char32_t, char, mbstate_t>::~codecvt()
3042{
3043}
3044
3045codecvt<char32_t, char, mbstate_t>::result
3046codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003047 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003048 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3049{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003050 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3051 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3052 const uint32_t* _frm_nxt = _frm;
3053 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3054 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3055 uint8_t* _to_nxt = _to;
3056 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3057 frm_nxt = frm + (_frm_nxt - _frm);
3058 to_nxt = to + (_to_nxt - _to);
3059 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003060}
3061
3062codecvt<char32_t, char, mbstate_t>::result
3063codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003064 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003065 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3066{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003067 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3068 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3069 const uint8_t* _frm_nxt = _frm;
3070 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3071 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3072 uint32_t* _to_nxt = _to;
3073 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3074 frm_nxt = frm + (_frm_nxt - _frm);
3075 to_nxt = to + (_to_nxt - _to);
3076 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003077}
3078
3079codecvt<char32_t, char, mbstate_t>::result
3080codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3081 extern_type* to, extern_type*, extern_type*& to_nxt) const
3082{
3083 to_nxt = to;
3084 return noconv;
3085}
3086
3087int
Howard Hinnantc9834542011-05-31 15:34:58 +00003088codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003089{
3090 return 0;
3091}
3092
3093bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003094codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003095{
3096 return false;
3097}
3098
3099int
3100codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3101 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3102{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003103 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3104 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3105 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003106}
3107
3108int
Howard Hinnantc9834542011-05-31 15:34:58 +00003109codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003110{
3111 return 4;
3112}
3113
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003114// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003115
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003116__codecvt_utf8<wchar_t>::result
3117__codecvt_utf8<wchar_t>::do_out(state_type&,
3118 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003119 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3120{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003121 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3122 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3123 const uint32_t* _frm_nxt = _frm;
3124 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3125 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3126 uint8_t* _to_nxt = _to;
3127 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3128 _Maxcode_, _Mode_);
3129 frm_nxt = frm + (_frm_nxt - _frm);
3130 to_nxt = to + (_to_nxt - _to);
3131 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003132}
3133
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003134__codecvt_utf8<wchar_t>::result
3135__codecvt_utf8<wchar_t>::do_in(state_type&,
3136 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003137 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3138{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003139 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3140 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3141 const uint8_t* _frm_nxt = _frm;
3142 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3143 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3144 uint32_t* _to_nxt = _to;
3145 result r = utf8_to_ucs4(_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_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003154 extern_type* to, extern_type*, extern_type*& to_nxt) const
3155{
3156 to_nxt = to;
3157 return noconv;
3158}
3159
3160int
Howard Hinnantc9834542011-05-31 15:34:58 +00003161__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003162{
3163 return 0;
3164}
3165
3166bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003167__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003168{
3169 return false;
3170}
3171
3172int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003173__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003174 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3175{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003176 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3177 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3178 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003179}
3180
3181int
Howard Hinnantc9834542011-05-31 15:34:58 +00003182__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003183{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003184 if (_Mode_ & consume_header)
3185 return 7;
3186 return 4;
3187}
3188
3189// __codecvt_utf8<char16_t>
3190
3191__codecvt_utf8<char16_t>::result
3192__codecvt_utf8<char16_t>::do_out(state_type&,
3193 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3194 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3195{
3196 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3197 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3198 const uint16_t* _frm_nxt = _frm;
3199 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3200 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3201 uint8_t* _to_nxt = _to;
3202 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3203 _Maxcode_, _Mode_);
3204 frm_nxt = frm + (_frm_nxt - _frm);
3205 to_nxt = to + (_to_nxt - _to);
3206 return r;
3207}
3208
3209__codecvt_utf8<char16_t>::result
3210__codecvt_utf8<char16_t>::do_in(state_type&,
3211 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3212 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3213{
3214 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3215 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3216 const uint8_t* _frm_nxt = _frm;
3217 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3218 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3219 uint16_t* _to_nxt = _to;
3220 result r = utf8_to_ucs2(_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_unshift(state_type&,
3229 extern_type* to, extern_type*, extern_type*& to_nxt) const
3230{
3231 to_nxt = to;
3232 return noconv;
3233}
3234
3235int
Howard Hinnantc9834542011-05-31 15:34:58 +00003236__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003237{
3238 return 0;
3239}
3240
3241bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003242__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003243{
3244 return false;
3245}
3246
3247int
3248__codecvt_utf8<char16_t>::do_length(state_type&,
3249 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3250{
3251 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3252 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3253 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3254}
3255
3256int
Howard Hinnantc9834542011-05-31 15:34:58 +00003257__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003258{
3259 if (_Mode_ & consume_header)
3260 return 6;
3261 return 3;
3262}
3263
3264// __codecvt_utf8<char32_t>
3265
3266__codecvt_utf8<char32_t>::result
3267__codecvt_utf8<char32_t>::do_out(state_type&,
3268 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3269 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3270{
3271 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3272 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3273 const uint32_t* _frm_nxt = _frm;
3274 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3275 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3276 uint8_t* _to_nxt = _to;
3277 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3278 _Maxcode_, _Mode_);
3279 frm_nxt = frm + (_frm_nxt - _frm);
3280 to_nxt = to + (_to_nxt - _to);
3281 return r;
3282}
3283
3284__codecvt_utf8<char32_t>::result
3285__codecvt_utf8<char32_t>::do_in(state_type&,
3286 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3287 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3288{
3289 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3290 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3291 const uint8_t* _frm_nxt = _frm;
3292 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3293 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3294 uint32_t* _to_nxt = _to;
3295 result r = utf8_to_ucs4(_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_unshift(state_type&,
3304 extern_type* to, extern_type*, extern_type*& to_nxt) const
3305{
3306 to_nxt = to;
3307 return noconv;
3308}
3309
3310int
Howard Hinnantc9834542011-05-31 15:34:58 +00003311__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003312{
3313 return 0;
3314}
3315
3316bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003317__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003318{
3319 return false;
3320}
3321
3322int
3323__codecvt_utf8<char32_t>::do_length(state_type&,
3324 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3325{
3326 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3327 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3328 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3329}
3330
3331int
Howard Hinnantc9834542011-05-31 15:34:58 +00003332__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003333{
3334 if (_Mode_ & consume_header)
3335 return 7;
3336 return 4;
3337}
3338
3339// __codecvt_utf16<wchar_t, false>
3340
3341__codecvt_utf16<wchar_t, false>::result
3342__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3343 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3344 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3345{
3346 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3347 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3348 const uint32_t* _frm_nxt = _frm;
3349 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3350 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3351 uint8_t* _to_nxt = _to;
3352 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3353 _Maxcode_, _Mode_);
3354 frm_nxt = frm + (_frm_nxt - _frm);
3355 to_nxt = to + (_to_nxt - _to);
3356 return r;
3357}
3358
3359__codecvt_utf16<wchar_t, false>::result
3360__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3361 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3362 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3363{
3364 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3365 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3366 const uint8_t* _frm_nxt = _frm;
3367 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3368 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3369 uint32_t* _to_nxt = _to;
3370 result r = utf16be_to_ucs4(_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_unshift(state_type&,
3379 extern_type* to, extern_type*, extern_type*& to_nxt) const
3380{
3381 to_nxt = to;
3382 return noconv;
3383}
3384
3385int
Howard Hinnantc9834542011-05-31 15:34:58 +00003386__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003387{
3388 return 0;
3389}
3390
3391bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003392__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003393{
3394 return false;
3395}
3396
3397int
3398__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3399 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3400{
3401 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3402 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3403 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3404}
3405
3406int
Howard Hinnantc9834542011-05-31 15:34:58 +00003407__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003408{
3409 if (_Mode_ & consume_header)
3410 return 6;
3411 return 4;
3412}
3413
3414// __codecvt_utf16<wchar_t, true>
3415
3416__codecvt_utf16<wchar_t, true>::result
3417__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3418 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3419 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3420{
3421 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3422 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3423 const uint32_t* _frm_nxt = _frm;
3424 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3425 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3426 uint8_t* _to_nxt = _to;
3427 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3428 _Maxcode_, _Mode_);
3429 frm_nxt = frm + (_frm_nxt - _frm);
3430 to_nxt = to + (_to_nxt - _to);
3431 return r;
3432}
3433
3434__codecvt_utf16<wchar_t, true>::result
3435__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3436 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3437 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3438{
3439 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3440 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3441 const uint8_t* _frm_nxt = _frm;
3442 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3443 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3444 uint32_t* _to_nxt = _to;
3445 result r = utf16le_to_ucs4(_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_unshift(state_type&,
3454 extern_type* to, extern_type*, extern_type*& to_nxt) const
3455{
3456 to_nxt = to;
3457 return noconv;
3458}
3459
3460int
Howard Hinnantc9834542011-05-31 15:34:58 +00003461__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003462{
3463 return 0;
3464}
3465
3466bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003467__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003468{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003469 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003470}
3471
3472int
3473__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3474 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3475{
3476 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3477 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3478 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3479}
3480
3481int
Howard Hinnantc9834542011-05-31 15:34:58 +00003482__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003483{
3484 if (_Mode_ & consume_header)
3485 return 6;
3486 return 4;
3487}
3488
3489// __codecvt_utf16<char16_t, false>
3490
3491__codecvt_utf16<char16_t, false>::result
3492__codecvt_utf16<char16_t, false>::do_out(state_type&,
3493 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3494 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3495{
3496 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3497 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3498 const uint16_t* _frm_nxt = _frm;
3499 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3500 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3501 uint8_t* _to_nxt = _to;
3502 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3503 _Maxcode_, _Mode_);
3504 frm_nxt = frm + (_frm_nxt - _frm);
3505 to_nxt = to + (_to_nxt - _to);
3506 return r;
3507}
3508
3509__codecvt_utf16<char16_t, false>::result
3510__codecvt_utf16<char16_t, false>::do_in(state_type&,
3511 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3512 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3513{
3514 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3515 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3516 const uint8_t* _frm_nxt = _frm;
3517 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3518 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3519 uint16_t* _to_nxt = _to;
3520 result r = utf16be_to_ucs2(_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_unshift(state_type&,
3529 extern_type* to, extern_type*, extern_type*& to_nxt) const
3530{
3531 to_nxt = to;
3532 return noconv;
3533}
3534
3535int
Howard Hinnantc9834542011-05-31 15:34:58 +00003536__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003537{
3538 return 0;
3539}
3540
3541bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003542__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003543{
3544 return false;
3545}
3546
3547int
3548__codecvt_utf16<char16_t, false>::do_length(state_type&,
3549 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3550{
3551 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3552 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3553 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3554}
3555
3556int
Howard Hinnantc9834542011-05-31 15:34:58 +00003557__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003558{
3559 if (_Mode_ & consume_header)
3560 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003561 return 2;
3562}
3563
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003564// __codecvt_utf16<char16_t, true>
3565
3566__codecvt_utf16<char16_t, true>::result
3567__codecvt_utf16<char16_t, true>::do_out(state_type&,
3568 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3569 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3570{
3571 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3572 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3573 const uint16_t* _frm_nxt = _frm;
3574 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3575 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3576 uint8_t* _to_nxt = _to;
3577 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3578 _Maxcode_, _Mode_);
3579 frm_nxt = frm + (_frm_nxt - _frm);
3580 to_nxt = to + (_to_nxt - _to);
3581 return r;
3582}
3583
3584__codecvt_utf16<char16_t, true>::result
3585__codecvt_utf16<char16_t, true>::do_in(state_type&,
3586 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3587 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3588{
3589 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3590 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3591 const uint8_t* _frm_nxt = _frm;
3592 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3593 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3594 uint16_t* _to_nxt = _to;
3595 result r = utf16le_to_ucs2(_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_unshift(state_type&,
3604 extern_type* to, extern_type*, extern_type*& to_nxt) const
3605{
3606 to_nxt = to;
3607 return noconv;
3608}
3609
3610int
Howard Hinnantc9834542011-05-31 15:34:58 +00003611__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003612{
3613 return 0;
3614}
3615
3616bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003617__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003618{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003619 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003620}
3621
3622int
3623__codecvt_utf16<char16_t, true>::do_length(state_type&,
3624 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3625{
3626 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3627 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3628 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3629}
3630
3631int
Howard Hinnantc9834542011-05-31 15:34:58 +00003632__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003633{
3634 if (_Mode_ & consume_header)
3635 return 4;
3636 return 2;
3637}
3638
3639// __codecvt_utf16<char32_t, false>
3640
3641__codecvt_utf16<char32_t, false>::result
3642__codecvt_utf16<char32_t, false>::do_out(state_type&,
3643 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3644 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3645{
3646 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3647 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3648 const uint32_t* _frm_nxt = _frm;
3649 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3650 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3651 uint8_t* _to_nxt = _to;
3652 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3653 _Maxcode_, _Mode_);
3654 frm_nxt = frm + (_frm_nxt - _frm);
3655 to_nxt = to + (_to_nxt - _to);
3656 return r;
3657}
3658
3659__codecvt_utf16<char32_t, false>::result
3660__codecvt_utf16<char32_t, false>::do_in(state_type&,
3661 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3662 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3663{
3664 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3665 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3666 const uint8_t* _frm_nxt = _frm;
3667 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3668 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3669 uint32_t* _to_nxt = _to;
3670 result r = utf16be_to_ucs4(_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_unshift(state_type&,
3679 extern_type* to, extern_type*, extern_type*& to_nxt) const
3680{
3681 to_nxt = to;
3682 return noconv;
3683}
3684
3685int
Howard Hinnantc9834542011-05-31 15:34:58 +00003686__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003687{
3688 return 0;
3689}
3690
3691bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003692__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003693{
3694 return false;
3695}
3696
3697int
3698__codecvt_utf16<char32_t, false>::do_length(state_type&,
3699 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3700{
3701 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3702 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3703 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3704}
3705
3706int
Howard Hinnantc9834542011-05-31 15:34:58 +00003707__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003708{
3709 if (_Mode_ & consume_header)
3710 return 6;
3711 return 4;
3712}
3713
3714// __codecvt_utf16<char32_t, true>
3715
3716__codecvt_utf16<char32_t, true>::result
3717__codecvt_utf16<char32_t, true>::do_out(state_type&,
3718 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3719 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3720{
3721 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3722 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3723 const uint32_t* _frm_nxt = _frm;
3724 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3725 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3726 uint8_t* _to_nxt = _to;
3727 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3728 _Maxcode_, _Mode_);
3729 frm_nxt = frm + (_frm_nxt - _frm);
3730 to_nxt = to + (_to_nxt - _to);
3731 return r;
3732}
3733
3734__codecvt_utf16<char32_t, true>::result
3735__codecvt_utf16<char32_t, true>::do_in(state_type&,
3736 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3737 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3738{
3739 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3740 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3741 const uint8_t* _frm_nxt = _frm;
3742 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3743 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3744 uint32_t* _to_nxt = _to;
3745 result r = utf16le_to_ucs4(_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_unshift(state_type&,
3754 extern_type* to, extern_type*, extern_type*& to_nxt) const
3755{
3756 to_nxt = to;
3757 return noconv;
3758}
3759
3760int
Howard Hinnantc9834542011-05-31 15:34:58 +00003761__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003762{
3763 return 0;
3764}
3765
3766bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003767__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003768{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003769 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003770}
3771
3772int
3773__codecvt_utf16<char32_t, true>::do_length(state_type&,
3774 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3775{
3776 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3777 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3778 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3779}
3780
3781int
Howard Hinnantc9834542011-05-31 15:34:58 +00003782__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003783{
3784 if (_Mode_ & consume_header)
3785 return 6;
3786 return 4;
3787}
3788
3789// __codecvt_utf8_utf16<wchar_t>
3790
3791__codecvt_utf8_utf16<wchar_t>::result
3792__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3793 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3794 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3795{
3796 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3797 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3798 const uint32_t* _frm_nxt = _frm;
3799 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3800 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3801 uint8_t* _to_nxt = _to;
3802 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3803 _Maxcode_, _Mode_);
3804 frm_nxt = frm + (_frm_nxt - _frm);
3805 to_nxt = to + (_to_nxt - _to);
3806 return r;
3807}
3808
3809__codecvt_utf8_utf16<wchar_t>::result
3810__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3811 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3812 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3813{
3814 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3815 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3816 const uint8_t* _frm_nxt = _frm;
3817 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3818 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3819 uint32_t* _to_nxt = _to;
3820 result r = utf8_to_utf16(_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_unshift(state_type&,
3829 extern_type* to, extern_type*, extern_type*& to_nxt) const
3830{
3831 to_nxt = to;
3832 return noconv;
3833}
3834
3835int
Howard Hinnantc9834542011-05-31 15:34:58 +00003836__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003837{
3838 return 0;
3839}
3840
3841bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003842__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003843{
3844 return false;
3845}
3846
3847int
3848__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3849 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3850{
3851 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3852 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3853 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3854}
3855
3856int
Howard Hinnantc9834542011-05-31 15:34:58 +00003857__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003858{
3859 if (_Mode_ & consume_header)
3860 return 7;
3861 return 4;
3862}
3863
3864// __codecvt_utf8_utf16<char16_t>
3865
3866__codecvt_utf8_utf16<char16_t>::result
3867__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3868 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3869 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3870{
3871 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3872 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3873 const uint16_t* _frm_nxt = _frm;
3874 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3875 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3876 uint8_t* _to_nxt = _to;
3877 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3878 _Maxcode_, _Mode_);
3879 frm_nxt = frm + (_frm_nxt - _frm);
3880 to_nxt = to + (_to_nxt - _to);
3881 return r;
3882}
3883
3884__codecvt_utf8_utf16<char16_t>::result
3885__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3886 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3887 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3888{
3889 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3890 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3891 const uint8_t* _frm_nxt = _frm;
3892 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3893 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3894 uint16_t* _to_nxt = _to;
3895 result r = utf8_to_utf16(_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_unshift(state_type&,
3904 extern_type* to, extern_type*, extern_type*& to_nxt) const
3905{
3906 to_nxt = to;
3907 return noconv;
3908}
3909
3910int
Howard Hinnantc9834542011-05-31 15:34:58 +00003911__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003912{
3913 return 0;
3914}
3915
3916bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003917__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003918{
3919 return false;
3920}
3921
3922int
3923__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3924 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3925{
3926 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3927 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3928 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3929}
3930
3931int
Howard Hinnantc9834542011-05-31 15:34:58 +00003932__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003933{
3934 if (_Mode_ & consume_header)
3935 return 7;
3936 return 4;
3937}
3938
3939// __codecvt_utf8_utf16<char32_t>
3940
3941__codecvt_utf8_utf16<char32_t>::result
3942__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3943 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3944 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3945{
3946 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3947 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3948 const uint32_t* _frm_nxt = _frm;
3949 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3950 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3951 uint8_t* _to_nxt = _to;
3952 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3953 _Maxcode_, _Mode_);
3954 frm_nxt = frm + (_frm_nxt - _frm);
3955 to_nxt = to + (_to_nxt - _to);
3956 return r;
3957}
3958
3959__codecvt_utf8_utf16<char32_t>::result
3960__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3961 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3962 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3963{
3964 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3965 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3966 const uint8_t* _frm_nxt = _frm;
3967 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3968 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3969 uint32_t* _to_nxt = _to;
3970 result r = utf8_to_utf16(_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_unshift(state_type&,
3979 extern_type* to, extern_type*, extern_type*& to_nxt) const
3980{
3981 to_nxt = to;
3982 return noconv;
3983}
3984
3985int
Howard Hinnantc9834542011-05-31 15:34:58 +00003986__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003987{
3988 return 0;
3989}
3990
3991bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003992__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003993{
3994 return false;
3995}
3996
3997int
3998__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3999 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4000{
4001 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4002 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4003 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4004}
4005
4006int
Howard Hinnantc9834542011-05-31 15:34:58 +00004007__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004008{
4009 if (_Mode_ & consume_header)
4010 return 7;
4011 return 4;
4012}
4013
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004014// __narrow_to_utf8<16>
4015
4016__narrow_to_utf8<16>::~__narrow_to_utf8()
4017{
4018}
4019
4020// __narrow_to_utf8<32>
4021
4022__narrow_to_utf8<32>::~__narrow_to_utf8()
4023{
4024}
4025
4026// __widen_from_utf8<16>
4027
4028__widen_from_utf8<16>::~__widen_from_utf8()
4029{
4030}
4031
4032// __widen_from_utf8<32>
4033
4034__widen_from_utf8<32>::~__widen_from_utf8()
4035{
4036}
4037
4038// numpunct<char> && numpunct<wchar_t>
4039
4040locale::id numpunct< char >::id;
4041locale::id numpunct<wchar_t>::id;
4042
4043numpunct<char>::numpunct(size_t refs)
4044 : locale::facet(refs),
4045 __decimal_point_('.'),
4046 __thousands_sep_(',')
4047{
4048}
4049
4050numpunct<wchar_t>::numpunct(size_t refs)
4051 : locale::facet(refs),
4052 __decimal_point_(L'.'),
4053 __thousands_sep_(L',')
4054{
4055}
4056
4057numpunct<char>::~numpunct()
4058{
4059}
4060
4061numpunct<wchar_t>::~numpunct()
4062{
4063}
4064
4065 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4066wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4067
4068 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4069wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4070
4071string numpunct< char >::do_grouping() const {return __grouping_;}
4072string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4073
4074 string numpunct< char >::do_truename() const {return "true";}
4075wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4076
4077 string numpunct< char >::do_falsename() const {return "false";}
4078wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4079
4080// numpunct_byname<char>
4081
4082numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4083 : numpunct<char>(refs)
4084{
4085 __init(nm);
4086}
4087
4088numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4089 : numpunct<char>(refs)
4090{
4091 __init(nm.c_str());
4092}
4093
4094numpunct_byname<char>::~numpunct_byname()
4095{
4096}
4097
4098void
4099numpunct_byname<char>::__init(const char* nm)
4100{
4101 if (strcmp(nm, "C") != 0)
4102 {
Sean Huntf3907e62011-07-15 05:40:33 +00004103 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004104#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004105 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004106 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4107 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004108#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004109#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004110 lconv* lc = localeconv_l(loc.get());
4111#else
4112 lconv* lc = __localeconv_l(loc.get());
4113#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004114 if (*lc->decimal_point)
4115 __decimal_point_ = *lc->decimal_point;
4116 if (*lc->thousands_sep)
4117 __thousands_sep_ = *lc->thousands_sep;
4118 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004119 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004120 }
4121}
4122
4123// numpunct_byname<wchar_t>
4124
4125numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4126 : numpunct<wchar_t>(refs)
4127{
4128 __init(nm);
4129}
4130
4131numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4132 : numpunct<wchar_t>(refs)
4133{
4134 __init(nm.c_str());
4135}
4136
4137numpunct_byname<wchar_t>::~numpunct_byname()
4138{
4139}
4140
4141void
4142numpunct_byname<wchar_t>::__init(const char* nm)
4143{
4144 if (strcmp(nm, "C") != 0)
4145 {
Sean Huntf3907e62011-07-15 05:40:33 +00004146 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004147#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004148 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004149 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4150 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004151#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004152#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004153 lconv* lc = localeconv_l(loc.get());
4154#else
4155 lconv* lc = __localeconv_l(loc.get());
4156#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004157 if (*lc->decimal_point)
4158 __decimal_point_ = *lc->decimal_point;
4159 if (*lc->thousands_sep)
4160 __thousands_sep_ = *lc->thousands_sep;
4161 __grouping_ = lc->grouping;
4162 // locallization for truename and falsename is not available
4163 }
4164}
4165
4166// num_get helpers
4167
4168int
4169__num_get_base::__get_base(ios_base& iob)
4170{
4171 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4172 if (__basefield == ios_base::oct)
4173 return 8;
4174 else if (__basefield == ios_base::hex)
4175 return 16;
4176 else if (__basefield == 0)
4177 return 0;
4178 return 10;
4179}
4180
4181const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4182
4183void
4184__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4185 ios_base::iostate& __err)
4186{
4187 if (__grouping.size() != 0)
4188 {
4189 reverse(__g, __g_end);
4190 const char* __ig = __grouping.data();
4191 const char* __eg = __ig + __grouping.size();
4192 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4193 {
4194 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4195 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004196 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004197 {
4198 __err = ios_base::failbit;
4199 return;
4200 }
4201 }
4202 if (__eg - __ig > 1)
4203 ++__ig;
4204 }
4205 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4206 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004207 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004208 __err = ios_base::failbit;
4209 }
4210 }
4211}
4212
4213void
4214__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4215 ios_base::fmtflags __flags)
4216{
4217 if (__flags & ios_base::showpos)
4218 *__fmtp++ = '+';
4219 if (__flags & ios_base::showbase)
4220 *__fmtp++ = '#';
4221 while(*__len)
4222 *__fmtp++ = *__len++;
4223 if ((__flags & ios_base::basefield) == ios_base::oct)
4224 *__fmtp = 'o';
4225 else if ((__flags & ios_base::basefield) == ios_base::hex)
4226 {
4227 if (__flags & ios_base::uppercase)
4228 *__fmtp = 'X';
4229 else
4230 *__fmtp = 'x';
4231 }
4232 else if (__signd)
4233 *__fmtp = 'd';
4234 else
4235 *__fmtp = 'u';
4236}
4237
4238bool
4239__num_put_base::__format_float(char* __fmtp, const char* __len,
4240 ios_base::fmtflags __flags)
4241{
4242 bool specify_precision = true;
4243 if (__flags & ios_base::showpos)
4244 *__fmtp++ = '+';
4245 if (__flags & ios_base::showpoint)
4246 *__fmtp++ = '#';
4247 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4248 bool uppercase = __flags & ios_base::uppercase;
4249 if (floatfield == (ios_base::fixed | ios_base::scientific))
4250 specify_precision = false;
4251 else
4252 {
4253 *__fmtp++ = '.';
4254 *__fmtp++ = '*';
4255 }
4256 while(*__len)
4257 *__fmtp++ = *__len++;
4258 if (floatfield == ios_base::fixed)
4259 {
4260 if (uppercase)
4261 *__fmtp = 'F';
4262 else
4263 *__fmtp = 'f';
4264 }
4265 else if (floatfield == ios_base::scientific)
4266 {
4267 if (uppercase)
4268 *__fmtp = 'E';
4269 else
4270 *__fmtp = 'e';
4271 }
4272 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4273 {
4274 if (uppercase)
4275 *__fmtp = 'A';
4276 else
4277 *__fmtp = 'a';
4278 }
4279 else
4280 {
4281 if (uppercase)
4282 *__fmtp = 'G';
4283 else
4284 *__fmtp = 'g';
4285 }
4286 return specify_precision;
4287}
4288
4289char*
4290__num_put_base::__identify_padding(char* __nb, char* __ne,
4291 const ios_base& __iob)
4292{
4293 switch (__iob.flags() & ios_base::adjustfield)
4294 {
4295 case ios_base::internal:
4296 if (__nb[0] == '-' || __nb[0] == '+')
4297 return __nb+1;
4298 if (__ne - __nb >= 2 && __nb[0] == '0'
4299 && (__nb[1] == 'x' || __nb[1] == 'X'))
4300 return __nb+2;
4301 break;
4302 case ios_base::left:
4303 return __ne;
4304 case ios_base::right:
4305 default:
4306 break;
4307 }
4308 return __nb;
4309}
4310
4311// time_get
4312
4313static
4314string*
4315init_weeks()
4316{
4317 static string weeks[14];
4318 weeks[0] = "Sunday";
4319 weeks[1] = "Monday";
4320 weeks[2] = "Tuesday";
4321 weeks[3] = "Wednesday";
4322 weeks[4] = "Thursday";
4323 weeks[5] = "Friday";
4324 weeks[6] = "Saturday";
4325 weeks[7] = "Sun";
4326 weeks[8] = "Mon";
4327 weeks[9] = "Tue";
4328 weeks[10] = "Wed";
4329 weeks[11] = "Thu";
4330 weeks[12] = "Fri";
4331 weeks[13] = "Sat";
4332 return weeks;
4333}
4334
4335static
4336wstring*
4337init_wweeks()
4338{
4339 static wstring weeks[14];
4340 weeks[0] = L"Sunday";
4341 weeks[1] = L"Monday";
4342 weeks[2] = L"Tuesday";
4343 weeks[3] = L"Wednesday";
4344 weeks[4] = L"Thursday";
4345 weeks[5] = L"Friday";
4346 weeks[6] = L"Saturday";
4347 weeks[7] = L"Sun";
4348 weeks[8] = L"Mon";
4349 weeks[9] = L"Tue";
4350 weeks[10] = L"Wed";
4351 weeks[11] = L"Thu";
4352 weeks[12] = L"Fri";
4353 weeks[13] = L"Sat";
4354 return weeks;
4355}
4356
4357template <>
4358const string*
4359__time_get_c_storage<char>::__weeks() const
4360{
4361 static const string* weeks = init_weeks();
4362 return weeks;
4363}
4364
4365template <>
4366const wstring*
4367__time_get_c_storage<wchar_t>::__weeks() const
4368{
4369 static const wstring* weeks = init_wweeks();
4370 return weeks;
4371}
4372
4373static
4374string*
4375init_months()
4376{
4377 static string months[24];
4378 months[0] = "January";
4379 months[1] = "February";
4380 months[2] = "March";
4381 months[3] = "April";
4382 months[4] = "May";
4383 months[5] = "June";
4384 months[6] = "July";
4385 months[7] = "August";
4386 months[8] = "September";
4387 months[9] = "October";
4388 months[10] = "November";
4389 months[11] = "December";
4390 months[12] = "Jan";
4391 months[13] = "Feb";
4392 months[14] = "Mar";
4393 months[15] = "Apr";
4394 months[16] = "May";
4395 months[17] = "Jun";
4396 months[18] = "Jul";
4397 months[19] = "Aug";
4398 months[20] = "Sep";
4399 months[21] = "Oct";
4400 months[22] = "Nov";
4401 months[23] = "Dec";
4402 return months;
4403}
4404
4405static
4406wstring*
4407init_wmonths()
4408{
4409 static wstring months[24];
4410 months[0] = L"January";
4411 months[1] = L"February";
4412 months[2] = L"March";
4413 months[3] = L"April";
4414 months[4] = L"May";
4415 months[5] = L"June";
4416 months[6] = L"July";
4417 months[7] = L"August";
4418 months[8] = L"September";
4419 months[9] = L"October";
4420 months[10] = L"November";
4421 months[11] = L"December";
4422 months[12] = L"Jan";
4423 months[13] = L"Feb";
4424 months[14] = L"Mar";
4425 months[15] = L"Apr";
4426 months[16] = L"May";
4427 months[17] = L"Jun";
4428 months[18] = L"Jul";
4429 months[19] = L"Aug";
4430 months[20] = L"Sep";
4431 months[21] = L"Oct";
4432 months[22] = L"Nov";
4433 months[23] = L"Dec";
4434 return months;
4435}
4436
4437template <>
4438const string*
4439__time_get_c_storage<char>::__months() const
4440{
4441 static const string* months = init_months();
4442 return months;
4443}
4444
4445template <>
4446const wstring*
4447__time_get_c_storage<wchar_t>::__months() const
4448{
4449 static const wstring* months = init_wmonths();
4450 return months;
4451}
4452
4453static
4454string*
4455init_am_pm()
4456{
4457 static string am_pm[24];
4458 am_pm[0] = "AM";
4459 am_pm[1] = "PM";
4460 return am_pm;
4461}
4462
4463static
4464wstring*
4465init_wam_pm()
4466{
4467 static wstring am_pm[24];
4468 am_pm[0] = L"AM";
4469 am_pm[1] = L"PM";
4470 return am_pm;
4471}
4472
4473template <>
4474const string*
4475__time_get_c_storage<char>::__am_pm() const
4476{
4477 static const string* am_pm = init_am_pm();
4478 return am_pm;
4479}
4480
4481template <>
4482const wstring*
4483__time_get_c_storage<wchar_t>::__am_pm() const
4484{
4485 static const wstring* am_pm = init_wam_pm();
4486 return am_pm;
4487}
4488
4489template <>
4490const string&
4491__time_get_c_storage<char>::__x() const
4492{
4493 static string s("%m/%d/%y");
4494 return s;
4495}
4496
4497template <>
4498const wstring&
4499__time_get_c_storage<wchar_t>::__x() const
4500{
4501 static wstring s(L"%m/%d/%y");
4502 return s;
4503}
4504
4505template <>
4506const string&
4507__time_get_c_storage<char>::__X() const
4508{
4509 static string s("%H:%M:%S");
4510 return s;
4511}
4512
4513template <>
4514const wstring&
4515__time_get_c_storage<wchar_t>::__X() const
4516{
4517 static wstring s(L"%H:%M:%S");
4518 return s;
4519}
4520
4521template <>
4522const string&
4523__time_get_c_storage<char>::__c() const
4524{
4525 static string s("%a %b %d %H:%M:%S %Y");
4526 return s;
4527}
4528
4529template <>
4530const wstring&
4531__time_get_c_storage<wchar_t>::__c() const
4532{
4533 static wstring s(L"%a %b %d %H:%M:%S %Y");
4534 return s;
4535}
4536
4537template <>
4538const string&
4539__time_get_c_storage<char>::__r() const
4540{
4541 static string s("%I:%M:%S %p");
4542 return s;
4543}
4544
4545template <>
4546const wstring&
4547__time_get_c_storage<wchar_t>::__r() const
4548{
4549 static wstring s(L"%I:%M:%S %p");
4550 return s;
4551}
4552
4553// time_get_byname
4554
4555__time_get::__time_get(const char* nm)
4556 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4557{
Howard Hinnantd4444702010-08-11 17:04:31 +00004558#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004559 if (__loc_ == 0)
4560 throw runtime_error("time_get_byname"
4561 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004562#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004563}
4564
4565__time_get::__time_get(const string& nm)
4566 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4567{
Howard Hinnantd4444702010-08-11 17:04:31 +00004568#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004569 if (__loc_ == 0)
4570 throw runtime_error("time_get_byname"
4571 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004572#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004573}
4574
4575__time_get::~__time_get()
4576{
4577 freelocale(__loc_);
4578}
4579
Howard Hinnant335b1512012-02-20 16:51:43 +00004580#pragma clang diagnostic ignored "-Wmissing-field-initializers"
4581
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004582template <>
4583string
4584__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4585{
Howard Hinnant3074a052012-02-19 14:55:32 +00004586 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004587 t.tm_sec = 59;
4588 t.tm_min = 55;
4589 t.tm_hour = 23;
4590 t.tm_mday = 31;
4591 t.tm_mon = 11;
4592 t.tm_year = 161;
4593 t.tm_wday = 6;
4594 t.tm_yday = 364;
4595 t.tm_isdst = -1;
4596 char buf[100];
4597 char f[3] = {0};
4598 f[0] = '%';
4599 f[1] = fmt;
4600 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4601 char* bb = buf;
4602 char* be = buf + n;
4603 string result;
4604 while (bb != be)
4605 {
4606 if (ct.is(ctype_base::space, *bb))
4607 {
4608 result.push_back(' ');
4609 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4610 ;
4611 continue;
4612 }
4613 char* w = bb;
4614 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004615 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004616 ct, err, false)
4617 - this->__weeks_;
4618 if (i < 14)
4619 {
4620 result.push_back('%');
4621 if (i < 7)
4622 result.push_back('A');
4623 else
4624 result.push_back('a');
4625 bb = w;
4626 continue;
4627 }
4628 w = bb;
4629 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4630 ct, err, false)
4631 - this->__months_;
4632 if (i < 24)
4633 {
4634 result.push_back('%');
4635 if (i < 12)
4636 result.push_back('B');
4637 else
4638 result.push_back('b');
4639 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4640 result.back() = 'm';
4641 bb = w;
4642 continue;
4643 }
4644 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4645 {
4646 w = bb;
4647 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4648 ct, err, false) - this->__am_pm_;
4649 if (i < 2)
4650 {
4651 result.push_back('%');
4652 result.push_back('p');
4653 bb = w;
4654 continue;
4655 }
4656 }
4657 w = bb;
4658 if (ct.is(ctype_base::digit, *bb))
4659 {
4660 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4661 {
4662 case 6:
4663 result.push_back('%');
4664 result.push_back('w');
4665 break;
4666 case 7:
4667 result.push_back('%');
4668 result.push_back('u');
4669 break;
4670 case 11:
4671 result.push_back('%');
4672 result.push_back('I');
4673 break;
4674 case 12:
4675 result.push_back('%');
4676 result.push_back('m');
4677 break;
4678 case 23:
4679 result.push_back('%');
4680 result.push_back('H');
4681 break;
4682 case 31:
4683 result.push_back('%');
4684 result.push_back('d');
4685 break;
4686 case 55:
4687 result.push_back('%');
4688 result.push_back('M');
4689 break;
4690 case 59:
4691 result.push_back('%');
4692 result.push_back('S');
4693 break;
4694 case 61:
4695 result.push_back('%');
4696 result.push_back('y');
4697 break;
4698 case 364:
4699 result.push_back('%');
4700 result.push_back('j');
4701 break;
4702 case 2061:
4703 result.push_back('%');
4704 result.push_back('Y');
4705 break;
4706 default:
4707 for (; w != bb; ++w)
4708 result.push_back(*w);
4709 break;
4710 }
4711 continue;
4712 }
4713 if (*bb == '%')
4714 {
4715 result.push_back('%');
4716 result.push_back('%');
4717 ++bb;
4718 continue;
4719 }
4720 result.push_back(*bb);
4721 ++bb;
4722 }
4723 return result;
4724}
4725
Howard Hinnantec3773c2011-12-01 20:21:04 +00004726#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004727
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004728template <>
4729wstring
4730__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4731{
Howard Hinnant3074a052012-02-19 14:55:32 +00004732 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004733 t.tm_sec = 59;
4734 t.tm_min = 55;
4735 t.tm_hour = 23;
4736 t.tm_mday = 31;
4737 t.tm_mon = 11;
4738 t.tm_year = 161;
4739 t.tm_wday = 6;
4740 t.tm_yday = 364;
4741 t.tm_isdst = -1;
4742 char buf[100];
4743 char f[3] = {0};
4744 f[0] = '%';
4745 f[1] = fmt;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004746 strftime_l(buf, 100, f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004747 wchar_t wbuf[100];
4748 wchar_t* wbb = wbuf;
4749 mbstate_t mb = {0};
4750 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004751#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00004752 size_t j = mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004753#else
Howard Hinnantec3773c2011-12-01 20:21:04 +00004754 size_t j = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004755#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004756 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004757 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004758 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004759 wstring result;
4760 while (wbb != wbe)
4761 {
4762 if (ct.is(ctype_base::space, *wbb))
4763 {
4764 result.push_back(L' ');
4765 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4766 ;
4767 continue;
4768 }
4769 wchar_t* w = wbb;
4770 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004771 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004772 ct, err, false)
4773 - this->__weeks_;
4774 if (i < 14)
4775 {
4776 result.push_back(L'%');
4777 if (i < 7)
4778 result.push_back(L'A');
4779 else
4780 result.push_back(L'a');
4781 wbb = w;
4782 continue;
4783 }
4784 w = wbb;
4785 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4786 ct, err, false)
4787 - this->__months_;
4788 if (i < 24)
4789 {
4790 result.push_back(L'%');
4791 if (i < 12)
4792 result.push_back(L'B');
4793 else
4794 result.push_back(L'b');
4795 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4796 result.back() = L'm';
4797 wbb = w;
4798 continue;
4799 }
4800 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4801 {
4802 w = wbb;
4803 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4804 ct, err, false) - this->__am_pm_;
4805 if (i < 2)
4806 {
4807 result.push_back(L'%');
4808 result.push_back(L'p');
4809 wbb = w;
4810 continue;
4811 }
4812 }
4813 w = wbb;
4814 if (ct.is(ctype_base::digit, *wbb))
4815 {
4816 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4817 {
4818 case 6:
4819 result.push_back(L'%');
4820 result.push_back(L'w');
4821 break;
4822 case 7:
4823 result.push_back(L'%');
4824 result.push_back(L'u');
4825 break;
4826 case 11:
4827 result.push_back(L'%');
4828 result.push_back(L'I');
4829 break;
4830 case 12:
4831 result.push_back(L'%');
4832 result.push_back(L'm');
4833 break;
4834 case 23:
4835 result.push_back(L'%');
4836 result.push_back(L'H');
4837 break;
4838 case 31:
4839 result.push_back(L'%');
4840 result.push_back(L'd');
4841 break;
4842 case 55:
4843 result.push_back(L'%');
4844 result.push_back(L'M');
4845 break;
4846 case 59:
4847 result.push_back(L'%');
4848 result.push_back(L'S');
4849 break;
4850 case 61:
4851 result.push_back(L'%');
4852 result.push_back(L'y');
4853 break;
4854 case 364:
4855 result.push_back(L'%');
4856 result.push_back(L'j');
4857 break;
4858 case 2061:
4859 result.push_back(L'%');
4860 result.push_back(L'Y');
4861 break;
4862 default:
4863 for (; w != wbb; ++w)
4864 result.push_back(*w);
4865 break;
4866 }
4867 continue;
4868 }
4869 if (ct.narrow(*wbb, 0) == '%')
4870 {
4871 result.push_back(L'%');
4872 result.push_back(L'%');
4873 ++wbb;
4874 continue;
4875 }
4876 result.push_back(*wbb);
4877 ++wbb;
4878 }
4879 return result;
4880}
4881
4882template <>
4883void
4884__time_get_storage<char>::init(const ctype<char>& ct)
4885{
Howard Hinnantcd992362012-08-02 18:44:17 +00004886 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004887 char buf[100];
4888 // __weeks_
4889 for (int i = 0; i < 7; ++i)
4890 {
4891 t.tm_wday = i;
4892 strftime_l(buf, 100, "%A", &t, __loc_);
4893 __weeks_[i] = buf;
4894 strftime_l(buf, 100, "%a", &t, __loc_);
4895 __weeks_[i+7] = buf;
4896 }
4897 // __months_
4898 for (int i = 0; i < 12; ++i)
4899 {
4900 t.tm_mon = i;
4901 strftime_l(buf, 100, "%B", &t, __loc_);
4902 __months_[i] = buf;
4903 strftime_l(buf, 100, "%b", &t, __loc_);
4904 __months_[i+12] = buf;
4905 }
4906 // __am_pm_
4907 t.tm_hour = 1;
4908 strftime_l(buf, 100, "%p", &t, __loc_);
4909 __am_pm_[0] = buf;
4910 t.tm_hour = 13;
4911 strftime_l(buf, 100, "%p", &t, __loc_);
4912 __am_pm_[1] = buf;
4913 __c_ = __analyze('c', ct);
4914 __r_ = __analyze('r', ct);
4915 __x_ = __analyze('x', ct);
4916 __X_ = __analyze('X', ct);
4917}
4918
4919template <>
4920void
4921__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4922{
4923 tm t = {0};
4924 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004925 wchar_t wbuf[100];
4926 wchar_t* wbe;
4927 mbstate_t mb = {0};
4928 // __weeks_
4929 for (int i = 0; i < 7; ++i)
4930 {
4931 t.tm_wday = i;
Howard Hinnantc6e54b92012-12-27 18:46:00 +00004932 strftime_l(buf, 100, "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004933 mb = mbstate_t();
4934 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004935#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004936 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4937#else
4938 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4939#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004940 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004941 __throw_runtime_error("locale not supported");
4942 wbe = wbuf + j;
4943 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantc6e54b92012-12-27 18:46:00 +00004944 strftime_l(buf, 100, "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004945 mb = mbstate_t();
4946 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004947#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004948 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4949#else
4950 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4951#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004952 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004953 __throw_runtime_error("locale not supported");
4954 wbe = wbuf + j;
4955 __weeks_[i+7].assign(wbuf, wbe);
4956 }
4957 // __months_
4958 for (int i = 0; i < 12; ++i)
4959 {
4960 t.tm_mon = i;
Howard Hinnantc6e54b92012-12-27 18:46:00 +00004961 strftime_l(buf, 100, "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004962 mb = mbstate_t();
4963 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004964#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004965 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4966#else
4967 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4968#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004969 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004970 __throw_runtime_error("locale not supported");
4971 wbe = wbuf + j;
4972 __months_[i].assign(wbuf, wbe);
Howard Hinnantc6e54b92012-12-27 18:46:00 +00004973 strftime_l(buf, 100, "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004974 mb = mbstate_t();
4975 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004976#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004977 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4978#else
4979 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4980#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004981 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004982 __throw_runtime_error("locale not supported");
4983 wbe = wbuf + j;
4984 __months_[i+12].assign(wbuf, wbe);
4985 }
4986 // __am_pm_
4987 t.tm_hour = 1;
Howard Hinnantc6e54b92012-12-27 18:46:00 +00004988 strftime_l(buf, 100, "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004989 mb = mbstate_t();
4990 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004991#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004992 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4993#else
4994 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4995#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004996 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004997 __throw_runtime_error("locale not supported");
4998 wbe = wbuf + j;
4999 __am_pm_[0].assign(wbuf, wbe);
5000 t.tm_hour = 13;
Howard Hinnantc6e54b92012-12-27 18:46:00 +00005001 strftime_l(buf, 100, "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005002 mb = mbstate_t();
5003 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005004#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005005 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
5006#else
5007 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
5008#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005009 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005010 __throw_runtime_error("locale not supported");
5011 wbe = wbuf + j;
5012 __am_pm_[1].assign(wbuf, wbe);
5013 __c_ = __analyze('c', ct);
5014 __r_ = __analyze('r', ct);
5015 __x_ = __analyze('x', ct);
5016 __X_ = __analyze('X', ct);
5017}
5018
5019template <class CharT>
5020struct _LIBCPP_HIDDEN __time_get_temp
5021 : public ctype_byname<CharT>
5022{
5023 explicit __time_get_temp(const char* nm)
5024 : ctype_byname<CharT>(nm, 1) {}
5025 explicit __time_get_temp(const string& nm)
5026 : ctype_byname<CharT>(nm, 1) {}
5027};
5028
5029template <>
5030__time_get_storage<char>::__time_get_storage(const char* __nm)
5031 : __time_get(__nm)
5032{
5033 const __time_get_temp<char> ct(__nm);
5034 init(ct);
5035}
5036
5037template <>
5038__time_get_storage<char>::__time_get_storage(const string& __nm)
5039 : __time_get(__nm)
5040{
5041 const __time_get_temp<char> ct(__nm);
5042 init(ct);
5043}
5044
5045template <>
5046__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5047 : __time_get(__nm)
5048{
5049 const __time_get_temp<wchar_t> ct(__nm);
5050 init(ct);
5051}
5052
5053template <>
5054__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5055 : __time_get(__nm)
5056{
5057 const __time_get_temp<wchar_t> ct(__nm);
5058 init(ct);
5059}
5060
5061template <>
5062time_base::dateorder
5063__time_get_storage<char>::__do_date_order() const
5064{
5065 unsigned i;
5066 for (i = 0; i < __x_.size(); ++i)
5067 if (__x_[i] == '%')
5068 break;
5069 ++i;
5070 switch (__x_[i])
5071 {
5072 case 'y':
5073 case 'Y':
5074 for (++i; i < __x_.size(); ++i)
5075 if (__x_[i] == '%')
5076 break;
5077 if (i == __x_.size())
5078 break;
5079 ++i;
5080 switch (__x_[i])
5081 {
5082 case 'm':
5083 for (++i; i < __x_.size(); ++i)
5084 if (__x_[i] == '%')
5085 break;
5086 if (i == __x_.size())
5087 break;
5088 ++i;
5089 if (__x_[i] == 'd')
5090 return time_base::ymd;
5091 break;
5092 case 'd':
5093 for (++i; i < __x_.size(); ++i)
5094 if (__x_[i] == '%')
5095 break;
5096 if (i == __x_.size())
5097 break;
5098 ++i;
5099 if (__x_[i] == 'm')
5100 return time_base::ydm;
5101 break;
5102 }
5103 break;
5104 case 'm':
5105 for (++i; i < __x_.size(); ++i)
5106 if (__x_[i] == '%')
5107 break;
5108 if (i == __x_.size())
5109 break;
5110 ++i;
5111 if (__x_[i] == 'd')
5112 {
5113 for (++i; i < __x_.size(); ++i)
5114 if (__x_[i] == '%')
5115 break;
5116 if (i == __x_.size())
5117 break;
5118 ++i;
5119 if (__x_[i] == 'y' || __x_[i] == 'Y')
5120 return time_base::mdy;
5121 break;
5122 }
5123 break;
5124 case 'd':
5125 for (++i; i < __x_.size(); ++i)
5126 if (__x_[i] == '%')
5127 break;
5128 if (i == __x_.size())
5129 break;
5130 ++i;
5131 if (__x_[i] == 'm')
5132 {
5133 for (++i; i < __x_.size(); ++i)
5134 if (__x_[i] == '%')
5135 break;
5136 if (i == __x_.size())
5137 break;
5138 ++i;
5139 if (__x_[i] == 'y' || __x_[i] == 'Y')
5140 return time_base::dmy;
5141 break;
5142 }
5143 break;
5144 }
5145 return time_base::no_order;
5146}
5147
5148template <>
5149time_base::dateorder
5150__time_get_storage<wchar_t>::__do_date_order() const
5151{
5152 unsigned i;
5153 for (i = 0; i < __x_.size(); ++i)
5154 if (__x_[i] == L'%')
5155 break;
5156 ++i;
5157 switch (__x_[i])
5158 {
5159 case L'y':
5160 case L'Y':
5161 for (++i; i < __x_.size(); ++i)
5162 if (__x_[i] == L'%')
5163 break;
5164 if (i == __x_.size())
5165 break;
5166 ++i;
5167 switch (__x_[i])
5168 {
5169 case L'm':
5170 for (++i; i < __x_.size(); ++i)
5171 if (__x_[i] == L'%')
5172 break;
5173 if (i == __x_.size())
5174 break;
5175 ++i;
5176 if (__x_[i] == L'd')
5177 return time_base::ymd;
5178 break;
5179 case L'd':
5180 for (++i; i < __x_.size(); ++i)
5181 if (__x_[i] == L'%')
5182 break;
5183 if (i == __x_.size())
5184 break;
5185 ++i;
5186 if (__x_[i] == L'm')
5187 return time_base::ydm;
5188 break;
5189 }
5190 break;
5191 case L'm':
5192 for (++i; i < __x_.size(); ++i)
5193 if (__x_[i] == L'%')
5194 break;
5195 if (i == __x_.size())
5196 break;
5197 ++i;
5198 if (__x_[i] == L'd')
5199 {
5200 for (++i; i < __x_.size(); ++i)
5201 if (__x_[i] == L'%')
5202 break;
5203 if (i == __x_.size())
5204 break;
5205 ++i;
5206 if (__x_[i] == L'y' || __x_[i] == L'Y')
5207 return time_base::mdy;
5208 break;
5209 }
5210 break;
5211 case L'd':
5212 for (++i; i < __x_.size(); ++i)
5213 if (__x_[i] == L'%')
5214 break;
5215 if (i == __x_.size())
5216 break;
5217 ++i;
5218 if (__x_[i] == L'm')
5219 {
5220 for (++i; i < __x_.size(); ++i)
5221 if (__x_[i] == L'%')
5222 break;
5223 if (i == __x_.size())
5224 break;
5225 ++i;
5226 if (__x_[i] == L'y' || __x_[i] == L'Y')
5227 return time_base::dmy;
5228 break;
5229 }
5230 break;
5231 }
5232 return time_base::no_order;
5233}
5234
5235// time_put
5236
5237__time_put::__time_put(const char* nm)
5238 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5239{
Howard Hinnantd4444702010-08-11 17:04:31 +00005240#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005241 if (__loc_ == 0)
5242 throw runtime_error("time_put_byname"
5243 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005244#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005245}
5246
5247__time_put::__time_put(const string& nm)
5248 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5249{
Howard Hinnantd4444702010-08-11 17:04:31 +00005250#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005251 if (__loc_ == 0)
5252 throw runtime_error("time_put_byname"
5253 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005254#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005255}
5256
5257__time_put::~__time_put()
5258{
5259 if (__loc_)
5260 freelocale(__loc_);
5261}
5262
5263void
5264__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5265 char __fmt, char __mod) const
5266{
5267 char fmt[] = {'%', __fmt, __mod, 0};
5268 if (__mod != 0)
5269 swap(fmt[1], fmt[2]);
Howard Hinnantec3773c2011-12-01 20:21:04 +00005270 size_t n = strftime_l(__nb, static_cast<size_t>(__ne-__nb), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005271 __ne = __nb + n;
5272}
5273
5274void
5275__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5276 char __fmt, char __mod) const
5277{
5278 char __nar[100];
5279 char* __ne = __nar + 100;
5280 __do_put(__nar, __ne, __tm, __fmt, __mod);
5281 mbstate_t mb = {0};
5282 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005283#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005284 size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5285#else
5286 size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5287#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005288 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005289 __throw_runtime_error("locale not supported");
5290 __we = __wb + j;
5291}
5292
5293// moneypunct_byname
5294
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005295template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005296static
5297void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005298__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5299 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5300 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005301{
5302 const char sign = static_cast<char>(money_base::sign);
5303 const char space = static_cast<char>(money_base::space);
5304 const char none = static_cast<char>(money_base::none);
5305 const char symbol = static_cast<char>(money_base::symbol);
5306 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005307 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5308
5309 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5310 // function'. "Space between sign and symbol or value" means that
5311 // if the sign is adjacent to the symbol, there's a space between
5312 // them, and otherwise there's a space between the sign and value.
5313 //
5314 // C11's localeconv specifies that the fourth character of an
5315 // international curr_symbol is used to separate the sign and
5316 // value when sep_by_space says to do so. C++ can't represent
5317 // that, so we just use a space. When sep_by_space says to
5318 // separate the symbol and value-or-sign with a space, we rearrange the
5319 // curr_symbol to put its spacing character on the correct side of
5320 // the symbol.
5321 //
5322 // We also need to avoid adding an extra space between the sign
5323 // and value when the currency symbol is suppressed (by not
5324 // setting showbase). We match glibc's strfmon by interpreting
5325 // sep_by_space==1 as "omit the space when the currency symbol is
5326 // absent".
5327 //
5328 // Users who want to get this right should use ICU instead.
5329
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005330 switch (cs_precedes)
5331 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005332 case 0: // value before curr_symbol
5333 if (symbol_contains_sep) {
5334 // Move the separator to before the symbol, to place it
5335 // between the value and symbol.
5336 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5337 __curr_symbol_.end());
5338 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005339 switch (sign_posn)
5340 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005341 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005342 pat.field[0] = sign;
5343 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005344 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005345 pat.field[3] = symbol;
5346 switch (sep_by_space)
5347 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005348 case 0: // No space separates the currency symbol and value.
5349 // This case may have changed between C99 and C11;
5350 // assume the currency symbol matches the intention.
5351 case 2: // Space between sign and currency or value.
5352 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005353 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005354 case 1: // Space between currency-and-sign or currency and value.
5355 if (!symbol_contains_sep) {
5356 // We insert the space into the symbol instead of
5357 // setting pat.field[2]=space so that when
5358 // showbase is not set, the space goes away too.
5359 __curr_symbol_.insert(0, 1, space_char);
5360 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005361 return;
5362 default:
5363 break;
5364 }
5365 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005366 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005367 pat.field[0] = sign;
5368 pat.field[3] = symbol;
5369 switch (sep_by_space)
5370 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005371 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005372 pat.field[1] = value;
5373 pat.field[2] = none;
5374 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005375 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005376 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005377 pat.field[2] = none;
5378 if (!symbol_contains_sep) {
5379 // We insert the space into the symbol instead of
5380 // setting pat.field[2]=space so that when
5381 // showbase is not set, the space goes away too.
5382 __curr_symbol_.insert(0, 1, space_char);
5383 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005384 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005385 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005386 pat.field[1] = space;
5387 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005388 if (symbol_contains_sep) {
5389 // Remove the separator from the symbol, since it
5390 // has already appeared after the sign.
5391 __curr_symbol_.erase(__curr_symbol_.begin());
5392 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005393 return;
5394 default:
5395 break;
5396 }
5397 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005398 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005399 pat.field[0] = value;
5400 pat.field[3] = sign;
5401 switch (sep_by_space)
5402 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005403 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005404 pat.field[1] = none;
5405 pat.field[2] = symbol;
5406 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005407 case 1: // Space between currency-and-sign or currency and value.
5408 if (!symbol_contains_sep) {
5409 // We insert the space into the symbol instead of
5410 // setting pat.field[1]=space so that when
5411 // showbase is not set, the space goes away too.
5412 __curr_symbol_.insert(0, 1, space_char);
5413 }
5414 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005415 pat.field[2] = symbol;
5416 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005417 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005418 pat.field[1] = symbol;
5419 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005420 if (symbol_contains_sep) {
5421 // Remove the separator from the symbol, since it
5422 // should not be removed if showbase is absent.
5423 __curr_symbol_.erase(__curr_symbol_.begin());
5424 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005425 return;
5426 default:
5427 break;
5428 }
5429 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005430 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005431 pat.field[0] = value;
5432 pat.field[3] = symbol;
5433 switch (sep_by_space)
5434 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005435 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005436 pat.field[1] = none;
5437 pat.field[2] = sign;
5438 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005439 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005440 pat.field[1] = space;
5441 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005442 if (symbol_contains_sep) {
5443 // Remove the separator from the symbol, since it
5444 // has already appeared before the sign.
5445 __curr_symbol_.erase(__curr_symbol_.begin());
5446 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005447 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005448 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005449 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005450 pat.field[2] = none;
5451 if (!symbol_contains_sep) {
5452 // We insert the space into the symbol instead of
5453 // setting pat.field[2]=space so that when
5454 // showbase is not set, the space goes away too.
5455 __curr_symbol_.insert(0, 1, space_char);
5456 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005457 return;
5458 default:
5459 break;
5460 }
5461 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005462 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005463 pat.field[0] = value;
5464 pat.field[3] = sign;
5465 switch (sep_by_space)
5466 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005467 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005468 pat.field[1] = none;
5469 pat.field[2] = symbol;
5470 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005471 case 1: // Space between currency-and-sign or currency and value.
5472 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005473 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005474 if (!symbol_contains_sep) {
5475 // We insert the space into the symbol instead of
5476 // setting pat.field[1]=space so that when
5477 // showbase is not set, the space goes away too.
5478 __curr_symbol_.insert(0, 1, space_char);
5479 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005480 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005481 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005482 pat.field[1] = symbol;
5483 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005484 if (symbol_contains_sep) {
5485 // Remove the separator from the symbol, since it
5486 // should not disappear when showbase is absent.
5487 __curr_symbol_.erase(__curr_symbol_.begin());
5488 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005489 return;
5490 default:
5491 break;
5492 }
5493 break;
5494 default:
5495 break;
5496 }
5497 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005498 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005499 switch (sign_posn)
5500 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005501 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005502 pat.field[0] = sign;
5503 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005504 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005505 pat.field[3] = value;
5506 switch (sep_by_space)
5507 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005508 case 0: // No space separates the currency symbol and value.
5509 // This case may have changed between C99 and C11;
5510 // assume the currency symbol matches the intention.
5511 case 2: // Space between sign and currency or value.
5512 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005513 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005514 case 1: // Space between currency-and-sign or currency and value.
5515 if (!symbol_contains_sep) {
5516 // We insert the space into the symbol instead of
5517 // setting pat.field[2]=space so that when
5518 // showbase is not set, the space goes away too.
5519 __curr_symbol_.insert(0, 1, space_char);
5520 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005521 return;
5522 default:
5523 break;
5524 }
5525 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005526 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005527 pat.field[0] = sign;
5528 pat.field[3] = value;
5529 switch (sep_by_space)
5530 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005531 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005532 pat.field[1] = symbol;
5533 pat.field[2] = none;
5534 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005535 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005536 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005537 pat.field[2] = none;
5538 if (!symbol_contains_sep) {
5539 // We insert the space into the symbol instead of
5540 // setting pat.field[2]=space so that when
5541 // showbase is not set, the space goes away too.
5542 __curr_symbol_.push_back(space_char);
5543 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005544 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005545 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005546 pat.field[1] = space;
5547 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005548 if (symbol_contains_sep) {
5549 // Remove the separator from the symbol, since it
5550 // has already appeared after the sign.
5551 __curr_symbol_.pop_back();
5552 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005553 return;
5554 default:
5555 break;
5556 }
5557 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005558 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005559 pat.field[0] = symbol;
5560 pat.field[3] = sign;
5561 switch (sep_by_space)
5562 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005563 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005564 pat.field[1] = none;
5565 pat.field[2] = value;
5566 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005567 case 1: // Space between currency-and-sign or currency and value.
5568 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005569 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005570 if (!symbol_contains_sep) {
5571 // We insert the space into the symbol instead of
5572 // setting pat.field[1]=space so that when
5573 // showbase is not set, the space goes away too.
5574 __curr_symbol_.push_back(space_char);
5575 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005576 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005577 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005578 pat.field[1] = value;
5579 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005580 if (symbol_contains_sep) {
5581 // Remove the separator from the symbol, since it
5582 // will appear before the sign.
5583 __curr_symbol_.pop_back();
5584 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005585 return;
5586 default:
5587 break;
5588 }
5589 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005590 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005591 pat.field[0] = sign;
5592 pat.field[3] = value;
5593 switch (sep_by_space)
5594 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005595 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005596 pat.field[1] = symbol;
5597 pat.field[2] = none;
5598 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005599 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005600 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005601 pat.field[2] = none;
5602 if (!symbol_contains_sep) {
5603 // We insert the space into the symbol instead of
5604 // setting pat.field[2]=space so that when
5605 // showbase is not set, the space goes away too.
5606 __curr_symbol_.push_back(space_char);
5607 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005608 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005609 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005610 pat.field[1] = space;
5611 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005612 if (symbol_contains_sep) {
5613 // Remove the separator from the symbol, since it
5614 // has already appeared after the sign.
5615 __curr_symbol_.pop_back();
5616 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005617 return;
5618 default:
5619 break;
5620 }
5621 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005622 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005623 pat.field[0] = symbol;
5624 pat.field[3] = value;
5625 switch (sep_by_space)
5626 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005627 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005628 pat.field[1] = sign;
5629 pat.field[2] = none;
5630 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005631 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005632 pat.field[1] = sign;
5633 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005634 if (symbol_contains_sep) {
5635 // Remove the separator from the symbol, since it
5636 // should not disappear when showbase is absent.
5637 __curr_symbol_.pop_back();
5638 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005639 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005640 case 2: // Space between sign and currency or value.
5641 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005642 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005643 if (!symbol_contains_sep) {
5644 // We insert the space into the symbol instead of
5645 // setting pat.field[1]=space so that when
5646 // showbase is not set, the space goes away too.
5647 __curr_symbol_.push_back(space_char);
5648 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005649 return;
5650 default:
5651 break;
5652 }
5653 break;
5654 default:
5655 break;
5656 }
5657 break;
5658 default:
5659 break;
5660 }
5661 pat.field[0] = symbol;
5662 pat.field[1] = sign;
5663 pat.field[2] = none;
5664 pat.field[3] = value;
5665}
5666
5667template<>
5668void
5669moneypunct_byname<char, false>::init(const char* nm)
5670{
5671 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005672 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005673#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005674 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005675 throw runtime_error("moneypunct_byname"
5676 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005677#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005678#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005679 lconv* lc = localeconv_l(loc.get());
5680#else
5681 lconv* lc = __localeconv_l(loc.get());
5682#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005683 if (*lc->mon_decimal_point)
5684 __decimal_point_ = *lc->mon_decimal_point;
5685 else
5686 __decimal_point_ = base::do_decimal_point();
5687 if (*lc->mon_thousands_sep)
5688 __thousands_sep_ = *lc->mon_thousands_sep;
5689 else
5690 __thousands_sep_ = base::do_thousands_sep();
5691 __grouping_ = lc->mon_grouping;
5692 __curr_symbol_ = lc->currency_symbol;
5693 if (lc->frac_digits != CHAR_MAX)
5694 __frac_digits_ = lc->frac_digits;
5695 else
5696 __frac_digits_ = base::do_frac_digits();
5697 if (lc->p_sign_posn == 0)
5698 __positive_sign_ = "()";
5699 else
5700 __positive_sign_ = lc->positive_sign;
5701 if (lc->n_sign_posn == 0)
5702 __negative_sign_ = "()";
5703 else
5704 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005705 // Assume the positive and negative formats will want spaces in
5706 // the same places in curr_symbol since there's no way to
5707 // represent anything else.
5708 string_type __dummy_curr_symbol = __curr_symbol_;
5709 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5710 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5711 __init_pat(__neg_format_, __curr_symbol_, false,
5712 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005713}
5714
5715template<>
5716void
5717moneypunct_byname<char, true>::init(const char* nm)
5718{
5719 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005720 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005721#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005722 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005723 throw runtime_error("moneypunct_byname"
5724 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005725#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005726#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005727 lconv* lc = localeconv_l(loc.get());
5728#else
5729 lconv* lc = __localeconv_l(loc.get());
5730#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005731 if (*lc->mon_decimal_point)
5732 __decimal_point_ = *lc->mon_decimal_point;
5733 else
5734 __decimal_point_ = base::do_decimal_point();
5735 if (*lc->mon_thousands_sep)
5736 __thousands_sep_ = *lc->mon_thousands_sep;
5737 else
5738 __thousands_sep_ = base::do_thousands_sep();
5739 __grouping_ = lc->mon_grouping;
5740 __curr_symbol_ = lc->int_curr_symbol;
5741 if (lc->int_frac_digits != CHAR_MAX)
5742 __frac_digits_ = lc->int_frac_digits;
5743 else
5744 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005745#if _WIN32
5746 if (lc->p_sign_posn == 0)
5747#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005748 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005749#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005750 __positive_sign_ = "()";
5751 else
5752 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005753#if _WIN32
5754 if(lc->n_sign_posn == 0)
5755#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005756 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005757#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005758 __negative_sign_ = "()";
5759 else
5760 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005761 // Assume the positive and negative formats will want spaces in
5762 // the same places in curr_symbol since there's no way to
5763 // represent anything else.
5764 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005765#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005766 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5767 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5768 __init_pat(__neg_format_, __curr_symbol_, true,
5769 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005770#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005771 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5772 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5773 lc->int_p_sign_posn, ' ');
5774 __init_pat(__neg_format_, __curr_symbol_, true,
5775 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5776 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005777#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005778}
5779
5780template<>
5781void
5782moneypunct_byname<wchar_t, false>::init(const char* nm)
5783{
5784 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005785 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005786#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005787 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005788 throw runtime_error("moneypunct_byname"
5789 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005790#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005791#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005792 lconv* lc = localeconv_l(loc.get());
5793#else
5794 lconv* lc = __localeconv_l(loc.get());
5795#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005796 if (*lc->mon_decimal_point)
5797 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5798 else
5799 __decimal_point_ = base::do_decimal_point();
5800 if (*lc->mon_thousands_sep)
5801 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5802 else
5803 __thousands_sep_ = base::do_thousands_sep();
5804 __grouping_ = lc->mon_grouping;
5805 wchar_t wbuf[100];
5806 mbstate_t mb = {0};
5807 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005808#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005809 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5810#else
5811 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5812#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005813 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005814 __throw_runtime_error("locale not supported");
5815 wchar_t* wbe = wbuf + j;
5816 __curr_symbol_.assign(wbuf, wbe);
5817 if (lc->frac_digits != CHAR_MAX)
5818 __frac_digits_ = lc->frac_digits;
5819 else
5820 __frac_digits_ = base::do_frac_digits();
5821 if (lc->p_sign_posn == 0)
5822 __positive_sign_ = L"()";
5823 else
5824 {
5825 mb = mbstate_t();
5826 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005827#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005828 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5829#else
5830 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5831#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005832 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005833 __throw_runtime_error("locale not supported");
5834 wbe = wbuf + j;
5835 __positive_sign_.assign(wbuf, wbe);
5836 }
5837 if (lc->n_sign_posn == 0)
5838 __negative_sign_ = L"()";
5839 else
5840 {
5841 mb = mbstate_t();
5842 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005843#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005844 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5845#else
5846 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5847#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005848 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005849 __throw_runtime_error("locale not supported");
5850 wbe = wbuf + j;
5851 __negative_sign_.assign(wbuf, wbe);
5852 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005853 // Assume the positive and negative formats will want spaces in
5854 // the same places in curr_symbol since there's no way to
5855 // represent anything else.
5856 string_type __dummy_curr_symbol = __curr_symbol_;
5857 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5858 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5859 __init_pat(__neg_format_, __curr_symbol_, false,
5860 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005861}
5862
5863template<>
5864void
5865moneypunct_byname<wchar_t, true>::init(const char* nm)
5866{
5867 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005868 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005869#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005870 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005871 throw runtime_error("moneypunct_byname"
5872 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005873#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005874#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005875 lconv* lc = localeconv_l(loc.get());
5876#else
5877 lconv* lc = __localeconv_l(loc.get());
5878#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005879 if (*lc->mon_decimal_point)
5880 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5881 else
5882 __decimal_point_ = base::do_decimal_point();
5883 if (*lc->mon_thousands_sep)
5884 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5885 else
5886 __thousands_sep_ = base::do_thousands_sep();
5887 __grouping_ = lc->mon_grouping;
5888 wchar_t wbuf[100];
5889 mbstate_t mb = {0};
5890 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005891#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005892 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5893#else
5894 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5895#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005896 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005897 __throw_runtime_error("locale not supported");
5898 wchar_t* wbe = wbuf + j;
5899 __curr_symbol_.assign(wbuf, wbe);
5900 if (lc->int_frac_digits != CHAR_MAX)
5901 __frac_digits_ = lc->int_frac_digits;
5902 else
5903 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005904#if _WIN32
5905 if (lc->p_sign_posn == 0)
5906#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005907 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005908#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005909 __positive_sign_ = L"()";
5910 else
5911 {
5912 mb = mbstate_t();
5913 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005914#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005915 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5916#else
5917 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5918#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005919 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005920 __throw_runtime_error("locale not supported");
5921 wbe = wbuf + j;
5922 __positive_sign_.assign(wbuf, wbe);
5923 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005924#if _WIN32
5925 if (lc->n_sign_posn == 0)
5926#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005927 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005928#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005929 __negative_sign_ = L"()";
5930 else
5931 {
5932 mb = mbstate_t();
5933 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005934#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005935 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5936#else
5937 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5938#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005939 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005940 __throw_runtime_error("locale not supported");
5941 wbe = wbuf + j;
5942 __negative_sign_.assign(wbuf, wbe);
5943 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005944 // Assume the positive and negative formats will want spaces in
5945 // the same places in curr_symbol since there's no way to
5946 // represent anything else.
5947 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005948#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005949 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5950 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5951 __init_pat(__neg_format_, __curr_symbol_, true,
5952 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005953#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005954 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5955 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5956 lc->int_p_sign_posn, L' ');
5957 __init_pat(__neg_format_, __curr_symbol_, true,
5958 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5959 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005960#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005961}
5962
5963void __do_nothing(void*) {}
5964
5965void __throw_runtime_error(const char* msg)
5966{
Howard Hinnantd4444702010-08-11 17:04:31 +00005967#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005968 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00005969#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005970}
5971
5972template class collate<char>;
5973template class collate<wchar_t>;
5974
5975template class num_get<char>;
5976template class num_get<wchar_t>;
5977
Howard Hinnantec3773c2011-12-01 20:21:04 +00005978template struct __num_get<char>;
5979template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005980
5981template class num_put<char>;
5982template class num_put<wchar_t>;
5983
Howard Hinnantec3773c2011-12-01 20:21:04 +00005984template struct __num_put<char>;
5985template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005986
5987template class time_get<char>;
5988template class time_get<wchar_t>;
5989
5990template class time_get_byname<char>;
5991template class time_get_byname<wchar_t>;
5992
5993template class time_put<char>;
5994template class time_put<wchar_t>;
5995
5996template class time_put_byname<char>;
5997template class time_put_byname<wchar_t>;
5998
5999template class moneypunct<char, false>;
6000template class moneypunct<char, true>;
6001template class moneypunct<wchar_t, false>;
6002template class moneypunct<wchar_t, true>;
6003
6004template class moneypunct_byname<char, false>;
6005template class moneypunct_byname<char, true>;
6006template class moneypunct_byname<wchar_t, false>;
6007template class moneypunct_byname<wchar_t, true>;
6008
6009template class money_get<char>;
6010template class money_get<wchar_t>;
6011
6012template class __money_get<char>;
6013template class __money_get<wchar_t>;
6014
6015template class money_put<char>;
6016template class money_put<wchar_t>;
6017
6018template class __money_put<char>;
6019template class __money_put<wchar_t>;
6020
6021template class messages<char>;
6022template class messages<wchar_t>;
6023
6024template class messages_byname<char>;
6025template class messages_byname<wchar_t>;
6026
6027template class codecvt_byname<char, char, mbstate_t>;
6028template class codecvt_byname<wchar_t, char, mbstate_t>;
6029template class codecvt_byname<char16_t, char, mbstate_t>;
6030template class codecvt_byname<char32_t, char, mbstate_t>;
6031
6032template class __vector_base_common<true>;
6033
6034_LIBCPP_END_NAMESPACE_STD