1 | //===------------------------- locale.cpp ---------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // On Solaris, we need to define something to make the C99 parts of localeconv |
10 | // visible. |
11 | #ifdef __sun__ |
12 | #define _LCONV_C99 |
13 | #endif |
14 | |
15 | #include "string" |
16 | #include "locale" |
17 | #include "codecvt" |
18 | #include "vector" |
19 | #include "algorithm" |
20 | #include "typeinfo" |
21 | #ifndef _LIBCPP_NO_EXCEPTIONS |
22 | # include "type_traits" |
23 | #endif |
24 | #include "clocale" |
25 | #include "cstring" |
26 | #if defined(_LIBCPP_MSVCRT) |
27 | #define _CTYPE_DISABLE_MACROS |
28 | #endif |
29 | #include "cwctype" |
30 | #include "__sso_allocator" |
31 | #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
32 | #include "support/win32/locale_win32.h" |
33 | #elif !defined(__BIONIC__) |
34 | #include <langinfo.h> |
35 | #endif |
36 | #include <stdlib.h> |
37 | #include <stdio.h> |
38 | #include "include/atomic_support.h" |
39 | #include "__undef_macros" |
40 | |
41 | // On Linux, wint_t and wchar_t have different signed-ness, and this causes |
42 | // lots of noise in the build log, but no bugs that I know of. |
43 | #if defined(__clang__) |
44 | #pragma clang diagnostic ignored "-Wsign-conversion" |
45 | #endif |
46 | |
47 | _LIBCPP_BEGIN_NAMESPACE_STD |
48 | |
49 | struct __libcpp_unique_locale { |
50 | __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {} |
51 | |
52 | ~__libcpp_unique_locale() { |
53 | if (__loc_) |
54 | freelocale(__loc_); |
55 | } |
56 | |
57 | explicit operator bool() const { return __loc_; } |
58 | |
59 | locale_t& get() { return __loc_; } |
60 | |
61 | locale_t __loc_; |
62 | private: |
63 | __libcpp_unique_locale(__libcpp_unique_locale const&); |
64 | __libcpp_unique_locale& operator=(__libcpp_unique_locale const&); |
65 | }; |
66 | |
67 | #ifdef __cloc_defined |
68 | locale_t __cloc() { |
69 | // In theory this could create a race condition. In practice |
70 | // the race condition is non-fatal since it will just create |
71 | // a little resource leak. Better approach would be appreciated. |
72 | static locale_t result = newlocale(LC_ALL_MASK, "C" , 0); |
73 | return result; |
74 | } |
75 | #endif // __cloc_defined |
76 | |
77 | namespace { |
78 | |
79 | struct release |
80 | { |
81 | void operator()(locale::facet* p) {p->__release_shared();} |
82 | }; |
83 | |
84 | template <class T, class A0> |
85 | inline |
86 | T& |
87 | make(A0 a0) |
88 | { |
89 | static typename aligned_storage<sizeof(T)>::type buf; |
90 | auto *obj = ::new (&buf) T(a0); |
91 | return *obj; |
92 | } |
93 | |
94 | template <class T, class A0, class A1> |
95 | inline |
96 | T& |
97 | make(A0 a0, A1 a1) |
98 | { |
99 | static typename aligned_storage<sizeof(T)>::type buf; |
100 | ::new (&buf) T(a0, a1); |
101 | return *reinterpret_cast<T*>(&buf); |
102 | } |
103 | |
104 | template <class T, class A0, class A1, class A2> |
105 | inline |
106 | T& |
107 | make(A0 a0, A1 a1, A2 a2) |
108 | { |
109 | static typename aligned_storage<sizeof(T)>::type buf; |
110 | auto *obj = ::new (&buf) T(a0, a1, a2); |
111 | return *obj; |
112 | } |
113 | |
114 | template <typename T, size_t N> |
115 | inline |
116 | _LIBCPP_CONSTEXPR |
117 | size_t |
118 | countof(const T (&)[N]) |
119 | { |
120 | return N; |
121 | } |
122 | |
123 | template <typename T> |
124 | inline |
125 | _LIBCPP_CONSTEXPR |
126 | size_t |
127 | countof(const T * const begin, const T * const end) |
128 | { |
129 | return static_cast<size_t>(end - begin); |
130 | } |
131 | |
132 | _LIBCPP_NORETURN static void __throw_runtime_error(const string &msg) |
133 | { |
134 | #ifndef _LIBCPP_NO_EXCEPTIONS |
135 | throw runtime_error(msg); |
136 | #else |
137 | (void)msg; |
138 | _VSTD::abort(); |
139 | #endif |
140 | } |
141 | |
142 | } |
143 | |
144 | #if defined(_AIX) |
145 | // Set priority to INT_MIN + 256 + 150 |
146 | # pragma priority ( -2147483242 ) |
147 | #endif |
148 | |
149 | const locale::category locale::none; |
150 | const locale::category locale::collate; |
151 | const locale::category locale::ctype; |
152 | const locale::category locale::monetary; |
153 | const locale::category locale::numeric; |
154 | const locale::category locale::time; |
155 | const locale::category locale::messages; |
156 | const locale::category locale::all; |
157 | |
158 | class _LIBCPP_HIDDEN locale::__imp |
159 | : public facet |
160 | { |
161 | enum {N = 28}; |
162 | #if defined(_LIBCPP_COMPILER_MSVC) |
163 | // FIXME: MSVC doesn't support aligned parameters by value. |
164 | // I can't get the __sso_allocator to work here |
165 | // for MSVC I think for this reason. |
166 | vector<facet*> facets_; |
167 | #else |
168 | vector<facet*, __sso_allocator<facet*, N> > facets_; |
169 | #endif |
170 | string name_; |
171 | public: |
172 | explicit __imp(size_t refs = 0); |
173 | explicit __imp(const string& name, size_t refs = 0); |
174 | __imp(const __imp&); |
175 | __imp(const __imp&, const string&, locale::category c); |
176 | __imp(const __imp& other, const __imp& one, locale::category c); |
177 | __imp(const __imp&, facet* f, long id); |
178 | ~__imp(); |
179 | |
180 | const string& name() const {return name_;} |
181 | bool has_facet(long id) const |
182 | {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];} |
183 | const locale::facet* use_facet(long id) const; |
184 | |
185 | static const locale& make_classic(); |
186 | static locale& make_global(); |
187 | private: |
188 | void install(facet* f, long id); |
189 | template <class F> void install(F* f) {install(f, f->id.__get());} |
190 | template <class F> void install_from(const __imp& other); |
191 | }; |
192 | |
193 | locale::__imp::__imp(size_t refs) |
194 | : facet(refs), |
195 | facets_(N), |
196 | name_("C" ) |
197 | { |
198 | facets_.clear(); |
199 | install(&make<_VSTD::collate<char> >(1u)); |
200 | install(&make<_VSTD::collate<wchar_t> >(1u)); |
201 | install(&make<_VSTD::ctype<char> >(nullptr, false, 1u)); |
202 | install(&make<_VSTD::ctype<wchar_t> >(1u)); |
203 | install(&make<codecvt<char, char, mbstate_t> >(1u)); |
204 | install(&make<codecvt<wchar_t, char, mbstate_t> >(1u)); |
205 | install(&make<codecvt<char16_t, char, mbstate_t> >(1u)); |
206 | install(&make<codecvt<char32_t, char, mbstate_t> >(1u)); |
207 | install(&make<numpunct<char> >(1u)); |
208 | install(&make<numpunct<wchar_t> >(1u)); |
209 | install(&make<num_get<char> >(1u)); |
210 | install(&make<num_get<wchar_t> >(1u)); |
211 | install(&make<num_put<char> >(1u)); |
212 | install(&make<num_put<wchar_t> >(1u)); |
213 | install(&make<moneypunct<char, false> >(1u)); |
214 | install(&make<moneypunct<char, true> >(1u)); |
215 | install(&make<moneypunct<wchar_t, false> >(1u)); |
216 | install(&make<moneypunct<wchar_t, true> >(1u)); |
217 | install(&make<money_get<char> >(1u)); |
218 | install(&make<money_get<wchar_t> >(1u)); |
219 | install(&make<money_put<char> >(1u)); |
220 | install(&make<money_put<wchar_t> >(1u)); |
221 | install(&make<time_get<char> >(1u)); |
222 | install(&make<time_get<wchar_t> >(1u)); |
223 | install(&make<time_put<char> >(1u)); |
224 | install(&make<time_put<wchar_t> >(1u)); |
225 | install(&make<_VSTD::messages<char> >(1u)); |
226 | install(&make<_VSTD::messages<wchar_t> >(1u)); |
227 | } |
228 | |
229 | locale::__imp::__imp(const string& name, size_t refs) |
230 | : facet(refs), |
231 | facets_(N), |
232 | name_(name) |
233 | { |
234 | #ifndef _LIBCPP_NO_EXCEPTIONS |
235 | try |
236 | { |
237 | #endif // _LIBCPP_NO_EXCEPTIONS |
238 | facets_ = locale::classic().__locale_->facets_; |
239 | for (unsigned i = 0; i < facets_.size(); ++i) |
240 | if (facets_[i]) |
241 | facets_[i]->__add_shared(); |
242 | install(new collate_byname<char>(name_)); |
243 | install(new collate_byname<wchar_t>(name_)); |
244 | install(new ctype_byname<char>(name_)); |
245 | install(new ctype_byname<wchar_t>(name_)); |
246 | install(new codecvt_byname<char, char, mbstate_t>(name_)); |
247 | install(new codecvt_byname<wchar_t, char, mbstate_t>(name_)); |
248 | install(new codecvt_byname<char16_t, char, mbstate_t>(name_)); |
249 | install(new codecvt_byname<char32_t, char, mbstate_t>(name_)); |
250 | install(new numpunct_byname<char>(name_)); |
251 | install(new numpunct_byname<wchar_t>(name_)); |
252 | install(new moneypunct_byname<char, false>(name_)); |
253 | install(new moneypunct_byname<char, true>(name_)); |
254 | install(new moneypunct_byname<wchar_t, false>(name_)); |
255 | install(new moneypunct_byname<wchar_t, true>(name_)); |
256 | install(new time_get_byname<char>(name_)); |
257 | install(new time_get_byname<wchar_t>(name_)); |
258 | install(new time_put_byname<char>(name_)); |
259 | install(new time_put_byname<wchar_t>(name_)); |
260 | install(new messages_byname<char>(name_)); |
261 | install(new messages_byname<wchar_t>(name_)); |
262 | #ifndef _LIBCPP_NO_EXCEPTIONS |
263 | } |
264 | catch (...) |
265 | { |
266 | for (unsigned i = 0; i < facets_.size(); ++i) |
267 | if (facets_[i]) |
268 | facets_[i]->__release_shared(); |
269 | throw; |
270 | } |
271 | #endif // _LIBCPP_NO_EXCEPTIONS |
272 | } |
273 | |
274 | // NOTE avoid the `base class should be explicitly initialized in the |
275 | // copy constructor` warning emitted by GCC |
276 | #if defined(__clang__) || _GNUC_VER >= 406 |
277 | #pragma GCC diagnostic push |
278 | #pragma GCC diagnostic ignored "-Wextra" |
279 | #endif |
280 | |
281 | locale::__imp::__imp(const __imp& other) |
282 | : facets_(max<size_t>(N, other.facets_.size())), |
283 | name_(other.name_) |
284 | { |
285 | facets_ = other.facets_; |
286 | for (unsigned i = 0; i < facets_.size(); ++i) |
287 | if (facets_[i]) |
288 | facets_[i]->__add_shared(); |
289 | } |
290 | |
291 | #if defined(__clang__) || _GNUC_VER >= 406 |
292 | #pragma GCC diagnostic pop |
293 | #endif |
294 | |
295 | locale::__imp::__imp(const __imp& other, const string& name, locale::category c) |
296 | : facets_(N), |
297 | name_("*" ) |
298 | { |
299 | facets_ = other.facets_; |
300 | for (unsigned i = 0; i < facets_.size(); ++i) |
301 | if (facets_[i]) |
302 | facets_[i]->__add_shared(); |
303 | #ifndef _LIBCPP_NO_EXCEPTIONS |
304 | try |
305 | { |
306 | #endif // _LIBCPP_NO_EXCEPTIONS |
307 | if (c & locale::collate) |
308 | { |
309 | install(new collate_byname<char>(name)); |
310 | install(new collate_byname<wchar_t>(name)); |
311 | } |
312 | if (c & locale::ctype) |
313 | { |
314 | install(new ctype_byname<char>(name)); |
315 | install(new ctype_byname<wchar_t>(name)); |
316 | install(new codecvt_byname<char, char, mbstate_t>(name)); |
317 | install(new codecvt_byname<wchar_t, char, mbstate_t>(name)); |
318 | install(new codecvt_byname<char16_t, char, mbstate_t>(name)); |
319 | install(new codecvt_byname<char32_t, char, mbstate_t>(name)); |
320 | } |
321 | if (c & locale::monetary) |
322 | { |
323 | install(new moneypunct_byname<char, false>(name)); |
324 | install(new moneypunct_byname<char, true>(name)); |
325 | install(new moneypunct_byname<wchar_t, false>(name)); |
326 | install(new moneypunct_byname<wchar_t, true>(name)); |
327 | } |
328 | if (c & locale::numeric) |
329 | { |
330 | install(new numpunct_byname<char>(name)); |
331 | install(new numpunct_byname<wchar_t>(name)); |
332 | } |
333 | if (c & locale::time) |
334 | { |
335 | install(new time_get_byname<char>(name)); |
336 | install(new time_get_byname<wchar_t>(name)); |
337 | install(new time_put_byname<char>(name)); |
338 | install(new time_put_byname<wchar_t>(name)); |
339 | } |
340 | if (c & locale::messages) |
341 | { |
342 | install(new messages_byname<char>(name)); |
343 | install(new messages_byname<wchar_t>(name)); |
344 | } |
345 | #ifndef _LIBCPP_NO_EXCEPTIONS |
346 | } |
347 | catch (...) |
348 | { |
349 | for (unsigned i = 0; i < facets_.size(); ++i) |
350 | if (facets_[i]) |
351 | facets_[i]->__release_shared(); |
352 | throw; |
353 | } |
354 | #endif // _LIBCPP_NO_EXCEPTIONS |
355 | } |
356 | |
357 | template<class F> |
358 | inline |
359 | void |
360 | locale::__imp::install_from(const locale::__imp& one) |
361 | { |
362 | long id = F::id.__get(); |
363 | install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id); |
364 | } |
365 | |
366 | locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) |
367 | : facets_(N), |
368 | name_("*" ) |
369 | { |
370 | facets_ = other.facets_; |
371 | for (unsigned i = 0; i < facets_.size(); ++i) |
372 | if (facets_[i]) |
373 | facets_[i]->__add_shared(); |
374 | #ifndef _LIBCPP_NO_EXCEPTIONS |
375 | try |
376 | { |
377 | #endif // _LIBCPP_NO_EXCEPTIONS |
378 | if (c & locale::collate) |
379 | { |
380 | install_from<_VSTD::collate<char> >(one); |
381 | install_from<_VSTD::collate<wchar_t> >(one); |
382 | } |
383 | if (c & locale::ctype) |
384 | { |
385 | install_from<_VSTD::ctype<char> >(one); |
386 | install_from<_VSTD::ctype<wchar_t> >(one); |
387 | install_from<_VSTD::codecvt<char, char, mbstate_t> >(one); |
388 | install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one); |
389 | install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one); |
390 | install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one); |
391 | } |
392 | if (c & locale::monetary) |
393 | { |
394 | install_from<moneypunct<char, false> >(one); |
395 | install_from<moneypunct<char, true> >(one); |
396 | install_from<moneypunct<wchar_t, false> >(one); |
397 | install_from<moneypunct<wchar_t, true> >(one); |
398 | install_from<money_get<char> >(one); |
399 | install_from<money_get<wchar_t> >(one); |
400 | install_from<money_put<char> >(one); |
401 | install_from<money_put<wchar_t> >(one); |
402 | } |
403 | if (c & locale::numeric) |
404 | { |
405 | install_from<numpunct<char> >(one); |
406 | install_from<numpunct<wchar_t> >(one); |
407 | install_from<num_get<char> >(one); |
408 | install_from<num_get<wchar_t> >(one); |
409 | install_from<num_put<char> >(one); |
410 | install_from<num_put<wchar_t> >(one); |
411 | } |
412 | if (c & locale::time) |
413 | { |
414 | install_from<time_get<char> >(one); |
415 | install_from<time_get<wchar_t> >(one); |
416 | install_from<time_put<char> >(one); |
417 | install_from<time_put<wchar_t> >(one); |
418 | } |
419 | if (c & locale::messages) |
420 | { |
421 | install_from<_VSTD::messages<char> >(one); |
422 | install_from<_VSTD::messages<wchar_t> >(one); |
423 | } |
424 | #ifndef _LIBCPP_NO_EXCEPTIONS |
425 | } |
426 | catch (...) |
427 | { |
428 | for (unsigned i = 0; i < facets_.size(); ++i) |
429 | if (facets_[i]) |
430 | facets_[i]->__release_shared(); |
431 | throw; |
432 | } |
433 | #endif // _LIBCPP_NO_EXCEPTIONS |
434 | } |
435 | |
436 | locale::__imp::__imp(const __imp& other, facet* f, long id) |
437 | : facets_(max<size_t>(N, other.facets_.size()+1)), |
438 | name_("*" ) |
439 | { |
440 | f->__add_shared(); |
441 | unique_ptr<facet, release> hold(f); |
442 | facets_ = other.facets_; |
443 | for (unsigned i = 0; i < other.facets_.size(); ++i) |
444 | if (facets_[i]) |
445 | facets_[i]->__add_shared(); |
446 | install(hold.get(), id); |
447 | } |
448 | |
449 | locale::__imp::~__imp() |
450 | { |
451 | for (unsigned i = 0; i < facets_.size(); ++i) |
452 | if (facets_[i]) |
453 | facets_[i]->__release_shared(); |
454 | } |
455 | |
456 | void |
457 | locale::__imp::install(facet* f, long id) |
458 | { |
459 | f->__add_shared(); |
460 | unique_ptr<facet, release> hold(f); |
461 | if (static_cast<size_t>(id) >= facets_.size()) |
462 | facets_.resize(static_cast<size_t>(id+1)); |
463 | if (facets_[static_cast<size_t>(id)]) |
464 | facets_[static_cast<size_t>(id)]->__release_shared(); |
465 | facets_[static_cast<size_t>(id)] = hold.release(); |
466 | } |
467 | |
468 | const locale::facet* |
469 | locale::__imp::use_facet(long id) const |
470 | { |
471 | if (!has_facet(id)) |
472 | __throw_bad_cast(); |
473 | return facets_[static_cast<size_t>(id)]; |
474 | } |
475 | |
476 | // locale |
477 | |
478 | const locale& |
479 | locale::__imp::make_classic() |
480 | { |
481 | // only one thread can get in here and it only gets in once |
482 | static aligned_storage<sizeof(locale)>::type buf; |
483 | locale* c = reinterpret_cast<locale*>(&buf); |
484 | c->__locale_ = &make<__imp>(1u); |
485 | return *c; |
486 | } |
487 | |
488 | const locale& |
489 | locale::classic() |
490 | { |
491 | static const locale& c = __imp::make_classic(); |
492 | return c; |
493 | } |
494 | |
495 | locale& |
496 | locale::__imp::make_global() |
497 | { |
498 | // only one thread can get in here and it only gets in once |
499 | static aligned_storage<sizeof(locale)>::type buf; |
500 | auto *obj = ::new (&buf) locale(locale::classic()); |
501 | return *obj; |
502 | } |
503 | |
504 | locale& |
505 | locale::__global() |
506 | { |
507 | static locale& g = __imp::make_global(); |
508 | return g; |
509 | } |
510 | |
511 | locale::locale() _NOEXCEPT |
512 | : __locale_(__global().__locale_) |
513 | { |
514 | __locale_->__add_shared(); |
515 | } |
516 | |
517 | locale::locale(const locale& l) _NOEXCEPT |
518 | : __locale_(l.__locale_) |
519 | { |
520 | __locale_->__add_shared(); |
521 | } |
522 | |
523 | locale::~locale() |
524 | { |
525 | __locale_->__release_shared(); |
526 | } |
527 | |
528 | const locale& |
529 | locale::operator=(const locale& other) _NOEXCEPT |
530 | { |
531 | other.__locale_->__add_shared(); |
532 | __locale_->__release_shared(); |
533 | __locale_ = other.__locale_; |
534 | return *this; |
535 | } |
536 | |
537 | locale::locale(const char* name) |
538 | : __locale_(name ? new __imp(name) |
539 | : (__throw_runtime_error("locale constructed with null" ), (__imp*)0)) |
540 | { |
541 | __locale_->__add_shared(); |
542 | } |
543 | |
544 | locale::locale(const string& name) |
545 | : __locale_(new __imp(name)) |
546 | { |
547 | __locale_->__add_shared(); |
548 | } |
549 | |
550 | locale::locale(const locale& other, const char* name, category c) |
551 | : __locale_(name ? new __imp(*other.__locale_, name, c) |
552 | : (__throw_runtime_error("locale constructed with null" ), (__imp*)0)) |
553 | { |
554 | __locale_->__add_shared(); |
555 | } |
556 | |
557 | locale::locale(const locale& other, const string& name, category c) |
558 | : __locale_(new __imp(*other.__locale_, name, c)) |
559 | { |
560 | __locale_->__add_shared(); |
561 | } |
562 | |
563 | locale::locale(const locale& other, const locale& one, category c) |
564 | : __locale_(new __imp(*other.__locale_, *one.__locale_, c)) |
565 | { |
566 | __locale_->__add_shared(); |
567 | } |
568 | |
569 | string |
570 | locale::name() const |
571 | { |
572 | return __locale_->name(); |
573 | } |
574 | |
575 | void |
576 | locale::__install_ctor(const locale& other, facet* f, long id) |
577 | { |
578 | if (f) |
579 | __locale_ = new __imp(*other.__locale_, f, id); |
580 | else |
581 | __locale_ = other.__locale_; |
582 | __locale_->__add_shared(); |
583 | } |
584 | |
585 | locale |
586 | locale::global(const locale& loc) |
587 | { |
588 | locale& g = __global(); |
589 | locale r = g; |
590 | g = loc; |
591 | if (g.name() != "*" ) |
592 | setlocale(LC_ALL, g.name().c_str()); |
593 | return r; |
594 | } |
595 | |
596 | bool |
597 | locale::has_facet(id& x) const |
598 | { |
599 | return __locale_->has_facet(x.__get()); |
600 | } |
601 | |
602 | const locale::facet* |
603 | locale::use_facet(id& x) const |
604 | { |
605 | return __locale_->use_facet(x.__get()); |
606 | } |
607 | |
608 | bool |
609 | locale::operator==(const locale& y) const |
610 | { |
611 | return (__locale_ == y.__locale_) |
612 | || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name()); |
613 | } |
614 | |
615 | // locale::facet |
616 | |
617 | locale::facet::~facet() |
618 | { |
619 | } |
620 | |
621 | void |
622 | locale::facet::__on_zero_shared() _NOEXCEPT |
623 | { |
624 | delete this; |
625 | } |
626 | |
627 | // locale::id |
628 | |
629 | int32_t locale::id::__next_id = 0; |
630 | |
631 | namespace |
632 | { |
633 | |
634 | class __fake_bind |
635 | { |
636 | locale::id* id_; |
637 | void (locale::id::* pmf_)(); |
638 | public: |
639 | __fake_bind(void (locale::id::* pmf)(), locale::id* id) |
640 | : id_(id), pmf_(pmf) {} |
641 | |
642 | void operator()() const |
643 | { |
644 | (id_->*pmf_)(); |
645 | } |
646 | }; |
647 | |
648 | } |
649 | |
650 | long |
651 | locale::id::__get() |
652 | { |
653 | call_once(__flag_, __fake_bind(&locale::id::__init, this)); |
654 | return __id_ - 1; |
655 | } |
656 | |
657 | void |
658 | locale::id::__init() |
659 | { |
660 | __id_ = __libcpp_atomic_add(&__next_id, 1); |
661 | } |
662 | |
663 | // template <> class collate_byname<char> |
664 | |
665 | collate_byname<char>::collate_byname(const char* n, size_t refs) |
666 | : collate<char>(refs), |
667 | __l(newlocale(LC_ALL_MASK, n, 0)) |
668 | { |
669 | if (__l == 0) |
670 | __throw_runtime_error("collate_byname<char>::collate_byname" |
671 | " failed to construct for " + string(n)); |
672 | } |
673 | |
674 | collate_byname<char>::collate_byname(const string& name, size_t refs) |
675 | : collate<char>(refs), |
676 | __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) |
677 | { |
678 | if (__l == 0) |
679 | __throw_runtime_error("collate_byname<char>::collate_byname" |
680 | " failed to construct for " + name); |
681 | } |
682 | |
683 | collate_byname<char>::~collate_byname() |
684 | { |
685 | freelocale(__l); |
686 | } |
687 | |
688 | int |
689 | collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1, |
690 | const char_type* __lo2, const char_type* __hi2) const |
691 | { |
692 | string_type lhs(__lo1, __hi1); |
693 | string_type rhs(__lo2, __hi2); |
694 | int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l); |
695 | if (r < 0) |
696 | return -1; |
697 | if (r > 0) |
698 | return 1; |
699 | return r; |
700 | } |
701 | |
702 | collate_byname<char>::string_type |
703 | collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const |
704 | { |
705 | const string_type in(lo, hi); |
706 | string_type out(strxfrm_l(0, in.c_str(), 0, __l), char()); |
707 | strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l); |
708 | return out; |
709 | } |
710 | |
711 | // template <> class collate_byname<wchar_t> |
712 | |
713 | collate_byname<wchar_t>::collate_byname(const char* n, size_t refs) |
714 | : collate<wchar_t>(refs), |
715 | __l(newlocale(LC_ALL_MASK, n, 0)) |
716 | { |
717 | if (__l == 0) |
718 | __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" |
719 | " failed to construct for " + string(n)); |
720 | } |
721 | |
722 | collate_byname<wchar_t>::collate_byname(const string& name, size_t refs) |
723 | : collate<wchar_t>(refs), |
724 | __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) |
725 | { |
726 | if (__l == 0) |
727 | __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" |
728 | " failed to construct for " + name); |
729 | } |
730 | |
731 | collate_byname<wchar_t>::~collate_byname() |
732 | { |
733 | freelocale(__l); |
734 | } |
735 | |
736 | int |
737 | collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1, |
738 | const char_type* __lo2, const char_type* __hi2) const |
739 | { |
740 | string_type lhs(__lo1, __hi1); |
741 | string_type rhs(__lo2, __hi2); |
742 | int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l); |
743 | if (r < 0) |
744 | return -1; |
745 | if (r > 0) |
746 | return 1; |
747 | return r; |
748 | } |
749 | |
750 | collate_byname<wchar_t>::string_type |
751 | collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const |
752 | { |
753 | const string_type in(lo, hi); |
754 | string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t()); |
755 | wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l); |
756 | return out; |
757 | } |
758 | |
759 | // template <> class ctype<wchar_t>; |
760 | |
761 | const ctype_base::mask ctype_base::space; |
762 | const ctype_base::mask ctype_base::print; |
763 | const ctype_base::mask ctype_base::cntrl; |
764 | const ctype_base::mask ctype_base::upper; |
765 | const ctype_base::mask ctype_base::lower; |
766 | const ctype_base::mask ctype_base::alpha; |
767 | const ctype_base::mask ctype_base::digit; |
768 | const ctype_base::mask ctype_base::punct; |
769 | const ctype_base::mask ctype_base::xdigit; |
770 | const ctype_base::mask ctype_base::blank; |
771 | const ctype_base::mask ctype_base::alnum; |
772 | const ctype_base::mask ctype_base::graph; |
773 | |
774 | locale::id ctype<wchar_t>::id; |
775 | |
776 | ctype<wchar_t>::~ctype() |
777 | { |
778 | } |
779 | |
780 | bool |
781 | ctype<wchar_t>::do_is(mask m, char_type c) const |
782 | { |
783 | return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false; |
784 | } |
785 | |
786 | const wchar_t* |
787 | ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const |
788 | { |
789 | for (; low != high; ++low, ++vec) |
790 | *vec = static_cast<mask>(isascii(*low) ? |
791 | ctype<char>::classic_table()[*low] : 0); |
792 | return low; |
793 | } |
794 | |
795 | const wchar_t* |
796 | ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const |
797 | { |
798 | for (; low != high; ++low) |
799 | if (isascii(*low) && (ctype<char>::classic_table()[*low] & m)) |
800 | break; |
801 | return low; |
802 | } |
803 | |
804 | const wchar_t* |
805 | ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const |
806 | { |
807 | for (; low != high; ++low) |
808 | if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m))) |
809 | break; |
810 | return low; |
811 | } |
812 | |
813 | wchar_t |
814 | ctype<wchar_t>::do_toupper(char_type c) const |
815 | { |
816 | #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE |
817 | return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; |
818 | #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ |
819 | defined(__NetBSD__) |
820 | return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c; |
821 | #else |
822 | return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c; |
823 | #endif |
824 | } |
825 | |
826 | const wchar_t* |
827 | ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const |
828 | { |
829 | for (; low != high; ++low) |
830 | #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE |
831 | *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low; |
832 | #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ |
833 | defined(__NetBSD__) |
834 | *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] |
835 | : *low; |
836 | #else |
837 | *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low; |
838 | #endif |
839 | return low; |
840 | } |
841 | |
842 | wchar_t |
843 | ctype<wchar_t>::do_tolower(char_type c) const |
844 | { |
845 | #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE |
846 | return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; |
847 | #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ |
848 | defined(__NetBSD__) |
849 | return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c; |
850 | #else |
851 | return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c; |
852 | #endif |
853 | } |
854 | |
855 | const wchar_t* |
856 | ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const |
857 | { |
858 | for (; low != high; ++low) |
859 | #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE |
860 | *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low; |
861 | #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ |
862 | defined(__NetBSD__) |
863 | *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] |
864 | : *low; |
865 | #else |
866 | *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low; |
867 | #endif |
868 | return low; |
869 | } |
870 | |
871 | wchar_t |
872 | ctype<wchar_t>::do_widen(char c) const |
873 | { |
874 | return c; |
875 | } |
876 | |
877 | const char* |
878 | ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const |
879 | { |
880 | for (; low != high; ++low, ++dest) |
881 | *dest = *low; |
882 | return low; |
883 | } |
884 | |
885 | char |
886 | ctype<wchar_t>::do_narrow(char_type c, char dfault) const |
887 | { |
888 | if (isascii(c)) |
889 | return static_cast<char>(c); |
890 | return dfault; |
891 | } |
892 | |
893 | const wchar_t* |
894 | ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const |
895 | { |
896 | for (; low != high; ++low, ++dest) |
897 | if (isascii(*low)) |
898 | *dest = static_cast<char>(*low); |
899 | else |
900 | *dest = dfault; |
901 | return low; |
902 | } |
903 | |
904 | // template <> class ctype<char>; |
905 | |
906 | locale::id ctype<char>::id; |
907 | |
908 | ctype<char>::ctype(const mask* tab, bool del, size_t refs) |
909 | : locale::facet(refs), |
910 | __tab_(tab), |
911 | __del_(del) |
912 | { |
913 | if (__tab_ == 0) |
914 | __tab_ = classic_table(); |
915 | } |
916 | |
917 | ctype<char>::~ctype() |
918 | { |
919 | if (__tab_ && __del_) |
920 | delete [] __tab_; |
921 | } |
922 | |
923 | char |
924 | ctype<char>::do_toupper(char_type c) const |
925 | { |
926 | #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE |
927 | return isascii(c) ? |
928 | static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c; |
929 | #elif defined(__NetBSD__) |
930 | return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]); |
931 | #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) |
932 | return isascii(c) ? |
933 | static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c; |
934 | #else |
935 | return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c; |
936 | #endif |
937 | } |
938 | |
939 | const char* |
940 | ctype<char>::do_toupper(char_type* low, const char_type* high) const |
941 | { |
942 | for (; low != high; ++low) |
943 | #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE |
944 | *low = isascii(*low) ? |
945 | static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low; |
946 | #elif defined(__NetBSD__) |
947 | *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]); |
948 | #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) |
949 | *low = isascii(*low) ? |
950 | static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low; |
951 | #else |
952 | *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low; |
953 | #endif |
954 | return low; |
955 | } |
956 | |
957 | char |
958 | ctype<char>::do_tolower(char_type c) const |
959 | { |
960 | #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE |
961 | return isascii(c) ? |
962 | static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c; |
963 | #elif defined(__NetBSD__) |
964 | return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]); |
965 | #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) |
966 | return isascii(c) ? |
967 | static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c; |
968 | #else |
969 | return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c; |
970 | #endif |
971 | } |
972 | |
973 | const char* |
974 | ctype<char>::do_tolower(char_type* low, const char_type* high) const |
975 | { |
976 | for (; low != high; ++low) |
977 | #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE |
978 | *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low; |
979 | #elif defined(__NetBSD__) |
980 | *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]); |
981 | #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) |
982 | *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low; |
983 | #else |
984 | *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low; |
985 | #endif |
986 | return low; |
987 | } |
988 | |
989 | char |
990 | ctype<char>::do_widen(char c) const |
991 | { |
992 | return c; |
993 | } |
994 | |
995 | const char* |
996 | ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const |
997 | { |
998 | for (; low != high; ++low, ++dest) |
999 | *dest = *low; |
1000 | return low; |
1001 | } |
1002 | |
1003 | char |
1004 | ctype<char>::do_narrow(char_type c, char dfault) const |
1005 | { |
1006 | if (isascii(c)) |
1007 | return static_cast<char>(c); |
1008 | return dfault; |
1009 | } |
1010 | |
1011 | const char* |
1012 | ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const |
1013 | { |
1014 | for (; low != high; ++low, ++dest) |
1015 | if (isascii(*low)) |
1016 | *dest = *low; |
1017 | else |
1018 | *dest = dfault; |
1019 | return low; |
1020 | } |
1021 | |
1022 | #if defined(__EMSCRIPTEN__) |
1023 | extern "C" const unsigned short ** __ctype_b_loc(); |
1024 | extern "C" const int ** __ctype_tolower_loc(); |
1025 | extern "C" const int ** __ctype_toupper_loc(); |
1026 | #endif |
1027 | |
1028 | #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE |
1029 | const ctype<char>::mask* |
1030 | ctype<char>::classic_table() _NOEXCEPT |
1031 | { |
1032 | static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = { |
1033 | cntrl, cntrl, |
1034 | cntrl, cntrl, |
1035 | cntrl, cntrl, |
1036 | cntrl, cntrl, |
1037 | cntrl, cntrl | space | blank, |
1038 | cntrl | space, cntrl | space, |
1039 | cntrl | space, cntrl | space, |
1040 | cntrl, cntrl, |
1041 | cntrl, cntrl, |
1042 | cntrl, cntrl, |
1043 | cntrl, cntrl, |
1044 | cntrl, cntrl, |
1045 | cntrl, cntrl, |
1046 | cntrl, cntrl, |
1047 | cntrl, cntrl, |
1048 | cntrl, cntrl, |
1049 | space | blank | print, punct | print, |
1050 | punct | print, punct | print, |
1051 | punct | print, punct | print, |
1052 | punct | print, punct | print, |
1053 | punct | print, punct | print, |
1054 | punct | print, punct | print, |
1055 | punct | print, punct | print, |
1056 | punct | print, punct | print, |
1057 | digit | print | xdigit, digit | print | xdigit, |
1058 | digit | print | xdigit, digit | print | xdigit, |
1059 | digit | print | xdigit, digit | print | xdigit, |
1060 | digit | print | xdigit, digit | print | xdigit, |
1061 | digit | print | xdigit, digit | print | xdigit, |
1062 | punct | print, punct | print, |
1063 | punct | print, punct | print, |
1064 | punct | print, punct | print, |
1065 | punct | print, upper | xdigit | print | alpha, |
1066 | upper | xdigit | print | alpha, upper | xdigit | print | alpha, |
1067 | upper | xdigit | print | alpha, upper | xdigit | print | alpha, |
1068 | upper | xdigit | print | alpha, upper | print | alpha, |
1069 | upper | print | alpha, upper | print | alpha, |
1070 | upper | print | alpha, upper | print | alpha, |
1071 | upper | print | alpha, upper | print | alpha, |
1072 | upper | print | alpha, upper | print | alpha, |
1073 | upper | print | alpha, upper | print | alpha, |
1074 | upper | print | alpha, upper | print | alpha, |
1075 | upper | print | alpha, upper | print | alpha, |
1076 | upper | print | alpha, upper | print | alpha, |
1077 | upper | print | alpha, upper | print | alpha, |
1078 | upper | print | alpha, punct | print, |
1079 | punct | print, punct | print, |
1080 | punct | print, punct | print, |
1081 | punct | print, lower | xdigit | print | alpha, |
1082 | lower | xdigit | print | alpha, lower | xdigit | print | alpha, |
1083 | lower | xdigit | print | alpha, lower | xdigit | print | alpha, |
1084 | lower | xdigit | print | alpha, lower | print | alpha, |
1085 | lower | print | alpha, lower | print | alpha, |
1086 | lower | print | alpha, lower | print | alpha, |
1087 | lower | print | alpha, lower | print | alpha, |
1088 | lower | print | alpha, lower | print | alpha, |
1089 | lower | print | alpha, lower | print | alpha, |
1090 | lower | print | alpha, lower | print | alpha, |
1091 | lower | print | alpha, lower | print | alpha, |
1092 | lower | print | alpha, lower | print | alpha, |
1093 | lower | print | alpha, lower | print | alpha, |
1094 | lower | print | alpha, punct | print, |
1095 | punct | print, punct | print, |
1096 | punct | print, cntrl, |
1097 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
1098 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
1099 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
1100 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
1101 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
1102 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
1103 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
1104 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
1105 | }; |
1106 | return builtin_table; |
1107 | } |
1108 | #else |
1109 | const ctype<char>::mask* |
1110 | ctype<char>::classic_table() _NOEXCEPT |
1111 | { |
1112 | #if defined(__APPLE__) || defined(__FreeBSD__) |
1113 | return _DefaultRuneLocale.__runetype; |
1114 | #elif defined(__NetBSD__) |
1115 | return _C_ctype_tab_ + 1; |
1116 | #elif defined(__GLIBC__) |
1117 | return _LIBCPP_GET_C_LOCALE->__ctype_b; |
1118 | #elif __sun__ |
1119 | return __ctype_mask; |
1120 | #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
1121 | return __pctype_func(); |
1122 | #elif defined(__EMSCRIPTEN__) |
1123 | return *__ctype_b_loc(); |
1124 | #elif defined(_NEWLIB_VERSION) |
1125 | // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1]. |
1126 | return _ctype_ + 1; |
1127 | #elif defined(_AIX) |
1128 | return (const unsigned int *)__lc_ctype_ptr->obj->mask; |
1129 | #else |
1130 | // Platform not supported: abort so the person doing the port knows what to |
1131 | // fix |
1132 | # warning ctype<char>::classic_table() is not implemented |
1133 | printf("ctype<char>::classic_table() is not implemented\n" ); |
1134 | abort(); |
1135 | return NULL; |
1136 | #endif |
1137 | } |
1138 | #endif |
1139 | |
1140 | #if defined(__GLIBC__) |
1141 | const int* |
1142 | ctype<char>::__classic_lower_table() _NOEXCEPT |
1143 | { |
1144 | return _LIBCPP_GET_C_LOCALE->__ctype_tolower; |
1145 | } |
1146 | |
1147 | const int* |
1148 | ctype<char>::__classic_upper_table() _NOEXCEPT |
1149 | { |
1150 | return _LIBCPP_GET_C_LOCALE->__ctype_toupper; |
1151 | } |
1152 | #elif __NetBSD__ |
1153 | const short* |
1154 | ctype<char>::__classic_lower_table() _NOEXCEPT |
1155 | { |
1156 | return _C_tolower_tab_ + 1; |
1157 | } |
1158 | |
1159 | const short* |
1160 | ctype<char>::__classic_upper_table() _NOEXCEPT |
1161 | { |
1162 | return _C_toupper_tab_ + 1; |
1163 | } |
1164 | |
1165 | #elif defined(__EMSCRIPTEN__) |
1166 | const int* |
1167 | ctype<char>::__classic_lower_table() _NOEXCEPT |
1168 | { |
1169 | return *__ctype_tolower_loc(); |
1170 | } |
1171 | |
1172 | const int* |
1173 | ctype<char>::__classic_upper_table() _NOEXCEPT |
1174 | { |
1175 | return *__ctype_toupper_loc(); |
1176 | } |
1177 | #endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ |
1178 | |
1179 | // template <> class ctype_byname<char> |
1180 | |
1181 | ctype_byname<char>::ctype_byname(const char* name, size_t refs) |
1182 | : ctype<char>(0, false, refs), |
1183 | __l(newlocale(LC_ALL_MASK, name, 0)) |
1184 | { |
1185 | if (__l == 0) |
1186 | __throw_runtime_error("ctype_byname<char>::ctype_byname" |
1187 | " failed to construct for " + string(name)); |
1188 | } |
1189 | |
1190 | ctype_byname<char>::ctype_byname(const string& name, size_t refs) |
1191 | : ctype<char>(0, false, refs), |
1192 | __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) |
1193 | { |
1194 | if (__l == 0) |
1195 | __throw_runtime_error("ctype_byname<char>::ctype_byname" |
1196 | " failed to construct for " + name); |
1197 | } |
1198 | |
1199 | ctype_byname<char>::~ctype_byname() |
1200 | { |
1201 | freelocale(__l); |
1202 | } |
1203 | |
1204 | char |
1205 | ctype_byname<char>::do_toupper(char_type c) const |
1206 | { |
1207 | return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l)); |
1208 | } |
1209 | |
1210 | const char* |
1211 | ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const |
1212 | { |
1213 | for (; low != high; ++low) |
1214 | *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l)); |
1215 | return low; |
1216 | } |
1217 | |
1218 | char |
1219 | ctype_byname<char>::do_tolower(char_type c) const |
1220 | { |
1221 | return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l)); |
1222 | } |
1223 | |
1224 | const char* |
1225 | ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const |
1226 | { |
1227 | for (; low != high; ++low) |
1228 | *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l)); |
1229 | return low; |
1230 | } |
1231 | |
1232 | // template <> class ctype_byname<wchar_t> |
1233 | |
1234 | ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs) |
1235 | : ctype<wchar_t>(refs), |
1236 | __l(newlocale(LC_ALL_MASK, name, 0)) |
1237 | { |
1238 | if (__l == 0) |
1239 | __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname" |
1240 | " failed to construct for " + string(name)); |
1241 | } |
1242 | |
1243 | ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs) |
1244 | : ctype<wchar_t>(refs), |
1245 | __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) |
1246 | { |
1247 | if (__l == 0) |
1248 | __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname" |
1249 | " failed to construct for " + name); |
1250 | } |
1251 | |
1252 | ctype_byname<wchar_t>::~ctype_byname() |
1253 | { |
1254 | freelocale(__l); |
1255 | } |
1256 | |
1257 | bool |
1258 | ctype_byname<wchar_t>::do_is(mask m, char_type c) const |
1259 | { |
1260 | #ifdef _LIBCPP_WCTYPE_IS_MASK |
1261 | return static_cast<bool>(iswctype_l(c, m, __l)); |
1262 | #else |
1263 | bool result = false; |
1264 | wint_t ch = static_cast<wint_t>(c); |
1265 | if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0); |
1266 | if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0); |
1267 | if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0); |
1268 | if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0); |
1269 | if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0); |
1270 | if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0); |
1271 | if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0); |
1272 | if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0); |
1273 | if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0); |
1274 | if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0); |
1275 | return result; |
1276 | #endif |
1277 | } |
1278 | |
1279 | const wchar_t* |
1280 | ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const |
1281 | { |
1282 | for (; low != high; ++low, ++vec) |
1283 | { |
1284 | if (isascii(*low)) |
1285 | *vec = static_cast<mask>(ctype<char>::classic_table()[*low]); |
1286 | else |
1287 | { |
1288 | *vec = 0; |
1289 | wint_t ch = static_cast<wint_t>(*low); |
1290 | if (iswspace_l(ch, __l)) |
1291 | *vec |= space; |
1292 | #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT |
1293 | if (iswprint_l(ch, __l)) |
1294 | *vec |= print; |
1295 | #endif |
1296 | if (iswcntrl_l(ch, __l)) |
1297 | *vec |= cntrl; |
1298 | if (iswupper_l(ch, __l)) |
1299 | *vec |= upper; |
1300 | if (iswlower_l(ch, __l)) |
1301 | *vec |= lower; |
1302 | #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA |
1303 | if (iswalpha_l(ch, __l)) |
1304 | *vec |= alpha; |
1305 | #endif |
1306 | if (iswdigit_l(ch, __l)) |
1307 | *vec |= digit; |
1308 | if (iswpunct_l(ch, __l)) |
1309 | *vec |= punct; |
1310 | #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT |
1311 | if (iswxdigit_l(ch, __l)) |
1312 | *vec |= xdigit; |
1313 | #endif |
1314 | #if !defined(__sun__) |
1315 | if (iswblank_l(ch, __l)) |
1316 | *vec |= blank; |
1317 | #endif |
1318 | } |
1319 | } |
1320 | return low; |
1321 | } |
1322 | |
1323 | const wchar_t* |
1324 | ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const |
1325 | { |
1326 | for (; low != high; ++low) |
1327 | { |
1328 | #ifdef _LIBCPP_WCTYPE_IS_MASK |
1329 | if (iswctype_l(*low, m, __l)) |
1330 | break; |
1331 | #else |
1332 | wint_t ch = static_cast<wint_t>(*low); |
1333 | if ((m & space) == space && iswspace_l(ch, __l)) break; |
1334 | if ((m & print) == print && iswprint_l(ch, __l)) break; |
1335 | if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break; |
1336 | if ((m & upper) == upper && iswupper_l(ch, __l)) break; |
1337 | if ((m & lower) == lower && iswlower_l(ch, __l)) break; |
1338 | if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break; |
1339 | if ((m & digit) == digit && iswdigit_l(ch, __l)) break; |
1340 | if ((m & punct) == punct && iswpunct_l(ch, __l)) break; |
1341 | if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break; |
1342 | if ((m & blank) == blank && iswblank_l(ch, __l)) break; |
1343 | #endif |
1344 | } |
1345 | return low; |
1346 | } |
1347 | |
1348 | const wchar_t* |
1349 | ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const |
1350 | { |
1351 | for (; low != high; ++low) |
1352 | { |
1353 | #ifdef _LIBCPP_WCTYPE_IS_MASK |
1354 | if (!iswctype_l(*low, m, __l)) |
1355 | break; |
1356 | #else |
1357 | wint_t ch = static_cast<wint_t>(*low); |
1358 | if ((m & space) == space && iswspace_l(ch, __l)) continue; |
1359 | if ((m & print) == print && iswprint_l(ch, __l)) continue; |
1360 | if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue; |
1361 | if ((m & upper) == upper && iswupper_l(ch, __l)) continue; |
1362 | if ((m & lower) == lower && iswlower_l(ch, __l)) continue; |
1363 | if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue; |
1364 | if ((m & digit) == digit && iswdigit_l(ch, __l)) continue; |
1365 | if ((m & punct) == punct && iswpunct_l(ch, __l)) continue; |
1366 | if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue; |
1367 | if ((m & blank) == blank && iswblank_l(ch, __l)) continue; |
1368 | break; |
1369 | #endif |
1370 | } |
1371 | return low; |
1372 | } |
1373 | |
1374 | wchar_t |
1375 | ctype_byname<wchar_t>::do_toupper(char_type c) const |
1376 | { |
1377 | return towupper_l(c, __l); |
1378 | } |
1379 | |
1380 | const wchar_t* |
1381 | ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const |
1382 | { |
1383 | for (; low != high; ++low) |
1384 | *low = towupper_l(*low, __l); |
1385 | return low; |
1386 | } |
1387 | |
1388 | wchar_t |
1389 | ctype_byname<wchar_t>::do_tolower(char_type c) const |
1390 | { |
1391 | return towlower_l(c, __l); |
1392 | } |
1393 | |
1394 | const wchar_t* |
1395 | ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const |
1396 | { |
1397 | for (; low != high; ++low) |
1398 | *low = towlower_l(*low, __l); |
1399 | return low; |
1400 | } |
1401 | |
1402 | wchar_t |
1403 | ctype_byname<wchar_t>::do_widen(char c) const |
1404 | { |
1405 | return __libcpp_btowc_l(c, __l); |
1406 | } |
1407 | |
1408 | const char* |
1409 | ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const |
1410 | { |
1411 | for (; low != high; ++low, ++dest) |
1412 | *dest = __libcpp_btowc_l(*low, __l); |
1413 | return low; |
1414 | } |
1415 | |
1416 | char |
1417 | ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const |
1418 | { |
1419 | int r = __libcpp_wctob_l(c, __l); |
1420 | return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; |
1421 | } |
1422 | |
1423 | const wchar_t* |
1424 | ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const |
1425 | { |
1426 | for (; low != high; ++low, ++dest) |
1427 | { |
1428 | int r = __libcpp_wctob_l(*low, __l); |
1429 | *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; |
1430 | } |
1431 | return low; |
1432 | } |
1433 | |
1434 | // template <> class codecvt<char, char, mbstate_t> |
1435 | |
1436 | locale::id codecvt<char, char, mbstate_t>::id; |
1437 | |
1438 | codecvt<char, char, mbstate_t>::~codecvt() |
1439 | { |
1440 | } |
1441 | |
1442 | codecvt<char, char, mbstate_t>::result |
1443 | codecvt<char, char, mbstate_t>::do_out(state_type&, |
1444 | const intern_type* frm, const intern_type*, const intern_type*& frm_nxt, |
1445 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
1446 | { |
1447 | frm_nxt = frm; |
1448 | to_nxt = to; |
1449 | return noconv; |
1450 | } |
1451 | |
1452 | codecvt<char, char, mbstate_t>::result |
1453 | codecvt<char, char, mbstate_t>::do_in(state_type&, |
1454 | const extern_type* frm, const extern_type*, const extern_type*& frm_nxt, |
1455 | intern_type* to, intern_type*, intern_type*& to_nxt) const |
1456 | { |
1457 | frm_nxt = frm; |
1458 | to_nxt = to; |
1459 | return noconv; |
1460 | } |
1461 | |
1462 | codecvt<char, char, mbstate_t>::result |
1463 | codecvt<char, char, mbstate_t>::do_unshift(state_type&, |
1464 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
1465 | { |
1466 | to_nxt = to; |
1467 | return noconv; |
1468 | } |
1469 | |
1470 | int |
1471 | codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT |
1472 | { |
1473 | return 1; |
1474 | } |
1475 | |
1476 | bool |
1477 | codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT |
1478 | { |
1479 | return true; |
1480 | } |
1481 | |
1482 | int |
1483 | codecvt<char, char, mbstate_t>::do_length(state_type&, |
1484 | const extern_type* frm, const extern_type* end, size_t mx) const |
1485 | { |
1486 | return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm))); |
1487 | } |
1488 | |
1489 | int |
1490 | codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT |
1491 | { |
1492 | return 1; |
1493 | } |
1494 | |
1495 | // template <> class codecvt<wchar_t, char, mbstate_t> |
1496 | |
1497 | locale::id codecvt<wchar_t, char, mbstate_t>::id; |
1498 | |
1499 | codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) |
1500 | : locale::facet(refs), |
1501 | __l(_LIBCPP_GET_C_LOCALE) |
1502 | { |
1503 | } |
1504 | |
1505 | codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs) |
1506 | : locale::facet(refs), |
1507 | __l(newlocale(LC_ALL_MASK, nm, 0)) |
1508 | { |
1509 | if (__l == 0) |
1510 | __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname" |
1511 | " failed to construct for " + string(nm)); |
1512 | } |
1513 | |
1514 | codecvt<wchar_t, char, mbstate_t>::~codecvt() |
1515 | { |
1516 | if (__l != _LIBCPP_GET_C_LOCALE) |
1517 | freelocale(__l); |
1518 | } |
1519 | |
1520 | codecvt<wchar_t, char, mbstate_t>::result |
1521 | codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st, |
1522 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
1523 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
1524 | { |
1525 | // look for first internal null in frm |
1526 | const intern_type* fend = frm; |
1527 | for (; fend != frm_end; ++fend) |
1528 | if (*fend == 0) |
1529 | break; |
1530 | // loop over all null-terminated sequences in frm |
1531 | to_nxt = to; |
1532 | for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) |
1533 | { |
1534 | // save state in case it is needed to recover to_nxt on error |
1535 | mbstate_t save_state = st; |
1536 | size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), |
1537 | static_cast<size_t>(to_end-to), &st, __l); |
1538 | if (n == size_t(-1)) |
1539 | { |
1540 | // need to recover to_nxt |
1541 | for (to_nxt = to; frm != frm_nxt; ++frm) |
1542 | { |
1543 | n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l); |
1544 | if (n == size_t(-1)) |
1545 | break; |
1546 | to_nxt += n; |
1547 | } |
1548 | frm_nxt = frm; |
1549 | return error; |
1550 | } |
1551 | if (n == 0) |
1552 | return partial; |
1553 | to_nxt += n; |
1554 | if (to_nxt == to_end) |
1555 | break; |
1556 | if (fend != frm_end) // set up next null terminated sequence |
1557 | { |
1558 | // Try to write the terminating null |
1559 | extern_type tmp[MB_LEN_MAX]; |
1560 | n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); |
1561 | if (n == size_t(-1)) // on error |
1562 | return error; |
1563 | if (n > static_cast<size_t>(to_end-to_nxt)) // is there room? |
1564 | return partial; |
1565 | for (extern_type* p = tmp; n; --n) // write it |
1566 | *to_nxt++ = *p++; |
1567 | ++frm_nxt; |
1568 | // look for next null in frm |
1569 | for (fend = frm_nxt; fend != frm_end; ++fend) |
1570 | if (*fend == 0) |
1571 | break; |
1572 | } |
1573 | } |
1574 | return frm_nxt == frm_end ? ok : partial; |
1575 | } |
1576 | |
1577 | codecvt<wchar_t, char, mbstate_t>::result |
1578 | codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st, |
1579 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
1580 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
1581 | { |
1582 | // look for first internal null in frm |
1583 | const extern_type* fend = frm; |
1584 | for (; fend != frm_end; ++fend) |
1585 | if (*fend == 0) |
1586 | break; |
1587 | // loop over all null-terminated sequences in frm |
1588 | to_nxt = to; |
1589 | for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) |
1590 | { |
1591 | // save state in case it is needed to recover to_nxt on error |
1592 | mbstate_t save_state = st; |
1593 | size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), |
1594 | static_cast<size_t>(to_end-to), &st, __l); |
1595 | if (n == size_t(-1)) |
1596 | { |
1597 | // need to recover to_nxt |
1598 | for (to_nxt = to; frm != frm_nxt; ++to_nxt) |
1599 | { |
1600 | n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm), |
1601 | &save_state, __l); |
1602 | switch (n) |
1603 | { |
1604 | case 0: |
1605 | ++frm; |
1606 | break; |
1607 | case size_t(-1): |
1608 | frm_nxt = frm; |
1609 | return error; |
1610 | case size_t(-2): |
1611 | frm_nxt = frm; |
1612 | return partial; |
1613 | default: |
1614 | frm += n; |
1615 | break; |
1616 | } |
1617 | } |
1618 | frm_nxt = frm; |
1619 | return frm_nxt == frm_end ? ok : partial; |
1620 | } |
1621 | if (n == size_t(-1)) |
1622 | return error; |
1623 | to_nxt += n; |
1624 | if (to_nxt == to_end) |
1625 | break; |
1626 | if (fend != frm_end) // set up next null terminated sequence |
1627 | { |
1628 | // Try to write the terminating null |
1629 | n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l); |
1630 | if (n != 0) // on error |
1631 | return error; |
1632 | ++to_nxt; |
1633 | ++frm_nxt; |
1634 | // look for next null in frm |
1635 | for (fend = frm_nxt; fend != frm_end; ++fend) |
1636 | if (*fend == 0) |
1637 | break; |
1638 | } |
1639 | } |
1640 | return frm_nxt == frm_end ? ok : partial; |
1641 | } |
1642 | |
1643 | codecvt<wchar_t, char, mbstate_t>::result |
1644 | codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st, |
1645 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
1646 | { |
1647 | to_nxt = to; |
1648 | extern_type tmp[MB_LEN_MAX]; |
1649 | size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); |
1650 | if (n == size_t(-1) || n == 0) // on error |
1651 | return error; |
1652 | --n; |
1653 | if (n > static_cast<size_t>(to_end-to_nxt)) // is there room? |
1654 | return partial; |
1655 | for (extern_type* p = tmp; n; --n) // write it |
1656 | *to_nxt++ = *p++; |
1657 | return ok; |
1658 | } |
1659 | |
1660 | int |
1661 | codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT |
1662 | { |
1663 | if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0) |
1664 | return -1; |
1665 | |
1666 | // stateless encoding |
1667 | if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings |
1668 | return 1; // which take more than 1 char to form a wchar_t |
1669 | return 0; |
1670 | } |
1671 | |
1672 | bool |
1673 | codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT |
1674 | { |
1675 | return false; |
1676 | } |
1677 | |
1678 | int |
1679 | codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, |
1680 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
1681 | { |
1682 | int nbytes = 0; |
1683 | for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t) |
1684 | { |
1685 | size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l); |
1686 | switch (n) |
1687 | { |
1688 | case 0: |
1689 | ++nbytes; |
1690 | ++frm; |
1691 | break; |
1692 | case size_t(-1): |
1693 | case size_t(-2): |
1694 | return nbytes; |
1695 | default: |
1696 | nbytes += n; |
1697 | frm += n; |
1698 | break; |
1699 | } |
1700 | } |
1701 | return nbytes; |
1702 | } |
1703 | |
1704 | int |
1705 | codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT |
1706 | { |
1707 | return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l)); |
1708 | } |
1709 | |
1710 | // Valid UTF ranges |
1711 | // UTF-32 UTF-16 UTF-8 # of code points |
1712 | // first second first second third fourth |
1713 | // 000000 - 00007F 0000 - 007F 00 - 7F 127 |
1714 | // 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920 |
1715 | // 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048 |
1716 | // 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152 |
1717 | // 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048 |
1718 | // 00D800 - 00DFFF invalid |
1719 | // 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192 |
1720 | // 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608 |
1721 | // 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432 |
1722 | // 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536 |
1723 | |
1724 | static |
1725 | codecvt_base::result |
1726 | utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, |
1727 | uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, |
1728 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
1729 | { |
1730 | frm_nxt = frm; |
1731 | to_nxt = to; |
1732 | if (mode & generate_header) |
1733 | { |
1734 | if (to_end-to_nxt < 3) |
1735 | return codecvt_base::partial; |
1736 | *to_nxt++ = static_cast<uint8_t>(0xEF); |
1737 | *to_nxt++ = static_cast<uint8_t>(0xBB); |
1738 | *to_nxt++ = static_cast<uint8_t>(0xBF); |
1739 | } |
1740 | for (; frm_nxt < frm_end; ++frm_nxt) |
1741 | { |
1742 | uint16_t wc1 = *frm_nxt; |
1743 | if (wc1 > Maxcode) |
1744 | return codecvt_base::error; |
1745 | if (wc1 < 0x0080) |
1746 | { |
1747 | if (to_end-to_nxt < 1) |
1748 | return codecvt_base::partial; |
1749 | *to_nxt++ = static_cast<uint8_t>(wc1); |
1750 | } |
1751 | else if (wc1 < 0x0800) |
1752 | { |
1753 | if (to_end-to_nxt < 2) |
1754 | return codecvt_base::partial; |
1755 | *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); |
1756 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); |
1757 | } |
1758 | else if (wc1 < 0xD800) |
1759 | { |
1760 | if (to_end-to_nxt < 3) |
1761 | return codecvt_base::partial; |
1762 | *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); |
1763 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); |
1764 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); |
1765 | } |
1766 | else if (wc1 < 0xDC00) |
1767 | { |
1768 | if (frm_end-frm_nxt < 2) |
1769 | return codecvt_base::partial; |
1770 | uint16_t wc2 = frm_nxt[1]; |
1771 | if ((wc2 & 0xFC00) != 0xDC00) |
1772 | return codecvt_base::error; |
1773 | if (to_end-to_nxt < 4) |
1774 | return codecvt_base::partial; |
1775 | if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + |
1776 | ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) |
1777 | return codecvt_base::error; |
1778 | ++frm_nxt; |
1779 | uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; |
1780 | *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); |
1781 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); |
1782 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); |
1783 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); |
1784 | } |
1785 | else if (wc1 < 0xE000) |
1786 | { |
1787 | return codecvt_base::error; |
1788 | } |
1789 | else |
1790 | { |
1791 | if (to_end-to_nxt < 3) |
1792 | return codecvt_base::partial; |
1793 | *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); |
1794 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); |
1795 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); |
1796 | } |
1797 | } |
1798 | return codecvt_base::ok; |
1799 | } |
1800 | |
1801 | static |
1802 | codecvt_base::result |
1803 | utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, |
1804 | uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, |
1805 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
1806 | { |
1807 | frm_nxt = frm; |
1808 | to_nxt = to; |
1809 | if (mode & generate_header) |
1810 | { |
1811 | if (to_end-to_nxt < 3) |
1812 | return codecvt_base::partial; |
1813 | *to_nxt++ = static_cast<uint8_t>(0xEF); |
1814 | *to_nxt++ = static_cast<uint8_t>(0xBB); |
1815 | *to_nxt++ = static_cast<uint8_t>(0xBF); |
1816 | } |
1817 | for (; frm_nxt < frm_end; ++frm_nxt) |
1818 | { |
1819 | uint16_t wc1 = static_cast<uint16_t>(*frm_nxt); |
1820 | if (wc1 > Maxcode) |
1821 | return codecvt_base::error; |
1822 | if (wc1 < 0x0080) |
1823 | { |
1824 | if (to_end-to_nxt < 1) |
1825 | return codecvt_base::partial; |
1826 | *to_nxt++ = static_cast<uint8_t>(wc1); |
1827 | } |
1828 | else if (wc1 < 0x0800) |
1829 | { |
1830 | if (to_end-to_nxt < 2) |
1831 | return codecvt_base::partial; |
1832 | *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); |
1833 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); |
1834 | } |
1835 | else if (wc1 < 0xD800) |
1836 | { |
1837 | if (to_end-to_nxt < 3) |
1838 | return codecvt_base::partial; |
1839 | *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); |
1840 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); |
1841 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); |
1842 | } |
1843 | else if (wc1 < 0xDC00) |
1844 | { |
1845 | if (frm_end-frm_nxt < 2) |
1846 | return codecvt_base::partial; |
1847 | uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]); |
1848 | if ((wc2 & 0xFC00) != 0xDC00) |
1849 | return codecvt_base::error; |
1850 | if (to_end-to_nxt < 4) |
1851 | return codecvt_base::partial; |
1852 | if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + |
1853 | ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) |
1854 | return codecvt_base::error; |
1855 | ++frm_nxt; |
1856 | uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; |
1857 | *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); |
1858 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); |
1859 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); |
1860 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); |
1861 | } |
1862 | else if (wc1 < 0xE000) |
1863 | { |
1864 | return codecvt_base::error; |
1865 | } |
1866 | else |
1867 | { |
1868 | if (to_end-to_nxt < 3) |
1869 | return codecvt_base::partial; |
1870 | *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); |
1871 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); |
1872 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); |
1873 | } |
1874 | } |
1875 | return codecvt_base::ok; |
1876 | } |
1877 | |
1878 | static |
1879 | codecvt_base::result |
1880 | utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, |
1881 | uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, |
1882 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
1883 | { |
1884 | frm_nxt = frm; |
1885 | to_nxt = to; |
1886 | if (mode & consume_header) |
1887 | { |
1888 | if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && |
1889 | frm_nxt[2] == 0xBF) |
1890 | frm_nxt += 3; |
1891 | } |
1892 | for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) |
1893 | { |
1894 | uint8_t c1 = *frm_nxt; |
1895 | if (c1 > Maxcode) |
1896 | return codecvt_base::error; |
1897 | if (c1 < 0x80) |
1898 | { |
1899 | *to_nxt = static_cast<uint16_t>(c1); |
1900 | ++frm_nxt; |
1901 | } |
1902 | else if (c1 < 0xC2) |
1903 | { |
1904 | return codecvt_base::error; |
1905 | } |
1906 | else if (c1 < 0xE0) |
1907 | { |
1908 | if (frm_end-frm_nxt < 2) |
1909 | return codecvt_base::partial; |
1910 | uint8_t c2 = frm_nxt[1]; |
1911 | if ((c2 & 0xC0) != 0x80) |
1912 | return codecvt_base::error; |
1913 | uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); |
1914 | if (t > Maxcode) |
1915 | return codecvt_base::error; |
1916 | *to_nxt = t; |
1917 | frm_nxt += 2; |
1918 | } |
1919 | else if (c1 < 0xF0) |
1920 | { |
1921 | if (frm_end-frm_nxt < 3) |
1922 | return codecvt_base::partial; |
1923 | uint8_t c2 = frm_nxt[1]; |
1924 | uint8_t c3 = frm_nxt[2]; |
1925 | switch (c1) |
1926 | { |
1927 | case 0xE0: |
1928 | if ((c2 & 0xE0) != 0xA0) |
1929 | return codecvt_base::error; |
1930 | break; |
1931 | case 0xED: |
1932 | if ((c2 & 0xE0) != 0x80) |
1933 | return codecvt_base::error; |
1934 | break; |
1935 | default: |
1936 | if ((c2 & 0xC0) != 0x80) |
1937 | return codecvt_base::error; |
1938 | break; |
1939 | } |
1940 | if ((c3 & 0xC0) != 0x80) |
1941 | return codecvt_base::error; |
1942 | uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) |
1943 | | ((c2 & 0x3F) << 6) |
1944 | | (c3 & 0x3F)); |
1945 | if (t > Maxcode) |
1946 | return codecvt_base::error; |
1947 | *to_nxt = t; |
1948 | frm_nxt += 3; |
1949 | } |
1950 | else if (c1 < 0xF5) |
1951 | { |
1952 | if (frm_end-frm_nxt < 4) |
1953 | return codecvt_base::partial; |
1954 | uint8_t c2 = frm_nxt[1]; |
1955 | uint8_t c3 = frm_nxt[2]; |
1956 | uint8_t c4 = frm_nxt[3]; |
1957 | switch (c1) |
1958 | { |
1959 | case 0xF0: |
1960 | if (!(0x90 <= c2 && c2 <= 0xBF)) |
1961 | return codecvt_base::error; |
1962 | break; |
1963 | case 0xF4: |
1964 | if ((c2 & 0xF0) != 0x80) |
1965 | return codecvt_base::error; |
1966 | break; |
1967 | default: |
1968 | if ((c2 & 0xC0) != 0x80) |
1969 | return codecvt_base::error; |
1970 | break; |
1971 | } |
1972 | if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) |
1973 | return codecvt_base::error; |
1974 | if (to_end-to_nxt < 2) |
1975 | return codecvt_base::partial; |
1976 | if ((((c1 & 7UL) << 18) + |
1977 | ((c2 & 0x3FUL) << 12) + |
1978 | ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) |
1979 | return codecvt_base::error; |
1980 | *to_nxt = static_cast<uint16_t>( |
1981 | 0xD800 |
1982 | | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) |
1983 | | ((c2 & 0x0F) << 2) |
1984 | | ((c3 & 0x30) >> 4)); |
1985 | *++to_nxt = static_cast<uint16_t>( |
1986 | 0xDC00 |
1987 | | ((c3 & 0x0F) << 6) |
1988 | | (c4 & 0x3F)); |
1989 | frm_nxt += 4; |
1990 | } |
1991 | else |
1992 | { |
1993 | return codecvt_base::error; |
1994 | } |
1995 | } |
1996 | return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; |
1997 | } |
1998 | |
1999 | static |
2000 | codecvt_base::result |
2001 | utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, |
2002 | uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, |
2003 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2004 | { |
2005 | frm_nxt = frm; |
2006 | to_nxt = to; |
2007 | if (mode & consume_header) |
2008 | { |
2009 | if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && |
2010 | frm_nxt[2] == 0xBF) |
2011 | frm_nxt += 3; |
2012 | } |
2013 | for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) |
2014 | { |
2015 | uint8_t c1 = *frm_nxt; |
2016 | if (c1 > Maxcode) |
2017 | return codecvt_base::error; |
2018 | if (c1 < 0x80) |
2019 | { |
2020 | *to_nxt = static_cast<uint32_t>(c1); |
2021 | ++frm_nxt; |
2022 | } |
2023 | else if (c1 < 0xC2) |
2024 | { |
2025 | return codecvt_base::error; |
2026 | } |
2027 | else if (c1 < 0xE0) |
2028 | { |
2029 | if (frm_end-frm_nxt < 2) |
2030 | return codecvt_base::partial; |
2031 | uint8_t c2 = frm_nxt[1]; |
2032 | if ((c2 & 0xC0) != 0x80) |
2033 | return codecvt_base::error; |
2034 | uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); |
2035 | if (t > Maxcode) |
2036 | return codecvt_base::error; |
2037 | *to_nxt = static_cast<uint32_t>(t); |
2038 | frm_nxt += 2; |
2039 | } |
2040 | else if (c1 < 0xF0) |
2041 | { |
2042 | if (frm_end-frm_nxt < 3) |
2043 | return codecvt_base::partial; |
2044 | uint8_t c2 = frm_nxt[1]; |
2045 | uint8_t c3 = frm_nxt[2]; |
2046 | switch (c1) |
2047 | { |
2048 | case 0xE0: |
2049 | if ((c2 & 0xE0) != 0xA0) |
2050 | return codecvt_base::error; |
2051 | break; |
2052 | case 0xED: |
2053 | if ((c2 & 0xE0) != 0x80) |
2054 | return codecvt_base::error; |
2055 | break; |
2056 | default: |
2057 | if ((c2 & 0xC0) != 0x80) |
2058 | return codecvt_base::error; |
2059 | break; |
2060 | } |
2061 | if ((c3 & 0xC0) != 0x80) |
2062 | return codecvt_base::error; |
2063 | uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) |
2064 | | ((c2 & 0x3F) << 6) |
2065 | | (c3 & 0x3F)); |
2066 | if (t > Maxcode) |
2067 | return codecvt_base::error; |
2068 | *to_nxt = static_cast<uint32_t>(t); |
2069 | frm_nxt += 3; |
2070 | } |
2071 | else if (c1 < 0xF5) |
2072 | { |
2073 | if (frm_end-frm_nxt < 4) |
2074 | return codecvt_base::partial; |
2075 | uint8_t c2 = frm_nxt[1]; |
2076 | uint8_t c3 = frm_nxt[2]; |
2077 | uint8_t c4 = frm_nxt[3]; |
2078 | switch (c1) |
2079 | { |
2080 | case 0xF0: |
2081 | if (!(0x90 <= c2 && c2 <= 0xBF)) |
2082 | return codecvt_base::error; |
2083 | break; |
2084 | case 0xF4: |
2085 | if ((c2 & 0xF0) != 0x80) |
2086 | return codecvt_base::error; |
2087 | break; |
2088 | default: |
2089 | if ((c2 & 0xC0) != 0x80) |
2090 | return codecvt_base::error; |
2091 | break; |
2092 | } |
2093 | if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) |
2094 | return codecvt_base::error; |
2095 | if (to_end-to_nxt < 2) |
2096 | return codecvt_base::partial; |
2097 | if ((((c1 & 7UL) << 18) + |
2098 | ((c2 & 0x3FUL) << 12) + |
2099 | ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) |
2100 | return codecvt_base::error; |
2101 | *to_nxt = static_cast<uint32_t>( |
2102 | 0xD800 |
2103 | | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) |
2104 | | ((c2 & 0x0F) << 2) |
2105 | | ((c3 & 0x30) >> 4)); |
2106 | *++to_nxt = static_cast<uint32_t>( |
2107 | 0xDC00 |
2108 | | ((c3 & 0x0F) << 6) |
2109 | | (c4 & 0x3F)); |
2110 | frm_nxt += 4; |
2111 | } |
2112 | else |
2113 | { |
2114 | return codecvt_base::error; |
2115 | } |
2116 | } |
2117 | return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; |
2118 | } |
2119 | |
2120 | static |
2121 | int |
2122 | utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end, |
2123 | size_t mx, unsigned long Maxcode = 0x10FFFF, |
2124 | codecvt_mode mode = codecvt_mode(0)) |
2125 | { |
2126 | const uint8_t* frm_nxt = frm; |
2127 | if (mode & consume_header) |
2128 | { |
2129 | if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && |
2130 | frm_nxt[2] == 0xBF) |
2131 | frm_nxt += 3; |
2132 | } |
2133 | for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t) |
2134 | { |
2135 | uint8_t c1 = *frm_nxt; |
2136 | if (c1 > Maxcode) |
2137 | break; |
2138 | if (c1 < 0x80) |
2139 | { |
2140 | ++frm_nxt; |
2141 | } |
2142 | else if (c1 < 0xC2) |
2143 | { |
2144 | break; |
2145 | } |
2146 | else if (c1 < 0xE0) |
2147 | { |
2148 | if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80) |
2149 | break; |
2150 | uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)); |
2151 | if (t > Maxcode) |
2152 | break; |
2153 | frm_nxt += 2; |
2154 | } |
2155 | else if (c1 < 0xF0) |
2156 | { |
2157 | if (frm_end-frm_nxt < 3) |
2158 | break; |
2159 | uint8_t c2 = frm_nxt[1]; |
2160 | uint8_t c3 = frm_nxt[2]; |
2161 | switch (c1) |
2162 | { |
2163 | case 0xE0: |
2164 | if ((c2 & 0xE0) != 0xA0) |
2165 | return static_cast<int>(frm_nxt - frm); |
2166 | break; |
2167 | case 0xED: |
2168 | if ((c2 & 0xE0) != 0x80) |
2169 | return static_cast<int>(frm_nxt - frm); |
2170 | break; |
2171 | default: |
2172 | if ((c2 & 0xC0) != 0x80) |
2173 | return static_cast<int>(frm_nxt - frm); |
2174 | break; |
2175 | } |
2176 | if ((c3 & 0xC0) != 0x80) |
2177 | break; |
2178 | if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) |
2179 | break; |
2180 | frm_nxt += 3; |
2181 | } |
2182 | else if (c1 < 0xF5) |
2183 | { |
2184 | if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2) |
2185 | break; |
2186 | uint8_t c2 = frm_nxt[1]; |
2187 | uint8_t c3 = frm_nxt[2]; |
2188 | uint8_t c4 = frm_nxt[3]; |
2189 | switch (c1) |
2190 | { |
2191 | case 0xF0: |
2192 | if (!(0x90 <= c2 && c2 <= 0xBF)) |
2193 | return static_cast<int>(frm_nxt - frm); |
2194 | break; |
2195 | case 0xF4: |
2196 | if ((c2 & 0xF0) != 0x80) |
2197 | return static_cast<int>(frm_nxt - frm); |
2198 | break; |
2199 | default: |
2200 | if ((c2 & 0xC0) != 0x80) |
2201 | return static_cast<int>(frm_nxt - frm); |
2202 | break; |
2203 | } |
2204 | if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) |
2205 | break; |
2206 | if ((((c1 & 7UL) << 18) + |
2207 | ((c2 & 0x3FUL) << 12) + |
2208 | ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) |
2209 | break; |
2210 | ++nchar16_t; |
2211 | frm_nxt += 4; |
2212 | } |
2213 | else |
2214 | { |
2215 | break; |
2216 | } |
2217 | } |
2218 | return static_cast<int>(frm_nxt - frm); |
2219 | } |
2220 | |
2221 | static |
2222 | codecvt_base::result |
2223 | ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, |
2224 | uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, |
2225 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2226 | { |
2227 | frm_nxt = frm; |
2228 | to_nxt = to; |
2229 | if (mode & generate_header) |
2230 | { |
2231 | if (to_end-to_nxt < 3) |
2232 | return codecvt_base::partial; |
2233 | *to_nxt++ = static_cast<uint8_t>(0xEF); |
2234 | *to_nxt++ = static_cast<uint8_t>(0xBB); |
2235 | *to_nxt++ = static_cast<uint8_t>(0xBF); |
2236 | } |
2237 | for (; frm_nxt < frm_end; ++frm_nxt) |
2238 | { |
2239 | uint32_t wc = *frm_nxt; |
2240 | if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) |
2241 | return codecvt_base::error; |
2242 | if (wc < 0x000080) |
2243 | { |
2244 | if (to_end-to_nxt < 1) |
2245 | return codecvt_base::partial; |
2246 | *to_nxt++ = static_cast<uint8_t>(wc); |
2247 | } |
2248 | else if (wc < 0x000800) |
2249 | { |
2250 | if (to_end-to_nxt < 2) |
2251 | return codecvt_base::partial; |
2252 | *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); |
2253 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); |
2254 | } |
2255 | else if (wc < 0x010000) |
2256 | { |
2257 | if (to_end-to_nxt < 3) |
2258 | return codecvt_base::partial; |
2259 | *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); |
2260 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); |
2261 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); |
2262 | } |
2263 | else // if (wc < 0x110000) |
2264 | { |
2265 | if (to_end-to_nxt < 4) |
2266 | return codecvt_base::partial; |
2267 | *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18)); |
2268 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12)); |
2269 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6)); |
2270 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F)); |
2271 | } |
2272 | } |
2273 | return codecvt_base::ok; |
2274 | } |
2275 | |
2276 | static |
2277 | codecvt_base::result |
2278 | utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, |
2279 | uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, |
2280 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2281 | { |
2282 | frm_nxt = frm; |
2283 | to_nxt = to; |
2284 | if (mode & consume_header) |
2285 | { |
2286 | if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && |
2287 | frm_nxt[2] == 0xBF) |
2288 | frm_nxt += 3; |
2289 | } |
2290 | for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) |
2291 | { |
2292 | uint8_t c1 = static_cast<uint8_t>(*frm_nxt); |
2293 | if (c1 < 0x80) |
2294 | { |
2295 | if (c1 > Maxcode) |
2296 | return codecvt_base::error; |
2297 | *to_nxt = static_cast<uint32_t>(c1); |
2298 | ++frm_nxt; |
2299 | } |
2300 | else if (c1 < 0xC2) |
2301 | { |
2302 | return codecvt_base::error; |
2303 | } |
2304 | else if (c1 < 0xE0) |
2305 | { |
2306 | if (frm_end-frm_nxt < 2) |
2307 | return codecvt_base::partial; |
2308 | uint8_t c2 = frm_nxt[1]; |
2309 | if ((c2 & 0xC0) != 0x80) |
2310 | return codecvt_base::error; |
2311 | uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6) |
2312 | | (c2 & 0x3F)); |
2313 | if (t > Maxcode) |
2314 | return codecvt_base::error; |
2315 | *to_nxt = t; |
2316 | frm_nxt += 2; |
2317 | } |
2318 | else if (c1 < 0xF0) |
2319 | { |
2320 | if (frm_end-frm_nxt < 3) |
2321 | return codecvt_base::partial; |
2322 | uint8_t c2 = frm_nxt[1]; |
2323 | uint8_t c3 = frm_nxt[2]; |
2324 | switch (c1) |
2325 | { |
2326 | case 0xE0: |
2327 | if ((c2 & 0xE0) != 0xA0) |
2328 | return codecvt_base::error; |
2329 | break; |
2330 | case 0xED: |
2331 | if ((c2 & 0xE0) != 0x80) |
2332 | return codecvt_base::error; |
2333 | break; |
2334 | default: |
2335 | if ((c2 & 0xC0) != 0x80) |
2336 | return codecvt_base::error; |
2337 | break; |
2338 | } |
2339 | if ((c3 & 0xC0) != 0x80) |
2340 | return codecvt_base::error; |
2341 | uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12) |
2342 | | ((c2 & 0x3F) << 6) |
2343 | | (c3 & 0x3F)); |
2344 | if (t > Maxcode) |
2345 | return codecvt_base::error; |
2346 | *to_nxt = t; |
2347 | frm_nxt += 3; |
2348 | } |
2349 | else if (c1 < 0xF5) |
2350 | { |
2351 | if (frm_end-frm_nxt < 4) |
2352 | return codecvt_base::partial; |
2353 | uint8_t c2 = frm_nxt[1]; |
2354 | uint8_t c3 = frm_nxt[2]; |
2355 | uint8_t c4 = frm_nxt[3]; |
2356 | switch (c1) |
2357 | { |
2358 | case 0xF0: |
2359 | if (!(0x90 <= c2 && c2 <= 0xBF)) |
2360 | return codecvt_base::error; |
2361 | break; |
2362 | case 0xF4: |
2363 | if ((c2 & 0xF0) != 0x80) |
2364 | return codecvt_base::error; |
2365 | break; |
2366 | default: |
2367 | if ((c2 & 0xC0) != 0x80) |
2368 | return codecvt_base::error; |
2369 | break; |
2370 | } |
2371 | if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) |
2372 | return codecvt_base::error; |
2373 | uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18) |
2374 | | ((c2 & 0x3F) << 12) |
2375 | | ((c3 & 0x3F) << 6) |
2376 | | (c4 & 0x3F)); |
2377 | if (t > Maxcode) |
2378 | return codecvt_base::error; |
2379 | *to_nxt = t; |
2380 | frm_nxt += 4; |
2381 | } |
2382 | else |
2383 | { |
2384 | return codecvt_base::error; |
2385 | } |
2386 | } |
2387 | return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; |
2388 | } |
2389 | |
2390 | static |
2391 | int |
2392 | utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, |
2393 | size_t mx, unsigned long Maxcode = 0x10FFFF, |
2394 | codecvt_mode mode = codecvt_mode(0)) |
2395 | { |
2396 | const uint8_t* frm_nxt = frm; |
2397 | if (mode & consume_header) |
2398 | { |
2399 | if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && |
2400 | frm_nxt[2] == 0xBF) |
2401 | frm_nxt += 3; |
2402 | } |
2403 | for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) |
2404 | { |
2405 | uint8_t c1 = static_cast<uint8_t>(*frm_nxt); |
2406 | if (c1 < 0x80) |
2407 | { |
2408 | if (c1 > Maxcode) |
2409 | break; |
2410 | ++frm_nxt; |
2411 | } |
2412 | else if (c1 < 0xC2) |
2413 | { |
2414 | break; |
2415 | } |
2416 | else if (c1 < 0xE0) |
2417 | { |
2418 | if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) |
2419 | break; |
2420 | if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) |
2421 | break; |
2422 | frm_nxt += 2; |
2423 | } |
2424 | else if (c1 < 0xF0) |
2425 | { |
2426 | if (frm_end-frm_nxt < 3) |
2427 | break; |
2428 | uint8_t c2 = frm_nxt[1]; |
2429 | uint8_t c3 = frm_nxt[2]; |
2430 | switch (c1) |
2431 | { |
2432 | case 0xE0: |
2433 | if ((c2 & 0xE0) != 0xA0) |
2434 | return static_cast<int>(frm_nxt - frm); |
2435 | break; |
2436 | case 0xED: |
2437 | if ((c2 & 0xE0) != 0x80) |
2438 | return static_cast<int>(frm_nxt - frm); |
2439 | break; |
2440 | default: |
2441 | if ((c2 & 0xC0) != 0x80) |
2442 | return static_cast<int>(frm_nxt - frm); |
2443 | break; |
2444 | } |
2445 | if ((c3 & 0xC0) != 0x80) |
2446 | break; |
2447 | if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) |
2448 | break; |
2449 | frm_nxt += 3; |
2450 | } |
2451 | else if (c1 < 0xF5) |
2452 | { |
2453 | if (frm_end-frm_nxt < 4) |
2454 | break; |
2455 | uint8_t c2 = frm_nxt[1]; |
2456 | uint8_t c3 = frm_nxt[2]; |
2457 | uint8_t c4 = frm_nxt[3]; |
2458 | switch (c1) |
2459 | { |
2460 | case 0xF0: |
2461 | if (!(0x90 <= c2 && c2 <= 0xBF)) |
2462 | return static_cast<int>(frm_nxt - frm); |
2463 | break; |
2464 | case 0xF4: |
2465 | if ((c2 & 0xF0) != 0x80) |
2466 | return static_cast<int>(frm_nxt - frm); |
2467 | break; |
2468 | default: |
2469 | if ((c2 & 0xC0) != 0x80) |
2470 | return static_cast<int>(frm_nxt - frm); |
2471 | break; |
2472 | } |
2473 | if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) |
2474 | break; |
2475 | if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) | |
2476 | ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode) |
2477 | break; |
2478 | frm_nxt += 4; |
2479 | } |
2480 | else |
2481 | { |
2482 | break; |
2483 | } |
2484 | } |
2485 | return static_cast<int>(frm_nxt - frm); |
2486 | } |
2487 | |
2488 | static |
2489 | codecvt_base::result |
2490 | ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, |
2491 | uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, |
2492 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2493 | { |
2494 | frm_nxt = frm; |
2495 | to_nxt = to; |
2496 | if (mode & generate_header) |
2497 | { |
2498 | if (to_end-to_nxt < 3) |
2499 | return codecvt_base::partial; |
2500 | *to_nxt++ = static_cast<uint8_t>(0xEF); |
2501 | *to_nxt++ = static_cast<uint8_t>(0xBB); |
2502 | *to_nxt++ = static_cast<uint8_t>(0xBF); |
2503 | } |
2504 | for (; frm_nxt < frm_end; ++frm_nxt) |
2505 | { |
2506 | uint16_t wc = *frm_nxt; |
2507 | if ((wc & 0xF800) == 0xD800 || wc > Maxcode) |
2508 | return codecvt_base::error; |
2509 | if (wc < 0x0080) |
2510 | { |
2511 | if (to_end-to_nxt < 1) |
2512 | return codecvt_base::partial; |
2513 | *to_nxt++ = static_cast<uint8_t>(wc); |
2514 | } |
2515 | else if (wc < 0x0800) |
2516 | { |
2517 | if (to_end-to_nxt < 2) |
2518 | return codecvt_base::partial; |
2519 | *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); |
2520 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); |
2521 | } |
2522 | else // if (wc <= 0xFFFF) |
2523 | { |
2524 | if (to_end-to_nxt < 3) |
2525 | return codecvt_base::partial; |
2526 | *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); |
2527 | *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); |
2528 | *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); |
2529 | } |
2530 | } |
2531 | return codecvt_base::ok; |
2532 | } |
2533 | |
2534 | static |
2535 | codecvt_base::result |
2536 | utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, |
2537 | uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, |
2538 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2539 | { |
2540 | frm_nxt = frm; |
2541 | to_nxt = to; |
2542 | if (mode & consume_header) |
2543 | { |
2544 | if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && |
2545 | frm_nxt[2] == 0xBF) |
2546 | frm_nxt += 3; |
2547 | } |
2548 | for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) |
2549 | { |
2550 | uint8_t c1 = static_cast<uint8_t>(*frm_nxt); |
2551 | if (c1 < 0x80) |
2552 | { |
2553 | if (c1 > Maxcode) |
2554 | return codecvt_base::error; |
2555 | *to_nxt = static_cast<uint16_t>(c1); |
2556 | ++frm_nxt; |
2557 | } |
2558 | else if (c1 < 0xC2) |
2559 | { |
2560 | return codecvt_base::error; |
2561 | } |
2562 | else if (c1 < 0xE0) |
2563 | { |
2564 | if (frm_end-frm_nxt < 2) |
2565 | return codecvt_base::partial; |
2566 | uint8_t c2 = frm_nxt[1]; |
2567 | if ((c2 & 0xC0) != 0x80) |
2568 | return codecvt_base::error; |
2569 | uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) |
2570 | | (c2 & 0x3F)); |
2571 | if (t > Maxcode) |
2572 | return codecvt_base::error; |
2573 | *to_nxt = t; |
2574 | frm_nxt += 2; |
2575 | } |
2576 | else if (c1 < 0xF0) |
2577 | { |
2578 | if (frm_end-frm_nxt < 3) |
2579 | return codecvt_base::partial; |
2580 | uint8_t c2 = frm_nxt[1]; |
2581 | uint8_t c3 = frm_nxt[2]; |
2582 | switch (c1) |
2583 | { |
2584 | case 0xE0: |
2585 | if ((c2 & 0xE0) != 0xA0) |
2586 | return codecvt_base::error; |
2587 | break; |
2588 | case 0xED: |
2589 | if ((c2 & 0xE0) != 0x80) |
2590 | return codecvt_base::error; |
2591 | break; |
2592 | default: |
2593 | if ((c2 & 0xC0) != 0x80) |
2594 | return codecvt_base::error; |
2595 | break; |
2596 | } |
2597 | if ((c3 & 0xC0) != 0x80) |
2598 | return codecvt_base::error; |
2599 | uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) |
2600 | | ((c2 & 0x3F) << 6) |
2601 | | (c3 & 0x3F)); |
2602 | if (t > Maxcode) |
2603 | return codecvt_base::error; |
2604 | *to_nxt = t; |
2605 | frm_nxt += 3; |
2606 | } |
2607 | else |
2608 | { |
2609 | return codecvt_base::error; |
2610 | } |
2611 | } |
2612 | return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; |
2613 | } |
2614 | |
2615 | static |
2616 | int |
2617 | utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, |
2618 | size_t mx, unsigned long Maxcode = 0x10FFFF, |
2619 | codecvt_mode mode = codecvt_mode(0)) |
2620 | { |
2621 | const uint8_t* frm_nxt = frm; |
2622 | if (mode & consume_header) |
2623 | { |
2624 | if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && |
2625 | frm_nxt[2] == 0xBF) |
2626 | frm_nxt += 3; |
2627 | } |
2628 | for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) |
2629 | { |
2630 | uint8_t c1 = static_cast<uint8_t>(*frm_nxt); |
2631 | if (c1 < 0x80) |
2632 | { |
2633 | if (c1 > Maxcode) |
2634 | break; |
2635 | ++frm_nxt; |
2636 | } |
2637 | else if (c1 < 0xC2) |
2638 | { |
2639 | break; |
2640 | } |
2641 | else if (c1 < 0xE0) |
2642 | { |
2643 | if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) |
2644 | break; |
2645 | if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) |
2646 | break; |
2647 | frm_nxt += 2; |
2648 | } |
2649 | else if (c1 < 0xF0) |
2650 | { |
2651 | if (frm_end-frm_nxt < 3) |
2652 | break; |
2653 | uint8_t c2 = frm_nxt[1]; |
2654 | uint8_t c3 = frm_nxt[2]; |
2655 | switch (c1) |
2656 | { |
2657 | case 0xE0: |
2658 | if ((c2 & 0xE0) != 0xA0) |
2659 | return static_cast<int>(frm_nxt - frm); |
2660 | break; |
2661 | case 0xED: |
2662 | if ((c2 & 0xE0) != 0x80) |
2663 | return static_cast<int>(frm_nxt - frm); |
2664 | break; |
2665 | default: |
2666 | if ((c2 & 0xC0) != 0x80) |
2667 | return static_cast<int>(frm_nxt - frm); |
2668 | break; |
2669 | } |
2670 | if ((c3 & 0xC0) != 0x80) |
2671 | break; |
2672 | if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) |
2673 | break; |
2674 | frm_nxt += 3; |
2675 | } |
2676 | else |
2677 | { |
2678 | break; |
2679 | } |
2680 | } |
2681 | return static_cast<int>(frm_nxt - frm); |
2682 | } |
2683 | |
2684 | static |
2685 | codecvt_base::result |
2686 | ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, |
2687 | uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, |
2688 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2689 | { |
2690 | frm_nxt = frm; |
2691 | to_nxt = to; |
2692 | if (mode & generate_header) |
2693 | { |
2694 | if (to_end-to_nxt < 2) |
2695 | return codecvt_base::partial; |
2696 | *to_nxt++ = static_cast<uint8_t>(0xFE); |
2697 | *to_nxt++ = static_cast<uint8_t>(0xFF); |
2698 | } |
2699 | for (; frm_nxt < frm_end; ++frm_nxt) |
2700 | { |
2701 | uint32_t wc = *frm_nxt; |
2702 | if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) |
2703 | return codecvt_base::error; |
2704 | if (wc < 0x010000) |
2705 | { |
2706 | if (to_end-to_nxt < 2) |
2707 | return codecvt_base::partial; |
2708 | *to_nxt++ = static_cast<uint8_t>(wc >> 8); |
2709 | *to_nxt++ = static_cast<uint8_t>(wc); |
2710 | } |
2711 | else |
2712 | { |
2713 | if (to_end-to_nxt < 4) |
2714 | return codecvt_base::partial; |
2715 | uint16_t t = static_cast<uint16_t>( |
2716 | 0xD800 |
2717 | | ((((wc & 0x1F0000) >> 16) - 1) << 6) |
2718 | | ((wc & 0x00FC00) >> 10)); |
2719 | *to_nxt++ = static_cast<uint8_t>(t >> 8); |
2720 | *to_nxt++ = static_cast<uint8_t>(t); |
2721 | t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); |
2722 | *to_nxt++ = static_cast<uint8_t>(t >> 8); |
2723 | *to_nxt++ = static_cast<uint8_t>(t); |
2724 | } |
2725 | } |
2726 | return codecvt_base::ok; |
2727 | } |
2728 | |
2729 | static |
2730 | codecvt_base::result |
2731 | utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, |
2732 | uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, |
2733 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2734 | { |
2735 | frm_nxt = frm; |
2736 | to_nxt = to; |
2737 | if (mode & consume_header) |
2738 | { |
2739 | if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) |
2740 | frm_nxt += 2; |
2741 | } |
2742 | for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) |
2743 | { |
2744 | uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); |
2745 | if ((c1 & 0xFC00) == 0xDC00) |
2746 | return codecvt_base::error; |
2747 | if ((c1 & 0xFC00) != 0xD800) |
2748 | { |
2749 | if (c1 > Maxcode) |
2750 | return codecvt_base::error; |
2751 | *to_nxt = static_cast<uint32_t>(c1); |
2752 | frm_nxt += 2; |
2753 | } |
2754 | else |
2755 | { |
2756 | if (frm_end-frm_nxt < 4) |
2757 | return codecvt_base::partial; |
2758 | uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); |
2759 | if ((c2 & 0xFC00) != 0xDC00) |
2760 | return codecvt_base::error; |
2761 | uint32_t t = static_cast<uint32_t>( |
2762 | ((((c1 & 0x03C0) >> 6) + 1) << 16) |
2763 | | ((c1 & 0x003F) << 10) |
2764 | | (c2 & 0x03FF)); |
2765 | if (t > Maxcode) |
2766 | return codecvt_base::error; |
2767 | *to_nxt = t; |
2768 | frm_nxt += 4; |
2769 | } |
2770 | } |
2771 | return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; |
2772 | } |
2773 | |
2774 | static |
2775 | int |
2776 | utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, |
2777 | size_t mx, unsigned long Maxcode = 0x10FFFF, |
2778 | codecvt_mode mode = codecvt_mode(0)) |
2779 | { |
2780 | const uint8_t* frm_nxt = frm; |
2781 | if (mode & consume_header) |
2782 | { |
2783 | if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) |
2784 | frm_nxt += 2; |
2785 | } |
2786 | for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) |
2787 | { |
2788 | uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); |
2789 | if ((c1 & 0xFC00) == 0xDC00) |
2790 | break; |
2791 | if ((c1 & 0xFC00) != 0xD800) |
2792 | { |
2793 | if (c1 > Maxcode) |
2794 | break; |
2795 | frm_nxt += 2; |
2796 | } |
2797 | else |
2798 | { |
2799 | if (frm_end-frm_nxt < 4) |
2800 | break; |
2801 | uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); |
2802 | if ((c2 & 0xFC00) != 0xDC00) |
2803 | break; |
2804 | uint32_t t = static_cast<uint32_t>( |
2805 | ((((c1 & 0x03C0) >> 6) + 1) << 16) |
2806 | | ((c1 & 0x003F) << 10) |
2807 | | (c2 & 0x03FF)); |
2808 | if (t > Maxcode) |
2809 | break; |
2810 | frm_nxt += 4; |
2811 | } |
2812 | } |
2813 | return static_cast<int>(frm_nxt - frm); |
2814 | } |
2815 | |
2816 | static |
2817 | codecvt_base::result |
2818 | ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, |
2819 | uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, |
2820 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2821 | { |
2822 | frm_nxt = frm; |
2823 | to_nxt = to; |
2824 | if (mode & generate_header) |
2825 | { |
2826 | if (to_end - to_nxt < 2) |
2827 | return codecvt_base::partial; |
2828 | *to_nxt++ = static_cast<uint8_t>(0xFF); |
2829 | *to_nxt++ = static_cast<uint8_t>(0xFE); |
2830 | } |
2831 | for (; frm_nxt < frm_end; ++frm_nxt) |
2832 | { |
2833 | uint32_t wc = *frm_nxt; |
2834 | if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) |
2835 | return codecvt_base::error; |
2836 | if (wc < 0x010000) |
2837 | { |
2838 | if (to_end-to_nxt < 2) |
2839 | return codecvt_base::partial; |
2840 | *to_nxt++ = static_cast<uint8_t>(wc); |
2841 | *to_nxt++ = static_cast<uint8_t>(wc >> 8); |
2842 | } |
2843 | else |
2844 | { |
2845 | if (to_end-to_nxt < 4) |
2846 | return codecvt_base::partial; |
2847 | uint16_t t = static_cast<uint16_t>( |
2848 | 0xD800 |
2849 | | ((((wc & 0x1F0000) >> 16) - 1) << 6) |
2850 | | ((wc & 0x00FC00) >> 10)); |
2851 | *to_nxt++ = static_cast<uint8_t>(t); |
2852 | *to_nxt++ = static_cast<uint8_t>(t >> 8); |
2853 | t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); |
2854 | *to_nxt++ = static_cast<uint8_t>(t); |
2855 | *to_nxt++ = static_cast<uint8_t>(t >> 8); |
2856 | } |
2857 | } |
2858 | return codecvt_base::ok; |
2859 | } |
2860 | |
2861 | static |
2862 | codecvt_base::result |
2863 | utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, |
2864 | uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, |
2865 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2866 | { |
2867 | frm_nxt = frm; |
2868 | to_nxt = to; |
2869 | if (mode & consume_header) |
2870 | { |
2871 | if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) |
2872 | frm_nxt += 2; |
2873 | } |
2874 | for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) |
2875 | { |
2876 | uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); |
2877 | if ((c1 & 0xFC00) == 0xDC00) |
2878 | return codecvt_base::error; |
2879 | if ((c1 & 0xFC00) != 0xD800) |
2880 | { |
2881 | if (c1 > Maxcode) |
2882 | return codecvt_base::error; |
2883 | *to_nxt = static_cast<uint32_t>(c1); |
2884 | frm_nxt += 2; |
2885 | } |
2886 | else |
2887 | { |
2888 | if (frm_end-frm_nxt < 4) |
2889 | return codecvt_base::partial; |
2890 | uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); |
2891 | if ((c2 & 0xFC00) != 0xDC00) |
2892 | return codecvt_base::error; |
2893 | uint32_t t = static_cast<uint32_t>( |
2894 | ((((c1 & 0x03C0) >> 6) + 1) << 16) |
2895 | | ((c1 & 0x003F) << 10) |
2896 | | (c2 & 0x03FF)); |
2897 | if (t > Maxcode) |
2898 | return codecvt_base::error; |
2899 | *to_nxt = t; |
2900 | frm_nxt += 4; |
2901 | } |
2902 | } |
2903 | return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; |
2904 | } |
2905 | |
2906 | static |
2907 | int |
2908 | utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, |
2909 | size_t mx, unsigned long Maxcode = 0x10FFFF, |
2910 | codecvt_mode mode = codecvt_mode(0)) |
2911 | { |
2912 | const uint8_t* frm_nxt = frm; |
2913 | if (mode & consume_header) |
2914 | { |
2915 | if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) |
2916 | frm_nxt += 2; |
2917 | } |
2918 | for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) |
2919 | { |
2920 | uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); |
2921 | if ((c1 & 0xFC00) == 0xDC00) |
2922 | break; |
2923 | if ((c1 & 0xFC00) != 0xD800) |
2924 | { |
2925 | if (c1 > Maxcode) |
2926 | break; |
2927 | frm_nxt += 2; |
2928 | } |
2929 | else |
2930 | { |
2931 | if (frm_end-frm_nxt < 4) |
2932 | break; |
2933 | uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); |
2934 | if ((c2 & 0xFC00) != 0xDC00) |
2935 | break; |
2936 | uint32_t t = static_cast<uint32_t>( |
2937 | ((((c1 & 0x03C0) >> 6) + 1) << 16) |
2938 | | ((c1 & 0x003F) << 10) |
2939 | | (c2 & 0x03FF)); |
2940 | if (t > Maxcode) |
2941 | break; |
2942 | frm_nxt += 4; |
2943 | } |
2944 | } |
2945 | return static_cast<int>(frm_nxt - frm); |
2946 | } |
2947 | |
2948 | static |
2949 | codecvt_base::result |
2950 | ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, |
2951 | uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, |
2952 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2953 | { |
2954 | frm_nxt = frm; |
2955 | to_nxt = to; |
2956 | if (mode & generate_header) |
2957 | { |
2958 | if (to_end-to_nxt < 2) |
2959 | return codecvt_base::partial; |
2960 | *to_nxt++ = static_cast<uint8_t>(0xFE); |
2961 | *to_nxt++ = static_cast<uint8_t>(0xFF); |
2962 | } |
2963 | for (; frm_nxt < frm_end; ++frm_nxt) |
2964 | { |
2965 | uint16_t wc = *frm_nxt; |
2966 | if ((wc & 0xF800) == 0xD800 || wc > Maxcode) |
2967 | return codecvt_base::error; |
2968 | if (to_end-to_nxt < 2) |
2969 | return codecvt_base::partial; |
2970 | *to_nxt++ = static_cast<uint8_t>(wc >> 8); |
2971 | *to_nxt++ = static_cast<uint8_t>(wc); |
2972 | } |
2973 | return codecvt_base::ok; |
2974 | } |
2975 | |
2976 | static |
2977 | codecvt_base::result |
2978 | utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, |
2979 | uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, |
2980 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
2981 | { |
2982 | frm_nxt = frm; |
2983 | to_nxt = to; |
2984 | if (mode & consume_header) |
2985 | { |
2986 | if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) |
2987 | frm_nxt += 2; |
2988 | } |
2989 | for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) |
2990 | { |
2991 | uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); |
2992 | if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) |
2993 | return codecvt_base::error; |
2994 | *to_nxt = c1; |
2995 | frm_nxt += 2; |
2996 | } |
2997 | return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; |
2998 | } |
2999 | |
3000 | static |
3001 | int |
3002 | utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, |
3003 | size_t mx, unsigned long Maxcode = 0x10FFFF, |
3004 | codecvt_mode mode = codecvt_mode(0)) |
3005 | { |
3006 | const uint8_t* frm_nxt = frm; |
3007 | if (mode & consume_header) |
3008 | { |
3009 | if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) |
3010 | frm_nxt += 2; |
3011 | } |
3012 | for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) |
3013 | { |
3014 | uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); |
3015 | if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) |
3016 | break; |
3017 | frm_nxt += 2; |
3018 | } |
3019 | return static_cast<int>(frm_nxt - frm); |
3020 | } |
3021 | |
3022 | static |
3023 | codecvt_base::result |
3024 | ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, |
3025 | uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, |
3026 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
3027 | { |
3028 | frm_nxt = frm; |
3029 | to_nxt = to; |
3030 | if (mode & generate_header) |
3031 | { |
3032 | if (to_end-to_nxt < 2) |
3033 | return codecvt_base::partial; |
3034 | *to_nxt++ = static_cast<uint8_t>(0xFF); |
3035 | *to_nxt++ = static_cast<uint8_t>(0xFE); |
3036 | } |
3037 | for (; frm_nxt < frm_end; ++frm_nxt) |
3038 | { |
3039 | uint16_t wc = *frm_nxt; |
3040 | if ((wc & 0xF800) == 0xD800 || wc > Maxcode) |
3041 | return codecvt_base::error; |
3042 | if (to_end-to_nxt < 2) |
3043 | return codecvt_base::partial; |
3044 | *to_nxt++ = static_cast<uint8_t>(wc); |
3045 | *to_nxt++ = static_cast<uint8_t>(wc >> 8); |
3046 | } |
3047 | return codecvt_base::ok; |
3048 | } |
3049 | |
3050 | static |
3051 | codecvt_base::result |
3052 | utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, |
3053 | uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, |
3054 | unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) |
3055 | { |
3056 | frm_nxt = frm; |
3057 | to_nxt = to; |
3058 | if (mode & consume_header) |
3059 | { |
3060 | if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) |
3061 | frm_nxt += 2; |
3062 | } |
3063 | for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) |
3064 | { |
3065 | uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); |
3066 | if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) |
3067 | return codecvt_base::error; |
3068 | *to_nxt = c1; |
3069 | frm_nxt += 2; |
3070 | } |
3071 | return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; |
3072 | } |
3073 | |
3074 | static |
3075 | int |
3076 | utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, |
3077 | size_t mx, unsigned long Maxcode = 0x10FFFF, |
3078 | codecvt_mode mode = codecvt_mode(0)) |
3079 | { |
3080 | const uint8_t* frm_nxt = frm; |
3081 | frm_nxt = frm; |
3082 | if (mode & consume_header) |
3083 | { |
3084 | if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) |
3085 | frm_nxt += 2; |
3086 | } |
3087 | for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) |
3088 | { |
3089 | uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); |
3090 | if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) |
3091 | break; |
3092 | frm_nxt += 2; |
3093 | } |
3094 | return static_cast<int>(frm_nxt - frm); |
3095 | } |
3096 | |
3097 | // template <> class codecvt<char16_t, char, mbstate_t> |
3098 | |
3099 | locale::id codecvt<char16_t, char, mbstate_t>::id; |
3100 | |
3101 | codecvt<char16_t, char, mbstate_t>::~codecvt() |
3102 | { |
3103 | } |
3104 | |
3105 | codecvt<char16_t, char, mbstate_t>::result |
3106 | codecvt<char16_t, char, mbstate_t>::do_out(state_type&, |
3107 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3108 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3109 | { |
3110 | const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); |
3111 | const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); |
3112 | const uint16_t* _frm_nxt = _frm; |
3113 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3114 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3115 | uint8_t* _to_nxt = _to; |
3116 | result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); |
3117 | frm_nxt = frm + (_frm_nxt - _frm); |
3118 | to_nxt = to + (_to_nxt - _to); |
3119 | return r; |
3120 | } |
3121 | |
3122 | codecvt<char16_t, char, mbstate_t>::result |
3123 | codecvt<char16_t, char, mbstate_t>::do_in(state_type&, |
3124 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3125 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3126 | { |
3127 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3128 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3129 | const uint8_t* _frm_nxt = _frm; |
3130 | uint16_t* _to = reinterpret_cast<uint16_t*>(to); |
3131 | uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); |
3132 | uint16_t* _to_nxt = _to; |
3133 | result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); |
3134 | frm_nxt = frm + (_frm_nxt - _frm); |
3135 | to_nxt = to + (_to_nxt - _to); |
3136 | return r; |
3137 | } |
3138 | |
3139 | codecvt<char16_t, char, mbstate_t>::result |
3140 | codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, |
3141 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3142 | { |
3143 | to_nxt = to; |
3144 | return noconv; |
3145 | } |
3146 | |
3147 | int |
3148 | codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT |
3149 | { |
3150 | return 0; |
3151 | } |
3152 | |
3153 | bool |
3154 | codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT |
3155 | { |
3156 | return false; |
3157 | } |
3158 | |
3159 | int |
3160 | codecvt<char16_t, char, mbstate_t>::do_length(state_type&, |
3161 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3162 | { |
3163 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3164 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3165 | return utf8_to_utf16_length(_frm, _frm_end, mx); |
3166 | } |
3167 | |
3168 | int |
3169 | codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT |
3170 | { |
3171 | return 4; |
3172 | } |
3173 | |
3174 | // template <> class codecvt<char32_t, char, mbstate_t> |
3175 | |
3176 | locale::id codecvt<char32_t, char, mbstate_t>::id; |
3177 | |
3178 | codecvt<char32_t, char, mbstate_t>::~codecvt() |
3179 | { |
3180 | } |
3181 | |
3182 | codecvt<char32_t, char, mbstate_t>::result |
3183 | codecvt<char32_t, char, mbstate_t>::do_out(state_type&, |
3184 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3185 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3186 | { |
3187 | const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); |
3188 | const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); |
3189 | const uint32_t* _frm_nxt = _frm; |
3190 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3191 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3192 | uint8_t* _to_nxt = _to; |
3193 | result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); |
3194 | frm_nxt = frm + (_frm_nxt - _frm); |
3195 | to_nxt = to + (_to_nxt - _to); |
3196 | return r; |
3197 | } |
3198 | |
3199 | codecvt<char32_t, char, mbstate_t>::result |
3200 | codecvt<char32_t, char, mbstate_t>::do_in(state_type&, |
3201 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3202 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3203 | { |
3204 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3205 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3206 | const uint8_t* _frm_nxt = _frm; |
3207 | uint32_t* _to = reinterpret_cast<uint32_t*>(to); |
3208 | uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); |
3209 | uint32_t* _to_nxt = _to; |
3210 | result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); |
3211 | frm_nxt = frm + (_frm_nxt - _frm); |
3212 | to_nxt = to + (_to_nxt - _to); |
3213 | return r; |
3214 | } |
3215 | |
3216 | codecvt<char32_t, char, mbstate_t>::result |
3217 | codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, |
3218 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3219 | { |
3220 | to_nxt = to; |
3221 | return noconv; |
3222 | } |
3223 | |
3224 | int |
3225 | codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT |
3226 | { |
3227 | return 0; |
3228 | } |
3229 | |
3230 | bool |
3231 | codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT |
3232 | { |
3233 | return false; |
3234 | } |
3235 | |
3236 | int |
3237 | codecvt<char32_t, char, mbstate_t>::do_length(state_type&, |
3238 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3239 | { |
3240 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3241 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3242 | return utf8_to_ucs4_length(_frm, _frm_end, mx); |
3243 | } |
3244 | |
3245 | int |
3246 | codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT |
3247 | { |
3248 | return 4; |
3249 | } |
3250 | |
3251 | // __codecvt_utf8<wchar_t> |
3252 | |
3253 | __codecvt_utf8<wchar_t>::result |
3254 | __codecvt_utf8<wchar_t>::do_out(state_type&, |
3255 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3256 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3257 | { |
3258 | #if defined(_LIBCPP_SHORT_WCHAR) |
3259 | const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); |
3260 | const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); |
3261 | const uint16_t* _frm_nxt = _frm; |
3262 | #else |
3263 | const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); |
3264 | const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); |
3265 | const uint32_t* _frm_nxt = _frm; |
3266 | #endif |
3267 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3268 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3269 | uint8_t* _to_nxt = _to; |
3270 | #if defined(_LIBCPP_SHORT_WCHAR) |
3271 | result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3272 | _Maxcode_, _Mode_); |
3273 | #else |
3274 | result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3275 | _Maxcode_, _Mode_); |
3276 | #endif |
3277 | frm_nxt = frm + (_frm_nxt - _frm); |
3278 | to_nxt = to + (_to_nxt - _to); |
3279 | return r; |
3280 | } |
3281 | |
3282 | __codecvt_utf8<wchar_t>::result |
3283 | __codecvt_utf8<wchar_t>::do_in(state_type&, |
3284 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3285 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3286 | { |
3287 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3288 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3289 | const uint8_t* _frm_nxt = _frm; |
3290 | #if defined(_LIBCPP_SHORT_WCHAR) |
3291 | uint16_t* _to = reinterpret_cast<uint16_t*>(to); |
3292 | uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); |
3293 | uint16_t* _to_nxt = _to; |
3294 | result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3295 | _Maxcode_, _Mode_); |
3296 | #else |
3297 | uint32_t* _to = reinterpret_cast<uint32_t*>(to); |
3298 | uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); |
3299 | uint32_t* _to_nxt = _to; |
3300 | result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3301 | _Maxcode_, _Mode_); |
3302 | #endif |
3303 | frm_nxt = frm + (_frm_nxt - _frm); |
3304 | to_nxt = to + (_to_nxt - _to); |
3305 | return r; |
3306 | } |
3307 | |
3308 | __codecvt_utf8<wchar_t>::result |
3309 | __codecvt_utf8<wchar_t>::do_unshift(state_type&, |
3310 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3311 | { |
3312 | to_nxt = to; |
3313 | return noconv; |
3314 | } |
3315 | |
3316 | int |
3317 | __codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT |
3318 | { |
3319 | return 0; |
3320 | } |
3321 | |
3322 | bool |
3323 | __codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT |
3324 | { |
3325 | return false; |
3326 | } |
3327 | |
3328 | int |
3329 | __codecvt_utf8<wchar_t>::do_length(state_type&, |
3330 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3331 | { |
3332 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3333 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3334 | return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
3335 | } |
3336 | |
3337 | int |
3338 | __codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT |
3339 | { |
3340 | if (_Mode_ & consume_header) |
3341 | return 7; |
3342 | return 4; |
3343 | } |
3344 | |
3345 | // __codecvt_utf8<char16_t> |
3346 | |
3347 | __codecvt_utf8<char16_t>::result |
3348 | __codecvt_utf8<char16_t>::do_out(state_type&, |
3349 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3350 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3351 | { |
3352 | const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); |
3353 | const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); |
3354 | const uint16_t* _frm_nxt = _frm; |
3355 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3356 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3357 | uint8_t* _to_nxt = _to; |
3358 | result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3359 | _Maxcode_, _Mode_); |
3360 | frm_nxt = frm + (_frm_nxt - _frm); |
3361 | to_nxt = to + (_to_nxt - _to); |
3362 | return r; |
3363 | } |
3364 | |
3365 | __codecvt_utf8<char16_t>::result |
3366 | __codecvt_utf8<char16_t>::do_in(state_type&, |
3367 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3368 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3369 | { |
3370 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3371 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3372 | const uint8_t* _frm_nxt = _frm; |
3373 | uint16_t* _to = reinterpret_cast<uint16_t*>(to); |
3374 | uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); |
3375 | uint16_t* _to_nxt = _to; |
3376 | result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3377 | _Maxcode_, _Mode_); |
3378 | frm_nxt = frm + (_frm_nxt - _frm); |
3379 | to_nxt = to + (_to_nxt - _to); |
3380 | return r; |
3381 | } |
3382 | |
3383 | __codecvt_utf8<char16_t>::result |
3384 | __codecvt_utf8<char16_t>::do_unshift(state_type&, |
3385 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3386 | { |
3387 | to_nxt = to; |
3388 | return noconv; |
3389 | } |
3390 | |
3391 | int |
3392 | __codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT |
3393 | { |
3394 | return 0; |
3395 | } |
3396 | |
3397 | bool |
3398 | __codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT |
3399 | { |
3400 | return false; |
3401 | } |
3402 | |
3403 | int |
3404 | __codecvt_utf8<char16_t>::do_length(state_type&, |
3405 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3406 | { |
3407 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3408 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3409 | return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
3410 | } |
3411 | |
3412 | int |
3413 | __codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT |
3414 | { |
3415 | if (_Mode_ & consume_header) |
3416 | return 6; |
3417 | return 3; |
3418 | } |
3419 | |
3420 | // __codecvt_utf8<char32_t> |
3421 | |
3422 | __codecvt_utf8<char32_t>::result |
3423 | __codecvt_utf8<char32_t>::do_out(state_type&, |
3424 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3425 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3426 | { |
3427 | const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); |
3428 | const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); |
3429 | const uint32_t* _frm_nxt = _frm; |
3430 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3431 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3432 | uint8_t* _to_nxt = _to; |
3433 | result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3434 | _Maxcode_, _Mode_); |
3435 | frm_nxt = frm + (_frm_nxt - _frm); |
3436 | to_nxt = to + (_to_nxt - _to); |
3437 | return r; |
3438 | } |
3439 | |
3440 | __codecvt_utf8<char32_t>::result |
3441 | __codecvt_utf8<char32_t>::do_in(state_type&, |
3442 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3443 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3444 | { |
3445 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3446 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3447 | const uint8_t* _frm_nxt = _frm; |
3448 | uint32_t* _to = reinterpret_cast<uint32_t*>(to); |
3449 | uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); |
3450 | uint32_t* _to_nxt = _to; |
3451 | result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3452 | _Maxcode_, _Mode_); |
3453 | frm_nxt = frm + (_frm_nxt - _frm); |
3454 | to_nxt = to + (_to_nxt - _to); |
3455 | return r; |
3456 | } |
3457 | |
3458 | __codecvt_utf8<char32_t>::result |
3459 | __codecvt_utf8<char32_t>::do_unshift(state_type&, |
3460 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3461 | { |
3462 | to_nxt = to; |
3463 | return noconv; |
3464 | } |
3465 | |
3466 | int |
3467 | __codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT |
3468 | { |
3469 | return 0; |
3470 | } |
3471 | |
3472 | bool |
3473 | __codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT |
3474 | { |
3475 | return false; |
3476 | } |
3477 | |
3478 | int |
3479 | __codecvt_utf8<char32_t>::do_length(state_type&, |
3480 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3481 | { |
3482 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3483 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3484 | return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
3485 | } |
3486 | |
3487 | int |
3488 | __codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT |
3489 | { |
3490 | if (_Mode_ & consume_header) |
3491 | return 7; |
3492 | return 4; |
3493 | } |
3494 | |
3495 | // __codecvt_utf16<wchar_t, false> |
3496 | |
3497 | __codecvt_utf16<wchar_t, false>::result |
3498 | __codecvt_utf16<wchar_t, false>::do_out(state_type&, |
3499 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3500 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3501 | { |
3502 | const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); |
3503 | const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); |
3504 | const uint32_t* _frm_nxt = _frm; |
3505 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3506 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3507 | uint8_t* _to_nxt = _to; |
3508 | result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3509 | _Maxcode_, _Mode_); |
3510 | frm_nxt = frm + (_frm_nxt - _frm); |
3511 | to_nxt = to + (_to_nxt - _to); |
3512 | return r; |
3513 | } |
3514 | |
3515 | __codecvt_utf16<wchar_t, false>::result |
3516 | __codecvt_utf16<wchar_t, false>::do_in(state_type&, |
3517 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3518 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3519 | { |
3520 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3521 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3522 | const uint8_t* _frm_nxt = _frm; |
3523 | uint32_t* _to = reinterpret_cast<uint32_t*>(to); |
3524 | uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); |
3525 | uint32_t* _to_nxt = _to; |
3526 | result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3527 | _Maxcode_, _Mode_); |
3528 | frm_nxt = frm + (_frm_nxt - _frm); |
3529 | to_nxt = to + (_to_nxt - _to); |
3530 | return r; |
3531 | } |
3532 | |
3533 | __codecvt_utf16<wchar_t, false>::result |
3534 | __codecvt_utf16<wchar_t, false>::do_unshift(state_type&, |
3535 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3536 | { |
3537 | to_nxt = to; |
3538 | return noconv; |
3539 | } |
3540 | |
3541 | int |
3542 | __codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT |
3543 | { |
3544 | return 0; |
3545 | } |
3546 | |
3547 | bool |
3548 | __codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT |
3549 | { |
3550 | return false; |
3551 | } |
3552 | |
3553 | int |
3554 | __codecvt_utf16<wchar_t, false>::do_length(state_type&, |
3555 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3556 | { |
3557 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3558 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3559 | return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
3560 | } |
3561 | |
3562 | int |
3563 | __codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT |
3564 | { |
3565 | if (_Mode_ & consume_header) |
3566 | return 6; |
3567 | return 4; |
3568 | } |
3569 | |
3570 | // __codecvt_utf16<wchar_t, true> |
3571 | |
3572 | __codecvt_utf16<wchar_t, true>::result |
3573 | __codecvt_utf16<wchar_t, true>::do_out(state_type&, |
3574 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3575 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3576 | { |
3577 | const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); |
3578 | const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); |
3579 | const uint32_t* _frm_nxt = _frm; |
3580 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3581 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3582 | uint8_t* _to_nxt = _to; |
3583 | result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3584 | _Maxcode_, _Mode_); |
3585 | frm_nxt = frm + (_frm_nxt - _frm); |
3586 | to_nxt = to + (_to_nxt - _to); |
3587 | return r; |
3588 | } |
3589 | |
3590 | __codecvt_utf16<wchar_t, true>::result |
3591 | __codecvt_utf16<wchar_t, true>::do_in(state_type&, |
3592 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3593 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3594 | { |
3595 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3596 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3597 | const uint8_t* _frm_nxt = _frm; |
3598 | uint32_t* _to = reinterpret_cast<uint32_t*>(to); |
3599 | uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); |
3600 | uint32_t* _to_nxt = _to; |
3601 | result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3602 | _Maxcode_, _Mode_); |
3603 | frm_nxt = frm + (_frm_nxt - _frm); |
3604 | to_nxt = to + (_to_nxt - _to); |
3605 | return r; |
3606 | } |
3607 | |
3608 | __codecvt_utf16<wchar_t, true>::result |
3609 | __codecvt_utf16<wchar_t, true>::do_unshift(state_type&, |
3610 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3611 | { |
3612 | to_nxt = to; |
3613 | return noconv; |
3614 | } |
3615 | |
3616 | int |
3617 | __codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT |
3618 | { |
3619 | return 0; |
3620 | } |
3621 | |
3622 | bool |
3623 | __codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT |
3624 | { |
3625 | return false; |
3626 | } |
3627 | |
3628 | int |
3629 | __codecvt_utf16<wchar_t, true>::do_length(state_type&, |
3630 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3631 | { |
3632 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3633 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3634 | return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
3635 | } |
3636 | |
3637 | int |
3638 | __codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT |
3639 | { |
3640 | if (_Mode_ & consume_header) |
3641 | return 6; |
3642 | return 4; |
3643 | } |
3644 | |
3645 | // __codecvt_utf16<char16_t, false> |
3646 | |
3647 | __codecvt_utf16<char16_t, false>::result |
3648 | __codecvt_utf16<char16_t, false>::do_out(state_type&, |
3649 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3650 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3651 | { |
3652 | const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); |
3653 | const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); |
3654 | const uint16_t* _frm_nxt = _frm; |
3655 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3656 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3657 | uint8_t* _to_nxt = _to; |
3658 | result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3659 | _Maxcode_, _Mode_); |
3660 | frm_nxt = frm + (_frm_nxt - _frm); |
3661 | to_nxt = to + (_to_nxt - _to); |
3662 | return r; |
3663 | } |
3664 | |
3665 | __codecvt_utf16<char16_t, false>::result |
3666 | __codecvt_utf16<char16_t, false>::do_in(state_type&, |
3667 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3668 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3669 | { |
3670 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3671 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3672 | const uint8_t* _frm_nxt = _frm; |
3673 | uint16_t* _to = reinterpret_cast<uint16_t*>(to); |
3674 | uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); |
3675 | uint16_t* _to_nxt = _to; |
3676 | result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3677 | _Maxcode_, _Mode_); |
3678 | frm_nxt = frm + (_frm_nxt - _frm); |
3679 | to_nxt = to + (_to_nxt - _to); |
3680 | return r; |
3681 | } |
3682 | |
3683 | __codecvt_utf16<char16_t, false>::result |
3684 | __codecvt_utf16<char16_t, false>::do_unshift(state_type&, |
3685 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3686 | { |
3687 | to_nxt = to; |
3688 | return noconv; |
3689 | } |
3690 | |
3691 | int |
3692 | __codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT |
3693 | { |
3694 | return 0; |
3695 | } |
3696 | |
3697 | bool |
3698 | __codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT |
3699 | { |
3700 | return false; |
3701 | } |
3702 | |
3703 | int |
3704 | __codecvt_utf16<char16_t, false>::do_length(state_type&, |
3705 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3706 | { |
3707 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3708 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3709 | return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
3710 | } |
3711 | |
3712 | int |
3713 | __codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT |
3714 | { |
3715 | if (_Mode_ & consume_header) |
3716 | return 4; |
3717 | return 2; |
3718 | } |
3719 | |
3720 | // __codecvt_utf16<char16_t, true> |
3721 | |
3722 | __codecvt_utf16<char16_t, true>::result |
3723 | __codecvt_utf16<char16_t, true>::do_out(state_type&, |
3724 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3725 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3726 | { |
3727 | const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); |
3728 | const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); |
3729 | const uint16_t* _frm_nxt = _frm; |
3730 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3731 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3732 | uint8_t* _to_nxt = _to; |
3733 | result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3734 | _Maxcode_, _Mode_); |
3735 | frm_nxt = frm + (_frm_nxt - _frm); |
3736 | to_nxt = to + (_to_nxt - _to); |
3737 | return r; |
3738 | } |
3739 | |
3740 | __codecvt_utf16<char16_t, true>::result |
3741 | __codecvt_utf16<char16_t, true>::do_in(state_type&, |
3742 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3743 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3744 | { |
3745 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3746 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3747 | const uint8_t* _frm_nxt = _frm; |
3748 | uint16_t* _to = reinterpret_cast<uint16_t*>(to); |
3749 | uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); |
3750 | uint16_t* _to_nxt = _to; |
3751 | result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3752 | _Maxcode_, _Mode_); |
3753 | frm_nxt = frm + (_frm_nxt - _frm); |
3754 | to_nxt = to + (_to_nxt - _to); |
3755 | return r; |
3756 | } |
3757 | |
3758 | __codecvt_utf16<char16_t, true>::result |
3759 | __codecvt_utf16<char16_t, true>::do_unshift(state_type&, |
3760 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3761 | { |
3762 | to_nxt = to; |
3763 | return noconv; |
3764 | } |
3765 | |
3766 | int |
3767 | __codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT |
3768 | { |
3769 | return 0; |
3770 | } |
3771 | |
3772 | bool |
3773 | __codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT |
3774 | { |
3775 | return false; |
3776 | } |
3777 | |
3778 | int |
3779 | __codecvt_utf16<char16_t, true>::do_length(state_type&, |
3780 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3781 | { |
3782 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3783 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3784 | return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
3785 | } |
3786 | |
3787 | int |
3788 | __codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT |
3789 | { |
3790 | if (_Mode_ & consume_header) |
3791 | return 4; |
3792 | return 2; |
3793 | } |
3794 | |
3795 | // __codecvt_utf16<char32_t, false> |
3796 | |
3797 | __codecvt_utf16<char32_t, false>::result |
3798 | __codecvt_utf16<char32_t, false>::do_out(state_type&, |
3799 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3800 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3801 | { |
3802 | const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); |
3803 | const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); |
3804 | const uint32_t* _frm_nxt = _frm; |
3805 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3806 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3807 | uint8_t* _to_nxt = _to; |
3808 | result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3809 | _Maxcode_, _Mode_); |
3810 | frm_nxt = frm + (_frm_nxt - _frm); |
3811 | to_nxt = to + (_to_nxt - _to); |
3812 | return r; |
3813 | } |
3814 | |
3815 | __codecvt_utf16<char32_t, false>::result |
3816 | __codecvt_utf16<char32_t, false>::do_in(state_type&, |
3817 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3818 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3819 | { |
3820 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3821 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3822 | const uint8_t* _frm_nxt = _frm; |
3823 | uint32_t* _to = reinterpret_cast<uint32_t*>(to); |
3824 | uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); |
3825 | uint32_t* _to_nxt = _to; |
3826 | result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3827 | _Maxcode_, _Mode_); |
3828 | frm_nxt = frm + (_frm_nxt - _frm); |
3829 | to_nxt = to + (_to_nxt - _to); |
3830 | return r; |
3831 | } |
3832 | |
3833 | __codecvt_utf16<char32_t, false>::result |
3834 | __codecvt_utf16<char32_t, false>::do_unshift(state_type&, |
3835 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3836 | { |
3837 | to_nxt = to; |
3838 | return noconv; |
3839 | } |
3840 | |
3841 | int |
3842 | __codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT |
3843 | { |
3844 | return 0; |
3845 | } |
3846 | |
3847 | bool |
3848 | __codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT |
3849 | { |
3850 | return false; |
3851 | } |
3852 | |
3853 | int |
3854 | __codecvt_utf16<char32_t, false>::do_length(state_type&, |
3855 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3856 | { |
3857 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3858 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3859 | return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
3860 | } |
3861 | |
3862 | int |
3863 | __codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT |
3864 | { |
3865 | if (_Mode_ & consume_header) |
3866 | return 6; |
3867 | return 4; |
3868 | } |
3869 | |
3870 | // __codecvt_utf16<char32_t, true> |
3871 | |
3872 | __codecvt_utf16<char32_t, true>::result |
3873 | __codecvt_utf16<char32_t, true>::do_out(state_type&, |
3874 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3875 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3876 | { |
3877 | const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); |
3878 | const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); |
3879 | const uint32_t* _frm_nxt = _frm; |
3880 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3881 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3882 | uint8_t* _to_nxt = _to; |
3883 | result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3884 | _Maxcode_, _Mode_); |
3885 | frm_nxt = frm + (_frm_nxt - _frm); |
3886 | to_nxt = to + (_to_nxt - _to); |
3887 | return r; |
3888 | } |
3889 | |
3890 | __codecvt_utf16<char32_t, true>::result |
3891 | __codecvt_utf16<char32_t, true>::do_in(state_type&, |
3892 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3893 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3894 | { |
3895 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3896 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3897 | const uint8_t* _frm_nxt = _frm; |
3898 | uint32_t* _to = reinterpret_cast<uint32_t*>(to); |
3899 | uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); |
3900 | uint32_t* _to_nxt = _to; |
3901 | result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3902 | _Maxcode_, _Mode_); |
3903 | frm_nxt = frm + (_frm_nxt - _frm); |
3904 | to_nxt = to + (_to_nxt - _to); |
3905 | return r; |
3906 | } |
3907 | |
3908 | __codecvt_utf16<char32_t, true>::result |
3909 | __codecvt_utf16<char32_t, true>::do_unshift(state_type&, |
3910 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3911 | { |
3912 | to_nxt = to; |
3913 | return noconv; |
3914 | } |
3915 | |
3916 | int |
3917 | __codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT |
3918 | { |
3919 | return 0; |
3920 | } |
3921 | |
3922 | bool |
3923 | __codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT |
3924 | { |
3925 | return false; |
3926 | } |
3927 | |
3928 | int |
3929 | __codecvt_utf16<char32_t, true>::do_length(state_type&, |
3930 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
3931 | { |
3932 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3933 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3934 | return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
3935 | } |
3936 | |
3937 | int |
3938 | __codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT |
3939 | { |
3940 | if (_Mode_ & consume_header) |
3941 | return 6; |
3942 | return 4; |
3943 | } |
3944 | |
3945 | // __codecvt_utf8_utf16<wchar_t> |
3946 | |
3947 | __codecvt_utf8_utf16<wchar_t>::result |
3948 | __codecvt_utf8_utf16<wchar_t>::do_out(state_type&, |
3949 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
3950 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
3951 | { |
3952 | const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); |
3953 | const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); |
3954 | const uint32_t* _frm_nxt = _frm; |
3955 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
3956 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
3957 | uint8_t* _to_nxt = _to; |
3958 | result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3959 | _Maxcode_, _Mode_); |
3960 | frm_nxt = frm + (_frm_nxt - _frm); |
3961 | to_nxt = to + (_to_nxt - _to); |
3962 | return r; |
3963 | } |
3964 | |
3965 | __codecvt_utf8_utf16<wchar_t>::result |
3966 | __codecvt_utf8_utf16<wchar_t>::do_in(state_type&, |
3967 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
3968 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
3969 | { |
3970 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
3971 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
3972 | const uint8_t* _frm_nxt = _frm; |
3973 | uint32_t* _to = reinterpret_cast<uint32_t*>(to); |
3974 | uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); |
3975 | uint32_t* _to_nxt = _to; |
3976 | result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
3977 | _Maxcode_, _Mode_); |
3978 | frm_nxt = frm + (_frm_nxt - _frm); |
3979 | to_nxt = to + (_to_nxt - _to); |
3980 | return r; |
3981 | } |
3982 | |
3983 | __codecvt_utf8_utf16<wchar_t>::result |
3984 | __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&, |
3985 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
3986 | { |
3987 | to_nxt = to; |
3988 | return noconv; |
3989 | } |
3990 | |
3991 | int |
3992 | __codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT |
3993 | { |
3994 | return 0; |
3995 | } |
3996 | |
3997 | bool |
3998 | __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT |
3999 | { |
4000 | return false; |
4001 | } |
4002 | |
4003 | int |
4004 | __codecvt_utf8_utf16<wchar_t>::do_length(state_type&, |
4005 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
4006 | { |
4007 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
4008 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
4009 | return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
4010 | } |
4011 | |
4012 | int |
4013 | __codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT |
4014 | { |
4015 | if (_Mode_ & consume_header) |
4016 | return 7; |
4017 | return 4; |
4018 | } |
4019 | |
4020 | // __codecvt_utf8_utf16<char16_t> |
4021 | |
4022 | __codecvt_utf8_utf16<char16_t>::result |
4023 | __codecvt_utf8_utf16<char16_t>::do_out(state_type&, |
4024 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
4025 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
4026 | { |
4027 | const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); |
4028 | const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); |
4029 | const uint16_t* _frm_nxt = _frm; |
4030 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
4031 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
4032 | uint8_t* _to_nxt = _to; |
4033 | result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
4034 | _Maxcode_, _Mode_); |
4035 | frm_nxt = frm + (_frm_nxt - _frm); |
4036 | to_nxt = to + (_to_nxt - _to); |
4037 | return r; |
4038 | } |
4039 | |
4040 | __codecvt_utf8_utf16<char16_t>::result |
4041 | __codecvt_utf8_utf16<char16_t>::do_in(state_type&, |
4042 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
4043 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
4044 | { |
4045 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
4046 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
4047 | const uint8_t* _frm_nxt = _frm; |
4048 | uint16_t* _to = reinterpret_cast<uint16_t*>(to); |
4049 | uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); |
4050 | uint16_t* _to_nxt = _to; |
4051 | result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
4052 | _Maxcode_, _Mode_); |
4053 | frm_nxt = frm + (_frm_nxt - _frm); |
4054 | to_nxt = to + (_to_nxt - _to); |
4055 | return r; |
4056 | } |
4057 | |
4058 | __codecvt_utf8_utf16<char16_t>::result |
4059 | __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&, |
4060 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
4061 | { |
4062 | to_nxt = to; |
4063 | return noconv; |
4064 | } |
4065 | |
4066 | int |
4067 | __codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT |
4068 | { |
4069 | return 0; |
4070 | } |
4071 | |
4072 | bool |
4073 | __codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT |
4074 | { |
4075 | return false; |
4076 | } |
4077 | |
4078 | int |
4079 | __codecvt_utf8_utf16<char16_t>::do_length(state_type&, |
4080 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
4081 | { |
4082 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
4083 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
4084 | return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
4085 | } |
4086 | |
4087 | int |
4088 | __codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT |
4089 | { |
4090 | if (_Mode_ & consume_header) |
4091 | return 7; |
4092 | return 4; |
4093 | } |
4094 | |
4095 | // __codecvt_utf8_utf16<char32_t> |
4096 | |
4097 | __codecvt_utf8_utf16<char32_t>::result |
4098 | __codecvt_utf8_utf16<char32_t>::do_out(state_type&, |
4099 | const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, |
4100 | extern_type* to, extern_type* to_end, extern_type*& to_nxt) const |
4101 | { |
4102 | const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); |
4103 | const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); |
4104 | const uint32_t* _frm_nxt = _frm; |
4105 | uint8_t* _to = reinterpret_cast<uint8_t*>(to); |
4106 | uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); |
4107 | uint8_t* _to_nxt = _to; |
4108 | result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
4109 | _Maxcode_, _Mode_); |
4110 | frm_nxt = frm + (_frm_nxt - _frm); |
4111 | to_nxt = to + (_to_nxt - _to); |
4112 | return r; |
4113 | } |
4114 | |
4115 | __codecvt_utf8_utf16<char32_t>::result |
4116 | __codecvt_utf8_utf16<char32_t>::do_in(state_type&, |
4117 | const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, |
4118 | intern_type* to, intern_type* to_end, intern_type*& to_nxt) const |
4119 | { |
4120 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
4121 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
4122 | const uint8_t* _frm_nxt = _frm; |
4123 | uint32_t* _to = reinterpret_cast<uint32_t*>(to); |
4124 | uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); |
4125 | uint32_t* _to_nxt = _to; |
4126 | result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, |
4127 | _Maxcode_, _Mode_); |
4128 | frm_nxt = frm + (_frm_nxt - _frm); |
4129 | to_nxt = to + (_to_nxt - _to); |
4130 | return r; |
4131 | } |
4132 | |
4133 | __codecvt_utf8_utf16<char32_t>::result |
4134 | __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&, |
4135 | extern_type* to, extern_type*, extern_type*& to_nxt) const |
4136 | { |
4137 | to_nxt = to; |
4138 | return noconv; |
4139 | } |
4140 | |
4141 | int |
4142 | __codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT |
4143 | { |
4144 | return 0; |
4145 | } |
4146 | |
4147 | bool |
4148 | __codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT |
4149 | { |
4150 | return false; |
4151 | } |
4152 | |
4153 | int |
4154 | __codecvt_utf8_utf16<char32_t>::do_length(state_type&, |
4155 | const extern_type* frm, const extern_type* frm_end, size_t mx) const |
4156 | { |
4157 | const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); |
4158 | const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); |
4159 | return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); |
4160 | } |
4161 | |
4162 | int |
4163 | __codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT |
4164 | { |
4165 | if (_Mode_ & consume_header) |
4166 | return 7; |
4167 | return 4; |
4168 | } |
4169 | |
4170 | // __narrow_to_utf8<16> |
4171 | |
4172 | __narrow_to_utf8<16>::~__narrow_to_utf8() |
4173 | { |
4174 | } |
4175 | |
4176 | // __narrow_to_utf8<32> |
4177 | |
4178 | __narrow_to_utf8<32>::~__narrow_to_utf8() |
4179 | { |
4180 | } |
4181 | |
4182 | // __widen_from_utf8<16> |
4183 | |
4184 | __widen_from_utf8<16>::~__widen_from_utf8() |
4185 | { |
4186 | } |
4187 | |
4188 | // __widen_from_utf8<32> |
4189 | |
4190 | __widen_from_utf8<32>::~__widen_from_utf8() |
4191 | { |
4192 | } |
4193 | |
4194 | |
4195 | static bool checked_string_to_wchar_convert(wchar_t& dest, |
4196 | const char* ptr, |
4197 | locale_t loc) { |
4198 | if (*ptr == '\0') |
4199 | return false; |
4200 | mbstate_t mb = {}; |
4201 | wchar_t out; |
4202 | size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc); |
4203 | if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) { |
4204 | return false; |
4205 | } |
4206 | dest = out; |
4207 | return true; |
4208 | } |
4209 | |
4210 | static bool checked_string_to_char_convert(char& dest, |
4211 | const char* ptr, |
4212 | locale_t __loc) { |
4213 | if (*ptr == '\0') |
4214 | return false; |
4215 | if (!ptr[1]) { |
4216 | dest = *ptr; |
4217 | return true; |
4218 | } |
4219 | // First convert the MBS into a wide char then attempt to narrow it using |
4220 | // wctob_l. |
4221 | wchar_t wout; |
4222 | if (!checked_string_to_wchar_convert(wout, ptr, __loc)) |
4223 | return false; |
4224 | int res; |
4225 | if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) { |
4226 | dest = res; |
4227 | return true; |
4228 | } |
4229 | // FIXME: Work around specific multibyte sequences that we can reasonable |
4230 | // translate into a different single byte. |
4231 | switch (wout) { |
4232 | case L'\u202F': // narrow non-breaking space |
4233 | case L'\u00A0': // non-breaking space |
4234 | dest = ' '; |
4235 | return true; |
4236 | default: |
4237 | return false; |
4238 | } |
4239 | _LIBCPP_UNREACHABLE(); |
4240 | } |
4241 | |
4242 | |
4243 | // numpunct<char> && numpunct<wchar_t> |
4244 | |
4245 | locale::id numpunct< char >::id; |
4246 | locale::id numpunct<wchar_t>::id; |
4247 | |
4248 | numpunct<char>::numpunct(size_t refs) |
4249 | : locale::facet(refs), |
4250 | __decimal_point_('.'), |
4251 | __thousands_sep_(',') |
4252 | { |
4253 | } |
4254 | |
4255 | numpunct<wchar_t>::numpunct(size_t refs) |
4256 | : locale::facet(refs), |
4257 | __decimal_point_(L'.'), |
4258 | __thousands_sep_(L',') |
4259 | { |
4260 | } |
4261 | |
4262 | numpunct<char>::~numpunct() |
4263 | { |
4264 | } |
4265 | |
4266 | numpunct<wchar_t>::~numpunct() |
4267 | { |
4268 | } |
4269 | |
4270 | char numpunct< char >::do_decimal_point() const {return __decimal_point_;} |
4271 | wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;} |
4272 | |
4273 | char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;} |
4274 | wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;} |
4275 | |
4276 | string numpunct< char >::do_grouping() const {return __grouping_;} |
4277 | string numpunct<wchar_t>::do_grouping() const {return __grouping_;} |
4278 | |
4279 | string numpunct< char >::do_truename() const {return "true" ;} |
4280 | wstring numpunct<wchar_t>::do_truename() const {return L"true" ;} |
4281 | |
4282 | string numpunct< char >::do_falsename() const {return "false" ;} |
4283 | wstring numpunct<wchar_t>::do_falsename() const {return L"false" ;} |
4284 | |
4285 | // numpunct_byname<char> |
4286 | |
4287 | numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs) |
4288 | : numpunct<char>(refs) |
4289 | { |
4290 | __init(nm); |
4291 | } |
4292 | |
4293 | numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs) |
4294 | : numpunct<char>(refs) |
4295 | { |
4296 | __init(nm.c_str()); |
4297 | } |
4298 | |
4299 | numpunct_byname<char>::~numpunct_byname() |
4300 | { |
4301 | } |
4302 | |
4303 | void |
4304 | numpunct_byname<char>::__init(const char* nm) |
4305 | { |
4306 | if (strcmp(nm, "C" ) != 0) |
4307 | { |
4308 | __libcpp_unique_locale loc(nm); |
4309 | if (!loc) |
4310 | __throw_runtime_error("numpunct_byname<char>::numpunct_byname" |
4311 | " failed to construct for " + string(nm)); |
4312 | |
4313 | lconv* lc = __libcpp_localeconv_l(loc.get()); |
4314 | checked_string_to_char_convert(__decimal_point_, lc->decimal_point, |
4315 | loc.get()); |
4316 | checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep, |
4317 | loc.get()); |
4318 | __grouping_ = lc->grouping; |
4319 | // localization for truename and falsename is not available |
4320 | } |
4321 | } |
4322 | |
4323 | // numpunct_byname<wchar_t> |
4324 | |
4325 | numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs) |
4326 | : numpunct<wchar_t>(refs) |
4327 | { |
4328 | __init(nm); |
4329 | } |
4330 | |
4331 | numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs) |
4332 | : numpunct<wchar_t>(refs) |
4333 | { |
4334 | __init(nm.c_str()); |
4335 | } |
4336 | |
4337 | numpunct_byname<wchar_t>::~numpunct_byname() |
4338 | { |
4339 | } |
4340 | |
4341 | void |
4342 | numpunct_byname<wchar_t>::__init(const char* nm) |
4343 | { |
4344 | if (strcmp(nm, "C" ) != 0) |
4345 | { |
4346 | __libcpp_unique_locale loc(nm); |
4347 | if (!loc) |
4348 | __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname" |
4349 | " failed to construct for " + string(nm)); |
4350 | |
4351 | lconv* lc = __libcpp_localeconv_l(loc.get()); |
4352 | checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point, |
4353 | loc.get()); |
4354 | checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep, |
4355 | loc.get()); |
4356 | __grouping_ = lc->grouping; |
4357 | // localization for truename and falsename is not available |
4358 | } |
4359 | } |
4360 | |
4361 | // num_get helpers |
4362 | |
4363 | int |
4364 | __num_get_base::__get_base(ios_base& iob) |
4365 | { |
4366 | ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield; |
4367 | if (__basefield == ios_base::oct) |
4368 | return 8; |
4369 | else if (__basefield == ios_base::hex) |
4370 | return 16; |
4371 | else if (__basefield == 0) |
4372 | return 0; |
4373 | return 10; |
4374 | } |
4375 | |
4376 | const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN" ; |
4377 | |
4378 | void |
4379 | __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, |
4380 | ios_base::iostate& __err) |
4381 | { |
4382 | // if the grouping pattern is empty _or_ there are no grouping bits, then do nothing |
4383 | // we always have at least a single entry in [__g, __g_end); the end of the input sequence |
4384 | if (__grouping.size() != 0 && __g_end - __g > 1) |
4385 | { |
4386 | reverse(__g, __g_end); |
4387 | const char* __ig = __grouping.data(); |
4388 | const char* __eg = __ig + __grouping.size(); |
4389 | for (unsigned* __r = __g; __r < __g_end-1; ++__r) |
4390 | { |
4391 | if (0 < *__ig && *__ig < numeric_limits<char>::max()) |
4392 | { |
4393 | if (static_cast<unsigned>(*__ig) != *__r) |
4394 | { |
4395 | __err = ios_base::failbit; |
4396 | return; |
4397 | } |
4398 | } |
4399 | if (__eg - __ig > 1) |
4400 | ++__ig; |
4401 | } |
4402 | if (0 < *__ig && *__ig < numeric_limits<char>::max()) |
4403 | { |
4404 | if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0) |
4405 | __err = ios_base::failbit; |
4406 | } |
4407 | } |
4408 | } |
4409 | |
4410 | void |
4411 | __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, |
4412 | ios_base::fmtflags __flags) |
4413 | { |
4414 | if (__flags & ios_base::showpos) |
4415 | *__fmtp++ = '+'; |
4416 | if (__flags & ios_base::showbase) |
4417 | *__fmtp++ = '#'; |
4418 | while(*__len) |
4419 | *__fmtp++ = *__len++; |
4420 | if ((__flags & ios_base::basefield) == ios_base::oct) |
4421 | *__fmtp = 'o'; |
4422 | else if ((__flags & ios_base::basefield) == ios_base::hex) |
4423 | { |
4424 | if (__flags & ios_base::uppercase) |
4425 | *__fmtp = 'X'; |
4426 | else |
4427 | *__fmtp = 'x'; |
4428 | } |
4429 | else if (__signd) |
4430 | *__fmtp = 'd'; |
4431 | else |
4432 | *__fmtp = 'u'; |
4433 | } |
4434 | |
4435 | bool |
4436 | __num_put_base::__format_float(char* __fmtp, const char* __len, |
4437 | ios_base::fmtflags __flags) |
4438 | { |
4439 | bool specify_precision = true; |
4440 | if (__flags & ios_base::showpos) |
4441 | *__fmtp++ = '+'; |
4442 | if (__flags & ios_base::showpoint) |
4443 | *__fmtp++ = '#'; |
4444 | ios_base::fmtflags floatfield = __flags & ios_base::floatfield; |
4445 | bool uppercase = (__flags & ios_base::uppercase) != 0; |
4446 | if (floatfield == (ios_base::fixed | ios_base::scientific)) |
4447 | specify_precision = false; |
4448 | else |
4449 | { |
4450 | *__fmtp++ = '.'; |
4451 | *__fmtp++ = '*'; |
4452 | } |
4453 | while(*__len) |
4454 | *__fmtp++ = *__len++; |
4455 | if (floatfield == ios_base::fixed) |
4456 | { |
4457 | if (uppercase) |
4458 | *__fmtp = 'F'; |
4459 | else |
4460 | *__fmtp = 'f'; |
4461 | } |
4462 | else if (floatfield == ios_base::scientific) |
4463 | { |
4464 | if (uppercase) |
4465 | *__fmtp = 'E'; |
4466 | else |
4467 | *__fmtp = 'e'; |
4468 | } |
4469 | else if (floatfield == (ios_base::fixed | ios_base::scientific)) |
4470 | { |
4471 | if (uppercase) |
4472 | *__fmtp = 'A'; |
4473 | else |
4474 | *__fmtp = 'a'; |
4475 | } |
4476 | else |
4477 | { |
4478 | if (uppercase) |
4479 | *__fmtp = 'G'; |
4480 | else |
4481 | *__fmtp = 'g'; |
4482 | } |
4483 | return specify_precision; |
4484 | } |
4485 | |
4486 | char* |
4487 | __num_put_base::__identify_padding(char* __nb, char* __ne, |
4488 | const ios_base& __iob) |
4489 | { |
4490 | switch (__iob.flags() & ios_base::adjustfield) |
4491 | { |
4492 | case ios_base::internal: |
4493 | if (__nb[0] == '-' || __nb[0] == '+') |
4494 | return __nb+1; |
4495 | if (__ne - __nb >= 2 && __nb[0] == '0' |
4496 | && (__nb[1] == 'x' || __nb[1] == 'X')) |
4497 | return __nb+2; |
4498 | break; |
4499 | case ios_base::left: |
4500 | return __ne; |
4501 | case ios_base::right: |
4502 | default: |
4503 | break; |
4504 | } |
4505 | return __nb; |
4506 | } |
4507 | |
4508 | // time_get |
4509 | |
4510 | static |
4511 | string* |
4512 | init_weeks() |
4513 | { |
4514 | static string weeks[14]; |
4515 | weeks[0] = "Sunday" ; |
4516 | weeks[1] = "Monday" ; |
4517 | weeks[2] = "Tuesday" ; |
4518 | weeks[3] = "Wednesday" ; |
4519 | weeks[4] = "Thursday" ; |
4520 | weeks[5] = "Friday" ; |
4521 | weeks[6] = "Saturday" ; |
4522 | weeks[7] = "Sun" ; |
4523 | weeks[8] = "Mon" ; |
4524 | weeks[9] = "Tue" ; |
4525 | weeks[10] = "Wed" ; |
4526 | weeks[11] = "Thu" ; |
4527 | weeks[12] = "Fri" ; |
4528 | weeks[13] = "Sat" ; |
4529 | return weeks; |
4530 | } |
4531 | |
4532 | static |
4533 | wstring* |
4534 | init_wweeks() |
4535 | { |
4536 | static wstring weeks[14]; |
4537 | weeks[0] = L"Sunday" ; |
4538 | weeks[1] = L"Monday" ; |
4539 | weeks[2] = L"Tuesday" ; |
4540 | weeks[3] = L"Wednesday" ; |
4541 | weeks[4] = L"Thursday" ; |
4542 | weeks[5] = L"Friday" ; |
4543 | weeks[6] = L"Saturday" ; |
4544 | weeks[7] = L"Sun" ; |
4545 | weeks[8] = L"Mon" ; |
4546 | weeks[9] = L"Tue" ; |
4547 | weeks[10] = L"Wed" ; |
4548 | weeks[11] = L"Thu" ; |
4549 | weeks[12] = L"Fri" ; |
4550 | weeks[13] = L"Sat" ; |
4551 | return weeks; |
4552 | } |
4553 | |
4554 | template <> |
4555 | const string* |
4556 | __time_get_c_storage<char>::__weeks() const |
4557 | { |
4558 | static const string* weeks = init_weeks(); |
4559 | return weeks; |
4560 | } |
4561 | |
4562 | template <> |
4563 | const wstring* |
4564 | __time_get_c_storage<wchar_t>::__weeks() const |
4565 | { |
4566 | static const wstring* weeks = init_wweeks(); |
4567 | return weeks; |
4568 | } |
4569 | |
4570 | static |
4571 | string* |
4572 | init_months() |
4573 | { |
4574 | static string months[24]; |
4575 | months[0] = "January" ; |
4576 | months[1] = "February" ; |
4577 | months[2] = "March" ; |
4578 | months[3] = "April" ; |
4579 | months[4] = "May" ; |
4580 | months[5] = "June" ; |
4581 | months[6] = "July" ; |
4582 | months[7] = "August" ; |
4583 | months[8] = "September" ; |
4584 | months[9] = "October" ; |
4585 | months[10] = "November" ; |
4586 | months[11] = "December" ; |
4587 | months[12] = "Jan" ; |
4588 | months[13] = "Feb" ; |
4589 | months[14] = "Mar" ; |
4590 | months[15] = "Apr" ; |
4591 | months[16] = "May" ; |
4592 | months[17] = "Jun" ; |
4593 | months[18] = "Jul" ; |
4594 | months[19] = "Aug" ; |
4595 | months[20] = "Sep" ; |
4596 | months[21] = "Oct" ; |
4597 | months[22] = "Nov" ; |
4598 | months[23] = "Dec" ; |
4599 | return months; |
4600 | } |
4601 | |
4602 | static |
4603 | wstring* |
4604 | init_wmonths() |
4605 | { |
4606 | static wstring months[24]; |
4607 | months[0] = L"January" ; |
4608 | months[1] = L"February" ; |
4609 | months[2] = L"March" ; |
4610 | months[3] = L"April" ; |
4611 | months[4] = L"May" ; |
4612 | months[5] = L"June" ; |
4613 | months[6] = L"July" ; |
4614 | months[7] = L"August" ; |
4615 | months[8] = L"September" ; |
4616 | months[9] = L"October" ; |
4617 | months[10] = L"November" ; |
4618 | months[11] = L"December" ; |
4619 | months[12] = L"Jan" ; |
4620 | months[13] = L"Feb" ; |
4621 | months[14] = L"Mar" ; |
4622 | months[15] = L"Apr" ; |
4623 | months[16] = L"May" ; |
4624 | months[17] = L"Jun" ; |
4625 | months[18] = L"Jul" ; |
4626 | months[19] = L"Aug" ; |
4627 | months[20] = L"Sep" ; |
4628 | months[21] = L"Oct" ; |
4629 | months[22] = L"Nov" ; |
4630 | months[23] = L"Dec" ; |
4631 | return months; |
4632 | } |
4633 | |
4634 | template <> |
4635 | const string* |
4636 | __time_get_c_storage<char>::__months() const |
4637 | { |
4638 | static const string* months = init_months(); |
4639 | return months; |
4640 | } |
4641 | |
4642 | template <> |
4643 | const wstring* |
4644 | __time_get_c_storage<wchar_t>::__months() const |
4645 | { |
4646 | static const wstring* months = init_wmonths(); |
4647 | return months; |
4648 | } |
4649 | |
4650 | static |
4651 | string* |
4652 | init_am_pm() |
4653 | { |
4654 | static string am_pm[2]; |
4655 | am_pm[0] = "AM" ; |
4656 | am_pm[1] = "PM" ; |
4657 | return am_pm; |
4658 | } |
4659 | |
4660 | static |
4661 | wstring* |
4662 | init_wam_pm() |
4663 | { |
4664 | static wstring am_pm[2]; |
4665 | am_pm[0] = L"AM" ; |
4666 | am_pm[1] = L"PM" ; |
4667 | return am_pm; |
4668 | } |
4669 | |
4670 | template <> |
4671 | const string* |
4672 | __time_get_c_storage<char>::__am_pm() const |
4673 | { |
4674 | static const string* am_pm = init_am_pm(); |
4675 | return am_pm; |
4676 | } |
4677 | |
4678 | template <> |
4679 | const wstring* |
4680 | __time_get_c_storage<wchar_t>::__am_pm() const |
4681 | { |
4682 | static const wstring* am_pm = init_wam_pm(); |
4683 | return am_pm; |
4684 | } |
4685 | |
4686 | template <> |
4687 | const string& |
4688 | __time_get_c_storage<char>::__x() const |
4689 | { |
4690 | static string s("%m/%d/%y" ); |
4691 | return s; |
4692 | } |
4693 | |
4694 | template <> |
4695 | const wstring& |
4696 | __time_get_c_storage<wchar_t>::__x() const |
4697 | { |
4698 | static wstring s(L"%m/%d/%y" ); |
4699 | return s; |
4700 | } |
4701 | |
4702 | template <> |
4703 | const string& |
4704 | __time_get_c_storage<char>::__X() const |
4705 | { |
4706 | static string s("%H:%M:%S" ); |
4707 | return s; |
4708 | } |
4709 | |
4710 | template <> |
4711 | const wstring& |
4712 | __time_get_c_storage<wchar_t>::__X() const |
4713 | { |
4714 | static wstring s(L"%H:%M:%S" ); |
4715 | return s; |
4716 | } |
4717 | |
4718 | template <> |
4719 | const string& |
4720 | __time_get_c_storage<char>::__c() const |
4721 | { |
4722 | static string s("%a %b %d %H:%M:%S %Y" ); |
4723 | return s; |
4724 | } |
4725 | |
4726 | template <> |
4727 | const wstring& |
4728 | __time_get_c_storage<wchar_t>::__c() const |
4729 | { |
4730 | static wstring s(L"%a %b %d %H:%M:%S %Y" ); |
4731 | return s; |
4732 | } |
4733 | |
4734 | template <> |
4735 | const string& |
4736 | __time_get_c_storage<char>::__r() const |
4737 | { |
4738 | static string s("%I:%M:%S %p" ); |
4739 | return s; |
4740 | } |
4741 | |
4742 | template <> |
4743 | const wstring& |
4744 | __time_get_c_storage<wchar_t>::__r() const |
4745 | { |
4746 | static wstring s(L"%I:%M:%S %p" ); |
4747 | return s; |
4748 | } |
4749 | |
4750 | // time_get_byname |
4751 | |
4752 | __time_get::__time_get(const char* nm) |
4753 | : __loc_(newlocale(LC_ALL_MASK, nm, 0)) |
4754 | { |
4755 | if (__loc_ == 0) |
4756 | __throw_runtime_error("time_get_byname" |
4757 | " failed to construct for " + string(nm)); |
4758 | } |
4759 | |
4760 | __time_get::__time_get(const string& nm) |
4761 | : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) |
4762 | { |
4763 | if (__loc_ == 0) |
4764 | __throw_runtime_error("time_get_byname" |
4765 | " failed to construct for " + nm); |
4766 | } |
4767 | |
4768 | __time_get::~__time_get() |
4769 | { |
4770 | freelocale(__loc_); |
4771 | } |
4772 | #if defined(__clang__) |
4773 | #pragma clang diagnostic ignored "-Wmissing-field-initializers" |
4774 | #endif |
4775 | #if defined(__GNUG__) |
4776 | #pragma GCC diagnostic ignored "-Wmissing-field-initializers" |
4777 | #endif |
4778 | |
4779 | template <> |
4780 | string |
4781 | __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct) |
4782 | { |
4783 | tm t = {0}; |
4784 | t.tm_sec = 59; |
4785 | t.tm_min = 55; |
4786 | t.tm_hour = 23; |
4787 | t.tm_mday = 31; |
4788 | t.tm_mon = 11; |
4789 | t.tm_year = 161; |
4790 | t.tm_wday = 6; |
4791 | t.tm_yday = 364; |
4792 | t.tm_isdst = -1; |
4793 | char buf[100]; |
4794 | char f[3] = {0}; |
4795 | f[0] = '%'; |
4796 | f[1] = fmt; |
4797 | size_t n = strftime_l(buf, countof(buf), f, &t, __loc_); |
4798 | char* bb = buf; |
4799 | char* be = buf + n; |
4800 | string result; |
4801 | while (bb != be) |
4802 | { |
4803 | if (ct.is(ctype_base::space, *bb)) |
4804 | { |
4805 | result.push_back(' '); |
4806 | for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb) |
4807 | ; |
4808 | continue; |
4809 | } |
4810 | char* w = bb; |
4811 | ios_base::iostate err = ios_base::goodbit; |
4812 | ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14, |
4813 | ct, err, false) |
4814 | - this->__weeks_; |
4815 | if (i < 14) |
4816 | { |
4817 | result.push_back('%'); |
4818 | if (i < 7) |
4819 | result.push_back('A'); |
4820 | else |
4821 | result.push_back('a'); |
4822 | bb = w; |
4823 | continue; |
4824 | } |
4825 | w = bb; |
4826 | i = __scan_keyword(w, be, this->__months_, this->__months_+24, |
4827 | ct, err, false) |
4828 | - this->__months_; |
4829 | if (i < 24) |
4830 | { |
4831 | result.push_back('%'); |
4832 | if (i < 12) |
4833 | result.push_back('B'); |
4834 | else |
4835 | result.push_back('b'); |
4836 | if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) |
4837 | result.back() = 'm'; |
4838 | bb = w; |
4839 | continue; |
4840 | } |
4841 | if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) |
4842 | { |
4843 | w = bb; |
4844 | i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2, |
4845 | ct, err, false) - this->__am_pm_; |
4846 | if (i < 2) |
4847 | { |
4848 | result.push_back('%'); |
4849 | result.push_back('p'); |
4850 | bb = w; |
4851 | continue; |
4852 | } |
4853 | } |
4854 | w = bb; |
4855 | if (ct.is(ctype_base::digit, *bb)) |
4856 | { |
4857 | switch(__get_up_to_n_digits(bb, be, err, ct, 4)) |
4858 | { |
4859 | case 6: |
4860 | result.push_back('%'); |
4861 | result.push_back('w'); |
4862 | break; |
4863 | case 7: |
4864 | result.push_back('%'); |
4865 | result.push_back('u'); |
4866 | break; |
4867 | case 11: |
4868 | result.push_back('%'); |
4869 | result.push_back('I'); |
4870 | break; |
4871 | case 12: |
4872 | result.push_back('%'); |
4873 | result.push_back('m'); |
4874 | break; |
4875 | case 23: |
4876 | result.push_back('%'); |
4877 | result.push_back('H'); |
4878 | break; |
4879 | case 31: |
4880 | result.push_back('%'); |
4881 | result.push_back('d'); |
4882 | break; |
4883 | case 55: |
4884 | result.push_back('%'); |
4885 | result.push_back('M'); |
4886 | break; |
4887 | case 59: |
4888 | result.push_back('%'); |
4889 | result.push_back('S'); |
4890 | break; |
4891 | case 61: |
4892 | result.push_back('%'); |
4893 | result.push_back('y'); |
4894 | break; |
4895 | case 364: |
4896 | result.push_back('%'); |
4897 | result.push_back('j'); |
4898 | break; |
4899 | case 2061: |
4900 | result.push_back('%'); |
4901 | result.push_back('Y'); |
4902 | break; |
4903 | default: |
4904 | for (; w != bb; ++w) |
4905 | result.push_back(*w); |
4906 | break; |
4907 | } |
4908 | continue; |
4909 | } |
4910 | if (*bb == '%') |
4911 | { |
4912 | result.push_back('%'); |
4913 | result.push_back('%'); |
4914 | ++bb; |
4915 | continue; |
4916 | } |
4917 | result.push_back(*bb); |
4918 | ++bb; |
4919 | } |
4920 | return result; |
4921 | } |
4922 | |
4923 | #if defined(__clang__) |
4924 | #pragma clang diagnostic ignored "-Wmissing-braces" |
4925 | #endif |
4926 | |
4927 | template <> |
4928 | wstring |
4929 | __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct) |
4930 | { |
4931 | tm t = {0}; |
4932 | t.tm_sec = 59; |
4933 | t.tm_min = 55; |
4934 | t.tm_hour = 23; |
4935 | t.tm_mday = 31; |
4936 | t.tm_mon = 11; |
4937 | t.tm_year = 161; |
4938 | t.tm_wday = 6; |
4939 | t.tm_yday = 364; |
4940 | t.tm_isdst = -1; |
4941 | char buf[100]; |
4942 | char f[3] = {0}; |
4943 | f[0] = '%'; |
4944 | f[1] = fmt; |
4945 | strftime_l(buf, countof(buf), f, &t, __loc_); |
4946 | wchar_t wbuf[100]; |
4947 | wchar_t* wbb = wbuf; |
4948 | mbstate_t mb = {0}; |
4949 | const char* bb = buf; |
4950 | size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_); |
4951 | if (j == size_t(-1)) |
4952 | __throw_runtime_error("locale not supported" ); |
4953 | wchar_t* wbe = wbb + j; |
4954 | wstring result; |
4955 | while (wbb != wbe) |
4956 | { |
4957 | if (ct.is(ctype_base::space, *wbb)) |
4958 | { |
4959 | result.push_back(L' '); |
4960 | for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb) |
4961 | ; |
4962 | continue; |
4963 | } |
4964 | wchar_t* w = wbb; |
4965 | ios_base::iostate err = ios_base::goodbit; |
4966 | ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14, |
4967 | ct, err, false) |
4968 | - this->__weeks_; |
4969 | if (i < 14) |
4970 | { |
4971 | result.push_back(L'%'); |
4972 | if (i < 7) |
4973 | result.push_back(L'A'); |
4974 | else |
4975 | result.push_back(L'a'); |
4976 | wbb = w; |
4977 | continue; |
4978 | } |
4979 | w = wbb; |
4980 | i = __scan_keyword(w, wbe, this->__months_, this->__months_+24, |
4981 | ct, err, false) |
4982 | - this->__months_; |
4983 | if (i < 24) |
4984 | { |
4985 | result.push_back(L'%'); |
4986 | if (i < 12) |
4987 | result.push_back(L'B'); |
4988 | else |
4989 | result.push_back(L'b'); |
4990 | if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) |
4991 | result.back() = L'm'; |
4992 | wbb = w; |
4993 | continue; |
4994 | } |
4995 | if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) |
4996 | { |
4997 | w = wbb; |
4998 | i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2, |
4999 | ct, err, false) - this->__am_pm_; |
5000 | if (i < 2) |
5001 | { |
5002 | result.push_back(L'%'); |
5003 | result.push_back(L'p'); |
5004 | wbb = w; |
5005 | continue; |
5006 | } |
5007 | } |
5008 | w = wbb; |
5009 | if (ct.is(ctype_base::digit, *wbb)) |
5010 | { |
5011 | switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4)) |
5012 | { |
5013 | case 6: |
5014 | result.push_back(L'%'); |
5015 | result.push_back(L'w'); |
5016 | break; |
5017 | case 7: |
5018 | result.push_back(L'%'); |
5019 | result.push_back(L'u'); |
5020 | break; |
5021 | case 11: |
5022 | result.push_back(L'%'); |
5023 | result.push_back(L'I'); |
5024 | break; |
5025 | case 12: |
5026 | result.push_back(L'%'); |
5027 | result.push_back(L'm'); |
5028 | break; |
5029 | case 23: |
5030 | result.push_back(L'%'); |
5031 | result.push_back(L'H'); |
5032 | break; |
5033 | case 31: |
5034 | result.push_back(L'%'); |
5035 | result.push_back(L'd'); |
5036 | break; |
5037 | case 55: |
5038 | result.push_back(L'%'); |
5039 | result.push_back(L'M'); |
5040 | break; |
5041 | case 59: |
5042 | result.push_back(L'%'); |
5043 | result.push_back(L'S'); |
5044 | break; |
5045 | case 61: |
5046 | result.push_back(L'%'); |
5047 | result.push_back(L'y'); |
5048 | break; |
5049 | case 364: |
5050 | result.push_back(L'%'); |
5051 | result.push_back(L'j'); |
5052 | break; |
5053 | case 2061: |
5054 | result.push_back(L'%'); |
5055 | result.push_back(L'Y'); |
5056 | break; |
5057 | default: |
5058 | for (; w != wbb; ++w) |
5059 | result.push_back(*w); |
5060 | break; |
5061 | } |
5062 | continue; |
5063 | } |
5064 | if (ct.narrow(*wbb, 0) == '%') |
5065 | { |
5066 | result.push_back(L'%'); |
5067 | result.push_back(L'%'); |
5068 | ++wbb; |
5069 | continue; |
5070 | } |
5071 | result.push_back(*wbb); |
5072 | ++wbb; |
5073 | } |
5074 | return result; |
5075 | } |
5076 | |
5077 | template <> |
5078 | void |
5079 | __time_get_storage<char>::init(const ctype<char>& ct) |
5080 | { |
5081 | tm t = {0}; |
5082 | char buf[100]; |
5083 | // __weeks_ |
5084 | for (int i = 0; i < 7; ++i) |
5085 | { |
5086 | t.tm_wday = i; |
5087 | strftime_l(buf, countof(buf), "%A" , &t, __loc_); |
5088 | __weeks_[i] = buf; |
5089 | strftime_l(buf, countof(buf), "%a" , &t, __loc_); |
5090 | __weeks_[i+7] = buf; |
5091 | } |
5092 | // __months_ |
5093 | for (int i = 0; i < 12; ++i) |
5094 | { |
5095 | t.tm_mon = i; |
5096 | strftime_l(buf, countof(buf), "%B" , &t, __loc_); |
5097 | __months_[i] = buf; |
5098 | strftime_l(buf, countof(buf), "%b" , &t, __loc_); |
5099 | __months_[i+12] = buf; |
5100 | } |
5101 | // __am_pm_ |
5102 | t.tm_hour = 1; |
5103 | strftime_l(buf, countof(buf), "%p" , &t, __loc_); |
5104 | __am_pm_[0] = buf; |
5105 | t.tm_hour = 13; |
5106 | strftime_l(buf, countof(buf), "%p" , &t, __loc_); |
5107 | __am_pm_[1] = buf; |
5108 | __c_ = __analyze('c', ct); |
5109 | __r_ = __analyze('r', ct); |
5110 | __x_ = __analyze('x', ct); |
5111 | __X_ = __analyze('X', ct); |
5112 | } |
5113 | |
5114 | template <> |
5115 | void |
5116 | __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) |
5117 | { |
5118 | tm t = {0}; |
5119 | char buf[100]; |
5120 | wchar_t wbuf[100]; |
5121 | wchar_t* wbe; |
5122 | mbstate_t mb = {0}; |
5123 | // __weeks_ |
5124 | for (int i = 0; i < 7; ++i) |
5125 | { |
5126 | t.tm_wday = i; |
5127 | strftime_l(buf, countof(buf), "%A" , &t, __loc_); |
5128 | mb = mbstate_t(); |
5129 | const char* bb = buf; |
5130 | size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); |
5131 | if (j == size_t(-1)) |
5132 | __throw_runtime_error("locale not supported" ); |
5133 | wbe = wbuf + j; |
5134 | __weeks_[i].assign(wbuf, wbe); |
5135 | strftime_l(buf, countof(buf), "%a" , &t, __loc_); |
5136 | mb = mbstate_t(); |
5137 | bb = buf; |
5138 | j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); |
5139 | if (j == size_t(-1)) |
5140 | __throw_runtime_error("locale not supported" ); |
5141 | wbe = wbuf + j; |
5142 | __weeks_[i+7].assign(wbuf, wbe); |
5143 | } |
5144 | // __months_ |
5145 | for (int i = 0; i < 12; ++i) |
5146 | { |
5147 | t.tm_mon = i; |
5148 | strftime_l(buf, countof(buf), "%B" , &t, __loc_); |
5149 | mb = mbstate_t(); |
5150 | const char* bb = buf; |
5151 | size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); |
5152 | if (j == size_t(-1)) |
5153 | __throw_runtime_error("locale not supported" ); |
5154 | wbe = wbuf + j; |
5155 | __months_[i].assign(wbuf, wbe); |
5156 | strftime_l(buf, countof(buf), "%b" , &t, __loc_); |
5157 | mb = mbstate_t(); |
5158 | bb = buf; |
5159 | j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); |
5160 | if (j == size_t(-1)) |
5161 | __throw_runtime_error("locale not supported" ); |
5162 | wbe = wbuf + j; |
5163 | __months_[i+12].assign(wbuf, wbe); |
5164 | } |
5165 | // __am_pm_ |
5166 | t.tm_hour = 1; |
5167 | strftime_l(buf, countof(buf), "%p" , &t, __loc_); |
5168 | mb = mbstate_t(); |
5169 | const char* bb = buf; |
5170 | size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); |
5171 | if (j == size_t(-1)) |
5172 | __throw_runtime_error("locale not supported" ); |
5173 | wbe = wbuf + j; |
5174 | __am_pm_[0].assign(wbuf, wbe); |
5175 | t.tm_hour = 13; |
5176 | strftime_l(buf, countof(buf), "%p" , &t, __loc_); |
5177 | mb = mbstate_t(); |
5178 | bb = buf; |
5179 | j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); |
5180 | if (j == size_t(-1)) |
5181 | __throw_runtime_error("locale not supported" ); |
5182 | wbe = wbuf + j; |
5183 | __am_pm_[1].assign(wbuf, wbe); |
5184 | __c_ = __analyze('c', ct); |
5185 | __r_ = __analyze('r', ct); |
5186 | __x_ = __analyze('x', ct); |
5187 | __X_ = __analyze('X', ct); |
5188 | } |
5189 | |
5190 | template <class CharT> |
5191 | struct _LIBCPP_HIDDEN __time_get_temp |
5192 | : public ctype_byname<CharT> |
5193 | { |
5194 | explicit __time_get_temp(const char* nm) |
5195 | : ctype_byname<CharT>(nm, 1) {} |
5196 | explicit __time_get_temp(const string& nm) |
5197 | : ctype_byname<CharT>(nm, 1) {} |
5198 | }; |
5199 | |
5200 | template <> |
5201 | __time_get_storage<char>::__time_get_storage(const char* __nm) |
5202 | : __time_get(__nm) |
5203 | { |
5204 | const __time_get_temp<char> ct(__nm); |
5205 | init(ct); |
5206 | } |
5207 | |
5208 | template <> |
5209 | __time_get_storage<char>::__time_get_storage(const string& __nm) |
5210 | : __time_get(__nm) |
5211 | { |
5212 | const __time_get_temp<char> ct(__nm); |
5213 | init(ct); |
5214 | } |
5215 | |
5216 | template <> |
5217 | __time_get_storage<wchar_t>::__time_get_storage(const char* __nm) |
5218 | : __time_get(__nm) |
5219 | { |
5220 | const __time_get_temp<wchar_t> ct(__nm); |
5221 | init(ct); |
5222 | } |
5223 | |
5224 | template <> |
5225 | __time_get_storage<wchar_t>::__time_get_storage(const string& __nm) |
5226 | : __time_get(__nm) |
5227 | { |
5228 | const __time_get_temp<wchar_t> ct(__nm); |
5229 | init(ct); |
5230 | } |
5231 | |
5232 | template <> |
5233 | time_base::dateorder |
5234 | __time_get_storage<char>::__do_date_order() const |
5235 | { |
5236 | unsigned i; |
5237 | for (i = 0; i < __x_.size(); ++i) |
5238 | if (__x_[i] == '%') |
5239 | break; |
5240 | ++i; |
5241 | switch (__x_[i]) |
5242 | { |
5243 | case 'y': |
5244 | case 'Y': |
5245 | for (++i; i < __x_.size(); ++i) |
5246 | if (__x_[i] == '%') |
5247 | break; |
5248 | if (i == __x_.size()) |
5249 | break; |
5250 | ++i; |
5251 | switch (__x_[i]) |
5252 | { |
5253 | case 'm': |
5254 | for (++i; i < __x_.size(); ++i) |
5255 | if (__x_[i] == '%') |
5256 | break; |
5257 | if (i == __x_.size()) |
5258 | break; |
5259 | ++i; |
5260 | if (__x_[i] == 'd') |
5261 | return time_base::ymd; |
5262 | break; |
5263 | case 'd': |
5264 | for (++i; i < __x_.size(); ++i) |
5265 | if (__x_[i] == '%') |
5266 | break; |
5267 | if (i == __x_.size()) |
5268 | break; |
5269 | ++i; |
5270 | if (__x_[i] == 'm') |
5271 | return time_base::ydm; |
5272 | break; |
5273 | } |
5274 | break; |
5275 | case 'm': |
5276 | for (++i; i < __x_.size(); ++i) |
5277 | if (__x_[i] == '%') |
5278 | break; |
5279 | if (i == __x_.size()) |
5280 | break; |
5281 | ++i; |
5282 | if (__x_[i] == 'd') |
5283 | { |
5284 | for (++i; i < __x_.size(); ++i) |
5285 | if (__x_[i] == '%') |
5286 | break; |
5287 | if (i == __x_.size()) |
5288 | break; |
5289 | ++i; |
5290 | if (__x_[i] == 'y' || __x_[i] == 'Y') |
5291 | return time_base::mdy; |
5292 | break; |
5293 | } |
5294 | break; |
5295 | case 'd': |
5296 | for (++i; i < __x_.size(); ++i) |
5297 | if (__x_[i] == '%') |
5298 | break; |
5299 | if (i == __x_.size()) |
5300 | break; |
5301 | ++i; |
5302 | if (__x_[i] == 'm') |
5303 | { |
5304 | for (++i; i < __x_.size(); ++i) |
5305 | if (__x_[i] == '%') |
5306 | break; |
5307 | if (i == __x_.size()) |
5308 | break; |
5309 | ++i; |
5310 | if (__x_[i] == 'y' || __x_[i] == 'Y') |
5311 | return time_base::dmy; |
5312 | break; |
5313 | } |
5314 | break; |
5315 | } |
5316 | return time_base::no_order; |
5317 | } |
5318 | |
5319 | template <> |
5320 | time_base::dateorder |
5321 | __time_get_storage<wchar_t>::__do_date_order() const |
5322 | { |
5323 | unsigned i; |
5324 | for (i = 0; i < __x_.size(); ++i) |
5325 | if (__x_[i] == L'%') |
5326 | break; |
5327 | ++i; |
5328 | switch (__x_[i]) |
5329 | { |
5330 | case L'y': |
5331 | case L'Y': |
5332 | for (++i; i < __x_.size(); ++i) |
5333 | if (__x_[i] == L'%') |
5334 | break; |
5335 | if (i == __x_.size()) |
5336 | break; |
5337 | ++i; |
5338 | switch (__x_[i]) |
5339 | { |
5340 | case L'm': |
5341 | for (++i; i < __x_.size(); ++i) |
5342 | if (__x_[i] == L'%') |
5343 | break; |
5344 | if (i == __x_.size()) |
5345 | break; |
5346 | ++i; |
5347 | if (__x_[i] == L'd') |
5348 | return time_base::ymd; |
5349 | break; |
5350 | case L'd': |
5351 | for (++i; i < __x_.size(); ++i) |
5352 | if (__x_[i] == L'%') |
5353 | break; |
5354 | if (i == __x_.size()) |
5355 | break; |
5356 | ++i; |
5357 | if (__x_[i] == L'm') |
5358 | return time_base::ydm; |
5359 | break; |
5360 | } |
5361 | break; |
5362 | case L'm': |
5363 | for (++i; i < __x_.size(); ++i) |
5364 | if (__x_[i] == L'%') |
5365 | break; |
5366 | if (i == __x_.size()) |
5367 | break; |
5368 | ++i; |
5369 | if (__x_[i] == L'd') |
5370 | { |
5371 | for (++i; i < __x_.size(); ++i) |
5372 | if (__x_[i] == L'%') |
5373 | break; |
5374 | if (i == __x_.size()) |
5375 | break; |
5376 | ++i; |
5377 | if (__x_[i] == L'y' || __x_[i] == L'Y') |
5378 | return time_base::mdy; |
5379 | break; |
5380 | } |
5381 | break; |
5382 | case L'd': |
5383 | for (++i; i < __x_.size(); ++i) |
5384 | if (__x_[i] == L'%') |
5385 | break; |
5386 | if (i == __x_.size()) |
5387 | break; |
5388 | ++i; |
5389 | if (__x_[i] == L'm') |
5390 | { |
5391 | for (++i; i < __x_.size(); ++i) |
5392 | if (__x_[i] == L'%') |
5393 | break; |
5394 | if (i == __x_.size()) |
5395 | break; |
5396 | ++i; |
5397 | if (__x_[i] == L'y' || __x_[i] == L'Y') |
5398 | return time_base::dmy; |
5399 | break; |
5400 | } |
5401 | break; |
5402 | } |
5403 | return time_base::no_order; |
5404 | } |
5405 | |
5406 | // time_put |
5407 | |
5408 | __time_put::__time_put(const char* nm) |
5409 | : __loc_(newlocale(LC_ALL_MASK, nm, 0)) |
5410 | { |
5411 | if (__loc_ == 0) |
5412 | __throw_runtime_error("time_put_byname" |
5413 | " failed to construct for " + string(nm)); |
5414 | } |
5415 | |
5416 | __time_put::__time_put(const string& nm) |
5417 | : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) |
5418 | { |
5419 | if (__loc_ == 0) |
5420 | __throw_runtime_error("time_put_byname" |
5421 | " failed to construct for " + nm); |
5422 | } |
5423 | |
5424 | __time_put::~__time_put() |
5425 | { |
5426 | if (__loc_ != _LIBCPP_GET_C_LOCALE) |
5427 | freelocale(__loc_); |
5428 | } |
5429 | |
5430 | void |
5431 | __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm, |
5432 | char __fmt, char __mod) const |
5433 | { |
5434 | char fmt[] = {'%', __fmt, __mod, 0}; |
5435 | if (__mod != 0) |
5436 | swap(fmt[1], fmt[2]); |
5437 | size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_); |
5438 | __ne = __nb + n; |
5439 | } |
5440 | |
5441 | void |
5442 | __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, |
5443 | char __fmt, char __mod) const |
5444 | { |
5445 | char __nar[100]; |
5446 | char* __ne = __nar + 100; |
5447 | __do_put(__nar, __ne, __tm, __fmt, __mod); |
5448 | mbstate_t mb = {0}; |
5449 | const char* __nb = __nar; |
5450 | size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_); |
5451 | if (j == size_t(-1)) |
5452 | __throw_runtime_error("locale not supported" ); |
5453 | __we = __wb + j; |
5454 | } |
5455 | |
5456 | // moneypunct_byname |
5457 | |
5458 | template <class charT> |
5459 | static |
5460 | void |
5461 | __init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_, |
5462 | bool intl, char cs_precedes, char sep_by_space, char sign_posn, |
5463 | charT space_char) |
5464 | { |
5465 | const char sign = static_cast<char>(money_base::sign); |
5466 | const char space = static_cast<char>(money_base::space); |
5467 | const char none = static_cast<char>(money_base::none); |
5468 | const char symbol = static_cast<char>(money_base::symbol); |
5469 | const char value = static_cast<char>(money_base::value); |
5470 | const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4; |
5471 | |
5472 | // Comments on case branches reflect 'C11 7.11.2.1 The localeconv |
5473 | // function'. "Space between sign and symbol or value" means that |
5474 | // if the sign is adjacent to the symbol, there's a space between |
5475 | // them, and otherwise there's a space between the sign and value. |
5476 | // |
5477 | // C11's localeconv specifies that the fourth character of an |
5478 | // international curr_symbol is used to separate the sign and |
5479 | // value when sep_by_space says to do so. C++ can't represent |
5480 | // that, so we just use a space. When sep_by_space says to |
5481 | // separate the symbol and value-or-sign with a space, we rearrange the |
5482 | // curr_symbol to put its spacing character on the correct side of |
5483 | // the symbol. |
5484 | // |
5485 | // We also need to avoid adding an extra space between the sign |
5486 | // and value when the currency symbol is suppressed (by not |
5487 | // setting showbase). We match glibc's strfmon by interpreting |
5488 | // sep_by_space==1 as "omit the space when the currency symbol is |
5489 | // absent". |
5490 | // |
5491 | // Users who want to get this right should use ICU instead. |
5492 | |
5493 | switch (cs_precedes) |
5494 | { |
5495 | case 0: // value before curr_symbol |
5496 | if (symbol_contains_sep) { |
5497 | // Move the separator to before the symbol, to place it |
5498 | // between the value and symbol. |
5499 | rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3, |
5500 | __curr_symbol_.end()); |
5501 | } |
5502 | switch (sign_posn) |
5503 | { |
5504 | case 0: // Parentheses surround the quantity and currency symbol. |
5505 | pat.field[0] = sign; |
5506 | pat.field[1] = value; |
5507 | pat.field[2] = none; // Any space appears in the symbol. |
5508 | pat.field[3] = symbol; |
5509 | switch (sep_by_space) |
5510 | { |
5511 | case 0: // No space separates the currency symbol and value. |
5512 | // This case may have changed between C99 and C11; |
5513 | // assume the currency symbol matches the intention. |
5514 | case 2: // Space between sign and currency or value. |
5515 | // The "sign" is two parentheses, so no space here either. |
5516 | return; |
5517 | case 1: // Space between currency-and-sign or currency and value. |
5518 | if (!symbol_contains_sep) { |
5519 | // We insert the space into the symbol instead of |
5520 | // setting pat.field[2]=space so that when |
5521 | // showbase is not set, the space goes away too. |
5522 | __curr_symbol_.insert(0, 1, space_char); |
5523 | } |
5524 | return; |
5525 | default: |
5526 | break; |
5527 | } |
5528 | break; |
5529 | case 1: // The sign string precedes the quantity and currency symbol. |
5530 | pat.field[0] = sign; |
5531 | pat.field[3] = symbol; |
5532 | switch (sep_by_space) |
5533 | { |
5534 | case 0: // No space separates the currency symbol and value. |
5535 | pat.field[1] = value; |
5536 | pat.field[2] = none; |
5537 | return; |
5538 | case 1: // Space between currency-and-sign or currency and value. |
5539 | pat.field[1] = value; |
5540 | pat.field[2] = none; |
5541 | if (!symbol_contains_sep) { |
5542 | // We insert the space into the symbol instead of |
5543 | // setting pat.field[2]=space so that when |
5544 | // showbase is not set, the space goes away too. |
5545 | __curr_symbol_.insert(0, 1, space_char); |
5546 | } |
5547 | return; |
5548 | case 2: // Space between sign and currency or value. |
5549 | pat.field[1] = space; |
5550 | pat.field[2] = value; |
5551 | if (symbol_contains_sep) { |
5552 | // Remove the separator from the symbol, since it |
5553 | // has already appeared after the sign. |
5554 | __curr_symbol_.erase(__curr_symbol_.begin()); |
5555 | } |
5556 | return; |
5557 | default: |
5558 | break; |
5559 | } |
5560 | break; |
5561 | case 2: // The sign string succeeds the quantity and currency symbol. |
5562 | pat.field[0] = value; |
5563 | pat.field[3] = sign; |
5564 | switch (sep_by_space) |
5565 | { |
5566 | case 0: // No space separates the currency symbol and value. |
5567 | pat.field[1] = none; |
5568 | pat.field[2] = symbol; |
5569 | return; |
5570 | case 1: // Space between currency-and-sign or currency and value. |
5571 | if (!symbol_contains_sep) { |
5572 | // We insert the space into the symbol instead of |
5573 | // setting pat.field[1]=space so that when |
5574 | // showbase is not set, the space goes away too. |
5575 | __curr_symbol_.insert(0, 1, space_char); |
5576 | } |
5577 | pat.field[1] = none; |
5578 | pat.field[2] = symbol; |
5579 | return; |
5580 | case 2: // Space between sign and currency or value. |
5581 | pat.field[1] = symbol; |
5582 | pat.field[2] = space; |
5583 | if (symbol_contains_sep) { |
5584 | // Remove the separator from the symbol, since it |
5585 | // should not be removed if showbase is absent. |
5586 | __curr_symbol_.erase(__curr_symbol_.begin()); |
5587 | } |
5588 | return; |
5589 | default: |
5590 | break; |
5591 | } |
5592 | break; |
5593 | case 3: // The sign string immediately precedes the currency symbol. |
5594 | pat.field[0] = value; |
5595 | pat.field[3] = symbol; |
5596 | switch (sep_by_space) |
5597 | { |
5598 | case 0: // No space separates the currency symbol and value. |
5599 | pat.field[1] = none; |
5600 | pat.field[2] = sign; |
5601 | return; |
5602 | case 1: // Space between currency-and-sign or currency and value. |
5603 | pat.field[1] = space; |
5604 | pat.field[2] = sign; |
5605 | if (symbol_contains_sep) { |
5606 | // Remove the separator from the symbol, since it |
5607 | // has already appeared before the sign. |
5608 | __curr_symbol_.erase(__curr_symbol_.begin()); |
5609 | } |
5610 | return; |
5611 | case 2: // Space between sign and currency or value. |
5612 | pat.field[1] = sign; |
5613 | pat.field[2] = none; |
5614 | if (!symbol_contains_sep) { |
5615 | // We insert the space into the symbol instead of |
5616 | // setting pat.field[2]=space so that when |
5617 | // showbase is not set, the space goes away too. |
5618 | __curr_symbol_.insert(0, 1, space_char); |
5619 | } |
5620 | return; |
5621 | default: |
5622 | break; |
5623 | } |
5624 | break; |
5625 | case 4: // The sign string immediately succeeds the currency symbol. |
5626 | pat.field[0] = value; |
5627 | pat.field[3] = sign; |
5628 | switch (sep_by_space) |
5629 | { |
5630 | case 0: // No space separates the currency symbol and value. |
5631 | pat.field[1] = none; |
5632 | pat.field[2] = symbol; |
5633 | return; |
5634 | case 1: // Space between currency-and-sign or currency and value. |
5635 | pat.field[1] = none; |
5636 | pat.field[2] = symbol; |
5637 | if (!symbol_contains_sep) { |
5638 | // We insert the space into the symbol instead of |
5639 | // setting pat.field[1]=space so that when |
5640 | // showbase is not set, the space goes away too. |
5641 | __curr_symbol_.insert(0, 1, space_char); |
5642 | } |
5643 | return; |
5644 | case 2: // Space between sign and currency or value. |
5645 | pat.field[1] = symbol; |
5646 | pat.field[2] = space; |
5647 | if (symbol_contains_sep) { |
5648 | // Remove the separator from the symbol, since it |
5649 | // should not disappear when showbase is absent. |
5650 | __curr_symbol_.erase(__curr_symbol_.begin()); |
5651 | } |
5652 | return; |
5653 | default: |
5654 | break; |
5655 | } |
5656 | break; |
5657 | default: |
5658 | break; |
5659 | } |
5660 | break; |
5661 | case 1: // curr_symbol before value |
5662 | switch (sign_posn) |
5663 | { |
5664 | case 0: // Parentheses surround the quantity and currency symbol. |
5665 | pat.field[0] = sign; |
5666 | pat.field[1] = symbol; |
5667 | pat.field[2] = none; // Any space appears in the symbol. |
5668 | pat.field[3] = value; |
5669 | switch (sep_by_space) |
5670 | { |
5671 | case 0: // No space separates the currency symbol and value. |
5672 | // This case may have changed between C99 and C11; |
5673 | // assume the currency symbol matches the intention. |
5674 | case 2: // Space between sign and currency or value. |
5675 | // The "sign" is two parentheses, so no space here either. |
5676 | return; |
5677 | case 1: // Space between currency-and-sign or currency and value. |
5678 | if (!symbol_contains_sep) { |
5679 | // We insert the space into the symbol instead of |
5680 | // setting pat.field[2]=space so that when |
5681 | // showbase is not set, the space goes away too. |
5682 | __curr_symbol_.insert(0, 1, space_char); |
5683 | } |
5684 | return; |
5685 | default: |
5686 | break; |
5687 | } |
5688 | break; |
5689 | case 1: // The sign string precedes the quantity and currency symbol. |
5690 | pat.field[0] = sign; |
5691 | pat.field[3] = value; |
5692 | switch (sep_by_space) |
5693 | { |
5694 | case 0: // No space separates the currency symbol and value. |
5695 | pat.field[1] = symbol; |
5696 | pat.field[2] = none; |
5697 | return; |
5698 | case 1: // Space between currency-and-sign or currency and value. |
5699 | pat.field[1] = symbol; |
5700 | pat.field[2] = none; |
5701 | if (!symbol_contains_sep) { |
5702 | // We insert the space into the symbol instead of |
5703 | // setting pat.field[2]=space so that when |
5704 | // showbase is not set, the space goes away too. |
5705 | __curr_symbol_.push_back(space_char); |
5706 | } |
5707 | return; |
5708 | case 2: // Space between sign and currency or value. |
5709 | pat.field[1] = space; |
5710 | pat.field[2] = symbol; |
5711 | if (symbol_contains_sep) { |
5712 | // Remove the separator from the symbol, since it |
5713 | // has already appeared after the sign. |
5714 | __curr_symbol_.pop_back(); |
5715 | } |
5716 | return; |
5717 | default: |
5718 | break; |
5719 | } |
5720 | break; |
5721 | case 2: // The sign string succeeds the quantity and currency symbol. |
5722 | pat.field[0] = symbol; |
5723 | pat.field[3] = sign; |
5724 | switch (sep_by_space) |
5725 | { |
5726 | case 0: // No space separates the currency symbol and value. |
5727 | pat.field[1] = none; |
5728 | pat.field[2] = value; |
5729 | return; |
5730 | case 1: // Space between currency-and-sign or currency and value. |
5731 | pat.field[1] = none; |
5732 | pat.field[2] = value; |
5733 | if (!symbol_contains_sep) { |
5734 | // We insert the space into the symbol instead of |
5735 | // setting pat.field[1]=space so that when |
5736 | // showbase is not set, the space goes away too. |
5737 | __curr_symbol_.push_back(space_char); |
5738 | } |
5739 | return; |
5740 | case 2: // Space between sign and currency or value. |
5741 | pat.field[1] = value; |
5742 | pat.field[2] = space; |
5743 | if (symbol_contains_sep) { |
5744 | // Remove the separator from the symbol, since it |
5745 | // will appear before the sign. |
5746 | __curr_symbol_.pop_back(); |
5747 | } |
5748 | return; |
5749 | default: |
5750 | break; |
5751 | } |
5752 | break; |
5753 | case 3: // The sign string immediately precedes the currency symbol. |
5754 | pat.field[0] = sign; |
5755 | pat.field[3] = value; |
5756 | switch (sep_by_space) |
5757 | { |
5758 | case 0: // No space separates the currency symbol and value. |
5759 | pat.field[1] = symbol; |
5760 | pat.field[2] = none; |
5761 | return; |
5762 | case 1: // Space between currency-and-sign or currency and value. |
5763 | pat.field[1] = symbol; |
5764 | pat.field[2] = none; |
5765 | if (!symbol_contains_sep) { |
5766 | // We insert the space into the symbol instead of |
5767 | // setting pat.field[2]=space so that when |
5768 | // showbase is not set, the space goes away too. |
5769 | __curr_symbol_.push_back(space_char); |
5770 | } |
5771 | return; |
5772 | case 2: // Space between sign and currency or value. |
5773 | pat.field[1] = space; |
5774 | pat.field[2] = symbol; |
5775 | if (symbol_contains_sep) { |
5776 | // Remove the separator from the symbol, since it |
5777 | // has already appeared after the sign. |
5778 | __curr_symbol_.pop_back(); |
5779 | } |
5780 | return; |
5781 | default: |
5782 | break; |
5783 | } |
5784 | break; |
5785 | case 4: // The sign string immediately succeeds the currency symbol. |
5786 | pat.field[0] = symbol; |
5787 | pat.field[3] = value; |
5788 | switch (sep_by_space) |
5789 | { |
5790 | case 0: // No space separates the currency symbol and value. |
5791 | pat.field[1] = sign; |
5792 | pat.field[2] = none; |
5793 | return; |
5794 | case 1: // Space between currency-and-sign or currency and value. |
5795 | pat.field[1] = sign; |
5796 | pat.field[2] = space; |
5797 | if (symbol_contains_sep) { |
5798 | // Remove the separator from the symbol, since it |
5799 | // should not disappear when showbase is absent. |
5800 | __curr_symbol_.pop_back(); |
5801 | } |
5802 | return; |
5803 | case 2: // Space between sign and currency or value. |
5804 | pat.field[1] = none; |
5805 | pat.field[2] = sign; |
5806 | if (!symbol_contains_sep) { |
5807 | // We insert the space into the symbol instead of |
5808 | // setting pat.field[1]=space so that when |
5809 | // showbase is not set, the space goes away too. |
5810 | __curr_symbol_.push_back(space_char); |
5811 | } |
5812 | return; |
5813 | default: |
5814 | break; |
5815 | } |
5816 | break; |
5817 | default: |
5818 | break; |
5819 | } |
5820 | break; |
5821 | default: |
5822 | break; |
5823 | } |
5824 | pat.field[0] = symbol; |
5825 | pat.field[1] = sign; |
5826 | pat.field[2] = none; |
5827 | pat.field[3] = value; |
5828 | } |
5829 | |
5830 | template<> |
5831 | void |
5832 | moneypunct_byname<char, false>::init(const char* nm) |
5833 | { |
5834 | typedef moneypunct<char, false> base; |
5835 | __libcpp_unique_locale loc(nm); |
5836 | if (!loc) |
5837 | __throw_runtime_error("moneypunct_byname" |
5838 | " failed to construct for " + string(nm)); |
5839 | |
5840 | lconv* lc = __libcpp_localeconv_l(loc.get()); |
5841 | if (!checked_string_to_char_convert(__decimal_point_, |
5842 | lc->mon_decimal_point, |
5843 | loc.get())) |
5844 | __decimal_point_ = base::do_decimal_point(); |
5845 | if (!checked_string_to_char_convert(__thousands_sep_, |
5846 | lc->mon_thousands_sep, |
5847 | loc.get())) |
5848 | __thousands_sep_ = base::do_thousands_sep(); |
5849 | |
5850 | __grouping_ = lc->mon_grouping; |
5851 | __curr_symbol_ = lc->currency_symbol; |
5852 | if (lc->frac_digits != CHAR_MAX) |
5853 | __frac_digits_ = lc->frac_digits; |
5854 | else |
5855 | __frac_digits_ = base::do_frac_digits(); |
5856 | if (lc->p_sign_posn == 0) |
5857 | __positive_sign_ = "()" ; |
5858 | else |
5859 | __positive_sign_ = lc->positive_sign; |
5860 | if (lc->n_sign_posn == 0) |
5861 | __negative_sign_ = "()" ; |
5862 | else |
5863 | __negative_sign_ = lc->negative_sign; |
5864 | // Assume the positive and negative formats will want spaces in |
5865 | // the same places in curr_symbol since there's no way to |
5866 | // represent anything else. |
5867 | string_type __dummy_curr_symbol = __curr_symbol_; |
5868 | __init_pat(__pos_format_, __dummy_curr_symbol, false, |
5869 | lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); |
5870 | __init_pat(__neg_format_, __curr_symbol_, false, |
5871 | lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); |
5872 | } |
5873 | |
5874 | template<> |
5875 | void |
5876 | moneypunct_byname<char, true>::init(const char* nm) |
5877 | { |
5878 | typedef moneypunct<char, true> base; |
5879 | __libcpp_unique_locale loc(nm); |
5880 | if (!loc) |
5881 | __throw_runtime_error("moneypunct_byname" |
5882 | " failed to construct for " + string(nm)); |
5883 | |
5884 | lconv* lc = __libcpp_localeconv_l(loc.get()); |
5885 | if (!checked_string_to_char_convert(__decimal_point_, |
5886 | lc->mon_decimal_point, |
5887 | loc.get())) |
5888 | __decimal_point_ = base::do_decimal_point(); |
5889 | if (!checked_string_to_char_convert(__thousands_sep_, |
5890 | lc->mon_thousands_sep, |
5891 | loc.get())) |
5892 | __thousands_sep_ = base::do_thousands_sep(); |
5893 | __grouping_ = lc->mon_grouping; |
5894 | __curr_symbol_ = lc->int_curr_symbol; |
5895 | if (lc->int_frac_digits != CHAR_MAX) |
5896 | __frac_digits_ = lc->int_frac_digits; |
5897 | else |
5898 | __frac_digits_ = base::do_frac_digits(); |
5899 | #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
5900 | if (lc->p_sign_posn == 0) |
5901 | #else // _LIBCPP_MSVCRT |
5902 | if (lc->int_p_sign_posn == 0) |
5903 | #endif // !_LIBCPP_MSVCRT |
5904 | __positive_sign_ = "()" ; |
5905 | else |
5906 | __positive_sign_ = lc->positive_sign; |
5907 | #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
5908 | if(lc->n_sign_posn == 0) |
5909 | #else // _LIBCPP_MSVCRT |
5910 | if (lc->int_n_sign_posn == 0) |
5911 | #endif // !_LIBCPP_MSVCRT |
5912 | __negative_sign_ = "()" ; |
5913 | else |
5914 | __negative_sign_ = lc->negative_sign; |
5915 | // Assume the positive and negative formats will want spaces in |
5916 | // the same places in curr_symbol since there's no way to |
5917 | // represent anything else. |
5918 | string_type __dummy_curr_symbol = __curr_symbol_; |
5919 | #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
5920 | __init_pat(__pos_format_, __dummy_curr_symbol, true, |
5921 | lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); |
5922 | __init_pat(__neg_format_, __curr_symbol_, true, |
5923 | lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); |
5924 | #else // _LIBCPP_MSVCRT |
5925 | __init_pat(__pos_format_, __dummy_curr_symbol, true, |
5926 | lc->int_p_cs_precedes, lc->int_p_sep_by_space, |
5927 | lc->int_p_sign_posn, ' '); |
5928 | __init_pat(__neg_format_, __curr_symbol_, true, |
5929 | lc->int_n_cs_precedes, lc->int_n_sep_by_space, |
5930 | lc->int_n_sign_posn, ' '); |
5931 | #endif // !_LIBCPP_MSVCRT |
5932 | } |
5933 | |
5934 | template<> |
5935 | void |
5936 | moneypunct_byname<wchar_t, false>::init(const char* nm) |
5937 | { |
5938 | typedef moneypunct<wchar_t, false> base; |
5939 | __libcpp_unique_locale loc(nm); |
5940 | if (!loc) |
5941 | __throw_runtime_error("moneypunct_byname" |
5942 | " failed to construct for " + string(nm)); |
5943 | lconv* lc = __libcpp_localeconv_l(loc.get()); |
5944 | if (!checked_string_to_wchar_convert(__decimal_point_, |
5945 | lc->mon_decimal_point, |
5946 | loc.get())) |
5947 | __decimal_point_ = base::do_decimal_point(); |
5948 | if (!checked_string_to_wchar_convert(__thousands_sep_, |
5949 | lc->mon_thousands_sep, |
5950 | loc.get())) |
5951 | __thousands_sep_ = base::do_thousands_sep(); |
5952 | __grouping_ = lc->mon_grouping; |
5953 | wchar_t wbuf[100]; |
5954 | mbstate_t mb = {0}; |
5955 | const char* bb = lc->currency_symbol; |
5956 | size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); |
5957 | if (j == size_t(-1)) |
5958 | __throw_runtime_error("locale not supported" ); |
5959 | wchar_t* wbe = wbuf + j; |
5960 | __curr_symbol_.assign(wbuf, wbe); |
5961 | if (lc->frac_digits != CHAR_MAX) |
5962 | __frac_digits_ = lc->frac_digits; |
5963 | else |
5964 | __frac_digits_ = base::do_frac_digits(); |
5965 | if (lc->p_sign_posn == 0) |
5966 | __positive_sign_ = L"()" ; |
5967 | else |
5968 | { |
5969 | mb = mbstate_t(); |
5970 | bb = lc->positive_sign; |
5971 | j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); |
5972 | if (j == size_t(-1)) |
5973 | __throw_runtime_error("locale not supported" ); |
5974 | wbe = wbuf + j; |
5975 | __positive_sign_.assign(wbuf, wbe); |
5976 | } |
5977 | if (lc->n_sign_posn == 0) |
5978 | __negative_sign_ = L"()" ; |
5979 | else |
5980 | { |
5981 | mb = mbstate_t(); |
5982 | bb = lc->negative_sign; |
5983 | j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); |
5984 | if (j == size_t(-1)) |
5985 | __throw_runtime_error("locale not supported" ); |
5986 | wbe = wbuf + j; |
5987 | __negative_sign_.assign(wbuf, wbe); |
5988 | } |
5989 | // Assume the positive and negative formats will want spaces in |
5990 | // the same places in curr_symbol since there's no way to |
5991 | // represent anything else. |
5992 | string_type __dummy_curr_symbol = __curr_symbol_; |
5993 | __init_pat(__pos_format_, __dummy_curr_symbol, false, |
5994 | lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); |
5995 | __init_pat(__neg_format_, __curr_symbol_, false, |
5996 | lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); |
5997 | } |
5998 | |
5999 | template<> |
6000 | void |
6001 | moneypunct_byname<wchar_t, true>::init(const char* nm) |
6002 | { |
6003 | typedef moneypunct<wchar_t, true> base; |
6004 | __libcpp_unique_locale loc(nm); |
6005 | if (!loc) |
6006 | __throw_runtime_error("moneypunct_byname" |
6007 | " failed to construct for " + string(nm)); |
6008 | |
6009 | lconv* lc = __libcpp_localeconv_l(loc.get()); |
6010 | if (!checked_string_to_wchar_convert(__decimal_point_, |
6011 | lc->mon_decimal_point, |
6012 | loc.get())) |
6013 | __decimal_point_ = base::do_decimal_point(); |
6014 | if (!checked_string_to_wchar_convert(__thousands_sep_, |
6015 | lc->mon_thousands_sep, |
6016 | loc.get())) |
6017 | __thousands_sep_ = base::do_thousands_sep(); |
6018 | __grouping_ = lc->mon_grouping; |
6019 | wchar_t wbuf[100]; |
6020 | mbstate_t mb = {0}; |
6021 | const char* bb = lc->int_curr_symbol; |
6022 | size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); |
6023 | if (j == size_t(-1)) |
6024 | __throw_runtime_error("locale not supported" ); |
6025 | wchar_t* wbe = wbuf + j; |
6026 | __curr_symbol_.assign(wbuf, wbe); |
6027 | if (lc->int_frac_digits != CHAR_MAX) |
6028 | __frac_digits_ = lc->int_frac_digits; |
6029 | else |
6030 | __frac_digits_ = base::do_frac_digits(); |
6031 | #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
6032 | if (lc->p_sign_posn == 0) |
6033 | #else // _LIBCPP_MSVCRT |
6034 | if (lc->int_p_sign_posn == 0) |
6035 | #endif // !_LIBCPP_MSVCRT |
6036 | __positive_sign_ = L"()" ; |
6037 | else |
6038 | { |
6039 | mb = mbstate_t(); |
6040 | bb = lc->positive_sign; |
6041 | j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); |
6042 | if (j == size_t(-1)) |
6043 | __throw_runtime_error("locale not supported" ); |
6044 | wbe = wbuf + j; |
6045 | __positive_sign_.assign(wbuf, wbe); |
6046 | } |
6047 | #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
6048 | if (lc->n_sign_posn == 0) |
6049 | #else // _LIBCPP_MSVCRT |
6050 | if (lc->int_n_sign_posn == 0) |
6051 | #endif // !_LIBCPP_MSVCRT |
6052 | __negative_sign_ = L"()" ; |
6053 | else |
6054 | { |
6055 | mb = mbstate_t(); |
6056 | bb = lc->negative_sign; |
6057 | j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); |
6058 | if (j == size_t(-1)) |
6059 | __throw_runtime_error("locale not supported" ); |
6060 | wbe = wbuf + j; |
6061 | __negative_sign_.assign(wbuf, wbe); |
6062 | } |
6063 | // Assume the positive and negative formats will want spaces in |
6064 | // the same places in curr_symbol since there's no way to |
6065 | // represent anything else. |
6066 | string_type __dummy_curr_symbol = __curr_symbol_; |
6067 | #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
6068 | __init_pat(__pos_format_, __dummy_curr_symbol, true, |
6069 | lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); |
6070 | __init_pat(__neg_format_, __curr_symbol_, true, |
6071 | lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); |
6072 | #else // _LIBCPP_MSVCRT |
6073 | __init_pat(__pos_format_, __dummy_curr_symbol, true, |
6074 | lc->int_p_cs_precedes, lc->int_p_sep_by_space, |
6075 | lc->int_p_sign_posn, L' '); |
6076 | __init_pat(__neg_format_, __curr_symbol_, true, |
6077 | lc->int_n_cs_precedes, lc->int_n_sep_by_space, |
6078 | lc->int_n_sign_posn, L' '); |
6079 | #endif // !_LIBCPP_MSVCRT |
6080 | } |
6081 | |
6082 | void __do_nothing(void*) {} |
6083 | |
6084 | void __throw_runtime_error(const char* msg) |
6085 | { |
6086 | #ifndef _LIBCPP_NO_EXCEPTIONS |
6087 | throw runtime_error(msg); |
6088 | #else |
6089 | (void)msg; |
6090 | _VSTD::abort(); |
6091 | #endif |
6092 | } |
6093 | |
6094 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>; |
6095 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>; |
6096 | |
6097 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>; |
6098 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>; |
6099 | |
6100 | template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>; |
6101 | template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>; |
6102 | |
6103 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>; |
6104 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>; |
6105 | |
6106 | template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>; |
6107 | template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>; |
6108 | |
6109 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>; |
6110 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>; |
6111 | |
6112 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>; |
6113 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>; |
6114 | |
6115 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>; |
6116 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>; |
6117 | |
6118 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>; |
6119 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>; |
6120 | |
6121 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>; |
6122 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>; |
6123 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>; |
6124 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>; |
6125 | |
6126 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>; |
6127 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>; |
6128 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>; |
6129 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>; |
6130 | |
6131 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>; |
6132 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>; |
6133 | |
6134 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>; |
6135 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>; |
6136 | |
6137 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>; |
6138 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>; |
6139 | |
6140 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>; |
6141 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>; |
6142 | |
6143 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>; |
6144 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>; |
6145 | |
6146 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>; |
6147 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>; |
6148 | |
6149 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>; |
6150 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>; |
6151 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>; |
6152 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>; |
6153 | |
6154 | _LIBCPP_END_NAMESPACE_STD |
6155 | |