1227825Stheraven//===------------------------- locale.cpp ---------------------------------===//
2227825Stheraven//
3227825Stheraven//                     The LLVM Compiler Infrastructure
4227825Stheraven//
5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
6227825Stheraven// Source Licenses. See LICENSE.TXT for details.
7227825Stheraven//
8227825Stheraven//===----------------------------------------------------------------------===//
9227825Stheraven
10232950Stheraven// On Solaris, we need to define something to make the C99 parts of localeconv
11232950Stheraven// visible.
12232950Stheraven#ifdef __sun__
13232950Stheraven#define _LCONV_C99
14232950Stheraven#endif
15232950Stheraven
16227825Stheraven#include "string"
17227825Stheraven#include "locale"
18227825Stheraven#include "codecvt"
19227825Stheraven#include "vector"
20227825Stheraven#include "algorithm"
21227825Stheraven#include "algorithm"
22227825Stheraven#include "typeinfo"
23227825Stheraven#include "type_traits"
24227825Stheraven#include "clocale"
25227825Stheraven#include "cstring"
26227825Stheraven#include "cwctype"
27227825Stheraven#include "__sso_allocator"
28249998Sdim#ifdef _WIN32
29227825Stheraven#include <support/win32/locale_win32.h>
30227825Stheraven#else // _WIN32
31227825Stheraven#include <langinfo.h>
32227825Stheraven#endif // _!WIN32
33227825Stheraven#include <stdlib.h>
34227825Stheraven
35249998Sdim// On Linux, wint_t and wchar_t have different signed-ness, and this causes
36249998Sdim// lots of noise in the build log, but no bugs that I know of.
37249998Sdim#pragma clang diagnostic ignored "-Wsign-conversion"
38249998Sdim
39227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
40227825Stheraven
41227825Stheraven#ifdef __cloc_defined
42227825Stheravenlocale_t __cloc() {
43227825Stheraven  // In theory this could create a race condition. In practice
44227825Stheraven  // the race condition is non-fatal since it will just create
45227825Stheraven  // a little resource leak. Better approach would be appreciated.
46227825Stheraven  static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
47227825Stheraven  return result;
48227825Stheraven}
49227825Stheraven#endif // __cloc_defined
50227825Stheraven
51227825Stheravennamespace {
52227825Stheraven
53227825Stheravenstruct release
54227825Stheraven{
55227825Stheraven    void operator()(locale::facet* p) {p->__release_shared();}
56227825Stheraven};
57227825Stheraven
58227825Stheraventemplate <class T, class A0>
59227825Stheraveninline
60227825StheravenT&
61227825Stheravenmake(A0 a0)
62227825Stheraven{
63227825Stheraven    static typename aligned_storage<sizeof(T)>::type buf;
64227825Stheraven    ::new (&buf) T(a0);
65227825Stheraven    return *(T*)&buf;
66227825Stheraven}
67227825Stheraven
68227825Stheraventemplate <class T, class A0, class A1>
69227825Stheraveninline
70227825StheravenT&
71227825Stheravenmake(A0 a0, A1 a1)
72227825Stheraven{
73227825Stheraven    static typename aligned_storage<sizeof(T)>::type buf;
74227825Stheraven    ::new (&buf) T(a0, a1);
75227825Stheraven    return *(T*)&buf;
76227825Stheraven}
77227825Stheraven
78227825Stheraventemplate <class T, class A0, class A1, class A2>
79227825Stheraveninline
80227825StheravenT&
81227825Stheravenmake(A0 a0, A1 a1, A2 a2)
82227825Stheraven{
83227825Stheraven    static typename aligned_storage<sizeof(T)>::type buf;
84227825Stheraven    ::new (&buf) T(a0, a1, a2);
85227825Stheraven    return *(T*)&buf;
86227825Stheraven}
87227825Stheraven
88246487Stheraventemplate <typename T, size_t N>
89246487Stheraveninline
90246487Stheraven_LIBCPP_CONSTEXPR
91246487Stheravensize_t
92246487Stheravencountof(const T (&)[N])
93246487Stheraven{
94246487Stheraven    return N;
95227825Stheraven}
96227825Stheraven
97246487Stheraventemplate <typename T>
98246487Stheraveninline
99246487Stheraven_LIBCPP_CONSTEXPR
100246487Stheravensize_t
101246487Stheravencountof(const T * const begin, const T * const end)
102246487Stheraven{
103246487Stheraven    return static_cast<size_t>(end - begin);
104246487Stheraven}
105246487Stheraven
106246487Stheraven}
107246487Stheraven
108246487Stheravenconst locale::category locale::none;
109246487Stheravenconst locale::category locale::collate;
110246487Stheravenconst locale::category locale::ctype;
111246487Stheravenconst locale::category locale::monetary;
112246487Stheravenconst locale::category locale::numeric;
113246487Stheravenconst locale::category locale::time;
114246487Stheravenconst locale::category locale::messages;
115246487Stheravenconst locale::category locale::all;
116246487Stheraven
117232950Stheraven#pragma clang diagnostic push
118232950Stheraven#pragma clang diagnostic ignored "-Wpadded"
119232950Stheraven
120227825Stheravenclass _LIBCPP_HIDDEN locale::__imp
121227825Stheraven    : public facet
122227825Stheraven{
123227825Stheraven    enum {N = 28};
124232950Stheraven    vector<facet*, __sso_allocator<facet*, N> > facets_;
125227825Stheraven    string         name_;
126227825Stheravenpublic:
127227825Stheraven    explicit __imp(size_t refs = 0);
128227825Stheraven    explicit __imp(const string& name, size_t refs = 0);
129227825Stheraven    __imp(const __imp&);
130227825Stheraven    __imp(const __imp&, const string&, locale::category c);
131227825Stheraven    __imp(const __imp& other, const __imp& one, locale::category c);
132227825Stheraven    __imp(const __imp&, facet* f, long id);
133227825Stheraven    ~__imp();
134227825Stheraven
135227825Stheraven    const string& name() const {return name_;}
136232950Stheraven    bool has_facet(long id) const
137232950Stheraven        {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
138227825Stheraven    const locale::facet* use_facet(long id) const;
139227825Stheraven
140227825Stheraven    static const locale& make_classic();
141227825Stheraven    static       locale& make_global();
142227825Stheravenprivate:
143227825Stheraven    void install(facet* f, long id);
144227825Stheraven    template <class F> void install(F* f) {install(f, f->id.__get());}
145227825Stheraven    template <class F> void install_from(const __imp& other);
146227825Stheraven};
147227825Stheraven
148232950Stheraven#pragma clang diagnostic pop
149232950Stheraven
150227825Stheravenlocale::__imp::__imp(size_t refs)
151227825Stheraven    : facet(refs),
152232950Stheraven      facets_(N),
153232950Stheraven      name_("C")
154227825Stheraven{
155227825Stheraven    facets_.clear();
156232950Stheraven    install(&make<_VSTD::collate<char> >(1u));
157232950Stheraven    install(&make<_VSTD::collate<wchar_t> >(1u));
158232950Stheraven    install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
159232950Stheraven    install(&make<_VSTD::ctype<wchar_t> >(1u));
160232950Stheraven    install(&make<codecvt<char, char, mbstate_t> >(1u));
161232950Stheraven    install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
162232950Stheraven    install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
163232950Stheraven    install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
164232950Stheraven    install(&make<numpunct<char> >(1u));
165232950Stheraven    install(&make<numpunct<wchar_t> >(1u));
166232950Stheraven    install(&make<num_get<char> >(1u));
167232950Stheraven    install(&make<num_get<wchar_t> >(1u));
168232950Stheraven    install(&make<num_put<char> >(1u));
169232950Stheraven    install(&make<num_put<wchar_t> >(1u));
170232950Stheraven    install(&make<moneypunct<char, false> >(1u));
171232950Stheraven    install(&make<moneypunct<char, true> >(1u));
172232950Stheraven    install(&make<moneypunct<wchar_t, false> >(1u));
173232950Stheraven    install(&make<moneypunct<wchar_t, true> >(1u));
174232950Stheraven    install(&make<money_get<char> >(1u));
175232950Stheraven    install(&make<money_get<wchar_t> >(1u));
176232950Stheraven    install(&make<money_put<char> >(1u));
177232950Stheraven    install(&make<money_put<wchar_t> >(1u));
178232950Stheraven    install(&make<time_get<char> >(1u));
179232950Stheraven    install(&make<time_get<wchar_t> >(1u));
180232950Stheraven    install(&make<time_put<char> >(1u));
181232950Stheraven    install(&make<time_put<wchar_t> >(1u));
182232950Stheraven    install(&make<_VSTD::messages<char> >(1u));
183232950Stheraven    install(&make<_VSTD::messages<wchar_t> >(1u));
184227825Stheraven}
185227825Stheraven
186227825Stheravenlocale::__imp::__imp(const string& name, size_t refs)
187227825Stheraven    : facet(refs),
188232950Stheraven      facets_(N),
189232950Stheraven      name_(name)
190227825Stheraven{
191227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
192227825Stheraven    try
193227825Stheraven    {
194227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
195227825Stheraven        facets_ = locale::classic().__locale_->facets_;
196227825Stheraven        for (unsigned i = 0; i < facets_.size(); ++i)
197227825Stheraven            if (facets_[i])
198227825Stheraven                facets_[i]->__add_shared();
199227825Stheraven        install(new collate_byname<char>(name_));
200227825Stheraven        install(new collate_byname<wchar_t>(name_));
201227825Stheraven        install(new ctype_byname<char>(name_));
202227825Stheraven        install(new ctype_byname<wchar_t>(name_));
203227825Stheraven        install(new codecvt_byname<char, char, mbstate_t>(name_));
204227825Stheraven        install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
205227825Stheraven        install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
206227825Stheraven        install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
207227825Stheraven        install(new numpunct_byname<char>(name_));
208227825Stheraven        install(new numpunct_byname<wchar_t>(name_));
209227825Stheraven        install(new moneypunct_byname<char, false>(name_));
210227825Stheraven        install(new moneypunct_byname<char, true>(name_));
211227825Stheraven        install(new moneypunct_byname<wchar_t, false>(name_));
212227825Stheraven        install(new moneypunct_byname<wchar_t, true>(name_));
213227825Stheraven        install(new time_get_byname<char>(name_));
214227825Stheraven        install(new time_get_byname<wchar_t>(name_));
215227825Stheraven        install(new time_put_byname<char>(name_));
216227825Stheraven        install(new time_put_byname<wchar_t>(name_));
217227825Stheraven        install(new messages_byname<char>(name_));
218227825Stheraven        install(new messages_byname<wchar_t>(name_));
219227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
220227825Stheraven    }
221227825Stheraven    catch (...)
222227825Stheraven    {
223227825Stheraven        for (unsigned i = 0; i < facets_.size(); ++i)
224227825Stheraven            if (facets_[i])
225227825Stheraven                facets_[i]->__release_shared();
226227825Stheraven        throw;
227227825Stheraven    }
228227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
229227825Stheraven}
230227825Stheraven
231246487Stheraven// NOTE avoid the `base class should be explicitly initialized in the
232246487Stheraven// copy constructor` warning emitted by GCC
233253159Stheraven#if defined(__clang__) || _GNUC_VER >= 406
234246487Stheraven#pragma GCC diagnostic push
235246487Stheraven#pragma GCC diagnostic ignored "-Wextra"
236253159Stheraven#endif
237246487Stheraven
238227825Stheravenlocale::__imp::__imp(const __imp& other)
239232950Stheraven    : facets_(max<size_t>(N, other.facets_.size())),
240232950Stheraven      name_(other.name_)
241227825Stheraven{
242227825Stheraven    facets_ = other.facets_;
243227825Stheraven    for (unsigned i = 0; i < facets_.size(); ++i)
244227825Stheraven        if (facets_[i])
245227825Stheraven            facets_[i]->__add_shared();
246227825Stheraven}
247227825Stheraven
248253159Stheraven#if defined(__clang__) || _GNUC_VER >= 406
249246487Stheraven#pragma GCC diagnostic pop
250253159Stheraven#endif
251246487Stheraven
252227825Stheravenlocale::__imp::__imp(const __imp& other, const string& name, locale::category c)
253232950Stheraven    : facets_(N),
254232950Stheraven      name_("*")
255227825Stheraven{
256227825Stheraven    facets_ = other.facets_;
257227825Stheraven    for (unsigned i = 0; i < facets_.size(); ++i)
258227825Stheraven        if (facets_[i])
259227825Stheraven            facets_[i]->__add_shared();
260227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
261227825Stheraven    try
262227825Stheraven    {
263227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
264227825Stheraven        if (c & locale::collate)
265227825Stheraven        {
266227825Stheraven            install(new collate_byname<char>(name));
267227825Stheraven            install(new collate_byname<wchar_t>(name));
268227825Stheraven        }
269227825Stheraven        if (c & locale::ctype)
270227825Stheraven        {
271227825Stheraven            install(new ctype_byname<char>(name));
272227825Stheraven            install(new ctype_byname<wchar_t>(name));
273227825Stheraven            install(new codecvt_byname<char, char, mbstate_t>(name));
274227825Stheraven            install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
275227825Stheraven            install(new codecvt_byname<char16_t, char, mbstate_t>(name));
276227825Stheraven            install(new codecvt_byname<char32_t, char, mbstate_t>(name));
277227825Stheraven        }
278227825Stheraven        if (c & locale::monetary)
279227825Stheraven        {
280227825Stheraven            install(new moneypunct_byname<char, false>(name));
281227825Stheraven            install(new moneypunct_byname<char, true>(name));
282227825Stheraven            install(new moneypunct_byname<wchar_t, false>(name));
283227825Stheraven            install(new moneypunct_byname<wchar_t, true>(name));
284227825Stheraven        }
285227825Stheraven        if (c & locale::numeric)
286227825Stheraven        {
287227825Stheraven            install(new numpunct_byname<char>(name));
288227825Stheraven            install(new numpunct_byname<wchar_t>(name));
289227825Stheraven        }
290227825Stheraven        if (c & locale::time)
291227825Stheraven        {
292227825Stheraven            install(new time_get_byname<char>(name));
293227825Stheraven            install(new time_get_byname<wchar_t>(name));
294227825Stheraven            install(new time_put_byname<char>(name));
295227825Stheraven            install(new time_put_byname<wchar_t>(name));
296227825Stheraven        }
297227825Stheraven        if (c & locale::messages)
298227825Stheraven        {
299227825Stheraven            install(new messages_byname<char>(name));
300227825Stheraven            install(new messages_byname<wchar_t>(name));
301227825Stheraven        }
302227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
303227825Stheraven    }
304227825Stheraven    catch (...)
305227825Stheraven    {
306227825Stheraven        for (unsigned i = 0; i < facets_.size(); ++i)
307227825Stheraven            if (facets_[i])
308227825Stheraven                facets_[i]->__release_shared();
309227825Stheraven        throw;
310227825Stheraven    }
311227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
312227825Stheraven}
313227825Stheraven
314227825Stheraventemplate<class F>
315227825Stheraveninline
316227825Stheravenvoid
317227825Stheravenlocale::__imp::install_from(const locale::__imp& one)
318227825Stheraven{
319227825Stheraven    long id = F::id.__get();
320227825Stheraven    install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
321227825Stheraven}
322227825Stheraven
323227825Stheravenlocale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
324232950Stheraven    : facets_(N),
325232950Stheraven      name_("*")
326227825Stheraven{
327227825Stheraven    facets_ = other.facets_;
328227825Stheraven    for (unsigned i = 0; i < facets_.size(); ++i)
329227825Stheraven        if (facets_[i])
330227825Stheraven            facets_[i]->__add_shared();
331227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
332227825Stheraven    try
333227825Stheraven    {
334227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
335227825Stheraven        if (c & locale::collate)
336227825Stheraven        {
337227825Stheraven            install_from<_VSTD::collate<char> >(one);
338227825Stheraven            install_from<_VSTD::collate<wchar_t> >(one);
339227825Stheraven        }
340227825Stheraven        if (c & locale::ctype)
341227825Stheraven        {
342227825Stheraven            install_from<_VSTD::ctype<char> >(one);
343227825Stheraven            install_from<_VSTD::ctype<wchar_t> >(one);
344227825Stheraven            install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
345227825Stheraven            install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
346227825Stheraven            install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
347227825Stheraven            install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
348227825Stheraven        }
349227825Stheraven        if (c & locale::monetary)
350227825Stheraven        {
351227825Stheraven            install_from<moneypunct<char, false> >(one);
352227825Stheraven            install_from<moneypunct<char, true> >(one);
353227825Stheraven            install_from<moneypunct<wchar_t, false> >(one);
354227825Stheraven            install_from<moneypunct<wchar_t, true> >(one);
355227825Stheraven            install_from<money_get<char> >(one);
356227825Stheraven            install_from<money_get<wchar_t> >(one);
357227825Stheraven            install_from<money_put<char> >(one);
358227825Stheraven            install_from<money_put<wchar_t> >(one);
359227825Stheraven        }
360227825Stheraven        if (c & locale::numeric)
361227825Stheraven        {
362227825Stheraven            install_from<numpunct<char> >(one);
363227825Stheraven            install_from<numpunct<wchar_t> >(one);
364227825Stheraven            install_from<num_get<char> >(one);
365227825Stheraven            install_from<num_get<wchar_t> >(one);
366227825Stheraven            install_from<num_put<char> >(one);
367227825Stheraven            install_from<num_put<wchar_t> >(one);
368227825Stheraven        }
369227825Stheraven        if (c & locale::time)
370227825Stheraven        {
371227825Stheraven            install_from<time_get<char> >(one);
372227825Stheraven            install_from<time_get<wchar_t> >(one);
373227825Stheraven            install_from<time_put<char> >(one);
374227825Stheraven            install_from<time_put<wchar_t> >(one);
375227825Stheraven        }
376227825Stheraven        if (c & locale::messages)
377227825Stheraven        {
378227825Stheraven            install_from<_VSTD::messages<char> >(one);
379227825Stheraven            install_from<_VSTD::messages<wchar_t> >(one);
380227825Stheraven        }
381227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
382227825Stheraven    }
383227825Stheraven    catch (...)
384227825Stheraven    {
385227825Stheraven        for (unsigned i = 0; i < facets_.size(); ++i)
386227825Stheraven            if (facets_[i])
387227825Stheraven                facets_[i]->__release_shared();
388227825Stheraven        throw;
389227825Stheraven    }
390227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
391227825Stheraven}
392227825Stheraven
393227825Stheravenlocale::__imp::__imp(const __imp& other, facet* f, long id)
394232950Stheraven    : facets_(max<size_t>(N, other.facets_.size()+1)),
395232950Stheraven      name_("*")
396227825Stheraven{
397227825Stheraven    f->__add_shared();
398227825Stheraven    unique_ptr<facet, release> hold(f);
399227825Stheraven    facets_ = other.facets_;
400227825Stheraven    for (unsigned i = 0; i < other.facets_.size(); ++i)
401227825Stheraven        if (facets_[i])
402227825Stheraven            facets_[i]->__add_shared();
403227825Stheraven    install(hold.get(), id);
404227825Stheraven}
405227825Stheraven
406227825Stheravenlocale::__imp::~__imp()
407227825Stheraven{
408227825Stheraven    for (unsigned i = 0; i < facets_.size(); ++i)
409227825Stheraven        if (facets_[i])
410227825Stheraven            facets_[i]->__release_shared();
411227825Stheraven}
412227825Stheraven
413227825Stheravenvoid
414227825Stheravenlocale::__imp::install(facet* f, long id)
415227825Stheraven{
416227825Stheraven    f->__add_shared();
417227825Stheraven    unique_ptr<facet, release> hold(f);
418232950Stheraven    if (static_cast<size_t>(id) >= facets_.size())
419232950Stheraven        facets_.resize(static_cast<size_t>(id+1));
420232950Stheraven    if (facets_[static_cast<size_t>(id)])
421232950Stheraven        facets_[static_cast<size_t>(id)]->__release_shared();
422232950Stheraven    facets_[static_cast<size_t>(id)] = hold.release();
423227825Stheraven}
424227825Stheraven
425227825Stheravenconst locale::facet*
426227825Stheravenlocale::__imp::use_facet(long id) const
427227825Stheraven{
428227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
429227825Stheraven    if (!has_facet(id))
430227825Stheraven        throw bad_cast();
431227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
432232950Stheraven    return facets_[static_cast<size_t>(id)];
433227825Stheraven}
434227825Stheraven
435227825Stheraven// locale
436227825Stheraven
437227825Stheravenconst locale&
438227825Stheravenlocale::__imp::make_classic()
439227825Stheraven{
440227825Stheraven    // only one thread can get in here and it only gets in once
441227825Stheraven    static aligned_storage<sizeof(locale)>::type buf;
442227825Stheraven    locale* c = (locale*)&buf;
443232950Stheraven    c->__locale_ = &make<__imp>(1u);
444227825Stheraven    return *c;
445227825Stheraven}
446227825Stheraven
447227825Stheravenconst locale&
448227825Stheravenlocale::classic()
449227825Stheraven{
450227825Stheraven    static const locale& c = __imp::make_classic();
451227825Stheraven    return c;
452227825Stheraven}
453227825Stheraven
454227825Stheravenlocale&
455227825Stheravenlocale::__imp::make_global()
456227825Stheraven{
457227825Stheraven    // only one thread can get in here and it only gets in once
458227825Stheraven    static aligned_storage<sizeof(locale)>::type buf;
459227825Stheraven    ::new (&buf) locale(locale::classic());
460227825Stheraven    return *(locale*)&buf;
461227825Stheraven}
462227825Stheraven
463227825Stheravenlocale&
464227825Stheravenlocale::__global()
465227825Stheraven{
466227825Stheraven    static locale& g = __imp::make_global();
467227825Stheraven    return g;
468227825Stheraven}
469227825Stheraven
470227825Stheravenlocale::locale()  _NOEXCEPT
471227825Stheraven    : __locale_(__global().__locale_)
472227825Stheraven{
473227825Stheraven    __locale_->__add_shared();
474227825Stheraven}
475227825Stheraven
476227825Stheravenlocale::locale(const locale& l)  _NOEXCEPT
477227825Stheraven    : __locale_(l.__locale_)
478227825Stheraven{
479227825Stheraven    __locale_->__add_shared();
480227825Stheraven}
481227825Stheraven
482227825Stheravenlocale::~locale()
483227825Stheraven{
484227825Stheraven    __locale_->__release_shared();
485227825Stheraven}
486227825Stheraven
487227825Stheravenconst locale&
488227825Stheravenlocale::operator=(const locale& other)  _NOEXCEPT
489227825Stheraven{
490227825Stheraven    other.__locale_->__add_shared();
491227825Stheraven    __locale_->__release_shared();
492227825Stheraven    __locale_ = other.__locale_;
493227825Stheraven    return *this;
494227825Stheraven}
495227825Stheraven
496227825Stheravenlocale::locale(const char* name)
497227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
498227825Stheraven    : __locale_(name ? new __imp(name)
499227825Stheraven                     : throw runtime_error("locale constructed with null"))
500227825Stheraven#else  // _LIBCPP_NO_EXCEPTIONS
501227825Stheraven    : __locale_(new __imp(name))
502227825Stheraven#endif
503227825Stheraven{
504227825Stheraven    __locale_->__add_shared();
505227825Stheraven}
506227825Stheraven
507227825Stheravenlocale::locale(const string& name)
508227825Stheraven    : __locale_(new __imp(name))
509227825Stheraven{
510227825Stheraven    __locale_->__add_shared();
511227825Stheraven}
512227825Stheraven
513227825Stheravenlocale::locale(const locale& other, const char* name, category c)
514227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
515227825Stheraven    : __locale_(name ? new __imp(*other.__locale_, name, c)
516227825Stheraven                     : throw runtime_error("locale constructed with null"))
517227825Stheraven#else  // _LIBCPP_NO_EXCEPTIONS
518227825Stheraven    : __locale_(new __imp(*other.__locale_, name, c))
519227825Stheraven#endif
520227825Stheraven{
521227825Stheraven    __locale_->__add_shared();
522227825Stheraven}
523227825Stheraven
524227825Stheravenlocale::locale(const locale& other, const string& name, category c)
525227825Stheraven    : __locale_(new __imp(*other.__locale_, name, c))
526227825Stheraven{
527227825Stheraven    __locale_->__add_shared();
528227825Stheraven}
529227825Stheraven
530227825Stheravenlocale::locale(const locale& other, const locale& one, category c)
531227825Stheraven    : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
532227825Stheraven{
533227825Stheraven    __locale_->__add_shared();
534227825Stheraven}
535227825Stheraven
536227825Stheravenstring
537227825Stheravenlocale::name() const
538227825Stheraven{
539227825Stheraven    return __locale_->name();
540227825Stheraven}
541227825Stheraven
542227825Stheravenvoid
543227825Stheravenlocale::__install_ctor(const locale& other, facet* f, long id)
544227825Stheraven{
545227825Stheraven    if (f)
546227825Stheraven        __locale_ = new __imp(*other.__locale_, f, id);
547227825Stheraven    else
548227825Stheraven        __locale_ = other.__locale_;
549227825Stheraven    __locale_->__add_shared();
550227825Stheraven}
551227825Stheraven
552227825Stheravenlocale
553227825Stheravenlocale::global(const locale& loc)
554227825Stheraven{
555227825Stheraven    locale& g = __global();
556227825Stheraven    locale r = g;
557227825Stheraven    g = loc;
558227825Stheraven    if (g.name() != "*")
559227825Stheraven        setlocale(LC_ALL, g.name().c_str());
560227825Stheraven    return r;
561227825Stheraven}
562227825Stheraven
563227825Stheravenbool
564227825Stheravenlocale::has_facet(id& x) const
565227825Stheraven{
566227825Stheraven    return __locale_->has_facet(x.__get());
567227825Stheraven}
568227825Stheraven
569227825Stheravenconst locale::facet*
570227825Stheravenlocale::use_facet(id& x) const
571227825Stheraven{
572227825Stheraven    return __locale_->use_facet(x.__get());
573227825Stheraven}
574227825Stheraven
575227825Stheravenbool
576227825Stheravenlocale::operator==(const locale& y) const
577227825Stheraven{
578227825Stheraven    return (__locale_ == y.__locale_)
579227825Stheraven        || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
580227825Stheraven}
581227825Stheraven
582227825Stheraven// locale::facet
583227825Stheraven
584227825Stheravenlocale::facet::~facet()
585227825Stheraven{
586227825Stheraven}
587227825Stheraven
588227825Stheravenvoid
589227825Stheravenlocale::facet::__on_zero_shared() _NOEXCEPT
590227825Stheraven{
591227825Stheraven    delete this;
592227825Stheraven}
593227825Stheraven
594227825Stheraven// locale::id
595227825Stheraven
596227825Stheravenint32_t locale::id::__next_id = 0;
597227825Stheraven
598227825Stheravennamespace
599227825Stheraven{
600227825Stheraven
601227825Stheravenclass __fake_bind
602227825Stheraven{
603227825Stheraven    locale::id* id_;
604227825Stheraven    void (locale::id::* pmf_)();
605227825Stheravenpublic:
606227825Stheraven    __fake_bind(void (locale::id::* pmf)(), locale::id* id)
607227825Stheraven        : id_(id), pmf_(pmf) {}
608227825Stheraven
609227825Stheraven    void operator()() const
610227825Stheraven    {
611227825Stheraven        (id_->*pmf_)();
612227825Stheraven    }
613227825Stheraven};
614227825Stheraven
615227825Stheraven}
616227825Stheraven
617227825Stheravenlong
618227825Stheravenlocale::id::__get()
619227825Stheraven{
620227825Stheraven    call_once(__flag_, __fake_bind(&locale::id::__init, this));
621227825Stheraven    return __id_ - 1;
622227825Stheraven}
623227825Stheraven
624227825Stheravenvoid
625227825Stheravenlocale::id::__init()
626227825Stheraven{
627227825Stheraven    __id_ = __sync_add_and_fetch(&__next_id, 1);
628227825Stheraven}
629227825Stheraven
630227825Stheraven// template <> class collate_byname<char>
631227825Stheraven
632227825Stheravencollate_byname<char>::collate_byname(const char* n, size_t refs)
633227825Stheraven    : collate<char>(refs),
634227825Stheraven      __l(newlocale(LC_ALL_MASK, n, 0))
635227825Stheraven{
636227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
637227825Stheraven    if (__l == 0)
638227825Stheraven        throw runtime_error("collate_byname<char>::collate_byname"
639227825Stheraven                            " failed to construct for " + string(n));
640227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
641227825Stheraven}
642227825Stheraven
643227825Stheravencollate_byname<char>::collate_byname(const string& name, size_t refs)
644227825Stheraven    : collate<char>(refs),
645227825Stheraven      __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
646227825Stheraven{
647227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
648227825Stheraven    if (__l == 0)
649227825Stheraven        throw runtime_error("collate_byname<char>::collate_byname"
650227825Stheraven                            " failed to construct for " + name);
651227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
652227825Stheraven}
653227825Stheraven
654227825Stheravencollate_byname<char>::~collate_byname()
655227825Stheraven{
656227825Stheraven    freelocale(__l);
657227825Stheraven}
658227825Stheraven
659227825Stheravenint
660227825Stheravencollate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
661227825Stheraven                                 const char_type* __lo2, const char_type* __hi2) const
662227825Stheraven{
663227825Stheraven    string_type lhs(__lo1, __hi1);
664227825Stheraven    string_type rhs(__lo2, __hi2);
665227825Stheraven    int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
666227825Stheraven    if (r < 0)
667227825Stheraven        return -1;
668227825Stheraven    if (r > 0)
669227825Stheraven        return 1;
670227825Stheraven    return r;
671227825Stheraven}
672227825Stheraven
673227825Stheravencollate_byname<char>::string_type
674227825Stheravencollate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
675227825Stheraven{
676227825Stheraven    const string_type in(lo, hi);
677227825Stheraven    string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
678227825Stheraven    strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
679227825Stheraven    return out;
680227825Stheraven}
681227825Stheraven
682227825Stheraven// template <> class collate_byname<wchar_t>
683227825Stheraven
684227825Stheravencollate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
685227825Stheraven    : collate<wchar_t>(refs),
686227825Stheraven      __l(newlocale(LC_ALL_MASK, n, 0))
687227825Stheraven{
688227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
689227825Stheraven    if (__l == 0)
690227825Stheraven        throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
691227825Stheraven                            " failed to construct for " + string(n));
692227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
693227825Stheraven}
694227825Stheraven
695227825Stheravencollate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
696227825Stheraven    : collate<wchar_t>(refs),
697227825Stheraven      __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
698227825Stheraven{
699227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
700227825Stheraven    if (__l == 0)
701227825Stheraven        throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
702227825Stheraven                            " failed to construct for " + name);
703227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
704227825Stheraven}
705227825Stheraven
706227825Stheravencollate_byname<wchar_t>::~collate_byname()
707227825Stheraven{
708227825Stheraven    freelocale(__l);
709227825Stheraven}
710227825Stheraven
711227825Stheravenint
712227825Stheravencollate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
713227825Stheraven                                 const char_type* __lo2, const char_type* __hi2) const
714227825Stheraven{
715227825Stheraven    string_type lhs(__lo1, __hi1);
716227825Stheraven    string_type rhs(__lo2, __hi2);
717227825Stheraven    int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
718227825Stheraven    if (r < 0)
719227825Stheraven        return -1;
720227825Stheraven    if (r > 0)
721227825Stheraven        return 1;
722227825Stheraven    return r;
723227825Stheraven}
724227825Stheraven
725227825Stheravencollate_byname<wchar_t>::string_type
726227825Stheravencollate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
727227825Stheraven{
728227825Stheraven    const string_type in(lo, hi);
729227825Stheraven    string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
730227825Stheraven    wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
731227825Stheraven    return out;
732227825Stheraven}
733227825Stheraven
734227825Stheraven// template <> class ctype<wchar_t>;
735227825Stheraven
736246487Stheravenconst ctype_base::mask ctype_base::space;
737246487Stheravenconst ctype_base::mask ctype_base::print;
738246487Stheravenconst ctype_base::mask ctype_base::cntrl;
739246487Stheravenconst ctype_base::mask ctype_base::upper;
740246487Stheravenconst ctype_base::mask ctype_base::lower;
741246487Stheravenconst ctype_base::mask ctype_base::alpha;
742246487Stheravenconst ctype_base::mask ctype_base::digit;
743246487Stheravenconst ctype_base::mask ctype_base::punct;
744246487Stheravenconst ctype_base::mask ctype_base::xdigit;
745246487Stheravenconst ctype_base::mask ctype_base::blank;
746246487Stheravenconst ctype_base::mask ctype_base::alnum;
747246487Stheravenconst ctype_base::mask ctype_base::graph;
748246487Stheraven
749227825Stheravenlocale::id ctype<wchar_t>::id;
750227825Stheraven
751227825Stheravenctype<wchar_t>::~ctype()
752227825Stheraven{
753227825Stheraven}
754227825Stheraven
755227825Stheravenbool
756227825Stheravenctype<wchar_t>::do_is(mask m, char_type c) const
757227825Stheraven{
758227825Stheraven    return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
759227825Stheraven}
760227825Stheraven
761227825Stheravenconst wchar_t*
762227825Stheravenctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
763227825Stheraven{
764227825Stheraven    for (; low != high; ++low, ++vec)
765227825Stheraven        *vec = static_cast<mask>(isascii(*low) ?
766227825Stheraven                                   ctype<char>::classic_table()[*low] : 0);
767227825Stheraven    return low;
768227825Stheraven}
769227825Stheraven
770227825Stheravenconst wchar_t*
771227825Stheravenctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
772227825Stheraven{
773227825Stheraven    for (; low != high; ++low)
774227825Stheraven        if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
775227825Stheraven            break;
776227825Stheraven    return low;
777227825Stheraven}
778227825Stheraven
779227825Stheravenconst wchar_t*
780227825Stheravenctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
781227825Stheraven{
782227825Stheraven    for (; low != high; ++low)
783227825Stheraven        if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
784227825Stheraven            break;
785227825Stheraven    return low;
786227825Stheraven}
787227825Stheraven
788227825Stheravenwchar_t
789227825Stheravenctype<wchar_t>::do_toupper(char_type c) const
790227825Stheraven{
791227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
792227825Stheraven    return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
793253159Stheraven#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
794227825Stheraven    return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
795227825Stheraven#else
796227825Stheraven    return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
797227825Stheraven#endif
798227825Stheraven}
799227825Stheraven
800227825Stheravenconst wchar_t*
801227825Stheravenctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
802227825Stheraven{
803227825Stheraven    for (; low != high; ++low)
804227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
805227825Stheraven        *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
806253159Stheraven#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
807227825Stheraven        *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
808227825Stheraven                             : *low;
809227825Stheraven#else
810227825Stheraven        *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
811227825Stheraven#endif
812227825Stheraven    return low;
813227825Stheraven}
814227825Stheraven
815227825Stheravenwchar_t
816227825Stheravenctype<wchar_t>::do_tolower(char_type c) const
817227825Stheraven{
818227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
819227825Stheraven    return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
820253159Stheraven#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
821227825Stheraven    return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
822227825Stheraven#else
823227825Stheraven    return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
824227825Stheraven#endif
825227825Stheraven}
826227825Stheraven
827227825Stheravenconst wchar_t*
828227825Stheravenctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
829227825Stheraven{
830227825Stheraven    for (; low != high; ++low)
831227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
832227825Stheraven        *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
833253159Stheraven#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
834227825Stheraven        *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
835227825Stheraven                             : *low;
836227825Stheraven#else
837227825Stheraven        *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
838227825Stheraven#endif
839227825Stheraven    return low;
840227825Stheraven}
841227825Stheraven
842227825Stheravenwchar_t
843227825Stheravenctype<wchar_t>::do_widen(char c) const
844227825Stheraven{
845227825Stheraven    return c;
846227825Stheraven}
847227825Stheraven
848227825Stheravenconst char*
849227825Stheravenctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
850227825Stheraven{
851227825Stheraven    for (; low != high; ++low, ++dest)
852227825Stheraven        *dest = *low;
853227825Stheraven    return low;
854227825Stheraven}
855227825Stheraven
856227825Stheravenchar
857227825Stheravenctype<wchar_t>::do_narrow(char_type c, char dfault) const
858227825Stheraven{
859227825Stheraven    if (isascii(c))
860227825Stheraven        return static_cast<char>(c);
861227825Stheraven    return dfault;
862227825Stheraven}
863227825Stheraven
864227825Stheravenconst wchar_t*
865227825Stheravenctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
866227825Stheraven{
867227825Stheraven    for (; low != high; ++low, ++dest)
868227825Stheraven        if (isascii(*low))
869232950Stheraven            *dest = static_cast<char>(*low);
870227825Stheraven        else
871227825Stheraven            *dest = dfault;
872227825Stheraven    return low;
873227825Stheraven}
874227825Stheraven
875227825Stheraven// template <> class ctype<char>;
876227825Stheraven
877227825Stheravenlocale::id ctype<char>::id;
878227825Stheraven
879227825Stheravenctype<char>::ctype(const mask* tab, bool del, size_t refs)
880227825Stheraven    : locale::facet(refs),
881227825Stheraven      __tab_(tab),
882227825Stheraven      __del_(del)
883227825Stheraven{
884227825Stheraven  if (__tab_ == 0)
885227825Stheraven      __tab_ = classic_table();
886227825Stheraven}
887227825Stheraven
888227825Stheravenctype<char>::~ctype()
889227825Stheraven{
890227825Stheraven    if (__tab_ && __del_)
891227825Stheraven        delete [] __tab_;
892227825Stheraven}
893227825Stheraven
894227825Stheravenchar
895227825Stheravenctype<char>::do_toupper(char_type c) const
896227825Stheraven{
897227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
898232950Stheraven    return isascii(c) ?
899232950Stheraven      static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
900253159Stheraven#elif defined(__NetBSD__)
901253159Stheraven    return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
902249998Sdim#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
903249998Sdim    return isascii(c) ?
904253159Stheraven      static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
905227825Stheraven#else
906227825Stheraven    return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
907227825Stheraven#endif
908227825Stheraven}
909227825Stheraven
910227825Stheravenconst char*
911227825Stheravenctype<char>::do_toupper(char_type* low, const char_type* high) const
912227825Stheraven{
913227825Stheraven    for (; low != high; ++low)
914227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
915232950Stheraven        *low = isascii(*low) ?
916232950Stheraven          static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
917253159Stheraven#elif defined(__NetBSD__)
918253159Stheraven        *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
919249998Sdim#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
920249998Sdim        *low = isascii(*low) ?
921249998Sdim          static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
922227825Stheraven#else
923227825Stheraven        *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
924227825Stheraven#endif
925227825Stheraven    return low;
926227825Stheraven}
927227825Stheraven
928227825Stheravenchar
929227825Stheravenctype<char>::do_tolower(char_type c) const
930227825Stheraven{
931227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
932232950Stheraven    return isascii(c) ?
933232950Stheraven      static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
934253159Stheraven#elif defined(__NetBSD__)
935253159Stheraven    return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
936253159Stheraven#elif defined(__GLIBC__) || defined(EMSCRIPTEN) || defined(__NetBSD__)
937249998Sdim    return isascii(c) ?
938249998Sdim      static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
939227825Stheraven#else
940227825Stheraven    return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
941227825Stheraven#endif
942227825Stheraven}
943227825Stheraven
944227825Stheravenconst char*
945227825Stheravenctype<char>::do_tolower(char_type* low, const char_type* high) const
946227825Stheraven{
947227825Stheraven    for (; low != high; ++low)
948227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
949232950Stheraven        *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
950253159Stheraven#elif defined(__NetBSD__)
951253159Stheraven        *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
952249998Sdim#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
953249998Sdim        *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
954227825Stheraven#else
955227825Stheraven        *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
956227825Stheraven#endif
957227825Stheraven    return low;
958227825Stheraven}
959227825Stheraven
960227825Stheravenchar
961227825Stheravenctype<char>::do_widen(char c) const
962227825Stheraven{
963227825Stheraven    return c;
964227825Stheraven}
965227825Stheraven
966227825Stheravenconst char*
967227825Stheravenctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
968227825Stheraven{
969227825Stheraven    for (; low != high; ++low, ++dest)
970227825Stheraven        *dest = *low;
971227825Stheraven    return low;
972227825Stheraven}
973227825Stheraven
974227825Stheravenchar
975227825Stheravenctype<char>::do_narrow(char_type c, char dfault) const
976227825Stheraven{
977227825Stheraven    if (isascii(c))
978227825Stheraven        return static_cast<char>(c);
979227825Stheraven    return dfault;
980227825Stheraven}
981227825Stheraven
982227825Stheravenconst char*
983227825Stheravenctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
984227825Stheraven{
985227825Stheraven    for (; low != high; ++low, ++dest)
986227825Stheraven        if (isascii(*low))
987227825Stheraven            *dest = *low;
988227825Stheraven        else
989227825Stheraven            *dest = dfault;
990227825Stheraven    return low;
991227825Stheraven}
992227825Stheraven
993249998Sdim#ifdef EMSCRIPTEN
994249998Sdimextern "C" const unsigned short ** __ctype_b_loc();
995249998Sdimextern "C" const int ** __ctype_tolower_loc();
996249998Sdimextern "C" const int ** __ctype_toupper_loc();
997249998Sdim#endif
998249998Sdim
999227825Stheravenconst ctype<char>::mask*
1000227825Stheravenctype<char>::classic_table()  _NOEXCEPT
1001227825Stheraven{
1002227825Stheraven#if defined(__APPLE__) || defined(__FreeBSD__)
1003227825Stheraven    return _DefaultRuneLocale.__runetype;
1004253159Stheraven#elif defined(__NetBSD__)
1005253159Stheraven    return _C_ctype_tab_ + 1;
1006227825Stheraven#elif defined(__GLIBC__)
1007227825Stheraven    return __cloc()->__ctype_b;
1008232950Stheraven#elif __sun__
1009232950Stheraven    return __ctype_mask;
1010249998Sdim#elif defined(_WIN32)
1011227825Stheraven    return _ctype+1; // internal ctype mask table defined in msvcrt.dll
1012227825Stheraven// This is assumed to be safe, which is a nonsense assumption because we're
1013227825Stheraven// going to end up dereferencing it later...
1014249998Sdim#elif defined(EMSCRIPTEN)
1015249998Sdim    return *__ctype_b_loc();
1016227825Stheraven#else
1017232950Stheraven    // Platform not supported: abort so the person doing the port knows what to
1018232950Stheraven    // fix
1019232950Stheraven# warning  ctype<char>::classic_table() is not implemented
1020232950Stheraven    abort();
1021227825Stheraven    return NULL;
1022227825Stheraven#endif
1023227825Stheraven}
1024227825Stheraven
1025227825Stheraven#if defined(__GLIBC__)
1026227825Stheravenconst int*
1027227825Stheravenctype<char>::__classic_lower_table() _NOEXCEPT
1028227825Stheraven{
1029227825Stheraven    return __cloc()->__ctype_tolower;
1030227825Stheraven}
1031227825Stheraven
1032227825Stheravenconst int*
1033227825Stheravenctype<char>::__classic_upper_table() _NOEXCEPT
1034227825Stheraven{
1035227825Stheraven    return __cloc()->__ctype_toupper;
1036227825Stheraven}
1037253159Stheraven#elif __NetBSD__
1038253159Stheravenconst short*
1039253159Stheravenctype<char>::__classic_lower_table() _NOEXCEPT
1040253159Stheraven{
1041253159Stheraven    return _C_tolower_tab_ + 1;
1042253159Stheraven}
1043227825Stheraven
1044253159Stheravenconst short*
1045253159Stheravenctype<char>::__classic_upper_table() _NOEXCEPT
1046253159Stheraven{
1047253159Stheraven    return _C_toupper_tab_ + 1;
1048253159Stheraven}
1049253159Stheraven
1050253159Stheraven#elif defined(EMSCRIPTEN)
1051249998Sdimconst int*
1052249998Sdimctype<char>::__classic_lower_table() _NOEXCEPT
1053249998Sdim{
1054249998Sdim    return *__ctype_tolower_loc();
1055249998Sdim}
1056249998Sdim
1057249998Sdimconst int*
1058249998Sdimctype<char>::__classic_upper_table() _NOEXCEPT
1059249998Sdim{
1060249998Sdim    return *__ctype_toupper_loc();
1061249998Sdim}
1062253159Stheraven#endif // __GLIBC__ || EMSCRIPTEN || __NETBSD__
1063249998Sdim
1064227825Stheraven// template <> class ctype_byname<char>
1065227825Stheraven
1066227825Stheravenctype_byname<char>::ctype_byname(const char* name, size_t refs)
1067227825Stheraven    : ctype<char>(0, false, refs),
1068227825Stheraven      __l(newlocale(LC_ALL_MASK, name, 0))
1069227825Stheraven{
1070227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1071227825Stheraven    if (__l == 0)
1072227825Stheraven        throw runtime_error("ctype_byname<char>::ctype_byname"
1073227825Stheraven                            " failed to construct for " + string(name));
1074227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1075227825Stheraven}
1076227825Stheraven
1077227825Stheravenctype_byname<char>::ctype_byname(const string& name, size_t refs)
1078227825Stheraven    : ctype<char>(0, false, refs),
1079227825Stheraven      __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1080227825Stheraven{
1081227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1082227825Stheraven    if (__l == 0)
1083227825Stheraven        throw runtime_error("ctype_byname<char>::ctype_byname"
1084227825Stheraven                            " failed to construct for " + name);
1085227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1086227825Stheraven}
1087227825Stheraven
1088227825Stheravenctype_byname<char>::~ctype_byname()
1089227825Stheraven{
1090227825Stheraven    freelocale(__l);
1091227825Stheraven}
1092227825Stheraven
1093227825Stheravenchar
1094227825Stheravenctype_byname<char>::do_toupper(char_type c) const
1095227825Stheraven{
1096253159Stheraven    return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
1097227825Stheraven}
1098227825Stheraven
1099227825Stheravenconst char*
1100227825Stheravenctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1101227825Stheraven{
1102227825Stheraven    for (; low != high; ++low)
1103253159Stheraven        *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
1104227825Stheraven    return low;
1105227825Stheraven}
1106227825Stheraven
1107227825Stheravenchar
1108227825Stheravenctype_byname<char>::do_tolower(char_type c) const
1109227825Stheraven{
1110253159Stheraven    return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
1111227825Stheraven}
1112227825Stheraven
1113227825Stheravenconst char*
1114227825Stheravenctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1115227825Stheraven{
1116227825Stheraven    for (; low != high; ++low)
1117253159Stheraven        *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
1118227825Stheraven    return low;
1119227825Stheraven}
1120227825Stheraven
1121227825Stheraven// template <> class ctype_byname<wchar_t>
1122227825Stheraven
1123227825Stheravenctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1124227825Stheraven    : ctype<wchar_t>(refs),
1125227825Stheraven      __l(newlocale(LC_ALL_MASK, name, 0))
1126227825Stheraven{
1127227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1128227825Stheraven    if (__l == 0)
1129227825Stheraven        throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1130227825Stheraven                            " failed to construct for " + string(name));
1131227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1132227825Stheraven}
1133227825Stheraven
1134227825Stheravenctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1135227825Stheraven    : ctype<wchar_t>(refs),
1136227825Stheraven      __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1137227825Stheraven{
1138227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1139227825Stheraven    if (__l == 0)
1140227825Stheraven        throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1141227825Stheraven                            " failed to construct for " + name);
1142227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1143227825Stheraven}
1144227825Stheraven
1145227825Stheravenctype_byname<wchar_t>::~ctype_byname()
1146227825Stheraven{
1147227825Stheraven    freelocale(__l);
1148227825Stheraven}
1149227825Stheraven
1150227825Stheravenbool
1151227825Stheravenctype_byname<wchar_t>::do_is(mask m, char_type c) const
1152227825Stheraven{
1153227825Stheraven#ifdef _LIBCPP_WCTYPE_IS_MASK
1154227825Stheraven    return static_cast<bool>(iswctype_l(c, m, __l));
1155227825Stheraven#else
1156241903Sdim    bool result = false;
1157249998Sdim    wint_t ch = static_cast<wint_t>(c);
1158249998Sdim    if (m & space) result |= (iswspace_l(ch, __l) != 0);
1159249998Sdim    if (m & print) result |= (iswprint_l(ch, __l) != 0);
1160249998Sdim    if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1161249998Sdim    if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1162249998Sdim    if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1163249998Sdim    if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1164249998Sdim    if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1165249998Sdim    if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1166249998Sdim    if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1167249998Sdim    if (m & blank) result |= (iswblank_l(ch, __l) != 0);
1168227825Stheraven    return result;
1169227825Stheraven#endif
1170227825Stheraven}
1171227825Stheraven
1172227825Stheravenconst wchar_t*
1173227825Stheravenctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1174227825Stheraven{
1175227825Stheraven    for (; low != high; ++low, ++vec)
1176227825Stheraven    {
1177227825Stheraven        if (isascii(*low))
1178227825Stheraven            *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
1179227825Stheraven        else
1180227825Stheraven        {
1181227825Stheraven            *vec = 0;
1182249998Sdim            wint_t ch = static_cast<wint_t>(*low);
1183249998Sdim            if (iswspace_l(ch, __l))
1184227825Stheraven                *vec |= space;
1185249998Sdim            if (iswprint_l(ch, __l))
1186227825Stheraven                *vec |= print;
1187249998Sdim            if (iswcntrl_l(ch, __l))
1188227825Stheraven                *vec |= cntrl;
1189249998Sdim            if (iswupper_l(ch, __l))
1190227825Stheraven                *vec |= upper;
1191249998Sdim            if (iswlower_l(ch, __l))
1192227825Stheraven                *vec |= lower;
1193249998Sdim            if (iswalpha_l(ch, __l))
1194227825Stheraven                *vec |= alpha;
1195249998Sdim            if (iswdigit_l(ch, __l))
1196227825Stheraven                *vec |= digit;
1197249998Sdim            if (iswpunct_l(ch, __l))
1198227825Stheraven                *vec |= punct;
1199249998Sdim            if (iswxdigit_l(ch, __l))
1200227825Stheraven                *vec |= xdigit;
1201227825Stheraven        }
1202227825Stheraven    }
1203227825Stheraven    return low;
1204227825Stheraven}
1205227825Stheraven
1206227825Stheravenconst wchar_t*
1207227825Stheravenctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1208227825Stheraven{
1209227825Stheraven    for (; low != high; ++low)
1210227825Stheraven    {
1211227825Stheraven#ifdef _LIBCPP_WCTYPE_IS_MASK
1212227825Stheraven        if (iswctype_l(*low, m, __l))
1213227825Stheraven            break;
1214227825Stheraven#else
1215249998Sdim        wint_t ch = static_cast<wint_t>(*low);
1216249998Sdim        if (m & space && iswspace_l(ch, __l)) break;
1217249998Sdim        if (m & print && iswprint_l(ch, __l)) break;
1218249998Sdim        if (m & cntrl && iswcntrl_l(ch, __l)) break;
1219249998Sdim        if (m & upper && iswupper_l(ch, __l)) break;
1220249998Sdim        if (m & lower && iswlower_l(ch, __l)) break;
1221249998Sdim        if (m & alpha && iswalpha_l(ch, __l)) break;
1222249998Sdim        if (m & digit && iswdigit_l(ch, __l)) break;
1223249998Sdim        if (m & punct && iswpunct_l(ch, __l)) break;
1224249998Sdim        if (m & xdigit && iswxdigit_l(ch, __l)) break;
1225249998Sdim        if (m & blank && iswblank_l(ch, __l)) break;
1226227825Stheraven#endif
1227227825Stheraven    }
1228227825Stheraven    return low;
1229227825Stheraven}
1230227825Stheraven
1231227825Stheravenconst wchar_t*
1232227825Stheravenctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1233227825Stheraven{
1234227825Stheraven    for (; low != high; ++low)
1235227825Stheraven    {
1236227825Stheraven#ifdef _LIBCPP_WCTYPE_IS_MASK
1237227825Stheraven        if (!iswctype_l(*low, m, __l))
1238227825Stheraven            break;
1239227825Stheraven#else
1240249998Sdim        wint_t ch = static_cast<wint_t>(*low);
1241249998Sdim        if (m & space && iswspace_l(ch, __l)) continue;
1242249998Sdim        if (m & print && iswprint_l(ch, __l)) continue;
1243249998Sdim        if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1244249998Sdim        if (m & upper && iswupper_l(ch, __l)) continue;
1245249998Sdim        if (m & lower && iswlower_l(ch, __l)) continue;
1246249998Sdim        if (m & alpha && iswalpha_l(ch, __l)) continue;
1247249998Sdim        if (m & digit && iswdigit_l(ch, __l)) continue;
1248249998Sdim        if (m & punct && iswpunct_l(ch, __l)) continue;
1249249998Sdim        if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1250249998Sdim        if (m & blank && iswblank_l(ch, __l)) continue;
1251227825Stheraven        break;
1252227825Stheraven#endif
1253227825Stheraven    }
1254227825Stheraven    return low;
1255227825Stheraven}
1256227825Stheraven
1257227825Stheravenwchar_t
1258227825Stheravenctype_byname<wchar_t>::do_toupper(char_type c) const
1259227825Stheraven{
1260227825Stheraven    return towupper_l(c, __l);
1261227825Stheraven}
1262227825Stheraven
1263227825Stheravenconst wchar_t*
1264227825Stheravenctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1265227825Stheraven{
1266227825Stheraven    for (; low != high; ++low)
1267227825Stheraven        *low = towupper_l(*low, __l);
1268227825Stheraven    return low;
1269227825Stheraven}
1270227825Stheraven
1271227825Stheravenwchar_t
1272227825Stheravenctype_byname<wchar_t>::do_tolower(char_type c) const
1273227825Stheraven{
1274227825Stheraven    return towlower_l(c, __l);
1275227825Stheraven}
1276227825Stheraven
1277227825Stheravenconst wchar_t*
1278227825Stheravenctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1279227825Stheraven{
1280227825Stheraven    for (; low != high; ++low)
1281227825Stheraven        *low = towlower_l(*low, __l);
1282227825Stheraven    return low;
1283227825Stheraven}
1284227825Stheraven
1285227825Stheravenwchar_t
1286227825Stheravenctype_byname<wchar_t>::do_widen(char c) const
1287227825Stheraven{
1288227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1289227825Stheraven    return btowc_l(c, __l);
1290227825Stheraven#else
1291227825Stheraven    return __btowc_l(c, __l);
1292227825Stheraven#endif
1293227825Stheraven}
1294227825Stheraven
1295227825Stheravenconst char*
1296227825Stheravenctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1297227825Stheraven{
1298227825Stheraven    for (; low != high; ++low, ++dest)
1299227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1300227825Stheraven        *dest = btowc_l(*low, __l);
1301227825Stheraven#else
1302227825Stheraven        *dest = __btowc_l(*low, __l);
1303227825Stheraven#endif
1304227825Stheraven    return low;
1305227825Stheraven}
1306227825Stheraven
1307227825Stheravenchar
1308227825Stheravenctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1309227825Stheraven{
1310227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1311227825Stheraven    int r = wctob_l(c, __l);
1312227825Stheraven#else
1313227825Stheraven    int r = __wctob_l(c, __l);
1314227825Stheraven#endif
1315246487Stheraven    return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
1316227825Stheraven}
1317227825Stheraven
1318227825Stheravenconst wchar_t*
1319227825Stheravenctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1320227825Stheraven{
1321227825Stheraven    for (; low != high; ++low, ++dest)
1322227825Stheraven    {
1323227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1324227825Stheraven        int r = wctob_l(*low, __l);
1325227825Stheraven#else
1326227825Stheraven        int r = __wctob_l(*low, __l);
1327227825Stheraven#endif
1328246487Stheraven        *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
1329227825Stheraven    }
1330227825Stheraven    return low;
1331227825Stheraven}
1332227825Stheraven
1333227825Stheraven// template <> class codecvt<char, char, mbstate_t>
1334227825Stheraven
1335227825Stheravenlocale::id codecvt<char, char, mbstate_t>::id;
1336227825Stheraven
1337227825Stheravencodecvt<char, char, mbstate_t>::~codecvt()
1338227825Stheraven{
1339227825Stheraven}
1340227825Stheraven
1341227825Stheravencodecvt<char, char, mbstate_t>::result
1342227825Stheravencodecvt<char, char, mbstate_t>::do_out(state_type&,
1343227825Stheraven    const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
1344227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
1345227825Stheraven{
1346227825Stheraven    frm_nxt = frm;
1347227825Stheraven    to_nxt = to;
1348227825Stheraven    return noconv;
1349227825Stheraven}
1350227825Stheraven
1351227825Stheravencodecvt<char, char, mbstate_t>::result
1352227825Stheravencodecvt<char, char, mbstate_t>::do_in(state_type&,
1353227825Stheraven    const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
1354227825Stheraven    intern_type* to, intern_type*, intern_type*& to_nxt) const
1355227825Stheraven{
1356227825Stheraven    frm_nxt = frm;
1357227825Stheraven    to_nxt = to;
1358227825Stheraven    return noconv;
1359227825Stheraven}
1360227825Stheraven
1361227825Stheravencodecvt<char, char, mbstate_t>::result
1362227825Stheravencodecvt<char, char, mbstate_t>::do_unshift(state_type&,
1363227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
1364227825Stheraven{
1365227825Stheraven    to_nxt = to;
1366227825Stheraven    return noconv;
1367227825Stheraven}
1368227825Stheraven
1369227825Stheravenint
1370227825Stheravencodecvt<char, char, mbstate_t>::do_encoding() const  _NOEXCEPT
1371227825Stheraven{
1372227825Stheraven    return 1;
1373227825Stheraven}
1374227825Stheraven
1375227825Stheravenbool
1376227825Stheravencodecvt<char, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
1377227825Stheraven{
1378227825Stheraven    return true;
1379227825Stheraven}
1380227825Stheraven
1381227825Stheravenint
1382227825Stheravencodecvt<char, char, mbstate_t>::do_length(state_type&,
1383227825Stheraven    const extern_type* frm, const extern_type* end, size_t mx) const
1384227825Stheraven{
1385232950Stheraven    return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
1386227825Stheraven}
1387227825Stheraven
1388227825Stheravenint
1389227825Stheravencodecvt<char, char, mbstate_t>::do_max_length() const  _NOEXCEPT
1390227825Stheraven{
1391227825Stheraven    return 1;
1392227825Stheraven}
1393227825Stheraven
1394227825Stheraven// template <> class codecvt<wchar_t, char, mbstate_t>
1395227825Stheraven
1396227825Stheravenlocale::id codecvt<wchar_t, char, mbstate_t>::id;
1397227825Stheraven
1398227825Stheravencodecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1399227825Stheraven    : locale::facet(refs),
1400253159Stheraven      __l(_LIBCPP_GET_C_LOCALE)
1401227825Stheraven{
1402227825Stheraven}
1403227825Stheraven
1404227825Stheravencodecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1405227825Stheraven    : locale::facet(refs),
1406227825Stheraven      __l(newlocale(LC_ALL_MASK, nm, 0))
1407227825Stheraven{
1408227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1409227825Stheraven    if (__l == 0)
1410227825Stheraven        throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1411227825Stheraven                            " failed to construct for " + string(nm));
1412227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1413227825Stheraven}
1414227825Stheraven
1415227825Stheravencodecvt<wchar_t, char, mbstate_t>::~codecvt()
1416227825Stheraven{
1417253159Stheraven    if (__l != _LIBCPP_GET_C_LOCALE)
1418227825Stheraven        freelocale(__l);
1419227825Stheraven}
1420227825Stheraven
1421227825Stheravencodecvt<wchar_t, char, mbstate_t>::result
1422227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
1423227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1424227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1425227825Stheraven{
1426227825Stheraven    // look for first internal null in frm
1427227825Stheraven    const intern_type* fend = frm;
1428227825Stheraven    for (; fend != frm_end; ++fend)
1429227825Stheraven        if (*fend == 0)
1430227825Stheraven            break;
1431227825Stheraven    // loop over all null-terminated sequences in frm
1432227825Stheraven    to_nxt = to;
1433227825Stheraven    for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1434227825Stheraven    {
1435249998Sdim        // save state in case it is needed to recover to_nxt on error
1436227825Stheraven        mbstate_t save_state = st;
1437227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1438232950Stheraven        size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1439232950Stheraven                                static_cast<size_t>(to_end-to), &st, __l);
1440227825Stheraven#else
1441227825Stheraven        size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1442227825Stheraven#endif
1443227825Stheraven        if (n == size_t(-1))
1444227825Stheraven        {
1445227825Stheraven            // need to recover to_nxt
1446227825Stheraven            for (to_nxt = to; frm != frm_nxt; ++frm)
1447227825Stheraven            {
1448227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1449227825Stheraven                n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1450227825Stheraven#else
1451227825Stheraven                n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1452227825Stheraven#endif
1453227825Stheraven                if (n == size_t(-1))
1454227825Stheraven                    break;
1455227825Stheraven                to_nxt += n;
1456227825Stheraven            }
1457227825Stheraven            frm_nxt = frm;
1458227825Stheraven            return error;
1459227825Stheraven        }
1460227825Stheraven        if (n == 0)
1461227825Stheraven            return partial;
1462227825Stheraven        to_nxt += n;
1463227825Stheraven        if (to_nxt == to_end)
1464227825Stheraven            break;
1465227825Stheraven        if (fend != frm_end)  // set up next null terminated sequence
1466227825Stheraven        {
1467227825Stheraven            // Try to write the terminating null
1468227825Stheraven            extern_type tmp[MB_LEN_MAX];
1469227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1470227825Stheraven            n = wcrtomb_l(tmp, intern_type(), &st, __l);
1471227825Stheraven#else
1472227825Stheraven            n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1473227825Stheraven#endif
1474227825Stheraven            if (n == size_t(-1))  // on error
1475227825Stheraven                return error;
1476232950Stheraven            if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
1477227825Stheraven                return partial;
1478227825Stheraven            for (extern_type* p = tmp; n; --n)  // write it
1479227825Stheraven                *to_nxt++ = *p++;
1480227825Stheraven            ++frm_nxt;
1481227825Stheraven            // look for next null in frm
1482227825Stheraven            for (fend = frm_nxt; fend != frm_end; ++fend)
1483227825Stheraven                if (*fend == 0)
1484227825Stheraven                    break;
1485227825Stheraven        }
1486227825Stheraven    }
1487227825Stheraven    return frm_nxt == frm_end ? ok : partial;
1488227825Stheraven}
1489227825Stheraven
1490227825Stheravencodecvt<wchar_t, char, mbstate_t>::result
1491227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
1492227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1493227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1494227825Stheraven{
1495227825Stheraven    // look for first internal null in frm
1496227825Stheraven    const extern_type* fend = frm;
1497227825Stheraven    for (; fend != frm_end; ++fend)
1498227825Stheraven        if (*fend == 0)
1499227825Stheraven            break;
1500227825Stheraven    // loop over all null-terminated sequences in frm
1501227825Stheraven    to_nxt = to;
1502227825Stheraven    for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1503227825Stheraven    {
1504249998Sdim        // save state in case it is needed to recover to_nxt on error
1505227825Stheraven        mbstate_t save_state = st;
1506227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1507232950Stheraven        size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1508232950Stheraven                                static_cast<size_t>(to_end-to), &st, __l);
1509227825Stheraven#else
1510227825Stheraven        size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1511227825Stheraven#endif
1512227825Stheraven        if (n == size_t(-1))
1513227825Stheraven        {
1514227825Stheraven            // need to recover to_nxt
1515227825Stheraven            for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1516227825Stheraven            {
1517227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1518232950Stheraven                n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1519232950Stheraven                              &save_state, __l);
1520227825Stheraven#else
1521227825Stheraven                n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1522227825Stheraven#endif
1523227825Stheraven                switch (n)
1524227825Stheraven                {
1525227825Stheraven                case 0:
1526227825Stheraven                    ++frm;
1527227825Stheraven                    break;
1528232950Stheraven                case size_t(-1):
1529227825Stheraven                    frm_nxt = frm;
1530227825Stheraven                    return error;
1531232950Stheraven                case size_t(-2):
1532227825Stheraven                    frm_nxt = frm;
1533227825Stheraven                    return partial;
1534227825Stheraven                default:
1535227825Stheraven                    frm += n;
1536227825Stheraven                    break;
1537227825Stheraven                }
1538227825Stheraven            }
1539227825Stheraven            frm_nxt = frm;
1540227825Stheraven            return frm_nxt == frm_end ? ok : partial;
1541227825Stheraven        }
1542227825Stheraven        if (n == 0)
1543227825Stheraven            return error;
1544227825Stheraven        to_nxt += n;
1545227825Stheraven        if (to_nxt == to_end)
1546227825Stheraven            break;
1547227825Stheraven        if (fend != frm_end)  // set up next null terminated sequence
1548227825Stheraven        {
1549227825Stheraven            // Try to write the terminating null
1550227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1551227825Stheraven            n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1552227825Stheraven#else
1553227825Stheraven            n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1554227825Stheraven#endif
1555227825Stheraven            if (n != 0)  // on error
1556227825Stheraven                return error;
1557227825Stheraven            ++to_nxt;
1558227825Stheraven            ++frm_nxt;
1559227825Stheraven            // look for next null in frm
1560227825Stheraven            for (fend = frm_nxt; fend != frm_end; ++fend)
1561227825Stheraven                if (*fend == 0)
1562227825Stheraven                    break;
1563227825Stheraven        }
1564227825Stheraven    }
1565227825Stheraven    return frm_nxt == frm_end ? ok : partial;
1566227825Stheraven}
1567227825Stheraven
1568227825Stheravencodecvt<wchar_t, char, mbstate_t>::result
1569227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1570227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1571227825Stheraven{
1572227825Stheraven    to_nxt = to;
1573227825Stheraven    extern_type tmp[MB_LEN_MAX];
1574227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1575227825Stheraven    size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1576227825Stheraven#else
1577227825Stheraven    size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1578227825Stheraven#endif
1579227825Stheraven    if (n == size_t(-1) || n == 0)  // on error
1580227825Stheraven        return error;
1581227825Stheraven    --n;
1582232950Stheraven    if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
1583227825Stheraven        return partial;
1584227825Stheraven    for (extern_type* p = tmp; n; --n)  // write it
1585227825Stheraven        *to_nxt++ = *p++;
1586227825Stheraven    return ok;
1587227825Stheraven}
1588227825Stheraven
1589227825Stheravenint
1590227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
1591227825Stheraven{
1592227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1593227825Stheraven    if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1594227825Stheraven#else
1595227825Stheraven    if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1596227825Stheraven#endif
1597227825Stheraven    {
1598227825Stheraven        // stateless encoding
1599227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1600227825Stheraven        if (__l == 0 || MB_CUR_MAX_L(__l) == 1)  // there are no known constant length encodings
1601227825Stheraven#else
1602227825Stheraven        if (__l == 0 || __mb_cur_max_l(__l) == 1)  // there are no known constant length encodings
1603227825Stheraven#endif
1604227825Stheraven            return 1;                // which take more than 1 char to form a wchar_t
1605227825Stheraven         return 0;
1606227825Stheraven    }
1607227825Stheraven    return -1;
1608227825Stheraven}
1609227825Stheraven
1610227825Stheravenbool
1611227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
1612227825Stheraven{
1613227825Stheraven    return false;
1614227825Stheraven}
1615227825Stheraven
1616227825Stheravenint
1617227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1618227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
1619227825Stheraven{
1620227825Stheraven    int nbytes = 0;
1621227825Stheraven    for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1622227825Stheraven    {
1623227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1624232950Stheraven        size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
1625227825Stheraven#else
1626227825Stheraven        size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1627227825Stheraven#endif
1628227825Stheraven        switch (n)
1629227825Stheraven        {
1630227825Stheraven        case 0:
1631227825Stheraven            ++nbytes;
1632227825Stheraven            ++frm;
1633227825Stheraven            break;
1634232950Stheraven        case size_t(-1):
1635232950Stheraven        case size_t(-2):
1636227825Stheraven            return nbytes;
1637227825Stheraven        default:
1638227825Stheraven            nbytes += n;
1639227825Stheraven            frm += n;
1640227825Stheraven            break;
1641227825Stheraven        }
1642227825Stheraven    }
1643227825Stheraven    return nbytes;
1644227825Stheraven}
1645227825Stheraven
1646227825Stheravenint
1647227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
1648227825Stheraven{
1649227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1650249998Sdim    return __l == 0 ? 1 : static_cast<int>(  MB_CUR_MAX_L(__l));
1651227825Stheraven#else
1652249998Sdim    return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
1653227825Stheraven#endif
1654227825Stheraven}
1655227825Stheraven
1656227825Stheraven//                                     Valid UTF ranges
1657227825Stheraven//     UTF-32               UTF-16                          UTF-8               # of code points
1658227825Stheraven//                     first      second       first   second    third   fourth
1659227825Stheraven// 000000 - 00007F  0000 - 007F               00 - 7F                                 127
1660227825Stheraven// 000080 - 0007FF  0080 - 07FF               C2 - DF, 80 - BF                       1920
1661227825Stheraven// 000800 - 000FFF  0800 - 0FFF               E0 - E0, A0 - BF, 80 - BF              2048
1662227825Stheraven// 001000 - 00CFFF  1000 - CFFF               E1 - EC, 80 - BF, 80 - BF             49152
1663227825Stheraven// 00D000 - 00D7FF  D000 - D7FF               ED - ED, 80 - 9F, 80 - BF              2048
1664227825Stheraven// 00D800 - 00DFFF                invalid
1665227825Stheraven// 00E000 - 00FFFF  E000 - FFFF               EE - EF, 80 - BF, 80 - BF              8192
1666227825Stheraven// 010000 - 03FFFF  D800 - D8BF, DC00 - DFFF  F0 - F0, 90 - BF, 80 - BF, 80 - BF   196608
1667227825Stheraven// 040000 - 0FFFFF  D8C0 - DBBF, DC00 - DFFF  F1 - F3, 80 - BF, 80 - BF, 80 - BF   786432
1668227825Stheraven// 100000 - 10FFFF  DBC0 - DBFF, DC00 - DFFF  F4 - F4, 80 - 8F, 80 - BF, 80 - BF    65536
1669227825Stheraven
1670227825Stheravenstatic
1671227825Stheravencodecvt_base::result
1672227825Stheravenutf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1673227825Stheraven              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1674227825Stheraven              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1675227825Stheraven{
1676227825Stheraven    frm_nxt = frm;
1677227825Stheraven    to_nxt = to;
1678227825Stheraven    if (mode & generate_header)
1679227825Stheraven    {
1680227825Stheraven        if (to_end-to_nxt < 3)
1681227825Stheraven            return codecvt_base::partial;
1682227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xEF);
1683227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBB);
1684227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBF);
1685227825Stheraven    }
1686227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
1687227825Stheraven    {
1688227825Stheraven        uint16_t wc1 = *frm_nxt;
1689227825Stheraven        if (wc1 > Maxcode)
1690227825Stheraven            return codecvt_base::error;
1691227825Stheraven        if (wc1 < 0x0080)
1692227825Stheraven        {
1693227825Stheraven            if (to_end-to_nxt < 1)
1694227825Stheraven                return codecvt_base::partial;
1695227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc1);
1696227825Stheraven        }
1697227825Stheraven        else if (wc1 < 0x0800)
1698227825Stheraven        {
1699227825Stheraven            if (to_end-to_nxt < 2)
1700227825Stheraven                return codecvt_base::partial;
1701227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1702227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1703227825Stheraven        }
1704227825Stheraven        else if (wc1 < 0xD800)
1705227825Stheraven        {
1706227825Stheraven            if (to_end-to_nxt < 3)
1707227825Stheraven                return codecvt_base::partial;
1708227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1709227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1710227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1711227825Stheraven        }
1712227825Stheraven        else if (wc1 < 0xDC00)
1713227825Stheraven        {
1714227825Stheraven            if (frm_end-frm_nxt < 2)
1715227825Stheraven                return codecvt_base::partial;
1716227825Stheraven            uint16_t wc2 = frm_nxt[1];
1717227825Stheraven            if ((wc2 & 0xFC00) != 0xDC00)
1718227825Stheraven                return codecvt_base::error;
1719227825Stheraven            if (to_end-to_nxt < 4)
1720227825Stheraven                return codecvt_base::partial;
1721227825Stheraven            if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1722227825Stheraven                (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1723227825Stheraven                return codecvt_base::error;
1724227825Stheraven            ++frm_nxt;
1725227825Stheraven            uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1726227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1727227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
1728227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1729227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
1730227825Stheraven        }
1731227825Stheraven        else if (wc1 < 0xE000)
1732227825Stheraven        {
1733227825Stheraven            return codecvt_base::error;
1734227825Stheraven        }
1735227825Stheraven        else
1736227825Stheraven        {
1737227825Stheraven            if (to_end-to_nxt < 3)
1738227825Stheraven                return codecvt_base::partial;
1739227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1740227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1741227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1742227825Stheraven        }
1743227825Stheraven    }
1744227825Stheraven    return codecvt_base::ok;
1745227825Stheraven}
1746227825Stheraven
1747227825Stheravenstatic
1748227825Stheravencodecvt_base::result
1749227825Stheravenutf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1750227825Stheraven              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1751227825Stheraven              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1752227825Stheraven{
1753227825Stheraven    frm_nxt = frm;
1754227825Stheraven    to_nxt = to;
1755227825Stheraven    if (mode & generate_header)
1756227825Stheraven    {
1757227825Stheraven        if (to_end-to_nxt < 3)
1758227825Stheraven            return codecvt_base::partial;
1759227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xEF);
1760227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBB);
1761227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBF);
1762227825Stheraven    }
1763227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
1764227825Stheraven    {
1765227825Stheraven        uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1766227825Stheraven        if (wc1 > Maxcode)
1767227825Stheraven            return codecvt_base::error;
1768227825Stheraven        if (wc1 < 0x0080)
1769227825Stheraven        {
1770227825Stheraven            if (to_end-to_nxt < 1)
1771227825Stheraven                return codecvt_base::partial;
1772227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc1);
1773227825Stheraven        }
1774227825Stheraven        else if (wc1 < 0x0800)
1775227825Stheraven        {
1776227825Stheraven            if (to_end-to_nxt < 2)
1777227825Stheraven                return codecvt_base::partial;
1778227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1779227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1780227825Stheraven        }
1781227825Stheraven        else if (wc1 < 0xD800)
1782227825Stheraven        {
1783227825Stheraven            if (to_end-to_nxt < 3)
1784227825Stheraven                return codecvt_base::partial;
1785227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1786227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1787227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1788227825Stheraven        }
1789227825Stheraven        else if (wc1 < 0xDC00)
1790227825Stheraven        {
1791227825Stheraven            if (frm_end-frm_nxt < 2)
1792227825Stheraven                return codecvt_base::partial;
1793227825Stheraven            uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1794227825Stheraven            if ((wc2 & 0xFC00) != 0xDC00)
1795227825Stheraven                return codecvt_base::error;
1796227825Stheraven            if (to_end-to_nxt < 4)
1797227825Stheraven                return codecvt_base::partial;
1798227825Stheraven            if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1799227825Stheraven                (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1800227825Stheraven                return codecvt_base::error;
1801227825Stheraven            ++frm_nxt;
1802227825Stheraven            uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1803227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1804227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
1805227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1806227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
1807227825Stheraven        }
1808227825Stheraven        else if (wc1 < 0xE000)
1809227825Stheraven        {
1810227825Stheraven            return codecvt_base::error;
1811227825Stheraven        }
1812227825Stheraven        else
1813227825Stheraven        {
1814227825Stheraven            if (to_end-to_nxt < 3)
1815227825Stheraven                return codecvt_base::partial;
1816227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1817227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1818227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1819227825Stheraven        }
1820227825Stheraven    }
1821227825Stheraven    return codecvt_base::ok;
1822227825Stheraven}
1823227825Stheraven
1824227825Stheravenstatic
1825227825Stheravencodecvt_base::result
1826227825Stheravenutf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1827227825Stheraven              uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1828227825Stheraven              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1829227825Stheraven{
1830227825Stheraven    frm_nxt = frm;
1831227825Stheraven    to_nxt = to;
1832227825Stheraven    if (mode & consume_header)
1833227825Stheraven    {
1834227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1835227825Stheraven                                                          frm_nxt[2] == 0xBF)
1836227825Stheraven            frm_nxt += 3;
1837227825Stheraven    }
1838227825Stheraven    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1839227825Stheraven    {
1840227825Stheraven        uint8_t c1 = *frm_nxt;
1841227825Stheraven        if (c1 > Maxcode)
1842227825Stheraven            return codecvt_base::error;
1843227825Stheraven        if (c1 < 0x80)
1844227825Stheraven        {
1845227825Stheraven            *to_nxt = static_cast<uint16_t>(c1);
1846227825Stheraven            ++frm_nxt;
1847227825Stheraven        }
1848227825Stheraven        else if (c1 < 0xC2)
1849227825Stheraven        {
1850227825Stheraven            return codecvt_base::error;
1851227825Stheraven        }
1852227825Stheraven        else if (c1 < 0xE0)
1853227825Stheraven        {
1854227825Stheraven            if (frm_end-frm_nxt < 2)
1855227825Stheraven                return codecvt_base::partial;
1856227825Stheraven            uint8_t c2 = frm_nxt[1];
1857227825Stheraven            if ((c2 & 0xC0) != 0x80)
1858227825Stheraven                return codecvt_base::error;
1859227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1860227825Stheraven            if (t > Maxcode)
1861227825Stheraven                return codecvt_base::error;
1862227825Stheraven            *to_nxt = t;
1863227825Stheraven            frm_nxt += 2;
1864227825Stheraven        }
1865227825Stheraven        else if (c1 < 0xF0)
1866227825Stheraven        {
1867227825Stheraven            if (frm_end-frm_nxt < 3)
1868227825Stheraven                return codecvt_base::partial;
1869227825Stheraven            uint8_t c2 = frm_nxt[1];
1870227825Stheraven            uint8_t c3 = frm_nxt[2];
1871227825Stheraven            switch (c1)
1872227825Stheraven            {
1873227825Stheraven            case 0xE0:
1874227825Stheraven                if ((c2 & 0xE0) != 0xA0)
1875227825Stheraven                    return codecvt_base::error;
1876227825Stheraven                 break;
1877227825Stheraven            case 0xED:
1878227825Stheraven                if ((c2 & 0xE0) != 0x80)
1879227825Stheraven                    return codecvt_base::error;
1880227825Stheraven                 break;
1881227825Stheraven            default:
1882227825Stheraven                if ((c2 & 0xC0) != 0x80)
1883227825Stheraven                    return codecvt_base::error;
1884227825Stheraven                 break;
1885227825Stheraven            }
1886227825Stheraven            if ((c3 & 0xC0) != 0x80)
1887227825Stheraven                return codecvt_base::error;
1888227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1889227825Stheraven                                             | ((c2 & 0x3F) << 6)
1890227825Stheraven                                             |  (c3 & 0x3F));
1891227825Stheraven            if (t > Maxcode)
1892227825Stheraven                return codecvt_base::error;
1893227825Stheraven            *to_nxt = t;
1894227825Stheraven            frm_nxt += 3;
1895227825Stheraven        }
1896227825Stheraven        else if (c1 < 0xF5)
1897227825Stheraven        {
1898227825Stheraven            if (frm_end-frm_nxt < 4)
1899227825Stheraven                return codecvt_base::partial;
1900227825Stheraven            uint8_t c2 = frm_nxt[1];
1901227825Stheraven            uint8_t c3 = frm_nxt[2];
1902227825Stheraven            uint8_t c4 = frm_nxt[3];
1903227825Stheraven            switch (c1)
1904227825Stheraven            {
1905227825Stheraven            case 0xF0:
1906227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
1907227825Stheraven                    return codecvt_base::error;
1908227825Stheraven                 break;
1909227825Stheraven            case 0xF4:
1910227825Stheraven                if ((c2 & 0xF0) != 0x80)
1911227825Stheraven                    return codecvt_base::error;
1912227825Stheraven                 break;
1913227825Stheraven            default:
1914227825Stheraven                if ((c2 & 0xC0) != 0x80)
1915227825Stheraven                    return codecvt_base::error;
1916227825Stheraven                 break;
1917227825Stheraven            }
1918227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1919227825Stheraven                return codecvt_base::error;
1920227825Stheraven            if (to_end-to_nxt < 2)
1921227825Stheraven                return codecvt_base::partial;
1922227825Stheraven            if (((((unsigned long)c1 & 7) << 18) +
1923227825Stheraven                (((unsigned long)c2 & 0x3F) << 12) +
1924227825Stheraven                (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1925227825Stheraven                return codecvt_base::error;
1926227825Stheraven            *to_nxt = static_cast<uint16_t>(
1927227825Stheraven                    0xD800
1928227825Stheraven                  | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1929227825Stheraven                  | ((c2 & 0x0F) << 2)
1930227825Stheraven                  | ((c3 & 0x30) >> 4));
1931227825Stheraven            *++to_nxt = static_cast<uint16_t>(
1932227825Stheraven                    0xDC00
1933227825Stheraven                  | ((c3 & 0x0F) << 6)
1934227825Stheraven                  |  (c4 & 0x3F));
1935227825Stheraven            frm_nxt += 4;
1936227825Stheraven        }
1937227825Stheraven        else
1938227825Stheraven        {
1939227825Stheraven            return codecvt_base::error;
1940227825Stheraven        }
1941227825Stheraven    }
1942227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1943227825Stheraven}
1944227825Stheraven
1945227825Stheravenstatic
1946227825Stheravencodecvt_base::result
1947227825Stheravenutf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1948227825Stheraven              uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1949227825Stheraven              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1950227825Stheraven{
1951227825Stheraven    frm_nxt = frm;
1952227825Stheraven    to_nxt = to;
1953227825Stheraven    if (mode & consume_header)
1954227825Stheraven    {
1955227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1956227825Stheraven                                                          frm_nxt[2] == 0xBF)
1957227825Stheraven            frm_nxt += 3;
1958227825Stheraven    }
1959227825Stheraven    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1960227825Stheraven    {
1961227825Stheraven        uint8_t c1 = *frm_nxt;
1962227825Stheraven        if (c1 > Maxcode)
1963227825Stheraven            return codecvt_base::error;
1964227825Stheraven        if (c1 < 0x80)
1965227825Stheraven        {
1966227825Stheraven            *to_nxt = static_cast<uint32_t>(c1);
1967227825Stheraven            ++frm_nxt;
1968227825Stheraven        }
1969227825Stheraven        else if (c1 < 0xC2)
1970227825Stheraven        {
1971227825Stheraven            return codecvt_base::error;
1972227825Stheraven        }
1973227825Stheraven        else if (c1 < 0xE0)
1974227825Stheraven        {
1975227825Stheraven            if (frm_end-frm_nxt < 2)
1976227825Stheraven                return codecvt_base::partial;
1977227825Stheraven            uint8_t c2 = frm_nxt[1];
1978227825Stheraven            if ((c2 & 0xC0) != 0x80)
1979227825Stheraven                return codecvt_base::error;
1980227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1981227825Stheraven            if (t > Maxcode)
1982227825Stheraven                return codecvt_base::error;
1983227825Stheraven            *to_nxt = static_cast<uint32_t>(t);
1984227825Stheraven            frm_nxt += 2;
1985227825Stheraven        }
1986227825Stheraven        else if (c1 < 0xF0)
1987227825Stheraven        {
1988227825Stheraven            if (frm_end-frm_nxt < 3)
1989227825Stheraven                return codecvt_base::partial;
1990227825Stheraven            uint8_t c2 = frm_nxt[1];
1991227825Stheraven            uint8_t c3 = frm_nxt[2];
1992227825Stheraven            switch (c1)
1993227825Stheraven            {
1994227825Stheraven            case 0xE0:
1995227825Stheraven                if ((c2 & 0xE0) != 0xA0)
1996227825Stheraven                    return codecvt_base::error;
1997227825Stheraven                 break;
1998227825Stheraven            case 0xED:
1999227825Stheraven                if ((c2 & 0xE0) != 0x80)
2000227825Stheraven                    return codecvt_base::error;
2001227825Stheraven                 break;
2002227825Stheraven            default:
2003227825Stheraven                if ((c2 & 0xC0) != 0x80)
2004227825Stheraven                    return codecvt_base::error;
2005227825Stheraven                 break;
2006227825Stheraven            }
2007227825Stheraven            if ((c3 & 0xC0) != 0x80)
2008227825Stheraven                return codecvt_base::error;
2009227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2010227825Stheraven                                             | ((c2 & 0x3F) << 6)
2011227825Stheraven                                             |  (c3 & 0x3F));
2012227825Stheraven            if (t > Maxcode)
2013227825Stheraven                return codecvt_base::error;
2014227825Stheraven            *to_nxt = static_cast<uint32_t>(t);
2015227825Stheraven            frm_nxt += 3;
2016227825Stheraven        }
2017227825Stheraven        else if (c1 < 0xF5)
2018227825Stheraven        {
2019227825Stheraven            if (frm_end-frm_nxt < 4)
2020227825Stheraven                return codecvt_base::partial;
2021227825Stheraven            uint8_t c2 = frm_nxt[1];
2022227825Stheraven            uint8_t c3 = frm_nxt[2];
2023227825Stheraven            uint8_t c4 = frm_nxt[3];
2024227825Stheraven            switch (c1)
2025227825Stheraven            {
2026227825Stheraven            case 0xF0:
2027227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
2028227825Stheraven                    return codecvt_base::error;
2029227825Stheraven                 break;
2030227825Stheraven            case 0xF4:
2031227825Stheraven                if ((c2 & 0xF0) != 0x80)
2032227825Stheraven                    return codecvt_base::error;
2033227825Stheraven                 break;
2034227825Stheraven            default:
2035227825Stheraven                if ((c2 & 0xC0) != 0x80)
2036227825Stheraven                    return codecvt_base::error;
2037227825Stheraven                 break;
2038227825Stheraven            }
2039227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2040227825Stheraven                return codecvt_base::error;
2041227825Stheraven            if (to_end-to_nxt < 2)
2042227825Stheraven                return codecvt_base::partial;
2043227825Stheraven            if (((((unsigned long)c1 & 7) << 18) +
2044227825Stheraven                (((unsigned long)c2 & 0x3F) << 12) +
2045227825Stheraven                (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2046227825Stheraven                return codecvt_base::error;
2047227825Stheraven            *to_nxt = static_cast<uint32_t>(
2048227825Stheraven                    0xD800
2049227825Stheraven                  | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2050227825Stheraven                  | ((c2 & 0x0F) << 2)
2051227825Stheraven                  | ((c3 & 0x30) >> 4));
2052227825Stheraven            *++to_nxt = static_cast<uint32_t>(
2053227825Stheraven                    0xDC00
2054227825Stheraven                  | ((c3 & 0x0F) << 6)
2055227825Stheraven                  |  (c4 & 0x3F));
2056227825Stheraven            frm_nxt += 4;
2057227825Stheraven        }
2058227825Stheraven        else
2059227825Stheraven        {
2060227825Stheraven            return codecvt_base::error;
2061227825Stheraven        }
2062227825Stheraven    }
2063227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2064227825Stheraven}
2065227825Stheraven
2066227825Stheravenstatic
2067227825Stheravenint
2068227825Stheravenutf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2069227825Stheraven                     size_t mx, unsigned long Maxcode = 0x10FFFF,
2070227825Stheraven                     codecvt_mode mode = codecvt_mode(0))
2071227825Stheraven{
2072227825Stheraven    const uint8_t* frm_nxt = frm;
2073227825Stheraven    if (mode & consume_header)
2074227825Stheraven    {
2075227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2076227825Stheraven                                                          frm_nxt[2] == 0xBF)
2077227825Stheraven            frm_nxt += 3;
2078227825Stheraven    }
2079227825Stheraven    for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2080227825Stheraven    {
2081227825Stheraven        uint8_t c1 = *frm_nxt;
2082227825Stheraven        if (c1 > Maxcode)
2083227825Stheraven            break;
2084227825Stheraven        if (c1 < 0x80)
2085227825Stheraven        {
2086227825Stheraven            ++frm_nxt;
2087227825Stheraven        }
2088227825Stheraven        else if (c1 < 0xC2)
2089227825Stheraven        {
2090227825Stheraven            break;
2091227825Stheraven        }
2092227825Stheraven        else if (c1 < 0xE0)
2093227825Stheraven        {
2094227825Stheraven            if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2095227825Stheraven                break;
2096227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2097227825Stheraven            if (t > Maxcode)
2098227825Stheraven                break;
2099227825Stheraven            frm_nxt += 2;
2100227825Stheraven        }
2101227825Stheraven        else if (c1 < 0xF0)
2102227825Stheraven        {
2103227825Stheraven            if (frm_end-frm_nxt < 3)
2104227825Stheraven                break;
2105227825Stheraven            uint8_t c2 = frm_nxt[1];
2106227825Stheraven            uint8_t c3 = frm_nxt[2];
2107227825Stheraven            switch (c1)
2108227825Stheraven            {
2109227825Stheraven            case 0xE0:
2110227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2111227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2112227825Stheraven                break;
2113227825Stheraven            case 0xED:
2114227825Stheraven                if ((c2 & 0xE0) != 0x80)
2115227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2116227825Stheraven                 break;
2117227825Stheraven            default:
2118227825Stheraven                if ((c2 & 0xC0) != 0x80)
2119227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2120227825Stheraven                 break;
2121227825Stheraven            }
2122227825Stheraven            if ((c3 & 0xC0) != 0x80)
2123227825Stheraven                break;
2124232950Stheraven            if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2125227825Stheraven                break;
2126227825Stheraven            frm_nxt += 3;
2127227825Stheraven        }
2128227825Stheraven        else if (c1 < 0xF5)
2129227825Stheraven        {
2130227825Stheraven            if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2131227825Stheraven                break;
2132227825Stheraven            uint8_t c2 = frm_nxt[1];
2133227825Stheraven            uint8_t c3 = frm_nxt[2];
2134227825Stheraven            uint8_t c4 = frm_nxt[3];
2135227825Stheraven            switch (c1)
2136227825Stheraven            {
2137227825Stheraven            case 0xF0:
2138227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
2139227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2140227825Stheraven                 break;
2141227825Stheraven            case 0xF4:
2142227825Stheraven                if ((c2 & 0xF0) != 0x80)
2143227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2144227825Stheraven                 break;
2145227825Stheraven            default:
2146227825Stheraven                if ((c2 & 0xC0) != 0x80)
2147227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2148227825Stheraven                 break;
2149227825Stheraven            }
2150227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2151227825Stheraven                break;
2152227825Stheraven            if (((((unsigned long)c1 & 7) << 18) +
2153227825Stheraven                (((unsigned long)c2 & 0x3F) << 12) +
2154227825Stheraven                (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2155227825Stheraven                break;
2156227825Stheraven            ++nchar16_t;
2157227825Stheraven            frm_nxt += 4;
2158227825Stheraven        }
2159227825Stheraven        else
2160227825Stheraven        {
2161227825Stheraven            break;
2162227825Stheraven        }
2163227825Stheraven    }
2164227825Stheraven    return static_cast<int>(frm_nxt - frm);
2165227825Stheraven}
2166227825Stheraven
2167227825Stheravenstatic
2168227825Stheravencodecvt_base::result
2169227825Stheravenucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2170227825Stheraven             uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2171227825Stheraven             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2172227825Stheraven{
2173227825Stheraven    frm_nxt = frm;
2174227825Stheraven    to_nxt = to;
2175227825Stheraven    if (mode & generate_header)
2176227825Stheraven    {
2177227825Stheraven        if (to_end-to_nxt < 3)
2178227825Stheraven            return codecvt_base::partial;
2179227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xEF);
2180227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBB);
2181227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBF);
2182227825Stheraven    }
2183227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2184227825Stheraven    {
2185227825Stheraven        uint32_t wc = *frm_nxt;
2186227825Stheraven        if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2187227825Stheraven            return codecvt_base::error;
2188227825Stheraven        if (wc < 0x000080)
2189227825Stheraven        {
2190227825Stheraven            if (to_end-to_nxt < 1)
2191227825Stheraven                return codecvt_base::partial;
2192227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc);
2193227825Stheraven        }
2194227825Stheraven        else if (wc < 0x000800)
2195227825Stheraven        {
2196227825Stheraven            if (to_end-to_nxt < 2)
2197227825Stheraven                return codecvt_base::partial;
2198227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2199227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2200227825Stheraven        }
2201227825Stheraven        else if (wc < 0x010000)
2202227825Stheraven        {
2203227825Stheraven            if (to_end-to_nxt < 3)
2204227825Stheraven                return codecvt_base::partial;
2205227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
2206227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2207227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
2208227825Stheraven        }
2209227825Stheraven        else // if (wc < 0x110000)
2210227825Stheraven        {
2211227825Stheraven            if (to_end-to_nxt < 4)
2212227825Stheraven                return codecvt_base::partial;
2213227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xF0 |  (wc >> 18));
2214227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2215227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2216227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x00003F));
2217227825Stheraven        }
2218227825Stheraven    }
2219227825Stheraven    return codecvt_base::ok;
2220227825Stheraven}
2221227825Stheraven
2222227825Stheravenstatic
2223227825Stheravencodecvt_base::result
2224227825Stheravenutf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2225227825Stheraven             uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2226227825Stheraven             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2227227825Stheraven{
2228227825Stheraven    frm_nxt = frm;
2229227825Stheraven    to_nxt = to;
2230227825Stheraven    if (mode & consume_header)
2231227825Stheraven    {
2232227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2233227825Stheraven                                                          frm_nxt[2] == 0xBF)
2234227825Stheraven            frm_nxt += 3;
2235227825Stheraven    }
2236227825Stheraven    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2237227825Stheraven    {
2238227825Stheraven        uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2239227825Stheraven        if (c1 < 0x80)
2240227825Stheraven        {
2241227825Stheraven            if (c1 > Maxcode)
2242227825Stheraven                return codecvt_base::error;
2243227825Stheraven            *to_nxt = static_cast<uint32_t>(c1);
2244227825Stheraven            ++frm_nxt;
2245227825Stheraven        }
2246227825Stheraven        else if (c1 < 0xC2)
2247227825Stheraven        {
2248227825Stheraven            return codecvt_base::error;
2249227825Stheraven        }
2250227825Stheraven        else if (c1 < 0xE0)
2251227825Stheraven        {
2252227825Stheraven            if (frm_end-frm_nxt < 2)
2253227825Stheraven                return codecvt_base::partial;
2254227825Stheraven            uint8_t c2 = frm_nxt[1];
2255227825Stheraven            if ((c2 & 0xC0) != 0x80)
2256227825Stheraven                return codecvt_base::error;
2257227825Stheraven            uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2258227825Stheraven                                              | (c2 & 0x3F));
2259227825Stheraven            if (t > Maxcode)
2260227825Stheraven                return codecvt_base::error;
2261227825Stheraven            *to_nxt = t;
2262227825Stheraven            frm_nxt += 2;
2263227825Stheraven        }
2264227825Stheraven        else if (c1 < 0xF0)
2265227825Stheraven        {
2266227825Stheraven            if (frm_end-frm_nxt < 3)
2267227825Stheraven                return codecvt_base::partial;
2268227825Stheraven            uint8_t c2 = frm_nxt[1];
2269227825Stheraven            uint8_t c3 = frm_nxt[2];
2270227825Stheraven            switch (c1)
2271227825Stheraven            {
2272227825Stheraven            case 0xE0:
2273227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2274227825Stheraven                    return codecvt_base::error;
2275227825Stheraven                 break;
2276227825Stheraven            case 0xED:
2277227825Stheraven                if ((c2 & 0xE0) != 0x80)
2278227825Stheraven                    return codecvt_base::error;
2279227825Stheraven                 break;
2280227825Stheraven            default:
2281227825Stheraven                if ((c2 & 0xC0) != 0x80)
2282227825Stheraven                    return codecvt_base::error;
2283227825Stheraven                 break;
2284227825Stheraven            }
2285227825Stheraven            if ((c3 & 0xC0) != 0x80)
2286227825Stheraven                return codecvt_base::error;
2287227825Stheraven            uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2288227825Stheraven                                             | ((c2 & 0x3F) << 6)
2289227825Stheraven                                             |  (c3 & 0x3F));
2290227825Stheraven            if (t > Maxcode)
2291227825Stheraven                return codecvt_base::error;
2292227825Stheraven            *to_nxt = t;
2293227825Stheraven            frm_nxt += 3;
2294227825Stheraven        }
2295227825Stheraven        else if (c1 < 0xF5)
2296227825Stheraven        {
2297227825Stheraven            if (frm_end-frm_nxt < 4)
2298227825Stheraven                return codecvt_base::partial;
2299227825Stheraven            uint8_t c2 = frm_nxt[1];
2300227825Stheraven            uint8_t c3 = frm_nxt[2];
2301227825Stheraven            uint8_t c4 = frm_nxt[3];
2302227825Stheraven            switch (c1)
2303227825Stheraven            {
2304227825Stheraven            case 0xF0:
2305227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
2306227825Stheraven                    return codecvt_base::error;
2307227825Stheraven                 break;
2308227825Stheraven            case 0xF4:
2309227825Stheraven                if ((c2 & 0xF0) != 0x80)
2310227825Stheraven                    return codecvt_base::error;
2311227825Stheraven                 break;
2312227825Stheraven            default:
2313227825Stheraven                if ((c2 & 0xC0) != 0x80)
2314227825Stheraven                    return codecvt_base::error;
2315227825Stheraven                 break;
2316227825Stheraven            }
2317227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2318227825Stheraven                return codecvt_base::error;
2319227825Stheraven            uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2320227825Stheraven                                             | ((c2 & 0x3F) << 12)
2321227825Stheraven                                             | ((c3 & 0x3F) << 6)
2322227825Stheraven                                             |  (c4 & 0x3F));
2323227825Stheraven            if (t > Maxcode)
2324227825Stheraven                return codecvt_base::error;
2325227825Stheraven            *to_nxt = t;
2326227825Stheraven            frm_nxt += 4;
2327227825Stheraven        }
2328227825Stheraven        else
2329227825Stheraven        {
2330227825Stheraven            return codecvt_base::error;
2331227825Stheraven        }
2332227825Stheraven    }
2333227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2334227825Stheraven}
2335227825Stheraven
2336227825Stheravenstatic
2337227825Stheravenint
2338227825Stheravenutf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2339227825Stheraven                    size_t mx, unsigned long Maxcode = 0x10FFFF,
2340227825Stheraven                    codecvt_mode mode = codecvt_mode(0))
2341227825Stheraven{
2342227825Stheraven    const uint8_t* frm_nxt = frm;
2343227825Stheraven    if (mode & consume_header)
2344227825Stheraven    {
2345227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2346227825Stheraven                                                          frm_nxt[2] == 0xBF)
2347227825Stheraven            frm_nxt += 3;
2348227825Stheraven    }
2349227825Stheraven    for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2350227825Stheraven    {
2351227825Stheraven        uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2352227825Stheraven        if (c1 < 0x80)
2353227825Stheraven        {
2354227825Stheraven            if (c1 > Maxcode)
2355227825Stheraven                break;
2356227825Stheraven            ++frm_nxt;
2357227825Stheraven        }
2358227825Stheraven        else if (c1 < 0xC2)
2359227825Stheraven        {
2360227825Stheraven            break;
2361227825Stheraven        }
2362227825Stheraven        else if (c1 < 0xE0)
2363227825Stheraven        {
2364227825Stheraven            if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2365227825Stheraven                break;
2366232950Stheraven            if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2367227825Stheraven                break;
2368227825Stheraven            frm_nxt += 2;
2369227825Stheraven        }
2370227825Stheraven        else if (c1 < 0xF0)
2371227825Stheraven        {
2372227825Stheraven            if (frm_end-frm_nxt < 3)
2373227825Stheraven                break;
2374227825Stheraven            uint8_t c2 = frm_nxt[1];
2375227825Stheraven            uint8_t c3 = frm_nxt[2];
2376227825Stheraven            switch (c1)
2377227825Stheraven            {
2378227825Stheraven            case 0xE0:
2379227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2380227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2381227825Stheraven                break;
2382227825Stheraven            case 0xED:
2383227825Stheraven                if ((c2 & 0xE0) != 0x80)
2384227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2385227825Stheraven                 break;
2386227825Stheraven            default:
2387227825Stheraven                if ((c2 & 0xC0) != 0x80)
2388227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2389227825Stheraven                 break;
2390227825Stheraven            }
2391227825Stheraven            if ((c3 & 0xC0) != 0x80)
2392227825Stheraven                break;
2393232950Stheraven            if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2394227825Stheraven                break;
2395227825Stheraven            frm_nxt += 3;
2396227825Stheraven        }
2397227825Stheraven        else if (c1 < 0xF5)
2398227825Stheraven        {
2399227825Stheraven            if (frm_end-frm_nxt < 4)
2400227825Stheraven                break;
2401227825Stheraven            uint8_t c2 = frm_nxt[1];
2402227825Stheraven            uint8_t c3 = frm_nxt[2];
2403227825Stheraven            uint8_t c4 = frm_nxt[3];
2404227825Stheraven            switch (c1)
2405227825Stheraven            {
2406227825Stheraven            case 0xF0:
2407227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
2408227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2409227825Stheraven                 break;
2410227825Stheraven            case 0xF4:
2411227825Stheraven                if ((c2 & 0xF0) != 0x80)
2412227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2413227825Stheraven                 break;
2414227825Stheraven            default:
2415227825Stheraven                if ((c2 & 0xC0) != 0x80)
2416227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2417227825Stheraven                 break;
2418227825Stheraven            }
2419227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2420227825Stheraven                break;
2421232950Stheraven            if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2422232950Stheraven                 ((c3 & 0x3Fu) << 6)  |  (c4 & 0x3Fu)) > Maxcode)
2423227825Stheraven                break;
2424227825Stheraven            frm_nxt += 4;
2425227825Stheraven        }
2426227825Stheraven        else
2427227825Stheraven        {
2428227825Stheraven            break;
2429227825Stheraven        }
2430227825Stheraven    }
2431227825Stheraven    return static_cast<int>(frm_nxt - frm);
2432227825Stheraven}
2433227825Stheraven
2434227825Stheravenstatic
2435227825Stheravencodecvt_base::result
2436227825Stheravenucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2437227825Stheraven             uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2438227825Stheraven             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2439227825Stheraven{
2440227825Stheraven    frm_nxt = frm;
2441227825Stheraven    to_nxt = to;
2442227825Stheraven    if (mode & generate_header)
2443227825Stheraven    {
2444227825Stheraven        if (to_end-to_nxt < 3)
2445227825Stheraven            return codecvt_base::partial;
2446227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xEF);
2447227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBB);
2448227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBF);
2449227825Stheraven    }
2450227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2451227825Stheraven    {
2452227825Stheraven        uint16_t wc = *frm_nxt;
2453227825Stheraven        if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2454227825Stheraven            return codecvt_base::error;
2455227825Stheraven        if (wc < 0x0080)
2456227825Stheraven        {
2457227825Stheraven            if (to_end-to_nxt < 1)
2458227825Stheraven                return codecvt_base::partial;
2459227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc);
2460227825Stheraven        }
2461227825Stheraven        else if (wc < 0x0800)
2462227825Stheraven        {
2463227825Stheraven            if (to_end-to_nxt < 2)
2464227825Stheraven                return codecvt_base::partial;
2465227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2466227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2467227825Stheraven        }
2468227825Stheraven        else // if (wc <= 0xFFFF)
2469227825Stheraven        {
2470227825Stheraven            if (to_end-to_nxt < 3)
2471227825Stheraven                return codecvt_base::partial;
2472227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
2473227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2474227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
2475227825Stheraven        }
2476227825Stheraven    }
2477227825Stheraven    return codecvt_base::ok;
2478227825Stheraven}
2479227825Stheraven
2480227825Stheravenstatic
2481227825Stheravencodecvt_base::result
2482227825Stheravenutf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2483227825Stheraven             uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2484227825Stheraven             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2485227825Stheraven{
2486227825Stheraven    frm_nxt = frm;
2487227825Stheraven    to_nxt = to;
2488227825Stheraven    if (mode & consume_header)
2489227825Stheraven    {
2490227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2491227825Stheraven                                                          frm_nxt[2] == 0xBF)
2492227825Stheraven            frm_nxt += 3;
2493227825Stheraven    }
2494227825Stheraven    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2495227825Stheraven    {
2496227825Stheraven        uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2497227825Stheraven        if (c1 < 0x80)
2498227825Stheraven        {
2499227825Stheraven            if (c1 > Maxcode)
2500227825Stheraven                return codecvt_base::error;
2501227825Stheraven            *to_nxt = static_cast<uint16_t>(c1);
2502227825Stheraven            ++frm_nxt;
2503227825Stheraven        }
2504227825Stheraven        else if (c1 < 0xC2)
2505227825Stheraven        {
2506227825Stheraven            return codecvt_base::error;
2507227825Stheraven        }
2508227825Stheraven        else if (c1 < 0xE0)
2509227825Stheraven        {
2510227825Stheraven            if (frm_end-frm_nxt < 2)
2511227825Stheraven                return codecvt_base::partial;
2512227825Stheraven            uint8_t c2 = frm_nxt[1];
2513227825Stheraven            if ((c2 & 0xC0) != 0x80)
2514227825Stheraven                return codecvt_base::error;
2515227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2516227825Stheraven                                              | (c2 & 0x3F));
2517227825Stheraven            if (t > Maxcode)
2518227825Stheraven                return codecvt_base::error;
2519227825Stheraven            *to_nxt = t;
2520227825Stheraven            frm_nxt += 2;
2521227825Stheraven        }
2522227825Stheraven        else if (c1 < 0xF0)
2523227825Stheraven        {
2524227825Stheraven            if (frm_end-frm_nxt < 3)
2525227825Stheraven                return codecvt_base::partial;
2526227825Stheraven            uint8_t c2 = frm_nxt[1];
2527227825Stheraven            uint8_t c3 = frm_nxt[2];
2528227825Stheraven            switch (c1)
2529227825Stheraven            {
2530227825Stheraven            case 0xE0:
2531227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2532227825Stheraven                    return codecvt_base::error;
2533227825Stheraven                 break;
2534227825Stheraven            case 0xED:
2535227825Stheraven                if ((c2 & 0xE0) != 0x80)
2536227825Stheraven                    return codecvt_base::error;
2537227825Stheraven                 break;
2538227825Stheraven            default:
2539227825Stheraven                if ((c2 & 0xC0) != 0x80)
2540227825Stheraven                    return codecvt_base::error;
2541227825Stheraven                 break;
2542227825Stheraven            }
2543227825Stheraven            if ((c3 & 0xC0) != 0x80)
2544227825Stheraven                return codecvt_base::error;
2545227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2546227825Stheraven                                             | ((c2 & 0x3F) << 6)
2547227825Stheraven                                             |  (c3 & 0x3F));
2548227825Stheraven            if (t > Maxcode)
2549227825Stheraven                return codecvt_base::error;
2550227825Stheraven            *to_nxt = t;
2551227825Stheraven            frm_nxt += 3;
2552227825Stheraven        }
2553227825Stheraven        else
2554227825Stheraven        {
2555227825Stheraven            return codecvt_base::error;
2556227825Stheraven        }
2557227825Stheraven    }
2558227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2559227825Stheraven}
2560227825Stheraven
2561227825Stheravenstatic
2562227825Stheravenint
2563227825Stheravenutf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2564227825Stheraven                    size_t mx, unsigned long Maxcode = 0x10FFFF,
2565227825Stheraven                    codecvt_mode mode = codecvt_mode(0))
2566227825Stheraven{
2567227825Stheraven    const uint8_t* frm_nxt = frm;
2568227825Stheraven    if (mode & consume_header)
2569227825Stheraven    {
2570227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2571227825Stheraven                                                          frm_nxt[2] == 0xBF)
2572227825Stheraven            frm_nxt += 3;
2573227825Stheraven    }
2574227825Stheraven    for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2575227825Stheraven    {
2576227825Stheraven        uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2577227825Stheraven        if (c1 < 0x80)
2578227825Stheraven        {
2579227825Stheraven            if (c1 > Maxcode)
2580227825Stheraven                break;
2581227825Stheraven            ++frm_nxt;
2582227825Stheraven        }
2583227825Stheraven        else if (c1 < 0xC2)
2584227825Stheraven        {
2585227825Stheraven            break;
2586227825Stheraven        }
2587227825Stheraven        else if (c1 < 0xE0)
2588227825Stheraven        {
2589227825Stheraven            if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2590227825Stheraven                break;
2591232950Stheraven            if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2592227825Stheraven                break;
2593227825Stheraven            frm_nxt += 2;
2594227825Stheraven        }
2595227825Stheraven        else if (c1 < 0xF0)
2596227825Stheraven        {
2597227825Stheraven            if (frm_end-frm_nxt < 3)
2598227825Stheraven                break;
2599227825Stheraven            uint8_t c2 = frm_nxt[1];
2600227825Stheraven            uint8_t c3 = frm_nxt[2];
2601227825Stheraven            switch (c1)
2602227825Stheraven            {
2603227825Stheraven            case 0xE0:
2604227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2605227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2606227825Stheraven                break;
2607227825Stheraven            case 0xED:
2608227825Stheraven                if ((c2 & 0xE0) != 0x80)
2609227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2610227825Stheraven                 break;
2611227825Stheraven            default:
2612227825Stheraven                if ((c2 & 0xC0) != 0x80)
2613227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2614227825Stheraven                 break;
2615227825Stheraven            }
2616227825Stheraven            if ((c3 & 0xC0) != 0x80)
2617227825Stheraven                break;
2618232950Stheraven            if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2619227825Stheraven                break;
2620227825Stheraven            frm_nxt += 3;
2621227825Stheraven        }
2622227825Stheraven        else
2623227825Stheraven        {
2624227825Stheraven            break;
2625227825Stheraven        }
2626227825Stheraven    }
2627227825Stheraven    return static_cast<int>(frm_nxt - frm);
2628227825Stheraven}
2629227825Stheraven
2630227825Stheravenstatic
2631227825Stheravencodecvt_base::result
2632227825Stheravenucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2633227825Stheraven                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2634227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2635227825Stheraven{
2636227825Stheraven    frm_nxt = frm;
2637227825Stheraven    to_nxt = to;
2638227825Stheraven    if (mode & generate_header)
2639227825Stheraven    {
2640227825Stheraven        if (to_end-to_nxt < 2)
2641227825Stheraven            return codecvt_base::partial;
2642227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFE);
2643227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFF);
2644227825Stheraven    }
2645227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2646227825Stheraven    {
2647227825Stheraven        uint32_t wc = *frm_nxt;
2648227825Stheraven        if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2649227825Stheraven            return codecvt_base::error;
2650227825Stheraven        if (wc < 0x010000)
2651227825Stheraven        {
2652227825Stheraven            if (to_end-to_nxt < 2)
2653227825Stheraven                return codecvt_base::partial;
2654227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2655227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc);
2656227825Stheraven        }
2657227825Stheraven        else
2658227825Stheraven        {
2659227825Stheraven            if (to_end-to_nxt < 4)
2660227825Stheraven                return codecvt_base::partial;
2661227825Stheraven            uint16_t t = static_cast<uint16_t>(
2662227825Stheraven                    0xD800
2663227825Stheraven                  | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2664227825Stheraven                  |   ((wc & 0x00FC00) >> 10));
2665227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t >> 8);
2666227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t);
2667227825Stheraven            t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2668227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t >> 8);
2669227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t);
2670227825Stheraven        }
2671227825Stheraven    }
2672227825Stheraven    return codecvt_base::ok;
2673227825Stheraven}
2674227825Stheraven
2675227825Stheravenstatic
2676227825Stheravencodecvt_base::result
2677227825Stheravenutf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2678227825Stheraven                uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2679227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2680227825Stheraven{
2681227825Stheraven    frm_nxt = frm;
2682227825Stheraven    to_nxt = to;
2683227825Stheraven    if (mode & consume_header)
2684227825Stheraven    {
2685227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2686227825Stheraven            frm_nxt += 2;
2687227825Stheraven    }
2688227825Stheraven    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2689227825Stheraven    {
2690232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2691227825Stheraven        if ((c1 & 0xFC00) == 0xDC00)
2692227825Stheraven            return codecvt_base::error;
2693227825Stheraven        if ((c1 & 0xFC00) != 0xD800)
2694227825Stheraven        {
2695227825Stheraven            if (c1 > Maxcode)
2696227825Stheraven                return codecvt_base::error;
2697227825Stheraven            *to_nxt = static_cast<uint32_t>(c1);
2698227825Stheraven            frm_nxt += 2;
2699227825Stheraven        }
2700227825Stheraven        else
2701227825Stheraven        {
2702227825Stheraven            if (frm_end-frm_nxt < 4)
2703227825Stheraven                return codecvt_base::partial;
2704232950Stheraven            uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2705227825Stheraven            if ((c2 & 0xFC00) != 0xDC00)
2706227825Stheraven                return codecvt_base::error;
2707227825Stheraven            uint32_t t = static_cast<uint32_t>(
2708227825Stheraven                    ((((c1 & 0x03C0) >> 6) + 1) << 16)
2709227825Stheraven                  |   ((c1 & 0x003F) << 10)
2710227825Stheraven                  |    (c2 & 0x03FF));
2711227825Stheraven            if (t > Maxcode)
2712227825Stheraven                return codecvt_base::error;
2713227825Stheraven            *to_nxt = t;
2714227825Stheraven            frm_nxt += 4;
2715227825Stheraven        }
2716227825Stheraven    }
2717227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2718227825Stheraven}
2719227825Stheraven
2720227825Stheravenstatic
2721227825Stheravenint
2722227825Stheravenutf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2723227825Stheraven                       size_t mx, unsigned long Maxcode = 0x10FFFF,
2724227825Stheraven                       codecvt_mode mode = codecvt_mode(0))
2725227825Stheraven{
2726227825Stheraven    const uint8_t* frm_nxt = frm;
2727227825Stheraven    if (mode & consume_header)
2728227825Stheraven    {
2729227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2730227825Stheraven            frm_nxt += 2;
2731227825Stheraven    }
2732227825Stheraven    for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2733227825Stheraven    {
2734232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2735227825Stheraven        if ((c1 & 0xFC00) == 0xDC00)
2736227825Stheraven            break;
2737227825Stheraven        if ((c1 & 0xFC00) != 0xD800)
2738227825Stheraven        {
2739227825Stheraven            if (c1 > Maxcode)
2740227825Stheraven                break;
2741227825Stheraven            frm_nxt += 2;
2742227825Stheraven        }
2743227825Stheraven        else
2744227825Stheraven        {
2745227825Stheraven            if (frm_end-frm_nxt < 4)
2746227825Stheraven                break;
2747232950Stheraven            uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2748227825Stheraven            if ((c2 & 0xFC00) != 0xDC00)
2749227825Stheraven                break;
2750227825Stheraven            uint32_t t = static_cast<uint32_t>(
2751227825Stheraven                    ((((c1 & 0x03C0) >> 6) + 1) << 16)
2752227825Stheraven                  |   ((c1 & 0x003F) << 10)
2753227825Stheraven                  |    (c2 & 0x03FF));
2754227825Stheraven            if (t > Maxcode)
2755227825Stheraven                break;
2756227825Stheraven            frm_nxt += 4;
2757227825Stheraven        }
2758227825Stheraven    }
2759227825Stheraven    return static_cast<int>(frm_nxt - frm);
2760227825Stheraven}
2761227825Stheraven
2762227825Stheravenstatic
2763227825Stheravencodecvt_base::result
2764227825Stheravenucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2765227825Stheraven                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2766227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2767227825Stheraven{
2768227825Stheraven    frm_nxt = frm;
2769227825Stheraven    to_nxt = to;
2770227825Stheraven    if (mode & generate_header)
2771227825Stheraven    {
2772227825Stheraven        if (to_end-to_nxt < 2)
2773227825Stheraven            return codecvt_base::partial;
2774227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xFF);
2775227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xFE);
2776227825Stheraven    }
2777227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2778227825Stheraven    {
2779227825Stheraven        uint32_t wc = *frm_nxt;
2780227825Stheraven        if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2781227825Stheraven            return codecvt_base::error;
2782227825Stheraven        if (wc < 0x010000)
2783227825Stheraven        {
2784227825Stheraven            if (to_end-to_nxt < 2)
2785227825Stheraven                return codecvt_base::partial;
2786227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc);
2787227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2788227825Stheraven        }
2789227825Stheraven        else
2790227825Stheraven        {
2791227825Stheraven            if (to_end-to_nxt < 4)
2792227825Stheraven                return codecvt_base::partial;
2793227825Stheraven            uint16_t t = static_cast<uint16_t>(
2794227825Stheraven                    0xD800
2795227825Stheraven                  | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2796227825Stheraven                  |   ((wc & 0x00FC00) >> 10));
2797227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t);
2798227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t >> 8);
2799227825Stheraven            t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2800227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t);
2801227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t >> 8);
2802227825Stheraven        }
2803227825Stheraven    }
2804227825Stheraven    return codecvt_base::ok;
2805227825Stheraven}
2806227825Stheraven
2807227825Stheravenstatic
2808227825Stheravencodecvt_base::result
2809227825Stheravenutf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2810227825Stheraven                uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2811227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2812227825Stheraven{
2813227825Stheraven    frm_nxt = frm;
2814227825Stheraven    to_nxt = to;
2815227825Stheraven    if (mode & consume_header)
2816227825Stheraven    {
2817227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2818227825Stheraven            frm_nxt += 2;
2819227825Stheraven    }
2820227825Stheraven    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2821227825Stheraven    {
2822232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2823227825Stheraven        if ((c1 & 0xFC00) == 0xDC00)
2824227825Stheraven            return codecvt_base::error;
2825227825Stheraven        if ((c1 & 0xFC00) != 0xD800)
2826227825Stheraven        {
2827227825Stheraven            if (c1 > Maxcode)
2828227825Stheraven                return codecvt_base::error;
2829227825Stheraven            *to_nxt = static_cast<uint32_t>(c1);
2830227825Stheraven            frm_nxt += 2;
2831227825Stheraven        }
2832227825Stheraven        else
2833227825Stheraven        {
2834227825Stheraven            if (frm_end-frm_nxt < 4)
2835227825Stheraven                return codecvt_base::partial;
2836232950Stheraven            uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
2837227825Stheraven            if ((c2 & 0xFC00) != 0xDC00)
2838227825Stheraven                return codecvt_base::error;
2839227825Stheraven            uint32_t t = static_cast<uint32_t>(
2840227825Stheraven                    ((((c1 & 0x03C0) >> 6) + 1) << 16)
2841227825Stheraven                  |   ((c1 & 0x003F) << 10)
2842227825Stheraven                  |    (c2 & 0x03FF));
2843227825Stheraven            if (t > Maxcode)
2844227825Stheraven                return codecvt_base::error;
2845227825Stheraven            *to_nxt = t;
2846227825Stheraven            frm_nxt += 4;
2847227825Stheraven        }
2848227825Stheraven    }
2849227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2850227825Stheraven}
2851227825Stheraven
2852227825Stheravenstatic
2853227825Stheravenint
2854227825Stheravenutf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2855227825Stheraven                       size_t mx, unsigned long Maxcode = 0x10FFFF,
2856227825Stheraven                       codecvt_mode mode = codecvt_mode(0))
2857227825Stheraven{
2858227825Stheraven    const uint8_t* frm_nxt = frm;
2859227825Stheraven    if (mode & consume_header)
2860227825Stheraven    {
2861227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2862227825Stheraven            frm_nxt += 2;
2863227825Stheraven    }
2864227825Stheraven    for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2865227825Stheraven    {
2866232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2867227825Stheraven        if ((c1 & 0xFC00) == 0xDC00)
2868227825Stheraven            break;
2869227825Stheraven        if ((c1 & 0xFC00) != 0xD800)
2870227825Stheraven        {
2871227825Stheraven            if (c1 > Maxcode)
2872227825Stheraven                break;
2873227825Stheraven            frm_nxt += 2;
2874227825Stheraven        }
2875227825Stheraven        else
2876227825Stheraven        {
2877227825Stheraven            if (frm_end-frm_nxt < 4)
2878227825Stheraven                break;
2879232950Stheraven            uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
2880227825Stheraven            if ((c2 & 0xFC00) != 0xDC00)
2881227825Stheraven                break;
2882227825Stheraven            uint32_t t = static_cast<uint32_t>(
2883227825Stheraven                    ((((c1 & 0x03C0) >> 6) + 1) << 16)
2884227825Stheraven                  |   ((c1 & 0x003F) << 10)
2885227825Stheraven                  |    (c2 & 0x03FF));
2886227825Stheraven            if (t > Maxcode)
2887227825Stheraven                break;
2888227825Stheraven            frm_nxt += 4;
2889227825Stheraven        }
2890227825Stheraven    }
2891227825Stheraven    return static_cast<int>(frm_nxt - frm);
2892227825Stheraven}
2893227825Stheraven
2894227825Stheravenstatic
2895227825Stheravencodecvt_base::result
2896227825Stheravenucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2897227825Stheraven                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2898227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2899227825Stheraven{
2900227825Stheraven    frm_nxt = frm;
2901227825Stheraven    to_nxt = to;
2902227825Stheraven    if (mode & generate_header)
2903227825Stheraven    {
2904227825Stheraven        if (to_end-to_nxt < 2)
2905227825Stheraven            return codecvt_base::partial;
2906227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFE);
2907227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFF);
2908227825Stheraven    }
2909227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2910227825Stheraven    {
2911227825Stheraven        uint16_t wc = *frm_nxt;
2912227825Stheraven        if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2913227825Stheraven            return codecvt_base::error;
2914227825Stheraven        if (to_end-to_nxt < 2)
2915227825Stheraven            return codecvt_base::partial;
2916227825Stheraven        *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2917227825Stheraven        *to_nxt++ = static_cast<uint8_t>(wc);
2918227825Stheraven    }
2919227825Stheraven    return codecvt_base::ok;
2920227825Stheraven}
2921227825Stheraven
2922227825Stheravenstatic
2923227825Stheravencodecvt_base::result
2924227825Stheravenutf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2925227825Stheraven                uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2926227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2927227825Stheraven{
2928227825Stheraven    frm_nxt = frm;
2929227825Stheraven    to_nxt = to;
2930227825Stheraven    if (mode & consume_header)
2931227825Stheraven    {
2932227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2933227825Stheraven            frm_nxt += 2;
2934227825Stheraven    }
2935227825Stheraven    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2936227825Stheraven    {
2937232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2938227825Stheraven        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2939227825Stheraven            return codecvt_base::error;
2940227825Stheraven        *to_nxt = c1;
2941227825Stheraven        frm_nxt += 2;
2942227825Stheraven    }
2943227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2944227825Stheraven}
2945227825Stheraven
2946227825Stheravenstatic
2947227825Stheravenint
2948227825Stheravenutf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2949227825Stheraven                       size_t mx, unsigned long Maxcode = 0x10FFFF,
2950227825Stheraven                       codecvt_mode mode = codecvt_mode(0))
2951227825Stheraven{
2952227825Stheraven    const uint8_t* frm_nxt = frm;
2953227825Stheraven    if (mode & consume_header)
2954227825Stheraven    {
2955227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2956227825Stheraven            frm_nxt += 2;
2957227825Stheraven    }
2958227825Stheraven    for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2959227825Stheraven    {
2960232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2961227825Stheraven        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2962227825Stheraven            break;
2963227825Stheraven        frm_nxt += 2;
2964227825Stheraven    }
2965227825Stheraven    return static_cast<int>(frm_nxt - frm);
2966227825Stheraven}
2967227825Stheraven
2968227825Stheravenstatic
2969227825Stheravencodecvt_base::result
2970227825Stheravenucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2971227825Stheraven                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2972227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2973227825Stheraven{
2974227825Stheraven    frm_nxt = frm;
2975227825Stheraven    to_nxt = to;
2976227825Stheraven    if (mode & generate_header)
2977227825Stheraven    {
2978227825Stheraven        if (to_end-to_nxt < 2)
2979227825Stheraven            return codecvt_base::partial;
2980227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFF);
2981227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFE);
2982227825Stheraven    }
2983227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2984227825Stheraven    {
2985227825Stheraven        uint16_t wc = *frm_nxt;
2986227825Stheraven        if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2987227825Stheraven            return codecvt_base::error;
2988227825Stheraven        if (to_end-to_nxt < 2)
2989227825Stheraven            return codecvt_base::partial;
2990227825Stheraven        *to_nxt++ = static_cast<uint8_t>(wc);
2991227825Stheraven        *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2992227825Stheraven    }
2993227825Stheraven    return codecvt_base::ok;
2994227825Stheraven}
2995227825Stheraven
2996227825Stheravenstatic
2997227825Stheravencodecvt_base::result
2998227825Stheravenutf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2999227825Stheraven                uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3000227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3001227825Stheraven{
3002227825Stheraven    frm_nxt = frm;
3003227825Stheraven    to_nxt = to;
3004227825Stheraven    if (mode & consume_header)
3005227825Stheraven    {
3006227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3007227825Stheraven            frm_nxt += 2;
3008227825Stheraven    }
3009227825Stheraven    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3010227825Stheraven    {
3011232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3012227825Stheraven        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3013227825Stheraven            return codecvt_base::error;
3014227825Stheraven        *to_nxt = c1;
3015227825Stheraven        frm_nxt += 2;
3016227825Stheraven    }
3017227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3018227825Stheraven}
3019227825Stheraven
3020227825Stheravenstatic
3021227825Stheravenint
3022227825Stheravenutf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3023227825Stheraven                       size_t mx, unsigned long Maxcode = 0x10FFFF,
3024227825Stheraven                       codecvt_mode mode = codecvt_mode(0))
3025227825Stheraven{
3026227825Stheraven    const uint8_t* frm_nxt = frm;
3027227825Stheraven    frm_nxt = frm;
3028227825Stheraven    if (mode & consume_header)
3029227825Stheraven    {
3030227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3031227825Stheraven            frm_nxt += 2;
3032227825Stheraven    }
3033227825Stheraven    for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3034227825Stheraven    {
3035232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3036227825Stheraven        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3037227825Stheraven            break;
3038227825Stheraven        frm_nxt += 2;
3039227825Stheraven    }
3040227825Stheraven    return static_cast<int>(frm_nxt - frm);
3041227825Stheraven}
3042227825Stheraven
3043227825Stheraven// template <> class codecvt<char16_t, char, mbstate_t>
3044227825Stheraven
3045227825Stheravenlocale::id codecvt<char16_t, char, mbstate_t>::id;
3046227825Stheraven
3047227825Stheravencodecvt<char16_t, char, mbstate_t>::~codecvt()
3048227825Stheraven{
3049227825Stheraven}
3050227825Stheraven
3051227825Stheravencodecvt<char16_t, char, mbstate_t>::result
3052227825Stheravencodecvt<char16_t, char, mbstate_t>::do_out(state_type&,
3053227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3054227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3055227825Stheraven{
3056227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3057227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3058227825Stheraven    const uint16_t* _frm_nxt = _frm;
3059227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3060227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3061227825Stheraven    uint8_t* _to_nxt = _to;
3062227825Stheraven    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3063227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3064227825Stheraven    to_nxt = to + (_to_nxt - _to);
3065227825Stheraven    return r;
3066227825Stheraven}
3067227825Stheraven
3068227825Stheravencodecvt<char16_t, char, mbstate_t>::result
3069227825Stheravencodecvt<char16_t, char, mbstate_t>::do_in(state_type&,
3070227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3071227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3072227825Stheraven{
3073227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3074227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3075227825Stheraven    const uint8_t* _frm_nxt = _frm;
3076227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3077227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3078227825Stheraven    uint16_t* _to_nxt = _to;
3079227825Stheraven    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3080227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3081227825Stheraven    to_nxt = to + (_to_nxt - _to);
3082227825Stheraven    return r;
3083227825Stheraven}
3084227825Stheraven
3085227825Stheravencodecvt<char16_t, char, mbstate_t>::result
3086227825Stheravencodecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3087227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3088227825Stheraven{
3089227825Stheraven    to_nxt = to;
3090227825Stheraven    return noconv;
3091227825Stheraven}
3092227825Stheraven
3093227825Stheravenint
3094227825Stheravencodecvt<char16_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
3095227825Stheraven{
3096227825Stheraven    return 0;
3097227825Stheraven}
3098227825Stheraven
3099227825Stheravenbool
3100227825Stheravencodecvt<char16_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
3101227825Stheraven{
3102227825Stheraven    return false;
3103227825Stheraven}
3104227825Stheraven
3105227825Stheravenint
3106227825Stheravencodecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3107227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3108227825Stheraven{
3109227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3110227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3111227825Stheraven    return utf8_to_utf16_length(_frm, _frm_end, mx);
3112227825Stheraven}
3113227825Stheraven
3114227825Stheravenint
3115227825Stheravencodecvt<char16_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
3116227825Stheraven{
3117227825Stheraven    return 4;
3118227825Stheraven}
3119227825Stheraven
3120227825Stheraven// template <> class codecvt<char32_t, char, mbstate_t>
3121227825Stheraven
3122227825Stheravenlocale::id codecvt<char32_t, char, mbstate_t>::id;
3123227825Stheraven
3124227825Stheravencodecvt<char32_t, char, mbstate_t>::~codecvt()
3125227825Stheraven{
3126227825Stheraven}
3127227825Stheraven
3128227825Stheravencodecvt<char32_t, char, mbstate_t>::result
3129227825Stheravencodecvt<char32_t, char, mbstate_t>::do_out(state_type&,
3130227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3131227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3132227825Stheraven{
3133227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3134227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3135227825Stheraven    const uint32_t* _frm_nxt = _frm;
3136227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3137227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3138227825Stheraven    uint8_t* _to_nxt = _to;
3139227825Stheraven    result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3140227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3141227825Stheraven    to_nxt = to + (_to_nxt - _to);
3142227825Stheraven    return r;
3143227825Stheraven}
3144227825Stheraven
3145227825Stheravencodecvt<char32_t, char, mbstate_t>::result
3146227825Stheravencodecvt<char32_t, char, mbstate_t>::do_in(state_type&,
3147227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3148227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3149227825Stheraven{
3150227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3151227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3152227825Stheraven    const uint8_t* _frm_nxt = _frm;
3153227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3154227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3155227825Stheraven    uint32_t* _to_nxt = _to;
3156227825Stheraven    result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3157227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3158227825Stheraven    to_nxt = to + (_to_nxt - _to);
3159227825Stheraven    return r;
3160227825Stheraven}
3161227825Stheraven
3162227825Stheravencodecvt<char32_t, char, mbstate_t>::result
3163227825Stheravencodecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3164227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3165227825Stheraven{
3166227825Stheraven    to_nxt = to;
3167227825Stheraven    return noconv;
3168227825Stheraven}
3169227825Stheraven
3170227825Stheravenint
3171227825Stheravencodecvt<char32_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
3172227825Stheraven{
3173227825Stheraven    return 0;
3174227825Stheraven}
3175227825Stheraven
3176227825Stheravenbool
3177227825Stheravencodecvt<char32_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
3178227825Stheraven{
3179227825Stheraven    return false;
3180227825Stheraven}
3181227825Stheraven
3182227825Stheravenint
3183227825Stheravencodecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3184227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3185227825Stheraven{
3186227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3187227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3188227825Stheraven    return utf8_to_ucs4_length(_frm, _frm_end, mx);
3189227825Stheraven}
3190227825Stheraven
3191227825Stheravenint
3192227825Stheravencodecvt<char32_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
3193227825Stheraven{
3194227825Stheraven    return 4;
3195227825Stheraven}
3196227825Stheraven
3197227825Stheraven// __codecvt_utf8<wchar_t>
3198227825Stheraven
3199227825Stheraven__codecvt_utf8<wchar_t>::result
3200227825Stheraven__codecvt_utf8<wchar_t>::do_out(state_type&,
3201227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3202227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3203227825Stheraven{
3204227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3205227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3206227825Stheraven    const uint32_t* _frm_nxt = _frm;
3207227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3208227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3209227825Stheraven    uint8_t* _to_nxt = _to;
3210227825Stheraven    result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3211227825Stheraven                            _Maxcode_, _Mode_);
3212227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3213227825Stheraven    to_nxt = to + (_to_nxt - _to);
3214227825Stheraven    return r;
3215227825Stheraven}
3216227825Stheraven
3217227825Stheraven__codecvt_utf8<wchar_t>::result
3218227825Stheraven__codecvt_utf8<wchar_t>::do_in(state_type&,
3219227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3220227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3221227825Stheraven{
3222227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3223227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3224227825Stheraven    const uint8_t* _frm_nxt = _frm;
3225227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3226227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3227227825Stheraven    uint32_t* _to_nxt = _to;
3228227825Stheraven    result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3229227825Stheraven                            _Maxcode_, _Mode_);
3230227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3231227825Stheraven    to_nxt = to + (_to_nxt - _to);
3232227825Stheraven    return r;
3233227825Stheraven}
3234227825Stheraven
3235227825Stheraven__codecvt_utf8<wchar_t>::result
3236227825Stheraven__codecvt_utf8<wchar_t>::do_unshift(state_type&,
3237227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3238227825Stheraven{
3239227825Stheraven    to_nxt = to;
3240227825Stheraven    return noconv;
3241227825Stheraven}
3242227825Stheraven
3243227825Stheravenint
3244227825Stheraven__codecvt_utf8<wchar_t>::do_encoding() const  _NOEXCEPT
3245227825Stheraven{
3246227825Stheraven    return 0;
3247227825Stheraven}
3248227825Stheraven
3249227825Stheravenbool
3250227825Stheraven__codecvt_utf8<wchar_t>::do_always_noconv() const  _NOEXCEPT
3251227825Stheraven{
3252227825Stheraven    return false;
3253227825Stheraven}
3254227825Stheraven
3255227825Stheravenint
3256227825Stheraven__codecvt_utf8<wchar_t>::do_length(state_type&,
3257227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3258227825Stheraven{
3259227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3260227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3261227825Stheraven    return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3262227825Stheraven}
3263227825Stheraven
3264227825Stheravenint
3265227825Stheraven__codecvt_utf8<wchar_t>::do_max_length() const  _NOEXCEPT
3266227825Stheraven{
3267227825Stheraven    if (_Mode_ & consume_header)
3268227825Stheraven        return 7;
3269227825Stheraven    return 4;
3270227825Stheraven}
3271227825Stheraven
3272227825Stheraven// __codecvt_utf8<char16_t>
3273227825Stheraven
3274227825Stheraven__codecvt_utf8<char16_t>::result
3275227825Stheraven__codecvt_utf8<char16_t>::do_out(state_type&,
3276227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3277227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3278227825Stheraven{
3279227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3280227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3281227825Stheraven    const uint16_t* _frm_nxt = _frm;
3282227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3283227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3284227825Stheraven    uint8_t* _to_nxt = _to;
3285227825Stheraven    result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3286227825Stheraven                            _Maxcode_, _Mode_);
3287227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3288227825Stheraven    to_nxt = to + (_to_nxt - _to);
3289227825Stheraven    return r;
3290227825Stheraven}
3291227825Stheraven
3292227825Stheraven__codecvt_utf8<char16_t>::result
3293227825Stheraven__codecvt_utf8<char16_t>::do_in(state_type&,
3294227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3295227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3296227825Stheraven{
3297227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3298227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3299227825Stheraven    const uint8_t* _frm_nxt = _frm;
3300227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3301227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3302227825Stheraven    uint16_t* _to_nxt = _to;
3303227825Stheraven    result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3304227825Stheraven                            _Maxcode_, _Mode_);
3305227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3306227825Stheraven    to_nxt = to + (_to_nxt - _to);
3307227825Stheraven    return r;
3308227825Stheraven}
3309227825Stheraven
3310227825Stheraven__codecvt_utf8<char16_t>::result
3311227825Stheraven__codecvt_utf8<char16_t>::do_unshift(state_type&,
3312227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3313227825Stheraven{
3314227825Stheraven    to_nxt = to;
3315227825Stheraven    return noconv;
3316227825Stheraven}
3317227825Stheraven
3318227825Stheravenint
3319227825Stheraven__codecvt_utf8<char16_t>::do_encoding() const  _NOEXCEPT
3320227825Stheraven{
3321227825Stheraven    return 0;
3322227825Stheraven}
3323227825Stheraven
3324227825Stheravenbool
3325227825Stheraven__codecvt_utf8<char16_t>::do_always_noconv() const  _NOEXCEPT
3326227825Stheraven{
3327227825Stheraven    return false;
3328227825Stheraven}
3329227825Stheraven
3330227825Stheravenint
3331227825Stheraven__codecvt_utf8<char16_t>::do_length(state_type&,
3332227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3333227825Stheraven{
3334227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3335227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3336227825Stheraven    return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3337227825Stheraven}
3338227825Stheraven
3339227825Stheravenint
3340227825Stheraven__codecvt_utf8<char16_t>::do_max_length() const  _NOEXCEPT
3341227825Stheraven{
3342227825Stheraven    if (_Mode_ & consume_header)
3343227825Stheraven        return 6;
3344227825Stheraven    return 3;
3345227825Stheraven}
3346227825Stheraven
3347227825Stheraven// __codecvt_utf8<char32_t>
3348227825Stheraven
3349227825Stheraven__codecvt_utf8<char32_t>::result
3350227825Stheraven__codecvt_utf8<char32_t>::do_out(state_type&,
3351227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3352227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3353227825Stheraven{
3354227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3355227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3356227825Stheraven    const uint32_t* _frm_nxt = _frm;
3357227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3358227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3359227825Stheraven    uint8_t* _to_nxt = _to;
3360227825Stheraven    result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3361227825Stheraven                            _Maxcode_, _Mode_);
3362227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3363227825Stheraven    to_nxt = to + (_to_nxt - _to);
3364227825Stheraven    return r;
3365227825Stheraven}
3366227825Stheraven
3367227825Stheraven__codecvt_utf8<char32_t>::result
3368227825Stheraven__codecvt_utf8<char32_t>::do_in(state_type&,
3369227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3370227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3371227825Stheraven{
3372227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3373227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3374227825Stheraven    const uint8_t* _frm_nxt = _frm;
3375227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3376227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3377227825Stheraven    uint32_t* _to_nxt = _to;
3378227825Stheraven    result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3379227825Stheraven                            _Maxcode_, _Mode_);
3380227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3381227825Stheraven    to_nxt = to + (_to_nxt - _to);
3382227825Stheraven    return r;
3383227825Stheraven}
3384227825Stheraven
3385227825Stheraven__codecvt_utf8<char32_t>::result
3386227825Stheraven__codecvt_utf8<char32_t>::do_unshift(state_type&,
3387227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3388227825Stheraven{
3389227825Stheraven    to_nxt = to;
3390227825Stheraven    return noconv;
3391227825Stheraven}
3392227825Stheraven
3393227825Stheravenint
3394227825Stheraven__codecvt_utf8<char32_t>::do_encoding() const  _NOEXCEPT
3395227825Stheraven{
3396227825Stheraven    return 0;
3397227825Stheraven}
3398227825Stheraven
3399227825Stheravenbool
3400227825Stheraven__codecvt_utf8<char32_t>::do_always_noconv() const  _NOEXCEPT
3401227825Stheraven{
3402227825Stheraven    return false;
3403227825Stheraven}
3404227825Stheraven
3405227825Stheravenint
3406227825Stheraven__codecvt_utf8<char32_t>::do_length(state_type&,
3407227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3408227825Stheraven{
3409227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3410227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3411227825Stheraven    return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3412227825Stheraven}
3413227825Stheraven
3414227825Stheravenint
3415227825Stheraven__codecvt_utf8<char32_t>::do_max_length() const  _NOEXCEPT
3416227825Stheraven{
3417227825Stheraven    if (_Mode_ & consume_header)
3418227825Stheraven        return 7;
3419227825Stheraven    return 4;
3420227825Stheraven}
3421227825Stheraven
3422227825Stheraven// __codecvt_utf16<wchar_t, false>
3423227825Stheraven
3424227825Stheraven__codecvt_utf16<wchar_t, false>::result
3425227825Stheraven__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3426227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3427227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3428227825Stheraven{
3429227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3430227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3431227825Stheraven    const uint32_t* _frm_nxt = _frm;
3432227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3433227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3434227825Stheraven    uint8_t* _to_nxt = _to;
3435227825Stheraven    result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3436227825Stheraven                               _Maxcode_, _Mode_);
3437227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3438227825Stheraven    to_nxt = to + (_to_nxt - _to);
3439227825Stheraven    return r;
3440227825Stheraven}
3441227825Stheraven
3442227825Stheraven__codecvt_utf16<wchar_t, false>::result
3443227825Stheraven__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3444227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3445227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3446227825Stheraven{
3447227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3448227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3449227825Stheraven    const uint8_t* _frm_nxt = _frm;
3450227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3451227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3452227825Stheraven    uint32_t* _to_nxt = _to;
3453227825Stheraven    result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3454227825Stheraven                               _Maxcode_, _Mode_);
3455227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3456227825Stheraven    to_nxt = to + (_to_nxt - _to);
3457227825Stheraven    return r;
3458227825Stheraven}
3459227825Stheraven
3460227825Stheraven__codecvt_utf16<wchar_t, false>::result
3461227825Stheraven__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3462227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3463227825Stheraven{
3464227825Stheraven    to_nxt = to;
3465227825Stheraven    return noconv;
3466227825Stheraven}
3467227825Stheraven
3468227825Stheravenint
3469227825Stheraven__codecvt_utf16<wchar_t, false>::do_encoding() const  _NOEXCEPT
3470227825Stheraven{
3471227825Stheraven    return 0;
3472227825Stheraven}
3473227825Stheraven
3474227825Stheravenbool
3475227825Stheraven__codecvt_utf16<wchar_t, false>::do_always_noconv() const  _NOEXCEPT
3476227825Stheraven{
3477227825Stheraven    return false;
3478227825Stheraven}
3479227825Stheraven
3480227825Stheravenint
3481227825Stheraven__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3482227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3483227825Stheraven{
3484227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3485227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3486227825Stheraven    return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3487227825Stheraven}
3488227825Stheraven
3489227825Stheravenint
3490227825Stheraven__codecvt_utf16<wchar_t, false>::do_max_length() const  _NOEXCEPT
3491227825Stheraven{
3492227825Stheraven    if (_Mode_ & consume_header)
3493227825Stheraven        return 6;
3494227825Stheraven    return 4;
3495227825Stheraven}
3496227825Stheraven
3497227825Stheraven// __codecvt_utf16<wchar_t, true>
3498227825Stheraven
3499227825Stheraven__codecvt_utf16<wchar_t, true>::result
3500227825Stheraven__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3501227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3502227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3503227825Stheraven{
3504227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3505227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3506227825Stheraven    const uint32_t* _frm_nxt = _frm;
3507227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3508227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3509227825Stheraven    uint8_t* _to_nxt = _to;
3510227825Stheraven    result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3511227825Stheraven                               _Maxcode_, _Mode_);
3512227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3513227825Stheraven    to_nxt = to + (_to_nxt - _to);
3514227825Stheraven    return r;
3515227825Stheraven}
3516227825Stheraven
3517227825Stheraven__codecvt_utf16<wchar_t, true>::result
3518227825Stheraven__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3519227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3520227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3521227825Stheraven{
3522227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3523227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3524227825Stheraven    const uint8_t* _frm_nxt = _frm;
3525227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3526227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3527227825Stheraven    uint32_t* _to_nxt = _to;
3528227825Stheraven    result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3529227825Stheraven                               _Maxcode_, _Mode_);
3530227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3531227825Stheraven    to_nxt = to + (_to_nxt - _to);
3532227825Stheraven    return r;
3533227825Stheraven}
3534227825Stheraven
3535227825Stheraven__codecvt_utf16<wchar_t, true>::result
3536227825Stheraven__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3537227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3538227825Stheraven{
3539227825Stheraven    to_nxt = to;
3540227825Stheraven    return noconv;
3541227825Stheraven}
3542227825Stheraven
3543227825Stheravenint
3544227825Stheraven__codecvt_utf16<wchar_t, true>::do_encoding() const  _NOEXCEPT
3545227825Stheraven{
3546227825Stheraven    return 0;
3547227825Stheraven}
3548227825Stheraven
3549227825Stheravenbool
3550227825Stheraven__codecvt_utf16<wchar_t, true>::do_always_noconv() const  _NOEXCEPT
3551227825Stheraven{
3552227825Stheraven    return false;
3553227825Stheraven}
3554227825Stheraven
3555227825Stheravenint
3556227825Stheraven__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3557227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3558227825Stheraven{
3559227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3560227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3561227825Stheraven    return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3562227825Stheraven}
3563227825Stheraven
3564227825Stheravenint
3565227825Stheraven__codecvt_utf16<wchar_t, true>::do_max_length() const  _NOEXCEPT
3566227825Stheraven{
3567227825Stheraven    if (_Mode_ & consume_header)
3568227825Stheraven        return 6;
3569227825Stheraven    return 4;
3570227825Stheraven}
3571227825Stheraven
3572227825Stheraven// __codecvt_utf16<char16_t, false>
3573227825Stheraven
3574227825Stheraven__codecvt_utf16<char16_t, false>::result
3575227825Stheraven__codecvt_utf16<char16_t, false>::do_out(state_type&,
3576227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3577227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3578227825Stheraven{
3579227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3580227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3581227825Stheraven    const uint16_t* _frm_nxt = _frm;
3582227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3583227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3584227825Stheraven    uint8_t* _to_nxt = _to;
3585227825Stheraven    result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3586227825Stheraven                               _Maxcode_, _Mode_);
3587227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3588227825Stheraven    to_nxt = to + (_to_nxt - _to);
3589227825Stheraven    return r;
3590227825Stheraven}
3591227825Stheraven
3592227825Stheraven__codecvt_utf16<char16_t, false>::result
3593227825Stheraven__codecvt_utf16<char16_t, false>::do_in(state_type&,
3594227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3595227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3596227825Stheraven{
3597227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3598227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3599227825Stheraven    const uint8_t* _frm_nxt = _frm;
3600227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3601227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3602227825Stheraven    uint16_t* _to_nxt = _to;
3603227825Stheraven    result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3604227825Stheraven                               _Maxcode_, _Mode_);
3605227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3606227825Stheraven    to_nxt = to + (_to_nxt - _to);
3607227825Stheraven    return r;
3608227825Stheraven}
3609227825Stheraven
3610227825Stheraven__codecvt_utf16<char16_t, false>::result
3611227825Stheraven__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3612227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3613227825Stheraven{
3614227825Stheraven    to_nxt = to;
3615227825Stheraven    return noconv;
3616227825Stheraven}
3617227825Stheraven
3618227825Stheravenint
3619227825Stheraven__codecvt_utf16<char16_t, false>::do_encoding() const  _NOEXCEPT
3620227825Stheraven{
3621227825Stheraven    return 0;
3622227825Stheraven}
3623227825Stheraven
3624227825Stheravenbool
3625227825Stheraven__codecvt_utf16<char16_t, false>::do_always_noconv() const  _NOEXCEPT
3626227825Stheraven{
3627227825Stheraven    return false;
3628227825Stheraven}
3629227825Stheraven
3630227825Stheravenint
3631227825Stheraven__codecvt_utf16<char16_t, false>::do_length(state_type&,
3632227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3633227825Stheraven{
3634227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3635227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3636227825Stheraven    return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3637227825Stheraven}
3638227825Stheraven
3639227825Stheravenint
3640227825Stheraven__codecvt_utf16<char16_t, false>::do_max_length() const  _NOEXCEPT
3641227825Stheraven{
3642227825Stheraven    if (_Mode_ & consume_header)
3643227825Stheraven        return 4;
3644227825Stheraven    return 2;
3645227825Stheraven}
3646227825Stheraven
3647227825Stheraven// __codecvt_utf16<char16_t, true>
3648227825Stheraven
3649227825Stheraven__codecvt_utf16<char16_t, true>::result
3650227825Stheraven__codecvt_utf16<char16_t, true>::do_out(state_type&,
3651227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3652227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3653227825Stheraven{
3654227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3655227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3656227825Stheraven    const uint16_t* _frm_nxt = _frm;
3657227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3658227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3659227825Stheraven    uint8_t* _to_nxt = _to;
3660227825Stheraven    result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3661227825Stheraven                               _Maxcode_, _Mode_);
3662227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3663227825Stheraven    to_nxt = to + (_to_nxt - _to);
3664227825Stheraven    return r;
3665227825Stheraven}
3666227825Stheraven
3667227825Stheraven__codecvt_utf16<char16_t, true>::result
3668227825Stheraven__codecvt_utf16<char16_t, true>::do_in(state_type&,
3669227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3670227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3671227825Stheraven{
3672227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3673227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3674227825Stheraven    const uint8_t* _frm_nxt = _frm;
3675227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3676227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3677227825Stheraven    uint16_t* _to_nxt = _to;
3678227825Stheraven    result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3679227825Stheraven                               _Maxcode_, _Mode_);
3680227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3681227825Stheraven    to_nxt = to + (_to_nxt - _to);
3682227825Stheraven    return r;
3683227825Stheraven}
3684227825Stheraven
3685227825Stheraven__codecvt_utf16<char16_t, true>::result
3686227825Stheraven__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3687227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3688227825Stheraven{
3689227825Stheraven    to_nxt = to;
3690227825Stheraven    return noconv;
3691227825Stheraven}
3692227825Stheraven
3693227825Stheravenint
3694227825Stheraven__codecvt_utf16<char16_t, true>::do_encoding() const  _NOEXCEPT
3695227825Stheraven{
3696227825Stheraven    return 0;
3697227825Stheraven}
3698227825Stheraven
3699227825Stheravenbool
3700227825Stheraven__codecvt_utf16<char16_t, true>::do_always_noconv() const  _NOEXCEPT
3701227825Stheraven{
3702227825Stheraven    return false;
3703227825Stheraven}
3704227825Stheraven
3705227825Stheravenint
3706227825Stheraven__codecvt_utf16<char16_t, true>::do_length(state_type&,
3707227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3708227825Stheraven{
3709227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3710227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3711227825Stheraven    return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3712227825Stheraven}
3713227825Stheraven
3714227825Stheravenint
3715227825Stheraven__codecvt_utf16<char16_t, true>::do_max_length() const  _NOEXCEPT
3716227825Stheraven{
3717227825Stheraven    if (_Mode_ & consume_header)
3718227825Stheraven        return 4;
3719227825Stheraven    return 2;
3720227825Stheraven}
3721227825Stheraven
3722227825Stheraven// __codecvt_utf16<char32_t, false>
3723227825Stheraven
3724227825Stheraven__codecvt_utf16<char32_t, false>::result
3725227825Stheraven__codecvt_utf16<char32_t, false>::do_out(state_type&,
3726227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3727227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3728227825Stheraven{
3729227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3730227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3731227825Stheraven    const uint32_t* _frm_nxt = _frm;
3732227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3733227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3734227825Stheraven    uint8_t* _to_nxt = _to;
3735227825Stheraven    result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3736227825Stheraven                               _Maxcode_, _Mode_);
3737227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3738227825Stheraven    to_nxt = to + (_to_nxt - _to);
3739227825Stheraven    return r;
3740227825Stheraven}
3741227825Stheraven
3742227825Stheraven__codecvt_utf16<char32_t, false>::result
3743227825Stheraven__codecvt_utf16<char32_t, false>::do_in(state_type&,
3744227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3745227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3746227825Stheraven{
3747227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3748227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3749227825Stheraven    const uint8_t* _frm_nxt = _frm;
3750227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3751227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3752227825Stheraven    uint32_t* _to_nxt = _to;
3753227825Stheraven    result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3754227825Stheraven                               _Maxcode_, _Mode_);
3755227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3756227825Stheraven    to_nxt = to + (_to_nxt - _to);
3757227825Stheraven    return r;
3758227825Stheraven}
3759227825Stheraven
3760227825Stheraven__codecvt_utf16<char32_t, false>::result
3761227825Stheraven__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3762227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3763227825Stheraven{
3764227825Stheraven    to_nxt = to;
3765227825Stheraven    return noconv;
3766227825Stheraven}
3767227825Stheraven
3768227825Stheravenint
3769227825Stheraven__codecvt_utf16<char32_t, false>::do_encoding() const  _NOEXCEPT
3770227825Stheraven{
3771227825Stheraven    return 0;
3772227825Stheraven}
3773227825Stheraven
3774227825Stheravenbool
3775227825Stheraven__codecvt_utf16<char32_t, false>::do_always_noconv() const  _NOEXCEPT
3776227825Stheraven{
3777227825Stheraven    return false;
3778227825Stheraven}
3779227825Stheraven
3780227825Stheravenint
3781227825Stheraven__codecvt_utf16<char32_t, false>::do_length(state_type&,
3782227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3783227825Stheraven{
3784227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3785227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3786227825Stheraven    return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3787227825Stheraven}
3788227825Stheraven
3789227825Stheravenint
3790227825Stheraven__codecvt_utf16<char32_t, false>::do_max_length() const  _NOEXCEPT
3791227825Stheraven{
3792227825Stheraven    if (_Mode_ & consume_header)
3793227825Stheraven        return 6;
3794227825Stheraven    return 4;
3795227825Stheraven}
3796227825Stheraven
3797227825Stheraven// __codecvt_utf16<char32_t, true>
3798227825Stheraven
3799227825Stheraven__codecvt_utf16<char32_t, true>::result
3800227825Stheraven__codecvt_utf16<char32_t, true>::do_out(state_type&,
3801227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3802227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3803227825Stheraven{
3804227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3805227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3806227825Stheraven    const uint32_t* _frm_nxt = _frm;
3807227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3808227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3809227825Stheraven    uint8_t* _to_nxt = _to;
3810227825Stheraven    result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3811227825Stheraven                               _Maxcode_, _Mode_);
3812227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3813227825Stheraven    to_nxt = to + (_to_nxt - _to);
3814227825Stheraven    return r;
3815227825Stheraven}
3816227825Stheraven
3817227825Stheraven__codecvt_utf16<char32_t, true>::result
3818227825Stheraven__codecvt_utf16<char32_t, true>::do_in(state_type&,
3819227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3820227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3821227825Stheraven{
3822227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3823227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3824227825Stheraven    const uint8_t* _frm_nxt = _frm;
3825227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3826227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3827227825Stheraven    uint32_t* _to_nxt = _to;
3828227825Stheraven    result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3829227825Stheraven                               _Maxcode_, _Mode_);
3830227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3831227825Stheraven    to_nxt = to + (_to_nxt - _to);
3832227825Stheraven    return r;
3833227825Stheraven}
3834227825Stheraven
3835227825Stheraven__codecvt_utf16<char32_t, true>::result
3836227825Stheraven__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3837227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3838227825Stheraven{
3839227825Stheraven    to_nxt = to;
3840227825Stheraven    return noconv;
3841227825Stheraven}
3842227825Stheraven
3843227825Stheravenint
3844227825Stheraven__codecvt_utf16<char32_t, true>::do_encoding() const  _NOEXCEPT
3845227825Stheraven{
3846227825Stheraven    return 0;
3847227825Stheraven}
3848227825Stheraven
3849227825Stheravenbool
3850227825Stheraven__codecvt_utf16<char32_t, true>::do_always_noconv() const  _NOEXCEPT
3851227825Stheraven{
3852227825Stheraven    return false;
3853227825Stheraven}
3854227825Stheraven
3855227825Stheravenint
3856227825Stheraven__codecvt_utf16<char32_t, true>::do_length(state_type&,
3857227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3858227825Stheraven{
3859227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3860227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3861227825Stheraven    return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3862227825Stheraven}
3863227825Stheraven
3864227825Stheravenint
3865227825Stheraven__codecvt_utf16<char32_t, true>::do_max_length() const  _NOEXCEPT
3866227825Stheraven{
3867227825Stheraven    if (_Mode_ & consume_header)
3868227825Stheraven        return 6;
3869227825Stheraven    return 4;
3870227825Stheraven}
3871227825Stheraven
3872227825Stheraven// __codecvt_utf8_utf16<wchar_t>
3873227825Stheraven
3874227825Stheraven__codecvt_utf8_utf16<wchar_t>::result
3875227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3876227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3877227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3878227825Stheraven{
3879227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3880227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3881227825Stheraven    const uint32_t* _frm_nxt = _frm;
3882227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3883227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3884227825Stheraven    uint8_t* _to_nxt = _to;
3885227825Stheraven    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3886227825Stheraven                             _Maxcode_, _Mode_);
3887227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3888227825Stheraven    to_nxt = to + (_to_nxt - _to);
3889227825Stheraven    return r;
3890227825Stheraven}
3891227825Stheraven
3892227825Stheraven__codecvt_utf8_utf16<wchar_t>::result
3893227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3894227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3895227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3896227825Stheraven{
3897227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3898227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3899227825Stheraven    const uint8_t* _frm_nxt = _frm;
3900227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3901227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3902227825Stheraven    uint32_t* _to_nxt = _to;
3903227825Stheraven    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3904227825Stheraven                             _Maxcode_, _Mode_);
3905227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3906227825Stheraven    to_nxt = to + (_to_nxt - _to);
3907227825Stheraven    return r;
3908227825Stheraven}
3909227825Stheraven
3910227825Stheraven__codecvt_utf8_utf16<wchar_t>::result
3911227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3912227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3913227825Stheraven{
3914227825Stheraven    to_nxt = to;
3915227825Stheraven    return noconv;
3916227825Stheraven}
3917227825Stheraven
3918227825Stheravenint
3919227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_encoding() const  _NOEXCEPT
3920227825Stheraven{
3921227825Stheraven    return 0;
3922227825Stheraven}
3923227825Stheraven
3924227825Stheravenbool
3925227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const  _NOEXCEPT
3926227825Stheraven{
3927227825Stheraven    return false;
3928227825Stheraven}
3929227825Stheraven
3930227825Stheravenint
3931227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3932227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3933227825Stheraven{
3934227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3935227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3936227825Stheraven    return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3937227825Stheraven}
3938227825Stheraven
3939227825Stheravenint
3940227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_max_length() const  _NOEXCEPT
3941227825Stheraven{
3942227825Stheraven    if (_Mode_ & consume_header)
3943227825Stheraven        return 7;
3944227825Stheraven    return 4;
3945227825Stheraven}
3946227825Stheraven
3947227825Stheraven// __codecvt_utf8_utf16<char16_t>
3948227825Stheraven
3949227825Stheraven__codecvt_utf8_utf16<char16_t>::result
3950227825Stheraven__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3951227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3952227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3953227825Stheraven{
3954227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3955227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3956227825Stheraven    const uint16_t* _frm_nxt = _frm;
3957227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3958227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3959227825Stheraven    uint8_t* _to_nxt = _to;
3960227825Stheraven    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3961227825Stheraven                             _Maxcode_, _Mode_);
3962227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3963227825Stheraven    to_nxt = to + (_to_nxt - _to);
3964227825Stheraven    return r;
3965227825Stheraven}
3966227825Stheraven
3967227825Stheraven__codecvt_utf8_utf16<char16_t>::result
3968227825Stheraven__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3969227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3970227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3971227825Stheraven{
3972227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3973227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3974227825Stheraven    const uint8_t* _frm_nxt = _frm;
3975227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3976227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3977227825Stheraven    uint16_t* _to_nxt = _to;
3978227825Stheraven    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3979227825Stheraven                             _Maxcode_, _Mode_);
3980227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3981227825Stheraven    to_nxt = to + (_to_nxt - _to);
3982227825Stheraven    return r;
3983227825Stheraven}
3984227825Stheraven
3985227825Stheraven__codecvt_utf8_utf16<char16_t>::result
3986227825Stheraven__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3987227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3988227825Stheraven{
3989227825Stheraven    to_nxt = to;
3990227825Stheraven    return noconv;
3991227825Stheraven}
3992227825Stheraven
3993227825Stheravenint
3994227825Stheraven__codecvt_utf8_utf16<char16_t>::do_encoding() const  _NOEXCEPT
3995227825Stheraven{
3996227825Stheraven    return 0;
3997227825Stheraven}
3998227825Stheraven
3999227825Stheravenbool
4000227825Stheraven__codecvt_utf8_utf16<char16_t>::do_always_noconv() const  _NOEXCEPT
4001227825Stheraven{
4002227825Stheraven    return false;
4003227825Stheraven}
4004227825Stheraven
4005227825Stheravenint
4006227825Stheraven__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4007227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
4008227825Stheraven{
4009227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4010227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4011227825Stheraven    return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4012227825Stheraven}
4013227825Stheraven
4014227825Stheravenint
4015227825Stheraven__codecvt_utf8_utf16<char16_t>::do_max_length() const  _NOEXCEPT
4016227825Stheraven{
4017227825Stheraven    if (_Mode_ & consume_header)
4018227825Stheraven        return 7;
4019227825Stheraven    return 4;
4020227825Stheraven}
4021227825Stheraven
4022227825Stheraven// __codecvt_utf8_utf16<char32_t>
4023227825Stheraven
4024227825Stheraven__codecvt_utf8_utf16<char32_t>::result
4025227825Stheraven__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4026227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4027227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4028227825Stheraven{
4029227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4030227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4031227825Stheraven    const uint32_t* _frm_nxt = _frm;
4032227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4033227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4034227825Stheraven    uint8_t* _to_nxt = _to;
4035227825Stheraven    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4036227825Stheraven                             _Maxcode_, _Mode_);
4037227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
4038227825Stheraven    to_nxt = to + (_to_nxt - _to);
4039227825Stheraven    return r;
4040227825Stheraven}
4041227825Stheraven
4042227825Stheraven__codecvt_utf8_utf16<char32_t>::result
4043227825Stheraven__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4044227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4045227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4046227825Stheraven{
4047227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4048227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4049227825Stheraven    const uint8_t* _frm_nxt = _frm;
4050227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4051227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4052227825Stheraven    uint32_t* _to_nxt = _to;
4053227825Stheraven    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4054227825Stheraven                             _Maxcode_, _Mode_);
4055227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
4056227825Stheraven    to_nxt = to + (_to_nxt - _to);
4057227825Stheraven    return r;
4058227825Stheraven}
4059227825Stheraven
4060227825Stheraven__codecvt_utf8_utf16<char32_t>::result
4061227825Stheraven__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4062227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
4063227825Stheraven{
4064227825Stheraven    to_nxt = to;
4065227825Stheraven    return noconv;
4066227825Stheraven}
4067227825Stheraven
4068227825Stheravenint
4069227825Stheraven__codecvt_utf8_utf16<char32_t>::do_encoding() const  _NOEXCEPT
4070227825Stheraven{
4071227825Stheraven    return 0;
4072227825Stheraven}
4073227825Stheraven
4074227825Stheravenbool
4075227825Stheraven__codecvt_utf8_utf16<char32_t>::do_always_noconv() const  _NOEXCEPT
4076227825Stheraven{
4077227825Stheraven    return false;
4078227825Stheraven}
4079227825Stheraven
4080227825Stheravenint
4081227825Stheraven__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4082227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
4083227825Stheraven{
4084227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4085227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4086227825Stheraven    return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4087227825Stheraven}
4088227825Stheraven
4089227825Stheravenint
4090227825Stheraven__codecvt_utf8_utf16<char32_t>::do_max_length() const  _NOEXCEPT
4091227825Stheraven{
4092227825Stheraven    if (_Mode_ & consume_header)
4093227825Stheraven        return 7;
4094227825Stheraven    return 4;
4095227825Stheraven}
4096227825Stheraven
4097227825Stheraven// __narrow_to_utf8<16>
4098227825Stheraven
4099227825Stheraven__narrow_to_utf8<16>::~__narrow_to_utf8()
4100227825Stheraven{
4101227825Stheraven}
4102227825Stheraven
4103227825Stheraven// __narrow_to_utf8<32>
4104227825Stheraven
4105227825Stheraven__narrow_to_utf8<32>::~__narrow_to_utf8()
4106227825Stheraven{
4107227825Stheraven}
4108227825Stheraven
4109227825Stheraven// __widen_from_utf8<16>
4110227825Stheraven
4111227825Stheraven__widen_from_utf8<16>::~__widen_from_utf8()
4112227825Stheraven{
4113227825Stheraven}
4114227825Stheraven
4115227825Stheraven// __widen_from_utf8<32>
4116227825Stheraven
4117227825Stheraven__widen_from_utf8<32>::~__widen_from_utf8()
4118227825Stheraven{
4119227825Stheraven}
4120227825Stheraven
4121227825Stheraven// numpunct<char> && numpunct<wchar_t>
4122227825Stheraven
4123227825Stheravenlocale::id numpunct< char  >::id;
4124227825Stheravenlocale::id numpunct<wchar_t>::id;
4125227825Stheraven
4126227825Stheravennumpunct<char>::numpunct(size_t refs)
4127227825Stheraven    : locale::facet(refs),
4128227825Stheraven      __decimal_point_('.'),
4129227825Stheraven      __thousands_sep_(',')
4130227825Stheraven{
4131227825Stheraven}
4132227825Stheraven
4133227825Stheravennumpunct<wchar_t>::numpunct(size_t refs)
4134227825Stheraven    : locale::facet(refs),
4135227825Stheraven      __decimal_point_(L'.'),
4136227825Stheraven      __thousands_sep_(L',')
4137227825Stheraven{
4138227825Stheraven}
4139227825Stheraven
4140227825Stheravennumpunct<char>::~numpunct()
4141227825Stheraven{
4142227825Stheraven}
4143227825Stheraven
4144227825Stheravennumpunct<wchar_t>::~numpunct()
4145227825Stheraven{
4146227825Stheraven}
4147227825Stheraven
4148227825Stheraven char   numpunct< char  >::do_decimal_point() const {return __decimal_point_;}
4149227825Stheravenwchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4150227825Stheraven
4151227825Stheraven char   numpunct< char  >::do_thousands_sep() const {return __thousands_sep_;}
4152227825Stheravenwchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4153227825Stheraven
4154227825Stheravenstring numpunct< char  >::do_grouping() const {return __grouping_;}
4155227825Stheravenstring numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4156227825Stheraven
4157227825Stheraven string numpunct< char  >::do_truename() const {return "true";}
4158227825Stheravenwstring numpunct<wchar_t>::do_truename() const {return L"true";}
4159227825Stheraven
4160227825Stheraven string numpunct< char  >::do_falsename() const {return "false";}
4161227825Stheravenwstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4162227825Stheraven
4163227825Stheraven// numpunct_byname<char>
4164227825Stheraven
4165227825Stheravennumpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4166227825Stheraven    : numpunct<char>(refs)
4167227825Stheraven{
4168227825Stheraven    __init(nm);
4169227825Stheraven}
4170227825Stheraven
4171227825Stheravennumpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4172227825Stheraven    : numpunct<char>(refs)
4173227825Stheraven{
4174227825Stheraven    __init(nm.c_str());
4175227825Stheraven}
4176227825Stheraven
4177227825Stheravennumpunct_byname<char>::~numpunct_byname()
4178227825Stheraven{
4179227825Stheraven}
4180227825Stheraven
4181227825Stheravenvoid
4182227825Stheravennumpunct_byname<char>::__init(const char* nm)
4183227825Stheraven{
4184227825Stheraven    if (strcmp(nm, "C") != 0)
4185227825Stheraven    {
4186227825Stheraven        __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
4187227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
4188232950Stheraven        if (loc == nullptr)
4189227825Stheraven            throw runtime_error("numpunct_byname<char>::numpunct_byname"
4190227825Stheraven                                " failed to construct for " + string(nm));
4191227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
4192227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
4193227825Stheraven        lconv* lc = localeconv_l(loc.get());
4194227825Stheraven#else
4195227825Stheraven        lconv* lc = __localeconv_l(loc.get());
4196227825Stheraven#endif
4197227825Stheraven        if (*lc->decimal_point)
4198227825Stheraven            __decimal_point_ = *lc->decimal_point;
4199227825Stheraven        if (*lc->thousands_sep)
4200227825Stheraven            __thousands_sep_ = *lc->thousands_sep;
4201227825Stheraven        __grouping_ = lc->grouping;
4202227825Stheraven        // localization for truename and falsename is not available
4203227825Stheraven    }
4204227825Stheraven}
4205227825Stheraven
4206227825Stheraven// numpunct_byname<wchar_t>
4207227825Stheraven
4208227825Stheravennumpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4209227825Stheraven    : numpunct<wchar_t>(refs)
4210227825Stheraven{
4211227825Stheraven    __init(nm);
4212227825Stheraven}
4213227825Stheraven
4214227825Stheravennumpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4215227825Stheraven    : numpunct<wchar_t>(refs)
4216227825Stheraven{
4217227825Stheraven    __init(nm.c_str());
4218227825Stheraven}
4219227825Stheraven
4220227825Stheravennumpunct_byname<wchar_t>::~numpunct_byname()
4221227825Stheraven{
4222227825Stheraven}
4223227825Stheraven
4224227825Stheravenvoid
4225227825Stheravennumpunct_byname<wchar_t>::__init(const char* nm)
4226227825Stheraven{
4227227825Stheraven    if (strcmp(nm, "C") != 0)
4228227825Stheraven    {
4229227825Stheraven        __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
4230227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
4231232950Stheraven        if (loc == nullptr)
4232227825Stheraven            throw runtime_error("numpunct_byname<char>::numpunct_byname"
4233227825Stheraven                                " failed to construct for " + string(nm));
4234227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
4235227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
4236227825Stheraven        lconv* lc = localeconv_l(loc.get());
4237227825Stheraven#else
4238227825Stheraven        lconv* lc = __localeconv_l(loc.get());
4239227825Stheraven#endif
4240227825Stheraven        if (*lc->decimal_point)
4241227825Stheraven            __decimal_point_ = *lc->decimal_point;
4242227825Stheraven        if (*lc->thousands_sep)
4243227825Stheraven            __thousands_sep_ = *lc->thousands_sep;
4244227825Stheraven        __grouping_ = lc->grouping;
4245227825Stheraven        // locallization for truename and falsename is not available
4246227825Stheraven    }
4247227825Stheraven}
4248227825Stheraven
4249227825Stheraven// num_get helpers
4250227825Stheraven
4251227825Stheravenint
4252227825Stheraven__num_get_base::__get_base(ios_base& iob)
4253227825Stheraven{
4254227825Stheraven    ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4255227825Stheraven    if (__basefield == ios_base::oct)
4256227825Stheraven        return 8;
4257227825Stheraven    else if (__basefield == ios_base::hex)
4258227825Stheraven        return 16;
4259227825Stheraven    else if (__basefield == 0)
4260227825Stheraven        return 0;
4261227825Stheraven    return 10;
4262227825Stheraven}
4263227825Stheraven
4264227825Stheravenconst char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4265227825Stheraven
4266227825Stheravenvoid
4267227825Stheraven__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4268227825Stheraven                 ios_base::iostate& __err)
4269227825Stheraven{
4270227825Stheraven    if (__grouping.size() != 0)
4271227825Stheraven    {
4272227825Stheraven        reverse(__g, __g_end);
4273227825Stheraven        const char* __ig = __grouping.data();
4274227825Stheraven        const char* __eg = __ig + __grouping.size();
4275227825Stheraven        for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4276227825Stheraven        {
4277227825Stheraven            if (0 < *__ig && *__ig < numeric_limits<char>::max())
4278227825Stheraven            {
4279232950Stheraven                if (static_cast<unsigned>(*__ig) != *__r)
4280227825Stheraven                {
4281227825Stheraven                    __err = ios_base::failbit;
4282227825Stheraven                    return;
4283227825Stheraven                }
4284227825Stheraven            }
4285227825Stheraven            if (__eg - __ig > 1)
4286227825Stheraven                ++__ig;
4287227825Stheraven        }
4288227825Stheraven        if (0 < *__ig && *__ig < numeric_limits<char>::max())
4289227825Stheraven        {
4290232950Stheraven            if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
4291227825Stheraven                __err = ios_base::failbit;
4292227825Stheraven        }
4293227825Stheraven    }
4294227825Stheraven}
4295227825Stheraven
4296227825Stheravenvoid
4297227825Stheraven__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4298227825Stheraven                             ios_base::fmtflags __flags)
4299227825Stheraven{
4300227825Stheraven    if (__flags & ios_base::showpos)
4301227825Stheraven        *__fmtp++ = '+';
4302227825Stheraven    if (__flags & ios_base::showbase)
4303227825Stheraven        *__fmtp++ = '#';
4304227825Stheraven    while(*__len)
4305227825Stheraven        *__fmtp++ = *__len++;
4306227825Stheraven    if ((__flags & ios_base::basefield) == ios_base::oct)
4307227825Stheraven        *__fmtp = 'o';
4308227825Stheraven    else if ((__flags & ios_base::basefield) == ios_base::hex)
4309227825Stheraven    {
4310227825Stheraven        if (__flags & ios_base::uppercase)
4311227825Stheraven            *__fmtp = 'X';
4312227825Stheraven        else
4313227825Stheraven            *__fmtp = 'x';
4314227825Stheraven    }
4315227825Stheraven    else if (__signd)
4316227825Stheraven        *__fmtp = 'd';
4317227825Stheraven    else
4318227825Stheraven        *__fmtp = 'u';
4319227825Stheraven}
4320227825Stheraven
4321227825Stheravenbool
4322227825Stheraven__num_put_base::__format_float(char* __fmtp, const char* __len,
4323227825Stheraven                               ios_base::fmtflags __flags)
4324227825Stheraven{
4325227825Stheraven    bool specify_precision = true;
4326227825Stheraven    if (__flags & ios_base::showpos)
4327227825Stheraven        *__fmtp++ = '+';
4328227825Stheraven    if (__flags & ios_base::showpoint)
4329227825Stheraven        *__fmtp++ = '#';
4330227825Stheraven    ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4331227825Stheraven    bool uppercase = __flags & ios_base::uppercase;
4332227825Stheraven    if (floatfield == (ios_base::fixed | ios_base::scientific))
4333227825Stheraven        specify_precision = false;
4334227825Stheraven    else
4335227825Stheraven    {
4336227825Stheraven        *__fmtp++ = '.';
4337227825Stheraven        *__fmtp++ = '*';
4338227825Stheraven    }
4339227825Stheraven    while(*__len)
4340227825Stheraven        *__fmtp++ = *__len++;
4341227825Stheraven    if (floatfield == ios_base::fixed)
4342227825Stheraven    {
4343227825Stheraven        if (uppercase)
4344227825Stheraven            *__fmtp = 'F';
4345227825Stheraven        else
4346227825Stheraven            *__fmtp = 'f';
4347227825Stheraven    }
4348227825Stheraven    else if (floatfield == ios_base::scientific)
4349227825Stheraven    {
4350227825Stheraven        if (uppercase)
4351227825Stheraven            *__fmtp = 'E';
4352227825Stheraven        else
4353227825Stheraven            *__fmtp = 'e';
4354227825Stheraven    }
4355227825Stheraven    else if (floatfield == (ios_base::fixed | ios_base::scientific))
4356227825Stheraven    {
4357227825Stheraven        if (uppercase)
4358227825Stheraven            *__fmtp = 'A';
4359227825Stheraven        else
4360227825Stheraven            *__fmtp = 'a';
4361227825Stheraven    }
4362227825Stheraven    else
4363227825Stheraven    {
4364227825Stheraven        if (uppercase)
4365227825Stheraven            *__fmtp = 'G';
4366227825Stheraven        else
4367227825Stheraven            *__fmtp = 'g';
4368227825Stheraven    }
4369227825Stheraven    return specify_precision;
4370227825Stheraven}
4371227825Stheraven
4372227825Stheravenchar*
4373227825Stheraven__num_put_base::__identify_padding(char* __nb, char* __ne,
4374227825Stheraven                                   const ios_base& __iob)
4375227825Stheraven{
4376227825Stheraven    switch (__iob.flags() & ios_base::adjustfield)
4377227825Stheraven    {
4378227825Stheraven    case ios_base::internal:
4379227825Stheraven        if (__nb[0] == '-' || __nb[0] == '+')
4380227825Stheraven            return __nb+1;
4381227825Stheraven        if (__ne - __nb >= 2 && __nb[0] == '0'
4382227825Stheraven                            && (__nb[1] == 'x' || __nb[1] == 'X'))
4383227825Stheraven            return __nb+2;
4384227825Stheraven        break;
4385227825Stheraven    case ios_base::left:
4386227825Stheraven        return __ne;
4387227825Stheraven    case ios_base::right:
4388227825Stheraven    default:
4389227825Stheraven        break;
4390227825Stheraven    }
4391227825Stheraven    return __nb;
4392227825Stheraven}
4393227825Stheraven
4394227825Stheraven// time_get
4395227825Stheraven
4396227825Stheravenstatic
4397227825Stheravenstring*
4398227825Stheraveninit_weeks()
4399227825Stheraven{
4400227825Stheraven    static string weeks[14];
4401227825Stheraven    weeks[0]  = "Sunday";
4402227825Stheraven    weeks[1]  = "Monday";
4403227825Stheraven    weeks[2]  = "Tuesday";
4404227825Stheraven    weeks[3]  = "Wednesday";
4405227825Stheraven    weeks[4]  = "Thursday";
4406227825Stheraven    weeks[5]  = "Friday";
4407227825Stheraven    weeks[6]  = "Saturday";
4408227825Stheraven    weeks[7]  = "Sun";
4409227825Stheraven    weeks[8]  = "Mon";
4410227825Stheraven    weeks[9]  = "Tue";
4411227825Stheraven    weeks[10] = "Wed";
4412227825Stheraven    weeks[11] = "Thu";
4413227825Stheraven    weeks[12] = "Fri";
4414227825Stheraven    weeks[13] = "Sat";
4415227825Stheraven    return weeks;
4416227825Stheraven}
4417227825Stheraven
4418227825Stheravenstatic
4419227825Stheravenwstring*
4420227825Stheraveninit_wweeks()
4421227825Stheraven{
4422227825Stheraven    static wstring weeks[14];
4423227825Stheraven    weeks[0]  = L"Sunday";
4424227825Stheraven    weeks[1]  = L"Monday";
4425227825Stheraven    weeks[2]  = L"Tuesday";
4426227825Stheraven    weeks[3]  = L"Wednesday";
4427227825Stheraven    weeks[4]  = L"Thursday";
4428227825Stheraven    weeks[5]  = L"Friday";
4429227825Stheraven    weeks[6]  = L"Saturday";
4430227825Stheraven    weeks[7]  = L"Sun";
4431227825Stheraven    weeks[8]  = L"Mon";
4432227825Stheraven    weeks[9]  = L"Tue";
4433227825Stheraven    weeks[10] = L"Wed";
4434227825Stheraven    weeks[11] = L"Thu";
4435227825Stheraven    weeks[12] = L"Fri";
4436227825Stheraven    weeks[13] = L"Sat";
4437227825Stheraven    return weeks;
4438227825Stheraven}
4439227825Stheraven
4440227825Stheraventemplate <>
4441227825Stheravenconst string*
4442227825Stheraven__time_get_c_storage<char>::__weeks() const
4443227825Stheraven{
4444227825Stheraven    static const string* weeks = init_weeks();
4445227825Stheraven    return weeks;
4446227825Stheraven}
4447227825Stheraven
4448227825Stheraventemplate <>
4449227825Stheravenconst wstring*
4450227825Stheraven__time_get_c_storage<wchar_t>::__weeks() const
4451227825Stheraven{
4452227825Stheraven    static const wstring* weeks = init_wweeks();
4453227825Stheraven    return weeks;
4454227825Stheraven}
4455227825Stheraven
4456227825Stheravenstatic
4457227825Stheravenstring*
4458227825Stheraveninit_months()
4459227825Stheraven{
4460227825Stheraven    static string months[24];
4461227825Stheraven    months[0]  = "January";
4462227825Stheraven    months[1]  = "February";
4463227825Stheraven    months[2]  = "March";
4464227825Stheraven    months[3]  = "April";
4465227825Stheraven    months[4]  = "May";
4466227825Stheraven    months[5]  = "June";
4467227825Stheraven    months[6]  = "July";
4468227825Stheraven    months[7]  = "August";
4469227825Stheraven    months[8]  = "September";
4470227825Stheraven    months[9]  = "October";
4471227825Stheraven    months[10] = "November";
4472227825Stheraven    months[11] = "December";
4473227825Stheraven    months[12] = "Jan";
4474227825Stheraven    months[13] = "Feb";
4475227825Stheraven    months[14] = "Mar";
4476227825Stheraven    months[15] = "Apr";
4477227825Stheraven    months[16] = "May";
4478227825Stheraven    months[17] = "Jun";
4479227825Stheraven    months[18] = "Jul";
4480227825Stheraven    months[19] = "Aug";
4481227825Stheraven    months[20] = "Sep";
4482227825Stheraven    months[21] = "Oct";
4483227825Stheraven    months[22] = "Nov";
4484227825Stheraven    months[23] = "Dec";
4485227825Stheraven    return months;
4486227825Stheraven}
4487227825Stheraven
4488227825Stheravenstatic
4489227825Stheravenwstring*
4490227825Stheraveninit_wmonths()
4491227825Stheraven{
4492227825Stheraven    static wstring months[24];
4493227825Stheraven    months[0]  = L"January";
4494227825Stheraven    months[1]  = L"February";
4495227825Stheraven    months[2]  = L"March";
4496227825Stheraven    months[3]  = L"April";
4497227825Stheraven    months[4]  = L"May";
4498227825Stheraven    months[5]  = L"June";
4499227825Stheraven    months[6]  = L"July";
4500227825Stheraven    months[7]  = L"August";
4501227825Stheraven    months[8]  = L"September";
4502227825Stheraven    months[9]  = L"October";
4503227825Stheraven    months[10] = L"November";
4504227825Stheraven    months[11] = L"December";
4505227825Stheraven    months[12] = L"Jan";
4506227825Stheraven    months[13] = L"Feb";
4507227825Stheraven    months[14] = L"Mar";
4508227825Stheraven    months[15] = L"Apr";
4509227825Stheraven    months[16] = L"May";
4510227825Stheraven    months[17] = L"Jun";
4511227825Stheraven    months[18] = L"Jul";
4512227825Stheraven    months[19] = L"Aug";
4513227825Stheraven    months[20] = L"Sep";
4514227825Stheraven    months[21] = L"Oct";
4515227825Stheraven    months[22] = L"Nov";
4516227825Stheraven    months[23] = L"Dec";
4517227825Stheraven    return months;
4518227825Stheraven}
4519227825Stheraven
4520227825Stheraventemplate <>
4521227825Stheravenconst string*
4522227825Stheraven__time_get_c_storage<char>::__months() const
4523227825Stheraven{
4524227825Stheraven    static const string* months = init_months();
4525227825Stheraven    return months;
4526227825Stheraven}
4527227825Stheraven
4528227825Stheraventemplate <>
4529227825Stheravenconst wstring*
4530227825Stheraven__time_get_c_storage<wchar_t>::__months() const
4531227825Stheraven{
4532227825Stheraven    static const wstring* months = init_wmonths();
4533227825Stheraven    return months;
4534227825Stheraven}
4535227825Stheraven
4536227825Stheravenstatic
4537227825Stheravenstring*
4538227825Stheraveninit_am_pm()
4539227825Stheraven{
4540227825Stheraven    static string am_pm[24];
4541227825Stheraven    am_pm[0]  = "AM";
4542227825Stheraven    am_pm[1]  = "PM";
4543227825Stheraven    return am_pm;
4544227825Stheraven}
4545227825Stheraven
4546227825Stheravenstatic
4547227825Stheravenwstring*
4548227825Stheraveninit_wam_pm()
4549227825Stheraven{
4550227825Stheraven    static wstring am_pm[24];
4551227825Stheraven    am_pm[0]  = L"AM";
4552227825Stheraven    am_pm[1]  = L"PM";
4553227825Stheraven    return am_pm;
4554227825Stheraven}
4555227825Stheraven
4556227825Stheraventemplate <>
4557227825Stheravenconst string*
4558227825Stheraven__time_get_c_storage<char>::__am_pm() const
4559227825Stheraven{
4560227825Stheraven    static const string* am_pm = init_am_pm();
4561227825Stheraven    return am_pm;
4562227825Stheraven}
4563227825Stheraven
4564227825Stheraventemplate <>
4565227825Stheravenconst wstring*
4566227825Stheraven__time_get_c_storage<wchar_t>::__am_pm() const
4567227825Stheraven{
4568227825Stheraven    static const wstring* am_pm = init_wam_pm();
4569227825Stheraven    return am_pm;
4570227825Stheraven}
4571227825Stheraven
4572227825Stheraventemplate <>
4573227825Stheravenconst string&
4574227825Stheraven__time_get_c_storage<char>::__x() const
4575227825Stheraven{
4576227825Stheraven    static string s("%m/%d/%y");
4577227825Stheraven    return s;
4578227825Stheraven}
4579227825Stheraven
4580227825Stheraventemplate <>
4581227825Stheravenconst wstring&
4582227825Stheraven__time_get_c_storage<wchar_t>::__x() const
4583227825Stheraven{
4584227825Stheraven    static wstring s(L"%m/%d/%y");
4585227825Stheraven    return s;
4586227825Stheraven}
4587227825Stheraven
4588227825Stheraventemplate <>
4589227825Stheravenconst string&
4590227825Stheraven__time_get_c_storage<char>::__X() const
4591227825Stheraven{
4592227825Stheraven    static string s("%H:%M:%S");
4593227825Stheraven    return s;
4594227825Stheraven}
4595227825Stheraven
4596227825Stheraventemplate <>
4597227825Stheravenconst wstring&
4598227825Stheraven__time_get_c_storage<wchar_t>::__X() const
4599227825Stheraven{
4600227825Stheraven    static wstring s(L"%H:%M:%S");
4601227825Stheraven    return s;
4602227825Stheraven}
4603227825Stheraven
4604227825Stheraventemplate <>
4605227825Stheravenconst string&
4606227825Stheraven__time_get_c_storage<char>::__c() const
4607227825Stheraven{
4608227825Stheraven    static string s("%a %b %d %H:%M:%S %Y");
4609227825Stheraven    return s;
4610227825Stheraven}
4611227825Stheraven
4612227825Stheraventemplate <>
4613227825Stheravenconst wstring&
4614227825Stheraven__time_get_c_storage<wchar_t>::__c() const
4615227825Stheraven{
4616227825Stheraven    static wstring s(L"%a %b %d %H:%M:%S %Y");
4617227825Stheraven    return s;
4618227825Stheraven}
4619227825Stheraven
4620227825Stheraventemplate <>
4621227825Stheravenconst string&
4622227825Stheraven__time_get_c_storage<char>::__r() const
4623227825Stheraven{
4624227825Stheraven    static string s("%I:%M:%S %p");
4625227825Stheraven    return s;
4626227825Stheraven}
4627227825Stheraven
4628227825Stheraventemplate <>
4629227825Stheravenconst wstring&
4630227825Stheraven__time_get_c_storage<wchar_t>::__r() const
4631227825Stheraven{
4632227825Stheraven    static wstring s(L"%I:%M:%S %p");
4633227825Stheraven    return s;
4634227825Stheraven}
4635227825Stheraven
4636227825Stheraven// time_get_byname
4637227825Stheraven
4638227825Stheraven__time_get::__time_get(const char* nm)
4639227825Stheraven    : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4640227825Stheraven{
4641227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
4642227825Stheraven    if (__loc_ == 0)
4643227825Stheraven        throw runtime_error("time_get_byname"
4644227825Stheraven                            " failed to construct for " + string(nm));
4645227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
4646227825Stheraven}
4647227825Stheraven
4648227825Stheraven__time_get::__time_get(const string& nm)
4649227825Stheraven    : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4650227825Stheraven{
4651227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
4652227825Stheraven    if (__loc_ == 0)
4653227825Stheraven        throw runtime_error("time_get_byname"
4654227825Stheraven                            " failed to construct for " + nm);
4655227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
4656227825Stheraven}
4657227825Stheraven
4658227825Stheraven__time_get::~__time_get()
4659227825Stheraven{
4660227825Stheraven    freelocale(__loc_);
4661227825Stheraven}
4662227825Stheraven
4663232950Stheraven#pragma clang diagnostic ignored "-Wmissing-field-initializers"
4664246487Stheraven#pragma GCC   diagnostic ignored "-Wmissing-field-initializers"
4665232950Stheraven
4666227825Stheraventemplate <>
4667227825Stheravenstring
4668227825Stheraven__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4669227825Stheraven{
4670232950Stheraven    tm t = {0};
4671227825Stheraven    t.tm_sec = 59;
4672227825Stheraven    t.tm_min = 55;
4673227825Stheraven    t.tm_hour = 23;
4674227825Stheraven    t.tm_mday = 31;
4675227825Stheraven    t.tm_mon = 11;
4676227825Stheraven    t.tm_year = 161;
4677227825Stheraven    t.tm_wday = 6;
4678227825Stheraven    t.tm_yday = 364;
4679227825Stheraven    t.tm_isdst = -1;
4680227825Stheraven    char buf[100];
4681227825Stheraven    char f[3] = {0};
4682227825Stheraven    f[0] = '%';
4683227825Stheraven    f[1] = fmt;
4684246487Stheraven    size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
4685227825Stheraven    char* bb = buf;
4686227825Stheraven    char* be = buf + n;
4687227825Stheraven    string result;
4688227825Stheraven    while (bb != be)
4689227825Stheraven    {
4690227825Stheraven        if (ct.is(ctype_base::space, *bb))
4691227825Stheraven        {
4692227825Stheraven            result.push_back(' ');
4693227825Stheraven            for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4694227825Stheraven                ;
4695227825Stheraven            continue;
4696227825Stheraven        }
4697227825Stheraven        char* w = bb;
4698227825Stheraven        ios_base::iostate err = ios_base::goodbit;
4699232950Stheraven        ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4700227825Stheraven                               ct, err, false)
4701227825Stheraven                               - this->__weeks_;
4702227825Stheraven        if (i < 14)
4703227825Stheraven        {
4704227825Stheraven            result.push_back('%');
4705227825Stheraven            if (i < 7)
4706227825Stheraven                result.push_back('A');
4707227825Stheraven            else
4708227825Stheraven                result.push_back('a');
4709227825Stheraven            bb = w;
4710227825Stheraven            continue;
4711227825Stheraven        }
4712227825Stheraven        w = bb;
4713227825Stheraven        i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4714227825Stheraven                           ct, err, false)
4715227825Stheraven                           - this->__months_;
4716227825Stheraven        if (i < 24)
4717227825Stheraven        {
4718227825Stheraven            result.push_back('%');
4719227825Stheraven            if (i < 12)
4720227825Stheraven                result.push_back('B');
4721227825Stheraven            else
4722227825Stheraven                result.push_back('b');
4723227825Stheraven            if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4724227825Stheraven                result.back() = 'm';
4725227825Stheraven            bb = w;
4726227825Stheraven            continue;
4727227825Stheraven        }
4728227825Stheraven        if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4729227825Stheraven        {
4730227825Stheraven            w = bb;
4731227825Stheraven            i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4732227825Stheraven                               ct, err, false) - this->__am_pm_;
4733227825Stheraven            if (i < 2)
4734227825Stheraven            {
4735227825Stheraven                result.push_back('%');
4736227825Stheraven                result.push_back('p');
4737227825Stheraven                bb = w;
4738227825Stheraven                continue;
4739227825Stheraven            }
4740227825Stheraven        }
4741227825Stheraven        w = bb;
4742227825Stheraven        if (ct.is(ctype_base::digit, *bb))
4743227825Stheraven        {
4744227825Stheraven            switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4745227825Stheraven            {
4746227825Stheraven            case 6:
4747227825Stheraven                result.push_back('%');
4748227825Stheraven                result.push_back('w');
4749227825Stheraven                break;
4750227825Stheraven            case 7:
4751227825Stheraven                result.push_back('%');
4752227825Stheraven                result.push_back('u');
4753227825Stheraven                break;
4754227825Stheraven            case 11:
4755227825Stheraven                result.push_back('%');
4756227825Stheraven                result.push_back('I');
4757227825Stheraven                break;
4758227825Stheraven            case 12:
4759227825Stheraven                result.push_back('%');
4760227825Stheraven                result.push_back('m');
4761227825Stheraven                break;
4762227825Stheraven            case 23:
4763227825Stheraven                result.push_back('%');
4764227825Stheraven                result.push_back('H');
4765227825Stheraven                break;
4766227825Stheraven            case 31:
4767227825Stheraven                result.push_back('%');
4768227825Stheraven                result.push_back('d');
4769227825Stheraven                break;
4770227825Stheraven            case 55:
4771227825Stheraven                result.push_back('%');
4772227825Stheraven                result.push_back('M');
4773227825Stheraven                break;
4774227825Stheraven            case 59:
4775227825Stheraven                result.push_back('%');
4776227825Stheraven                result.push_back('S');
4777227825Stheraven                break;
4778227825Stheraven            case 61:
4779227825Stheraven                result.push_back('%');
4780227825Stheraven                result.push_back('y');
4781227825Stheraven                break;
4782227825Stheraven            case 364:
4783227825Stheraven                result.push_back('%');
4784227825Stheraven                result.push_back('j');
4785227825Stheraven                break;
4786227825Stheraven            case 2061:
4787227825Stheraven                result.push_back('%');
4788227825Stheraven                result.push_back('Y');
4789227825Stheraven                break;
4790227825Stheraven            default:
4791227825Stheraven                for (; w != bb; ++w)
4792227825Stheraven                    result.push_back(*w);
4793227825Stheraven                break;
4794227825Stheraven            }
4795227825Stheraven            continue;
4796227825Stheraven        }
4797227825Stheraven        if (*bb == '%')
4798227825Stheraven        {
4799227825Stheraven            result.push_back('%');
4800227825Stheraven            result.push_back('%');
4801227825Stheraven            ++bb;
4802227825Stheraven            continue;
4803227825Stheraven        }
4804227825Stheraven        result.push_back(*bb);
4805227825Stheraven        ++bb;
4806227825Stheraven    }
4807227825Stheraven    return result;
4808227825Stheraven}
4809227825Stheraven
4810232950Stheraven#pragma clang diagnostic ignored "-Wmissing-braces"
4811232950Stheraven
4812227825Stheraventemplate <>
4813227825Stheravenwstring
4814227825Stheraven__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4815227825Stheraven{
4816232950Stheraven    tm t = {0};
4817227825Stheraven    t.tm_sec = 59;
4818227825Stheraven    t.tm_min = 55;
4819227825Stheraven    t.tm_hour = 23;
4820227825Stheraven    t.tm_mday = 31;
4821227825Stheraven    t.tm_mon = 11;
4822227825Stheraven    t.tm_year = 161;
4823227825Stheraven    t.tm_wday = 6;
4824227825Stheraven    t.tm_yday = 364;
4825227825Stheraven    t.tm_isdst = -1;
4826227825Stheraven    char buf[100];
4827227825Stheraven    char f[3] = {0};
4828227825Stheraven    f[0] = '%';
4829227825Stheraven    f[1] = fmt;
4830246487Stheraven    strftime_l(buf, countof(buf), f, &t, __loc_);
4831227825Stheraven    wchar_t wbuf[100];
4832227825Stheraven    wchar_t* wbb = wbuf;
4833227825Stheraven    mbstate_t mb = {0};
4834227825Stheraven    const char* bb = buf;
4835227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
4836246487Stheraven    size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
4837227825Stheraven#else
4838246487Stheraven    size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
4839227825Stheraven#endif
4840232950Stheraven    if (j == size_t(-1))
4841227825Stheraven        __throw_runtime_error("locale not supported");
4842232950Stheraven    wchar_t* wbe = wbb + j;
4843227825Stheraven    wstring result;
4844227825Stheraven    while (wbb != wbe)
4845227825Stheraven    {
4846227825Stheraven        if (ct.is(ctype_base::space, *wbb))
4847227825Stheraven        {
4848227825Stheraven            result.push_back(L' ');
4849227825Stheraven            for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4850227825Stheraven                ;
4851227825Stheraven            continue;
4852227825Stheraven        }
4853227825Stheraven        wchar_t* w = wbb;
4854227825Stheraven        ios_base::iostate err = ios_base::goodbit;
4855232950Stheraven        ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4856227825Stheraven                               ct, err, false)
4857227825Stheraven                               - this->__weeks_;
4858227825Stheraven        if (i < 14)
4859227825Stheraven        {
4860227825Stheraven            result.push_back(L'%');
4861227825Stheraven            if (i < 7)
4862227825Stheraven                result.push_back(L'A');
4863227825Stheraven            else
4864227825Stheraven                result.push_back(L'a');
4865227825Stheraven            wbb = w;
4866227825Stheraven            continue;
4867227825Stheraven        }
4868227825Stheraven        w = wbb;
4869227825Stheraven        i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4870227825Stheraven                           ct, err, false)
4871227825Stheraven                           - this->__months_;
4872227825Stheraven        if (i < 24)
4873227825Stheraven        {
4874227825Stheraven            result.push_back(L'%');
4875227825Stheraven            if (i < 12)
4876227825Stheraven                result.push_back(L'B');
4877227825Stheraven            else
4878227825Stheraven                result.push_back(L'b');
4879227825Stheraven            if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4880227825Stheraven                result.back() = L'm';
4881227825Stheraven            wbb = w;
4882227825Stheraven            continue;
4883227825Stheraven        }
4884227825Stheraven        if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4885227825Stheraven        {
4886227825Stheraven            w = wbb;
4887227825Stheraven            i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4888227825Stheraven                               ct, err, false) - this->__am_pm_;
4889227825Stheraven            if (i < 2)
4890227825Stheraven            {
4891227825Stheraven                result.push_back(L'%');
4892227825Stheraven                result.push_back(L'p');
4893227825Stheraven                wbb = w;
4894227825Stheraven                continue;
4895227825Stheraven            }
4896227825Stheraven        }
4897227825Stheraven        w = wbb;
4898227825Stheraven        if (ct.is(ctype_base::digit, *wbb))
4899227825Stheraven        {
4900227825Stheraven            switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4901227825Stheraven            {
4902227825Stheraven            case 6:
4903227825Stheraven                result.push_back(L'%');
4904227825Stheraven                result.push_back(L'w');
4905227825Stheraven                break;
4906227825Stheraven            case 7:
4907227825Stheraven                result.push_back(L'%');
4908227825Stheraven                result.push_back(L'u');
4909227825Stheraven                break;
4910227825Stheraven            case 11:
4911227825Stheraven                result.push_back(L'%');
4912227825Stheraven                result.push_back(L'I');
4913227825Stheraven                break;
4914227825Stheraven            case 12:
4915227825Stheraven                result.push_back(L'%');
4916227825Stheraven                result.push_back(L'm');
4917227825Stheraven                break;
4918227825Stheraven            case 23:
4919227825Stheraven                result.push_back(L'%');
4920227825Stheraven                result.push_back(L'H');
4921227825Stheraven                break;
4922227825Stheraven            case 31:
4923227825Stheraven                result.push_back(L'%');
4924227825Stheraven                result.push_back(L'd');
4925227825Stheraven                break;
4926227825Stheraven            case 55:
4927227825Stheraven                result.push_back(L'%');
4928227825Stheraven                result.push_back(L'M');
4929227825Stheraven                break;
4930227825Stheraven            case 59:
4931227825Stheraven                result.push_back(L'%');
4932227825Stheraven                result.push_back(L'S');
4933227825Stheraven                break;
4934227825Stheraven            case 61:
4935227825Stheraven                result.push_back(L'%');
4936227825Stheraven                result.push_back(L'y');
4937227825Stheraven                break;
4938227825Stheraven            case 364:
4939227825Stheraven                result.push_back(L'%');
4940227825Stheraven                result.push_back(L'j');
4941227825Stheraven                break;
4942227825Stheraven            case 2061:
4943227825Stheraven                result.push_back(L'%');
4944227825Stheraven                result.push_back(L'Y');
4945227825Stheraven                break;
4946227825Stheraven            default:
4947227825Stheraven                for (; w != wbb; ++w)
4948227825Stheraven                    result.push_back(*w);
4949227825Stheraven                break;
4950227825Stheraven            }
4951227825Stheraven            continue;
4952227825Stheraven        }
4953227825Stheraven        if (ct.narrow(*wbb, 0) == '%')
4954227825Stheraven        {
4955227825Stheraven            result.push_back(L'%');
4956227825Stheraven            result.push_back(L'%');
4957227825Stheraven            ++wbb;
4958227825Stheraven            continue;
4959227825Stheraven        }
4960227825Stheraven        result.push_back(*wbb);
4961227825Stheraven        ++wbb;
4962227825Stheraven    }
4963227825Stheraven    return result;
4964227825Stheraven}
4965227825Stheraven
4966227825Stheraventemplate <>
4967227825Stheravenvoid
4968227825Stheraven__time_get_storage<char>::init(const ctype<char>& ct)
4969227825Stheraven{
4970241903Sdim    tm t = {0};
4971227825Stheraven    char buf[100];
4972227825Stheraven    // __weeks_
4973227825Stheraven    for (int i = 0; i < 7; ++i)
4974227825Stheraven    {
4975227825Stheraven        t.tm_wday = i;
4976246487Stheraven        strftime_l(buf, countof(buf), "%A", &t, __loc_);
4977227825Stheraven        __weeks_[i] = buf;
4978246487Stheraven        strftime_l(buf, countof(buf), "%a", &t, __loc_);
4979227825Stheraven        __weeks_[i+7] = buf;
4980227825Stheraven    }
4981227825Stheraven    // __months_
4982227825Stheraven    for (int i = 0; i < 12; ++i)
4983227825Stheraven    {
4984227825Stheraven        t.tm_mon = i;
4985246487Stheraven        strftime_l(buf, countof(buf), "%B", &t, __loc_);
4986227825Stheraven        __months_[i] = buf;
4987246487Stheraven        strftime_l(buf, countof(buf), "%b", &t, __loc_);
4988227825Stheraven        __months_[i+12] = buf;
4989227825Stheraven    }
4990227825Stheraven    // __am_pm_
4991227825Stheraven    t.tm_hour = 1;
4992246487Stheraven    strftime_l(buf, countof(buf), "%p", &t, __loc_);
4993227825Stheraven    __am_pm_[0] = buf;
4994227825Stheraven    t.tm_hour = 13;
4995246487Stheraven    strftime_l(buf, countof(buf), "%p", &t, __loc_);
4996227825Stheraven    __am_pm_[1] = buf;
4997227825Stheraven    __c_ = __analyze('c', ct);
4998227825Stheraven    __r_ = __analyze('r', ct);
4999227825Stheraven    __x_ = __analyze('x', ct);
5000227825Stheraven    __X_ = __analyze('X', ct);
5001227825Stheraven}
5002227825Stheraven
5003227825Stheraventemplate <>
5004227825Stheravenvoid
5005227825Stheraven__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5006227825Stheraven{
5007227825Stheraven    tm t = {0};
5008227825Stheraven    char buf[100];
5009227825Stheraven    wchar_t wbuf[100];
5010227825Stheraven    wchar_t* wbe;
5011227825Stheraven    mbstate_t mb = {0};
5012227825Stheraven    // __weeks_
5013227825Stheraven    for (int i = 0; i < 7; ++i)
5014227825Stheraven    {
5015227825Stheraven        t.tm_wday = i;
5016246487Stheraven        strftime_l(buf, countof(buf), "%A", &t, __loc_);
5017227825Stheraven        mb = mbstate_t();
5018227825Stheraven        const char* bb = buf;
5019227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5020246487Stheraven        size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5021227825Stheraven#else
5022246487Stheraven        size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5023227825Stheraven#endif
5024232950Stheraven        if (j == size_t(-1))
5025227825Stheraven            __throw_runtime_error("locale not supported");
5026227825Stheraven        wbe = wbuf + j;
5027227825Stheraven        __weeks_[i].assign(wbuf, wbe);
5028246487Stheraven        strftime_l(buf, countof(buf), "%a", &t, __loc_);
5029227825Stheraven        mb = mbstate_t();
5030227825Stheraven        bb = buf;
5031227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5032246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5033227825Stheraven#else
5034246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5035227825Stheraven#endif
5036232950Stheraven        if (j == size_t(-1))
5037227825Stheraven            __throw_runtime_error("locale not supported");
5038227825Stheraven        wbe = wbuf + j;
5039227825Stheraven        __weeks_[i+7].assign(wbuf, wbe);
5040227825Stheraven    }
5041227825Stheraven    // __months_
5042227825Stheraven    for (int i = 0; i < 12; ++i)
5043227825Stheraven    {
5044227825Stheraven        t.tm_mon = i;
5045246487Stheraven        strftime_l(buf, countof(buf), "%B", &t, __loc_);
5046227825Stheraven        mb = mbstate_t();
5047227825Stheraven        const char* bb = buf;
5048227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5049246487Stheraven        size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5050227825Stheraven#else
5051246487Stheraven        size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5052227825Stheraven#endif
5053232950Stheraven        if (j == size_t(-1))
5054227825Stheraven            __throw_runtime_error("locale not supported");
5055227825Stheraven        wbe = wbuf + j;
5056227825Stheraven        __months_[i].assign(wbuf, wbe);
5057246487Stheraven        strftime_l(buf, countof(buf), "%b", &t, __loc_);
5058227825Stheraven        mb = mbstate_t();
5059227825Stheraven        bb = buf;
5060227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5061246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5062227825Stheraven#else
5063246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5064227825Stheraven#endif
5065232950Stheraven        if (j == size_t(-1))
5066227825Stheraven            __throw_runtime_error("locale not supported");
5067227825Stheraven        wbe = wbuf + j;
5068227825Stheraven        __months_[i+12].assign(wbuf, wbe);
5069227825Stheraven    }
5070227825Stheraven    // __am_pm_
5071227825Stheraven    t.tm_hour = 1;
5072246487Stheraven    strftime_l(buf, countof(buf), "%p", &t, __loc_);
5073227825Stheraven    mb = mbstate_t();
5074227825Stheraven    const char* bb = buf;
5075227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5076246487Stheraven    size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5077227825Stheraven#else
5078246487Stheraven    size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5079227825Stheraven#endif
5080232950Stheraven    if (j == size_t(-1))
5081227825Stheraven        __throw_runtime_error("locale not supported");
5082227825Stheraven    wbe = wbuf + j;
5083227825Stheraven    __am_pm_[0].assign(wbuf, wbe);
5084227825Stheraven    t.tm_hour = 13;
5085246487Stheraven    strftime_l(buf, countof(buf), "%p", &t, __loc_);
5086227825Stheraven    mb = mbstate_t();
5087227825Stheraven    bb = buf;
5088227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5089246487Stheraven    j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5090227825Stheraven#else
5091246487Stheraven    j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5092227825Stheraven#endif
5093232950Stheraven    if (j == size_t(-1))
5094227825Stheraven        __throw_runtime_error("locale not supported");
5095227825Stheraven    wbe = wbuf + j;
5096227825Stheraven    __am_pm_[1].assign(wbuf, wbe);
5097227825Stheraven    __c_ = __analyze('c', ct);
5098227825Stheraven    __r_ = __analyze('r', ct);
5099227825Stheraven    __x_ = __analyze('x', ct);
5100227825Stheraven    __X_ = __analyze('X', ct);
5101227825Stheraven}
5102227825Stheraven
5103227825Stheraventemplate <class CharT>
5104227825Stheravenstruct _LIBCPP_HIDDEN __time_get_temp
5105227825Stheraven    : public ctype_byname<CharT>
5106227825Stheraven{
5107227825Stheraven    explicit __time_get_temp(const char* nm)
5108227825Stheraven        : ctype_byname<CharT>(nm, 1) {}
5109227825Stheraven    explicit __time_get_temp(const string& nm)
5110227825Stheraven        : ctype_byname<CharT>(nm, 1) {}
5111227825Stheraven};
5112227825Stheraven
5113227825Stheraventemplate <>
5114227825Stheraven__time_get_storage<char>::__time_get_storage(const char* __nm)
5115227825Stheraven    : __time_get(__nm)
5116227825Stheraven{
5117227825Stheraven    const __time_get_temp<char> ct(__nm);
5118227825Stheraven    init(ct);
5119227825Stheraven}
5120227825Stheraven
5121227825Stheraventemplate <>
5122227825Stheraven__time_get_storage<char>::__time_get_storage(const string& __nm)
5123227825Stheraven    : __time_get(__nm)
5124227825Stheraven{
5125227825Stheraven    const __time_get_temp<char> ct(__nm);
5126227825Stheraven    init(ct);
5127227825Stheraven}
5128227825Stheraven
5129227825Stheraventemplate <>
5130227825Stheraven__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5131227825Stheraven    : __time_get(__nm)
5132227825Stheraven{
5133227825Stheraven    const __time_get_temp<wchar_t> ct(__nm);
5134227825Stheraven    init(ct);
5135227825Stheraven}
5136227825Stheraven
5137227825Stheraventemplate <>
5138227825Stheraven__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5139227825Stheraven    : __time_get(__nm)
5140227825Stheraven{
5141227825Stheraven    const __time_get_temp<wchar_t> ct(__nm);
5142227825Stheraven    init(ct);
5143227825Stheraven}
5144227825Stheraven
5145227825Stheraventemplate <>
5146227825Stheraventime_base::dateorder
5147227825Stheraven__time_get_storage<char>::__do_date_order() const
5148227825Stheraven{
5149227825Stheraven    unsigned i;
5150227825Stheraven    for (i = 0; i < __x_.size(); ++i)
5151227825Stheraven        if (__x_[i] == '%')
5152227825Stheraven            break;
5153227825Stheraven    ++i;
5154227825Stheraven    switch (__x_[i])
5155227825Stheraven    {
5156227825Stheraven    case 'y':
5157227825Stheraven    case 'Y':
5158227825Stheraven        for (++i; i < __x_.size(); ++i)
5159227825Stheraven            if (__x_[i] == '%')
5160227825Stheraven                break;
5161227825Stheraven        if (i == __x_.size())
5162227825Stheraven            break;
5163227825Stheraven        ++i;
5164227825Stheraven        switch (__x_[i])
5165227825Stheraven        {
5166227825Stheraven        case 'm':
5167227825Stheraven            for (++i; i < __x_.size(); ++i)
5168227825Stheraven                if (__x_[i] == '%')
5169227825Stheraven                    break;
5170227825Stheraven            if (i == __x_.size())
5171227825Stheraven                break;
5172227825Stheraven            ++i;
5173227825Stheraven            if (__x_[i] == 'd')
5174227825Stheraven                return time_base::ymd;
5175227825Stheraven            break;
5176227825Stheraven        case 'd':
5177227825Stheraven            for (++i; i < __x_.size(); ++i)
5178227825Stheraven                if (__x_[i] == '%')
5179227825Stheraven                    break;
5180227825Stheraven            if (i == __x_.size())
5181227825Stheraven                break;
5182227825Stheraven            ++i;
5183227825Stheraven            if (__x_[i] == 'm')
5184227825Stheraven                return time_base::ydm;
5185227825Stheraven            break;
5186227825Stheraven        }
5187227825Stheraven        break;
5188227825Stheraven    case 'm':
5189227825Stheraven        for (++i; i < __x_.size(); ++i)
5190227825Stheraven            if (__x_[i] == '%')
5191227825Stheraven                break;
5192227825Stheraven        if (i == __x_.size())
5193227825Stheraven            break;
5194227825Stheraven        ++i;
5195227825Stheraven        if (__x_[i] == 'd')
5196227825Stheraven        {
5197227825Stheraven            for (++i; i < __x_.size(); ++i)
5198227825Stheraven                if (__x_[i] == '%')
5199227825Stheraven                    break;
5200227825Stheraven            if (i == __x_.size())
5201227825Stheraven                break;
5202227825Stheraven            ++i;
5203227825Stheraven            if (__x_[i] == 'y' || __x_[i] == 'Y')
5204227825Stheraven                return time_base::mdy;
5205227825Stheraven            break;
5206227825Stheraven        }
5207227825Stheraven        break;
5208227825Stheraven    case 'd':
5209227825Stheraven        for (++i; i < __x_.size(); ++i)
5210227825Stheraven            if (__x_[i] == '%')
5211227825Stheraven                break;
5212227825Stheraven        if (i == __x_.size())
5213227825Stheraven            break;
5214227825Stheraven        ++i;
5215227825Stheraven        if (__x_[i] == 'm')
5216227825Stheraven        {
5217227825Stheraven            for (++i; i < __x_.size(); ++i)
5218227825Stheraven                if (__x_[i] == '%')
5219227825Stheraven                    break;
5220227825Stheraven            if (i == __x_.size())
5221227825Stheraven                break;
5222227825Stheraven            ++i;
5223227825Stheraven            if (__x_[i] == 'y' || __x_[i] == 'Y')
5224227825Stheraven                return time_base::dmy;
5225227825Stheraven            break;
5226227825Stheraven        }
5227227825Stheraven        break;
5228227825Stheraven    }
5229227825Stheraven    return time_base::no_order;
5230227825Stheraven}
5231227825Stheraven
5232227825Stheraventemplate <>
5233227825Stheraventime_base::dateorder
5234227825Stheraven__time_get_storage<wchar_t>::__do_date_order() const
5235227825Stheraven{
5236227825Stheraven    unsigned i;
5237227825Stheraven    for (i = 0; i < __x_.size(); ++i)
5238227825Stheraven        if (__x_[i] == L'%')
5239227825Stheraven            break;
5240227825Stheraven    ++i;
5241227825Stheraven    switch (__x_[i])
5242227825Stheraven    {
5243227825Stheraven    case L'y':
5244227825Stheraven    case L'Y':
5245227825Stheraven        for (++i; i < __x_.size(); ++i)
5246227825Stheraven            if (__x_[i] == L'%')
5247227825Stheraven                break;
5248227825Stheraven        if (i == __x_.size())
5249227825Stheraven            break;
5250227825Stheraven        ++i;
5251227825Stheraven        switch (__x_[i])
5252227825Stheraven        {
5253227825Stheraven        case L'm':
5254227825Stheraven            for (++i; i < __x_.size(); ++i)
5255227825Stheraven                if (__x_[i] == L'%')
5256227825Stheraven                    break;
5257227825Stheraven            if (i == __x_.size())
5258227825Stheraven                break;
5259227825Stheraven            ++i;
5260227825Stheraven            if (__x_[i] == L'd')
5261227825Stheraven                return time_base::ymd;
5262227825Stheraven            break;
5263227825Stheraven        case L'd':
5264227825Stheraven            for (++i; i < __x_.size(); ++i)
5265227825Stheraven                if (__x_[i] == L'%')
5266227825Stheraven                    break;
5267227825Stheraven            if (i == __x_.size())
5268227825Stheraven                break;
5269227825Stheraven            ++i;
5270227825Stheraven            if (__x_[i] == L'm')
5271227825Stheraven                return time_base::ydm;
5272227825Stheraven            break;
5273227825Stheraven        }
5274227825Stheraven        break;
5275227825Stheraven    case L'm':
5276227825Stheraven        for (++i; i < __x_.size(); ++i)
5277227825Stheraven            if (__x_[i] == L'%')
5278227825Stheraven                break;
5279227825Stheraven        if (i == __x_.size())
5280227825Stheraven            break;
5281227825Stheraven        ++i;
5282227825Stheraven        if (__x_[i] == L'd')
5283227825Stheraven        {
5284227825Stheraven            for (++i; i < __x_.size(); ++i)
5285227825Stheraven                if (__x_[i] == L'%')
5286227825Stheraven                    break;
5287227825Stheraven            if (i == __x_.size())
5288227825Stheraven                break;
5289227825Stheraven            ++i;
5290227825Stheraven            if (__x_[i] == L'y' || __x_[i] == L'Y')
5291227825Stheraven                return time_base::mdy;
5292227825Stheraven            break;
5293227825Stheraven        }
5294227825Stheraven        break;
5295227825Stheraven    case L'd':
5296227825Stheraven        for (++i; i < __x_.size(); ++i)
5297227825Stheraven            if (__x_[i] == L'%')
5298227825Stheraven                break;
5299227825Stheraven        if (i == __x_.size())
5300227825Stheraven            break;
5301227825Stheraven        ++i;
5302227825Stheraven        if (__x_[i] == L'm')
5303227825Stheraven        {
5304227825Stheraven            for (++i; i < __x_.size(); ++i)
5305227825Stheraven                if (__x_[i] == L'%')
5306227825Stheraven                    break;
5307227825Stheraven            if (i == __x_.size())
5308227825Stheraven                break;
5309227825Stheraven            ++i;
5310227825Stheraven            if (__x_[i] == L'y' || __x_[i] == L'Y')
5311227825Stheraven                return time_base::dmy;
5312227825Stheraven            break;
5313227825Stheraven        }
5314227825Stheraven        break;
5315227825Stheraven    }
5316227825Stheraven    return time_base::no_order;
5317227825Stheraven}
5318227825Stheraven
5319227825Stheraven// time_put
5320227825Stheraven
5321227825Stheraven__time_put::__time_put(const char* nm)
5322227825Stheraven    : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5323227825Stheraven{
5324227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5325227825Stheraven    if (__loc_ == 0)
5326227825Stheraven        throw runtime_error("time_put_byname"
5327227825Stheraven                            " failed to construct for " + string(nm));
5328227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5329227825Stheraven}
5330227825Stheraven
5331227825Stheraven__time_put::__time_put(const string& nm)
5332227825Stheraven    : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5333227825Stheraven{
5334227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5335227825Stheraven    if (__loc_ == 0)
5336227825Stheraven        throw runtime_error("time_put_byname"
5337227825Stheraven                            " failed to construct for " + nm);
5338227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5339227825Stheraven}
5340227825Stheraven
5341227825Stheraven__time_put::~__time_put()
5342227825Stheraven{
5343253159Stheraven    if (__loc_ != _LIBCPP_GET_C_LOCALE)
5344227825Stheraven        freelocale(__loc_);
5345227825Stheraven}
5346227825Stheraven
5347227825Stheravenvoid
5348227825Stheraven__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5349227825Stheraven                     char __fmt, char __mod) const
5350227825Stheraven{
5351227825Stheraven    char fmt[] = {'%', __fmt, __mod, 0};
5352227825Stheraven    if (__mod != 0)
5353227825Stheraven        swap(fmt[1], fmt[2]);
5354246487Stheraven    size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
5355227825Stheraven    __ne = __nb + n;
5356227825Stheraven}
5357227825Stheraven
5358227825Stheravenvoid
5359227825Stheraven__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5360227825Stheraven                     char __fmt, char __mod) const
5361227825Stheraven{
5362227825Stheraven    char __nar[100];
5363227825Stheraven    char* __ne = __nar + 100;
5364227825Stheraven    __do_put(__nar, __ne, __tm, __fmt, __mod);
5365227825Stheraven    mbstate_t mb = {0};
5366227825Stheraven    const char* __nb = __nar;
5367227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5368246487Stheraven    size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
5369227825Stheraven#else
5370246487Stheraven    size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
5371227825Stheraven#endif
5372232950Stheraven    if (j == size_t(-1))
5373227825Stheraven        __throw_runtime_error("locale not supported");
5374227825Stheraven    __we = __wb + j;
5375227825Stheraven}
5376227825Stheraven
5377227825Stheraven// moneypunct_byname
5378227825Stheraven
5379232950Stheraventemplate <class charT>
5380227825Stheravenstatic
5381227825Stheravenvoid
5382232950Stheraven__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5383232950Stheraven           bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5384232950Stheraven           charT space_char)
5385227825Stheraven{
5386227825Stheraven    const char sign = static_cast<char>(money_base::sign);
5387227825Stheraven    const char space = static_cast<char>(money_base::space);
5388227825Stheraven    const char none = static_cast<char>(money_base::none);
5389227825Stheraven    const char symbol = static_cast<char>(money_base::symbol);
5390227825Stheraven    const char value = static_cast<char>(money_base::value);
5391232950Stheraven    const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5392232950Stheraven
5393232950Stheraven    // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5394232950Stheraven    // function'. "Space between sign and symbol or value" means that
5395232950Stheraven    // if the sign is adjacent to the symbol, there's a space between
5396232950Stheraven    // them, and otherwise there's a space between the sign and value.
5397232950Stheraven    //
5398232950Stheraven    // C11's localeconv specifies that the fourth character of an
5399232950Stheraven    // international curr_symbol is used to separate the sign and
5400232950Stheraven    // value when sep_by_space says to do so. C++ can't represent
5401232950Stheraven    // that, so we just use a space.  When sep_by_space says to
5402232950Stheraven    // separate the symbol and value-or-sign with a space, we rearrange the
5403232950Stheraven    // curr_symbol to put its spacing character on the correct side of
5404232950Stheraven    // the symbol.
5405232950Stheraven    //
5406232950Stheraven    // We also need to avoid adding an extra space between the sign
5407232950Stheraven    // and value when the currency symbol is suppressed (by not
5408232950Stheraven    // setting showbase).  We match glibc's strfmon by interpreting
5409232950Stheraven    // sep_by_space==1 as "omit the space when the currency symbol is
5410232950Stheraven    // absent".
5411232950Stheraven    //
5412232950Stheraven    // Users who want to get this right should use ICU instead.
5413232950Stheraven
5414227825Stheraven    switch (cs_precedes)
5415227825Stheraven    {
5416232950Stheraven    case 0:  // value before curr_symbol
5417232950Stheraven        if (symbol_contains_sep) {
5418232950Stheraven            // Move the separator to before the symbol, to place it
5419232950Stheraven            // between the value and symbol.
5420232950Stheraven            rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5421232950Stheraven                   __curr_symbol_.end());
5422232950Stheraven        }
5423227825Stheraven        switch (sign_posn)
5424227825Stheraven        {
5425232950Stheraven        case 0:  // Parentheses surround the quantity and currency symbol.
5426227825Stheraven            pat.field[0] = sign;
5427227825Stheraven            pat.field[1] = value;
5428232950Stheraven            pat.field[2] = none;  // Any space appears in the symbol.
5429227825Stheraven            pat.field[3] = symbol;
5430227825Stheraven            switch (sep_by_space)
5431227825Stheraven            {
5432232950Stheraven            case 0:  // No space separates the currency symbol and value.
5433232950Stheraven                // This case may have changed between C99 and C11;
5434232950Stheraven                // assume the currency symbol matches the intention.
5435232950Stheraven            case 2:  // Space between sign and currency or value.
5436232950Stheraven                // The "sign" is two parentheses, so no space here either.
5437227825Stheraven                return;
5438232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5439232950Stheraven                if (!symbol_contains_sep) {
5440232950Stheraven                    // We insert the space into the symbol instead of
5441232950Stheraven                    // setting pat.field[2]=space so that when
5442232950Stheraven                    // showbase is not set, the space goes away too.
5443232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5444232950Stheraven                }
5445227825Stheraven                return;
5446227825Stheraven            default:
5447227825Stheraven                break;
5448227825Stheraven            }
5449227825Stheraven            break;
5450232950Stheraven        case 1:  // The sign string precedes the quantity and currency symbol.
5451227825Stheraven            pat.field[0] = sign;
5452227825Stheraven            pat.field[3] = symbol;
5453227825Stheraven            switch (sep_by_space)
5454227825Stheraven            {
5455232950Stheraven            case 0:  // No space separates the currency symbol and value.
5456227825Stheraven                pat.field[1] = value;
5457227825Stheraven                pat.field[2] = none;
5458227825Stheraven                return;
5459232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5460227825Stheraven                pat.field[1] = value;
5461232950Stheraven                pat.field[2] = none;
5462232950Stheraven                if (!symbol_contains_sep) {
5463232950Stheraven                    // We insert the space into the symbol instead of
5464232950Stheraven                    // setting pat.field[2]=space so that when
5465232950Stheraven                    // showbase is not set, the space goes away too.
5466232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5467232950Stheraven                }
5468227825Stheraven                return;
5469232950Stheraven            case 2:  // Space between sign and currency or value.
5470227825Stheraven                pat.field[1] = space;
5471227825Stheraven                pat.field[2] = value;
5472232950Stheraven                if (symbol_contains_sep) {
5473232950Stheraven                    // Remove the separator from the symbol, since it
5474232950Stheraven                    // has already appeared after the sign.
5475232950Stheraven                    __curr_symbol_.erase(__curr_symbol_.begin());
5476232950Stheraven                }
5477227825Stheraven                return;
5478227825Stheraven            default:
5479227825Stheraven                break;
5480227825Stheraven            }
5481227825Stheraven            break;
5482232950Stheraven        case 2:  // The sign string succeeds the quantity and currency symbol.
5483227825Stheraven            pat.field[0] = value;
5484227825Stheraven            pat.field[3] = sign;
5485227825Stheraven            switch (sep_by_space)
5486227825Stheraven            {
5487232950Stheraven            case 0:  // No space separates the currency symbol and value.
5488227825Stheraven                pat.field[1] = none;
5489227825Stheraven                pat.field[2] = symbol;
5490227825Stheraven                return;
5491232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5492232950Stheraven                if (!symbol_contains_sep) {
5493232950Stheraven                    // We insert the space into the symbol instead of
5494232950Stheraven                    // setting pat.field[1]=space so that when
5495232950Stheraven                    // showbase is not set, the space goes away too.
5496232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5497232950Stheraven                }
5498232950Stheraven                pat.field[1] = none;
5499227825Stheraven                pat.field[2] = symbol;
5500227825Stheraven                return;
5501232950Stheraven            case 2:  // Space between sign and currency or value.
5502227825Stheraven                pat.field[1] = symbol;
5503227825Stheraven                pat.field[2] = space;
5504232950Stheraven                if (symbol_contains_sep) {
5505232950Stheraven                    // Remove the separator from the symbol, since it
5506232950Stheraven                    // should not be removed if showbase is absent.
5507232950Stheraven                    __curr_symbol_.erase(__curr_symbol_.begin());
5508232950Stheraven                }
5509227825Stheraven                return;
5510227825Stheraven            default:
5511227825Stheraven                break;
5512227825Stheraven            }
5513227825Stheraven            break;
5514232950Stheraven        case 3:  // The sign string immediately precedes the currency symbol.
5515227825Stheraven            pat.field[0] = value;
5516227825Stheraven            pat.field[3] = symbol;
5517227825Stheraven            switch (sep_by_space)
5518227825Stheraven            {
5519232950Stheraven            case 0:  // No space separates the currency symbol and value.
5520227825Stheraven                pat.field[1] = none;
5521227825Stheraven                pat.field[2] = sign;
5522227825Stheraven                return;
5523232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5524227825Stheraven                pat.field[1] = space;
5525227825Stheraven                pat.field[2] = sign;
5526232950Stheraven                if (symbol_contains_sep) {
5527232950Stheraven                    // Remove the separator from the symbol, since it
5528232950Stheraven                    // has already appeared before the sign.
5529232950Stheraven                    __curr_symbol_.erase(__curr_symbol_.begin());
5530232950Stheraven                }
5531227825Stheraven                return;
5532232950Stheraven            case 2:  // Space between sign and currency or value.
5533227825Stheraven                pat.field[1] = sign;
5534232950Stheraven                pat.field[2] = none;
5535232950Stheraven                if (!symbol_contains_sep) {
5536232950Stheraven                    // We insert the space into the symbol instead of
5537232950Stheraven                    // setting pat.field[2]=space so that when
5538232950Stheraven                    // showbase is not set, the space goes away too.
5539232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5540232950Stheraven                }
5541227825Stheraven                return;
5542227825Stheraven            default:
5543227825Stheraven                break;
5544227825Stheraven            }
5545227825Stheraven            break;
5546232950Stheraven        case 4:  // The sign string immediately succeeds the currency symbol.
5547227825Stheraven            pat.field[0] = value;
5548227825Stheraven            pat.field[3] = sign;
5549227825Stheraven            switch (sep_by_space)
5550227825Stheraven            {
5551232950Stheraven            case 0:  // No space separates the currency symbol and value.
5552227825Stheraven                pat.field[1] = none;
5553227825Stheraven                pat.field[2] = symbol;
5554227825Stheraven                return;
5555232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5556232950Stheraven                pat.field[1] = none;
5557227825Stheraven                pat.field[2] = symbol;
5558232950Stheraven                if (!symbol_contains_sep) {
5559232950Stheraven                    // We insert the space into the symbol instead of
5560232950Stheraven                    // setting pat.field[1]=space so that when
5561232950Stheraven                    // showbase is not set, the space goes away too.
5562232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5563232950Stheraven                }
5564227825Stheraven                return;
5565232950Stheraven            case 2:  // Space between sign and currency or value.
5566227825Stheraven                pat.field[1] = symbol;
5567227825Stheraven                pat.field[2] = space;
5568232950Stheraven                if (symbol_contains_sep) {
5569232950Stheraven                    // Remove the separator from the symbol, since it
5570232950Stheraven                    // should not disappear when showbase is absent.
5571232950Stheraven                    __curr_symbol_.erase(__curr_symbol_.begin());
5572232950Stheraven                }
5573227825Stheraven                return;
5574227825Stheraven            default:
5575227825Stheraven                break;
5576227825Stheraven            }
5577227825Stheraven            break;
5578227825Stheraven        default:
5579227825Stheraven            break;
5580227825Stheraven        }
5581227825Stheraven        break;
5582232950Stheraven    case 1:  // curr_symbol before value
5583227825Stheraven        switch (sign_posn)
5584227825Stheraven        {
5585232950Stheraven        case 0:  // Parentheses surround the quantity and currency symbol.
5586227825Stheraven            pat.field[0] = sign;
5587227825Stheraven            pat.field[1] = symbol;
5588232950Stheraven            pat.field[2] = none;  // Any space appears in the symbol.
5589227825Stheraven            pat.field[3] = value;
5590227825Stheraven            switch (sep_by_space)
5591227825Stheraven            {
5592232950Stheraven            case 0:  // No space separates the currency symbol and value.
5593232950Stheraven                // This case may have changed between C99 and C11;
5594232950Stheraven                // assume the currency symbol matches the intention.
5595232950Stheraven            case 2:  // Space between sign and currency or value.
5596232950Stheraven                // The "sign" is two parentheses, so no space here either.
5597227825Stheraven                return;
5598232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5599232950Stheraven                if (!symbol_contains_sep) {
5600232950Stheraven                    // We insert the space into the symbol instead of
5601232950Stheraven                    // setting pat.field[2]=space so that when
5602232950Stheraven                    // showbase is not set, the space goes away too.
5603232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5604232950Stheraven                }
5605227825Stheraven                return;
5606227825Stheraven            default:
5607227825Stheraven                break;
5608227825Stheraven            }
5609227825Stheraven            break;
5610232950Stheraven        case 1:  // The sign string precedes the quantity and currency symbol.
5611227825Stheraven            pat.field[0] = sign;
5612227825Stheraven            pat.field[3] = value;
5613227825Stheraven            switch (sep_by_space)
5614227825Stheraven            {
5615232950Stheraven            case 0:  // No space separates the currency symbol and value.
5616227825Stheraven                pat.field[1] = symbol;
5617227825Stheraven                pat.field[2] = none;
5618227825Stheraven                return;
5619232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5620227825Stheraven                pat.field[1] = symbol;
5621232950Stheraven                pat.field[2] = none;
5622232950Stheraven                if (!symbol_contains_sep) {
5623232950Stheraven                    // We insert the space into the symbol instead of
5624232950Stheraven                    // setting pat.field[2]=space so that when
5625232950Stheraven                    // showbase is not set, the space goes away too.
5626232950Stheraven                    __curr_symbol_.push_back(space_char);
5627232950Stheraven                }
5628227825Stheraven                return;
5629232950Stheraven            case 2:  // Space between sign and currency or value.
5630227825Stheraven                pat.field[1] = space;
5631227825Stheraven                pat.field[2] = symbol;
5632232950Stheraven                if (symbol_contains_sep) {
5633232950Stheraven                    // Remove the separator from the symbol, since it
5634232950Stheraven                    // has already appeared after the sign.
5635232950Stheraven                    __curr_symbol_.pop_back();
5636232950Stheraven                }
5637227825Stheraven                return;
5638227825Stheraven            default:
5639227825Stheraven                break;
5640227825Stheraven            }
5641227825Stheraven            break;
5642232950Stheraven        case 2:  // The sign string succeeds the quantity and currency symbol.
5643227825Stheraven            pat.field[0] = symbol;
5644227825Stheraven            pat.field[3] = sign;
5645227825Stheraven            switch (sep_by_space)
5646227825Stheraven            {
5647232950Stheraven            case 0:  // No space separates the currency symbol and value.
5648227825Stheraven                pat.field[1] = none;
5649227825Stheraven                pat.field[2] = value;
5650227825Stheraven                return;
5651232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5652232950Stheraven                pat.field[1] = none;
5653227825Stheraven                pat.field[2] = value;
5654232950Stheraven                if (!symbol_contains_sep) {
5655232950Stheraven                    // We insert the space into the symbol instead of
5656232950Stheraven                    // setting pat.field[1]=space so that when
5657232950Stheraven                    // showbase is not set, the space goes away too.
5658232950Stheraven                    __curr_symbol_.push_back(space_char);
5659232950Stheraven                }
5660227825Stheraven                return;
5661232950Stheraven            case 2:  // Space between sign and currency or value.
5662227825Stheraven                pat.field[1] = value;
5663227825Stheraven                pat.field[2] = space;
5664232950Stheraven                if (symbol_contains_sep) {
5665232950Stheraven                    // Remove the separator from the symbol, since it
5666232950Stheraven                    // will appear before the sign.
5667232950Stheraven                    __curr_symbol_.pop_back();
5668232950Stheraven                }
5669227825Stheraven                return;
5670227825Stheraven            default:
5671227825Stheraven                break;
5672227825Stheraven            }
5673227825Stheraven            break;
5674232950Stheraven        case 3:  // The sign string immediately precedes the currency symbol.
5675227825Stheraven            pat.field[0] = sign;
5676227825Stheraven            pat.field[3] = value;
5677227825Stheraven            switch (sep_by_space)
5678227825Stheraven            {
5679232950Stheraven            case 0:  // No space separates the currency symbol and value.
5680227825Stheraven                pat.field[1] = symbol;
5681227825Stheraven                pat.field[2] = none;
5682227825Stheraven                return;
5683232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5684227825Stheraven                pat.field[1] = symbol;
5685232950Stheraven                pat.field[2] = none;
5686232950Stheraven                if (!symbol_contains_sep) {
5687232950Stheraven                    // We insert the space into the symbol instead of
5688232950Stheraven                    // setting pat.field[2]=space so that when
5689232950Stheraven                    // showbase is not set, the space goes away too.
5690232950Stheraven                    __curr_symbol_.push_back(space_char);
5691232950Stheraven                }
5692227825Stheraven                return;
5693232950Stheraven            case 2:  // Space between sign and currency or value.
5694227825Stheraven                pat.field[1] = space;
5695227825Stheraven                pat.field[2] = symbol;
5696232950Stheraven                if (symbol_contains_sep) {
5697232950Stheraven                    // Remove the separator from the symbol, since it
5698232950Stheraven                    // has already appeared after the sign.
5699232950Stheraven                    __curr_symbol_.pop_back();
5700232950Stheraven                }
5701227825Stheraven                return;
5702227825Stheraven            default:
5703227825Stheraven                break;
5704227825Stheraven            }
5705227825Stheraven            break;
5706232950Stheraven        case 4:  // The sign string immediately succeeds the currency symbol.
5707227825Stheraven            pat.field[0] = symbol;
5708227825Stheraven            pat.field[3] = value;
5709227825Stheraven            switch (sep_by_space)
5710227825Stheraven            {
5711232950Stheraven            case 0:  // No space separates the currency symbol and value.
5712227825Stheraven                pat.field[1] = sign;
5713227825Stheraven                pat.field[2] = none;
5714227825Stheraven                return;
5715232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5716227825Stheraven                pat.field[1] = sign;
5717227825Stheraven                pat.field[2] = space;
5718232950Stheraven                if (symbol_contains_sep) {
5719232950Stheraven                    // Remove the separator from the symbol, since it
5720232950Stheraven                    // should not disappear when showbase is absent.
5721232950Stheraven                    __curr_symbol_.pop_back();
5722232950Stheraven                }
5723227825Stheraven                return;
5724232950Stheraven            case 2:  // Space between sign and currency or value.
5725232950Stheraven                pat.field[1] = none;
5726227825Stheraven                pat.field[2] = sign;
5727232950Stheraven                if (!symbol_contains_sep) {
5728232950Stheraven                    // We insert the space into the symbol instead of
5729232950Stheraven                    // setting pat.field[1]=space so that when
5730232950Stheraven                    // showbase is not set, the space goes away too.
5731232950Stheraven                    __curr_symbol_.push_back(space_char);
5732232950Stheraven                }
5733227825Stheraven                return;
5734227825Stheraven           default:
5735227825Stheraven                break;
5736227825Stheraven            }
5737227825Stheraven            break;
5738227825Stheraven        default:
5739227825Stheraven            break;
5740227825Stheraven        }
5741227825Stheraven        break;
5742227825Stheraven    default:
5743227825Stheraven        break;
5744227825Stheraven    }
5745227825Stheraven    pat.field[0] = symbol;
5746227825Stheraven    pat.field[1] = sign;
5747227825Stheraven    pat.field[2] = none;
5748227825Stheraven    pat.field[3] = value;
5749227825Stheraven}
5750227825Stheraven
5751227825Stheraventemplate<>
5752227825Stheravenvoid
5753227825Stheravenmoneypunct_byname<char, false>::init(const char* nm)
5754227825Stheraven{
5755227825Stheraven    typedef moneypunct<char, false> base;
5756227825Stheraven    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
5757227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5758232950Stheraven    if (loc == nullptr)
5759227825Stheraven        throw runtime_error("moneypunct_byname"
5760227825Stheraven                            " failed to construct for " + string(nm));
5761227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5762227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5763227825Stheraven    lconv* lc = localeconv_l(loc.get());
5764227825Stheraven#else
5765227825Stheraven    lconv* lc = __localeconv_l(loc.get());
5766227825Stheraven#endif
5767227825Stheraven    if (*lc->mon_decimal_point)
5768227825Stheraven        __decimal_point_ = *lc->mon_decimal_point;
5769227825Stheraven    else
5770227825Stheraven        __decimal_point_ = base::do_decimal_point();
5771227825Stheraven    if (*lc->mon_thousands_sep)
5772227825Stheraven        __thousands_sep_ = *lc->mon_thousands_sep;
5773227825Stheraven    else
5774227825Stheraven        __thousands_sep_ = base::do_thousands_sep();
5775227825Stheraven    __grouping_ = lc->mon_grouping;
5776227825Stheraven    __curr_symbol_ = lc->currency_symbol;
5777227825Stheraven    if (lc->frac_digits != CHAR_MAX)
5778227825Stheraven        __frac_digits_ = lc->frac_digits;
5779227825Stheraven    else
5780227825Stheraven        __frac_digits_ = base::do_frac_digits();
5781227825Stheraven    if (lc->p_sign_posn == 0)
5782227825Stheraven        __positive_sign_ = "()";
5783227825Stheraven    else
5784227825Stheraven        __positive_sign_ = lc->positive_sign;
5785227825Stheraven    if (lc->n_sign_posn == 0)
5786227825Stheraven        __negative_sign_ = "()";
5787227825Stheraven    else
5788227825Stheraven        __negative_sign_ = lc->negative_sign;
5789232950Stheraven    // Assume the positive and negative formats will want spaces in
5790232950Stheraven    // the same places in curr_symbol since there's no way to
5791232950Stheraven    // represent anything else.
5792232950Stheraven    string_type __dummy_curr_symbol = __curr_symbol_;
5793232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, false,
5794232950Stheraven               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5795232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, false,
5796232950Stheraven               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
5797227825Stheraven}
5798227825Stheraven
5799227825Stheraventemplate<>
5800227825Stheravenvoid
5801227825Stheravenmoneypunct_byname<char, true>::init(const char* nm)
5802227825Stheraven{
5803227825Stheraven    typedef moneypunct<char, true> base;
5804227825Stheraven    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
5805227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5806232950Stheraven    if (loc == nullptr)
5807227825Stheraven        throw runtime_error("moneypunct_byname"
5808227825Stheraven                            " failed to construct for " + string(nm));
5809227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5810227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5811227825Stheraven    lconv* lc = localeconv_l(loc.get());
5812227825Stheraven#else
5813227825Stheraven    lconv* lc = __localeconv_l(loc.get());
5814227825Stheraven#endif
5815227825Stheraven    if (*lc->mon_decimal_point)
5816227825Stheraven        __decimal_point_ = *lc->mon_decimal_point;
5817227825Stheraven    else
5818227825Stheraven        __decimal_point_ = base::do_decimal_point();
5819227825Stheraven    if (*lc->mon_thousands_sep)
5820227825Stheraven        __thousands_sep_ = *lc->mon_thousands_sep;
5821227825Stheraven    else
5822227825Stheraven        __thousands_sep_ = base::do_thousands_sep();
5823227825Stheraven    __grouping_ = lc->mon_grouping;
5824227825Stheraven    __curr_symbol_ = lc->int_curr_symbol;
5825227825Stheraven    if (lc->int_frac_digits != CHAR_MAX)
5826227825Stheraven        __frac_digits_ = lc->int_frac_digits;
5827227825Stheraven    else
5828227825Stheraven        __frac_digits_ = base::do_frac_digits();
5829249998Sdim#ifdef _WIN32
5830227825Stheraven    if (lc->p_sign_posn == 0)
5831227825Stheraven#else // _WIN32
5832227825Stheraven    if (lc->int_p_sign_posn == 0)
5833227825Stheraven#endif //_WIN32
5834227825Stheraven        __positive_sign_ = "()";
5835227825Stheraven    else
5836227825Stheraven        __positive_sign_ = lc->positive_sign;
5837249998Sdim#ifdef _WIN32
5838227825Stheraven    if(lc->n_sign_posn == 0)
5839227825Stheraven#else // _WIN32
5840227825Stheraven    if (lc->int_n_sign_posn == 0)
5841227825Stheraven#endif // _WIN32
5842227825Stheraven        __negative_sign_ = "()";
5843227825Stheraven    else
5844227825Stheraven        __negative_sign_ = lc->negative_sign;
5845232950Stheraven    // Assume the positive and negative formats will want spaces in
5846232950Stheraven    // the same places in curr_symbol since there's no way to
5847232950Stheraven    // represent anything else.
5848232950Stheraven    string_type __dummy_curr_symbol = __curr_symbol_;
5849249998Sdim#ifdef _WIN32
5850232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, true,
5851232950Stheraven               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5852232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, true,
5853232950Stheraven               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
5854227825Stheraven#else
5855232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, true,
5856232950Stheraven               lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5857232950Stheraven               lc->int_p_sign_posn, ' ');
5858232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, true,
5859232950Stheraven               lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5860232950Stheraven               lc->int_n_sign_posn, ' ');
5861227825Stheraven#endif // _WIN32
5862227825Stheraven}
5863227825Stheraven
5864227825Stheraventemplate<>
5865227825Stheravenvoid
5866227825Stheravenmoneypunct_byname<wchar_t, false>::init(const char* nm)
5867227825Stheraven{
5868227825Stheraven    typedef moneypunct<wchar_t, false> base;
5869227825Stheraven    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
5870227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5871232950Stheraven    if (loc == nullptr)
5872227825Stheraven        throw runtime_error("moneypunct_byname"
5873227825Stheraven                            " failed to construct for " + string(nm));
5874227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5875227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5876227825Stheraven    lconv* lc = localeconv_l(loc.get());
5877227825Stheraven#else
5878227825Stheraven    lconv* lc = __localeconv_l(loc.get());
5879227825Stheraven#endif
5880227825Stheraven    if (*lc->mon_decimal_point)
5881227825Stheraven        __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5882227825Stheraven    else
5883227825Stheraven        __decimal_point_ = base::do_decimal_point();
5884227825Stheraven    if (*lc->mon_thousands_sep)
5885227825Stheraven        __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5886227825Stheraven    else
5887227825Stheraven        __thousands_sep_ = base::do_thousands_sep();
5888227825Stheraven    __grouping_ = lc->mon_grouping;
5889227825Stheraven    wchar_t wbuf[100];
5890227825Stheraven    mbstate_t mb = {0};
5891227825Stheraven    const char* bb = lc->currency_symbol;
5892227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5893246487Stheraven    size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5894227825Stheraven#else
5895246487Stheraven    size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5896227825Stheraven#endif
5897232950Stheraven    if (j == size_t(-1))
5898227825Stheraven        __throw_runtime_error("locale not supported");
5899227825Stheraven    wchar_t* wbe = wbuf + j;
5900227825Stheraven    __curr_symbol_.assign(wbuf, wbe);
5901227825Stheraven    if (lc->frac_digits != CHAR_MAX)
5902227825Stheraven        __frac_digits_ = lc->frac_digits;
5903227825Stheraven    else
5904227825Stheraven        __frac_digits_ = base::do_frac_digits();
5905227825Stheraven    if (lc->p_sign_posn == 0)
5906227825Stheraven        __positive_sign_ = L"()";
5907227825Stheraven    else
5908227825Stheraven    {
5909227825Stheraven        mb = mbstate_t();
5910227825Stheraven        bb = lc->positive_sign;
5911227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5912246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5913227825Stheraven#else
5914246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5915227825Stheraven#endif
5916232950Stheraven        if (j == size_t(-1))
5917227825Stheraven            __throw_runtime_error("locale not supported");
5918227825Stheraven        wbe = wbuf + j;
5919227825Stheraven        __positive_sign_.assign(wbuf, wbe);
5920227825Stheraven    }
5921227825Stheraven    if (lc->n_sign_posn == 0)
5922227825Stheraven        __negative_sign_ = L"()";
5923227825Stheraven    else
5924227825Stheraven    {
5925227825Stheraven        mb = mbstate_t();
5926227825Stheraven        bb = lc->negative_sign;
5927227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5928246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5929227825Stheraven#else
5930246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5931227825Stheraven#endif
5932232950Stheraven        if (j == size_t(-1))
5933227825Stheraven            __throw_runtime_error("locale not supported");
5934227825Stheraven        wbe = wbuf + j;
5935227825Stheraven        __negative_sign_.assign(wbuf, wbe);
5936227825Stheraven    }
5937232950Stheraven    // Assume the positive and negative formats will want spaces in
5938232950Stheraven    // the same places in curr_symbol since there's no way to
5939232950Stheraven    // represent anything else.
5940232950Stheraven    string_type __dummy_curr_symbol = __curr_symbol_;
5941232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, false,
5942232950Stheraven               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5943232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, false,
5944232950Stheraven               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
5945227825Stheraven}
5946227825Stheraven
5947227825Stheraventemplate<>
5948227825Stheravenvoid
5949227825Stheravenmoneypunct_byname<wchar_t, true>::init(const char* nm)
5950227825Stheraven{
5951227825Stheraven    typedef moneypunct<wchar_t, true> base;
5952227825Stheraven    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
5953227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5954232950Stheraven    if (loc == nullptr)
5955227825Stheraven        throw runtime_error("moneypunct_byname"
5956227825Stheraven                            " failed to construct for " + string(nm));
5957227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5958227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5959227825Stheraven    lconv* lc = localeconv_l(loc.get());
5960227825Stheraven#else
5961227825Stheraven    lconv* lc = __localeconv_l(loc.get());
5962227825Stheraven#endif
5963227825Stheraven    if (*lc->mon_decimal_point)
5964227825Stheraven        __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5965227825Stheraven    else
5966227825Stheraven        __decimal_point_ = base::do_decimal_point();
5967227825Stheraven    if (*lc->mon_thousands_sep)
5968227825Stheraven        __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5969227825Stheraven    else
5970227825Stheraven        __thousands_sep_ = base::do_thousands_sep();
5971227825Stheraven    __grouping_ = lc->mon_grouping;
5972227825Stheraven    wchar_t wbuf[100];
5973227825Stheraven    mbstate_t mb = {0};
5974227825Stheraven    const char* bb = lc->int_curr_symbol;
5975227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5976246487Stheraven    size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5977227825Stheraven#else
5978246487Stheraven    size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5979227825Stheraven#endif
5980232950Stheraven    if (j == size_t(-1))
5981227825Stheraven        __throw_runtime_error("locale not supported");
5982227825Stheraven    wchar_t* wbe = wbuf + j;
5983227825Stheraven    __curr_symbol_.assign(wbuf, wbe);
5984227825Stheraven    if (lc->int_frac_digits != CHAR_MAX)
5985227825Stheraven        __frac_digits_ = lc->int_frac_digits;
5986227825Stheraven    else
5987227825Stheraven        __frac_digits_ = base::do_frac_digits();
5988249998Sdim#ifdef _WIN32
5989227825Stheraven    if (lc->p_sign_posn == 0)
5990227825Stheraven#else // _WIN32
5991227825Stheraven    if (lc->int_p_sign_posn == 0)
5992227825Stheraven#endif // _WIN32
5993227825Stheraven        __positive_sign_ = L"()";
5994227825Stheraven    else
5995227825Stheraven    {
5996227825Stheraven        mb = mbstate_t();
5997227825Stheraven        bb = lc->positive_sign;
5998227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5999246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6000227825Stheraven#else
6001246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6002227825Stheraven#endif
6003232950Stheraven        if (j == size_t(-1))
6004227825Stheraven            __throw_runtime_error("locale not supported");
6005227825Stheraven        wbe = wbuf + j;
6006227825Stheraven        __positive_sign_.assign(wbuf, wbe);
6007227825Stheraven    }
6008249998Sdim#ifdef _WIN32
6009227825Stheraven    if (lc->n_sign_posn == 0)
6010227825Stheraven#else // _WIN32
6011227825Stheraven    if (lc->int_n_sign_posn == 0)
6012227825Stheraven#endif // _WIN32
6013227825Stheraven        __negative_sign_ = L"()";
6014227825Stheraven    else
6015227825Stheraven    {
6016227825Stheraven        mb = mbstate_t();
6017227825Stheraven        bb = lc->negative_sign;
6018227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6019246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6020227825Stheraven#else
6021246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6022227825Stheraven#endif
6023232950Stheraven        if (j == size_t(-1))
6024227825Stheraven            __throw_runtime_error("locale not supported");
6025227825Stheraven        wbe = wbuf + j;
6026227825Stheraven        __negative_sign_.assign(wbuf, wbe);
6027227825Stheraven    }
6028232950Stheraven    // Assume the positive and negative formats will want spaces in
6029232950Stheraven    // the same places in curr_symbol since there's no way to
6030232950Stheraven    // represent anything else.
6031232950Stheraven    string_type __dummy_curr_symbol = __curr_symbol_;
6032249998Sdim#ifdef _WIN32
6033232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, true,
6034232950Stheraven               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6035232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, true,
6036232950Stheraven               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6037227825Stheraven#else // _WIN32
6038232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, true,
6039232950Stheraven               lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6040232950Stheraven               lc->int_p_sign_posn, L' ');
6041232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, true,
6042232950Stheraven               lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6043232950Stheraven               lc->int_n_sign_posn, L' ');
6044227825Stheraven#endif // _WIN32
6045227825Stheraven}
6046227825Stheraven
6047227825Stheravenvoid __do_nothing(void*) {}
6048227825Stheraven
6049227825Stheravenvoid __throw_runtime_error(const char* msg)
6050227825Stheraven{
6051227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
6052227825Stheraven    throw runtime_error(msg);
6053249998Sdim#else
6054249998Sdim    (void)msg;
6055227825Stheraven#endif
6056227825Stheraven}
6057227825Stheraven
6058227825Stheraventemplate class collate<char>;
6059227825Stheraventemplate class collate<wchar_t>;
6060227825Stheraven
6061227825Stheraventemplate class num_get<char>;
6062227825Stheraventemplate class num_get<wchar_t>;
6063227825Stheraven
6064232950Stheraventemplate struct __num_get<char>;
6065232950Stheraventemplate struct __num_get<wchar_t>;
6066227825Stheraven
6067227825Stheraventemplate class num_put<char>;
6068227825Stheraventemplate class num_put<wchar_t>;
6069227825Stheraven
6070232950Stheraventemplate struct __num_put<char>;
6071232950Stheraventemplate struct __num_put<wchar_t>;
6072227825Stheraven
6073227825Stheraventemplate class time_get<char>;
6074227825Stheraventemplate class time_get<wchar_t>;
6075227825Stheraven
6076227825Stheraventemplate class time_get_byname<char>;
6077227825Stheraventemplate class time_get_byname<wchar_t>;
6078227825Stheraven
6079227825Stheraventemplate class time_put<char>;
6080227825Stheraventemplate class time_put<wchar_t>;
6081227825Stheraven
6082227825Stheraventemplate class time_put_byname<char>;
6083227825Stheraventemplate class time_put_byname<wchar_t>;
6084227825Stheraven
6085227825Stheraventemplate class moneypunct<char, false>;
6086227825Stheraventemplate class moneypunct<char, true>;
6087227825Stheraventemplate class moneypunct<wchar_t, false>;
6088227825Stheraventemplate class moneypunct<wchar_t, true>;
6089227825Stheraven
6090227825Stheraventemplate class moneypunct_byname<char, false>;
6091227825Stheraventemplate class moneypunct_byname<char, true>;
6092227825Stheraventemplate class moneypunct_byname<wchar_t, false>;
6093227825Stheraventemplate class moneypunct_byname<wchar_t, true>;
6094227825Stheraven
6095227825Stheraventemplate class money_get<char>;
6096227825Stheraventemplate class money_get<wchar_t>;
6097227825Stheraven
6098227825Stheraventemplate class __money_get<char>;
6099227825Stheraventemplate class __money_get<wchar_t>;
6100227825Stheraven
6101227825Stheraventemplate class money_put<char>;
6102227825Stheraventemplate class money_put<wchar_t>;
6103227825Stheraven
6104227825Stheraventemplate class __money_put<char>;
6105227825Stheraventemplate class __money_put<wchar_t>;
6106227825Stheraven
6107227825Stheraventemplate class messages<char>;
6108227825Stheraventemplate class messages<wchar_t>;
6109227825Stheraven
6110227825Stheraventemplate class messages_byname<char>;
6111227825Stheraventemplate class messages_byname<wchar_t>;
6112227825Stheraven
6113227825Stheraventemplate class codecvt_byname<char, char, mbstate_t>;
6114227825Stheraventemplate class codecvt_byname<wchar_t, char, mbstate_t>;
6115227825Stheraventemplate class codecvt_byname<char16_t, char, mbstate_t>;
6116227825Stheraventemplate class codecvt_byname<char32_t, char, mbstate_t>;
6117227825Stheraven
6118227825Stheraventemplate class __vector_base_common<true>;
6119227825Stheraven
6120227825Stheraven_LIBCPP_END_NAMESPACE_STD
6121