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