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