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
10262801Sdim#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
11262801Sdim
12232950Stheraven// On Solaris, we need to define something to make the C99 parts of localeconv
13232950Stheraven// visible.
14232950Stheraven#ifdef __sun__
15232950Stheraven#define _LCONV_C99
16232950Stheraven#endif
17232950Stheraven
18227825Stheraven#include "string"
19227825Stheraven#include "locale"
20227825Stheraven#include "codecvt"
21227825Stheraven#include "vector"
22227825Stheraven#include "algorithm"
23227825Stheraven#include "typeinfo"
24262801Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
25262801Sdim#  include "type_traits"
26262801Sdim#endif
27227825Stheraven#include "clocale"
28227825Stheraven#include "cstring"
29227825Stheraven#include "cwctype"
30227825Stheraven#include "__sso_allocator"
31262801Sdim#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
32227825Stheraven#include <support/win32/locale_win32.h>
33262801Sdim#else // _LIBCPP_MSVCRT
34227825Stheraven#include <langinfo.h>
35262801Sdim#endif // !_LIBCPP_MSVCRT
36227825Stheraven#include <stdlib.h>
37262801Sdim#include <stdio.h>
38227825Stheraven
39249998Sdim// On Linux, wint_t and wchar_t have different signed-ness, and this causes
40249998Sdim// lots of noise in the build log, but no bugs that I know of.
41262801Sdim#if defined(__clang__)
42249998Sdim#pragma clang diagnostic ignored "-Wsign-conversion"
43262801Sdim#endif
44249998Sdim
45227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
46227825Stheraven
47227825Stheraven#ifdef __cloc_defined
48227825Stheravenlocale_t __cloc() {
49227825Stheraven  // In theory this could create a race condition. In practice
50227825Stheraven  // the race condition is non-fatal since it will just create
51227825Stheraven  // a little resource leak. Better approach would be appreciated.
52227825Stheraven  static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
53227825Stheraven  return result;
54227825Stheraven}
55227825Stheraven#endif // __cloc_defined
56227825Stheraven
57227825Stheravennamespace {
58227825Stheraven
59227825Stheravenstruct release
60227825Stheraven{
61227825Stheraven    void operator()(locale::facet* p) {p->__release_shared();}
62227825Stheraven};
63227825Stheraven
64227825Stheraventemplate <class T, class A0>
65227825Stheraveninline
66227825StheravenT&
67227825Stheravenmake(A0 a0)
68227825Stheraven{
69227825Stheraven    static typename aligned_storage<sizeof(T)>::type buf;
70227825Stheraven    ::new (&buf) T(a0);
71227825Stheraven    return *(T*)&buf;
72227825Stheraven}
73227825Stheraven
74227825Stheraventemplate <class T, class A0, class A1>
75227825Stheraveninline
76227825StheravenT&
77227825Stheravenmake(A0 a0, A1 a1)
78227825Stheraven{
79227825Stheraven    static typename aligned_storage<sizeof(T)>::type buf;
80227825Stheraven    ::new (&buf) T(a0, a1);
81227825Stheraven    return *(T*)&buf;
82227825Stheraven}
83227825Stheraven
84227825Stheraventemplate <class T, class A0, class A1, class A2>
85227825Stheraveninline
86227825StheravenT&
87227825Stheravenmake(A0 a0, A1 a1, A2 a2)
88227825Stheraven{
89227825Stheraven    static typename aligned_storage<sizeof(T)>::type buf;
90227825Stheraven    ::new (&buf) T(a0, a1, a2);
91227825Stheraven    return *(T*)&buf;
92227825Stheraven}
93227825Stheraven
94246487Stheraventemplate <typename T, size_t N>
95246487Stheraveninline
96246487Stheraven_LIBCPP_CONSTEXPR
97246487Stheravensize_t
98246487Stheravencountof(const T (&)[N])
99246487Stheraven{
100246487Stheraven    return N;
101227825Stheraven}
102227825Stheraven
103246487Stheraventemplate <typename T>
104246487Stheraveninline
105246487Stheraven_LIBCPP_CONSTEXPR
106246487Stheravensize_t
107246487Stheravencountof(const T * const begin, const T * const end)
108246487Stheraven{
109246487Stheraven    return static_cast<size_t>(end - begin);
110246487Stheraven}
111246487Stheraven
112246487Stheraven}
113246487Stheraven
114262801Sdim#if defined(_AIX)
115262801Sdim// Set priority to INT_MIN + 256 + 150
116262801Sdim# pragma priority ( -2147483242 )
117262801Sdim#endif
118262801Sdim
119246487Stheravenconst locale::category locale::none;
120246487Stheravenconst locale::category locale::collate;
121246487Stheravenconst locale::category locale::ctype;
122246487Stheravenconst locale::category locale::monetary;
123246487Stheravenconst locale::category locale::numeric;
124246487Stheravenconst locale::category locale::time;
125246487Stheravenconst locale::category locale::messages;
126246487Stheravenconst locale::category locale::all;
127246487Stheraven
128262801Sdim#if defined(__clang__)
129232950Stheraven#pragma clang diagnostic push
130232950Stheraven#pragma clang diagnostic ignored "-Wpadded"
131262801Sdim#endif
132232950Stheraven
133227825Stheravenclass _LIBCPP_HIDDEN locale::__imp
134227825Stheraven    : public facet
135227825Stheraven{
136227825Stheraven    enum {N = 28};
137262801Sdim#if defined(_LIBCPP_MSVC)
138262801Sdim// FIXME: MSVC doesn't support aligned parameters by value.
139262801Sdim// I can't get the __sso_allocator to work here
140262801Sdim// for MSVC I think for this reason.
141262801Sdim    vector<facet*> facets_;
142262801Sdim#else
143232950Stheraven    vector<facet*, __sso_allocator<facet*, N> > facets_;
144262801Sdim#endif
145227825Stheraven    string         name_;
146227825Stheravenpublic:
147227825Stheraven    explicit __imp(size_t refs = 0);
148227825Stheraven    explicit __imp(const string& name, size_t refs = 0);
149227825Stheraven    __imp(const __imp&);
150227825Stheraven    __imp(const __imp&, const string&, locale::category c);
151227825Stheraven    __imp(const __imp& other, const __imp& one, locale::category c);
152227825Stheraven    __imp(const __imp&, facet* f, long id);
153227825Stheraven    ~__imp();
154227825Stheraven
155227825Stheraven    const string& name() const {return name_;}
156232950Stheraven    bool has_facet(long id) const
157232950Stheraven        {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
158227825Stheraven    const locale::facet* use_facet(long id) const;
159227825Stheraven
160227825Stheraven    static const locale& make_classic();
161227825Stheraven    static       locale& make_global();
162227825Stheravenprivate:
163227825Stheraven    void install(facet* f, long id);
164227825Stheraven    template <class F> void install(F* f) {install(f, f->id.__get());}
165227825Stheraven    template <class F> void install_from(const __imp& other);
166227825Stheraven};
167227825Stheraven
168262801Sdim#if defined(__clang__)
169232950Stheraven#pragma clang diagnostic pop
170262801Sdim#endif
171232950Stheraven
172227825Stheravenlocale::__imp::__imp(size_t refs)
173227825Stheraven    : facet(refs),
174232950Stheraven      facets_(N),
175232950Stheraven      name_("C")
176227825Stheraven{
177227825Stheraven    facets_.clear();
178232950Stheraven    install(&make<_VSTD::collate<char> >(1u));
179232950Stheraven    install(&make<_VSTD::collate<wchar_t> >(1u));
180232950Stheraven    install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
181232950Stheraven    install(&make<_VSTD::ctype<wchar_t> >(1u));
182232950Stheraven    install(&make<codecvt<char, char, mbstate_t> >(1u));
183232950Stheraven    install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
184232950Stheraven    install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
185232950Stheraven    install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
186232950Stheraven    install(&make<numpunct<char> >(1u));
187232950Stheraven    install(&make<numpunct<wchar_t> >(1u));
188232950Stheraven    install(&make<num_get<char> >(1u));
189232950Stheraven    install(&make<num_get<wchar_t> >(1u));
190232950Stheraven    install(&make<num_put<char> >(1u));
191232950Stheraven    install(&make<num_put<wchar_t> >(1u));
192232950Stheraven    install(&make<moneypunct<char, false> >(1u));
193232950Stheraven    install(&make<moneypunct<char, true> >(1u));
194232950Stheraven    install(&make<moneypunct<wchar_t, false> >(1u));
195232950Stheraven    install(&make<moneypunct<wchar_t, true> >(1u));
196232950Stheraven    install(&make<money_get<char> >(1u));
197232950Stheraven    install(&make<money_get<wchar_t> >(1u));
198232950Stheraven    install(&make<money_put<char> >(1u));
199232950Stheraven    install(&make<money_put<wchar_t> >(1u));
200232950Stheraven    install(&make<time_get<char> >(1u));
201232950Stheraven    install(&make<time_get<wchar_t> >(1u));
202232950Stheraven    install(&make<time_put<char> >(1u));
203232950Stheraven    install(&make<time_put<wchar_t> >(1u));
204232950Stheraven    install(&make<_VSTD::messages<char> >(1u));
205232950Stheraven    install(&make<_VSTD::messages<wchar_t> >(1u));
206227825Stheraven}
207227825Stheraven
208227825Stheravenlocale::__imp::__imp(const string& name, size_t refs)
209227825Stheraven    : facet(refs),
210232950Stheraven      facets_(N),
211232950Stheraven      name_(name)
212227825Stheraven{
213227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
214227825Stheraven    try
215227825Stheraven    {
216227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
217227825Stheraven        facets_ = locale::classic().__locale_->facets_;
218227825Stheraven        for (unsigned i = 0; i < facets_.size(); ++i)
219227825Stheraven            if (facets_[i])
220227825Stheraven                facets_[i]->__add_shared();
221227825Stheraven        install(new collate_byname<char>(name_));
222227825Stheraven        install(new collate_byname<wchar_t>(name_));
223227825Stheraven        install(new ctype_byname<char>(name_));
224227825Stheraven        install(new ctype_byname<wchar_t>(name_));
225227825Stheraven        install(new codecvt_byname<char, char, mbstate_t>(name_));
226227825Stheraven        install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
227227825Stheraven        install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
228227825Stheraven        install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
229227825Stheraven        install(new numpunct_byname<char>(name_));
230227825Stheraven        install(new numpunct_byname<wchar_t>(name_));
231227825Stheraven        install(new moneypunct_byname<char, false>(name_));
232227825Stheraven        install(new moneypunct_byname<char, true>(name_));
233227825Stheraven        install(new moneypunct_byname<wchar_t, false>(name_));
234227825Stheraven        install(new moneypunct_byname<wchar_t, true>(name_));
235227825Stheraven        install(new time_get_byname<char>(name_));
236227825Stheraven        install(new time_get_byname<wchar_t>(name_));
237227825Stheraven        install(new time_put_byname<char>(name_));
238227825Stheraven        install(new time_put_byname<wchar_t>(name_));
239227825Stheraven        install(new messages_byname<char>(name_));
240227825Stheraven        install(new messages_byname<wchar_t>(name_));
241227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
242227825Stheraven    }
243227825Stheraven    catch (...)
244227825Stheraven    {
245227825Stheraven        for (unsigned i = 0; i < facets_.size(); ++i)
246227825Stheraven            if (facets_[i])
247227825Stheraven                facets_[i]->__release_shared();
248227825Stheraven        throw;
249227825Stheraven    }
250227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
251227825Stheraven}
252227825Stheraven
253246487Stheraven// NOTE avoid the `base class should be explicitly initialized in the
254246487Stheraven// copy constructor` warning emitted by GCC
255253159Stheraven#if defined(__clang__) || _GNUC_VER >= 406
256246487Stheraven#pragma GCC diagnostic push
257246487Stheraven#pragma GCC diagnostic ignored "-Wextra"
258253159Stheraven#endif
259246487Stheraven
260227825Stheravenlocale::__imp::__imp(const __imp& other)
261232950Stheraven    : facets_(max<size_t>(N, other.facets_.size())),
262232950Stheraven      name_(other.name_)
263227825Stheraven{
264227825Stheraven    facets_ = other.facets_;
265227825Stheraven    for (unsigned i = 0; i < facets_.size(); ++i)
266227825Stheraven        if (facets_[i])
267227825Stheraven            facets_[i]->__add_shared();
268227825Stheraven}
269227825Stheraven
270253159Stheraven#if defined(__clang__) || _GNUC_VER >= 406
271246487Stheraven#pragma GCC diagnostic pop
272253159Stheraven#endif
273246487Stheraven
274227825Stheravenlocale::__imp::__imp(const __imp& other, const string& name, locale::category c)
275232950Stheraven    : facets_(N),
276232950Stheraven      name_("*")
277227825Stheraven{
278227825Stheraven    facets_ = other.facets_;
279227825Stheraven    for (unsigned i = 0; i < facets_.size(); ++i)
280227825Stheraven        if (facets_[i])
281227825Stheraven            facets_[i]->__add_shared();
282227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
283227825Stheraven    try
284227825Stheraven    {
285227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
286227825Stheraven        if (c & locale::collate)
287227825Stheraven        {
288227825Stheraven            install(new collate_byname<char>(name));
289227825Stheraven            install(new collate_byname<wchar_t>(name));
290227825Stheraven        }
291227825Stheraven        if (c & locale::ctype)
292227825Stheraven        {
293227825Stheraven            install(new ctype_byname<char>(name));
294227825Stheraven            install(new ctype_byname<wchar_t>(name));
295227825Stheraven            install(new codecvt_byname<char, char, mbstate_t>(name));
296227825Stheraven            install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
297227825Stheraven            install(new codecvt_byname<char16_t, char, mbstate_t>(name));
298227825Stheraven            install(new codecvt_byname<char32_t, char, mbstate_t>(name));
299227825Stheraven        }
300227825Stheraven        if (c & locale::monetary)
301227825Stheraven        {
302227825Stheraven            install(new moneypunct_byname<char, false>(name));
303227825Stheraven            install(new moneypunct_byname<char, true>(name));
304227825Stheraven            install(new moneypunct_byname<wchar_t, false>(name));
305227825Stheraven            install(new moneypunct_byname<wchar_t, true>(name));
306227825Stheraven        }
307227825Stheraven        if (c & locale::numeric)
308227825Stheraven        {
309227825Stheraven            install(new numpunct_byname<char>(name));
310227825Stheraven            install(new numpunct_byname<wchar_t>(name));
311227825Stheraven        }
312227825Stheraven        if (c & locale::time)
313227825Stheraven        {
314227825Stheraven            install(new time_get_byname<char>(name));
315227825Stheraven            install(new time_get_byname<wchar_t>(name));
316227825Stheraven            install(new time_put_byname<char>(name));
317227825Stheraven            install(new time_put_byname<wchar_t>(name));
318227825Stheraven        }
319227825Stheraven        if (c & locale::messages)
320227825Stheraven        {
321227825Stheraven            install(new messages_byname<char>(name));
322227825Stheraven            install(new messages_byname<wchar_t>(name));
323227825Stheraven        }
324227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
325227825Stheraven    }
326227825Stheraven    catch (...)
327227825Stheraven    {
328227825Stheraven        for (unsigned i = 0; i < facets_.size(); ++i)
329227825Stheraven            if (facets_[i])
330227825Stheraven                facets_[i]->__release_shared();
331227825Stheraven        throw;
332227825Stheraven    }
333227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
334227825Stheraven}
335227825Stheraven
336227825Stheraventemplate<class F>
337227825Stheraveninline
338227825Stheravenvoid
339227825Stheravenlocale::__imp::install_from(const locale::__imp& one)
340227825Stheraven{
341227825Stheraven    long id = F::id.__get();
342227825Stheraven    install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
343227825Stheraven}
344227825Stheraven
345227825Stheravenlocale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
346232950Stheraven    : facets_(N),
347232950Stheraven      name_("*")
348227825Stheraven{
349227825Stheraven    facets_ = other.facets_;
350227825Stheraven    for (unsigned i = 0; i < facets_.size(); ++i)
351227825Stheraven        if (facets_[i])
352227825Stheraven            facets_[i]->__add_shared();
353227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
354227825Stheraven    try
355227825Stheraven    {
356227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
357227825Stheraven        if (c & locale::collate)
358227825Stheraven        {
359227825Stheraven            install_from<_VSTD::collate<char> >(one);
360227825Stheraven            install_from<_VSTD::collate<wchar_t> >(one);
361227825Stheraven        }
362227825Stheraven        if (c & locale::ctype)
363227825Stheraven        {
364227825Stheraven            install_from<_VSTD::ctype<char> >(one);
365227825Stheraven            install_from<_VSTD::ctype<wchar_t> >(one);
366227825Stheraven            install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
367227825Stheraven            install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
368227825Stheraven            install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
369227825Stheraven            install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
370227825Stheraven        }
371227825Stheraven        if (c & locale::monetary)
372227825Stheraven        {
373227825Stheraven            install_from<moneypunct<char, false> >(one);
374227825Stheraven            install_from<moneypunct<char, true> >(one);
375227825Stheraven            install_from<moneypunct<wchar_t, false> >(one);
376227825Stheraven            install_from<moneypunct<wchar_t, true> >(one);
377227825Stheraven            install_from<money_get<char> >(one);
378227825Stheraven            install_from<money_get<wchar_t> >(one);
379227825Stheraven            install_from<money_put<char> >(one);
380227825Stheraven            install_from<money_put<wchar_t> >(one);
381227825Stheraven        }
382227825Stheraven        if (c & locale::numeric)
383227825Stheraven        {
384227825Stheraven            install_from<numpunct<char> >(one);
385227825Stheraven            install_from<numpunct<wchar_t> >(one);
386227825Stheraven            install_from<num_get<char> >(one);
387227825Stheraven            install_from<num_get<wchar_t> >(one);
388227825Stheraven            install_from<num_put<char> >(one);
389227825Stheraven            install_from<num_put<wchar_t> >(one);
390227825Stheraven        }
391227825Stheraven        if (c & locale::time)
392227825Stheraven        {
393227825Stheraven            install_from<time_get<char> >(one);
394227825Stheraven            install_from<time_get<wchar_t> >(one);
395227825Stheraven            install_from<time_put<char> >(one);
396227825Stheraven            install_from<time_put<wchar_t> >(one);
397227825Stheraven        }
398227825Stheraven        if (c & locale::messages)
399227825Stheraven        {
400227825Stheraven            install_from<_VSTD::messages<char> >(one);
401227825Stheraven            install_from<_VSTD::messages<wchar_t> >(one);
402227825Stheraven        }
403227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
404227825Stheraven    }
405227825Stheraven    catch (...)
406227825Stheraven    {
407227825Stheraven        for (unsigned i = 0; i < facets_.size(); ++i)
408227825Stheraven            if (facets_[i])
409227825Stheraven                facets_[i]->__release_shared();
410227825Stheraven        throw;
411227825Stheraven    }
412227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
413227825Stheraven}
414227825Stheraven
415227825Stheravenlocale::__imp::__imp(const __imp& other, facet* f, long id)
416232950Stheraven    : facets_(max<size_t>(N, other.facets_.size()+1)),
417232950Stheraven      name_("*")
418227825Stheraven{
419227825Stheraven    f->__add_shared();
420227825Stheraven    unique_ptr<facet, release> hold(f);
421227825Stheraven    facets_ = other.facets_;
422227825Stheraven    for (unsigned i = 0; i < other.facets_.size(); ++i)
423227825Stheraven        if (facets_[i])
424227825Stheraven            facets_[i]->__add_shared();
425227825Stheraven    install(hold.get(), id);
426227825Stheraven}
427227825Stheraven
428227825Stheravenlocale::__imp::~__imp()
429227825Stheraven{
430227825Stheraven    for (unsigned i = 0; i < facets_.size(); ++i)
431227825Stheraven        if (facets_[i])
432227825Stheraven            facets_[i]->__release_shared();
433227825Stheraven}
434227825Stheraven
435227825Stheravenvoid
436227825Stheravenlocale::__imp::install(facet* f, long id)
437227825Stheraven{
438227825Stheraven    f->__add_shared();
439227825Stheraven    unique_ptr<facet, release> hold(f);
440232950Stheraven    if (static_cast<size_t>(id) >= facets_.size())
441232950Stheraven        facets_.resize(static_cast<size_t>(id+1));
442232950Stheraven    if (facets_[static_cast<size_t>(id)])
443232950Stheraven        facets_[static_cast<size_t>(id)]->__release_shared();
444232950Stheraven    facets_[static_cast<size_t>(id)] = hold.release();
445227825Stheraven}
446227825Stheraven
447227825Stheravenconst locale::facet*
448227825Stheravenlocale::__imp::use_facet(long id) const
449227825Stheraven{
450227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
451227825Stheraven    if (!has_facet(id))
452227825Stheraven        throw bad_cast();
453227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
454232950Stheraven    return facets_[static_cast<size_t>(id)];
455227825Stheraven}
456227825Stheraven
457227825Stheraven// locale
458227825Stheraven
459227825Stheravenconst locale&
460227825Stheravenlocale::__imp::make_classic()
461227825Stheraven{
462227825Stheraven    // only one thread can get in here and it only gets in once
463227825Stheraven    static aligned_storage<sizeof(locale)>::type buf;
464227825Stheraven    locale* c = (locale*)&buf;
465232950Stheraven    c->__locale_ = &make<__imp>(1u);
466227825Stheraven    return *c;
467227825Stheraven}
468227825Stheraven
469227825Stheravenconst locale&
470227825Stheravenlocale::classic()
471227825Stheraven{
472227825Stheraven    static const locale& c = __imp::make_classic();
473227825Stheraven    return c;
474227825Stheraven}
475227825Stheraven
476227825Stheravenlocale&
477227825Stheravenlocale::__imp::make_global()
478227825Stheraven{
479227825Stheraven    // only one thread can get in here and it only gets in once
480227825Stheraven    static aligned_storage<sizeof(locale)>::type buf;
481227825Stheraven    ::new (&buf) locale(locale::classic());
482227825Stheraven    return *(locale*)&buf;
483227825Stheraven}
484227825Stheraven
485227825Stheravenlocale&
486227825Stheravenlocale::__global()
487227825Stheraven{
488227825Stheraven    static locale& g = __imp::make_global();
489227825Stheraven    return g;
490227825Stheraven}
491227825Stheraven
492227825Stheravenlocale::locale()  _NOEXCEPT
493227825Stheraven    : __locale_(__global().__locale_)
494227825Stheraven{
495227825Stheraven    __locale_->__add_shared();
496227825Stheraven}
497227825Stheraven
498227825Stheravenlocale::locale(const locale& l)  _NOEXCEPT
499227825Stheraven    : __locale_(l.__locale_)
500227825Stheraven{
501227825Stheraven    __locale_->__add_shared();
502227825Stheraven}
503227825Stheraven
504227825Stheravenlocale::~locale()
505227825Stheraven{
506227825Stheraven    __locale_->__release_shared();
507227825Stheraven}
508227825Stheraven
509227825Stheravenconst locale&
510227825Stheravenlocale::operator=(const locale& other)  _NOEXCEPT
511227825Stheraven{
512227825Stheraven    other.__locale_->__add_shared();
513227825Stheraven    __locale_->__release_shared();
514227825Stheraven    __locale_ = other.__locale_;
515227825Stheraven    return *this;
516227825Stheraven}
517227825Stheraven
518227825Stheravenlocale::locale(const char* name)
519227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
520227825Stheraven    : __locale_(name ? new __imp(name)
521227825Stheraven                     : throw runtime_error("locale constructed with null"))
522227825Stheraven#else  // _LIBCPP_NO_EXCEPTIONS
523227825Stheraven    : __locale_(new __imp(name))
524227825Stheraven#endif
525227825Stheraven{
526227825Stheraven    __locale_->__add_shared();
527227825Stheraven}
528227825Stheraven
529227825Stheravenlocale::locale(const string& name)
530227825Stheraven    : __locale_(new __imp(name))
531227825Stheraven{
532227825Stheraven    __locale_->__add_shared();
533227825Stheraven}
534227825Stheraven
535227825Stheravenlocale::locale(const locale& other, const char* name, category c)
536227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
537227825Stheraven    : __locale_(name ? new __imp(*other.__locale_, name, c)
538227825Stheraven                     : throw runtime_error("locale constructed with null"))
539227825Stheraven#else  // _LIBCPP_NO_EXCEPTIONS
540227825Stheraven    : __locale_(new __imp(*other.__locale_, name, c))
541227825Stheraven#endif
542227825Stheraven{
543227825Stheraven    __locale_->__add_shared();
544227825Stheraven}
545227825Stheraven
546227825Stheravenlocale::locale(const locale& other, const string& name, category c)
547227825Stheraven    : __locale_(new __imp(*other.__locale_, name, c))
548227825Stheraven{
549227825Stheraven    __locale_->__add_shared();
550227825Stheraven}
551227825Stheraven
552227825Stheravenlocale::locale(const locale& other, const locale& one, category c)
553227825Stheraven    : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
554227825Stheraven{
555227825Stheraven    __locale_->__add_shared();
556227825Stheraven}
557227825Stheraven
558227825Stheravenstring
559227825Stheravenlocale::name() const
560227825Stheraven{
561227825Stheraven    return __locale_->name();
562227825Stheraven}
563227825Stheraven
564227825Stheravenvoid
565227825Stheravenlocale::__install_ctor(const locale& other, facet* f, long id)
566227825Stheraven{
567227825Stheraven    if (f)
568227825Stheraven        __locale_ = new __imp(*other.__locale_, f, id);
569227825Stheraven    else
570227825Stheraven        __locale_ = other.__locale_;
571227825Stheraven    __locale_->__add_shared();
572227825Stheraven}
573227825Stheraven
574227825Stheravenlocale
575227825Stheravenlocale::global(const locale& loc)
576227825Stheraven{
577227825Stheraven    locale& g = __global();
578227825Stheraven    locale r = g;
579227825Stheraven    g = loc;
580227825Stheraven    if (g.name() != "*")
581227825Stheraven        setlocale(LC_ALL, g.name().c_str());
582227825Stheraven    return r;
583227825Stheraven}
584227825Stheraven
585227825Stheravenbool
586227825Stheravenlocale::has_facet(id& x) const
587227825Stheraven{
588227825Stheraven    return __locale_->has_facet(x.__get());
589227825Stheraven}
590227825Stheraven
591227825Stheravenconst locale::facet*
592227825Stheravenlocale::use_facet(id& x) const
593227825Stheraven{
594227825Stheraven    return __locale_->use_facet(x.__get());
595227825Stheraven}
596227825Stheraven
597227825Stheravenbool
598227825Stheravenlocale::operator==(const locale& y) const
599227825Stheraven{
600227825Stheraven    return (__locale_ == y.__locale_)
601227825Stheraven        || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
602227825Stheraven}
603227825Stheraven
604227825Stheraven// locale::facet
605227825Stheraven
606227825Stheravenlocale::facet::~facet()
607227825Stheraven{
608227825Stheraven}
609227825Stheraven
610227825Stheravenvoid
611227825Stheravenlocale::facet::__on_zero_shared() _NOEXCEPT
612227825Stheraven{
613227825Stheraven    delete this;
614227825Stheraven}
615227825Stheraven
616227825Stheraven// locale::id
617227825Stheraven
618227825Stheravenint32_t locale::id::__next_id = 0;
619227825Stheraven
620227825Stheravennamespace
621227825Stheraven{
622227825Stheraven
623227825Stheravenclass __fake_bind
624227825Stheraven{
625227825Stheraven    locale::id* id_;
626227825Stheraven    void (locale::id::* pmf_)();
627227825Stheravenpublic:
628227825Stheraven    __fake_bind(void (locale::id::* pmf)(), locale::id* id)
629227825Stheraven        : id_(id), pmf_(pmf) {}
630227825Stheraven
631227825Stheraven    void operator()() const
632227825Stheraven    {
633227825Stheraven        (id_->*pmf_)();
634227825Stheraven    }
635227825Stheraven};
636227825Stheraven
637227825Stheraven}
638227825Stheraven
639227825Stheravenlong
640227825Stheravenlocale::id::__get()
641227825Stheraven{
642227825Stheraven    call_once(__flag_, __fake_bind(&locale::id::__init, this));
643227825Stheraven    return __id_ - 1;
644227825Stheraven}
645227825Stheraven
646227825Stheravenvoid
647227825Stheravenlocale::id::__init()
648227825Stheraven{
649227825Stheraven    __id_ = __sync_add_and_fetch(&__next_id, 1);
650227825Stheraven}
651227825Stheraven
652227825Stheraven// template <> class collate_byname<char>
653227825Stheraven
654227825Stheravencollate_byname<char>::collate_byname(const char* n, size_t refs)
655227825Stheraven    : collate<char>(refs),
656227825Stheraven      __l(newlocale(LC_ALL_MASK, n, 0))
657227825Stheraven{
658227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
659227825Stheraven    if (__l == 0)
660227825Stheraven        throw runtime_error("collate_byname<char>::collate_byname"
661227825Stheraven                            " failed to construct for " + string(n));
662227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
663227825Stheraven}
664227825Stheraven
665227825Stheravencollate_byname<char>::collate_byname(const string& name, size_t refs)
666227825Stheraven    : collate<char>(refs),
667227825Stheraven      __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
668227825Stheraven{
669227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
670227825Stheraven    if (__l == 0)
671227825Stheraven        throw runtime_error("collate_byname<char>::collate_byname"
672227825Stheraven                            " failed to construct for " + name);
673227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
674227825Stheraven}
675227825Stheraven
676227825Stheravencollate_byname<char>::~collate_byname()
677227825Stheraven{
678227825Stheraven    freelocale(__l);
679227825Stheraven}
680227825Stheraven
681227825Stheravenint
682227825Stheravencollate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
683227825Stheraven                                 const char_type* __lo2, const char_type* __hi2) const
684227825Stheraven{
685227825Stheraven    string_type lhs(__lo1, __hi1);
686227825Stheraven    string_type rhs(__lo2, __hi2);
687227825Stheraven    int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
688227825Stheraven    if (r < 0)
689227825Stheraven        return -1;
690227825Stheraven    if (r > 0)
691227825Stheraven        return 1;
692227825Stheraven    return r;
693227825Stheraven}
694227825Stheraven
695227825Stheravencollate_byname<char>::string_type
696227825Stheravencollate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
697227825Stheraven{
698227825Stheraven    const string_type in(lo, hi);
699227825Stheraven    string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
700227825Stheraven    strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
701227825Stheraven    return out;
702227825Stheraven}
703227825Stheraven
704227825Stheraven// template <> class collate_byname<wchar_t>
705227825Stheraven
706227825Stheravencollate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
707227825Stheraven    : collate<wchar_t>(refs),
708227825Stheraven      __l(newlocale(LC_ALL_MASK, n, 0))
709227825Stheraven{
710227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
711227825Stheraven    if (__l == 0)
712227825Stheraven        throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
713227825Stheraven                            " failed to construct for " + string(n));
714227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
715227825Stheraven}
716227825Stheraven
717227825Stheravencollate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
718227825Stheraven    : collate<wchar_t>(refs),
719227825Stheraven      __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
720227825Stheraven{
721227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
722227825Stheraven    if (__l == 0)
723227825Stheraven        throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
724227825Stheraven                            " failed to construct for " + name);
725227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
726227825Stheraven}
727227825Stheraven
728227825Stheravencollate_byname<wchar_t>::~collate_byname()
729227825Stheraven{
730227825Stheraven    freelocale(__l);
731227825Stheraven}
732227825Stheraven
733227825Stheravenint
734227825Stheravencollate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
735227825Stheraven                                 const char_type* __lo2, const char_type* __hi2) const
736227825Stheraven{
737227825Stheraven    string_type lhs(__lo1, __hi1);
738227825Stheraven    string_type rhs(__lo2, __hi2);
739227825Stheraven    int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
740227825Stheraven    if (r < 0)
741227825Stheraven        return -1;
742227825Stheraven    if (r > 0)
743227825Stheraven        return 1;
744227825Stheraven    return r;
745227825Stheraven}
746227825Stheraven
747227825Stheravencollate_byname<wchar_t>::string_type
748227825Stheravencollate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
749227825Stheraven{
750227825Stheraven    const string_type in(lo, hi);
751227825Stheraven    string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
752227825Stheraven    wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
753227825Stheraven    return out;
754227825Stheraven}
755227825Stheraven
756227825Stheraven// template <> class ctype<wchar_t>;
757227825Stheraven
758246487Stheravenconst ctype_base::mask ctype_base::space;
759246487Stheravenconst ctype_base::mask ctype_base::print;
760246487Stheravenconst ctype_base::mask ctype_base::cntrl;
761246487Stheravenconst ctype_base::mask ctype_base::upper;
762246487Stheravenconst ctype_base::mask ctype_base::lower;
763246487Stheravenconst ctype_base::mask ctype_base::alpha;
764246487Stheravenconst ctype_base::mask ctype_base::digit;
765246487Stheravenconst ctype_base::mask ctype_base::punct;
766246487Stheravenconst ctype_base::mask ctype_base::xdigit;
767246487Stheravenconst ctype_base::mask ctype_base::blank;
768246487Stheravenconst ctype_base::mask ctype_base::alnum;
769246487Stheravenconst ctype_base::mask ctype_base::graph;
770246487Stheraven
771227825Stheravenlocale::id ctype<wchar_t>::id;
772227825Stheraven
773227825Stheravenctype<wchar_t>::~ctype()
774227825Stheraven{
775227825Stheraven}
776227825Stheraven
777227825Stheravenbool
778227825Stheravenctype<wchar_t>::do_is(mask m, char_type c) const
779227825Stheraven{
780262801Sdim    return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
781227825Stheraven}
782227825Stheraven
783227825Stheravenconst wchar_t*
784227825Stheravenctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
785227825Stheraven{
786227825Stheraven    for (; low != high; ++low, ++vec)
787227825Stheraven        *vec = static_cast<mask>(isascii(*low) ?
788227825Stheraven                                   ctype<char>::classic_table()[*low] : 0);
789227825Stheraven    return low;
790227825Stheraven}
791227825Stheraven
792227825Stheravenconst wchar_t*
793227825Stheravenctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
794227825Stheraven{
795227825Stheraven    for (; low != high; ++low)
796227825Stheraven        if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
797227825Stheraven            break;
798227825Stheraven    return low;
799227825Stheraven}
800227825Stheraven
801227825Stheravenconst wchar_t*
802227825Stheravenctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
803227825Stheraven{
804227825Stheraven    for (; low != high; ++low)
805227825Stheraven        if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
806227825Stheraven            break;
807227825Stheraven    return low;
808227825Stheraven}
809227825Stheraven
810227825Stheravenwchar_t
811227825Stheravenctype<wchar_t>::do_toupper(char_type c) const
812227825Stheraven{
813227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
814227825Stheraven    return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
815262801Sdim#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
816227825Stheraven    return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
817227825Stheraven#else
818227825Stheraven    return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
819227825Stheraven#endif
820227825Stheraven}
821227825Stheraven
822227825Stheravenconst wchar_t*
823227825Stheravenctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
824227825Stheraven{
825227825Stheraven    for (; low != high; ++low)
826227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
827227825Stheraven        *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
828262801Sdim#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
829227825Stheraven        *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
830227825Stheraven                             : *low;
831227825Stheraven#else
832227825Stheraven        *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
833227825Stheraven#endif
834227825Stheraven    return low;
835227825Stheraven}
836227825Stheraven
837227825Stheravenwchar_t
838227825Stheravenctype<wchar_t>::do_tolower(char_type c) const
839227825Stheraven{
840227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
841227825Stheraven    return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
842262801Sdim#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
843227825Stheraven    return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
844227825Stheraven#else
845227825Stheraven    return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
846227825Stheraven#endif
847227825Stheraven}
848227825Stheraven
849227825Stheravenconst wchar_t*
850227825Stheravenctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
851227825Stheraven{
852227825Stheraven    for (; low != high; ++low)
853227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
854227825Stheraven        *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
855262801Sdim#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
856227825Stheraven        *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
857227825Stheraven                             : *low;
858227825Stheraven#else
859227825Stheraven        *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
860227825Stheraven#endif
861227825Stheraven    return low;
862227825Stheraven}
863227825Stheraven
864227825Stheravenwchar_t
865227825Stheravenctype<wchar_t>::do_widen(char c) const
866227825Stheraven{
867227825Stheraven    return c;
868227825Stheraven}
869227825Stheraven
870227825Stheravenconst char*
871227825Stheravenctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
872227825Stheraven{
873227825Stheraven    for (; low != high; ++low, ++dest)
874227825Stheraven        *dest = *low;
875227825Stheraven    return low;
876227825Stheraven}
877227825Stheraven
878227825Stheravenchar
879227825Stheravenctype<wchar_t>::do_narrow(char_type c, char dfault) const
880227825Stheraven{
881227825Stheraven    if (isascii(c))
882227825Stheraven        return static_cast<char>(c);
883227825Stheraven    return dfault;
884227825Stheraven}
885227825Stheraven
886227825Stheravenconst wchar_t*
887227825Stheravenctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
888227825Stheraven{
889227825Stheraven    for (; low != high; ++low, ++dest)
890227825Stheraven        if (isascii(*low))
891232950Stheraven            *dest = static_cast<char>(*low);
892227825Stheraven        else
893227825Stheraven            *dest = dfault;
894227825Stheraven    return low;
895227825Stheraven}
896227825Stheraven
897227825Stheraven// template <> class ctype<char>;
898227825Stheraven
899227825Stheravenlocale::id ctype<char>::id;
900227825Stheraven
901227825Stheravenctype<char>::ctype(const mask* tab, bool del, size_t refs)
902227825Stheraven    : locale::facet(refs),
903227825Stheraven      __tab_(tab),
904227825Stheraven      __del_(del)
905227825Stheraven{
906227825Stheraven  if (__tab_ == 0)
907227825Stheraven      __tab_ = classic_table();
908227825Stheraven}
909227825Stheraven
910227825Stheravenctype<char>::~ctype()
911227825Stheraven{
912227825Stheraven    if (__tab_ && __del_)
913227825Stheraven        delete [] __tab_;
914227825Stheraven}
915227825Stheraven
916227825Stheravenchar
917227825Stheravenctype<char>::do_toupper(char_type c) const
918227825Stheraven{
919227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
920232950Stheraven    return isascii(c) ?
921232950Stheraven      static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
922253159Stheraven#elif defined(__NetBSD__)
923253159Stheraven    return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
924262801Sdim#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
925249998Sdim    return isascii(c) ?
926253159Stheraven      static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
927227825Stheraven#else
928227825Stheraven    return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
929227825Stheraven#endif
930227825Stheraven}
931227825Stheraven
932227825Stheravenconst char*
933227825Stheravenctype<char>::do_toupper(char_type* low, const char_type* high) const
934227825Stheraven{
935227825Stheraven    for (; low != high; ++low)
936227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
937232950Stheraven        *low = isascii(*low) ?
938232950Stheraven          static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
939253159Stheraven#elif defined(__NetBSD__)
940253159Stheraven        *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
941262801Sdim#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
942249998Sdim        *low = isascii(*low) ?
943249998Sdim          static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
944227825Stheraven#else
945227825Stheraven        *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
946227825Stheraven#endif
947227825Stheraven    return low;
948227825Stheraven}
949227825Stheraven
950227825Stheravenchar
951227825Stheravenctype<char>::do_tolower(char_type c) const
952227825Stheraven{
953227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
954232950Stheraven    return isascii(c) ?
955232950Stheraven      static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
956253159Stheraven#elif defined(__NetBSD__)
957253159Stheraven    return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
958262801Sdim#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
959249998Sdim    return isascii(c) ?
960249998Sdim      static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
961227825Stheraven#else
962227825Stheraven    return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
963227825Stheraven#endif
964227825Stheraven}
965227825Stheraven
966227825Stheravenconst char*
967227825Stheravenctype<char>::do_tolower(char_type* low, const char_type* high) const
968227825Stheraven{
969227825Stheraven    for (; low != high; ++low)
970227825Stheraven#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
971232950Stheraven        *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
972253159Stheraven#elif defined(__NetBSD__)
973253159Stheraven        *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
974262801Sdim#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
975249998Sdim        *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
976227825Stheraven#else
977227825Stheraven        *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
978227825Stheraven#endif
979227825Stheraven    return low;
980227825Stheraven}
981227825Stheraven
982227825Stheravenchar
983227825Stheravenctype<char>::do_widen(char c) const
984227825Stheraven{
985227825Stheraven    return c;
986227825Stheraven}
987227825Stheraven
988227825Stheravenconst char*
989227825Stheravenctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
990227825Stheraven{
991227825Stheraven    for (; low != high; ++low, ++dest)
992227825Stheraven        *dest = *low;
993227825Stheraven    return low;
994227825Stheraven}
995227825Stheraven
996227825Stheravenchar
997227825Stheravenctype<char>::do_narrow(char_type c, char dfault) const
998227825Stheraven{
999227825Stheraven    if (isascii(c))
1000227825Stheraven        return static_cast<char>(c);
1001227825Stheraven    return dfault;
1002227825Stheraven}
1003227825Stheraven
1004227825Stheravenconst char*
1005227825Stheravenctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1006227825Stheraven{
1007227825Stheraven    for (; low != high; ++low, ++dest)
1008227825Stheraven        if (isascii(*low))
1009227825Stheraven            *dest = *low;
1010227825Stheraven        else
1011227825Stheraven            *dest = dfault;
1012227825Stheraven    return low;
1013227825Stheraven}
1014227825Stheraven
1015262801Sdim#ifdef __EMSCRIPTEN__
1016249998Sdimextern "C" const unsigned short ** __ctype_b_loc();
1017249998Sdimextern "C" const int ** __ctype_tolower_loc();
1018249998Sdimextern "C" const int ** __ctype_toupper_loc();
1019249998Sdim#endif
1020249998Sdim
1021227825Stheravenconst ctype<char>::mask*
1022227825Stheravenctype<char>::classic_table()  _NOEXCEPT
1023227825Stheraven{
1024227825Stheraven#if defined(__APPLE__) || defined(__FreeBSD__)
1025227825Stheraven    return _DefaultRuneLocale.__runetype;
1026253159Stheraven#elif defined(__NetBSD__)
1027253159Stheraven    return _C_ctype_tab_ + 1;
1028227825Stheraven#elif defined(__GLIBC__)
1029227825Stheraven    return __cloc()->__ctype_b;
1030232950Stheraven#elif __sun__
1031232950Stheraven    return __ctype_mask;
1032262801Sdim#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
1033227825Stheraven    return _ctype+1; // internal ctype mask table defined in msvcrt.dll
1034227825Stheraven// This is assumed to be safe, which is a nonsense assumption because we're
1035227825Stheraven// going to end up dereferencing it later...
1036262801Sdim#elif defined(__EMSCRIPTEN__)
1037249998Sdim    return *__ctype_b_loc();
1038262801Sdim#elif defined(_AIX)
1039262801Sdim    return (const unsigned long *)__lc_ctype_ptr->obj->mask;
1040227825Stheraven#else
1041232950Stheraven    // Platform not supported: abort so the person doing the port knows what to
1042232950Stheraven    // fix
1043232950Stheraven# warning  ctype<char>::classic_table() is not implemented
1044262801Sdim    printf("ctype<char>::classic_table() is not implemented\n");
1045232950Stheraven    abort();
1046227825Stheraven    return NULL;
1047227825Stheraven#endif
1048227825Stheraven}
1049227825Stheraven
1050227825Stheraven#if defined(__GLIBC__)
1051227825Stheravenconst int*
1052227825Stheravenctype<char>::__classic_lower_table() _NOEXCEPT
1053227825Stheraven{
1054227825Stheraven    return __cloc()->__ctype_tolower;
1055227825Stheraven}
1056227825Stheraven
1057227825Stheravenconst int*
1058227825Stheravenctype<char>::__classic_upper_table() _NOEXCEPT
1059227825Stheraven{
1060227825Stheraven    return __cloc()->__ctype_toupper;
1061227825Stheraven}
1062253159Stheraven#elif __NetBSD__
1063253159Stheravenconst short*
1064253159Stheravenctype<char>::__classic_lower_table() _NOEXCEPT
1065253159Stheraven{
1066253159Stheraven    return _C_tolower_tab_ + 1;
1067253159Stheraven}
1068227825Stheraven
1069253159Stheravenconst short*
1070253159Stheravenctype<char>::__classic_upper_table() _NOEXCEPT
1071253159Stheraven{
1072253159Stheraven    return _C_toupper_tab_ + 1;
1073253159Stheraven}
1074253159Stheraven
1075262801Sdim#elif defined(__EMSCRIPTEN__)
1076249998Sdimconst int*
1077249998Sdimctype<char>::__classic_lower_table() _NOEXCEPT
1078249998Sdim{
1079249998Sdim    return *__ctype_tolower_loc();
1080249998Sdim}
1081249998Sdim
1082249998Sdimconst int*
1083249998Sdimctype<char>::__classic_upper_table() _NOEXCEPT
1084249998Sdim{
1085249998Sdim    return *__ctype_toupper_loc();
1086249998Sdim}
1087262801Sdim#endif // __GLIBC__ || __EMSCRIPTEN__ || __NETBSD__
1088249998Sdim
1089227825Stheraven// template <> class ctype_byname<char>
1090227825Stheraven
1091227825Stheravenctype_byname<char>::ctype_byname(const char* name, size_t refs)
1092227825Stheraven    : ctype<char>(0, false, refs),
1093227825Stheraven      __l(newlocale(LC_ALL_MASK, name, 0))
1094227825Stheraven{
1095227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1096227825Stheraven    if (__l == 0)
1097227825Stheraven        throw runtime_error("ctype_byname<char>::ctype_byname"
1098227825Stheraven                            " failed to construct for " + string(name));
1099227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1100227825Stheraven}
1101227825Stheraven
1102227825Stheravenctype_byname<char>::ctype_byname(const string& name, size_t refs)
1103227825Stheraven    : ctype<char>(0, false, refs),
1104227825Stheraven      __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1105227825Stheraven{
1106227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1107227825Stheraven    if (__l == 0)
1108227825Stheraven        throw runtime_error("ctype_byname<char>::ctype_byname"
1109227825Stheraven                            " failed to construct for " + name);
1110227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1111227825Stheraven}
1112227825Stheraven
1113227825Stheravenctype_byname<char>::~ctype_byname()
1114227825Stheraven{
1115227825Stheraven    freelocale(__l);
1116227825Stheraven}
1117227825Stheraven
1118227825Stheravenchar
1119227825Stheravenctype_byname<char>::do_toupper(char_type c) const
1120227825Stheraven{
1121253159Stheraven    return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
1122227825Stheraven}
1123227825Stheraven
1124227825Stheravenconst char*
1125227825Stheravenctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1126227825Stheraven{
1127227825Stheraven    for (; low != high; ++low)
1128253159Stheraven        *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
1129227825Stheraven    return low;
1130227825Stheraven}
1131227825Stheraven
1132227825Stheravenchar
1133227825Stheravenctype_byname<char>::do_tolower(char_type c) const
1134227825Stheraven{
1135253159Stheraven    return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
1136227825Stheraven}
1137227825Stheraven
1138227825Stheravenconst char*
1139227825Stheravenctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1140227825Stheraven{
1141227825Stheraven    for (; low != high; ++low)
1142253159Stheraven        *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
1143227825Stheraven    return low;
1144227825Stheraven}
1145227825Stheraven
1146227825Stheraven// template <> class ctype_byname<wchar_t>
1147227825Stheraven
1148227825Stheravenctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1149227825Stheraven    : ctype<wchar_t>(refs),
1150227825Stheraven      __l(newlocale(LC_ALL_MASK, name, 0))
1151227825Stheraven{
1152227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1153227825Stheraven    if (__l == 0)
1154227825Stheraven        throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1155227825Stheraven                            " failed to construct for " + string(name));
1156227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1157227825Stheraven}
1158227825Stheraven
1159227825Stheravenctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1160227825Stheraven    : ctype<wchar_t>(refs),
1161227825Stheraven      __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1162227825Stheraven{
1163227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1164227825Stheraven    if (__l == 0)
1165227825Stheraven        throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1166227825Stheraven                            " failed to construct for " + name);
1167227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1168227825Stheraven}
1169227825Stheraven
1170227825Stheravenctype_byname<wchar_t>::~ctype_byname()
1171227825Stheraven{
1172227825Stheraven    freelocale(__l);
1173227825Stheraven}
1174227825Stheraven
1175227825Stheravenbool
1176227825Stheravenctype_byname<wchar_t>::do_is(mask m, char_type c) const
1177227825Stheraven{
1178227825Stheraven#ifdef _LIBCPP_WCTYPE_IS_MASK
1179227825Stheraven    return static_cast<bool>(iswctype_l(c, m, __l));
1180227825Stheraven#else
1181241903Sdim    bool result = false;
1182249998Sdim    wint_t ch = static_cast<wint_t>(c);
1183249998Sdim    if (m & space) result |= (iswspace_l(ch, __l) != 0);
1184249998Sdim    if (m & print) result |= (iswprint_l(ch, __l) != 0);
1185249998Sdim    if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1186249998Sdim    if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1187249998Sdim    if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1188249998Sdim    if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1189249998Sdim    if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1190249998Sdim    if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1191249998Sdim    if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1192249998Sdim    if (m & blank) result |= (iswblank_l(ch, __l) != 0);
1193227825Stheraven    return result;
1194227825Stheraven#endif
1195227825Stheraven}
1196227825Stheraven
1197227825Stheravenconst wchar_t*
1198227825Stheravenctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1199227825Stheraven{
1200227825Stheraven    for (; low != high; ++low, ++vec)
1201227825Stheraven    {
1202227825Stheraven        if (isascii(*low))
1203227825Stheraven            *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
1204227825Stheraven        else
1205227825Stheraven        {
1206227825Stheraven            *vec = 0;
1207249998Sdim            wint_t ch = static_cast<wint_t>(*low);
1208249998Sdim            if (iswspace_l(ch, __l))
1209227825Stheraven                *vec |= space;
1210249998Sdim            if (iswprint_l(ch, __l))
1211227825Stheraven                *vec |= print;
1212249998Sdim            if (iswcntrl_l(ch, __l))
1213227825Stheraven                *vec |= cntrl;
1214249998Sdim            if (iswupper_l(ch, __l))
1215227825Stheraven                *vec |= upper;
1216249998Sdim            if (iswlower_l(ch, __l))
1217227825Stheraven                *vec |= lower;
1218249998Sdim            if (iswalpha_l(ch, __l))
1219227825Stheraven                *vec |= alpha;
1220249998Sdim            if (iswdigit_l(ch, __l))
1221227825Stheraven                *vec |= digit;
1222249998Sdim            if (iswpunct_l(ch, __l))
1223227825Stheraven                *vec |= punct;
1224249998Sdim            if (iswxdigit_l(ch, __l))
1225227825Stheraven                *vec |= xdigit;
1226227825Stheraven        }
1227227825Stheraven    }
1228227825Stheraven    return low;
1229227825Stheraven}
1230227825Stheraven
1231227825Stheravenconst wchar_t*
1232227825Stheravenctype_byname<wchar_t>::do_scan_is(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)) break;
1242249998Sdim        if (m & print && iswprint_l(ch, __l)) break;
1243249998Sdim        if (m & cntrl && iswcntrl_l(ch, __l)) break;
1244249998Sdim        if (m & upper && iswupper_l(ch, __l)) break;
1245249998Sdim        if (m & lower && iswlower_l(ch, __l)) break;
1246249998Sdim        if (m & alpha && iswalpha_l(ch, __l)) break;
1247249998Sdim        if (m & digit && iswdigit_l(ch, __l)) break;
1248249998Sdim        if (m & punct && iswpunct_l(ch, __l)) break;
1249249998Sdim        if (m & xdigit && iswxdigit_l(ch, __l)) break;
1250249998Sdim        if (m & blank && iswblank_l(ch, __l)) break;
1251227825Stheraven#endif
1252227825Stheraven    }
1253227825Stheraven    return low;
1254227825Stheraven}
1255227825Stheraven
1256227825Stheravenconst wchar_t*
1257227825Stheravenctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1258227825Stheraven{
1259227825Stheraven    for (; low != high; ++low)
1260227825Stheraven    {
1261227825Stheraven#ifdef _LIBCPP_WCTYPE_IS_MASK
1262227825Stheraven        if (!iswctype_l(*low, m, __l))
1263227825Stheraven            break;
1264227825Stheraven#else
1265249998Sdim        wint_t ch = static_cast<wint_t>(*low);
1266249998Sdim        if (m & space && iswspace_l(ch, __l)) continue;
1267249998Sdim        if (m & print && iswprint_l(ch, __l)) continue;
1268249998Sdim        if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1269249998Sdim        if (m & upper && iswupper_l(ch, __l)) continue;
1270249998Sdim        if (m & lower && iswlower_l(ch, __l)) continue;
1271249998Sdim        if (m & alpha && iswalpha_l(ch, __l)) continue;
1272249998Sdim        if (m & digit && iswdigit_l(ch, __l)) continue;
1273249998Sdim        if (m & punct && iswpunct_l(ch, __l)) continue;
1274249998Sdim        if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1275249998Sdim        if (m & blank && iswblank_l(ch, __l)) continue;
1276227825Stheraven        break;
1277227825Stheraven#endif
1278227825Stheraven    }
1279227825Stheraven    return low;
1280227825Stheraven}
1281227825Stheraven
1282227825Stheravenwchar_t
1283227825Stheravenctype_byname<wchar_t>::do_toupper(char_type c) const
1284227825Stheraven{
1285227825Stheraven    return towupper_l(c, __l);
1286227825Stheraven}
1287227825Stheraven
1288227825Stheravenconst wchar_t*
1289227825Stheravenctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1290227825Stheraven{
1291227825Stheraven    for (; low != high; ++low)
1292227825Stheraven        *low = towupper_l(*low, __l);
1293227825Stheraven    return low;
1294227825Stheraven}
1295227825Stheraven
1296227825Stheravenwchar_t
1297227825Stheravenctype_byname<wchar_t>::do_tolower(char_type c) const
1298227825Stheraven{
1299227825Stheraven    return towlower_l(c, __l);
1300227825Stheraven}
1301227825Stheraven
1302227825Stheravenconst wchar_t*
1303227825Stheravenctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1304227825Stheraven{
1305227825Stheraven    for (; low != high; ++low)
1306227825Stheraven        *low = towlower_l(*low, __l);
1307227825Stheraven    return low;
1308227825Stheraven}
1309227825Stheraven
1310227825Stheravenwchar_t
1311227825Stheravenctype_byname<wchar_t>::do_widen(char c) const
1312227825Stheraven{
1313227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1314227825Stheraven    return btowc_l(c, __l);
1315227825Stheraven#else
1316227825Stheraven    return __btowc_l(c, __l);
1317227825Stheraven#endif
1318227825Stheraven}
1319227825Stheraven
1320227825Stheravenconst char*
1321227825Stheravenctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1322227825Stheraven{
1323227825Stheraven    for (; low != high; ++low, ++dest)
1324227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1325227825Stheraven        *dest = btowc_l(*low, __l);
1326227825Stheraven#else
1327227825Stheraven        *dest = __btowc_l(*low, __l);
1328227825Stheraven#endif
1329227825Stheraven    return low;
1330227825Stheraven}
1331227825Stheraven
1332227825Stheravenchar
1333227825Stheravenctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1334227825Stheraven{
1335227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1336227825Stheraven    int r = wctob_l(c, __l);
1337227825Stheraven#else
1338227825Stheraven    int r = __wctob_l(c, __l);
1339227825Stheraven#endif
1340246487Stheraven    return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
1341227825Stheraven}
1342227825Stheraven
1343227825Stheravenconst wchar_t*
1344227825Stheravenctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1345227825Stheraven{
1346227825Stheraven    for (; low != high; ++low, ++dest)
1347227825Stheraven    {
1348227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1349227825Stheraven        int r = wctob_l(*low, __l);
1350227825Stheraven#else
1351227825Stheraven        int r = __wctob_l(*low, __l);
1352227825Stheraven#endif
1353246487Stheraven        *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
1354227825Stheraven    }
1355227825Stheraven    return low;
1356227825Stheraven}
1357227825Stheraven
1358227825Stheraven// template <> class codecvt<char, char, mbstate_t>
1359227825Stheraven
1360227825Stheravenlocale::id codecvt<char, char, mbstate_t>::id;
1361227825Stheraven
1362227825Stheravencodecvt<char, char, mbstate_t>::~codecvt()
1363227825Stheraven{
1364227825Stheraven}
1365227825Stheraven
1366227825Stheravencodecvt<char, char, mbstate_t>::result
1367227825Stheravencodecvt<char, char, mbstate_t>::do_out(state_type&,
1368227825Stheraven    const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
1369227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
1370227825Stheraven{
1371227825Stheraven    frm_nxt = frm;
1372227825Stheraven    to_nxt = to;
1373227825Stheraven    return noconv;
1374227825Stheraven}
1375227825Stheraven
1376227825Stheravencodecvt<char, char, mbstate_t>::result
1377227825Stheravencodecvt<char, char, mbstate_t>::do_in(state_type&,
1378227825Stheraven    const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
1379227825Stheraven    intern_type* to, intern_type*, intern_type*& to_nxt) const
1380227825Stheraven{
1381227825Stheraven    frm_nxt = frm;
1382227825Stheraven    to_nxt = to;
1383227825Stheraven    return noconv;
1384227825Stheraven}
1385227825Stheraven
1386227825Stheravencodecvt<char, char, mbstate_t>::result
1387227825Stheravencodecvt<char, char, mbstate_t>::do_unshift(state_type&,
1388227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
1389227825Stheraven{
1390227825Stheraven    to_nxt = to;
1391227825Stheraven    return noconv;
1392227825Stheraven}
1393227825Stheraven
1394227825Stheravenint
1395227825Stheravencodecvt<char, char, mbstate_t>::do_encoding() const  _NOEXCEPT
1396227825Stheraven{
1397227825Stheraven    return 1;
1398227825Stheraven}
1399227825Stheraven
1400227825Stheravenbool
1401227825Stheravencodecvt<char, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
1402227825Stheraven{
1403227825Stheraven    return true;
1404227825Stheraven}
1405227825Stheraven
1406227825Stheravenint
1407227825Stheravencodecvt<char, char, mbstate_t>::do_length(state_type&,
1408227825Stheraven    const extern_type* frm, const extern_type* end, size_t mx) const
1409227825Stheraven{
1410232950Stheraven    return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
1411227825Stheraven}
1412227825Stheraven
1413227825Stheravenint
1414227825Stheravencodecvt<char, char, mbstate_t>::do_max_length() const  _NOEXCEPT
1415227825Stheraven{
1416227825Stheraven    return 1;
1417227825Stheraven}
1418227825Stheraven
1419227825Stheraven// template <> class codecvt<wchar_t, char, mbstate_t>
1420227825Stheraven
1421227825Stheravenlocale::id codecvt<wchar_t, char, mbstate_t>::id;
1422227825Stheraven
1423227825Stheravencodecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1424227825Stheraven    : locale::facet(refs),
1425253159Stheraven      __l(_LIBCPP_GET_C_LOCALE)
1426227825Stheraven{
1427227825Stheraven}
1428227825Stheraven
1429227825Stheravencodecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1430227825Stheraven    : locale::facet(refs),
1431227825Stheraven      __l(newlocale(LC_ALL_MASK, nm, 0))
1432227825Stheraven{
1433227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
1434227825Stheraven    if (__l == 0)
1435227825Stheraven        throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1436227825Stheraven                            " failed to construct for " + string(nm));
1437227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
1438227825Stheraven}
1439227825Stheraven
1440227825Stheravencodecvt<wchar_t, char, mbstate_t>::~codecvt()
1441227825Stheraven{
1442253159Stheraven    if (__l != _LIBCPP_GET_C_LOCALE)
1443227825Stheraven        freelocale(__l);
1444227825Stheraven}
1445227825Stheraven
1446227825Stheravencodecvt<wchar_t, char, mbstate_t>::result
1447227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
1448227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1449227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1450227825Stheraven{
1451227825Stheraven    // look for first internal null in frm
1452227825Stheraven    const intern_type* fend = frm;
1453227825Stheraven    for (; fend != frm_end; ++fend)
1454227825Stheraven        if (*fend == 0)
1455227825Stheraven            break;
1456227825Stheraven    // loop over all null-terminated sequences in frm
1457227825Stheraven    to_nxt = to;
1458227825Stheraven    for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1459227825Stheraven    {
1460249998Sdim        // save state in case it is needed to recover to_nxt on error
1461227825Stheraven        mbstate_t save_state = st;
1462227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1463232950Stheraven        size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1464232950Stheraven                                static_cast<size_t>(to_end-to), &st, __l);
1465227825Stheraven#else
1466227825Stheraven        size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1467227825Stheraven#endif
1468227825Stheraven        if (n == size_t(-1))
1469227825Stheraven        {
1470227825Stheraven            // need to recover to_nxt
1471227825Stheraven            for (to_nxt = to; frm != frm_nxt; ++frm)
1472227825Stheraven            {
1473227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1474227825Stheraven                n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1475227825Stheraven#else
1476227825Stheraven                n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1477227825Stheraven#endif
1478227825Stheraven                if (n == size_t(-1))
1479227825Stheraven                    break;
1480227825Stheraven                to_nxt += n;
1481227825Stheraven            }
1482227825Stheraven            frm_nxt = frm;
1483227825Stheraven            return error;
1484227825Stheraven        }
1485227825Stheraven        if (n == 0)
1486227825Stheraven            return partial;
1487227825Stheraven        to_nxt += n;
1488227825Stheraven        if (to_nxt == to_end)
1489227825Stheraven            break;
1490227825Stheraven        if (fend != frm_end)  // set up next null terminated sequence
1491227825Stheraven        {
1492227825Stheraven            // Try to write the terminating null
1493227825Stheraven            extern_type tmp[MB_LEN_MAX];
1494227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1495227825Stheraven            n = wcrtomb_l(tmp, intern_type(), &st, __l);
1496227825Stheraven#else
1497227825Stheraven            n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1498227825Stheraven#endif
1499227825Stheraven            if (n == size_t(-1))  // on error
1500227825Stheraven                return error;
1501232950Stheraven            if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
1502227825Stheraven                return partial;
1503227825Stheraven            for (extern_type* p = tmp; n; --n)  // write it
1504227825Stheraven                *to_nxt++ = *p++;
1505227825Stheraven            ++frm_nxt;
1506227825Stheraven            // look for next null in frm
1507227825Stheraven            for (fend = frm_nxt; fend != frm_end; ++fend)
1508227825Stheraven                if (*fend == 0)
1509227825Stheraven                    break;
1510227825Stheraven        }
1511227825Stheraven    }
1512227825Stheraven    return frm_nxt == frm_end ? ok : partial;
1513227825Stheraven}
1514227825Stheraven
1515227825Stheravencodecvt<wchar_t, char, mbstate_t>::result
1516227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
1517227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1518227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1519227825Stheraven{
1520227825Stheraven    // look for first internal null in frm
1521227825Stheraven    const extern_type* fend = frm;
1522227825Stheraven    for (; fend != frm_end; ++fend)
1523227825Stheraven        if (*fend == 0)
1524227825Stheraven            break;
1525227825Stheraven    // loop over all null-terminated sequences in frm
1526227825Stheraven    to_nxt = to;
1527227825Stheraven    for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1528227825Stheraven    {
1529249998Sdim        // save state in case it is needed to recover to_nxt on error
1530227825Stheraven        mbstate_t save_state = st;
1531227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1532232950Stheraven        size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1533232950Stheraven                                static_cast<size_t>(to_end-to), &st, __l);
1534227825Stheraven#else
1535227825Stheraven        size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1536227825Stheraven#endif
1537227825Stheraven        if (n == size_t(-1))
1538227825Stheraven        {
1539227825Stheraven            // need to recover to_nxt
1540227825Stheraven            for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1541227825Stheraven            {
1542227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1543232950Stheraven                n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1544232950Stheraven                              &save_state, __l);
1545227825Stheraven#else
1546227825Stheraven                n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1547227825Stheraven#endif
1548227825Stheraven                switch (n)
1549227825Stheraven                {
1550227825Stheraven                case 0:
1551227825Stheraven                    ++frm;
1552227825Stheraven                    break;
1553232950Stheraven                case size_t(-1):
1554227825Stheraven                    frm_nxt = frm;
1555227825Stheraven                    return error;
1556232950Stheraven                case size_t(-2):
1557227825Stheraven                    frm_nxt = frm;
1558227825Stheraven                    return partial;
1559227825Stheraven                default:
1560227825Stheraven                    frm += n;
1561227825Stheraven                    break;
1562227825Stheraven                }
1563227825Stheraven            }
1564227825Stheraven            frm_nxt = frm;
1565227825Stheraven            return frm_nxt == frm_end ? ok : partial;
1566227825Stheraven        }
1567227825Stheraven        if (n == 0)
1568227825Stheraven            return error;
1569227825Stheraven        to_nxt += n;
1570227825Stheraven        if (to_nxt == to_end)
1571227825Stheraven            break;
1572227825Stheraven        if (fend != frm_end)  // set up next null terminated sequence
1573227825Stheraven        {
1574227825Stheraven            // Try to write the terminating null
1575227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1576227825Stheraven            n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1577227825Stheraven#else
1578227825Stheraven            n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1579227825Stheraven#endif
1580227825Stheraven            if (n != 0)  // on error
1581227825Stheraven                return error;
1582227825Stheraven            ++to_nxt;
1583227825Stheraven            ++frm_nxt;
1584227825Stheraven            // look for next null in frm
1585227825Stheraven            for (fend = frm_nxt; fend != frm_end; ++fend)
1586227825Stheraven                if (*fend == 0)
1587227825Stheraven                    break;
1588227825Stheraven        }
1589227825Stheraven    }
1590227825Stheraven    return frm_nxt == frm_end ? ok : partial;
1591227825Stheraven}
1592227825Stheraven
1593227825Stheravencodecvt<wchar_t, char, mbstate_t>::result
1594227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1595227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1596227825Stheraven{
1597227825Stheraven    to_nxt = to;
1598227825Stheraven    extern_type tmp[MB_LEN_MAX];
1599227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1600227825Stheraven    size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1601227825Stheraven#else
1602227825Stheraven    size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1603227825Stheraven#endif
1604227825Stheraven    if (n == size_t(-1) || n == 0)  // on error
1605227825Stheraven        return error;
1606227825Stheraven    --n;
1607232950Stheraven    if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
1608227825Stheraven        return partial;
1609227825Stheraven    for (extern_type* p = tmp; n; --n)  // write it
1610227825Stheraven        *to_nxt++ = *p++;
1611227825Stheraven    return ok;
1612227825Stheraven}
1613227825Stheraven
1614227825Stheravenint
1615227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
1616227825Stheraven{
1617227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1618227825Stheraven    if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1619227825Stheraven#else
1620227825Stheraven    if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1621227825Stheraven#endif
1622227825Stheraven    {
1623227825Stheraven        // stateless encoding
1624227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1625227825Stheraven        if (__l == 0 || MB_CUR_MAX_L(__l) == 1)  // there are no known constant length encodings
1626227825Stheraven#else
1627227825Stheraven        if (__l == 0 || __mb_cur_max_l(__l) == 1)  // there are no known constant length encodings
1628227825Stheraven#endif
1629227825Stheraven            return 1;                // which take more than 1 char to form a wchar_t
1630227825Stheraven         return 0;
1631227825Stheraven    }
1632227825Stheraven    return -1;
1633227825Stheraven}
1634227825Stheraven
1635227825Stheravenbool
1636227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
1637227825Stheraven{
1638227825Stheraven    return false;
1639227825Stheraven}
1640227825Stheraven
1641227825Stheravenint
1642227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1643227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
1644227825Stheraven{
1645227825Stheraven    int nbytes = 0;
1646227825Stheraven    for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1647227825Stheraven    {
1648227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1649232950Stheraven        size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
1650227825Stheraven#else
1651227825Stheraven        size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1652227825Stheraven#endif
1653227825Stheraven        switch (n)
1654227825Stheraven        {
1655227825Stheraven        case 0:
1656227825Stheraven            ++nbytes;
1657227825Stheraven            ++frm;
1658227825Stheraven            break;
1659232950Stheraven        case size_t(-1):
1660232950Stheraven        case size_t(-2):
1661227825Stheraven            return nbytes;
1662227825Stheraven        default:
1663227825Stheraven            nbytes += n;
1664227825Stheraven            frm += n;
1665227825Stheraven            break;
1666227825Stheraven        }
1667227825Stheraven    }
1668227825Stheraven    return nbytes;
1669227825Stheraven}
1670227825Stheraven
1671227825Stheravenint
1672227825Stheravencodecvt<wchar_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
1673227825Stheraven{
1674227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1675249998Sdim    return __l == 0 ? 1 : static_cast<int>(  MB_CUR_MAX_L(__l));
1676227825Stheraven#else
1677249998Sdim    return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
1678227825Stheraven#endif
1679227825Stheraven}
1680227825Stheraven
1681227825Stheraven//                                     Valid UTF ranges
1682227825Stheraven//     UTF-32               UTF-16                          UTF-8               # of code points
1683227825Stheraven//                     first      second       first   second    third   fourth
1684227825Stheraven// 000000 - 00007F  0000 - 007F               00 - 7F                                 127
1685227825Stheraven// 000080 - 0007FF  0080 - 07FF               C2 - DF, 80 - BF                       1920
1686227825Stheraven// 000800 - 000FFF  0800 - 0FFF               E0 - E0, A0 - BF, 80 - BF              2048
1687227825Stheraven// 001000 - 00CFFF  1000 - CFFF               E1 - EC, 80 - BF, 80 - BF             49152
1688227825Stheraven// 00D000 - 00D7FF  D000 - D7FF               ED - ED, 80 - 9F, 80 - BF              2048
1689227825Stheraven// 00D800 - 00DFFF                invalid
1690227825Stheraven// 00E000 - 00FFFF  E000 - FFFF               EE - EF, 80 - BF, 80 - BF              8192
1691227825Stheraven// 010000 - 03FFFF  D800 - D8BF, DC00 - DFFF  F0 - F0, 90 - BF, 80 - BF, 80 - BF   196608
1692227825Stheraven// 040000 - 0FFFFF  D8C0 - DBBF, DC00 - DFFF  F1 - F3, 80 - BF, 80 - BF, 80 - BF   786432
1693227825Stheraven// 100000 - 10FFFF  DBC0 - DBFF, DC00 - DFFF  F4 - F4, 80 - 8F, 80 - BF, 80 - BF    65536
1694227825Stheraven
1695227825Stheravenstatic
1696227825Stheravencodecvt_base::result
1697227825Stheravenutf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1698227825Stheraven              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1699227825Stheraven              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1700227825Stheraven{
1701227825Stheraven    frm_nxt = frm;
1702227825Stheraven    to_nxt = to;
1703227825Stheraven    if (mode & generate_header)
1704227825Stheraven    {
1705227825Stheraven        if (to_end-to_nxt < 3)
1706227825Stheraven            return codecvt_base::partial;
1707227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xEF);
1708227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBB);
1709227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBF);
1710227825Stheraven    }
1711227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
1712227825Stheraven    {
1713227825Stheraven        uint16_t wc1 = *frm_nxt;
1714227825Stheraven        if (wc1 > Maxcode)
1715227825Stheraven            return codecvt_base::error;
1716227825Stheraven        if (wc1 < 0x0080)
1717227825Stheraven        {
1718227825Stheraven            if (to_end-to_nxt < 1)
1719227825Stheraven                return codecvt_base::partial;
1720227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc1);
1721227825Stheraven        }
1722227825Stheraven        else if (wc1 < 0x0800)
1723227825Stheraven        {
1724227825Stheraven            if (to_end-to_nxt < 2)
1725227825Stheraven                return codecvt_base::partial;
1726227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1727227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1728227825Stheraven        }
1729227825Stheraven        else if (wc1 < 0xD800)
1730227825Stheraven        {
1731227825Stheraven            if (to_end-to_nxt < 3)
1732227825Stheraven                return codecvt_base::partial;
1733227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1734227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1735227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1736227825Stheraven        }
1737227825Stheraven        else if (wc1 < 0xDC00)
1738227825Stheraven        {
1739227825Stheraven            if (frm_end-frm_nxt < 2)
1740227825Stheraven                return codecvt_base::partial;
1741227825Stheraven            uint16_t wc2 = frm_nxt[1];
1742227825Stheraven            if ((wc2 & 0xFC00) != 0xDC00)
1743227825Stheraven                return codecvt_base::error;
1744227825Stheraven            if (to_end-to_nxt < 4)
1745227825Stheraven                return codecvt_base::partial;
1746227825Stheraven            if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1747227825Stheraven                (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1748227825Stheraven                return codecvt_base::error;
1749227825Stheraven            ++frm_nxt;
1750227825Stheraven            uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1751227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1752227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
1753227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1754227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
1755227825Stheraven        }
1756227825Stheraven        else if (wc1 < 0xE000)
1757227825Stheraven        {
1758227825Stheraven            return codecvt_base::error;
1759227825Stheraven        }
1760227825Stheraven        else
1761227825Stheraven        {
1762227825Stheraven            if (to_end-to_nxt < 3)
1763227825Stheraven                return codecvt_base::partial;
1764227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1765227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1766227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1767227825Stheraven        }
1768227825Stheraven    }
1769227825Stheraven    return codecvt_base::ok;
1770227825Stheraven}
1771227825Stheraven
1772227825Stheravenstatic
1773227825Stheravencodecvt_base::result
1774227825Stheravenutf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1775227825Stheraven              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1776227825Stheraven              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1777227825Stheraven{
1778227825Stheraven    frm_nxt = frm;
1779227825Stheraven    to_nxt = to;
1780227825Stheraven    if (mode & generate_header)
1781227825Stheraven    {
1782227825Stheraven        if (to_end-to_nxt < 3)
1783227825Stheraven            return codecvt_base::partial;
1784227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xEF);
1785227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBB);
1786227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBF);
1787227825Stheraven    }
1788227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
1789227825Stheraven    {
1790227825Stheraven        uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1791227825Stheraven        if (wc1 > Maxcode)
1792227825Stheraven            return codecvt_base::error;
1793227825Stheraven        if (wc1 < 0x0080)
1794227825Stheraven        {
1795227825Stheraven            if (to_end-to_nxt < 1)
1796227825Stheraven                return codecvt_base::partial;
1797227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc1);
1798227825Stheraven        }
1799227825Stheraven        else if (wc1 < 0x0800)
1800227825Stheraven        {
1801227825Stheraven            if (to_end-to_nxt < 2)
1802227825Stheraven                return codecvt_base::partial;
1803227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1804227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1805227825Stheraven        }
1806227825Stheraven        else if (wc1 < 0xD800)
1807227825Stheraven        {
1808227825Stheraven            if (to_end-to_nxt < 3)
1809227825Stheraven                return codecvt_base::partial;
1810227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1811227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1812227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1813227825Stheraven        }
1814227825Stheraven        else if (wc1 < 0xDC00)
1815227825Stheraven        {
1816227825Stheraven            if (frm_end-frm_nxt < 2)
1817227825Stheraven                return codecvt_base::partial;
1818227825Stheraven            uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1819227825Stheraven            if ((wc2 & 0xFC00) != 0xDC00)
1820227825Stheraven                return codecvt_base::error;
1821227825Stheraven            if (to_end-to_nxt < 4)
1822227825Stheraven                return codecvt_base::partial;
1823227825Stheraven            if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1824227825Stheraven                (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1825227825Stheraven                return codecvt_base::error;
1826227825Stheraven            ++frm_nxt;
1827227825Stheraven            uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1828227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1829227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
1830227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1831227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
1832227825Stheraven        }
1833227825Stheraven        else if (wc1 < 0xE000)
1834227825Stheraven        {
1835227825Stheraven            return codecvt_base::error;
1836227825Stheraven        }
1837227825Stheraven        else
1838227825Stheraven        {
1839227825Stheraven            if (to_end-to_nxt < 3)
1840227825Stheraven                return codecvt_base::partial;
1841227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1842227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1843227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1844227825Stheraven        }
1845227825Stheraven    }
1846227825Stheraven    return codecvt_base::ok;
1847227825Stheraven}
1848227825Stheraven
1849227825Stheravenstatic
1850227825Stheravencodecvt_base::result
1851227825Stheravenutf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1852227825Stheraven              uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1853227825Stheraven              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1854227825Stheraven{
1855227825Stheraven    frm_nxt = frm;
1856227825Stheraven    to_nxt = to;
1857227825Stheraven    if (mode & consume_header)
1858227825Stheraven    {
1859227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1860227825Stheraven                                                          frm_nxt[2] == 0xBF)
1861227825Stheraven            frm_nxt += 3;
1862227825Stheraven    }
1863227825Stheraven    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1864227825Stheraven    {
1865227825Stheraven        uint8_t c1 = *frm_nxt;
1866227825Stheraven        if (c1 > Maxcode)
1867227825Stheraven            return codecvt_base::error;
1868227825Stheraven        if (c1 < 0x80)
1869227825Stheraven        {
1870227825Stheraven            *to_nxt = static_cast<uint16_t>(c1);
1871227825Stheraven            ++frm_nxt;
1872227825Stheraven        }
1873227825Stheraven        else if (c1 < 0xC2)
1874227825Stheraven        {
1875227825Stheraven            return codecvt_base::error;
1876227825Stheraven        }
1877227825Stheraven        else if (c1 < 0xE0)
1878227825Stheraven        {
1879227825Stheraven            if (frm_end-frm_nxt < 2)
1880227825Stheraven                return codecvt_base::partial;
1881227825Stheraven            uint8_t c2 = frm_nxt[1];
1882227825Stheraven            if ((c2 & 0xC0) != 0x80)
1883227825Stheraven                return codecvt_base::error;
1884227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1885227825Stheraven            if (t > Maxcode)
1886227825Stheraven                return codecvt_base::error;
1887227825Stheraven            *to_nxt = t;
1888227825Stheraven            frm_nxt += 2;
1889227825Stheraven        }
1890227825Stheraven        else if (c1 < 0xF0)
1891227825Stheraven        {
1892227825Stheraven            if (frm_end-frm_nxt < 3)
1893227825Stheraven                return codecvt_base::partial;
1894227825Stheraven            uint8_t c2 = frm_nxt[1];
1895227825Stheraven            uint8_t c3 = frm_nxt[2];
1896227825Stheraven            switch (c1)
1897227825Stheraven            {
1898227825Stheraven            case 0xE0:
1899227825Stheraven                if ((c2 & 0xE0) != 0xA0)
1900227825Stheraven                    return codecvt_base::error;
1901227825Stheraven                 break;
1902227825Stheraven            case 0xED:
1903227825Stheraven                if ((c2 & 0xE0) != 0x80)
1904227825Stheraven                    return codecvt_base::error;
1905227825Stheraven                 break;
1906227825Stheraven            default:
1907227825Stheraven                if ((c2 & 0xC0) != 0x80)
1908227825Stheraven                    return codecvt_base::error;
1909227825Stheraven                 break;
1910227825Stheraven            }
1911227825Stheraven            if ((c3 & 0xC0) != 0x80)
1912227825Stheraven                return codecvt_base::error;
1913227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1914227825Stheraven                                             | ((c2 & 0x3F) << 6)
1915227825Stheraven                                             |  (c3 & 0x3F));
1916227825Stheraven            if (t > Maxcode)
1917227825Stheraven                return codecvt_base::error;
1918227825Stheraven            *to_nxt = t;
1919227825Stheraven            frm_nxt += 3;
1920227825Stheraven        }
1921227825Stheraven        else if (c1 < 0xF5)
1922227825Stheraven        {
1923227825Stheraven            if (frm_end-frm_nxt < 4)
1924227825Stheraven                return codecvt_base::partial;
1925227825Stheraven            uint8_t c2 = frm_nxt[1];
1926227825Stheraven            uint8_t c3 = frm_nxt[2];
1927227825Stheraven            uint8_t c4 = frm_nxt[3];
1928227825Stheraven            switch (c1)
1929227825Stheraven            {
1930227825Stheraven            case 0xF0:
1931227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
1932227825Stheraven                    return codecvt_base::error;
1933227825Stheraven                 break;
1934227825Stheraven            case 0xF4:
1935227825Stheraven                if ((c2 & 0xF0) != 0x80)
1936227825Stheraven                    return codecvt_base::error;
1937227825Stheraven                 break;
1938227825Stheraven            default:
1939227825Stheraven                if ((c2 & 0xC0) != 0x80)
1940227825Stheraven                    return codecvt_base::error;
1941227825Stheraven                 break;
1942227825Stheraven            }
1943227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1944227825Stheraven                return codecvt_base::error;
1945227825Stheraven            if (to_end-to_nxt < 2)
1946227825Stheraven                return codecvt_base::partial;
1947227825Stheraven            if (((((unsigned long)c1 & 7) << 18) +
1948227825Stheraven                (((unsigned long)c2 & 0x3F) << 12) +
1949227825Stheraven                (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1950227825Stheraven                return codecvt_base::error;
1951227825Stheraven            *to_nxt = static_cast<uint16_t>(
1952227825Stheraven                    0xD800
1953227825Stheraven                  | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1954227825Stheraven                  | ((c2 & 0x0F) << 2)
1955227825Stheraven                  | ((c3 & 0x30) >> 4));
1956227825Stheraven            *++to_nxt = static_cast<uint16_t>(
1957227825Stheraven                    0xDC00
1958227825Stheraven                  | ((c3 & 0x0F) << 6)
1959227825Stheraven                  |  (c4 & 0x3F));
1960227825Stheraven            frm_nxt += 4;
1961227825Stheraven        }
1962227825Stheraven        else
1963227825Stheraven        {
1964227825Stheraven            return codecvt_base::error;
1965227825Stheraven        }
1966227825Stheraven    }
1967227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1968227825Stheraven}
1969227825Stheraven
1970227825Stheravenstatic
1971227825Stheravencodecvt_base::result
1972227825Stheravenutf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1973227825Stheraven              uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1974227825Stheraven              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1975227825Stheraven{
1976227825Stheraven    frm_nxt = frm;
1977227825Stheraven    to_nxt = to;
1978227825Stheraven    if (mode & consume_header)
1979227825Stheraven    {
1980227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1981227825Stheraven                                                          frm_nxt[2] == 0xBF)
1982227825Stheraven            frm_nxt += 3;
1983227825Stheraven    }
1984227825Stheraven    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1985227825Stheraven    {
1986227825Stheraven        uint8_t c1 = *frm_nxt;
1987227825Stheraven        if (c1 > Maxcode)
1988227825Stheraven            return codecvt_base::error;
1989227825Stheraven        if (c1 < 0x80)
1990227825Stheraven        {
1991227825Stheraven            *to_nxt = static_cast<uint32_t>(c1);
1992227825Stheraven            ++frm_nxt;
1993227825Stheraven        }
1994227825Stheraven        else if (c1 < 0xC2)
1995227825Stheraven        {
1996227825Stheraven            return codecvt_base::error;
1997227825Stheraven        }
1998227825Stheraven        else if (c1 < 0xE0)
1999227825Stheraven        {
2000227825Stheraven            if (frm_end-frm_nxt < 2)
2001227825Stheraven                return codecvt_base::partial;
2002227825Stheraven            uint8_t c2 = frm_nxt[1];
2003227825Stheraven            if ((c2 & 0xC0) != 0x80)
2004227825Stheraven                return codecvt_base::error;
2005227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2006227825Stheraven            if (t > Maxcode)
2007227825Stheraven                return codecvt_base::error;
2008227825Stheraven            *to_nxt = static_cast<uint32_t>(t);
2009227825Stheraven            frm_nxt += 2;
2010227825Stheraven        }
2011227825Stheraven        else if (c1 < 0xF0)
2012227825Stheraven        {
2013227825Stheraven            if (frm_end-frm_nxt < 3)
2014227825Stheraven                return codecvt_base::partial;
2015227825Stheraven            uint8_t c2 = frm_nxt[1];
2016227825Stheraven            uint8_t c3 = frm_nxt[2];
2017227825Stheraven            switch (c1)
2018227825Stheraven            {
2019227825Stheraven            case 0xE0:
2020227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2021227825Stheraven                    return codecvt_base::error;
2022227825Stheraven                 break;
2023227825Stheraven            case 0xED:
2024227825Stheraven                if ((c2 & 0xE0) != 0x80)
2025227825Stheraven                    return codecvt_base::error;
2026227825Stheraven                 break;
2027227825Stheraven            default:
2028227825Stheraven                if ((c2 & 0xC0) != 0x80)
2029227825Stheraven                    return codecvt_base::error;
2030227825Stheraven                 break;
2031227825Stheraven            }
2032227825Stheraven            if ((c3 & 0xC0) != 0x80)
2033227825Stheraven                return codecvt_base::error;
2034227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2035227825Stheraven                                             | ((c2 & 0x3F) << 6)
2036227825Stheraven                                             |  (c3 & 0x3F));
2037227825Stheraven            if (t > Maxcode)
2038227825Stheraven                return codecvt_base::error;
2039227825Stheraven            *to_nxt = static_cast<uint32_t>(t);
2040227825Stheraven            frm_nxt += 3;
2041227825Stheraven        }
2042227825Stheraven        else if (c1 < 0xF5)
2043227825Stheraven        {
2044227825Stheraven            if (frm_end-frm_nxt < 4)
2045227825Stheraven                return codecvt_base::partial;
2046227825Stheraven            uint8_t c2 = frm_nxt[1];
2047227825Stheraven            uint8_t c3 = frm_nxt[2];
2048227825Stheraven            uint8_t c4 = frm_nxt[3];
2049227825Stheraven            switch (c1)
2050227825Stheraven            {
2051227825Stheraven            case 0xF0:
2052227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
2053227825Stheraven                    return codecvt_base::error;
2054227825Stheraven                 break;
2055227825Stheraven            case 0xF4:
2056227825Stheraven                if ((c2 & 0xF0) != 0x80)
2057227825Stheraven                    return codecvt_base::error;
2058227825Stheraven                 break;
2059227825Stheraven            default:
2060227825Stheraven                if ((c2 & 0xC0) != 0x80)
2061227825Stheraven                    return codecvt_base::error;
2062227825Stheraven                 break;
2063227825Stheraven            }
2064227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2065227825Stheraven                return codecvt_base::error;
2066227825Stheraven            if (to_end-to_nxt < 2)
2067227825Stheraven                return codecvt_base::partial;
2068227825Stheraven            if (((((unsigned long)c1 & 7) << 18) +
2069227825Stheraven                (((unsigned long)c2 & 0x3F) << 12) +
2070227825Stheraven                (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2071227825Stheraven                return codecvt_base::error;
2072227825Stheraven            *to_nxt = static_cast<uint32_t>(
2073227825Stheraven                    0xD800
2074227825Stheraven                  | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2075227825Stheraven                  | ((c2 & 0x0F) << 2)
2076227825Stheraven                  | ((c3 & 0x30) >> 4));
2077227825Stheraven            *++to_nxt = static_cast<uint32_t>(
2078227825Stheraven                    0xDC00
2079227825Stheraven                  | ((c3 & 0x0F) << 6)
2080227825Stheraven                  |  (c4 & 0x3F));
2081227825Stheraven            frm_nxt += 4;
2082227825Stheraven        }
2083227825Stheraven        else
2084227825Stheraven        {
2085227825Stheraven            return codecvt_base::error;
2086227825Stheraven        }
2087227825Stheraven    }
2088227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2089227825Stheraven}
2090227825Stheraven
2091227825Stheravenstatic
2092227825Stheravenint
2093227825Stheravenutf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2094227825Stheraven                     size_t mx, unsigned long Maxcode = 0x10FFFF,
2095227825Stheraven                     codecvt_mode mode = codecvt_mode(0))
2096227825Stheraven{
2097227825Stheraven    const uint8_t* frm_nxt = frm;
2098227825Stheraven    if (mode & consume_header)
2099227825Stheraven    {
2100227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2101227825Stheraven                                                          frm_nxt[2] == 0xBF)
2102227825Stheraven            frm_nxt += 3;
2103227825Stheraven    }
2104227825Stheraven    for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2105227825Stheraven    {
2106227825Stheraven        uint8_t c1 = *frm_nxt;
2107227825Stheraven        if (c1 > Maxcode)
2108227825Stheraven            break;
2109227825Stheraven        if (c1 < 0x80)
2110227825Stheraven        {
2111227825Stheraven            ++frm_nxt;
2112227825Stheraven        }
2113227825Stheraven        else if (c1 < 0xC2)
2114227825Stheraven        {
2115227825Stheraven            break;
2116227825Stheraven        }
2117227825Stheraven        else if (c1 < 0xE0)
2118227825Stheraven        {
2119227825Stheraven            if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2120227825Stheraven                break;
2121227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2122227825Stheraven            if (t > Maxcode)
2123227825Stheraven                break;
2124227825Stheraven            frm_nxt += 2;
2125227825Stheraven        }
2126227825Stheraven        else if (c1 < 0xF0)
2127227825Stheraven        {
2128227825Stheraven            if (frm_end-frm_nxt < 3)
2129227825Stheraven                break;
2130227825Stheraven            uint8_t c2 = frm_nxt[1];
2131227825Stheraven            uint8_t c3 = frm_nxt[2];
2132227825Stheraven            switch (c1)
2133227825Stheraven            {
2134227825Stheraven            case 0xE0:
2135227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2136227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2137227825Stheraven                break;
2138227825Stheraven            case 0xED:
2139227825Stheraven                if ((c2 & 0xE0) != 0x80)
2140227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2141227825Stheraven                 break;
2142227825Stheraven            default:
2143227825Stheraven                if ((c2 & 0xC0) != 0x80)
2144227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2145227825Stheraven                 break;
2146227825Stheraven            }
2147227825Stheraven            if ((c3 & 0xC0) != 0x80)
2148227825Stheraven                break;
2149232950Stheraven            if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2150227825Stheraven                break;
2151227825Stheraven            frm_nxt += 3;
2152227825Stheraven        }
2153227825Stheraven        else if (c1 < 0xF5)
2154227825Stheraven        {
2155227825Stheraven            if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2156227825Stheraven                break;
2157227825Stheraven            uint8_t c2 = frm_nxt[1];
2158227825Stheraven            uint8_t c3 = frm_nxt[2];
2159227825Stheraven            uint8_t c4 = frm_nxt[3];
2160227825Stheraven            switch (c1)
2161227825Stheraven            {
2162227825Stheraven            case 0xF0:
2163227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
2164227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2165227825Stheraven                 break;
2166227825Stheraven            case 0xF4:
2167227825Stheraven                if ((c2 & 0xF0) != 0x80)
2168227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2169227825Stheraven                 break;
2170227825Stheraven            default:
2171227825Stheraven                if ((c2 & 0xC0) != 0x80)
2172227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2173227825Stheraven                 break;
2174227825Stheraven            }
2175227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2176227825Stheraven                break;
2177227825Stheraven            if (((((unsigned long)c1 & 7) << 18) +
2178227825Stheraven                (((unsigned long)c2 & 0x3F) << 12) +
2179227825Stheraven                (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2180227825Stheraven                break;
2181227825Stheraven            ++nchar16_t;
2182227825Stheraven            frm_nxt += 4;
2183227825Stheraven        }
2184227825Stheraven        else
2185227825Stheraven        {
2186227825Stheraven            break;
2187227825Stheraven        }
2188227825Stheraven    }
2189227825Stheraven    return static_cast<int>(frm_nxt - frm);
2190227825Stheraven}
2191227825Stheraven
2192227825Stheravenstatic
2193227825Stheravencodecvt_base::result
2194227825Stheravenucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2195227825Stheraven             uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2196227825Stheraven             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2197227825Stheraven{
2198227825Stheraven    frm_nxt = frm;
2199227825Stheraven    to_nxt = to;
2200227825Stheraven    if (mode & generate_header)
2201227825Stheraven    {
2202227825Stheraven        if (to_end-to_nxt < 3)
2203227825Stheraven            return codecvt_base::partial;
2204227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xEF);
2205227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBB);
2206227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBF);
2207227825Stheraven    }
2208227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2209227825Stheraven    {
2210227825Stheraven        uint32_t wc = *frm_nxt;
2211227825Stheraven        if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2212227825Stheraven            return codecvt_base::error;
2213227825Stheraven        if (wc < 0x000080)
2214227825Stheraven        {
2215227825Stheraven            if (to_end-to_nxt < 1)
2216227825Stheraven                return codecvt_base::partial;
2217227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc);
2218227825Stheraven        }
2219227825Stheraven        else if (wc < 0x000800)
2220227825Stheraven        {
2221227825Stheraven            if (to_end-to_nxt < 2)
2222227825Stheraven                return codecvt_base::partial;
2223227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2224227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2225227825Stheraven        }
2226227825Stheraven        else if (wc < 0x010000)
2227227825Stheraven        {
2228227825Stheraven            if (to_end-to_nxt < 3)
2229227825Stheraven                return codecvt_base::partial;
2230227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
2231227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2232227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
2233227825Stheraven        }
2234227825Stheraven        else // if (wc < 0x110000)
2235227825Stheraven        {
2236227825Stheraven            if (to_end-to_nxt < 4)
2237227825Stheraven                return codecvt_base::partial;
2238227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xF0 |  (wc >> 18));
2239227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2240227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2241227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x00003F));
2242227825Stheraven        }
2243227825Stheraven    }
2244227825Stheraven    return codecvt_base::ok;
2245227825Stheraven}
2246227825Stheraven
2247227825Stheravenstatic
2248227825Stheravencodecvt_base::result
2249227825Stheravenutf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2250227825Stheraven             uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2251227825Stheraven             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2252227825Stheraven{
2253227825Stheraven    frm_nxt = frm;
2254227825Stheraven    to_nxt = to;
2255227825Stheraven    if (mode & consume_header)
2256227825Stheraven    {
2257227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2258227825Stheraven                                                          frm_nxt[2] == 0xBF)
2259227825Stheraven            frm_nxt += 3;
2260227825Stheraven    }
2261227825Stheraven    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2262227825Stheraven    {
2263227825Stheraven        uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2264227825Stheraven        if (c1 < 0x80)
2265227825Stheraven        {
2266227825Stheraven            if (c1 > Maxcode)
2267227825Stheraven                return codecvt_base::error;
2268227825Stheraven            *to_nxt = static_cast<uint32_t>(c1);
2269227825Stheraven            ++frm_nxt;
2270227825Stheraven        }
2271227825Stheraven        else if (c1 < 0xC2)
2272227825Stheraven        {
2273227825Stheraven            return codecvt_base::error;
2274227825Stheraven        }
2275227825Stheraven        else if (c1 < 0xE0)
2276227825Stheraven        {
2277227825Stheraven            if (frm_end-frm_nxt < 2)
2278227825Stheraven                return codecvt_base::partial;
2279227825Stheraven            uint8_t c2 = frm_nxt[1];
2280227825Stheraven            if ((c2 & 0xC0) != 0x80)
2281227825Stheraven                return codecvt_base::error;
2282227825Stheraven            uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2283227825Stheraven                                              | (c2 & 0x3F));
2284227825Stheraven            if (t > Maxcode)
2285227825Stheraven                return codecvt_base::error;
2286227825Stheraven            *to_nxt = t;
2287227825Stheraven            frm_nxt += 2;
2288227825Stheraven        }
2289227825Stheraven        else if (c1 < 0xF0)
2290227825Stheraven        {
2291227825Stheraven            if (frm_end-frm_nxt < 3)
2292227825Stheraven                return codecvt_base::partial;
2293227825Stheraven            uint8_t c2 = frm_nxt[1];
2294227825Stheraven            uint8_t c3 = frm_nxt[2];
2295227825Stheraven            switch (c1)
2296227825Stheraven            {
2297227825Stheraven            case 0xE0:
2298227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2299227825Stheraven                    return codecvt_base::error;
2300227825Stheraven                 break;
2301227825Stheraven            case 0xED:
2302227825Stheraven                if ((c2 & 0xE0) != 0x80)
2303227825Stheraven                    return codecvt_base::error;
2304227825Stheraven                 break;
2305227825Stheraven            default:
2306227825Stheraven                if ((c2 & 0xC0) != 0x80)
2307227825Stheraven                    return codecvt_base::error;
2308227825Stheraven                 break;
2309227825Stheraven            }
2310227825Stheraven            if ((c3 & 0xC0) != 0x80)
2311227825Stheraven                return codecvt_base::error;
2312227825Stheraven            uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2313227825Stheraven                                             | ((c2 & 0x3F) << 6)
2314227825Stheraven                                             |  (c3 & 0x3F));
2315227825Stheraven            if (t > Maxcode)
2316227825Stheraven                return codecvt_base::error;
2317227825Stheraven            *to_nxt = t;
2318227825Stheraven            frm_nxt += 3;
2319227825Stheraven        }
2320227825Stheraven        else if (c1 < 0xF5)
2321227825Stheraven        {
2322227825Stheraven            if (frm_end-frm_nxt < 4)
2323227825Stheraven                return codecvt_base::partial;
2324227825Stheraven            uint8_t c2 = frm_nxt[1];
2325227825Stheraven            uint8_t c3 = frm_nxt[2];
2326227825Stheraven            uint8_t c4 = frm_nxt[3];
2327227825Stheraven            switch (c1)
2328227825Stheraven            {
2329227825Stheraven            case 0xF0:
2330227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
2331227825Stheraven                    return codecvt_base::error;
2332227825Stheraven                 break;
2333227825Stheraven            case 0xF4:
2334227825Stheraven                if ((c2 & 0xF0) != 0x80)
2335227825Stheraven                    return codecvt_base::error;
2336227825Stheraven                 break;
2337227825Stheraven            default:
2338227825Stheraven                if ((c2 & 0xC0) != 0x80)
2339227825Stheraven                    return codecvt_base::error;
2340227825Stheraven                 break;
2341227825Stheraven            }
2342227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2343227825Stheraven                return codecvt_base::error;
2344227825Stheraven            uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2345227825Stheraven                                             | ((c2 & 0x3F) << 12)
2346227825Stheraven                                             | ((c3 & 0x3F) << 6)
2347227825Stheraven                                             |  (c4 & 0x3F));
2348227825Stheraven            if (t > Maxcode)
2349227825Stheraven                return codecvt_base::error;
2350227825Stheraven            *to_nxt = t;
2351227825Stheraven            frm_nxt += 4;
2352227825Stheraven        }
2353227825Stheraven        else
2354227825Stheraven        {
2355227825Stheraven            return codecvt_base::error;
2356227825Stheraven        }
2357227825Stheraven    }
2358227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2359227825Stheraven}
2360227825Stheraven
2361227825Stheravenstatic
2362227825Stheravenint
2363227825Stheravenutf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2364227825Stheraven                    size_t mx, unsigned long Maxcode = 0x10FFFF,
2365227825Stheraven                    codecvt_mode mode = codecvt_mode(0))
2366227825Stheraven{
2367227825Stheraven    const uint8_t* frm_nxt = frm;
2368227825Stheraven    if (mode & consume_header)
2369227825Stheraven    {
2370227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2371227825Stheraven                                                          frm_nxt[2] == 0xBF)
2372227825Stheraven            frm_nxt += 3;
2373227825Stheraven    }
2374227825Stheraven    for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2375227825Stheraven    {
2376227825Stheraven        uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2377227825Stheraven        if (c1 < 0x80)
2378227825Stheraven        {
2379227825Stheraven            if (c1 > Maxcode)
2380227825Stheraven                break;
2381227825Stheraven            ++frm_nxt;
2382227825Stheraven        }
2383227825Stheraven        else if (c1 < 0xC2)
2384227825Stheraven        {
2385227825Stheraven            break;
2386227825Stheraven        }
2387227825Stheraven        else if (c1 < 0xE0)
2388227825Stheraven        {
2389227825Stheraven            if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2390227825Stheraven                break;
2391232950Stheraven            if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2392227825Stheraven                break;
2393227825Stheraven            frm_nxt += 2;
2394227825Stheraven        }
2395227825Stheraven        else if (c1 < 0xF0)
2396227825Stheraven        {
2397227825Stheraven            if (frm_end-frm_nxt < 3)
2398227825Stheraven                break;
2399227825Stheraven            uint8_t c2 = frm_nxt[1];
2400227825Stheraven            uint8_t c3 = frm_nxt[2];
2401227825Stheraven            switch (c1)
2402227825Stheraven            {
2403227825Stheraven            case 0xE0:
2404227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2405227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2406227825Stheraven                break;
2407227825Stheraven            case 0xED:
2408227825Stheraven                if ((c2 & 0xE0) != 0x80)
2409227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2410227825Stheraven                 break;
2411227825Stheraven            default:
2412227825Stheraven                if ((c2 & 0xC0) != 0x80)
2413227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2414227825Stheraven                 break;
2415227825Stheraven            }
2416227825Stheraven            if ((c3 & 0xC0) != 0x80)
2417227825Stheraven                break;
2418232950Stheraven            if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2419227825Stheraven                break;
2420227825Stheraven            frm_nxt += 3;
2421227825Stheraven        }
2422227825Stheraven        else if (c1 < 0xF5)
2423227825Stheraven        {
2424227825Stheraven            if (frm_end-frm_nxt < 4)
2425227825Stheraven                break;
2426227825Stheraven            uint8_t c2 = frm_nxt[1];
2427227825Stheraven            uint8_t c3 = frm_nxt[2];
2428227825Stheraven            uint8_t c4 = frm_nxt[3];
2429227825Stheraven            switch (c1)
2430227825Stheraven            {
2431227825Stheraven            case 0xF0:
2432227825Stheraven                if (!(0x90 <= c2 && c2 <= 0xBF))
2433227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2434227825Stheraven                 break;
2435227825Stheraven            case 0xF4:
2436227825Stheraven                if ((c2 & 0xF0) != 0x80)
2437227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2438227825Stheraven                 break;
2439227825Stheraven            default:
2440227825Stheraven                if ((c2 & 0xC0) != 0x80)
2441227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2442227825Stheraven                 break;
2443227825Stheraven            }
2444227825Stheraven            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2445227825Stheraven                break;
2446232950Stheraven            if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2447232950Stheraven                 ((c3 & 0x3Fu) << 6)  |  (c4 & 0x3Fu)) > Maxcode)
2448227825Stheraven                break;
2449227825Stheraven            frm_nxt += 4;
2450227825Stheraven        }
2451227825Stheraven        else
2452227825Stheraven        {
2453227825Stheraven            break;
2454227825Stheraven        }
2455227825Stheraven    }
2456227825Stheraven    return static_cast<int>(frm_nxt - frm);
2457227825Stheraven}
2458227825Stheraven
2459227825Stheravenstatic
2460227825Stheravencodecvt_base::result
2461227825Stheravenucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2462227825Stheraven             uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2463227825Stheraven             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2464227825Stheraven{
2465227825Stheraven    frm_nxt = frm;
2466227825Stheraven    to_nxt = to;
2467227825Stheraven    if (mode & generate_header)
2468227825Stheraven    {
2469227825Stheraven        if (to_end-to_nxt < 3)
2470227825Stheraven            return codecvt_base::partial;
2471227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xEF);
2472227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBB);
2473227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xBF);
2474227825Stheraven    }
2475227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2476227825Stheraven    {
2477227825Stheraven        uint16_t wc = *frm_nxt;
2478227825Stheraven        if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2479227825Stheraven            return codecvt_base::error;
2480227825Stheraven        if (wc < 0x0080)
2481227825Stheraven        {
2482227825Stheraven            if (to_end-to_nxt < 1)
2483227825Stheraven                return codecvt_base::partial;
2484227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc);
2485227825Stheraven        }
2486227825Stheraven        else if (wc < 0x0800)
2487227825Stheraven        {
2488227825Stheraven            if (to_end-to_nxt < 2)
2489227825Stheraven                return codecvt_base::partial;
2490227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2491227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2492227825Stheraven        }
2493227825Stheraven        else // if (wc <= 0xFFFF)
2494227825Stheraven        {
2495227825Stheraven            if (to_end-to_nxt < 3)
2496227825Stheraven                return codecvt_base::partial;
2497227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
2498227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2499227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
2500227825Stheraven        }
2501227825Stheraven    }
2502227825Stheraven    return codecvt_base::ok;
2503227825Stheraven}
2504227825Stheraven
2505227825Stheravenstatic
2506227825Stheravencodecvt_base::result
2507227825Stheravenutf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2508227825Stheraven             uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2509227825Stheraven             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2510227825Stheraven{
2511227825Stheraven    frm_nxt = frm;
2512227825Stheraven    to_nxt = to;
2513227825Stheraven    if (mode & consume_header)
2514227825Stheraven    {
2515227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2516227825Stheraven                                                          frm_nxt[2] == 0xBF)
2517227825Stheraven            frm_nxt += 3;
2518227825Stheraven    }
2519227825Stheraven    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2520227825Stheraven    {
2521227825Stheraven        uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2522227825Stheraven        if (c1 < 0x80)
2523227825Stheraven        {
2524227825Stheraven            if (c1 > Maxcode)
2525227825Stheraven                return codecvt_base::error;
2526227825Stheraven            *to_nxt = static_cast<uint16_t>(c1);
2527227825Stheraven            ++frm_nxt;
2528227825Stheraven        }
2529227825Stheraven        else if (c1 < 0xC2)
2530227825Stheraven        {
2531227825Stheraven            return codecvt_base::error;
2532227825Stheraven        }
2533227825Stheraven        else if (c1 < 0xE0)
2534227825Stheraven        {
2535227825Stheraven            if (frm_end-frm_nxt < 2)
2536227825Stheraven                return codecvt_base::partial;
2537227825Stheraven            uint8_t c2 = frm_nxt[1];
2538227825Stheraven            if ((c2 & 0xC0) != 0x80)
2539227825Stheraven                return codecvt_base::error;
2540227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2541227825Stheraven                                              | (c2 & 0x3F));
2542227825Stheraven            if (t > Maxcode)
2543227825Stheraven                return codecvt_base::error;
2544227825Stheraven            *to_nxt = t;
2545227825Stheraven            frm_nxt += 2;
2546227825Stheraven        }
2547227825Stheraven        else if (c1 < 0xF0)
2548227825Stheraven        {
2549227825Stheraven            if (frm_end-frm_nxt < 3)
2550227825Stheraven                return codecvt_base::partial;
2551227825Stheraven            uint8_t c2 = frm_nxt[1];
2552227825Stheraven            uint8_t c3 = frm_nxt[2];
2553227825Stheraven            switch (c1)
2554227825Stheraven            {
2555227825Stheraven            case 0xE0:
2556227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2557227825Stheraven                    return codecvt_base::error;
2558227825Stheraven                 break;
2559227825Stheraven            case 0xED:
2560227825Stheraven                if ((c2 & 0xE0) != 0x80)
2561227825Stheraven                    return codecvt_base::error;
2562227825Stheraven                 break;
2563227825Stheraven            default:
2564227825Stheraven                if ((c2 & 0xC0) != 0x80)
2565227825Stheraven                    return codecvt_base::error;
2566227825Stheraven                 break;
2567227825Stheraven            }
2568227825Stheraven            if ((c3 & 0xC0) != 0x80)
2569227825Stheraven                return codecvt_base::error;
2570227825Stheraven            uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2571227825Stheraven                                             | ((c2 & 0x3F) << 6)
2572227825Stheraven                                             |  (c3 & 0x3F));
2573227825Stheraven            if (t > Maxcode)
2574227825Stheraven                return codecvt_base::error;
2575227825Stheraven            *to_nxt = t;
2576227825Stheraven            frm_nxt += 3;
2577227825Stheraven        }
2578227825Stheraven        else
2579227825Stheraven        {
2580227825Stheraven            return codecvt_base::error;
2581227825Stheraven        }
2582227825Stheraven    }
2583227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2584227825Stheraven}
2585227825Stheraven
2586227825Stheravenstatic
2587227825Stheravenint
2588227825Stheravenutf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2589227825Stheraven                    size_t mx, unsigned long Maxcode = 0x10FFFF,
2590227825Stheraven                    codecvt_mode mode = codecvt_mode(0))
2591227825Stheraven{
2592227825Stheraven    const uint8_t* frm_nxt = frm;
2593227825Stheraven    if (mode & consume_header)
2594227825Stheraven    {
2595227825Stheraven        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2596227825Stheraven                                                          frm_nxt[2] == 0xBF)
2597227825Stheraven            frm_nxt += 3;
2598227825Stheraven    }
2599227825Stheraven    for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2600227825Stheraven    {
2601227825Stheraven        uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2602227825Stheraven        if (c1 < 0x80)
2603227825Stheraven        {
2604227825Stheraven            if (c1 > Maxcode)
2605227825Stheraven                break;
2606227825Stheraven            ++frm_nxt;
2607227825Stheraven        }
2608227825Stheraven        else if (c1 < 0xC2)
2609227825Stheraven        {
2610227825Stheraven            break;
2611227825Stheraven        }
2612227825Stheraven        else if (c1 < 0xE0)
2613227825Stheraven        {
2614227825Stheraven            if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2615227825Stheraven                break;
2616232950Stheraven            if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2617227825Stheraven                break;
2618227825Stheraven            frm_nxt += 2;
2619227825Stheraven        }
2620227825Stheraven        else if (c1 < 0xF0)
2621227825Stheraven        {
2622227825Stheraven            if (frm_end-frm_nxt < 3)
2623227825Stheraven                break;
2624227825Stheraven            uint8_t c2 = frm_nxt[1];
2625227825Stheraven            uint8_t c3 = frm_nxt[2];
2626227825Stheraven            switch (c1)
2627227825Stheraven            {
2628227825Stheraven            case 0xE0:
2629227825Stheraven                if ((c2 & 0xE0) != 0xA0)
2630227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2631227825Stheraven                break;
2632227825Stheraven            case 0xED:
2633227825Stheraven                if ((c2 & 0xE0) != 0x80)
2634227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2635227825Stheraven                 break;
2636227825Stheraven            default:
2637227825Stheraven                if ((c2 & 0xC0) != 0x80)
2638227825Stheraven                    return static_cast<int>(frm_nxt - frm);
2639227825Stheraven                 break;
2640227825Stheraven            }
2641227825Stheraven            if ((c3 & 0xC0) != 0x80)
2642227825Stheraven                break;
2643232950Stheraven            if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2644227825Stheraven                break;
2645227825Stheraven            frm_nxt += 3;
2646227825Stheraven        }
2647227825Stheraven        else
2648227825Stheraven        {
2649227825Stheraven            break;
2650227825Stheraven        }
2651227825Stheraven    }
2652227825Stheraven    return static_cast<int>(frm_nxt - frm);
2653227825Stheraven}
2654227825Stheraven
2655227825Stheravenstatic
2656227825Stheravencodecvt_base::result
2657227825Stheravenucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2658227825Stheraven                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2659227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2660227825Stheraven{
2661227825Stheraven    frm_nxt = frm;
2662227825Stheraven    to_nxt = to;
2663227825Stheraven    if (mode & generate_header)
2664227825Stheraven    {
2665227825Stheraven        if (to_end-to_nxt < 2)
2666227825Stheraven            return codecvt_base::partial;
2667227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFE);
2668227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFF);
2669227825Stheraven    }
2670227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2671227825Stheraven    {
2672227825Stheraven        uint32_t wc = *frm_nxt;
2673227825Stheraven        if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2674227825Stheraven            return codecvt_base::error;
2675227825Stheraven        if (wc < 0x010000)
2676227825Stheraven        {
2677227825Stheraven            if (to_end-to_nxt < 2)
2678227825Stheraven                return codecvt_base::partial;
2679227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2680227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc);
2681227825Stheraven        }
2682227825Stheraven        else
2683227825Stheraven        {
2684227825Stheraven            if (to_end-to_nxt < 4)
2685227825Stheraven                return codecvt_base::partial;
2686227825Stheraven            uint16_t t = static_cast<uint16_t>(
2687227825Stheraven                    0xD800
2688227825Stheraven                  | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2689227825Stheraven                  |   ((wc & 0x00FC00) >> 10));
2690227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t >> 8);
2691227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t);
2692227825Stheraven            t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2693227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t >> 8);
2694227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t);
2695227825Stheraven        }
2696227825Stheraven    }
2697227825Stheraven    return codecvt_base::ok;
2698227825Stheraven}
2699227825Stheraven
2700227825Stheravenstatic
2701227825Stheravencodecvt_base::result
2702227825Stheravenutf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2703227825Stheraven                uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2704227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2705227825Stheraven{
2706227825Stheraven    frm_nxt = frm;
2707227825Stheraven    to_nxt = to;
2708227825Stheraven    if (mode & consume_header)
2709227825Stheraven    {
2710227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2711227825Stheraven            frm_nxt += 2;
2712227825Stheraven    }
2713227825Stheraven    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2714227825Stheraven    {
2715232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2716227825Stheraven        if ((c1 & 0xFC00) == 0xDC00)
2717227825Stheraven            return codecvt_base::error;
2718227825Stheraven        if ((c1 & 0xFC00) != 0xD800)
2719227825Stheraven        {
2720227825Stheraven            if (c1 > Maxcode)
2721227825Stheraven                return codecvt_base::error;
2722227825Stheraven            *to_nxt = static_cast<uint32_t>(c1);
2723227825Stheraven            frm_nxt += 2;
2724227825Stheraven        }
2725227825Stheraven        else
2726227825Stheraven        {
2727227825Stheraven            if (frm_end-frm_nxt < 4)
2728227825Stheraven                return codecvt_base::partial;
2729232950Stheraven            uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2730227825Stheraven            if ((c2 & 0xFC00) != 0xDC00)
2731227825Stheraven                return codecvt_base::error;
2732227825Stheraven            uint32_t t = static_cast<uint32_t>(
2733227825Stheraven                    ((((c1 & 0x03C0) >> 6) + 1) << 16)
2734227825Stheraven                  |   ((c1 & 0x003F) << 10)
2735227825Stheraven                  |    (c2 & 0x03FF));
2736227825Stheraven            if (t > Maxcode)
2737227825Stheraven                return codecvt_base::error;
2738227825Stheraven            *to_nxt = t;
2739227825Stheraven            frm_nxt += 4;
2740227825Stheraven        }
2741227825Stheraven    }
2742227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2743227825Stheraven}
2744227825Stheraven
2745227825Stheravenstatic
2746227825Stheravenint
2747227825Stheravenutf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2748227825Stheraven                       size_t mx, unsigned long Maxcode = 0x10FFFF,
2749227825Stheraven                       codecvt_mode mode = codecvt_mode(0))
2750227825Stheraven{
2751227825Stheraven    const uint8_t* frm_nxt = frm;
2752227825Stheraven    if (mode & consume_header)
2753227825Stheraven    {
2754227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2755227825Stheraven            frm_nxt += 2;
2756227825Stheraven    }
2757227825Stheraven    for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2758227825Stheraven    {
2759232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2760227825Stheraven        if ((c1 & 0xFC00) == 0xDC00)
2761227825Stheraven            break;
2762227825Stheraven        if ((c1 & 0xFC00) != 0xD800)
2763227825Stheraven        {
2764227825Stheraven            if (c1 > Maxcode)
2765227825Stheraven                break;
2766227825Stheraven            frm_nxt += 2;
2767227825Stheraven        }
2768227825Stheraven        else
2769227825Stheraven        {
2770227825Stheraven            if (frm_end-frm_nxt < 4)
2771227825Stheraven                break;
2772232950Stheraven            uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2773227825Stheraven            if ((c2 & 0xFC00) != 0xDC00)
2774227825Stheraven                break;
2775227825Stheraven            uint32_t t = static_cast<uint32_t>(
2776227825Stheraven                    ((((c1 & 0x03C0) >> 6) + 1) << 16)
2777227825Stheraven                  |   ((c1 & 0x003F) << 10)
2778227825Stheraven                  |    (c2 & 0x03FF));
2779227825Stheraven            if (t > Maxcode)
2780227825Stheraven                break;
2781227825Stheraven            frm_nxt += 4;
2782227825Stheraven        }
2783227825Stheraven    }
2784227825Stheraven    return static_cast<int>(frm_nxt - frm);
2785227825Stheraven}
2786227825Stheraven
2787227825Stheravenstatic
2788227825Stheravencodecvt_base::result
2789227825Stheravenucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2790227825Stheraven                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2791227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2792227825Stheraven{
2793227825Stheraven    frm_nxt = frm;
2794227825Stheraven    to_nxt = to;
2795227825Stheraven    if (mode & generate_header)
2796227825Stheraven    {
2797227825Stheraven        if (to_end-to_nxt < 2)
2798227825Stheraven            return codecvt_base::partial;
2799227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xFF);
2800227825Stheraven            *to_nxt++ = static_cast<uint8_t>(0xFE);
2801227825Stheraven    }
2802227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2803227825Stheraven    {
2804227825Stheraven        uint32_t wc = *frm_nxt;
2805227825Stheraven        if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2806227825Stheraven            return codecvt_base::error;
2807227825Stheraven        if (wc < 0x010000)
2808227825Stheraven        {
2809227825Stheraven            if (to_end-to_nxt < 2)
2810227825Stheraven                return codecvt_base::partial;
2811227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc);
2812227825Stheraven            *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2813227825Stheraven        }
2814227825Stheraven        else
2815227825Stheraven        {
2816227825Stheraven            if (to_end-to_nxt < 4)
2817227825Stheraven                return codecvt_base::partial;
2818227825Stheraven            uint16_t t = static_cast<uint16_t>(
2819227825Stheraven                    0xD800
2820227825Stheraven                  | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2821227825Stheraven                  |   ((wc & 0x00FC00) >> 10));
2822227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t);
2823227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t >> 8);
2824227825Stheraven            t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2825227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t);
2826227825Stheraven            *to_nxt++ = static_cast<uint8_t>(t >> 8);
2827227825Stheraven        }
2828227825Stheraven    }
2829227825Stheraven    return codecvt_base::ok;
2830227825Stheraven}
2831227825Stheraven
2832227825Stheravenstatic
2833227825Stheravencodecvt_base::result
2834227825Stheravenutf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2835227825Stheraven                uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2836227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2837227825Stheraven{
2838227825Stheraven    frm_nxt = frm;
2839227825Stheraven    to_nxt = to;
2840227825Stheraven    if (mode & consume_header)
2841227825Stheraven    {
2842227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2843227825Stheraven            frm_nxt += 2;
2844227825Stheraven    }
2845227825Stheraven    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2846227825Stheraven    {
2847232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2848227825Stheraven        if ((c1 & 0xFC00) == 0xDC00)
2849227825Stheraven            return codecvt_base::error;
2850227825Stheraven        if ((c1 & 0xFC00) != 0xD800)
2851227825Stheraven        {
2852227825Stheraven            if (c1 > Maxcode)
2853227825Stheraven                return codecvt_base::error;
2854227825Stheraven            *to_nxt = static_cast<uint32_t>(c1);
2855227825Stheraven            frm_nxt += 2;
2856227825Stheraven        }
2857227825Stheraven        else
2858227825Stheraven        {
2859227825Stheraven            if (frm_end-frm_nxt < 4)
2860227825Stheraven                return codecvt_base::partial;
2861232950Stheraven            uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
2862227825Stheraven            if ((c2 & 0xFC00) != 0xDC00)
2863227825Stheraven                return codecvt_base::error;
2864227825Stheraven            uint32_t t = static_cast<uint32_t>(
2865227825Stheraven                    ((((c1 & 0x03C0) >> 6) + 1) << 16)
2866227825Stheraven                  |   ((c1 & 0x003F) << 10)
2867227825Stheraven                  |    (c2 & 0x03FF));
2868227825Stheraven            if (t > Maxcode)
2869227825Stheraven                return codecvt_base::error;
2870227825Stheraven            *to_nxt = t;
2871227825Stheraven            frm_nxt += 4;
2872227825Stheraven        }
2873227825Stheraven    }
2874227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2875227825Stheraven}
2876227825Stheraven
2877227825Stheravenstatic
2878227825Stheravenint
2879227825Stheravenutf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2880227825Stheraven                       size_t mx, unsigned long Maxcode = 0x10FFFF,
2881227825Stheraven                       codecvt_mode mode = codecvt_mode(0))
2882227825Stheraven{
2883227825Stheraven    const uint8_t* frm_nxt = frm;
2884227825Stheraven    if (mode & consume_header)
2885227825Stheraven    {
2886227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2887227825Stheraven            frm_nxt += 2;
2888227825Stheraven    }
2889227825Stheraven    for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2890227825Stheraven    {
2891232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2892227825Stheraven        if ((c1 & 0xFC00) == 0xDC00)
2893227825Stheraven            break;
2894227825Stheraven        if ((c1 & 0xFC00) != 0xD800)
2895227825Stheraven        {
2896227825Stheraven            if (c1 > Maxcode)
2897227825Stheraven                break;
2898227825Stheraven            frm_nxt += 2;
2899227825Stheraven        }
2900227825Stheraven        else
2901227825Stheraven        {
2902227825Stheraven            if (frm_end-frm_nxt < 4)
2903227825Stheraven                break;
2904232950Stheraven            uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
2905227825Stheraven            if ((c2 & 0xFC00) != 0xDC00)
2906227825Stheraven                break;
2907227825Stheraven            uint32_t t = static_cast<uint32_t>(
2908227825Stheraven                    ((((c1 & 0x03C0) >> 6) + 1) << 16)
2909227825Stheraven                  |   ((c1 & 0x003F) << 10)
2910227825Stheraven                  |    (c2 & 0x03FF));
2911227825Stheraven            if (t > Maxcode)
2912227825Stheraven                break;
2913227825Stheraven            frm_nxt += 4;
2914227825Stheraven        }
2915227825Stheraven    }
2916227825Stheraven    return static_cast<int>(frm_nxt - frm);
2917227825Stheraven}
2918227825Stheraven
2919227825Stheravenstatic
2920227825Stheravencodecvt_base::result
2921227825Stheravenucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2922227825Stheraven                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2923227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2924227825Stheraven{
2925227825Stheraven    frm_nxt = frm;
2926227825Stheraven    to_nxt = to;
2927227825Stheraven    if (mode & generate_header)
2928227825Stheraven    {
2929227825Stheraven        if (to_end-to_nxt < 2)
2930227825Stheraven            return codecvt_base::partial;
2931227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFE);
2932227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFF);
2933227825Stheraven    }
2934227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
2935227825Stheraven    {
2936227825Stheraven        uint16_t wc = *frm_nxt;
2937227825Stheraven        if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2938227825Stheraven            return codecvt_base::error;
2939227825Stheraven        if (to_end-to_nxt < 2)
2940227825Stheraven            return codecvt_base::partial;
2941227825Stheraven        *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2942227825Stheraven        *to_nxt++ = static_cast<uint8_t>(wc);
2943227825Stheraven    }
2944227825Stheraven    return codecvt_base::ok;
2945227825Stheraven}
2946227825Stheraven
2947227825Stheravenstatic
2948227825Stheravencodecvt_base::result
2949227825Stheravenutf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2950227825Stheraven                uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2951227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2952227825Stheraven{
2953227825Stheraven    frm_nxt = frm;
2954227825Stheraven    to_nxt = to;
2955227825Stheraven    if (mode & consume_header)
2956227825Stheraven    {
2957227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2958227825Stheraven            frm_nxt += 2;
2959227825Stheraven    }
2960227825Stheraven    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2961227825Stheraven    {
2962232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2963227825Stheraven        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2964227825Stheraven            return codecvt_base::error;
2965227825Stheraven        *to_nxt = c1;
2966227825Stheraven        frm_nxt += 2;
2967227825Stheraven    }
2968227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2969227825Stheraven}
2970227825Stheraven
2971227825Stheravenstatic
2972227825Stheravenint
2973227825Stheravenutf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2974227825Stheraven                       size_t mx, unsigned long Maxcode = 0x10FFFF,
2975227825Stheraven                       codecvt_mode mode = codecvt_mode(0))
2976227825Stheraven{
2977227825Stheraven    const uint8_t* frm_nxt = frm;
2978227825Stheraven    if (mode & consume_header)
2979227825Stheraven    {
2980227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2981227825Stheraven            frm_nxt += 2;
2982227825Stheraven    }
2983227825Stheraven    for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2984227825Stheraven    {
2985232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2986227825Stheraven        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2987227825Stheraven            break;
2988227825Stheraven        frm_nxt += 2;
2989227825Stheraven    }
2990227825Stheraven    return static_cast<int>(frm_nxt - frm);
2991227825Stheraven}
2992227825Stheraven
2993227825Stheravenstatic
2994227825Stheravencodecvt_base::result
2995227825Stheravenucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2996227825Stheraven                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2997227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2998227825Stheraven{
2999227825Stheraven    frm_nxt = frm;
3000227825Stheraven    to_nxt = to;
3001227825Stheraven    if (mode & generate_header)
3002227825Stheraven    {
3003227825Stheraven        if (to_end-to_nxt < 2)
3004227825Stheraven            return codecvt_base::partial;
3005227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFF);
3006227825Stheraven        *to_nxt++ = static_cast<uint8_t>(0xFE);
3007227825Stheraven    }
3008227825Stheraven    for (; frm_nxt < frm_end; ++frm_nxt)
3009227825Stheraven    {
3010227825Stheraven        uint16_t wc = *frm_nxt;
3011227825Stheraven        if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3012227825Stheraven            return codecvt_base::error;
3013227825Stheraven        if (to_end-to_nxt < 2)
3014227825Stheraven            return codecvt_base::partial;
3015227825Stheraven        *to_nxt++ = static_cast<uint8_t>(wc);
3016227825Stheraven        *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3017227825Stheraven    }
3018227825Stheraven    return codecvt_base::ok;
3019227825Stheraven}
3020227825Stheraven
3021227825Stheravenstatic
3022227825Stheravencodecvt_base::result
3023227825Stheravenutf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3024227825Stheraven                uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3025227825Stheraven                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3026227825Stheraven{
3027227825Stheraven    frm_nxt = frm;
3028227825Stheraven    to_nxt = to;
3029227825Stheraven    if (mode & consume_header)
3030227825Stheraven    {
3031227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3032227825Stheraven            frm_nxt += 2;
3033227825Stheraven    }
3034227825Stheraven    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3035227825Stheraven    {
3036232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3037227825Stheraven        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3038227825Stheraven            return codecvt_base::error;
3039227825Stheraven        *to_nxt = c1;
3040227825Stheraven        frm_nxt += 2;
3041227825Stheraven    }
3042227825Stheraven    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3043227825Stheraven}
3044227825Stheraven
3045227825Stheravenstatic
3046227825Stheravenint
3047227825Stheravenutf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3048227825Stheraven                       size_t mx, unsigned long Maxcode = 0x10FFFF,
3049227825Stheraven                       codecvt_mode mode = codecvt_mode(0))
3050227825Stheraven{
3051227825Stheraven    const uint8_t* frm_nxt = frm;
3052227825Stheraven    frm_nxt = frm;
3053227825Stheraven    if (mode & consume_header)
3054227825Stheraven    {
3055227825Stheraven        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3056227825Stheraven            frm_nxt += 2;
3057227825Stheraven    }
3058227825Stheraven    for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3059227825Stheraven    {
3060232950Stheraven        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3061227825Stheraven        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3062227825Stheraven            break;
3063227825Stheraven        frm_nxt += 2;
3064227825Stheraven    }
3065227825Stheraven    return static_cast<int>(frm_nxt - frm);
3066227825Stheraven}
3067227825Stheraven
3068227825Stheraven// template <> class codecvt<char16_t, char, mbstate_t>
3069227825Stheraven
3070227825Stheravenlocale::id codecvt<char16_t, char, mbstate_t>::id;
3071227825Stheraven
3072227825Stheravencodecvt<char16_t, char, mbstate_t>::~codecvt()
3073227825Stheraven{
3074227825Stheraven}
3075227825Stheraven
3076227825Stheravencodecvt<char16_t, char, mbstate_t>::result
3077227825Stheravencodecvt<char16_t, char, mbstate_t>::do_out(state_type&,
3078227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3079227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3080227825Stheraven{
3081227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3082227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3083227825Stheraven    const uint16_t* _frm_nxt = _frm;
3084227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3085227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3086227825Stheraven    uint8_t* _to_nxt = _to;
3087227825Stheraven    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3088227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3089227825Stheraven    to_nxt = to + (_to_nxt - _to);
3090227825Stheraven    return r;
3091227825Stheraven}
3092227825Stheraven
3093227825Stheravencodecvt<char16_t, char, mbstate_t>::result
3094227825Stheravencodecvt<char16_t, char, mbstate_t>::do_in(state_type&,
3095227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3096227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3097227825Stheraven{
3098227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3099227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3100227825Stheraven    const uint8_t* _frm_nxt = _frm;
3101227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3102227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3103227825Stheraven    uint16_t* _to_nxt = _to;
3104227825Stheraven    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3105227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3106227825Stheraven    to_nxt = to + (_to_nxt - _to);
3107227825Stheraven    return r;
3108227825Stheraven}
3109227825Stheraven
3110227825Stheravencodecvt<char16_t, char, mbstate_t>::result
3111227825Stheravencodecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3112227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3113227825Stheraven{
3114227825Stheraven    to_nxt = to;
3115227825Stheraven    return noconv;
3116227825Stheraven}
3117227825Stheraven
3118227825Stheravenint
3119227825Stheravencodecvt<char16_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
3120227825Stheraven{
3121227825Stheraven    return 0;
3122227825Stheraven}
3123227825Stheraven
3124227825Stheravenbool
3125227825Stheravencodecvt<char16_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
3126227825Stheraven{
3127227825Stheraven    return false;
3128227825Stheraven}
3129227825Stheraven
3130227825Stheravenint
3131227825Stheravencodecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3132227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3133227825Stheraven{
3134227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3135227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3136227825Stheraven    return utf8_to_utf16_length(_frm, _frm_end, mx);
3137227825Stheraven}
3138227825Stheraven
3139227825Stheravenint
3140227825Stheravencodecvt<char16_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
3141227825Stheraven{
3142227825Stheraven    return 4;
3143227825Stheraven}
3144227825Stheraven
3145227825Stheraven// template <> class codecvt<char32_t, char, mbstate_t>
3146227825Stheraven
3147227825Stheravenlocale::id codecvt<char32_t, char, mbstate_t>::id;
3148227825Stheraven
3149227825Stheravencodecvt<char32_t, char, mbstate_t>::~codecvt()
3150227825Stheraven{
3151227825Stheraven}
3152227825Stheraven
3153227825Stheravencodecvt<char32_t, char, mbstate_t>::result
3154227825Stheravencodecvt<char32_t, char, mbstate_t>::do_out(state_type&,
3155227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3156227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3157227825Stheraven{
3158227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3159227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3160227825Stheraven    const uint32_t* _frm_nxt = _frm;
3161227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3162227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3163227825Stheraven    uint8_t* _to_nxt = _to;
3164227825Stheraven    result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3165227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3166227825Stheraven    to_nxt = to + (_to_nxt - _to);
3167227825Stheraven    return r;
3168227825Stheraven}
3169227825Stheraven
3170227825Stheravencodecvt<char32_t, char, mbstate_t>::result
3171227825Stheravencodecvt<char32_t, char, mbstate_t>::do_in(state_type&,
3172227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3173227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3174227825Stheraven{
3175227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3176227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3177227825Stheraven    const uint8_t* _frm_nxt = _frm;
3178227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3179227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3180227825Stheraven    uint32_t* _to_nxt = _to;
3181227825Stheraven    result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3182227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3183227825Stheraven    to_nxt = to + (_to_nxt - _to);
3184227825Stheraven    return r;
3185227825Stheraven}
3186227825Stheraven
3187227825Stheravencodecvt<char32_t, char, mbstate_t>::result
3188227825Stheravencodecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3189227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3190227825Stheraven{
3191227825Stheraven    to_nxt = to;
3192227825Stheraven    return noconv;
3193227825Stheraven}
3194227825Stheraven
3195227825Stheravenint
3196227825Stheravencodecvt<char32_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
3197227825Stheraven{
3198227825Stheraven    return 0;
3199227825Stheraven}
3200227825Stheraven
3201227825Stheravenbool
3202227825Stheravencodecvt<char32_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
3203227825Stheraven{
3204227825Stheraven    return false;
3205227825Stheraven}
3206227825Stheraven
3207227825Stheravenint
3208227825Stheravencodecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3209227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3210227825Stheraven{
3211227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3212227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3213227825Stheraven    return utf8_to_ucs4_length(_frm, _frm_end, mx);
3214227825Stheraven}
3215227825Stheraven
3216227825Stheravenint
3217227825Stheravencodecvt<char32_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
3218227825Stheraven{
3219227825Stheraven    return 4;
3220227825Stheraven}
3221227825Stheraven
3222227825Stheraven// __codecvt_utf8<wchar_t>
3223227825Stheraven
3224227825Stheraven__codecvt_utf8<wchar_t>::result
3225227825Stheraven__codecvt_utf8<wchar_t>::do_out(state_type&,
3226227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3227227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3228227825Stheraven{
3229262801Sdim#if _WIN32
3230262801Sdim    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3231262801Sdim    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3232262801Sdim    const uint16_t* _frm_nxt = _frm;
3233262801Sdim#else
3234227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3235227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3236227825Stheraven    const uint32_t* _frm_nxt = _frm;
3237262801Sdim#endif
3238227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3239227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3240227825Stheraven    uint8_t* _to_nxt = _to;
3241262801Sdim#if _WIN32
3242262801Sdim    result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3243262801Sdim                            _Maxcode_, _Mode_);
3244262801Sdim#else
3245227825Stheraven    result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3246227825Stheraven                            _Maxcode_, _Mode_);
3247262801Sdim#endif
3248227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3249227825Stheraven    to_nxt = to + (_to_nxt - _to);
3250227825Stheraven    return r;
3251227825Stheraven}
3252227825Stheraven
3253227825Stheraven__codecvt_utf8<wchar_t>::result
3254227825Stheraven__codecvt_utf8<wchar_t>::do_in(state_type&,
3255227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3256227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3257227825Stheraven{
3258227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3259227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3260227825Stheraven    const uint8_t* _frm_nxt = _frm;
3261262801Sdim#if _WIN32
3262262801Sdim    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3263262801Sdim    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3264262801Sdim    uint16_t* _to_nxt = _to;
3265262801Sdim    result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3266262801Sdim                            _Maxcode_, _Mode_);
3267262801Sdim#else
3268227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3269227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3270227825Stheraven    uint32_t* _to_nxt = _to;
3271227825Stheraven    result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3272227825Stheraven                            _Maxcode_, _Mode_);
3273262801Sdim#endif
3274227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3275227825Stheraven    to_nxt = to + (_to_nxt - _to);
3276227825Stheraven    return r;
3277227825Stheraven}
3278227825Stheraven
3279227825Stheraven__codecvt_utf8<wchar_t>::result
3280227825Stheraven__codecvt_utf8<wchar_t>::do_unshift(state_type&,
3281227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3282227825Stheraven{
3283227825Stheraven    to_nxt = to;
3284227825Stheraven    return noconv;
3285227825Stheraven}
3286227825Stheraven
3287227825Stheravenint
3288227825Stheraven__codecvt_utf8<wchar_t>::do_encoding() const  _NOEXCEPT
3289227825Stheraven{
3290227825Stheraven    return 0;
3291227825Stheraven}
3292227825Stheraven
3293227825Stheravenbool
3294227825Stheraven__codecvt_utf8<wchar_t>::do_always_noconv() const  _NOEXCEPT
3295227825Stheraven{
3296227825Stheraven    return false;
3297227825Stheraven}
3298227825Stheraven
3299227825Stheravenint
3300227825Stheraven__codecvt_utf8<wchar_t>::do_length(state_type&,
3301227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3302227825Stheraven{
3303227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3304227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3305227825Stheraven    return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3306227825Stheraven}
3307227825Stheraven
3308227825Stheravenint
3309227825Stheraven__codecvt_utf8<wchar_t>::do_max_length() const  _NOEXCEPT
3310227825Stheraven{
3311227825Stheraven    if (_Mode_ & consume_header)
3312227825Stheraven        return 7;
3313227825Stheraven    return 4;
3314227825Stheraven}
3315227825Stheraven
3316227825Stheraven// __codecvt_utf8<char16_t>
3317227825Stheraven
3318227825Stheraven__codecvt_utf8<char16_t>::result
3319227825Stheraven__codecvt_utf8<char16_t>::do_out(state_type&,
3320227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3321227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3322227825Stheraven{
3323227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3324227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3325227825Stheraven    const uint16_t* _frm_nxt = _frm;
3326227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3327227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3328227825Stheraven    uint8_t* _to_nxt = _to;
3329227825Stheraven    result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3330227825Stheraven                            _Maxcode_, _Mode_);
3331227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3332227825Stheraven    to_nxt = to + (_to_nxt - _to);
3333227825Stheraven    return r;
3334227825Stheraven}
3335227825Stheraven
3336227825Stheraven__codecvt_utf8<char16_t>::result
3337227825Stheraven__codecvt_utf8<char16_t>::do_in(state_type&,
3338227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3339227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3340227825Stheraven{
3341227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3342227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3343227825Stheraven    const uint8_t* _frm_nxt = _frm;
3344227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3345227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3346227825Stheraven    uint16_t* _to_nxt = _to;
3347227825Stheraven    result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3348227825Stheraven                            _Maxcode_, _Mode_);
3349227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3350227825Stheraven    to_nxt = to + (_to_nxt - _to);
3351227825Stheraven    return r;
3352227825Stheraven}
3353227825Stheraven
3354227825Stheraven__codecvt_utf8<char16_t>::result
3355227825Stheraven__codecvt_utf8<char16_t>::do_unshift(state_type&,
3356227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3357227825Stheraven{
3358227825Stheraven    to_nxt = to;
3359227825Stheraven    return noconv;
3360227825Stheraven}
3361227825Stheraven
3362227825Stheravenint
3363227825Stheraven__codecvt_utf8<char16_t>::do_encoding() const  _NOEXCEPT
3364227825Stheraven{
3365227825Stheraven    return 0;
3366227825Stheraven}
3367227825Stheraven
3368227825Stheravenbool
3369227825Stheraven__codecvt_utf8<char16_t>::do_always_noconv() const  _NOEXCEPT
3370227825Stheraven{
3371227825Stheraven    return false;
3372227825Stheraven}
3373227825Stheraven
3374227825Stheravenint
3375227825Stheraven__codecvt_utf8<char16_t>::do_length(state_type&,
3376227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3377227825Stheraven{
3378227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3379227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3380227825Stheraven    return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3381227825Stheraven}
3382227825Stheraven
3383227825Stheravenint
3384227825Stheraven__codecvt_utf8<char16_t>::do_max_length() const  _NOEXCEPT
3385227825Stheraven{
3386227825Stheraven    if (_Mode_ & consume_header)
3387227825Stheraven        return 6;
3388227825Stheraven    return 3;
3389227825Stheraven}
3390227825Stheraven
3391227825Stheraven// __codecvt_utf8<char32_t>
3392227825Stheraven
3393227825Stheraven__codecvt_utf8<char32_t>::result
3394227825Stheraven__codecvt_utf8<char32_t>::do_out(state_type&,
3395227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3396227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3397227825Stheraven{
3398227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3399227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3400227825Stheraven    const uint32_t* _frm_nxt = _frm;
3401227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3402227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3403227825Stheraven    uint8_t* _to_nxt = _to;
3404227825Stheraven    result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3405227825Stheraven                            _Maxcode_, _Mode_);
3406227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3407227825Stheraven    to_nxt = to + (_to_nxt - _to);
3408227825Stheraven    return r;
3409227825Stheraven}
3410227825Stheraven
3411227825Stheraven__codecvt_utf8<char32_t>::result
3412227825Stheraven__codecvt_utf8<char32_t>::do_in(state_type&,
3413227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3414227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3415227825Stheraven{
3416227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3417227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3418227825Stheraven    const uint8_t* _frm_nxt = _frm;
3419227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3420227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3421227825Stheraven    uint32_t* _to_nxt = _to;
3422227825Stheraven    result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3423227825Stheraven                            _Maxcode_, _Mode_);
3424227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3425227825Stheraven    to_nxt = to + (_to_nxt - _to);
3426227825Stheraven    return r;
3427227825Stheraven}
3428227825Stheraven
3429227825Stheraven__codecvt_utf8<char32_t>::result
3430227825Stheraven__codecvt_utf8<char32_t>::do_unshift(state_type&,
3431227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3432227825Stheraven{
3433227825Stheraven    to_nxt = to;
3434227825Stheraven    return noconv;
3435227825Stheraven}
3436227825Stheraven
3437227825Stheravenint
3438227825Stheraven__codecvt_utf8<char32_t>::do_encoding() const  _NOEXCEPT
3439227825Stheraven{
3440227825Stheraven    return 0;
3441227825Stheraven}
3442227825Stheraven
3443227825Stheravenbool
3444227825Stheraven__codecvt_utf8<char32_t>::do_always_noconv() const  _NOEXCEPT
3445227825Stheraven{
3446227825Stheraven    return false;
3447227825Stheraven}
3448227825Stheraven
3449227825Stheravenint
3450227825Stheraven__codecvt_utf8<char32_t>::do_length(state_type&,
3451227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3452227825Stheraven{
3453227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3454227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3455227825Stheraven    return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3456227825Stheraven}
3457227825Stheraven
3458227825Stheravenint
3459227825Stheraven__codecvt_utf8<char32_t>::do_max_length() const  _NOEXCEPT
3460227825Stheraven{
3461227825Stheraven    if (_Mode_ & consume_header)
3462227825Stheraven        return 7;
3463227825Stheraven    return 4;
3464227825Stheraven}
3465227825Stheraven
3466227825Stheraven// __codecvt_utf16<wchar_t, false>
3467227825Stheraven
3468227825Stheraven__codecvt_utf16<wchar_t, false>::result
3469227825Stheraven__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3470227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3471227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3472227825Stheraven{
3473227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3474227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3475227825Stheraven    const uint32_t* _frm_nxt = _frm;
3476227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3477227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3478227825Stheraven    uint8_t* _to_nxt = _to;
3479227825Stheraven    result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3480227825Stheraven                               _Maxcode_, _Mode_);
3481227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3482227825Stheraven    to_nxt = to + (_to_nxt - _to);
3483227825Stheraven    return r;
3484227825Stheraven}
3485227825Stheraven
3486227825Stheraven__codecvt_utf16<wchar_t, false>::result
3487227825Stheraven__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3488227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3489227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3490227825Stheraven{
3491227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3492227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3493227825Stheraven    const uint8_t* _frm_nxt = _frm;
3494227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3495227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3496227825Stheraven    uint32_t* _to_nxt = _to;
3497227825Stheraven    result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3498227825Stheraven                               _Maxcode_, _Mode_);
3499227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3500227825Stheraven    to_nxt = to + (_to_nxt - _to);
3501227825Stheraven    return r;
3502227825Stheraven}
3503227825Stheraven
3504227825Stheraven__codecvt_utf16<wchar_t, false>::result
3505227825Stheraven__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3506227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3507227825Stheraven{
3508227825Stheraven    to_nxt = to;
3509227825Stheraven    return noconv;
3510227825Stheraven}
3511227825Stheraven
3512227825Stheravenint
3513227825Stheraven__codecvt_utf16<wchar_t, false>::do_encoding() const  _NOEXCEPT
3514227825Stheraven{
3515227825Stheraven    return 0;
3516227825Stheraven}
3517227825Stheraven
3518227825Stheravenbool
3519227825Stheraven__codecvt_utf16<wchar_t, false>::do_always_noconv() const  _NOEXCEPT
3520227825Stheraven{
3521227825Stheraven    return false;
3522227825Stheraven}
3523227825Stheraven
3524227825Stheravenint
3525227825Stheraven__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3526227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3527227825Stheraven{
3528227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3529227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3530227825Stheraven    return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3531227825Stheraven}
3532227825Stheraven
3533227825Stheravenint
3534227825Stheraven__codecvt_utf16<wchar_t, false>::do_max_length() const  _NOEXCEPT
3535227825Stheraven{
3536227825Stheraven    if (_Mode_ & consume_header)
3537227825Stheraven        return 6;
3538227825Stheraven    return 4;
3539227825Stheraven}
3540227825Stheraven
3541227825Stheraven// __codecvt_utf16<wchar_t, true>
3542227825Stheraven
3543227825Stheraven__codecvt_utf16<wchar_t, true>::result
3544227825Stheraven__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3545227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3546227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3547227825Stheraven{
3548227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3549227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3550227825Stheraven    const uint32_t* _frm_nxt = _frm;
3551227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3552227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3553227825Stheraven    uint8_t* _to_nxt = _to;
3554227825Stheraven    result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3555227825Stheraven                               _Maxcode_, _Mode_);
3556227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3557227825Stheraven    to_nxt = to + (_to_nxt - _to);
3558227825Stheraven    return r;
3559227825Stheraven}
3560227825Stheraven
3561227825Stheraven__codecvt_utf16<wchar_t, true>::result
3562227825Stheraven__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3563227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3564227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3565227825Stheraven{
3566227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3567227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3568227825Stheraven    const uint8_t* _frm_nxt = _frm;
3569227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3570227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3571227825Stheraven    uint32_t* _to_nxt = _to;
3572227825Stheraven    result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3573227825Stheraven                               _Maxcode_, _Mode_);
3574227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3575227825Stheraven    to_nxt = to + (_to_nxt - _to);
3576227825Stheraven    return r;
3577227825Stheraven}
3578227825Stheraven
3579227825Stheraven__codecvt_utf16<wchar_t, true>::result
3580227825Stheraven__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3581227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3582227825Stheraven{
3583227825Stheraven    to_nxt = to;
3584227825Stheraven    return noconv;
3585227825Stheraven}
3586227825Stheraven
3587227825Stheravenint
3588227825Stheraven__codecvt_utf16<wchar_t, true>::do_encoding() const  _NOEXCEPT
3589227825Stheraven{
3590227825Stheraven    return 0;
3591227825Stheraven}
3592227825Stheraven
3593227825Stheravenbool
3594227825Stheraven__codecvt_utf16<wchar_t, true>::do_always_noconv() const  _NOEXCEPT
3595227825Stheraven{
3596227825Stheraven    return false;
3597227825Stheraven}
3598227825Stheraven
3599227825Stheravenint
3600227825Stheraven__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3601227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3602227825Stheraven{
3603227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3604227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3605227825Stheraven    return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3606227825Stheraven}
3607227825Stheraven
3608227825Stheravenint
3609227825Stheraven__codecvt_utf16<wchar_t, true>::do_max_length() const  _NOEXCEPT
3610227825Stheraven{
3611227825Stheraven    if (_Mode_ & consume_header)
3612227825Stheraven        return 6;
3613227825Stheraven    return 4;
3614227825Stheraven}
3615227825Stheraven
3616227825Stheraven// __codecvt_utf16<char16_t, false>
3617227825Stheraven
3618227825Stheraven__codecvt_utf16<char16_t, false>::result
3619227825Stheraven__codecvt_utf16<char16_t, false>::do_out(state_type&,
3620227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3621227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3622227825Stheraven{
3623227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3624227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3625227825Stheraven    const uint16_t* _frm_nxt = _frm;
3626227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3627227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3628227825Stheraven    uint8_t* _to_nxt = _to;
3629227825Stheraven    result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3630227825Stheraven                               _Maxcode_, _Mode_);
3631227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3632227825Stheraven    to_nxt = to + (_to_nxt - _to);
3633227825Stheraven    return r;
3634227825Stheraven}
3635227825Stheraven
3636227825Stheraven__codecvt_utf16<char16_t, false>::result
3637227825Stheraven__codecvt_utf16<char16_t, false>::do_in(state_type&,
3638227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3639227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3640227825Stheraven{
3641227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3642227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3643227825Stheraven    const uint8_t* _frm_nxt = _frm;
3644227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3645227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3646227825Stheraven    uint16_t* _to_nxt = _to;
3647227825Stheraven    result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3648227825Stheraven                               _Maxcode_, _Mode_);
3649227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3650227825Stheraven    to_nxt = to + (_to_nxt - _to);
3651227825Stheraven    return r;
3652227825Stheraven}
3653227825Stheraven
3654227825Stheraven__codecvt_utf16<char16_t, false>::result
3655227825Stheraven__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3656227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3657227825Stheraven{
3658227825Stheraven    to_nxt = to;
3659227825Stheraven    return noconv;
3660227825Stheraven}
3661227825Stheraven
3662227825Stheravenint
3663227825Stheraven__codecvt_utf16<char16_t, false>::do_encoding() const  _NOEXCEPT
3664227825Stheraven{
3665227825Stheraven    return 0;
3666227825Stheraven}
3667227825Stheraven
3668227825Stheravenbool
3669227825Stheraven__codecvt_utf16<char16_t, false>::do_always_noconv() const  _NOEXCEPT
3670227825Stheraven{
3671227825Stheraven    return false;
3672227825Stheraven}
3673227825Stheraven
3674227825Stheravenint
3675227825Stheraven__codecvt_utf16<char16_t, false>::do_length(state_type&,
3676227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3677227825Stheraven{
3678227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3679227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3680227825Stheraven    return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3681227825Stheraven}
3682227825Stheraven
3683227825Stheravenint
3684227825Stheraven__codecvt_utf16<char16_t, false>::do_max_length() const  _NOEXCEPT
3685227825Stheraven{
3686227825Stheraven    if (_Mode_ & consume_header)
3687227825Stheraven        return 4;
3688227825Stheraven    return 2;
3689227825Stheraven}
3690227825Stheraven
3691227825Stheraven// __codecvt_utf16<char16_t, true>
3692227825Stheraven
3693227825Stheraven__codecvt_utf16<char16_t, true>::result
3694227825Stheraven__codecvt_utf16<char16_t, true>::do_out(state_type&,
3695227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3696227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3697227825Stheraven{
3698227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3699227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3700227825Stheraven    const uint16_t* _frm_nxt = _frm;
3701227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3702227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3703227825Stheraven    uint8_t* _to_nxt = _to;
3704227825Stheraven    result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3705227825Stheraven                               _Maxcode_, _Mode_);
3706227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3707227825Stheraven    to_nxt = to + (_to_nxt - _to);
3708227825Stheraven    return r;
3709227825Stheraven}
3710227825Stheraven
3711227825Stheraven__codecvt_utf16<char16_t, true>::result
3712227825Stheraven__codecvt_utf16<char16_t, true>::do_in(state_type&,
3713227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3714227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3715227825Stheraven{
3716227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3717227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3718227825Stheraven    const uint8_t* _frm_nxt = _frm;
3719227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3720227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3721227825Stheraven    uint16_t* _to_nxt = _to;
3722227825Stheraven    result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3723227825Stheraven                               _Maxcode_, _Mode_);
3724227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3725227825Stheraven    to_nxt = to + (_to_nxt - _to);
3726227825Stheraven    return r;
3727227825Stheraven}
3728227825Stheraven
3729227825Stheraven__codecvt_utf16<char16_t, true>::result
3730227825Stheraven__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3731227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3732227825Stheraven{
3733227825Stheraven    to_nxt = to;
3734227825Stheraven    return noconv;
3735227825Stheraven}
3736227825Stheraven
3737227825Stheravenint
3738227825Stheraven__codecvt_utf16<char16_t, true>::do_encoding() const  _NOEXCEPT
3739227825Stheraven{
3740227825Stheraven    return 0;
3741227825Stheraven}
3742227825Stheraven
3743227825Stheravenbool
3744227825Stheraven__codecvt_utf16<char16_t, true>::do_always_noconv() const  _NOEXCEPT
3745227825Stheraven{
3746227825Stheraven    return false;
3747227825Stheraven}
3748227825Stheraven
3749227825Stheravenint
3750227825Stheraven__codecvt_utf16<char16_t, true>::do_length(state_type&,
3751227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3752227825Stheraven{
3753227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3754227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3755227825Stheraven    return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3756227825Stheraven}
3757227825Stheraven
3758227825Stheravenint
3759227825Stheraven__codecvt_utf16<char16_t, true>::do_max_length() const  _NOEXCEPT
3760227825Stheraven{
3761227825Stheraven    if (_Mode_ & consume_header)
3762227825Stheraven        return 4;
3763227825Stheraven    return 2;
3764227825Stheraven}
3765227825Stheraven
3766227825Stheraven// __codecvt_utf16<char32_t, false>
3767227825Stheraven
3768227825Stheraven__codecvt_utf16<char32_t, false>::result
3769227825Stheraven__codecvt_utf16<char32_t, false>::do_out(state_type&,
3770227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3771227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3772227825Stheraven{
3773227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3774227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3775227825Stheraven    const uint32_t* _frm_nxt = _frm;
3776227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3777227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3778227825Stheraven    uint8_t* _to_nxt = _to;
3779227825Stheraven    result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3780227825Stheraven                               _Maxcode_, _Mode_);
3781227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3782227825Stheraven    to_nxt = to + (_to_nxt - _to);
3783227825Stheraven    return r;
3784227825Stheraven}
3785227825Stheraven
3786227825Stheraven__codecvt_utf16<char32_t, false>::result
3787227825Stheraven__codecvt_utf16<char32_t, false>::do_in(state_type&,
3788227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3789227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3790227825Stheraven{
3791227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3792227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3793227825Stheraven    const uint8_t* _frm_nxt = _frm;
3794227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3795227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3796227825Stheraven    uint32_t* _to_nxt = _to;
3797227825Stheraven    result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3798227825Stheraven                               _Maxcode_, _Mode_);
3799227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3800227825Stheraven    to_nxt = to + (_to_nxt - _to);
3801227825Stheraven    return r;
3802227825Stheraven}
3803227825Stheraven
3804227825Stheraven__codecvt_utf16<char32_t, false>::result
3805227825Stheraven__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3806227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3807227825Stheraven{
3808227825Stheraven    to_nxt = to;
3809227825Stheraven    return noconv;
3810227825Stheraven}
3811227825Stheraven
3812227825Stheravenint
3813227825Stheraven__codecvt_utf16<char32_t, false>::do_encoding() const  _NOEXCEPT
3814227825Stheraven{
3815227825Stheraven    return 0;
3816227825Stheraven}
3817227825Stheraven
3818227825Stheravenbool
3819227825Stheraven__codecvt_utf16<char32_t, false>::do_always_noconv() const  _NOEXCEPT
3820227825Stheraven{
3821227825Stheraven    return false;
3822227825Stheraven}
3823227825Stheraven
3824227825Stheravenint
3825227825Stheraven__codecvt_utf16<char32_t, false>::do_length(state_type&,
3826227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3827227825Stheraven{
3828227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3829227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3830227825Stheraven    return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3831227825Stheraven}
3832227825Stheraven
3833227825Stheravenint
3834227825Stheraven__codecvt_utf16<char32_t, false>::do_max_length() const  _NOEXCEPT
3835227825Stheraven{
3836227825Stheraven    if (_Mode_ & consume_header)
3837227825Stheraven        return 6;
3838227825Stheraven    return 4;
3839227825Stheraven}
3840227825Stheraven
3841227825Stheraven// __codecvt_utf16<char32_t, true>
3842227825Stheraven
3843227825Stheraven__codecvt_utf16<char32_t, true>::result
3844227825Stheraven__codecvt_utf16<char32_t, true>::do_out(state_type&,
3845227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3846227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3847227825Stheraven{
3848227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3849227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3850227825Stheraven    const uint32_t* _frm_nxt = _frm;
3851227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3852227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3853227825Stheraven    uint8_t* _to_nxt = _to;
3854227825Stheraven    result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3855227825Stheraven                               _Maxcode_, _Mode_);
3856227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3857227825Stheraven    to_nxt = to + (_to_nxt - _to);
3858227825Stheraven    return r;
3859227825Stheraven}
3860227825Stheraven
3861227825Stheraven__codecvt_utf16<char32_t, true>::result
3862227825Stheraven__codecvt_utf16<char32_t, true>::do_in(state_type&,
3863227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3864227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3865227825Stheraven{
3866227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3867227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3868227825Stheraven    const uint8_t* _frm_nxt = _frm;
3869227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3870227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3871227825Stheraven    uint32_t* _to_nxt = _to;
3872227825Stheraven    result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3873227825Stheraven                               _Maxcode_, _Mode_);
3874227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3875227825Stheraven    to_nxt = to + (_to_nxt - _to);
3876227825Stheraven    return r;
3877227825Stheraven}
3878227825Stheraven
3879227825Stheraven__codecvt_utf16<char32_t, true>::result
3880227825Stheraven__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3881227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3882227825Stheraven{
3883227825Stheraven    to_nxt = to;
3884227825Stheraven    return noconv;
3885227825Stheraven}
3886227825Stheraven
3887227825Stheravenint
3888227825Stheraven__codecvt_utf16<char32_t, true>::do_encoding() const  _NOEXCEPT
3889227825Stheraven{
3890227825Stheraven    return 0;
3891227825Stheraven}
3892227825Stheraven
3893227825Stheravenbool
3894227825Stheraven__codecvt_utf16<char32_t, true>::do_always_noconv() const  _NOEXCEPT
3895227825Stheraven{
3896227825Stheraven    return false;
3897227825Stheraven}
3898227825Stheraven
3899227825Stheravenint
3900227825Stheraven__codecvt_utf16<char32_t, true>::do_length(state_type&,
3901227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3902227825Stheraven{
3903227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3904227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3905227825Stheraven    return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3906227825Stheraven}
3907227825Stheraven
3908227825Stheravenint
3909227825Stheraven__codecvt_utf16<char32_t, true>::do_max_length() const  _NOEXCEPT
3910227825Stheraven{
3911227825Stheraven    if (_Mode_ & consume_header)
3912227825Stheraven        return 6;
3913227825Stheraven    return 4;
3914227825Stheraven}
3915227825Stheraven
3916227825Stheraven// __codecvt_utf8_utf16<wchar_t>
3917227825Stheraven
3918227825Stheraven__codecvt_utf8_utf16<wchar_t>::result
3919227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3920227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3921227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3922227825Stheraven{
3923227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3924227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3925227825Stheraven    const uint32_t* _frm_nxt = _frm;
3926227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3927227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3928227825Stheraven    uint8_t* _to_nxt = _to;
3929227825Stheraven    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3930227825Stheraven                             _Maxcode_, _Mode_);
3931227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3932227825Stheraven    to_nxt = to + (_to_nxt - _to);
3933227825Stheraven    return r;
3934227825Stheraven}
3935227825Stheraven
3936227825Stheraven__codecvt_utf8_utf16<wchar_t>::result
3937227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3938227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3939227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3940227825Stheraven{
3941227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3942227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3943227825Stheraven    const uint8_t* _frm_nxt = _frm;
3944227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3945227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3946227825Stheraven    uint32_t* _to_nxt = _to;
3947227825Stheraven    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3948227825Stheraven                             _Maxcode_, _Mode_);
3949227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
3950227825Stheraven    to_nxt = to + (_to_nxt - _to);
3951227825Stheraven    return r;
3952227825Stheraven}
3953227825Stheraven
3954227825Stheraven__codecvt_utf8_utf16<wchar_t>::result
3955227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3956227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
3957227825Stheraven{
3958227825Stheraven    to_nxt = to;
3959227825Stheraven    return noconv;
3960227825Stheraven}
3961227825Stheraven
3962227825Stheravenint
3963227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_encoding() const  _NOEXCEPT
3964227825Stheraven{
3965227825Stheraven    return 0;
3966227825Stheraven}
3967227825Stheraven
3968227825Stheravenbool
3969227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const  _NOEXCEPT
3970227825Stheraven{
3971227825Stheraven    return false;
3972227825Stheraven}
3973227825Stheraven
3974227825Stheravenint
3975227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3976227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
3977227825Stheraven{
3978227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3979227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3980227825Stheraven    return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3981227825Stheraven}
3982227825Stheraven
3983227825Stheravenint
3984227825Stheraven__codecvt_utf8_utf16<wchar_t>::do_max_length() const  _NOEXCEPT
3985227825Stheraven{
3986227825Stheraven    if (_Mode_ & consume_header)
3987227825Stheraven        return 7;
3988227825Stheraven    return 4;
3989227825Stheraven}
3990227825Stheraven
3991227825Stheraven// __codecvt_utf8_utf16<char16_t>
3992227825Stheraven
3993227825Stheraven__codecvt_utf8_utf16<char16_t>::result
3994227825Stheraven__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3995227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3996227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3997227825Stheraven{
3998227825Stheraven    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3999227825Stheraven    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4000227825Stheraven    const uint16_t* _frm_nxt = _frm;
4001227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4002227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4003227825Stheraven    uint8_t* _to_nxt = _to;
4004227825Stheraven    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4005227825Stheraven                             _Maxcode_, _Mode_);
4006227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
4007227825Stheraven    to_nxt = to + (_to_nxt - _to);
4008227825Stheraven    return r;
4009227825Stheraven}
4010227825Stheraven
4011227825Stheraven__codecvt_utf8_utf16<char16_t>::result
4012227825Stheraven__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4013227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4014227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4015227825Stheraven{
4016227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4017227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4018227825Stheraven    const uint8_t* _frm_nxt = _frm;
4019227825Stheraven    uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4020227825Stheraven    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4021227825Stheraven    uint16_t* _to_nxt = _to;
4022227825Stheraven    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4023227825Stheraven                             _Maxcode_, _Mode_);
4024227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
4025227825Stheraven    to_nxt = to + (_to_nxt - _to);
4026227825Stheraven    return r;
4027227825Stheraven}
4028227825Stheraven
4029227825Stheraven__codecvt_utf8_utf16<char16_t>::result
4030227825Stheraven__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4031227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
4032227825Stheraven{
4033227825Stheraven    to_nxt = to;
4034227825Stheraven    return noconv;
4035227825Stheraven}
4036227825Stheraven
4037227825Stheravenint
4038227825Stheraven__codecvt_utf8_utf16<char16_t>::do_encoding() const  _NOEXCEPT
4039227825Stheraven{
4040227825Stheraven    return 0;
4041227825Stheraven}
4042227825Stheraven
4043227825Stheravenbool
4044227825Stheraven__codecvt_utf8_utf16<char16_t>::do_always_noconv() const  _NOEXCEPT
4045227825Stheraven{
4046227825Stheraven    return false;
4047227825Stheraven}
4048227825Stheraven
4049227825Stheravenint
4050227825Stheraven__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4051227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
4052227825Stheraven{
4053227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4054227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4055227825Stheraven    return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4056227825Stheraven}
4057227825Stheraven
4058227825Stheravenint
4059227825Stheraven__codecvt_utf8_utf16<char16_t>::do_max_length() const  _NOEXCEPT
4060227825Stheraven{
4061227825Stheraven    if (_Mode_ & consume_header)
4062227825Stheraven        return 7;
4063227825Stheraven    return 4;
4064227825Stheraven}
4065227825Stheraven
4066227825Stheraven// __codecvt_utf8_utf16<char32_t>
4067227825Stheraven
4068227825Stheraven__codecvt_utf8_utf16<char32_t>::result
4069227825Stheraven__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4070227825Stheraven    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4071227825Stheraven    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4072227825Stheraven{
4073227825Stheraven    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4074227825Stheraven    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4075227825Stheraven    const uint32_t* _frm_nxt = _frm;
4076227825Stheraven    uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4077227825Stheraven    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4078227825Stheraven    uint8_t* _to_nxt = _to;
4079227825Stheraven    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4080227825Stheraven                             _Maxcode_, _Mode_);
4081227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
4082227825Stheraven    to_nxt = to + (_to_nxt - _to);
4083227825Stheraven    return r;
4084227825Stheraven}
4085227825Stheraven
4086227825Stheraven__codecvt_utf8_utf16<char32_t>::result
4087227825Stheraven__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4088227825Stheraven    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4089227825Stheraven    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4090227825Stheraven{
4091227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4092227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4093227825Stheraven    const uint8_t* _frm_nxt = _frm;
4094227825Stheraven    uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4095227825Stheraven    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4096227825Stheraven    uint32_t* _to_nxt = _to;
4097227825Stheraven    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4098227825Stheraven                             _Maxcode_, _Mode_);
4099227825Stheraven    frm_nxt = frm + (_frm_nxt - _frm);
4100227825Stheraven    to_nxt = to + (_to_nxt - _to);
4101227825Stheraven    return r;
4102227825Stheraven}
4103227825Stheraven
4104227825Stheraven__codecvt_utf8_utf16<char32_t>::result
4105227825Stheraven__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4106227825Stheraven    extern_type* to, extern_type*, extern_type*& to_nxt) const
4107227825Stheraven{
4108227825Stheraven    to_nxt = to;
4109227825Stheraven    return noconv;
4110227825Stheraven}
4111227825Stheraven
4112227825Stheravenint
4113227825Stheraven__codecvt_utf8_utf16<char32_t>::do_encoding() const  _NOEXCEPT
4114227825Stheraven{
4115227825Stheraven    return 0;
4116227825Stheraven}
4117227825Stheraven
4118227825Stheravenbool
4119227825Stheraven__codecvt_utf8_utf16<char32_t>::do_always_noconv() const  _NOEXCEPT
4120227825Stheraven{
4121227825Stheraven    return false;
4122227825Stheraven}
4123227825Stheraven
4124227825Stheravenint
4125227825Stheraven__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4126227825Stheraven    const extern_type* frm, const extern_type* frm_end, size_t mx) const
4127227825Stheraven{
4128227825Stheraven    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4129227825Stheraven    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4130227825Stheraven    return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4131227825Stheraven}
4132227825Stheraven
4133227825Stheravenint
4134227825Stheraven__codecvt_utf8_utf16<char32_t>::do_max_length() const  _NOEXCEPT
4135227825Stheraven{
4136227825Stheraven    if (_Mode_ & consume_header)
4137227825Stheraven        return 7;
4138227825Stheraven    return 4;
4139227825Stheraven}
4140227825Stheraven
4141227825Stheraven// __narrow_to_utf8<16>
4142227825Stheraven
4143227825Stheraven__narrow_to_utf8<16>::~__narrow_to_utf8()
4144227825Stheraven{
4145227825Stheraven}
4146227825Stheraven
4147227825Stheraven// __narrow_to_utf8<32>
4148227825Stheraven
4149227825Stheraven__narrow_to_utf8<32>::~__narrow_to_utf8()
4150227825Stheraven{
4151227825Stheraven}
4152227825Stheraven
4153227825Stheraven// __widen_from_utf8<16>
4154227825Stheraven
4155227825Stheraven__widen_from_utf8<16>::~__widen_from_utf8()
4156227825Stheraven{
4157227825Stheraven}
4158227825Stheraven
4159227825Stheraven// __widen_from_utf8<32>
4160227825Stheraven
4161227825Stheraven__widen_from_utf8<32>::~__widen_from_utf8()
4162227825Stheraven{
4163227825Stheraven}
4164227825Stheraven
4165227825Stheraven// numpunct<char> && numpunct<wchar_t>
4166227825Stheraven
4167227825Stheravenlocale::id numpunct< char  >::id;
4168227825Stheravenlocale::id numpunct<wchar_t>::id;
4169227825Stheraven
4170227825Stheravennumpunct<char>::numpunct(size_t refs)
4171227825Stheraven    : locale::facet(refs),
4172227825Stheraven      __decimal_point_('.'),
4173227825Stheraven      __thousands_sep_(',')
4174227825Stheraven{
4175227825Stheraven}
4176227825Stheraven
4177227825Stheravennumpunct<wchar_t>::numpunct(size_t refs)
4178227825Stheraven    : locale::facet(refs),
4179227825Stheraven      __decimal_point_(L'.'),
4180227825Stheraven      __thousands_sep_(L',')
4181227825Stheraven{
4182227825Stheraven}
4183227825Stheraven
4184227825Stheravennumpunct<char>::~numpunct()
4185227825Stheraven{
4186227825Stheraven}
4187227825Stheraven
4188227825Stheravennumpunct<wchar_t>::~numpunct()
4189227825Stheraven{
4190227825Stheraven}
4191227825Stheraven
4192227825Stheraven char   numpunct< char  >::do_decimal_point() const {return __decimal_point_;}
4193227825Stheravenwchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4194227825Stheraven
4195227825Stheraven char   numpunct< char  >::do_thousands_sep() const {return __thousands_sep_;}
4196227825Stheravenwchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4197227825Stheraven
4198227825Stheravenstring numpunct< char  >::do_grouping() const {return __grouping_;}
4199227825Stheravenstring numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4200227825Stheraven
4201227825Stheraven string numpunct< char  >::do_truename() const {return "true";}
4202227825Stheravenwstring numpunct<wchar_t>::do_truename() const {return L"true";}
4203227825Stheraven
4204227825Stheraven string numpunct< char  >::do_falsename() const {return "false";}
4205227825Stheravenwstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4206227825Stheraven
4207227825Stheraven// numpunct_byname<char>
4208227825Stheraven
4209227825Stheravennumpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4210227825Stheraven    : numpunct<char>(refs)
4211227825Stheraven{
4212227825Stheraven    __init(nm);
4213227825Stheraven}
4214227825Stheraven
4215227825Stheravennumpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4216227825Stheraven    : numpunct<char>(refs)
4217227825Stheraven{
4218227825Stheraven    __init(nm.c_str());
4219227825Stheraven}
4220227825Stheraven
4221227825Stheravennumpunct_byname<char>::~numpunct_byname()
4222227825Stheraven{
4223227825Stheraven}
4224227825Stheraven
4225227825Stheravenvoid
4226227825Stheravennumpunct_byname<char>::__init(const char* nm)
4227227825Stheraven{
4228227825Stheraven    if (strcmp(nm, "C") != 0)
4229227825Stheraven    {
4230227825Stheraven        __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
4231227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
4232232950Stheraven        if (loc == nullptr)
4233227825Stheraven            throw runtime_error("numpunct_byname<char>::numpunct_byname"
4234227825Stheraven                                " failed to construct for " + string(nm));
4235227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
4236227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
4237227825Stheraven        lconv* lc = localeconv_l(loc.get());
4238227825Stheraven#else
4239227825Stheraven        lconv* lc = __localeconv_l(loc.get());
4240227825Stheraven#endif
4241227825Stheraven        if (*lc->decimal_point)
4242227825Stheraven            __decimal_point_ = *lc->decimal_point;
4243227825Stheraven        if (*lc->thousands_sep)
4244227825Stheraven            __thousands_sep_ = *lc->thousands_sep;
4245227825Stheraven        __grouping_ = lc->grouping;
4246227825Stheraven        // localization for truename and falsename is not available
4247227825Stheraven    }
4248227825Stheraven}
4249227825Stheraven
4250227825Stheraven// numpunct_byname<wchar_t>
4251227825Stheraven
4252227825Stheravennumpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4253227825Stheraven    : numpunct<wchar_t>(refs)
4254227825Stheraven{
4255227825Stheraven    __init(nm);
4256227825Stheraven}
4257227825Stheraven
4258227825Stheravennumpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4259227825Stheraven    : numpunct<wchar_t>(refs)
4260227825Stheraven{
4261227825Stheraven    __init(nm.c_str());
4262227825Stheraven}
4263227825Stheraven
4264227825Stheravennumpunct_byname<wchar_t>::~numpunct_byname()
4265227825Stheraven{
4266227825Stheraven}
4267227825Stheraven
4268227825Stheravenvoid
4269227825Stheravennumpunct_byname<wchar_t>::__init(const char* nm)
4270227825Stheraven{
4271227825Stheraven    if (strcmp(nm, "C") != 0)
4272227825Stheraven    {
4273227825Stheraven        __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
4274227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
4275232950Stheraven        if (loc == nullptr)
4276227825Stheraven            throw runtime_error("numpunct_byname<char>::numpunct_byname"
4277227825Stheraven                                " failed to construct for " + string(nm));
4278227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
4279227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
4280227825Stheraven        lconv* lc = localeconv_l(loc.get());
4281227825Stheraven#else
4282227825Stheraven        lconv* lc = __localeconv_l(loc.get());
4283227825Stheraven#endif
4284227825Stheraven        if (*lc->decimal_point)
4285227825Stheraven            __decimal_point_ = *lc->decimal_point;
4286227825Stheraven        if (*lc->thousands_sep)
4287227825Stheraven            __thousands_sep_ = *lc->thousands_sep;
4288227825Stheraven        __grouping_ = lc->grouping;
4289227825Stheraven        // locallization for truename and falsename is not available
4290227825Stheraven    }
4291227825Stheraven}
4292227825Stheraven
4293227825Stheraven// num_get helpers
4294227825Stheraven
4295227825Stheravenint
4296227825Stheraven__num_get_base::__get_base(ios_base& iob)
4297227825Stheraven{
4298227825Stheraven    ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4299227825Stheraven    if (__basefield == ios_base::oct)
4300227825Stheraven        return 8;
4301227825Stheraven    else if (__basefield == ios_base::hex)
4302227825Stheraven        return 16;
4303227825Stheraven    else if (__basefield == 0)
4304227825Stheraven        return 0;
4305227825Stheraven    return 10;
4306227825Stheraven}
4307227825Stheraven
4308227825Stheravenconst char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4309227825Stheraven
4310227825Stheravenvoid
4311227825Stheraven__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4312227825Stheraven                 ios_base::iostate& __err)
4313227825Stheraven{
4314227825Stheraven    if (__grouping.size() != 0)
4315227825Stheraven    {
4316227825Stheraven        reverse(__g, __g_end);
4317227825Stheraven        const char* __ig = __grouping.data();
4318227825Stheraven        const char* __eg = __ig + __grouping.size();
4319227825Stheraven        for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4320227825Stheraven        {
4321227825Stheraven            if (0 < *__ig && *__ig < numeric_limits<char>::max())
4322227825Stheraven            {
4323232950Stheraven                if (static_cast<unsigned>(*__ig) != *__r)
4324227825Stheraven                {
4325227825Stheraven                    __err = ios_base::failbit;
4326227825Stheraven                    return;
4327227825Stheraven                }
4328227825Stheraven            }
4329227825Stheraven            if (__eg - __ig > 1)
4330227825Stheraven                ++__ig;
4331227825Stheraven        }
4332227825Stheraven        if (0 < *__ig && *__ig < numeric_limits<char>::max())
4333227825Stheraven        {
4334232950Stheraven            if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
4335227825Stheraven                __err = ios_base::failbit;
4336227825Stheraven        }
4337227825Stheraven    }
4338227825Stheraven}
4339227825Stheraven
4340227825Stheravenvoid
4341227825Stheraven__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4342227825Stheraven                             ios_base::fmtflags __flags)
4343227825Stheraven{
4344227825Stheraven    if (__flags & ios_base::showpos)
4345227825Stheraven        *__fmtp++ = '+';
4346227825Stheraven    if (__flags & ios_base::showbase)
4347227825Stheraven        *__fmtp++ = '#';
4348227825Stheraven    while(*__len)
4349227825Stheraven        *__fmtp++ = *__len++;
4350227825Stheraven    if ((__flags & ios_base::basefield) == ios_base::oct)
4351227825Stheraven        *__fmtp = 'o';
4352227825Stheraven    else if ((__flags & ios_base::basefield) == ios_base::hex)
4353227825Stheraven    {
4354227825Stheraven        if (__flags & ios_base::uppercase)
4355227825Stheraven            *__fmtp = 'X';
4356227825Stheraven        else
4357227825Stheraven            *__fmtp = 'x';
4358227825Stheraven    }
4359227825Stheraven    else if (__signd)
4360227825Stheraven        *__fmtp = 'd';
4361227825Stheraven    else
4362227825Stheraven        *__fmtp = 'u';
4363227825Stheraven}
4364227825Stheraven
4365227825Stheravenbool
4366227825Stheraven__num_put_base::__format_float(char* __fmtp, const char* __len,
4367227825Stheraven                               ios_base::fmtflags __flags)
4368227825Stheraven{
4369227825Stheraven    bool specify_precision = true;
4370227825Stheraven    if (__flags & ios_base::showpos)
4371227825Stheraven        *__fmtp++ = '+';
4372227825Stheraven    if (__flags & ios_base::showpoint)
4373227825Stheraven        *__fmtp++ = '#';
4374227825Stheraven    ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4375262801Sdim    bool uppercase = (__flags & ios_base::uppercase) != 0;
4376227825Stheraven    if (floatfield == (ios_base::fixed | ios_base::scientific))
4377227825Stheraven        specify_precision = false;
4378227825Stheraven    else
4379227825Stheraven    {
4380227825Stheraven        *__fmtp++ = '.';
4381227825Stheraven        *__fmtp++ = '*';
4382227825Stheraven    }
4383227825Stheraven    while(*__len)
4384227825Stheraven        *__fmtp++ = *__len++;
4385227825Stheraven    if (floatfield == ios_base::fixed)
4386227825Stheraven    {
4387227825Stheraven        if (uppercase)
4388227825Stheraven            *__fmtp = 'F';
4389227825Stheraven        else
4390227825Stheraven            *__fmtp = 'f';
4391227825Stheraven    }
4392227825Stheraven    else if (floatfield == ios_base::scientific)
4393227825Stheraven    {
4394227825Stheraven        if (uppercase)
4395227825Stheraven            *__fmtp = 'E';
4396227825Stheraven        else
4397227825Stheraven            *__fmtp = 'e';
4398227825Stheraven    }
4399227825Stheraven    else if (floatfield == (ios_base::fixed | ios_base::scientific))
4400227825Stheraven    {
4401227825Stheraven        if (uppercase)
4402227825Stheraven            *__fmtp = 'A';
4403227825Stheraven        else
4404227825Stheraven            *__fmtp = 'a';
4405227825Stheraven    }
4406227825Stheraven    else
4407227825Stheraven    {
4408227825Stheraven        if (uppercase)
4409227825Stheraven            *__fmtp = 'G';
4410227825Stheraven        else
4411227825Stheraven            *__fmtp = 'g';
4412227825Stheraven    }
4413227825Stheraven    return specify_precision;
4414227825Stheraven}
4415227825Stheraven
4416227825Stheravenchar*
4417227825Stheraven__num_put_base::__identify_padding(char* __nb, char* __ne,
4418227825Stheraven                                   const ios_base& __iob)
4419227825Stheraven{
4420227825Stheraven    switch (__iob.flags() & ios_base::adjustfield)
4421227825Stheraven    {
4422227825Stheraven    case ios_base::internal:
4423227825Stheraven        if (__nb[0] == '-' || __nb[0] == '+')
4424227825Stheraven            return __nb+1;
4425227825Stheraven        if (__ne - __nb >= 2 && __nb[0] == '0'
4426227825Stheraven                            && (__nb[1] == 'x' || __nb[1] == 'X'))
4427227825Stheraven            return __nb+2;
4428227825Stheraven        break;
4429227825Stheraven    case ios_base::left:
4430227825Stheraven        return __ne;
4431227825Stheraven    case ios_base::right:
4432227825Stheraven    default:
4433227825Stheraven        break;
4434227825Stheraven    }
4435227825Stheraven    return __nb;
4436227825Stheraven}
4437227825Stheraven
4438227825Stheraven// time_get
4439227825Stheraven
4440227825Stheravenstatic
4441227825Stheravenstring*
4442227825Stheraveninit_weeks()
4443227825Stheraven{
4444227825Stheraven    static string weeks[14];
4445227825Stheraven    weeks[0]  = "Sunday";
4446227825Stheraven    weeks[1]  = "Monday";
4447227825Stheraven    weeks[2]  = "Tuesday";
4448227825Stheraven    weeks[3]  = "Wednesday";
4449227825Stheraven    weeks[4]  = "Thursday";
4450227825Stheraven    weeks[5]  = "Friday";
4451227825Stheraven    weeks[6]  = "Saturday";
4452227825Stheraven    weeks[7]  = "Sun";
4453227825Stheraven    weeks[8]  = "Mon";
4454227825Stheraven    weeks[9]  = "Tue";
4455227825Stheraven    weeks[10] = "Wed";
4456227825Stheraven    weeks[11] = "Thu";
4457227825Stheraven    weeks[12] = "Fri";
4458227825Stheraven    weeks[13] = "Sat";
4459227825Stheraven    return weeks;
4460227825Stheraven}
4461227825Stheraven
4462227825Stheravenstatic
4463227825Stheravenwstring*
4464227825Stheraveninit_wweeks()
4465227825Stheraven{
4466227825Stheraven    static wstring weeks[14];
4467227825Stheraven    weeks[0]  = L"Sunday";
4468227825Stheraven    weeks[1]  = L"Monday";
4469227825Stheraven    weeks[2]  = L"Tuesday";
4470227825Stheraven    weeks[3]  = L"Wednesday";
4471227825Stheraven    weeks[4]  = L"Thursday";
4472227825Stheraven    weeks[5]  = L"Friday";
4473227825Stheraven    weeks[6]  = L"Saturday";
4474227825Stheraven    weeks[7]  = L"Sun";
4475227825Stheraven    weeks[8]  = L"Mon";
4476227825Stheraven    weeks[9]  = L"Tue";
4477227825Stheraven    weeks[10] = L"Wed";
4478227825Stheraven    weeks[11] = L"Thu";
4479227825Stheraven    weeks[12] = L"Fri";
4480227825Stheraven    weeks[13] = L"Sat";
4481227825Stheraven    return weeks;
4482227825Stheraven}
4483227825Stheraven
4484227825Stheraventemplate <>
4485227825Stheravenconst string*
4486227825Stheraven__time_get_c_storage<char>::__weeks() const
4487227825Stheraven{
4488227825Stheraven    static const string* weeks = init_weeks();
4489227825Stheraven    return weeks;
4490227825Stheraven}
4491227825Stheraven
4492227825Stheraventemplate <>
4493227825Stheravenconst wstring*
4494227825Stheraven__time_get_c_storage<wchar_t>::__weeks() const
4495227825Stheraven{
4496227825Stheraven    static const wstring* weeks = init_wweeks();
4497227825Stheraven    return weeks;
4498227825Stheraven}
4499227825Stheraven
4500227825Stheravenstatic
4501227825Stheravenstring*
4502227825Stheraveninit_months()
4503227825Stheraven{
4504227825Stheraven    static string months[24];
4505227825Stheraven    months[0]  = "January";
4506227825Stheraven    months[1]  = "February";
4507227825Stheraven    months[2]  = "March";
4508227825Stheraven    months[3]  = "April";
4509227825Stheraven    months[4]  = "May";
4510227825Stheraven    months[5]  = "June";
4511227825Stheraven    months[6]  = "July";
4512227825Stheraven    months[7]  = "August";
4513227825Stheraven    months[8]  = "September";
4514227825Stheraven    months[9]  = "October";
4515227825Stheraven    months[10] = "November";
4516227825Stheraven    months[11] = "December";
4517227825Stheraven    months[12] = "Jan";
4518227825Stheraven    months[13] = "Feb";
4519227825Stheraven    months[14] = "Mar";
4520227825Stheraven    months[15] = "Apr";
4521227825Stheraven    months[16] = "May";
4522227825Stheraven    months[17] = "Jun";
4523227825Stheraven    months[18] = "Jul";
4524227825Stheraven    months[19] = "Aug";
4525227825Stheraven    months[20] = "Sep";
4526227825Stheraven    months[21] = "Oct";
4527227825Stheraven    months[22] = "Nov";
4528227825Stheraven    months[23] = "Dec";
4529227825Stheraven    return months;
4530227825Stheraven}
4531227825Stheraven
4532227825Stheravenstatic
4533227825Stheravenwstring*
4534227825Stheraveninit_wmonths()
4535227825Stheraven{
4536227825Stheraven    static wstring months[24];
4537227825Stheraven    months[0]  = L"January";
4538227825Stheraven    months[1]  = L"February";
4539227825Stheraven    months[2]  = L"March";
4540227825Stheraven    months[3]  = L"April";
4541227825Stheraven    months[4]  = L"May";
4542227825Stheraven    months[5]  = L"June";
4543227825Stheraven    months[6]  = L"July";
4544227825Stheraven    months[7]  = L"August";
4545227825Stheraven    months[8]  = L"September";
4546227825Stheraven    months[9]  = L"October";
4547227825Stheraven    months[10] = L"November";
4548227825Stheraven    months[11] = L"December";
4549227825Stheraven    months[12] = L"Jan";
4550227825Stheraven    months[13] = L"Feb";
4551227825Stheraven    months[14] = L"Mar";
4552227825Stheraven    months[15] = L"Apr";
4553227825Stheraven    months[16] = L"May";
4554227825Stheraven    months[17] = L"Jun";
4555227825Stheraven    months[18] = L"Jul";
4556227825Stheraven    months[19] = L"Aug";
4557227825Stheraven    months[20] = L"Sep";
4558227825Stheraven    months[21] = L"Oct";
4559227825Stheraven    months[22] = L"Nov";
4560227825Stheraven    months[23] = L"Dec";
4561227825Stheraven    return months;
4562227825Stheraven}
4563227825Stheraven
4564227825Stheraventemplate <>
4565227825Stheravenconst string*
4566227825Stheraven__time_get_c_storage<char>::__months() const
4567227825Stheraven{
4568227825Stheraven    static const string* months = init_months();
4569227825Stheraven    return months;
4570227825Stheraven}
4571227825Stheraven
4572227825Stheraventemplate <>
4573227825Stheravenconst wstring*
4574227825Stheraven__time_get_c_storage<wchar_t>::__months() const
4575227825Stheraven{
4576227825Stheraven    static const wstring* months = init_wmonths();
4577227825Stheraven    return months;
4578227825Stheraven}
4579227825Stheraven
4580227825Stheravenstatic
4581227825Stheravenstring*
4582227825Stheraveninit_am_pm()
4583227825Stheraven{
4584227825Stheraven    static string am_pm[24];
4585227825Stheraven    am_pm[0]  = "AM";
4586227825Stheraven    am_pm[1]  = "PM";
4587227825Stheraven    return am_pm;
4588227825Stheraven}
4589227825Stheraven
4590227825Stheravenstatic
4591227825Stheravenwstring*
4592227825Stheraveninit_wam_pm()
4593227825Stheraven{
4594227825Stheraven    static wstring am_pm[24];
4595227825Stheraven    am_pm[0]  = L"AM";
4596227825Stheraven    am_pm[1]  = L"PM";
4597227825Stheraven    return am_pm;
4598227825Stheraven}
4599227825Stheraven
4600227825Stheraventemplate <>
4601227825Stheravenconst string*
4602227825Stheraven__time_get_c_storage<char>::__am_pm() const
4603227825Stheraven{
4604227825Stheraven    static const string* am_pm = init_am_pm();
4605227825Stheraven    return am_pm;
4606227825Stheraven}
4607227825Stheraven
4608227825Stheraventemplate <>
4609227825Stheravenconst wstring*
4610227825Stheraven__time_get_c_storage<wchar_t>::__am_pm() const
4611227825Stheraven{
4612227825Stheraven    static const wstring* am_pm = init_wam_pm();
4613227825Stheraven    return am_pm;
4614227825Stheraven}
4615227825Stheraven
4616227825Stheraventemplate <>
4617227825Stheravenconst string&
4618227825Stheraven__time_get_c_storage<char>::__x() const
4619227825Stheraven{
4620227825Stheraven    static string s("%m/%d/%y");
4621227825Stheraven    return s;
4622227825Stheraven}
4623227825Stheraven
4624227825Stheraventemplate <>
4625227825Stheravenconst wstring&
4626227825Stheraven__time_get_c_storage<wchar_t>::__x() const
4627227825Stheraven{
4628227825Stheraven    static wstring s(L"%m/%d/%y");
4629227825Stheraven    return s;
4630227825Stheraven}
4631227825Stheraven
4632227825Stheraventemplate <>
4633227825Stheravenconst string&
4634227825Stheraven__time_get_c_storage<char>::__X() const
4635227825Stheraven{
4636227825Stheraven    static string s("%H:%M:%S");
4637227825Stheraven    return s;
4638227825Stheraven}
4639227825Stheraven
4640227825Stheraventemplate <>
4641227825Stheravenconst wstring&
4642227825Stheraven__time_get_c_storage<wchar_t>::__X() const
4643227825Stheraven{
4644227825Stheraven    static wstring s(L"%H:%M:%S");
4645227825Stheraven    return s;
4646227825Stheraven}
4647227825Stheraven
4648227825Stheraventemplate <>
4649227825Stheravenconst string&
4650227825Stheraven__time_get_c_storage<char>::__c() const
4651227825Stheraven{
4652227825Stheraven    static string s("%a %b %d %H:%M:%S %Y");
4653227825Stheraven    return s;
4654227825Stheraven}
4655227825Stheraven
4656227825Stheraventemplate <>
4657227825Stheravenconst wstring&
4658227825Stheraven__time_get_c_storage<wchar_t>::__c() const
4659227825Stheraven{
4660227825Stheraven    static wstring s(L"%a %b %d %H:%M:%S %Y");
4661227825Stheraven    return s;
4662227825Stheraven}
4663227825Stheraven
4664227825Stheraventemplate <>
4665227825Stheravenconst string&
4666227825Stheraven__time_get_c_storage<char>::__r() const
4667227825Stheraven{
4668227825Stheraven    static string s("%I:%M:%S %p");
4669227825Stheraven    return s;
4670227825Stheraven}
4671227825Stheraven
4672227825Stheraventemplate <>
4673227825Stheravenconst wstring&
4674227825Stheraven__time_get_c_storage<wchar_t>::__r() const
4675227825Stheraven{
4676227825Stheraven    static wstring s(L"%I:%M:%S %p");
4677227825Stheraven    return s;
4678227825Stheraven}
4679227825Stheraven
4680227825Stheraven// time_get_byname
4681227825Stheraven
4682227825Stheraven__time_get::__time_get(const char* nm)
4683227825Stheraven    : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4684227825Stheraven{
4685227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
4686227825Stheraven    if (__loc_ == 0)
4687227825Stheraven        throw runtime_error("time_get_byname"
4688227825Stheraven                            " failed to construct for " + string(nm));
4689227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
4690227825Stheraven}
4691227825Stheraven
4692227825Stheraven__time_get::__time_get(const string& nm)
4693227825Stheraven    : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4694227825Stheraven{
4695227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
4696227825Stheraven    if (__loc_ == 0)
4697227825Stheraven        throw runtime_error("time_get_byname"
4698227825Stheraven                            " failed to construct for " + nm);
4699227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
4700227825Stheraven}
4701227825Stheraven
4702227825Stheraven__time_get::~__time_get()
4703227825Stheraven{
4704227825Stheraven    freelocale(__loc_);
4705227825Stheraven}
4706262801Sdim#if defined(__clang__)
4707232950Stheraven#pragma clang diagnostic ignored "-Wmissing-field-initializers"
4708262801Sdim#endif
4709262801Sdim#if defined(__GNUG__)
4710246487Stheraven#pragma GCC   diagnostic ignored "-Wmissing-field-initializers"
4711262801Sdim#endif
4712232950Stheraven
4713227825Stheraventemplate <>
4714227825Stheravenstring
4715227825Stheraven__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4716227825Stheraven{
4717232950Stheraven    tm t = {0};
4718227825Stheraven    t.tm_sec = 59;
4719227825Stheraven    t.tm_min = 55;
4720227825Stheraven    t.tm_hour = 23;
4721227825Stheraven    t.tm_mday = 31;
4722227825Stheraven    t.tm_mon = 11;
4723227825Stheraven    t.tm_year = 161;
4724227825Stheraven    t.tm_wday = 6;
4725227825Stheraven    t.tm_yday = 364;
4726227825Stheraven    t.tm_isdst = -1;
4727227825Stheraven    char buf[100];
4728227825Stheraven    char f[3] = {0};
4729227825Stheraven    f[0] = '%';
4730227825Stheraven    f[1] = fmt;
4731246487Stheraven    size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
4732227825Stheraven    char* bb = buf;
4733227825Stheraven    char* be = buf + n;
4734227825Stheraven    string result;
4735227825Stheraven    while (bb != be)
4736227825Stheraven    {
4737227825Stheraven        if (ct.is(ctype_base::space, *bb))
4738227825Stheraven        {
4739227825Stheraven            result.push_back(' ');
4740227825Stheraven            for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4741227825Stheraven                ;
4742227825Stheraven            continue;
4743227825Stheraven        }
4744227825Stheraven        char* w = bb;
4745227825Stheraven        ios_base::iostate err = ios_base::goodbit;
4746232950Stheraven        ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4747227825Stheraven                               ct, err, false)
4748227825Stheraven                               - this->__weeks_;
4749227825Stheraven        if (i < 14)
4750227825Stheraven        {
4751227825Stheraven            result.push_back('%');
4752227825Stheraven            if (i < 7)
4753227825Stheraven                result.push_back('A');
4754227825Stheraven            else
4755227825Stheraven                result.push_back('a');
4756227825Stheraven            bb = w;
4757227825Stheraven            continue;
4758227825Stheraven        }
4759227825Stheraven        w = bb;
4760227825Stheraven        i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4761227825Stheraven                           ct, err, false)
4762227825Stheraven                           - this->__months_;
4763227825Stheraven        if (i < 24)
4764227825Stheraven        {
4765227825Stheraven            result.push_back('%');
4766227825Stheraven            if (i < 12)
4767227825Stheraven                result.push_back('B');
4768227825Stheraven            else
4769227825Stheraven                result.push_back('b');
4770227825Stheraven            if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4771227825Stheraven                result.back() = 'm';
4772227825Stheraven            bb = w;
4773227825Stheraven            continue;
4774227825Stheraven        }
4775227825Stheraven        if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4776227825Stheraven        {
4777227825Stheraven            w = bb;
4778227825Stheraven            i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4779227825Stheraven                               ct, err, false) - this->__am_pm_;
4780227825Stheraven            if (i < 2)
4781227825Stheraven            {
4782227825Stheraven                result.push_back('%');
4783227825Stheraven                result.push_back('p');
4784227825Stheraven                bb = w;
4785227825Stheraven                continue;
4786227825Stheraven            }
4787227825Stheraven        }
4788227825Stheraven        w = bb;
4789227825Stheraven        if (ct.is(ctype_base::digit, *bb))
4790227825Stheraven        {
4791227825Stheraven            switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4792227825Stheraven            {
4793227825Stheraven            case 6:
4794227825Stheraven                result.push_back('%');
4795227825Stheraven                result.push_back('w');
4796227825Stheraven                break;
4797227825Stheraven            case 7:
4798227825Stheraven                result.push_back('%');
4799227825Stheraven                result.push_back('u');
4800227825Stheraven                break;
4801227825Stheraven            case 11:
4802227825Stheraven                result.push_back('%');
4803227825Stheraven                result.push_back('I');
4804227825Stheraven                break;
4805227825Stheraven            case 12:
4806227825Stheraven                result.push_back('%');
4807227825Stheraven                result.push_back('m');
4808227825Stheraven                break;
4809227825Stheraven            case 23:
4810227825Stheraven                result.push_back('%');
4811227825Stheraven                result.push_back('H');
4812227825Stheraven                break;
4813227825Stheraven            case 31:
4814227825Stheraven                result.push_back('%');
4815227825Stheraven                result.push_back('d');
4816227825Stheraven                break;
4817227825Stheraven            case 55:
4818227825Stheraven                result.push_back('%');
4819227825Stheraven                result.push_back('M');
4820227825Stheraven                break;
4821227825Stheraven            case 59:
4822227825Stheraven                result.push_back('%');
4823227825Stheraven                result.push_back('S');
4824227825Stheraven                break;
4825227825Stheraven            case 61:
4826227825Stheraven                result.push_back('%');
4827227825Stheraven                result.push_back('y');
4828227825Stheraven                break;
4829227825Stheraven            case 364:
4830227825Stheraven                result.push_back('%');
4831227825Stheraven                result.push_back('j');
4832227825Stheraven                break;
4833227825Stheraven            case 2061:
4834227825Stheraven                result.push_back('%');
4835227825Stheraven                result.push_back('Y');
4836227825Stheraven                break;
4837227825Stheraven            default:
4838227825Stheraven                for (; w != bb; ++w)
4839227825Stheraven                    result.push_back(*w);
4840227825Stheraven                break;
4841227825Stheraven            }
4842227825Stheraven            continue;
4843227825Stheraven        }
4844227825Stheraven        if (*bb == '%')
4845227825Stheraven        {
4846227825Stheraven            result.push_back('%');
4847227825Stheraven            result.push_back('%');
4848227825Stheraven            ++bb;
4849227825Stheraven            continue;
4850227825Stheraven        }
4851227825Stheraven        result.push_back(*bb);
4852227825Stheraven        ++bb;
4853227825Stheraven    }
4854227825Stheraven    return result;
4855227825Stheraven}
4856227825Stheraven
4857262801Sdim#if defined(__clang__)
4858232950Stheraven#pragma clang diagnostic ignored "-Wmissing-braces"
4859262801Sdim#endif
4860232950Stheraven
4861227825Stheraventemplate <>
4862227825Stheravenwstring
4863227825Stheraven__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4864227825Stheraven{
4865232950Stheraven    tm t = {0};
4866227825Stheraven    t.tm_sec = 59;
4867227825Stheraven    t.tm_min = 55;
4868227825Stheraven    t.tm_hour = 23;
4869227825Stheraven    t.tm_mday = 31;
4870227825Stheraven    t.tm_mon = 11;
4871227825Stheraven    t.tm_year = 161;
4872227825Stheraven    t.tm_wday = 6;
4873227825Stheraven    t.tm_yday = 364;
4874227825Stheraven    t.tm_isdst = -1;
4875227825Stheraven    char buf[100];
4876227825Stheraven    char f[3] = {0};
4877227825Stheraven    f[0] = '%';
4878227825Stheraven    f[1] = fmt;
4879246487Stheraven    strftime_l(buf, countof(buf), f, &t, __loc_);
4880227825Stheraven    wchar_t wbuf[100];
4881227825Stheraven    wchar_t* wbb = wbuf;
4882227825Stheraven    mbstate_t mb = {0};
4883227825Stheraven    const char* bb = buf;
4884227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
4885246487Stheraven    size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
4886227825Stheraven#else
4887246487Stheraven    size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
4888227825Stheraven#endif
4889232950Stheraven    if (j == size_t(-1))
4890227825Stheraven        __throw_runtime_error("locale not supported");
4891232950Stheraven    wchar_t* wbe = wbb + j;
4892227825Stheraven    wstring result;
4893227825Stheraven    while (wbb != wbe)
4894227825Stheraven    {
4895227825Stheraven        if (ct.is(ctype_base::space, *wbb))
4896227825Stheraven        {
4897227825Stheraven            result.push_back(L' ');
4898227825Stheraven            for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4899227825Stheraven                ;
4900227825Stheraven            continue;
4901227825Stheraven        }
4902227825Stheraven        wchar_t* w = wbb;
4903227825Stheraven        ios_base::iostate err = ios_base::goodbit;
4904232950Stheraven        ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4905227825Stheraven                               ct, err, false)
4906227825Stheraven                               - this->__weeks_;
4907227825Stheraven        if (i < 14)
4908227825Stheraven        {
4909227825Stheraven            result.push_back(L'%');
4910227825Stheraven            if (i < 7)
4911227825Stheraven                result.push_back(L'A');
4912227825Stheraven            else
4913227825Stheraven                result.push_back(L'a');
4914227825Stheraven            wbb = w;
4915227825Stheraven            continue;
4916227825Stheraven        }
4917227825Stheraven        w = wbb;
4918227825Stheraven        i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4919227825Stheraven                           ct, err, false)
4920227825Stheraven                           - this->__months_;
4921227825Stheraven        if (i < 24)
4922227825Stheraven        {
4923227825Stheraven            result.push_back(L'%');
4924227825Stheraven            if (i < 12)
4925227825Stheraven                result.push_back(L'B');
4926227825Stheraven            else
4927227825Stheraven                result.push_back(L'b');
4928227825Stheraven            if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4929227825Stheraven                result.back() = L'm';
4930227825Stheraven            wbb = w;
4931227825Stheraven            continue;
4932227825Stheraven        }
4933227825Stheraven        if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4934227825Stheraven        {
4935227825Stheraven            w = wbb;
4936227825Stheraven            i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4937227825Stheraven                               ct, err, false) - this->__am_pm_;
4938227825Stheraven            if (i < 2)
4939227825Stheraven            {
4940227825Stheraven                result.push_back(L'%');
4941227825Stheraven                result.push_back(L'p');
4942227825Stheraven                wbb = w;
4943227825Stheraven                continue;
4944227825Stheraven            }
4945227825Stheraven        }
4946227825Stheraven        w = wbb;
4947227825Stheraven        if (ct.is(ctype_base::digit, *wbb))
4948227825Stheraven        {
4949227825Stheraven            switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4950227825Stheraven            {
4951227825Stheraven            case 6:
4952227825Stheraven                result.push_back(L'%');
4953227825Stheraven                result.push_back(L'w');
4954227825Stheraven                break;
4955227825Stheraven            case 7:
4956227825Stheraven                result.push_back(L'%');
4957227825Stheraven                result.push_back(L'u');
4958227825Stheraven                break;
4959227825Stheraven            case 11:
4960227825Stheraven                result.push_back(L'%');
4961227825Stheraven                result.push_back(L'I');
4962227825Stheraven                break;
4963227825Stheraven            case 12:
4964227825Stheraven                result.push_back(L'%');
4965227825Stheraven                result.push_back(L'm');
4966227825Stheraven                break;
4967227825Stheraven            case 23:
4968227825Stheraven                result.push_back(L'%');
4969227825Stheraven                result.push_back(L'H');
4970227825Stheraven                break;
4971227825Stheraven            case 31:
4972227825Stheraven                result.push_back(L'%');
4973227825Stheraven                result.push_back(L'd');
4974227825Stheraven                break;
4975227825Stheraven            case 55:
4976227825Stheraven                result.push_back(L'%');
4977227825Stheraven                result.push_back(L'M');
4978227825Stheraven                break;
4979227825Stheraven            case 59:
4980227825Stheraven                result.push_back(L'%');
4981227825Stheraven                result.push_back(L'S');
4982227825Stheraven                break;
4983227825Stheraven            case 61:
4984227825Stheraven                result.push_back(L'%');
4985227825Stheraven                result.push_back(L'y');
4986227825Stheraven                break;
4987227825Stheraven            case 364:
4988227825Stheraven                result.push_back(L'%');
4989227825Stheraven                result.push_back(L'j');
4990227825Stheraven                break;
4991227825Stheraven            case 2061:
4992227825Stheraven                result.push_back(L'%');
4993227825Stheraven                result.push_back(L'Y');
4994227825Stheraven                break;
4995227825Stheraven            default:
4996227825Stheraven                for (; w != wbb; ++w)
4997227825Stheraven                    result.push_back(*w);
4998227825Stheraven                break;
4999227825Stheraven            }
5000227825Stheraven            continue;
5001227825Stheraven        }
5002227825Stheraven        if (ct.narrow(*wbb, 0) == '%')
5003227825Stheraven        {
5004227825Stheraven            result.push_back(L'%');
5005227825Stheraven            result.push_back(L'%');
5006227825Stheraven            ++wbb;
5007227825Stheraven            continue;
5008227825Stheraven        }
5009227825Stheraven        result.push_back(*wbb);
5010227825Stheraven        ++wbb;
5011227825Stheraven    }
5012227825Stheraven    return result;
5013227825Stheraven}
5014227825Stheraven
5015227825Stheraventemplate <>
5016227825Stheravenvoid
5017227825Stheraven__time_get_storage<char>::init(const ctype<char>& ct)
5018227825Stheraven{
5019241903Sdim    tm t = {0};
5020227825Stheraven    char buf[100];
5021227825Stheraven    // __weeks_
5022227825Stheraven    for (int i = 0; i < 7; ++i)
5023227825Stheraven    {
5024227825Stheraven        t.tm_wday = i;
5025246487Stheraven        strftime_l(buf, countof(buf), "%A", &t, __loc_);
5026227825Stheraven        __weeks_[i] = buf;
5027246487Stheraven        strftime_l(buf, countof(buf), "%a", &t, __loc_);
5028227825Stheraven        __weeks_[i+7] = buf;
5029227825Stheraven    }
5030227825Stheraven    // __months_
5031227825Stheraven    for (int i = 0; i < 12; ++i)
5032227825Stheraven    {
5033227825Stheraven        t.tm_mon = i;
5034246487Stheraven        strftime_l(buf, countof(buf), "%B", &t, __loc_);
5035227825Stheraven        __months_[i] = buf;
5036246487Stheraven        strftime_l(buf, countof(buf), "%b", &t, __loc_);
5037227825Stheraven        __months_[i+12] = buf;
5038227825Stheraven    }
5039227825Stheraven    // __am_pm_
5040227825Stheraven    t.tm_hour = 1;
5041246487Stheraven    strftime_l(buf, countof(buf), "%p", &t, __loc_);
5042227825Stheraven    __am_pm_[0] = buf;
5043227825Stheraven    t.tm_hour = 13;
5044246487Stheraven    strftime_l(buf, countof(buf), "%p", &t, __loc_);
5045227825Stheraven    __am_pm_[1] = buf;
5046227825Stheraven    __c_ = __analyze('c', ct);
5047227825Stheraven    __r_ = __analyze('r', ct);
5048227825Stheraven    __x_ = __analyze('x', ct);
5049227825Stheraven    __X_ = __analyze('X', ct);
5050227825Stheraven}
5051227825Stheraven
5052227825Stheraventemplate <>
5053227825Stheravenvoid
5054227825Stheraven__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5055227825Stheraven{
5056227825Stheraven    tm t = {0};
5057227825Stheraven    char buf[100];
5058227825Stheraven    wchar_t wbuf[100];
5059227825Stheraven    wchar_t* wbe;
5060227825Stheraven    mbstate_t mb = {0};
5061227825Stheraven    // __weeks_
5062227825Stheraven    for (int i = 0; i < 7; ++i)
5063227825Stheraven    {
5064227825Stheraven        t.tm_wday = i;
5065246487Stheraven        strftime_l(buf, countof(buf), "%A", &t, __loc_);
5066227825Stheraven        mb = mbstate_t();
5067227825Stheraven        const char* bb = buf;
5068227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5069246487Stheraven        size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5070227825Stheraven#else
5071246487Stheraven        size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5072227825Stheraven#endif
5073232950Stheraven        if (j == size_t(-1))
5074227825Stheraven            __throw_runtime_error("locale not supported");
5075227825Stheraven        wbe = wbuf + j;
5076227825Stheraven        __weeks_[i].assign(wbuf, wbe);
5077246487Stheraven        strftime_l(buf, countof(buf), "%a", &t, __loc_);
5078227825Stheraven        mb = mbstate_t();
5079227825Stheraven        bb = buf;
5080227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5081246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5082227825Stheraven#else
5083246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5084227825Stheraven#endif
5085232950Stheraven        if (j == size_t(-1))
5086227825Stheraven            __throw_runtime_error("locale not supported");
5087227825Stheraven        wbe = wbuf + j;
5088227825Stheraven        __weeks_[i+7].assign(wbuf, wbe);
5089227825Stheraven    }
5090227825Stheraven    // __months_
5091227825Stheraven    for (int i = 0; i < 12; ++i)
5092227825Stheraven    {
5093227825Stheraven        t.tm_mon = i;
5094246487Stheraven        strftime_l(buf, countof(buf), "%B", &t, __loc_);
5095227825Stheraven        mb = mbstate_t();
5096227825Stheraven        const char* bb = buf;
5097227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5098246487Stheraven        size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5099227825Stheraven#else
5100246487Stheraven        size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5101227825Stheraven#endif
5102232950Stheraven        if (j == size_t(-1))
5103227825Stheraven            __throw_runtime_error("locale not supported");
5104227825Stheraven        wbe = wbuf + j;
5105227825Stheraven        __months_[i].assign(wbuf, wbe);
5106246487Stheraven        strftime_l(buf, countof(buf), "%b", &t, __loc_);
5107227825Stheraven        mb = mbstate_t();
5108227825Stheraven        bb = buf;
5109227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5110246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5111227825Stheraven#else
5112246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5113227825Stheraven#endif
5114232950Stheraven        if (j == size_t(-1))
5115227825Stheraven            __throw_runtime_error("locale not supported");
5116227825Stheraven        wbe = wbuf + j;
5117227825Stheraven        __months_[i+12].assign(wbuf, wbe);
5118227825Stheraven    }
5119227825Stheraven    // __am_pm_
5120227825Stheraven    t.tm_hour = 1;
5121246487Stheraven    strftime_l(buf, countof(buf), "%p", &t, __loc_);
5122227825Stheraven    mb = mbstate_t();
5123227825Stheraven    const char* bb = buf;
5124227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5125246487Stheraven    size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5126227825Stheraven#else
5127246487Stheraven    size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5128227825Stheraven#endif
5129232950Stheraven    if (j == size_t(-1))
5130227825Stheraven        __throw_runtime_error("locale not supported");
5131227825Stheraven    wbe = wbuf + j;
5132227825Stheraven    __am_pm_[0].assign(wbuf, wbe);
5133227825Stheraven    t.tm_hour = 13;
5134246487Stheraven    strftime_l(buf, countof(buf), "%p", &t, __loc_);
5135227825Stheraven    mb = mbstate_t();
5136227825Stheraven    bb = buf;
5137227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5138246487Stheraven    j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5139227825Stheraven#else
5140246487Stheraven    j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5141227825Stheraven#endif
5142232950Stheraven    if (j == size_t(-1))
5143227825Stheraven        __throw_runtime_error("locale not supported");
5144227825Stheraven    wbe = wbuf + j;
5145227825Stheraven    __am_pm_[1].assign(wbuf, wbe);
5146227825Stheraven    __c_ = __analyze('c', ct);
5147227825Stheraven    __r_ = __analyze('r', ct);
5148227825Stheraven    __x_ = __analyze('x', ct);
5149227825Stheraven    __X_ = __analyze('X', ct);
5150227825Stheraven}
5151227825Stheraven
5152227825Stheraventemplate <class CharT>
5153227825Stheravenstruct _LIBCPP_HIDDEN __time_get_temp
5154227825Stheraven    : public ctype_byname<CharT>
5155227825Stheraven{
5156227825Stheraven    explicit __time_get_temp(const char* nm)
5157227825Stheraven        : ctype_byname<CharT>(nm, 1) {}
5158227825Stheraven    explicit __time_get_temp(const string& nm)
5159227825Stheraven        : ctype_byname<CharT>(nm, 1) {}
5160227825Stheraven};
5161227825Stheraven
5162227825Stheraventemplate <>
5163227825Stheraven__time_get_storage<char>::__time_get_storage(const char* __nm)
5164227825Stheraven    : __time_get(__nm)
5165227825Stheraven{
5166227825Stheraven    const __time_get_temp<char> ct(__nm);
5167227825Stheraven    init(ct);
5168227825Stheraven}
5169227825Stheraven
5170227825Stheraventemplate <>
5171227825Stheraven__time_get_storage<char>::__time_get_storage(const string& __nm)
5172227825Stheraven    : __time_get(__nm)
5173227825Stheraven{
5174227825Stheraven    const __time_get_temp<char> ct(__nm);
5175227825Stheraven    init(ct);
5176227825Stheraven}
5177227825Stheraven
5178227825Stheraventemplate <>
5179227825Stheraven__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5180227825Stheraven    : __time_get(__nm)
5181227825Stheraven{
5182227825Stheraven    const __time_get_temp<wchar_t> ct(__nm);
5183227825Stheraven    init(ct);
5184227825Stheraven}
5185227825Stheraven
5186227825Stheraventemplate <>
5187227825Stheraven__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5188227825Stheraven    : __time_get(__nm)
5189227825Stheraven{
5190227825Stheraven    const __time_get_temp<wchar_t> ct(__nm);
5191227825Stheraven    init(ct);
5192227825Stheraven}
5193227825Stheraven
5194227825Stheraventemplate <>
5195227825Stheraventime_base::dateorder
5196227825Stheraven__time_get_storage<char>::__do_date_order() const
5197227825Stheraven{
5198227825Stheraven    unsigned i;
5199227825Stheraven    for (i = 0; i < __x_.size(); ++i)
5200227825Stheraven        if (__x_[i] == '%')
5201227825Stheraven            break;
5202227825Stheraven    ++i;
5203227825Stheraven    switch (__x_[i])
5204227825Stheraven    {
5205227825Stheraven    case 'y':
5206227825Stheraven    case 'Y':
5207227825Stheraven        for (++i; i < __x_.size(); ++i)
5208227825Stheraven            if (__x_[i] == '%')
5209227825Stheraven                break;
5210227825Stheraven        if (i == __x_.size())
5211227825Stheraven            break;
5212227825Stheraven        ++i;
5213227825Stheraven        switch (__x_[i])
5214227825Stheraven        {
5215227825Stheraven        case 'm':
5216227825Stheraven            for (++i; i < __x_.size(); ++i)
5217227825Stheraven                if (__x_[i] == '%')
5218227825Stheraven                    break;
5219227825Stheraven            if (i == __x_.size())
5220227825Stheraven                break;
5221227825Stheraven            ++i;
5222227825Stheraven            if (__x_[i] == 'd')
5223227825Stheraven                return time_base::ymd;
5224227825Stheraven            break;
5225227825Stheraven        case 'd':
5226227825Stheraven            for (++i; i < __x_.size(); ++i)
5227227825Stheraven                if (__x_[i] == '%')
5228227825Stheraven                    break;
5229227825Stheraven            if (i == __x_.size())
5230227825Stheraven                break;
5231227825Stheraven            ++i;
5232227825Stheraven            if (__x_[i] == 'm')
5233227825Stheraven                return time_base::ydm;
5234227825Stheraven            break;
5235227825Stheraven        }
5236227825Stheraven        break;
5237227825Stheraven    case 'm':
5238227825Stheraven        for (++i; i < __x_.size(); ++i)
5239227825Stheraven            if (__x_[i] == '%')
5240227825Stheraven                break;
5241227825Stheraven        if (i == __x_.size())
5242227825Stheraven            break;
5243227825Stheraven        ++i;
5244227825Stheraven        if (__x_[i] == 'd')
5245227825Stheraven        {
5246227825Stheraven            for (++i; i < __x_.size(); ++i)
5247227825Stheraven                if (__x_[i] == '%')
5248227825Stheraven                    break;
5249227825Stheraven            if (i == __x_.size())
5250227825Stheraven                break;
5251227825Stheraven            ++i;
5252227825Stheraven            if (__x_[i] == 'y' || __x_[i] == 'Y')
5253227825Stheraven                return time_base::mdy;
5254227825Stheraven            break;
5255227825Stheraven        }
5256227825Stheraven        break;
5257227825Stheraven    case 'd':
5258227825Stheraven        for (++i; i < __x_.size(); ++i)
5259227825Stheraven            if (__x_[i] == '%')
5260227825Stheraven                break;
5261227825Stheraven        if (i == __x_.size())
5262227825Stheraven            break;
5263227825Stheraven        ++i;
5264227825Stheraven        if (__x_[i] == 'm')
5265227825Stheraven        {
5266227825Stheraven            for (++i; i < __x_.size(); ++i)
5267227825Stheraven                if (__x_[i] == '%')
5268227825Stheraven                    break;
5269227825Stheraven            if (i == __x_.size())
5270227825Stheraven                break;
5271227825Stheraven            ++i;
5272227825Stheraven            if (__x_[i] == 'y' || __x_[i] == 'Y')
5273227825Stheraven                return time_base::dmy;
5274227825Stheraven            break;
5275227825Stheraven        }
5276227825Stheraven        break;
5277227825Stheraven    }
5278227825Stheraven    return time_base::no_order;
5279227825Stheraven}
5280227825Stheraven
5281227825Stheraventemplate <>
5282227825Stheraventime_base::dateorder
5283227825Stheraven__time_get_storage<wchar_t>::__do_date_order() const
5284227825Stheraven{
5285227825Stheraven    unsigned i;
5286227825Stheraven    for (i = 0; i < __x_.size(); ++i)
5287227825Stheraven        if (__x_[i] == L'%')
5288227825Stheraven            break;
5289227825Stheraven    ++i;
5290227825Stheraven    switch (__x_[i])
5291227825Stheraven    {
5292227825Stheraven    case L'y':
5293227825Stheraven    case L'Y':
5294227825Stheraven        for (++i; i < __x_.size(); ++i)
5295227825Stheraven            if (__x_[i] == L'%')
5296227825Stheraven                break;
5297227825Stheraven        if (i == __x_.size())
5298227825Stheraven            break;
5299227825Stheraven        ++i;
5300227825Stheraven        switch (__x_[i])
5301227825Stheraven        {
5302227825Stheraven        case L'm':
5303227825Stheraven            for (++i; i < __x_.size(); ++i)
5304227825Stheraven                if (__x_[i] == L'%')
5305227825Stheraven                    break;
5306227825Stheraven            if (i == __x_.size())
5307227825Stheraven                break;
5308227825Stheraven            ++i;
5309227825Stheraven            if (__x_[i] == L'd')
5310227825Stheraven                return time_base::ymd;
5311227825Stheraven            break;
5312227825Stheraven        case L'd':
5313227825Stheraven            for (++i; i < __x_.size(); ++i)
5314227825Stheraven                if (__x_[i] == L'%')
5315227825Stheraven                    break;
5316227825Stheraven            if (i == __x_.size())
5317227825Stheraven                break;
5318227825Stheraven            ++i;
5319227825Stheraven            if (__x_[i] == L'm')
5320227825Stheraven                return time_base::ydm;
5321227825Stheraven            break;
5322227825Stheraven        }
5323227825Stheraven        break;
5324227825Stheraven    case L'm':
5325227825Stheraven        for (++i; i < __x_.size(); ++i)
5326227825Stheraven            if (__x_[i] == L'%')
5327227825Stheraven                break;
5328227825Stheraven        if (i == __x_.size())
5329227825Stheraven            break;
5330227825Stheraven        ++i;
5331227825Stheraven        if (__x_[i] == L'd')
5332227825Stheraven        {
5333227825Stheraven            for (++i; i < __x_.size(); ++i)
5334227825Stheraven                if (__x_[i] == L'%')
5335227825Stheraven                    break;
5336227825Stheraven            if (i == __x_.size())
5337227825Stheraven                break;
5338227825Stheraven            ++i;
5339227825Stheraven            if (__x_[i] == L'y' || __x_[i] == L'Y')
5340227825Stheraven                return time_base::mdy;
5341227825Stheraven            break;
5342227825Stheraven        }
5343227825Stheraven        break;
5344227825Stheraven    case L'd':
5345227825Stheraven        for (++i; i < __x_.size(); ++i)
5346227825Stheraven            if (__x_[i] == L'%')
5347227825Stheraven                break;
5348227825Stheraven        if (i == __x_.size())
5349227825Stheraven            break;
5350227825Stheraven        ++i;
5351227825Stheraven        if (__x_[i] == L'm')
5352227825Stheraven        {
5353227825Stheraven            for (++i; i < __x_.size(); ++i)
5354227825Stheraven                if (__x_[i] == L'%')
5355227825Stheraven                    break;
5356227825Stheraven            if (i == __x_.size())
5357227825Stheraven                break;
5358227825Stheraven            ++i;
5359227825Stheraven            if (__x_[i] == L'y' || __x_[i] == L'Y')
5360227825Stheraven                return time_base::dmy;
5361227825Stheraven            break;
5362227825Stheraven        }
5363227825Stheraven        break;
5364227825Stheraven    }
5365227825Stheraven    return time_base::no_order;
5366227825Stheraven}
5367227825Stheraven
5368227825Stheraven// time_put
5369227825Stheraven
5370227825Stheraven__time_put::__time_put(const char* nm)
5371227825Stheraven    : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5372227825Stheraven{
5373227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5374227825Stheraven    if (__loc_ == 0)
5375227825Stheraven        throw runtime_error("time_put_byname"
5376227825Stheraven                            " failed to construct for " + string(nm));
5377227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5378227825Stheraven}
5379227825Stheraven
5380227825Stheraven__time_put::__time_put(const string& nm)
5381227825Stheraven    : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5382227825Stheraven{
5383227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5384227825Stheraven    if (__loc_ == 0)
5385227825Stheraven        throw runtime_error("time_put_byname"
5386227825Stheraven                            " failed to construct for " + nm);
5387227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5388227825Stheraven}
5389227825Stheraven
5390227825Stheraven__time_put::~__time_put()
5391227825Stheraven{
5392253159Stheraven    if (__loc_ != _LIBCPP_GET_C_LOCALE)
5393227825Stheraven        freelocale(__loc_);
5394227825Stheraven}
5395227825Stheraven
5396227825Stheravenvoid
5397227825Stheraven__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5398227825Stheraven                     char __fmt, char __mod) const
5399227825Stheraven{
5400227825Stheraven    char fmt[] = {'%', __fmt, __mod, 0};
5401227825Stheraven    if (__mod != 0)
5402227825Stheraven        swap(fmt[1], fmt[2]);
5403246487Stheraven    size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
5404227825Stheraven    __ne = __nb + n;
5405227825Stheraven}
5406227825Stheraven
5407227825Stheravenvoid
5408227825Stheraven__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5409227825Stheraven                     char __fmt, char __mod) const
5410227825Stheraven{
5411227825Stheraven    char __nar[100];
5412227825Stheraven    char* __ne = __nar + 100;
5413227825Stheraven    __do_put(__nar, __ne, __tm, __fmt, __mod);
5414227825Stheraven    mbstate_t mb = {0};
5415227825Stheraven    const char* __nb = __nar;
5416227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5417246487Stheraven    size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
5418227825Stheraven#else
5419246487Stheraven    size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
5420227825Stheraven#endif
5421232950Stheraven    if (j == size_t(-1))
5422227825Stheraven        __throw_runtime_error("locale not supported");
5423227825Stheraven    __we = __wb + j;
5424227825Stheraven}
5425227825Stheraven
5426227825Stheraven// moneypunct_byname
5427227825Stheraven
5428232950Stheraventemplate <class charT>
5429227825Stheravenstatic
5430227825Stheravenvoid
5431232950Stheraven__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5432232950Stheraven           bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5433232950Stheraven           charT space_char)
5434227825Stheraven{
5435227825Stheraven    const char sign = static_cast<char>(money_base::sign);
5436227825Stheraven    const char space = static_cast<char>(money_base::space);
5437227825Stheraven    const char none = static_cast<char>(money_base::none);
5438227825Stheraven    const char symbol = static_cast<char>(money_base::symbol);
5439227825Stheraven    const char value = static_cast<char>(money_base::value);
5440232950Stheraven    const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5441232950Stheraven
5442232950Stheraven    // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5443232950Stheraven    // function'. "Space between sign and symbol or value" means that
5444232950Stheraven    // if the sign is adjacent to the symbol, there's a space between
5445232950Stheraven    // them, and otherwise there's a space between the sign and value.
5446232950Stheraven    //
5447232950Stheraven    // C11's localeconv specifies that the fourth character of an
5448232950Stheraven    // international curr_symbol is used to separate the sign and
5449232950Stheraven    // value when sep_by_space says to do so. C++ can't represent
5450232950Stheraven    // that, so we just use a space.  When sep_by_space says to
5451232950Stheraven    // separate the symbol and value-or-sign with a space, we rearrange the
5452232950Stheraven    // curr_symbol to put its spacing character on the correct side of
5453232950Stheraven    // the symbol.
5454232950Stheraven    //
5455232950Stheraven    // We also need to avoid adding an extra space between the sign
5456232950Stheraven    // and value when the currency symbol is suppressed (by not
5457232950Stheraven    // setting showbase).  We match glibc's strfmon by interpreting
5458232950Stheraven    // sep_by_space==1 as "omit the space when the currency symbol is
5459232950Stheraven    // absent".
5460232950Stheraven    //
5461232950Stheraven    // Users who want to get this right should use ICU instead.
5462232950Stheraven
5463227825Stheraven    switch (cs_precedes)
5464227825Stheraven    {
5465232950Stheraven    case 0:  // value before curr_symbol
5466232950Stheraven        if (symbol_contains_sep) {
5467232950Stheraven            // Move the separator to before the symbol, to place it
5468232950Stheraven            // between the value and symbol.
5469232950Stheraven            rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5470232950Stheraven                   __curr_symbol_.end());
5471232950Stheraven        }
5472227825Stheraven        switch (sign_posn)
5473227825Stheraven        {
5474232950Stheraven        case 0:  // Parentheses surround the quantity and currency symbol.
5475227825Stheraven            pat.field[0] = sign;
5476227825Stheraven            pat.field[1] = value;
5477232950Stheraven            pat.field[2] = none;  // Any space appears in the symbol.
5478227825Stheraven            pat.field[3] = symbol;
5479227825Stheraven            switch (sep_by_space)
5480227825Stheraven            {
5481232950Stheraven            case 0:  // No space separates the currency symbol and value.
5482232950Stheraven                // This case may have changed between C99 and C11;
5483232950Stheraven                // assume the currency symbol matches the intention.
5484232950Stheraven            case 2:  // Space between sign and currency or value.
5485232950Stheraven                // The "sign" is two parentheses, so no space here either.
5486227825Stheraven                return;
5487232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5488232950Stheraven                if (!symbol_contains_sep) {
5489232950Stheraven                    // We insert the space into the symbol instead of
5490232950Stheraven                    // setting pat.field[2]=space so that when
5491232950Stheraven                    // showbase is not set, the space goes away too.
5492232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5493232950Stheraven                }
5494227825Stheraven                return;
5495227825Stheraven            default:
5496227825Stheraven                break;
5497227825Stheraven            }
5498227825Stheraven            break;
5499232950Stheraven        case 1:  // The sign string precedes the quantity and currency symbol.
5500227825Stheraven            pat.field[0] = sign;
5501227825Stheraven            pat.field[3] = symbol;
5502227825Stheraven            switch (sep_by_space)
5503227825Stheraven            {
5504232950Stheraven            case 0:  // No space separates the currency symbol and value.
5505227825Stheraven                pat.field[1] = value;
5506227825Stheraven                pat.field[2] = none;
5507227825Stheraven                return;
5508232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5509227825Stheraven                pat.field[1] = value;
5510232950Stheraven                pat.field[2] = none;
5511232950Stheraven                if (!symbol_contains_sep) {
5512232950Stheraven                    // We insert the space into the symbol instead of
5513232950Stheraven                    // setting pat.field[2]=space so that when
5514232950Stheraven                    // showbase is not set, the space goes away too.
5515232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5516232950Stheraven                }
5517227825Stheraven                return;
5518232950Stheraven            case 2:  // Space between sign and currency or value.
5519227825Stheraven                pat.field[1] = space;
5520227825Stheraven                pat.field[2] = value;
5521232950Stheraven                if (symbol_contains_sep) {
5522232950Stheraven                    // Remove the separator from the symbol, since it
5523232950Stheraven                    // has already appeared after the sign.
5524232950Stheraven                    __curr_symbol_.erase(__curr_symbol_.begin());
5525232950Stheraven                }
5526227825Stheraven                return;
5527227825Stheraven            default:
5528227825Stheraven                break;
5529227825Stheraven            }
5530227825Stheraven            break;
5531232950Stheraven        case 2:  // The sign string succeeds the quantity and currency symbol.
5532227825Stheraven            pat.field[0] = value;
5533227825Stheraven            pat.field[3] = sign;
5534227825Stheraven            switch (sep_by_space)
5535227825Stheraven            {
5536232950Stheraven            case 0:  // No space separates the currency symbol and value.
5537227825Stheraven                pat.field[1] = none;
5538227825Stheraven                pat.field[2] = symbol;
5539227825Stheraven                return;
5540232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5541232950Stheraven                if (!symbol_contains_sep) {
5542232950Stheraven                    // We insert the space into the symbol instead of
5543232950Stheraven                    // setting pat.field[1]=space so that when
5544232950Stheraven                    // showbase is not set, the space goes away too.
5545232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5546232950Stheraven                }
5547232950Stheraven                pat.field[1] = none;
5548227825Stheraven                pat.field[2] = symbol;
5549227825Stheraven                return;
5550232950Stheraven            case 2:  // Space between sign and currency or value.
5551227825Stheraven                pat.field[1] = symbol;
5552227825Stheraven                pat.field[2] = space;
5553232950Stheraven                if (symbol_contains_sep) {
5554232950Stheraven                    // Remove the separator from the symbol, since it
5555232950Stheraven                    // should not be removed if showbase is absent.
5556232950Stheraven                    __curr_symbol_.erase(__curr_symbol_.begin());
5557232950Stheraven                }
5558227825Stheraven                return;
5559227825Stheraven            default:
5560227825Stheraven                break;
5561227825Stheraven            }
5562227825Stheraven            break;
5563232950Stheraven        case 3:  // The sign string immediately precedes the currency symbol.
5564227825Stheraven            pat.field[0] = value;
5565227825Stheraven            pat.field[3] = symbol;
5566227825Stheraven            switch (sep_by_space)
5567227825Stheraven            {
5568232950Stheraven            case 0:  // No space separates the currency symbol and value.
5569227825Stheraven                pat.field[1] = none;
5570227825Stheraven                pat.field[2] = sign;
5571227825Stheraven                return;
5572232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5573227825Stheraven                pat.field[1] = space;
5574227825Stheraven                pat.field[2] = sign;
5575232950Stheraven                if (symbol_contains_sep) {
5576232950Stheraven                    // Remove the separator from the symbol, since it
5577232950Stheraven                    // has already appeared before the sign.
5578232950Stheraven                    __curr_symbol_.erase(__curr_symbol_.begin());
5579232950Stheraven                }
5580227825Stheraven                return;
5581232950Stheraven            case 2:  // Space between sign and currency or value.
5582227825Stheraven                pat.field[1] = sign;
5583232950Stheraven                pat.field[2] = none;
5584232950Stheraven                if (!symbol_contains_sep) {
5585232950Stheraven                    // We insert the space into the symbol instead of
5586232950Stheraven                    // setting pat.field[2]=space so that when
5587232950Stheraven                    // showbase is not set, the space goes away too.
5588232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5589232950Stheraven                }
5590227825Stheraven                return;
5591227825Stheraven            default:
5592227825Stheraven                break;
5593227825Stheraven            }
5594227825Stheraven            break;
5595232950Stheraven        case 4:  // The sign string immediately succeeds the currency symbol.
5596227825Stheraven            pat.field[0] = value;
5597227825Stheraven            pat.field[3] = sign;
5598227825Stheraven            switch (sep_by_space)
5599227825Stheraven            {
5600232950Stheraven            case 0:  // No space separates the currency symbol and value.
5601227825Stheraven                pat.field[1] = none;
5602227825Stheraven                pat.field[2] = symbol;
5603227825Stheraven                return;
5604232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5605232950Stheraven                pat.field[1] = none;
5606227825Stheraven                pat.field[2] = symbol;
5607232950Stheraven                if (!symbol_contains_sep) {
5608232950Stheraven                    // We insert the space into the symbol instead of
5609232950Stheraven                    // setting pat.field[1]=space so that when
5610232950Stheraven                    // showbase is not set, the space goes away too.
5611232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5612232950Stheraven                }
5613227825Stheraven                return;
5614232950Stheraven            case 2:  // Space between sign and currency or value.
5615227825Stheraven                pat.field[1] = symbol;
5616227825Stheraven                pat.field[2] = space;
5617232950Stheraven                if (symbol_contains_sep) {
5618232950Stheraven                    // Remove the separator from the symbol, since it
5619232950Stheraven                    // should not disappear when showbase is absent.
5620232950Stheraven                    __curr_symbol_.erase(__curr_symbol_.begin());
5621232950Stheraven                }
5622227825Stheraven                return;
5623227825Stheraven            default:
5624227825Stheraven                break;
5625227825Stheraven            }
5626227825Stheraven            break;
5627227825Stheraven        default:
5628227825Stheraven            break;
5629227825Stheraven        }
5630227825Stheraven        break;
5631232950Stheraven    case 1:  // curr_symbol before value
5632227825Stheraven        switch (sign_posn)
5633227825Stheraven        {
5634232950Stheraven        case 0:  // Parentheses surround the quantity and currency symbol.
5635227825Stheraven            pat.field[0] = sign;
5636227825Stheraven            pat.field[1] = symbol;
5637232950Stheraven            pat.field[2] = none;  // Any space appears in the symbol.
5638227825Stheraven            pat.field[3] = value;
5639227825Stheraven            switch (sep_by_space)
5640227825Stheraven            {
5641232950Stheraven            case 0:  // No space separates the currency symbol and value.
5642232950Stheraven                // This case may have changed between C99 and C11;
5643232950Stheraven                // assume the currency symbol matches the intention.
5644232950Stheraven            case 2:  // Space between sign and currency or value.
5645232950Stheraven                // The "sign" is two parentheses, so no space here either.
5646227825Stheraven                return;
5647232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5648232950Stheraven                if (!symbol_contains_sep) {
5649232950Stheraven                    // We insert the space into the symbol instead of
5650232950Stheraven                    // setting pat.field[2]=space so that when
5651232950Stheraven                    // showbase is not set, the space goes away too.
5652232950Stheraven                    __curr_symbol_.insert(0, 1, space_char);
5653232950Stheraven                }
5654227825Stheraven                return;
5655227825Stheraven            default:
5656227825Stheraven                break;
5657227825Stheraven            }
5658227825Stheraven            break;
5659232950Stheraven        case 1:  // The sign string precedes the quantity and currency symbol.
5660227825Stheraven            pat.field[0] = sign;
5661227825Stheraven            pat.field[3] = value;
5662227825Stheraven            switch (sep_by_space)
5663227825Stheraven            {
5664232950Stheraven            case 0:  // No space separates the currency symbol and value.
5665227825Stheraven                pat.field[1] = symbol;
5666227825Stheraven                pat.field[2] = none;
5667227825Stheraven                return;
5668232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5669227825Stheraven                pat.field[1] = symbol;
5670232950Stheraven                pat.field[2] = none;
5671232950Stheraven                if (!symbol_contains_sep) {
5672232950Stheraven                    // We insert the space into the symbol instead of
5673232950Stheraven                    // setting pat.field[2]=space so that when
5674232950Stheraven                    // showbase is not set, the space goes away too.
5675232950Stheraven                    __curr_symbol_.push_back(space_char);
5676232950Stheraven                }
5677227825Stheraven                return;
5678232950Stheraven            case 2:  // Space between sign and currency or value.
5679227825Stheraven                pat.field[1] = space;
5680227825Stheraven                pat.field[2] = symbol;
5681232950Stheraven                if (symbol_contains_sep) {
5682232950Stheraven                    // Remove the separator from the symbol, since it
5683232950Stheraven                    // has already appeared after the sign.
5684232950Stheraven                    __curr_symbol_.pop_back();
5685232950Stheraven                }
5686227825Stheraven                return;
5687227825Stheraven            default:
5688227825Stheraven                break;
5689227825Stheraven            }
5690227825Stheraven            break;
5691232950Stheraven        case 2:  // The sign string succeeds the quantity and currency symbol.
5692227825Stheraven            pat.field[0] = symbol;
5693227825Stheraven            pat.field[3] = sign;
5694227825Stheraven            switch (sep_by_space)
5695227825Stheraven            {
5696232950Stheraven            case 0:  // No space separates the currency symbol and value.
5697227825Stheraven                pat.field[1] = none;
5698227825Stheraven                pat.field[2] = value;
5699227825Stheraven                return;
5700232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5701232950Stheraven                pat.field[1] = none;
5702227825Stheraven                pat.field[2] = value;
5703232950Stheraven                if (!symbol_contains_sep) {
5704232950Stheraven                    // We insert the space into the symbol instead of
5705232950Stheraven                    // setting pat.field[1]=space so that when
5706232950Stheraven                    // showbase is not set, the space goes away too.
5707232950Stheraven                    __curr_symbol_.push_back(space_char);
5708232950Stheraven                }
5709227825Stheraven                return;
5710232950Stheraven            case 2:  // Space between sign and currency or value.
5711227825Stheraven                pat.field[1] = value;
5712227825Stheraven                pat.field[2] = space;
5713232950Stheraven                if (symbol_contains_sep) {
5714232950Stheraven                    // Remove the separator from the symbol, since it
5715232950Stheraven                    // will appear before the sign.
5716232950Stheraven                    __curr_symbol_.pop_back();
5717232950Stheraven                }
5718227825Stheraven                return;
5719227825Stheraven            default:
5720227825Stheraven                break;
5721227825Stheraven            }
5722227825Stheraven            break;
5723232950Stheraven        case 3:  // The sign string immediately precedes the currency symbol.
5724227825Stheraven            pat.field[0] = sign;
5725227825Stheraven            pat.field[3] = value;
5726227825Stheraven            switch (sep_by_space)
5727227825Stheraven            {
5728232950Stheraven            case 0:  // No space separates the currency symbol and value.
5729227825Stheraven                pat.field[1] = symbol;
5730227825Stheraven                pat.field[2] = none;
5731227825Stheraven                return;
5732232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5733227825Stheraven                pat.field[1] = symbol;
5734232950Stheraven                pat.field[2] = none;
5735232950Stheraven                if (!symbol_contains_sep) {
5736232950Stheraven                    // We insert the space into the symbol instead of
5737232950Stheraven                    // setting pat.field[2]=space so that when
5738232950Stheraven                    // showbase is not set, the space goes away too.
5739232950Stheraven                    __curr_symbol_.push_back(space_char);
5740232950Stheraven                }
5741227825Stheraven                return;
5742232950Stheraven            case 2:  // Space between sign and currency or value.
5743227825Stheraven                pat.field[1] = space;
5744227825Stheraven                pat.field[2] = symbol;
5745232950Stheraven                if (symbol_contains_sep) {
5746232950Stheraven                    // Remove the separator from the symbol, since it
5747232950Stheraven                    // has already appeared after the sign.
5748232950Stheraven                    __curr_symbol_.pop_back();
5749232950Stheraven                }
5750227825Stheraven                return;
5751227825Stheraven            default:
5752227825Stheraven                break;
5753227825Stheraven            }
5754227825Stheraven            break;
5755232950Stheraven        case 4:  // The sign string immediately succeeds the currency symbol.
5756227825Stheraven            pat.field[0] = symbol;
5757227825Stheraven            pat.field[3] = value;
5758227825Stheraven            switch (sep_by_space)
5759227825Stheraven            {
5760232950Stheraven            case 0:  // No space separates the currency symbol and value.
5761227825Stheraven                pat.field[1] = sign;
5762227825Stheraven                pat.field[2] = none;
5763227825Stheraven                return;
5764232950Stheraven            case 1:  // Space between currency-and-sign or currency and value.
5765227825Stheraven                pat.field[1] = sign;
5766227825Stheraven                pat.field[2] = space;
5767232950Stheraven                if (symbol_contains_sep) {
5768232950Stheraven                    // Remove the separator from the symbol, since it
5769232950Stheraven                    // should not disappear when showbase is absent.
5770232950Stheraven                    __curr_symbol_.pop_back();
5771232950Stheraven                }
5772227825Stheraven                return;
5773232950Stheraven            case 2:  // Space between sign and currency or value.
5774232950Stheraven                pat.field[1] = none;
5775227825Stheraven                pat.field[2] = sign;
5776232950Stheraven                if (!symbol_contains_sep) {
5777232950Stheraven                    // We insert the space into the symbol instead of
5778232950Stheraven                    // setting pat.field[1]=space so that when
5779232950Stheraven                    // showbase is not set, the space goes away too.
5780232950Stheraven                    __curr_symbol_.push_back(space_char);
5781232950Stheraven                }
5782227825Stheraven                return;
5783227825Stheraven           default:
5784227825Stheraven                break;
5785227825Stheraven            }
5786227825Stheraven            break;
5787227825Stheraven        default:
5788227825Stheraven            break;
5789227825Stheraven        }
5790227825Stheraven        break;
5791227825Stheraven    default:
5792227825Stheraven        break;
5793227825Stheraven    }
5794227825Stheraven    pat.field[0] = symbol;
5795227825Stheraven    pat.field[1] = sign;
5796227825Stheraven    pat.field[2] = none;
5797227825Stheraven    pat.field[3] = value;
5798227825Stheraven}
5799227825Stheraven
5800227825Stheraventemplate<>
5801227825Stheravenvoid
5802227825Stheravenmoneypunct_byname<char, false>::init(const char* nm)
5803227825Stheraven{
5804227825Stheraven    typedef moneypunct<char, false> base;
5805227825Stheraven    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
5806227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5807232950Stheraven    if (loc == nullptr)
5808227825Stheraven        throw runtime_error("moneypunct_byname"
5809227825Stheraven                            " failed to construct for " + string(nm));
5810227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5811227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5812227825Stheraven    lconv* lc = localeconv_l(loc.get());
5813227825Stheraven#else
5814227825Stheraven    lconv* lc = __localeconv_l(loc.get());
5815227825Stheraven#endif
5816227825Stheraven    if (*lc->mon_decimal_point)
5817227825Stheraven        __decimal_point_ = *lc->mon_decimal_point;
5818227825Stheraven    else
5819227825Stheraven        __decimal_point_ = base::do_decimal_point();
5820227825Stheraven    if (*lc->mon_thousands_sep)
5821227825Stheraven        __thousands_sep_ = *lc->mon_thousands_sep;
5822227825Stheraven    else
5823227825Stheraven        __thousands_sep_ = base::do_thousands_sep();
5824227825Stheraven    __grouping_ = lc->mon_grouping;
5825227825Stheraven    __curr_symbol_ = lc->currency_symbol;
5826227825Stheraven    if (lc->frac_digits != CHAR_MAX)
5827227825Stheraven        __frac_digits_ = lc->frac_digits;
5828227825Stheraven    else
5829227825Stheraven        __frac_digits_ = base::do_frac_digits();
5830227825Stheraven    if (lc->p_sign_posn == 0)
5831227825Stheraven        __positive_sign_ = "()";
5832227825Stheraven    else
5833227825Stheraven        __positive_sign_ = lc->positive_sign;
5834227825Stheraven    if (lc->n_sign_posn == 0)
5835227825Stheraven        __negative_sign_ = "()";
5836227825Stheraven    else
5837227825Stheraven        __negative_sign_ = lc->negative_sign;
5838232950Stheraven    // Assume the positive and negative formats will want spaces in
5839232950Stheraven    // the same places in curr_symbol since there's no way to
5840232950Stheraven    // represent anything else.
5841232950Stheraven    string_type __dummy_curr_symbol = __curr_symbol_;
5842232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, false,
5843232950Stheraven               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5844232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, false,
5845232950Stheraven               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
5846227825Stheraven}
5847227825Stheraven
5848227825Stheraventemplate<>
5849227825Stheravenvoid
5850227825Stheravenmoneypunct_byname<char, true>::init(const char* nm)
5851227825Stheraven{
5852227825Stheraven    typedef moneypunct<char, true> base;
5853227825Stheraven    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
5854227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5855232950Stheraven    if (loc == nullptr)
5856227825Stheraven        throw runtime_error("moneypunct_byname"
5857227825Stheraven                            " failed to construct for " + string(nm));
5858227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5859227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5860227825Stheraven    lconv* lc = localeconv_l(loc.get());
5861227825Stheraven#else
5862227825Stheraven    lconv* lc = __localeconv_l(loc.get());
5863227825Stheraven#endif
5864227825Stheraven    if (*lc->mon_decimal_point)
5865227825Stheraven        __decimal_point_ = *lc->mon_decimal_point;
5866227825Stheraven    else
5867227825Stheraven        __decimal_point_ = base::do_decimal_point();
5868227825Stheraven    if (*lc->mon_thousands_sep)
5869227825Stheraven        __thousands_sep_ = *lc->mon_thousands_sep;
5870227825Stheraven    else
5871227825Stheraven        __thousands_sep_ = base::do_thousands_sep();
5872227825Stheraven    __grouping_ = lc->mon_grouping;
5873227825Stheraven    __curr_symbol_ = lc->int_curr_symbol;
5874227825Stheraven    if (lc->int_frac_digits != CHAR_MAX)
5875227825Stheraven        __frac_digits_ = lc->int_frac_digits;
5876227825Stheraven    else
5877227825Stheraven        __frac_digits_ = base::do_frac_digits();
5878262801Sdim#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
5879227825Stheraven    if (lc->p_sign_posn == 0)
5880262801Sdim#else // _LIBCPP_MSVCRT
5881227825Stheraven    if (lc->int_p_sign_posn == 0)
5882262801Sdim#endif // !_LIBCPP_MSVCRT
5883227825Stheraven        __positive_sign_ = "()";
5884227825Stheraven    else
5885227825Stheraven        __positive_sign_ = lc->positive_sign;
5886262801Sdim#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
5887227825Stheraven    if(lc->n_sign_posn == 0)
5888262801Sdim#else // _LIBCPP_MSVCRT
5889227825Stheraven    if (lc->int_n_sign_posn == 0)
5890262801Sdim#endif // !_LIBCPP_MSVCRT
5891227825Stheraven        __negative_sign_ = "()";
5892227825Stheraven    else
5893227825Stheraven        __negative_sign_ = lc->negative_sign;
5894232950Stheraven    // Assume the positive and negative formats will want spaces in
5895232950Stheraven    // the same places in curr_symbol since there's no way to
5896232950Stheraven    // represent anything else.
5897232950Stheraven    string_type __dummy_curr_symbol = __curr_symbol_;
5898262801Sdim#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
5899232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, true,
5900232950Stheraven               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5901232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, true,
5902232950Stheraven               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
5903262801Sdim#else // _LIBCPP_MSVCRT
5904232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, true,
5905232950Stheraven               lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5906232950Stheraven               lc->int_p_sign_posn, ' ');
5907232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, true,
5908232950Stheraven               lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5909232950Stheraven               lc->int_n_sign_posn, ' ');
5910262801Sdim#endif // !_LIBCPP_MSVCRT
5911227825Stheraven}
5912227825Stheraven
5913227825Stheraventemplate<>
5914227825Stheravenvoid
5915227825Stheravenmoneypunct_byname<wchar_t, false>::init(const char* nm)
5916227825Stheraven{
5917227825Stheraven    typedef moneypunct<wchar_t, false> base;
5918227825Stheraven    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
5919227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
5920232950Stheraven    if (loc == nullptr)
5921227825Stheraven        throw runtime_error("moneypunct_byname"
5922227825Stheraven                            " failed to construct for " + string(nm));
5923227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
5924227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5925227825Stheraven    lconv* lc = localeconv_l(loc.get());
5926227825Stheraven#else
5927227825Stheraven    lconv* lc = __localeconv_l(loc.get());
5928227825Stheraven#endif
5929227825Stheraven    if (*lc->mon_decimal_point)
5930227825Stheraven        __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5931227825Stheraven    else
5932227825Stheraven        __decimal_point_ = base::do_decimal_point();
5933227825Stheraven    if (*lc->mon_thousands_sep)
5934227825Stheraven        __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5935227825Stheraven    else
5936227825Stheraven        __thousands_sep_ = base::do_thousands_sep();
5937227825Stheraven    __grouping_ = lc->mon_grouping;
5938227825Stheraven    wchar_t wbuf[100];
5939227825Stheraven    mbstate_t mb = {0};
5940227825Stheraven    const char* bb = lc->currency_symbol;
5941227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5942246487Stheraven    size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5943227825Stheraven#else
5944246487Stheraven    size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5945227825Stheraven#endif
5946232950Stheraven    if (j == size_t(-1))
5947227825Stheraven        __throw_runtime_error("locale not supported");
5948227825Stheraven    wchar_t* wbe = wbuf + j;
5949227825Stheraven    __curr_symbol_.assign(wbuf, wbe);
5950227825Stheraven    if (lc->frac_digits != CHAR_MAX)
5951227825Stheraven        __frac_digits_ = lc->frac_digits;
5952227825Stheraven    else
5953227825Stheraven        __frac_digits_ = base::do_frac_digits();
5954227825Stheraven    if (lc->p_sign_posn == 0)
5955227825Stheraven        __positive_sign_ = L"()";
5956227825Stheraven    else
5957227825Stheraven    {
5958227825Stheraven        mb = mbstate_t();
5959227825Stheraven        bb = lc->positive_sign;
5960227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5961246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5962227825Stheraven#else
5963246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5964227825Stheraven#endif
5965232950Stheraven        if (j == size_t(-1))
5966227825Stheraven            __throw_runtime_error("locale not supported");
5967227825Stheraven        wbe = wbuf + j;
5968227825Stheraven        __positive_sign_.assign(wbuf, wbe);
5969227825Stheraven    }
5970227825Stheraven    if (lc->n_sign_posn == 0)
5971227825Stheraven        __negative_sign_ = L"()";
5972227825Stheraven    else
5973227825Stheraven    {
5974227825Stheraven        mb = mbstate_t();
5975227825Stheraven        bb = lc->negative_sign;
5976227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5977246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5978227825Stheraven#else
5979246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
5980227825Stheraven#endif
5981232950Stheraven        if (j == size_t(-1))
5982227825Stheraven            __throw_runtime_error("locale not supported");
5983227825Stheraven        wbe = wbuf + j;
5984227825Stheraven        __negative_sign_.assign(wbuf, wbe);
5985227825Stheraven    }
5986232950Stheraven    // Assume the positive and negative formats will want spaces in
5987232950Stheraven    // the same places in curr_symbol since there's no way to
5988232950Stheraven    // represent anything else.
5989232950Stheraven    string_type __dummy_curr_symbol = __curr_symbol_;
5990232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, false,
5991232950Stheraven               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5992232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, false,
5993232950Stheraven               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
5994227825Stheraven}
5995227825Stheraven
5996227825Stheraventemplate<>
5997227825Stheravenvoid
5998227825Stheravenmoneypunct_byname<wchar_t, true>::init(const char* nm)
5999227825Stheraven{
6000227825Stheraven    typedef moneypunct<wchar_t, true> base;
6001227825Stheraven    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
6002227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
6003232950Stheraven    if (loc == nullptr)
6004227825Stheraven        throw runtime_error("moneypunct_byname"
6005227825Stheraven                            " failed to construct for " + string(nm));
6006227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
6007227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6008227825Stheraven    lconv* lc = localeconv_l(loc.get());
6009227825Stheraven#else
6010227825Stheraven    lconv* lc = __localeconv_l(loc.get());
6011227825Stheraven#endif
6012227825Stheraven    if (*lc->mon_decimal_point)
6013227825Stheraven        __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6014227825Stheraven    else
6015227825Stheraven        __decimal_point_ = base::do_decimal_point();
6016227825Stheraven    if (*lc->mon_thousands_sep)
6017227825Stheraven        __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6018227825Stheraven    else
6019227825Stheraven        __thousands_sep_ = base::do_thousands_sep();
6020227825Stheraven    __grouping_ = lc->mon_grouping;
6021227825Stheraven    wchar_t wbuf[100];
6022227825Stheraven    mbstate_t mb = {0};
6023227825Stheraven    const char* bb = lc->int_curr_symbol;
6024227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6025246487Stheraven    size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6026227825Stheraven#else
6027246487Stheraven    size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6028227825Stheraven#endif
6029232950Stheraven    if (j == size_t(-1))
6030227825Stheraven        __throw_runtime_error("locale not supported");
6031227825Stheraven    wchar_t* wbe = wbuf + j;
6032227825Stheraven    __curr_symbol_.assign(wbuf, wbe);
6033227825Stheraven    if (lc->int_frac_digits != CHAR_MAX)
6034227825Stheraven        __frac_digits_ = lc->int_frac_digits;
6035227825Stheraven    else
6036227825Stheraven        __frac_digits_ = base::do_frac_digits();
6037262801Sdim#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6038227825Stheraven    if (lc->p_sign_posn == 0)
6039262801Sdim#else // _LIBCPP_MSVCRT
6040227825Stheraven    if (lc->int_p_sign_posn == 0)
6041262801Sdim#endif // !_LIBCPP_MSVCRT
6042227825Stheraven        __positive_sign_ = L"()";
6043227825Stheraven    else
6044227825Stheraven    {
6045227825Stheraven        mb = mbstate_t();
6046227825Stheraven        bb = lc->positive_sign;
6047227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6048246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6049227825Stheraven#else
6050246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6051227825Stheraven#endif
6052232950Stheraven        if (j == size_t(-1))
6053227825Stheraven            __throw_runtime_error("locale not supported");
6054227825Stheraven        wbe = wbuf + j;
6055227825Stheraven        __positive_sign_.assign(wbuf, wbe);
6056227825Stheraven    }
6057262801Sdim#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6058227825Stheraven    if (lc->n_sign_posn == 0)
6059262801Sdim#else // _LIBCPP_MSVCRT
6060227825Stheraven    if (lc->int_n_sign_posn == 0)
6061262801Sdim#endif // !_LIBCPP_MSVCRT
6062227825Stheraven        __negative_sign_ = L"()";
6063227825Stheraven    else
6064227825Stheraven    {
6065227825Stheraven        mb = mbstate_t();
6066227825Stheraven        bb = lc->negative_sign;
6067227825Stheraven#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6068246487Stheraven        j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6069227825Stheraven#else
6070246487Stheraven        j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6071227825Stheraven#endif
6072232950Stheraven        if (j == size_t(-1))
6073227825Stheraven            __throw_runtime_error("locale not supported");
6074227825Stheraven        wbe = wbuf + j;
6075227825Stheraven        __negative_sign_.assign(wbuf, wbe);
6076227825Stheraven    }
6077232950Stheraven    // Assume the positive and negative formats will want spaces in
6078232950Stheraven    // the same places in curr_symbol since there's no way to
6079232950Stheraven    // represent anything else.
6080232950Stheraven    string_type __dummy_curr_symbol = __curr_symbol_;
6081262801Sdim#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6082232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, true,
6083232950Stheraven               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6084232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, true,
6085232950Stheraven               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6086262801Sdim#else // _LIBCPP_MSVCRT
6087232950Stheraven    __init_pat(__pos_format_, __dummy_curr_symbol, true,
6088232950Stheraven               lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6089232950Stheraven               lc->int_p_sign_posn, L' ');
6090232950Stheraven    __init_pat(__neg_format_, __curr_symbol_, true,
6091232950Stheraven               lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6092232950Stheraven               lc->int_n_sign_posn, L' ');
6093262801Sdim#endif // !_LIBCPP_MSVCRT
6094227825Stheraven}
6095227825Stheraven
6096227825Stheravenvoid __do_nothing(void*) {}
6097227825Stheraven
6098227825Stheravenvoid __throw_runtime_error(const char* msg)
6099227825Stheraven{
6100227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
6101227825Stheraven    throw runtime_error(msg);
6102249998Sdim#else
6103249998Sdim    (void)msg;
6104227825Stheraven#endif
6105227825Stheraven}
6106227825Stheraven
6107227825Stheraventemplate class collate<char>;
6108227825Stheraventemplate class collate<wchar_t>;
6109227825Stheraven
6110227825Stheraventemplate class num_get<char>;
6111227825Stheraventemplate class num_get<wchar_t>;
6112227825Stheraven
6113232950Stheraventemplate struct __num_get<char>;
6114232950Stheraventemplate struct __num_get<wchar_t>;
6115227825Stheraven
6116227825Stheraventemplate class num_put<char>;
6117227825Stheraventemplate class num_put<wchar_t>;
6118227825Stheraven
6119232950Stheraventemplate struct __num_put<char>;
6120232950Stheraventemplate struct __num_put<wchar_t>;
6121227825Stheraven
6122227825Stheraventemplate class time_get<char>;
6123227825Stheraventemplate class time_get<wchar_t>;
6124227825Stheraven
6125227825Stheraventemplate class time_get_byname<char>;
6126227825Stheraventemplate class time_get_byname<wchar_t>;
6127227825Stheraven
6128227825Stheraventemplate class time_put<char>;
6129227825Stheraventemplate class time_put<wchar_t>;
6130227825Stheraven
6131227825Stheraventemplate class time_put_byname<char>;
6132227825Stheraventemplate class time_put_byname<wchar_t>;
6133227825Stheraven
6134227825Stheraventemplate class moneypunct<char, false>;
6135227825Stheraventemplate class moneypunct<char, true>;
6136227825Stheraventemplate class moneypunct<wchar_t, false>;
6137227825Stheraventemplate class moneypunct<wchar_t, true>;
6138227825Stheraven
6139227825Stheraventemplate class moneypunct_byname<char, false>;
6140227825Stheraventemplate class moneypunct_byname<char, true>;
6141227825Stheraventemplate class moneypunct_byname<wchar_t, false>;
6142227825Stheraventemplate class moneypunct_byname<wchar_t, true>;
6143227825Stheraven
6144227825Stheraventemplate class money_get<char>;
6145227825Stheraventemplate class money_get<wchar_t>;
6146227825Stheraven
6147227825Stheraventemplate class __money_get<char>;
6148227825Stheraventemplate class __money_get<wchar_t>;
6149227825Stheraven
6150227825Stheraventemplate class money_put<char>;
6151227825Stheraventemplate class money_put<wchar_t>;
6152227825Stheraven
6153227825Stheraventemplate class __money_put<char>;
6154227825Stheraventemplate class __money_put<wchar_t>;
6155227825Stheraven
6156227825Stheraventemplate class messages<char>;
6157227825Stheraventemplate class messages<wchar_t>;
6158227825Stheraven
6159227825Stheraventemplate class messages_byname<char>;
6160227825Stheraventemplate class messages_byname<wchar_t>;
6161227825Stheraven
6162227825Stheraventemplate class codecvt_byname<char, char, mbstate_t>;
6163227825Stheraventemplate class codecvt_byname<wchar_t, char, mbstate_t>;
6164227825Stheraventemplate class codecvt_byname<char16_t, char, mbstate_t>;
6165227825Stheraventemplate class codecvt_byname<char32_t, char, mbstate_t>;
6166227825Stheraven
6167227825Stheraventemplate class __vector_base_common<true>;
6168227825Stheraven
6169227825Stheraven_LIBCPP_END_NAMESPACE_STD
6170