~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to system/lib/libcxx/locale.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

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