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