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