xref: /freebsd-12.1/contrib/libc++/include/locale (revision b5893f02)
17a984708SDavid Chisnall// -*- C++ -*-
27a984708SDavid Chisnall//===-------------------------- locale ------------------------------------===//
37a984708SDavid Chisnall//
47a984708SDavid Chisnall//                     The LLVM Compiler Infrastructure
57a984708SDavid Chisnall//
67a984708SDavid Chisnall// This file is dual licensed under the MIT and the University of Illinois Open
77a984708SDavid Chisnall// Source Licenses. See LICENSE.TXT for details.
87a984708SDavid Chisnall//
97a984708SDavid Chisnall//===----------------------------------------------------------------------===//
107a984708SDavid Chisnall
117a984708SDavid Chisnall#ifndef _LIBCPP_LOCALE
127a984708SDavid Chisnall#define _LIBCPP_LOCALE
137a984708SDavid Chisnall
147a984708SDavid Chisnall/*
157a984708SDavid Chisnall    locale synopsis
167a984708SDavid Chisnall
177a984708SDavid Chisnallnamespace std
187a984708SDavid Chisnall{
197a984708SDavid Chisnall
207a984708SDavid Chisnallclass locale
217a984708SDavid Chisnall{
227a984708SDavid Chisnallpublic:
237a984708SDavid Chisnall    // types:
247a984708SDavid Chisnall    class facet;
257a984708SDavid Chisnall    class id;
267a984708SDavid Chisnall
277a984708SDavid Chisnall    typedef int category;
287a984708SDavid Chisnall    static const category // values assigned here are for exposition only
297a984708SDavid Chisnall        none     = 0x000,
307a984708SDavid Chisnall        collate  = 0x010,
317a984708SDavid Chisnall        ctype    = 0x020,
327a984708SDavid Chisnall        monetary = 0x040,
337a984708SDavid Chisnall        numeric  = 0x080,
347a984708SDavid Chisnall        time     = 0x100,
357a984708SDavid Chisnall        messages = 0x200,
367a984708SDavid Chisnall        all = collate | ctype | monetary | numeric | time | messages;
377a984708SDavid Chisnall
387a984708SDavid Chisnall    // construct/copy/destroy:
397a984708SDavid Chisnall    locale() noexcept;
407a984708SDavid Chisnall    locale(const locale& other) noexcept;
417a984708SDavid Chisnall    explicit locale(const char* std_name);
427a984708SDavid Chisnall    explicit locale(const string& std_name);
437a984708SDavid Chisnall    locale(const locale& other, const char* std_name, category);
447a984708SDavid Chisnall    locale(const locale& other, const string& std_name, category);
457a984708SDavid Chisnall    template <class Facet> locale(const locale& other, Facet* f);
467a984708SDavid Chisnall    locale(const locale& other, const locale& one, category);
477a984708SDavid Chisnall
487a984708SDavid Chisnall    ~locale(); // not virtual
497a984708SDavid Chisnall
507a984708SDavid Chisnall    const locale& operator=(const locale& other) noexcept;
517a984708SDavid Chisnall
527a984708SDavid Chisnall    template <class Facet> locale combine(const locale& other) const;
537a984708SDavid Chisnall
547a984708SDavid Chisnall    // locale operations:
557a984708SDavid Chisnall    basic_string<char> name() const;
567a984708SDavid Chisnall    bool operator==(const locale& other) const;
577a984708SDavid Chisnall    bool operator!=(const locale& other) const;
587a984708SDavid Chisnall    template <class charT, class Traits, class Allocator>
597a984708SDavid Chisnall      bool operator()(const basic_string<charT,Traits,Allocator>& s1,
607a984708SDavid Chisnall                      const basic_string<charT,Traits,Allocator>& s2) const;
617a984708SDavid Chisnall
627a984708SDavid Chisnall    // global locale objects:
637a984708SDavid Chisnall    static locale global(const locale&);
647a984708SDavid Chisnall    static const locale& classic();
657a984708SDavid Chisnall};
667a984708SDavid Chisnall
677a984708SDavid Chisnalltemplate <class Facet> const Facet& use_facet(const locale&);
687a984708SDavid Chisnalltemplate <class Facet> bool has_facet(const locale&) noexcept;
697a984708SDavid Chisnall
707a984708SDavid Chisnall// 22.3.3, convenience interfaces:
717a984708SDavid Chisnalltemplate <class charT> bool isspace (charT c, const locale& loc);
727a984708SDavid Chisnalltemplate <class charT> bool isprint (charT c, const locale& loc);
737a984708SDavid Chisnalltemplate <class charT> bool iscntrl (charT c, const locale& loc);
747a984708SDavid Chisnalltemplate <class charT> bool isupper (charT c, const locale& loc);
757a984708SDavid Chisnalltemplate <class charT> bool islower (charT c, const locale& loc);
767a984708SDavid Chisnalltemplate <class charT> bool isalpha (charT c, const locale& loc);
777a984708SDavid Chisnalltemplate <class charT> bool isdigit (charT c, const locale& loc);
787a984708SDavid Chisnalltemplate <class charT> bool ispunct (charT c, const locale& loc);
797a984708SDavid Chisnalltemplate <class charT> bool isxdigit(charT c, const locale& loc);
807a984708SDavid Chisnalltemplate <class charT> bool isalnum (charT c, const locale& loc);
817a984708SDavid Chisnalltemplate <class charT> bool isgraph (charT c, const locale& loc);
827a984708SDavid Chisnalltemplate <class charT> charT toupper(charT c, const locale& loc);
837a984708SDavid Chisnalltemplate <class charT> charT tolower(charT c, const locale& loc);
847a984708SDavid Chisnall
857a984708SDavid Chisnalltemplate<class Codecvt, class Elem = wchar_t,
867a984708SDavid Chisnall         class Wide_alloc = allocator<Elem>,
877a984708SDavid Chisnall         class Byte_alloc = allocator<char>>
887a984708SDavid Chisnallclass wstring_convert
897a984708SDavid Chisnall{
907a984708SDavid Chisnallpublic:
917a984708SDavid Chisnall    typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
927a984708SDavid Chisnall    typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
937a984708SDavid Chisnall    typedef typename Codecvt::state_type                      state_type;
947a984708SDavid Chisnall    typedef typename wide_string::traits_type::int_type       int_type;
957a984708SDavid Chisnall
964f7ab58eSDimitry Andric    explicit wstring_convert(Codecvt* pcvt = new Codecvt);          // explicit in C++14
977a984708SDavid Chisnall    wstring_convert(Codecvt* pcvt, state_type state);
984f7ab58eSDimitry Andric    explicit wstring_convert(const byte_string& byte_err,           // explicit in C++14
997a984708SDavid Chisnall                    const wide_string& wide_err = wide_string());
1004f7ab58eSDimitry Andric    wstring_convert(const wstring_convert&) = delete;               // C++14
1014f7ab58eSDimitry Andric    wstring_convert & operator=(const wstring_convert &) = delete;  // C++14
1027a984708SDavid Chisnall    ~wstring_convert();
1037a984708SDavid Chisnall
1047a984708SDavid Chisnall    wide_string from_bytes(char byte);
1057a984708SDavid Chisnall    wide_string from_bytes(const char* ptr);
1067a984708SDavid Chisnall    wide_string from_bytes(const byte_string& str);
1077a984708SDavid Chisnall    wide_string from_bytes(const char* first, const char* last);
1087a984708SDavid Chisnall
1097a984708SDavid Chisnall    byte_string to_bytes(Elem wchar);
1107a984708SDavid Chisnall    byte_string to_bytes(const Elem* wptr);
1117a984708SDavid Chisnall    byte_string to_bytes(const wide_string& wstr);
1127a984708SDavid Chisnall    byte_string to_bytes(const Elem* first, const Elem* last);
1137a984708SDavid Chisnall
1144f7ab58eSDimitry Andric    size_t converted() const; // noexcept in C++14
1157a984708SDavid Chisnall    state_type state() const;
1167a984708SDavid Chisnall};
1177a984708SDavid Chisnall
1187a984708SDavid Chisnalltemplate <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
1197a984708SDavid Chisnallclass wbuffer_convert
1207a984708SDavid Chisnall    : public basic_streambuf<Elem, Tr>
1217a984708SDavid Chisnall{
1227a984708SDavid Chisnallpublic:
1237a984708SDavid Chisnall    typedef typename Tr::state_type state_type;
1247a984708SDavid Chisnall
1254f7ab58eSDimitry Andric    explicit wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
1264f7ab58eSDimitry Andric                    state_type state = state_type());       // explicit in C++14
1274f7ab58eSDimitry Andric    wbuffer_convert(const wbuffer_convert&) = delete;               // C++14
1284f7ab58eSDimitry Andric    wbuffer_convert & operator=(const wbuffer_convert &) = delete;  // C++14
1294f7ab58eSDimitry Andric    ~wbuffer_convert();                                             // C++14
1307a984708SDavid Chisnall
1317a984708SDavid Chisnall    streambuf* rdbuf() const;
1327a984708SDavid Chisnall    streambuf* rdbuf(streambuf* bytebuf);
1337a984708SDavid Chisnall
1347a984708SDavid Chisnall    state_type state() const;
1357a984708SDavid Chisnall};
1367a984708SDavid Chisnall
1377a984708SDavid Chisnall// 22.4.1 and 22.4.1.3, ctype:
1387a984708SDavid Chisnallclass ctype_base;
1397a984708SDavid Chisnalltemplate <class charT> class ctype;
1407a984708SDavid Chisnalltemplate <> class ctype<char>; // specialization
1417a984708SDavid Chisnalltemplate <class charT> class ctype_byname;
1427a984708SDavid Chisnalltemplate <> class ctype_byname<char>; // specialization
1437a984708SDavid Chisnall
1447a984708SDavid Chisnallclass codecvt_base;
1457a984708SDavid Chisnalltemplate <class internT, class externT, class stateT> class codecvt;
1467a984708SDavid Chisnalltemplate <class internT, class externT, class stateT> class codecvt_byname;
1477a984708SDavid Chisnall
1487a984708SDavid Chisnall// 22.4.2 and 22.4.3, numeric:
1497a984708SDavid Chisnalltemplate <class charT, class InputIterator> class num_get;
1507a984708SDavid Chisnalltemplate <class charT, class OutputIterator> class num_put;
1517a984708SDavid Chisnalltemplate <class charT> class numpunct;
1527a984708SDavid Chisnalltemplate <class charT> class numpunct_byname;
1537a984708SDavid Chisnall
1547a984708SDavid Chisnall// 22.4.4, col lation:
1557a984708SDavid Chisnalltemplate <class charT> class collate;
1567a984708SDavid Chisnalltemplate <class charT> class collate_byname;
1577a984708SDavid Chisnall
1587a984708SDavid Chisnall// 22.4.5, date and time:
1597a984708SDavid Chisnallclass time_base;
1607a984708SDavid Chisnalltemplate <class charT, class InputIterator> class time_get;
1617a984708SDavid Chisnalltemplate <class charT, class InputIterator> class time_get_byname;
1627a984708SDavid Chisnalltemplate <class charT, class OutputIterator> class time_put;
1637a984708SDavid Chisnalltemplate <class charT, class OutputIterator> class time_put_byname;
1647a984708SDavid Chisnall
1657a984708SDavid Chisnall// 22.4.6, money:
1667a984708SDavid Chisnallclass money_base;
1677a984708SDavid Chisnalltemplate <class charT, class InputIterator> class money_get;
1687a984708SDavid Chisnalltemplate <class charT, class OutputIterator> class money_put;
1697a984708SDavid Chisnalltemplate <class charT, bool Intl> class moneypunct;
1707a984708SDavid Chisnalltemplate <class charT, bool Intl> class moneypunct_byname;
1717a984708SDavid Chisnall
1727a984708SDavid Chisnall// 22.4.7, message retrieval:
1737a984708SDavid Chisnallclass messages_base;
1747a984708SDavid Chisnalltemplate <class charT> class messages;
1757a984708SDavid Chisnalltemplate <class charT> class messages_byname;
1767a984708SDavid Chisnall
1777a984708SDavid Chisnall}  // std
1787a984708SDavid Chisnall
1797a984708SDavid Chisnall*/
1807a984708SDavid Chisnall
1817a984708SDavid Chisnall#include <__config>
1827a984708SDavid Chisnall#include <__locale>
1837c82a1ecSDimitry Andric#include <__debug>
1847a984708SDavid Chisnall#include <algorithm>
1857a984708SDavid Chisnall#include <memory>
1867a984708SDavid Chisnall#include <ios>
1877a984708SDavid Chisnall#include <streambuf>
1887a984708SDavid Chisnall#include <iterator>
1897a984708SDavid Chisnall#include <limits>
190*b5893f02SDimitry Andric#include <version>
1911bf9f7c1SDimitry Andric#ifndef __APPLE__
1927a984708SDavid Chisnall#include <cstdarg>
1937a984708SDavid Chisnall#endif
1947a984708SDavid Chisnall#include <cstdlib>
1957a984708SDavid Chisnall#include <ctime>
196f9448bf3SDimitry Andric#include <cstdio>
197854fa44bSDimitry Andric#ifdef _LIBCPP_HAS_CATOPEN
1987a984708SDavid Chisnall#include <nl_types.h>
199d72607e9SDimitry Andric#endif
2007a984708SDavid Chisnall
2011bf9f7c1SDimitry Andric#ifdef __APPLE__
202fb6c5de6SDavid Chisnall#include <Availability.h>
203fb6c5de6SDavid Chisnall#endif
204fb6c5de6SDavid Chisnall
2057c82a1ecSDimitry Andric#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
2067c82a1ecSDimitry Andric#include <__bsd_locale_defaults.h>
2077c82a1ecSDimitry Andric#else
2087c82a1ecSDimitry Andric#include <__bsd_locale_fallbacks.h>
2097c82a1ecSDimitry Andric#endif
2107c82a1ecSDimitry Andric
211f9448bf3SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
212f9448bf3SDimitry Andric#pragma GCC system_header
213f9448bf3SDimitry Andric#endif
214f9448bf3SDimitry Andric
215f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS
216f9448bf3SDimitry Andric#include <__undef_macros>
217f9448bf3SDimitry Andric
218f9448bf3SDimitry Andric
2197a984708SDavid Chisnall_LIBCPP_BEGIN_NAMESPACE_STD
2207a984708SDavid Chisnall
2211bf9f7c1SDimitry Andric#if defined(__APPLE__) || defined(__FreeBSD__)
2227a984708SDavid Chisnall#  define _LIBCPP_GET_C_LOCALE 0
223854fa44bSDimitry Andric#elif defined(__CloudABI__) || defined(__NetBSD__)
2244bab9fd9SDavid Chisnall#  define _LIBCPP_GET_C_LOCALE LC_C_LOCALE
2257a984708SDavid Chisnall#else
2267a984708SDavid Chisnall#  define _LIBCPP_GET_C_LOCALE __cloc()
2277a984708SDavid Chisnall   // Get the C locale object
2284f7ab58eSDimitry Andric   _LIBCPP_FUNC_VIS locale_t __cloc();
2297a984708SDavid Chisnall#define __cloc_defined
2307a984708SDavid Chisnall#endif
2317a984708SDavid Chisnall
2327a984708SDavid Chisnall// __scan_keyword
2337a984708SDavid Chisnall// Scans [__b, __e) until a match is found in the basic_strings range
2347a984708SDavid Chisnall//  [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
2357a984708SDavid Chisnall//  __b will be incremented (visibly), consuming CharT until a match is found
2367a984708SDavid Chisnall//  or proved to not exist.  A keyword may be "", in which will match anything.
2377a984708SDavid Chisnall//  If one keyword is a prefix of another, and the next CharT in the input
2387a984708SDavid Chisnall//  might match another keyword, the algorithm will attempt to find the longest
2397a984708SDavid Chisnall//  matching keyword.  If the longer matching keyword ends up not matching, then
2407a984708SDavid Chisnall//  no keyword match is found.  If no keyword match is found, __ke is returned
2417a984708SDavid Chisnall//  and failbit is set in __err.
2427a984708SDavid Chisnall//  Else an iterator pointing to the matching keyword is found.  If more than
2437a984708SDavid Chisnall//  one keyword matches, an iterator to the first matching keyword is returned.
244d72607e9SDimitry Andric//  If on exit __b == __e, eofbit is set in __err.  If __case_sensitive is false,
2457a984708SDavid Chisnall//  __ct is used to force to lower case before comparing characters.
2467a984708SDavid Chisnall//  Examples:
2477a984708SDavid Chisnall//  Keywords:  "a", "abb"
2487a984708SDavid Chisnall//  If the input is "a", the first keyword matches and eofbit is set.
2497a984708SDavid Chisnall//  If the input is "abc", no match is found and "ab" are consumed.
2507a984708SDavid Chisnalltemplate <class _InputIterator, class _ForwardIterator, class _Ctype>
2517a984708SDavid Chisnall_LIBCPP_HIDDEN
2527a984708SDavid Chisnall_ForwardIterator
2537a984708SDavid Chisnall__scan_keyword(_InputIterator& __b, _InputIterator __e,
2547a984708SDavid Chisnall               _ForwardIterator __kb, _ForwardIterator __ke,
2557a984708SDavid Chisnall               const _Ctype& __ct, ios_base::iostate& __err,
2567a984708SDavid Chisnall               bool __case_sensitive = true)
2577a984708SDavid Chisnall{
2587a984708SDavid Chisnall    typedef typename iterator_traits<_InputIterator>::value_type _CharT;
25994e3ee44SDavid Chisnall    size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
2607a984708SDavid Chisnall    const unsigned char __doesnt_match = '\0';
2617a984708SDavid Chisnall    const unsigned char __might_match = '\1';
2627a984708SDavid Chisnall    const unsigned char __does_match = '\2';
2637a984708SDavid Chisnall    unsigned char __statbuf[100];
2647a984708SDavid Chisnall    unsigned char* __status = __statbuf;
2657a984708SDavid Chisnall    unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
2667a984708SDavid Chisnall    if (__nkw > sizeof(__statbuf))
2677a984708SDavid Chisnall    {
2687a984708SDavid Chisnall        __status = (unsigned char*)malloc(__nkw);
2697a984708SDavid Chisnall        if (__status == 0)
2707a984708SDavid Chisnall            __throw_bad_alloc();
2717a984708SDavid Chisnall        __stat_hold.reset(__status);
2727a984708SDavid Chisnall    }
2737a984708SDavid Chisnall    size_t __n_might_match = __nkw;  // At this point, any keyword might match
2747a984708SDavid Chisnall    size_t __n_does_match = 0;       // but none of them definitely do
2757a984708SDavid Chisnall    // Initialize all statuses to __might_match, except for "" keywords are __does_match
2767a984708SDavid Chisnall    unsigned char* __st = __status;
277d72607e9SDimitry Andric    for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
2787a984708SDavid Chisnall    {
2797a984708SDavid Chisnall        if (!__ky->empty())
2807a984708SDavid Chisnall            *__st = __might_match;
2817a984708SDavid Chisnall        else
2827a984708SDavid Chisnall        {
2837a984708SDavid Chisnall            *__st = __does_match;
2847a984708SDavid Chisnall            --__n_might_match;
2857a984708SDavid Chisnall            ++__n_does_match;
2867a984708SDavid Chisnall        }
2877a984708SDavid Chisnall    }
2887a984708SDavid Chisnall    // While there might be a match, test keywords against the next CharT
2897a984708SDavid Chisnall    for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
2907a984708SDavid Chisnall    {
2917a984708SDavid Chisnall        // Peek at the next CharT but don't consume it
2927a984708SDavid Chisnall        _CharT __c = *__b;
2937a984708SDavid Chisnall        if (!__case_sensitive)
2947a984708SDavid Chisnall            __c = __ct.toupper(__c);
2957a984708SDavid Chisnall        bool __consume = false;
2967a984708SDavid Chisnall        // For each keyword which might match, see if the __indx character is __c
2977a984708SDavid Chisnall        // If a match if found, consume __c
2987a984708SDavid Chisnall        // If a match is found, and that is the last character in the keyword,
2997a984708SDavid Chisnall        //    then that keyword matches.
3007a984708SDavid Chisnall        // If the keyword doesn't match this character, then change the keyword
3017a984708SDavid Chisnall        //    to doesn't match
3027a984708SDavid Chisnall        __st = __status;
303d72607e9SDimitry Andric        for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
3047a984708SDavid Chisnall        {
3057a984708SDavid Chisnall            if (*__st == __might_match)
3067a984708SDavid Chisnall            {
3077a984708SDavid Chisnall                _CharT __kc = (*__ky)[__indx];
3087a984708SDavid Chisnall                if (!__case_sensitive)
3097a984708SDavid Chisnall                    __kc = __ct.toupper(__kc);
3107a984708SDavid Chisnall                if (__c == __kc)
3117a984708SDavid Chisnall                {
3127a984708SDavid Chisnall                    __consume = true;
3137a984708SDavid Chisnall                    if (__ky->size() == __indx+1)
3147a984708SDavid Chisnall                    {
3157a984708SDavid Chisnall                        *__st = __does_match;
3167a984708SDavid Chisnall                        --__n_might_match;
3177a984708SDavid Chisnall                        ++__n_does_match;
3187a984708SDavid Chisnall                    }
3197a984708SDavid Chisnall                }
3207a984708SDavid Chisnall                else
3217a984708SDavid Chisnall                {
3227a984708SDavid Chisnall                    *__st = __doesnt_match;
3237a984708SDavid Chisnall                    --__n_might_match;
3247a984708SDavid Chisnall                }
3257a984708SDavid Chisnall            }
3267a984708SDavid Chisnall        }
3277a984708SDavid Chisnall        // consume if we matched a character
3287a984708SDavid Chisnall        if (__consume)
3297a984708SDavid Chisnall        {
3307a984708SDavid Chisnall            ++__b;
3317a984708SDavid Chisnall            // If we consumed a character and there might be a matched keyword that
3327a984708SDavid Chisnall            //   was marked matched on a previous iteration, then such keywords
3337a984708SDavid Chisnall            //   which are now marked as not matching.
3347a984708SDavid Chisnall            if (__n_might_match + __n_does_match > 1)
3357a984708SDavid Chisnall            {
3367a984708SDavid Chisnall                __st = __status;
337d72607e9SDimitry Andric                for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
3387a984708SDavid Chisnall                {
3397a984708SDavid Chisnall                    if (*__st == __does_match && __ky->size() != __indx+1)
3407a984708SDavid Chisnall                    {
3417a984708SDavid Chisnall                        *__st = __doesnt_match;
3427a984708SDavid Chisnall                        --__n_does_match;
3437a984708SDavid Chisnall                    }
3447a984708SDavid Chisnall                }
3457a984708SDavid Chisnall            }
3467a984708SDavid Chisnall        }
3477a984708SDavid Chisnall    }
3487a984708SDavid Chisnall    // We've exited the loop because we hit eof and/or we have no more "might matches".
3497a984708SDavid Chisnall    if (__b == __e)
3507a984708SDavid Chisnall        __err |= ios_base::eofbit;
3517a984708SDavid Chisnall    // Return the first matching result
352d72607e9SDimitry Andric    for (__st = __status; __kb != __ke; ++__kb, (void) ++__st)
3537a984708SDavid Chisnall        if (*__st == __does_match)
3547a984708SDavid Chisnall            break;
3557a984708SDavid Chisnall    if (__kb == __ke)
3567a984708SDavid Chisnall        __err |= ios_base::failbit;
3577a984708SDavid Chisnall    return __kb;
3587a984708SDavid Chisnall}
3597a984708SDavid Chisnall
3604f7ab58eSDimitry Andricstruct _LIBCPP_TYPE_VIS __num_get_base
3617a984708SDavid Chisnall{
3627a984708SDavid Chisnall    static const int __num_get_buf_sz = 40;
3637a984708SDavid Chisnall
3647a984708SDavid Chisnall    static int __get_base(ios_base&);
3657a984708SDavid Chisnall    static const char __src[33];
3667a984708SDavid Chisnall};
3677a984708SDavid Chisnall
3684f7ab58eSDimitry Andric_LIBCPP_FUNC_VIS
3697a984708SDavid Chisnallvoid __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
3707a984708SDavid Chisnall                      ios_base::iostate& __err);
3717a984708SDavid Chisnall
3727a984708SDavid Chisnalltemplate <class _CharT>
3737a984708SDavid Chisnallstruct __num_get
3747a984708SDavid Chisnall    : protected __num_get_base
3757a984708SDavid Chisnall{
3767a984708SDavid Chisnall    static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
3777a984708SDavid Chisnall                                      _CharT& __thousands_sep);
37824d58133SDimitry Andric
3797a984708SDavid Chisnall    static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
3807a984708SDavid Chisnall                                   char* __a, char*& __a_end,
3817a984708SDavid Chisnall                                   _CharT __decimal_point, _CharT __thousands_sep,
3827a984708SDavid Chisnall                                   const string& __grouping, unsigned* __g,
3837a984708SDavid Chisnall                                   unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
38424d58133SDimitry Andric#ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
38524d58133SDimitry Andric    static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
38624d58133SDimitry Andric    static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
38724d58133SDimitry Andric                  unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
38824d58133SDimitry Andric                  unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
38924d58133SDimitry Andric
39024d58133SDimitry Andric#else
39124d58133SDimitry Andric    static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep)
39224d58133SDimitry Andric    {
39324d58133SDimitry Andric        locale __loc = __iob.getloc();
39424d58133SDimitry Andric        const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
39524d58133SDimitry Andric        __thousands_sep = __np.thousands_sep();
39624d58133SDimitry Andric        return __np.grouping();
39724d58133SDimitry Andric    }
39824d58133SDimitry Andric
39924d58133SDimitry Andric    const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const
40024d58133SDimitry Andric    {
40124d58133SDimitry Andric      return __do_widen_p(__iob, __atoms);
40224d58133SDimitry Andric    }
40324d58133SDimitry Andric
40424d58133SDimitry Andric
40524d58133SDimitry Andric    static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
40624d58133SDimitry Andric                  unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
40724d58133SDimitry Andric                  unsigned* __g, unsigned*& __g_end, const _CharT* __atoms);
40824d58133SDimitry Andricprivate:
40924d58133SDimitry Andric    template<typename T>
41024d58133SDimitry Andric    const T* __do_widen_p(ios_base& __iob, T* __atoms) const
41124d58133SDimitry Andric    {
41224d58133SDimitry Andric      locale __loc = __iob.getloc();
41324d58133SDimitry Andric      use_facet<ctype<T> >(__loc).widen(__src, __src + 26, __atoms);
41424d58133SDimitry Andric      return __atoms;
41524d58133SDimitry Andric    }
41624d58133SDimitry Andric
41724d58133SDimitry Andric    const char* __do_widen_p(ios_base& __iob, char* __atoms) const
41824d58133SDimitry Andric    {
41924d58133SDimitry Andric      (void)__iob;
42024d58133SDimitry Andric      (void)__atoms;
42124d58133SDimitry Andric      return __src;
42224d58133SDimitry Andric    }
42324d58133SDimitry Andric#endif
4247a984708SDavid Chisnall};
4257a984708SDavid Chisnall
42624d58133SDimitry Andric#ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
4277a984708SDavid Chisnalltemplate <class _CharT>
4287a984708SDavid Chisnallstring
4297a984708SDavid Chisnall__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
4307a984708SDavid Chisnall{
4317a984708SDavid Chisnall    locale __loc = __iob.getloc();
4327a984708SDavid Chisnall    use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
4337a984708SDavid Chisnall    const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
4347a984708SDavid Chisnall    __thousands_sep = __np.thousands_sep();
4357a984708SDavid Chisnall    return __np.grouping();
4367a984708SDavid Chisnall}
43724d58133SDimitry Andric#endif
4387a984708SDavid Chisnall
4397a984708SDavid Chisnalltemplate <class _CharT>
4407a984708SDavid Chisnallstring
4417a984708SDavid Chisnall__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
4427a984708SDavid Chisnall                    _CharT& __thousands_sep)
4437a984708SDavid Chisnall{
4447a984708SDavid Chisnall    locale __loc = __iob.getloc();
4457a984708SDavid Chisnall    use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
4467a984708SDavid Chisnall    const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
4477a984708SDavid Chisnall    __decimal_point = __np.decimal_point();
4487a984708SDavid Chisnall    __thousands_sep = __np.thousands_sep();
4497a984708SDavid Chisnall    return __np.grouping();
4507a984708SDavid Chisnall}
4517a984708SDavid Chisnall
4527a984708SDavid Chisnalltemplate <class _CharT>
4537a984708SDavid Chisnallint
45424d58133SDimitry Andric#ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
4557a984708SDavid Chisnall__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
4567a984708SDavid Chisnall                  unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
4577a984708SDavid Chisnall                  unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
45824d58133SDimitry Andric#else
45924d58133SDimitry Andric__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
46024d58133SDimitry Andric                  unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
46124d58133SDimitry Andric                  unsigned* __g, unsigned*& __g_end, const _CharT* __atoms)
46224d58133SDimitry Andric
46324d58133SDimitry Andric#endif
4647a984708SDavid Chisnall{
4657a984708SDavid Chisnall    if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
4667a984708SDavid Chisnall    {
4677a984708SDavid Chisnall        *__a_end++ = __ct == __atoms[24] ? '+' : '-';
4687a984708SDavid Chisnall        __dc = 0;
4697a984708SDavid Chisnall        return 0;
4707a984708SDavid Chisnall    }
47194e3ee44SDavid Chisnall    if (__grouping.size() != 0 && __ct == __thousands_sep)
4727a984708SDavid Chisnall    {
4737a984708SDavid Chisnall        if (__g_end-__g < __num_get_buf_sz)
4747a984708SDavid Chisnall        {
4757a984708SDavid Chisnall            *__g_end++ = __dc;
4767a984708SDavid Chisnall            __dc = 0;
4777a984708SDavid Chisnall        }
4787a984708SDavid Chisnall        return 0;
4797a984708SDavid Chisnall    }
4807a984708SDavid Chisnall    ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
4817a984708SDavid Chisnall    if (__f >= 24)
4827a984708SDavid Chisnall        return -1;
4837a984708SDavid Chisnall    switch (__base)
4847a984708SDavid Chisnall    {
4857a984708SDavid Chisnall    case 8:
4867a984708SDavid Chisnall    case 10:
4877a984708SDavid Chisnall        if (__f >= __base)
4887a984708SDavid Chisnall            return -1;
4897a984708SDavid Chisnall        break;
4907a984708SDavid Chisnall    case 16:
4917a984708SDavid Chisnall        if (__f < 22)
4927a984708SDavid Chisnall            break;
4937a984708SDavid Chisnall        if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
4947a984708SDavid Chisnall        {
4957a984708SDavid Chisnall            __dc = 0;
4967a984708SDavid Chisnall            *__a_end++ = __src[__f];
4977a984708SDavid Chisnall            return 0;
4987a984708SDavid Chisnall        }
4997a984708SDavid Chisnall        return -1;
5007a984708SDavid Chisnall    }
5017a984708SDavid Chisnall    *__a_end++ = __src[__f];
5027a984708SDavid Chisnall    ++__dc;
5037a984708SDavid Chisnall    return 0;
5047a984708SDavid Chisnall}
5057a984708SDavid Chisnall
5067a984708SDavid Chisnalltemplate <class _CharT>
5077a984708SDavid Chisnallint
5087a984708SDavid Chisnall__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
5097a984708SDavid Chisnall                    _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
5107a984708SDavid Chisnall                    unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
5117a984708SDavid Chisnall{
5127a984708SDavid Chisnall    if (__ct == __decimal_point)
5137a984708SDavid Chisnall    {
5147a984708SDavid Chisnall        if (!__in_units)
5157a984708SDavid Chisnall            return -1;
5167a984708SDavid Chisnall        __in_units = false;
5177a984708SDavid Chisnall        *__a_end++ = '.';
5187a984708SDavid Chisnall        if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
5197a984708SDavid Chisnall            *__g_end++ = __dc;
5207a984708SDavid Chisnall        return 0;
5217a984708SDavid Chisnall    }
5227a984708SDavid Chisnall    if (__ct == __thousands_sep && __grouping.size() != 0)
5237a984708SDavid Chisnall    {
5247a984708SDavid Chisnall        if (!__in_units)
5257a984708SDavid Chisnall            return -1;
5267a984708SDavid Chisnall        if (__g_end-__g < __num_get_buf_sz)
5277a984708SDavid Chisnall        {
5287a984708SDavid Chisnall            *__g_end++ = __dc;
5297a984708SDavid Chisnall            __dc = 0;
5307a984708SDavid Chisnall        }
5317a984708SDavid Chisnall        return 0;
5327a984708SDavid Chisnall    }
5337a984708SDavid Chisnall    ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
5347a984708SDavid Chisnall    if (__f >= 32)
5357a984708SDavid Chisnall        return -1;
5367a984708SDavid Chisnall    char __x = __src[__f];
53794e3ee44SDavid Chisnall    if (__x == '-' || __x == '+')
53894e3ee44SDavid Chisnall    {
5391bf9f7c1SDimitry Andric        if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F))
54094e3ee44SDavid Chisnall        {
54194e3ee44SDavid Chisnall            *__a_end++ = __x;
54294e3ee44SDavid Chisnall            return 0;
54394e3ee44SDavid Chisnall        }
54494e3ee44SDavid Chisnall        return -1;
54594e3ee44SDavid Chisnall    }
5467a984708SDavid Chisnall    if (__x == 'x' || __x == 'X')
5477a984708SDavid Chisnall        __exp = 'P';
5481bf9f7c1SDimitry Andric    else if ((__x & 0x5F) == __exp)
5491bf9f7c1SDimitry Andric    {
5501bf9f7c1SDimitry Andric        __exp |= 0x80;
5511bf9f7c1SDimitry Andric        if (__in_units)
5527a984708SDavid Chisnall        {
5537a984708SDavid Chisnall            __in_units = false;
5547a984708SDavid Chisnall            if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
5557a984708SDavid Chisnall                *__g_end++ = __dc;
5567a984708SDavid Chisnall        }
5571bf9f7c1SDimitry Andric    }
5581bf9f7c1SDimitry Andric    *__a_end++ = __x;
5597a984708SDavid Chisnall    if (__f >= 22)
5607a984708SDavid Chisnall        return 0;
5617a984708SDavid Chisnall    ++__dc;
5627a984708SDavid Chisnall    return 0;
5637a984708SDavid Chisnall}
5647a984708SDavid Chisnall
565aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>)
566aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>)
5677a984708SDavid Chisnall
5687a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
569aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS num_get
5707a984708SDavid Chisnall    : public locale::facet,
5717a984708SDavid Chisnall      private __num_get<_CharT>
5727a984708SDavid Chisnall{
5737a984708SDavid Chisnallpublic:
5747a984708SDavid Chisnall    typedef _CharT char_type;
5757a984708SDavid Chisnall    typedef _InputIterator iter_type;
5767a984708SDavid Chisnall
5774ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5787a984708SDavid Chisnall    explicit num_get(size_t __refs = 0)
5797a984708SDavid Chisnall        : locale::facet(__refs) {}
5807a984708SDavid Chisnall
5814ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5827a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
5837a984708SDavid Chisnall                  ios_base::iostate& __err, bool& __v) const
5847a984708SDavid Chisnall    {
5857a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
5867a984708SDavid Chisnall    }
5877a984708SDavid Chisnall
5884ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5897a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
5907a984708SDavid Chisnall                  ios_base::iostate& __err, long& __v) const
5917a984708SDavid Chisnall    {
5927a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
5937a984708SDavid Chisnall    }
5947a984708SDavid Chisnall
5954ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5967a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
5977a984708SDavid Chisnall                  ios_base::iostate& __err, long long& __v) const
5987a984708SDavid Chisnall    {
5997a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
6007a984708SDavid Chisnall    }
6017a984708SDavid Chisnall
6024ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6037a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
6047a984708SDavid Chisnall                  ios_base::iostate& __err, unsigned short& __v) const
6057a984708SDavid Chisnall    {
6067a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
6077a984708SDavid Chisnall    }
6087a984708SDavid Chisnall
6094ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6107a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
6117a984708SDavid Chisnall                  ios_base::iostate& __err, unsigned int& __v) const
6127a984708SDavid Chisnall    {
6137a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
6147a984708SDavid Chisnall    }
6157a984708SDavid Chisnall
6164ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6177a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
6187a984708SDavid Chisnall                  ios_base::iostate& __err, unsigned long& __v) const
6197a984708SDavid Chisnall    {
6207a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
6217a984708SDavid Chisnall    }
6227a984708SDavid Chisnall
6234ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6247a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
6257a984708SDavid Chisnall                  ios_base::iostate& __err, unsigned long long& __v) const
6267a984708SDavid Chisnall    {
6277a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
6287a984708SDavid Chisnall    }
6297a984708SDavid Chisnall
6304ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6317a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
6327a984708SDavid Chisnall                  ios_base::iostate& __err, float& __v) const
6337a984708SDavid Chisnall    {
6347a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
6357a984708SDavid Chisnall    }
6367a984708SDavid Chisnall
6374ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6387a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
6397a984708SDavid Chisnall                  ios_base::iostate& __err, double& __v) const
6407a984708SDavid Chisnall    {
6417a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
6427a984708SDavid Chisnall    }
6437a984708SDavid Chisnall
6444ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6457a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
6467a984708SDavid Chisnall                  ios_base::iostate& __err, long double& __v) const
6477a984708SDavid Chisnall    {
6487a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
6497a984708SDavid Chisnall    }
6507a984708SDavid Chisnall
6514ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6527a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
6537a984708SDavid Chisnall                  ios_base::iostate& __err, void*& __v) const
6547a984708SDavid Chisnall    {
6557a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __v);
6567a984708SDavid Chisnall    }
6577a984708SDavid Chisnall
6587a984708SDavid Chisnall    static locale::id id;
6597a984708SDavid Chisnall
6607a984708SDavid Chisnallprotected:
6614ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6627a984708SDavid Chisnall    ~num_get() {}
6637a984708SDavid Chisnall
6644f7ab58eSDimitry Andric    template <class _Fp>
665540d2a8bSDimitry Andric    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
6664f7ab58eSDimitry Andric    iter_type __do_get_floating_point
6674f7ab58eSDimitry Andric                            (iter_type __b, iter_type __e, ios_base& __iob,
6684f7ab58eSDimitry Andric                             ios_base::iostate& __err, _Fp& __v) const;
6694f7ab58eSDimitry Andric
6704f7ab58eSDimitry Andric    template <class _Signed>
671540d2a8bSDimitry Andric    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
6724f7ab58eSDimitry Andric    iter_type __do_get_signed
6734f7ab58eSDimitry Andric                            (iter_type __b, iter_type __e, ios_base& __iob,
6744f7ab58eSDimitry Andric                             ios_base::iostate& __err, _Signed& __v) const;
6754f7ab58eSDimitry Andric
6764f7ab58eSDimitry Andric    template <class _Unsigned>
677540d2a8bSDimitry Andric    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
6784f7ab58eSDimitry Andric    iter_type __do_get_unsigned
6794f7ab58eSDimitry Andric                            (iter_type __b, iter_type __e, ios_base& __iob,
6804f7ab58eSDimitry Andric                             ios_base::iostate& __err, _Unsigned& __v) const;
6814f7ab58eSDimitry Andric
6824f7ab58eSDimitry Andric
6837a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
6847a984708SDavid Chisnall                             ios_base::iostate& __err, bool& __v) const;
6854f7ab58eSDimitry Andric
6867a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
6874f7ab58eSDimitry Andric                             ios_base::iostate& __err, long& __v) const
6884f7ab58eSDimitry Andric    { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
6894f7ab58eSDimitry Andric
6907a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
6914f7ab58eSDimitry Andric                             ios_base::iostate& __err, long long& __v) const
6924f7ab58eSDimitry Andric    { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
6934f7ab58eSDimitry Andric
6947a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
6954f7ab58eSDimitry Andric                             ios_base::iostate& __err, unsigned short& __v) const
6964f7ab58eSDimitry Andric    { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
6974f7ab58eSDimitry Andric
6987a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
6994f7ab58eSDimitry Andric                             ios_base::iostate& __err, unsigned int& __v) const
7004f7ab58eSDimitry Andric    { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
7014f7ab58eSDimitry Andric
7027a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
7034f7ab58eSDimitry Andric                             ios_base::iostate& __err, unsigned long& __v) const
7044f7ab58eSDimitry Andric    { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
7054f7ab58eSDimitry Andric
7067a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
7074f7ab58eSDimitry Andric                             ios_base::iostate& __err, unsigned long long& __v) const
7084f7ab58eSDimitry Andric    { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
7094f7ab58eSDimitry Andric
7107a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
7114f7ab58eSDimitry Andric                             ios_base::iostate& __err, float& __v) const
7124f7ab58eSDimitry Andric    { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
7134f7ab58eSDimitry Andric
7147a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
7154f7ab58eSDimitry Andric                             ios_base::iostate& __err, double& __v) const
7164f7ab58eSDimitry Andric    { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
7174f7ab58eSDimitry Andric
7187a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
7194f7ab58eSDimitry Andric                             ios_base::iostate& __err, long double& __v) const
7204f7ab58eSDimitry Andric    { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
7214f7ab58eSDimitry Andric
7227a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
7237a984708SDavid Chisnall                             ios_base::iostate& __err, void*& __v) const;
7247a984708SDavid Chisnall};
7257a984708SDavid Chisnall
7267a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
7277a984708SDavid Chisnalllocale::id
7287a984708SDavid Chisnallnum_get<_CharT, _InputIterator>::id;
7297a984708SDavid Chisnall
7307a984708SDavid Chisnalltemplate <class _Tp>
731*b5893f02SDimitry Andric_LIBCPP_HIDDEN _Tp
7327a984708SDavid Chisnall__num_get_signed_integral(const char* __a, const char* __a_end,
7337a984708SDavid Chisnall                          ios_base::iostate& __err, int __base)
7347a984708SDavid Chisnall{
7357a984708SDavid Chisnall    if (__a != __a_end)
7367a984708SDavid Chisnall    {
737cfdf2879SDavid Chisnall        typename remove_reference<decltype(errno)>::type __save_errno = errno;
7387a984708SDavid Chisnall        errno = 0;
7397a984708SDavid Chisnall        char *__p2;
7407a984708SDavid Chisnall        long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
741cfdf2879SDavid Chisnall        typename remove_reference<decltype(errno)>::type __current_errno = errno;
7427a984708SDavid Chisnall        if (__current_errno == 0)
7437a984708SDavid Chisnall            errno = __save_errno;
7447a984708SDavid Chisnall        if (__p2 != __a_end)
7457a984708SDavid Chisnall        {
7467a984708SDavid Chisnall            __err = ios_base::failbit;
7477a984708SDavid Chisnall            return 0;
7487a984708SDavid Chisnall        }
7497a984708SDavid Chisnall        else if (__current_errno == ERANGE         ||
7507a984708SDavid Chisnall                 __ll < numeric_limits<_Tp>::min() ||
7517a984708SDavid Chisnall                 numeric_limits<_Tp>::max() < __ll)
7527a984708SDavid Chisnall        {
7537a984708SDavid Chisnall            __err = ios_base::failbit;
7547a984708SDavid Chisnall            if (__ll > 0)
7557a984708SDavid Chisnall                return numeric_limits<_Tp>::max();
7567a984708SDavid Chisnall            else
7577a984708SDavid Chisnall                return numeric_limits<_Tp>::min();
7587a984708SDavid Chisnall        }
7597a984708SDavid Chisnall        return static_cast<_Tp>(__ll);
7607a984708SDavid Chisnall    }
7617a984708SDavid Chisnall    __err = ios_base::failbit;
7627a984708SDavid Chisnall    return 0;
7637a984708SDavid Chisnall}
7647a984708SDavid Chisnall
7657a984708SDavid Chisnalltemplate <class _Tp>
766*b5893f02SDimitry Andric_LIBCPP_HIDDEN _Tp
7677a984708SDavid Chisnall__num_get_unsigned_integral(const char* __a, const char* __a_end,
7687a984708SDavid Chisnall                            ios_base::iostate& __err, int __base)
7697a984708SDavid Chisnall{
7707a984708SDavid Chisnall    if (__a != __a_end)
7717a984708SDavid Chisnall    {
7724ba319b5SDimitry Andric        const bool __negate = *__a == '-';
7734ba319b5SDimitry Andric        if (__negate && ++__a == __a_end) {
7747a984708SDavid Chisnall          __err = ios_base::failbit;
7757a984708SDavid Chisnall          return 0;
7767a984708SDavid Chisnall        }
777cfdf2879SDavid Chisnall        typename remove_reference<decltype(errno)>::type __save_errno = errno;
7787a984708SDavid Chisnall        errno = 0;
7797a984708SDavid Chisnall        char *__p2;
7807a984708SDavid Chisnall        unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
781cfdf2879SDavid Chisnall        typename remove_reference<decltype(errno)>::type __current_errno = errno;
7827a984708SDavid Chisnall        if (__current_errno == 0)
7837a984708SDavid Chisnall            errno = __save_errno;
7847a984708SDavid Chisnall        if (__p2 != __a_end)
7857a984708SDavid Chisnall        {
7867a984708SDavid Chisnall            __err = ios_base::failbit;
7877a984708SDavid Chisnall            return 0;
7887a984708SDavid Chisnall        }
7894ba319b5SDimitry Andric        else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll)
7907a984708SDavid Chisnall        {
7917a984708SDavid Chisnall            __err = ios_base::failbit;
7927a984708SDavid Chisnall            return numeric_limits<_Tp>::max();
7937a984708SDavid Chisnall        }
7944ba319b5SDimitry Andric        _Tp __res = static_cast<_Tp>(__ll);
7954ba319b5SDimitry Andric        if (__negate) __res = -__res;
7964ba319b5SDimitry Andric        return __res;
7977a984708SDavid Chisnall    }
7987a984708SDavid Chisnall    __err = ios_base::failbit;
7997a984708SDavid Chisnall    return 0;
8007a984708SDavid Chisnall}
8017a984708SDavid Chisnall
8027a984708SDavid Chisnalltemplate <class _Tp>
8037c82a1ecSDimitry Andric_LIBCPP_INLINE_VISIBILITY
8047c82a1ecSDimitry Andric_Tp __do_strtod(const char* __a, char** __p2);
8057c82a1ecSDimitry Andric
8067c82a1ecSDimitry Andrictemplate <>
8077c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
8087c82a1ecSDimitry Andricfloat __do_strtod<float>(const char* __a, char** __p2) {
8097c82a1ecSDimitry Andric    return strtof_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
8107c82a1ecSDimitry Andric}
8117c82a1ecSDimitry Andric
8127c82a1ecSDimitry Andrictemplate <>
8137c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
8147c82a1ecSDimitry Andricdouble __do_strtod<double>(const char* __a, char** __p2) {
8157c82a1ecSDimitry Andric    return strtod_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
8167c82a1ecSDimitry Andric}
8177c82a1ecSDimitry Andric
8187c82a1ecSDimitry Andrictemplate <>
8197c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
8207c82a1ecSDimitry Andriclong double __do_strtod<long double>(const char* __a, char** __p2) {
8217c82a1ecSDimitry Andric    return strtold_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
8227c82a1ecSDimitry Andric}
8237c82a1ecSDimitry Andric
8247c82a1ecSDimitry Andrictemplate <class _Tp>
825aed8d94eSDimitry Andric_LIBCPP_HIDDEN
8267a984708SDavid Chisnall_Tp
8277a984708SDavid Chisnall__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
8287a984708SDavid Chisnall{
8297a984708SDavid Chisnall    if (__a != __a_end)
8307a984708SDavid Chisnall    {
8311bf9f7c1SDimitry Andric        typename remove_reference<decltype(errno)>::type __save_errno = errno;
8321bf9f7c1SDimitry Andric        errno = 0;
8337a984708SDavid Chisnall        char *__p2;
8347c82a1ecSDimitry Andric        _Tp __ld = __do_strtod<_Tp>(__a, &__p2);
8351bf9f7c1SDimitry Andric        typename remove_reference<decltype(errno)>::type __current_errno = errno;
8361bf9f7c1SDimitry Andric        if (__current_errno == 0)
8371bf9f7c1SDimitry Andric            errno = __save_errno;
8387a984708SDavid Chisnall        if (__p2 != __a_end)
8397a984708SDavid Chisnall        {
8407a984708SDavid Chisnall            __err = ios_base::failbit;
8417a984708SDavid Chisnall            return 0;
8427a984708SDavid Chisnall        }
8431bf9f7c1SDimitry Andric        else if (__current_errno == ERANGE)
8441bf9f7c1SDimitry Andric            __err = ios_base::failbit;
8457c82a1ecSDimitry Andric        return __ld;
8467a984708SDavid Chisnall    }
8477a984708SDavid Chisnall    __err = ios_base::failbit;
8487a984708SDavid Chisnall    return 0;
8497a984708SDavid Chisnall}
8507a984708SDavid Chisnall
8517a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
8527a984708SDavid Chisnall_InputIterator
8537a984708SDavid Chisnallnum_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
8547a984708SDavid Chisnall                                        ios_base& __iob,
8557a984708SDavid Chisnall                                        ios_base::iostate& __err,
8567a984708SDavid Chisnall                                        bool& __v) const
8577a984708SDavid Chisnall{
8587a984708SDavid Chisnall    if ((__iob.flags() & ios_base::boolalpha) == 0)
8597a984708SDavid Chisnall    {
8607a984708SDavid Chisnall        long __lv = -1;
8617a984708SDavid Chisnall        __b = do_get(__b, __e, __iob, __err, __lv);
8627a984708SDavid Chisnall        switch (__lv)
8637a984708SDavid Chisnall        {
8647a984708SDavid Chisnall        case 0:
8657a984708SDavid Chisnall            __v = false;
8667a984708SDavid Chisnall            break;
8677a984708SDavid Chisnall        case 1:
8687a984708SDavid Chisnall            __v = true;
8697a984708SDavid Chisnall            break;
8707a984708SDavid Chisnall        default:
8717a984708SDavid Chisnall            __v = true;
8727a984708SDavid Chisnall            __err = ios_base::failbit;
8737a984708SDavid Chisnall            break;
8747a984708SDavid Chisnall        }
8757a984708SDavid Chisnall        return __b;
8767a984708SDavid Chisnall    }
8777a984708SDavid Chisnall    const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
8787a984708SDavid Chisnall    const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
8797a984708SDavid Chisnall    typedef typename numpunct<_CharT>::string_type string_type;
8807a984708SDavid Chisnall    const string_type __names[2] = {__np.truename(), __np.falsename()};
8817a984708SDavid Chisnall    const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
8827a984708SDavid Chisnall                                            __ct, __err);
8837a984708SDavid Chisnall    __v = __i == __names;
8847a984708SDavid Chisnall    return __b;
8857a984708SDavid Chisnall}
8867a984708SDavid Chisnall
8874f7ab58eSDimitry Andric// signed
8884f7ab58eSDimitry Andric
8897a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
8904f7ab58eSDimitry Andrictemplate <class _Signed>
8917a984708SDavid Chisnall_InputIterator
8924f7ab58eSDimitry Andricnum_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e,
8937a984708SDavid Chisnall                                        ios_base& __iob,
8947a984708SDavid Chisnall                                        ios_base::iostate& __err,
8954f7ab58eSDimitry Andric                                        _Signed& __v) const
8967a984708SDavid Chisnall{
8977a984708SDavid Chisnall    // Stage 1
8987a984708SDavid Chisnall    int __base = this->__get_base(__iob);
8997a984708SDavid Chisnall    // Stage 2
9007a984708SDavid Chisnall    char_type __thousands_sep;
90124d58133SDimitry Andric    const int __atoms_size = 26;
90224d58133SDimitry Andric#ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
90324d58133SDimitry Andric    char_type __atoms1[__atoms_size];
90424d58133SDimitry Andric    const char_type *__atoms = this->__do_widen(__iob, __atoms1);
90524d58133SDimitry Andric    string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
90624d58133SDimitry Andric#else
90724d58133SDimitry Andric    char_type __atoms[__atoms_size];
9087a984708SDavid Chisnall    string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
90924d58133SDimitry Andric#endif
9101bf9f7c1SDimitry Andric    string __buf;
9111bf9f7c1SDimitry Andric    __buf.resize(__buf.capacity());
9121bf9f7c1SDimitry Andric    char* __a = &__buf[0];
9137a984708SDavid Chisnall    char* __a_end = __a;
9147a984708SDavid Chisnall    unsigned __g[__num_get_base::__num_get_buf_sz];
9157a984708SDavid Chisnall    unsigned* __g_end = __g;
9167a984708SDavid Chisnall    unsigned __dc = 0;
9177a984708SDavid Chisnall    for (; __b != __e; ++__b)
9181bf9f7c1SDimitry Andric    {
919d4567974SDimitry Andric        if (__a_end == __a + __buf.size())
9201bf9f7c1SDimitry Andric        {
9211bf9f7c1SDimitry Andric            size_t __tmp = __buf.size();
9221bf9f7c1SDimitry Andric            __buf.resize(2*__buf.size());
9231bf9f7c1SDimitry Andric            __buf.resize(__buf.capacity());
9241bf9f7c1SDimitry Andric            __a = &__buf[0];
9251bf9f7c1SDimitry Andric            __a_end = __a + __tmp;
9261bf9f7c1SDimitry Andric        }
9277a984708SDavid Chisnall        if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
9287a984708SDavid Chisnall                                    __thousands_sep, __grouping, __g, __g_end,
9297a984708SDavid Chisnall                                    __atoms))
9307a984708SDavid Chisnall            break;
9311bf9f7c1SDimitry Andric    }
9327a984708SDavid Chisnall    if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
9337a984708SDavid Chisnall        *__g_end++ = __dc;
9347a984708SDavid Chisnall    // Stage 3
9354f7ab58eSDimitry Andric    __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
9367a984708SDavid Chisnall    // Digit grouping checked
9377a984708SDavid Chisnall    __check_grouping(__grouping, __g, __g_end, __err);
9387a984708SDavid Chisnall    // EOF checked
9397a984708SDavid Chisnall    if (__b == __e)
9407a984708SDavid Chisnall        __err |= ios_base::eofbit;
9417a984708SDavid Chisnall    return __b;
9427a984708SDavid Chisnall}
9437a984708SDavid Chisnall
9444f7ab58eSDimitry Andric// unsigned
9454f7ab58eSDimitry Andric
9467a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
9474f7ab58eSDimitry Andrictemplate <class _Unsigned>
9487a984708SDavid Chisnall_InputIterator
9494f7ab58eSDimitry Andricnum_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e,
9507a984708SDavid Chisnall                                        ios_base& __iob,
9517a984708SDavid Chisnall                                        ios_base::iostate& __err,
9524f7ab58eSDimitry Andric                                        _Unsigned& __v) const
9537a984708SDavid Chisnall{
9547a984708SDavid Chisnall    // Stage 1
9557a984708SDavid Chisnall    int __base = this->__get_base(__iob);
9567a984708SDavid Chisnall    // Stage 2
9577a984708SDavid Chisnall    char_type __thousands_sep;
95824d58133SDimitry Andric    const int __atoms_size = 26;
95924d58133SDimitry Andric#ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
96024d58133SDimitry Andric    char_type __atoms1[__atoms_size];
96124d58133SDimitry Andric    const char_type *__atoms = this->__do_widen(__iob, __atoms1);
96224d58133SDimitry Andric    string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
96324d58133SDimitry Andric#else
96424d58133SDimitry Andric    char_type __atoms[__atoms_size];
9657a984708SDavid Chisnall    string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
96624d58133SDimitry Andric#endif
9671bf9f7c1SDimitry Andric    string __buf;
9681bf9f7c1SDimitry Andric    __buf.resize(__buf.capacity());
9691bf9f7c1SDimitry Andric    char* __a = &__buf[0];
9707a984708SDavid Chisnall    char* __a_end = __a;
9717a984708SDavid Chisnall    unsigned __g[__num_get_base::__num_get_buf_sz];
9727a984708SDavid Chisnall    unsigned* __g_end = __g;
9737a984708SDavid Chisnall    unsigned __dc = 0;
9747a984708SDavid Chisnall    for (; __b != __e; ++__b)
9751bf9f7c1SDimitry Andric    {
976d4567974SDimitry Andric        if (__a_end == __a + __buf.size())
9771bf9f7c1SDimitry Andric        {
9781bf9f7c1SDimitry Andric            size_t __tmp = __buf.size();
9791bf9f7c1SDimitry Andric            __buf.resize(2*__buf.size());
9801bf9f7c1SDimitry Andric            __buf.resize(__buf.capacity());
9811bf9f7c1SDimitry Andric            __a = &__buf[0];
9821bf9f7c1SDimitry Andric            __a_end = __a + __tmp;
9831bf9f7c1SDimitry Andric        }
9847a984708SDavid Chisnall        if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
9857a984708SDavid Chisnall                                    __thousands_sep, __grouping, __g, __g_end,
9867a984708SDavid Chisnall                                    __atoms))
9877a984708SDavid Chisnall            break;
9881bf9f7c1SDimitry Andric    }
9897a984708SDavid Chisnall    if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
9907a984708SDavid Chisnall        *__g_end++ = __dc;
9917a984708SDavid Chisnall    // Stage 3
9924f7ab58eSDimitry Andric    __v = __num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
9937a984708SDavid Chisnall    // Digit grouping checked
9947a984708SDavid Chisnall    __check_grouping(__grouping, __g, __g_end, __err);
9957a984708SDavid Chisnall    // EOF checked
9967a984708SDavid Chisnall    if (__b == __e)
9977a984708SDavid Chisnall        __err |= ios_base::eofbit;
9987a984708SDavid Chisnall    return __b;
9997a984708SDavid Chisnall}
10007a984708SDavid Chisnall
10014f7ab58eSDimitry Andric// floating point
10027a984708SDavid Chisnall
10037a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
10044f7ab58eSDimitry Andrictemplate <class _Fp>
10057a984708SDavid Chisnall_InputIterator
10064f7ab58eSDimitry Andricnum_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_type __e,
10077a984708SDavid Chisnall                                        ios_base& __iob,
10087a984708SDavid Chisnall                                        ios_base::iostate& __err,
10094f7ab58eSDimitry Andric                                        _Fp& __v) const
10107a984708SDavid Chisnall{
10117a984708SDavid Chisnall    // Stage 1, nothing to do
10127a984708SDavid Chisnall    // Stage 2
10137a984708SDavid Chisnall    char_type __atoms[32];
10147a984708SDavid Chisnall    char_type __decimal_point;
10157a984708SDavid Chisnall    char_type __thousands_sep;
10167a984708SDavid Chisnall    string __grouping = this->__stage2_float_prep(__iob, __atoms,
10177a984708SDavid Chisnall                                                  __decimal_point,
10187a984708SDavid Chisnall                                                  __thousands_sep);
10191bf9f7c1SDimitry Andric    string __buf;
10201bf9f7c1SDimitry Andric    __buf.resize(__buf.capacity());
10211bf9f7c1SDimitry Andric    char* __a = &__buf[0];
10227a984708SDavid Chisnall    char* __a_end = __a;
10237a984708SDavid Chisnall    unsigned __g[__num_get_base::__num_get_buf_sz];
10247a984708SDavid Chisnall    unsigned* __g_end = __g;
10257a984708SDavid Chisnall    unsigned __dc = 0;
10267a984708SDavid Chisnall    bool __in_units = true;
10277a984708SDavid Chisnall    char __exp = 'E';
10287a984708SDavid Chisnall    for (; __b != __e; ++__b)
10291bf9f7c1SDimitry Andric    {
1030d4567974SDimitry Andric        if (__a_end == __a + __buf.size())
10311bf9f7c1SDimitry Andric        {
10321bf9f7c1SDimitry Andric            size_t __tmp = __buf.size();
10331bf9f7c1SDimitry Andric            __buf.resize(2*__buf.size());
10341bf9f7c1SDimitry Andric            __buf.resize(__buf.capacity());
10351bf9f7c1SDimitry Andric            __a = &__buf[0];
10361bf9f7c1SDimitry Andric            __a_end = __a + __tmp;
10371bf9f7c1SDimitry Andric        }
10387a984708SDavid Chisnall        if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
10397a984708SDavid Chisnall                                      __decimal_point, __thousands_sep,
10407a984708SDavid Chisnall                                      __grouping, __g, __g_end,
10417a984708SDavid Chisnall                                      __dc, __atoms))
10427a984708SDavid Chisnall            break;
10431bf9f7c1SDimitry Andric    }
10447a984708SDavid Chisnall    if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
10457a984708SDavid Chisnall        *__g_end++ = __dc;
10467a984708SDavid Chisnall    // Stage 3
10474f7ab58eSDimitry Andric    __v = __num_get_float<_Fp>(__a, __a_end, __err);
10487a984708SDavid Chisnall    // Digit grouping checked
10497a984708SDavid Chisnall    __check_grouping(__grouping, __g, __g_end, __err);
10507a984708SDavid Chisnall    // EOF checked
10517a984708SDavid Chisnall    if (__b == __e)
10527a984708SDavid Chisnall        __err |= ios_base::eofbit;
10537a984708SDavid Chisnall    return __b;
10547a984708SDavid Chisnall}
10557a984708SDavid Chisnall
10567a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
10577a984708SDavid Chisnall_InputIterator
10587a984708SDavid Chisnallnum_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
10597a984708SDavid Chisnall                                        ios_base& __iob,
10607a984708SDavid Chisnall                                        ios_base::iostate& __err,
10617a984708SDavid Chisnall                                        void*& __v) const
10627a984708SDavid Chisnall{
10637a984708SDavid Chisnall    // Stage 1
10647a984708SDavid Chisnall    int __base = 16;
10657a984708SDavid Chisnall    // Stage 2
10667a984708SDavid Chisnall    char_type __atoms[26];
106794e3ee44SDavid Chisnall    char_type __thousands_sep = 0;
10687a984708SDavid Chisnall    string __grouping;
10697a984708SDavid Chisnall    use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
10707a984708SDavid Chisnall                                                    __num_get_base::__src + 26, __atoms);
10711bf9f7c1SDimitry Andric    string __buf;
10721bf9f7c1SDimitry Andric    __buf.resize(__buf.capacity());
10731bf9f7c1SDimitry Andric    char* __a = &__buf[0];
10747a984708SDavid Chisnall    char* __a_end = __a;
10757a984708SDavid Chisnall    unsigned __g[__num_get_base::__num_get_buf_sz];
10767a984708SDavid Chisnall    unsigned* __g_end = __g;
10777a984708SDavid Chisnall    unsigned __dc = 0;
10787a984708SDavid Chisnall    for (; __b != __e; ++__b)
10791bf9f7c1SDimitry Andric    {
1080d4567974SDimitry Andric        if (__a_end == __a + __buf.size())
10811bf9f7c1SDimitry Andric        {
10821bf9f7c1SDimitry Andric            size_t __tmp = __buf.size();
10831bf9f7c1SDimitry Andric            __buf.resize(2*__buf.size());
10841bf9f7c1SDimitry Andric            __buf.resize(__buf.capacity());
10851bf9f7c1SDimitry Andric            __a = &__buf[0];
10861bf9f7c1SDimitry Andric            __a_end = __a + __tmp;
10871bf9f7c1SDimitry Andric        }
10887a984708SDavid Chisnall        if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
10897a984708SDavid Chisnall                                    __thousands_sep, __grouping,
10907a984708SDavid Chisnall                                    __g, __g_end, __atoms))
10917a984708SDavid Chisnall            break;
10921bf9f7c1SDimitry Andric    }
10937a984708SDavid Chisnall    // Stage 3
1094d72607e9SDimitry Andric    __buf.resize(__a_end - __a);
10957c82a1ecSDimitry Andric    if (__libcpp_sscanf_l(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
10967a984708SDavid Chisnall        __err = ios_base::failbit;
10977a984708SDavid Chisnall    // EOF checked
10987a984708SDavid Chisnall    if (__b == __e)
10997a984708SDavid Chisnall        __err |= ios_base::eofbit;
11007a984708SDavid Chisnall    return __b;
11017a984708SDavid Chisnall}
11027a984708SDavid Chisnall
1103aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>)
1104aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>)
11057a984708SDavid Chisnall
11064f7ab58eSDimitry Andricstruct _LIBCPP_TYPE_VIS __num_put_base
11077a984708SDavid Chisnall{
11087a984708SDavid Chisnallprotected:
11097a984708SDavid Chisnall    static void __format_int(char* __fmt, const char* __len, bool __signd,
11107a984708SDavid Chisnall                             ios_base::fmtflags __flags);
11117a984708SDavid Chisnall    static bool __format_float(char* __fmt, const char* __len,
11127a984708SDavid Chisnall                               ios_base::fmtflags __flags);
11137a984708SDavid Chisnall    static char* __identify_padding(char* __nb, char* __ne,
11147a984708SDavid Chisnall                                    const ios_base& __iob);
11157a984708SDavid Chisnall};
11167a984708SDavid Chisnall
11177a984708SDavid Chisnalltemplate <class _CharT>
11187a984708SDavid Chisnallstruct __num_put
11197a984708SDavid Chisnall    : protected __num_put_base
11207a984708SDavid Chisnall{
11217a984708SDavid Chisnall    static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
11227a984708SDavid Chisnall                                      _CharT* __ob, _CharT*& __op, _CharT*& __oe,
11237a984708SDavid Chisnall                                      const locale& __loc);
11247a984708SDavid Chisnall    static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
11257a984708SDavid Chisnall                                        _CharT* __ob, _CharT*& __op, _CharT*& __oe,
11267a984708SDavid Chisnall                                        const locale& __loc);
11277a984708SDavid Chisnall};
11287a984708SDavid Chisnall
11297a984708SDavid Chisnalltemplate <class _CharT>
11307a984708SDavid Chisnallvoid
11317a984708SDavid Chisnall__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
11327a984708SDavid Chisnall                                         _CharT* __ob, _CharT*& __op, _CharT*& __oe,
11337a984708SDavid Chisnall                                         const locale& __loc)
11347a984708SDavid Chisnall{
11357a984708SDavid Chisnall    const ctype<_CharT>&    __ct = use_facet<ctype<_CharT> >   (__loc);
11367a984708SDavid Chisnall    const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
11377a984708SDavid Chisnall    string __grouping = __npt.grouping();
11387a984708SDavid Chisnall    if (__grouping.empty())
11397a984708SDavid Chisnall    {
11407a984708SDavid Chisnall        __ct.widen(__nb, __ne, __ob);
11417a984708SDavid Chisnall        __oe = __ob + (__ne - __nb);
11427a984708SDavid Chisnall    }
11437a984708SDavid Chisnall    else
11447a984708SDavid Chisnall    {
11457a984708SDavid Chisnall        __oe = __ob;
11467a984708SDavid Chisnall        char* __nf = __nb;
11477a984708SDavid Chisnall        if (*__nf == '-' || *__nf == '+')
11487a984708SDavid Chisnall            *__oe++ = __ct.widen(*__nf++);
11497a984708SDavid Chisnall        if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
11507a984708SDavid Chisnall                                                   __nf[1] == 'X'))
11517a984708SDavid Chisnall        {
11527a984708SDavid Chisnall            *__oe++ = __ct.widen(*__nf++);
11537a984708SDavid Chisnall            *__oe++ = __ct.widen(*__nf++);
11547a984708SDavid Chisnall        }
11557a984708SDavid Chisnall        reverse(__nf, __ne);
11567a984708SDavid Chisnall        _CharT __thousands_sep = __npt.thousands_sep();
11577a984708SDavid Chisnall        unsigned __dc = 0;
11587a984708SDavid Chisnall        unsigned __dg = 0;
11597a984708SDavid Chisnall        for (char* __p = __nf; __p < __ne; ++__p)
11607a984708SDavid Chisnall        {
11617a984708SDavid Chisnall            if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
11627a984708SDavid Chisnall                __dc == static_cast<unsigned>(__grouping[__dg]))
11637a984708SDavid Chisnall            {
11647a984708SDavid Chisnall                *__oe++ = __thousands_sep;
11657a984708SDavid Chisnall                __dc = 0;
11667a984708SDavid Chisnall                if (__dg < __grouping.size()-1)
11677a984708SDavid Chisnall                    ++__dg;
11687a984708SDavid Chisnall            }
11697a984708SDavid Chisnall            *__oe++ = __ct.widen(*__p);
11707a984708SDavid Chisnall            ++__dc;
11717a984708SDavid Chisnall        }
11727a984708SDavid Chisnall        reverse(__ob + (__nf - __nb), __oe);
11737a984708SDavid Chisnall    }
11747a984708SDavid Chisnall    if (__np == __ne)
11757a984708SDavid Chisnall        __op = __oe;
11767a984708SDavid Chisnall    else
11777a984708SDavid Chisnall        __op = __ob + (__np - __nb);
11787a984708SDavid Chisnall}
11797a984708SDavid Chisnall
11807a984708SDavid Chisnalltemplate <class _CharT>
11817a984708SDavid Chisnallvoid
11827a984708SDavid Chisnall__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
11837a984708SDavid Chisnall                                           _CharT* __ob, _CharT*& __op, _CharT*& __oe,
11847a984708SDavid Chisnall                                           const locale& __loc)
11857a984708SDavid Chisnall{
11867a984708SDavid Chisnall    const ctype<_CharT>&    __ct = use_facet<ctype<_CharT> >   (__loc);
11877a984708SDavid Chisnall    const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
11887a984708SDavid Chisnall    string __grouping = __npt.grouping();
11897a984708SDavid Chisnall    __oe = __ob;
11907a984708SDavid Chisnall    char* __nf = __nb;
11917a984708SDavid Chisnall    if (*__nf == '-' || *__nf == '+')
11927a984708SDavid Chisnall        *__oe++ = __ct.widen(*__nf++);
11937a984708SDavid Chisnall    char* __ns;
11947a984708SDavid Chisnall    if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
11957a984708SDavid Chisnall                                               __nf[1] == 'X'))
11967a984708SDavid Chisnall    {
11977a984708SDavid Chisnall        *__oe++ = __ct.widen(*__nf++);
11987a984708SDavid Chisnall        *__oe++ = __ct.widen(*__nf++);
11997a984708SDavid Chisnall        for (__ns = __nf; __ns < __ne; ++__ns)
12007a984708SDavid Chisnall            if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
12017a984708SDavid Chisnall                break;
12027a984708SDavid Chisnall    }
12037a984708SDavid Chisnall    else
12047a984708SDavid Chisnall    {
12057a984708SDavid Chisnall        for (__ns = __nf; __ns < __ne; ++__ns)
12067a984708SDavid Chisnall            if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
12077a984708SDavid Chisnall                break;
12087a984708SDavid Chisnall    }
12097a984708SDavid Chisnall    if (__grouping.empty())
12107a984708SDavid Chisnall    {
12117a984708SDavid Chisnall        __ct.widen(__nf, __ns, __oe);
12127a984708SDavid Chisnall        __oe += __ns - __nf;
12137a984708SDavid Chisnall    }
12147a984708SDavid Chisnall    else
12157a984708SDavid Chisnall    {
12167a984708SDavid Chisnall        reverse(__nf, __ns);
12177a984708SDavid Chisnall        _CharT __thousands_sep = __npt.thousands_sep();
12187a984708SDavid Chisnall        unsigned __dc = 0;
12197a984708SDavid Chisnall        unsigned __dg = 0;
12207a984708SDavid Chisnall        for (char* __p = __nf; __p < __ns; ++__p)
12217a984708SDavid Chisnall        {
12227a984708SDavid Chisnall            if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
12237a984708SDavid Chisnall            {
12247a984708SDavid Chisnall                *__oe++ = __thousands_sep;
12257a984708SDavid Chisnall                __dc = 0;
12267a984708SDavid Chisnall                if (__dg < __grouping.size()-1)
12277a984708SDavid Chisnall                    ++__dg;
12287a984708SDavid Chisnall            }
12297a984708SDavid Chisnall            *__oe++ = __ct.widen(*__p);
12307a984708SDavid Chisnall            ++__dc;
12317a984708SDavid Chisnall        }
12327a984708SDavid Chisnall        reverse(__ob + (__nf - __nb), __oe);
12337a984708SDavid Chisnall    }
12347a984708SDavid Chisnall    for (__nf = __ns; __nf < __ne; ++__nf)
12357a984708SDavid Chisnall    {
12367a984708SDavid Chisnall        if (*__nf == '.')
12377a984708SDavid Chisnall        {
12387a984708SDavid Chisnall            *__oe++ = __npt.decimal_point();
12397a984708SDavid Chisnall            ++__nf;
12407a984708SDavid Chisnall            break;
12417a984708SDavid Chisnall        }
12427a984708SDavid Chisnall        else
12437a984708SDavid Chisnall            *__oe++ = __ct.widen(*__nf);
12447a984708SDavid Chisnall    }
12457a984708SDavid Chisnall    __ct.widen(__nf, __ne, __oe);
12467a984708SDavid Chisnall    __oe += __ne - __nf;
12477a984708SDavid Chisnall    if (__np == __ne)
12487a984708SDavid Chisnall        __op = __oe;
12497a984708SDavid Chisnall    else
12507a984708SDavid Chisnall        __op = __ob + (__np - __nb);
12517a984708SDavid Chisnall}
12527a984708SDavid Chisnall
1253aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<char>)
1254aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<wchar_t>)
12557a984708SDavid Chisnall
12567a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
1257aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS num_put
12587a984708SDavid Chisnall    : public locale::facet,
12597a984708SDavid Chisnall      private __num_put<_CharT>
12607a984708SDavid Chisnall{
12617a984708SDavid Chisnallpublic:
12627a984708SDavid Chisnall    typedef _CharT char_type;
12637a984708SDavid Chisnall    typedef _OutputIterator iter_type;
12647a984708SDavid Chisnall
12654ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12667a984708SDavid Chisnall    explicit num_put(size_t __refs = 0)
12677a984708SDavid Chisnall        : locale::facet(__refs) {}
12687a984708SDavid Chisnall
12694ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12707a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
12717a984708SDavid Chisnall                  bool __v) const
12727a984708SDavid Chisnall    {
12737a984708SDavid Chisnall        return do_put(__s, __iob, __fl, __v);
12747a984708SDavid Chisnall    }
12757a984708SDavid Chisnall
12764ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12777a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
12787a984708SDavid Chisnall                  long __v) const
12797a984708SDavid Chisnall    {
12807a984708SDavid Chisnall        return do_put(__s, __iob, __fl, __v);
12817a984708SDavid Chisnall    }
12827a984708SDavid Chisnall
12834ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12847a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
12857a984708SDavid Chisnall                  long long __v) const
12867a984708SDavid Chisnall    {
12877a984708SDavid Chisnall        return do_put(__s, __iob, __fl, __v);
12887a984708SDavid Chisnall    }
12897a984708SDavid Chisnall
12904ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12917a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
12927a984708SDavid Chisnall                  unsigned long __v) const
12937a984708SDavid Chisnall    {
12947a984708SDavid Chisnall        return do_put(__s, __iob, __fl, __v);
12957a984708SDavid Chisnall    }
12967a984708SDavid Chisnall
12974ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
12987a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
12997a984708SDavid Chisnall                  unsigned long long __v) const
13007a984708SDavid Chisnall    {
13017a984708SDavid Chisnall        return do_put(__s, __iob, __fl, __v);
13027a984708SDavid Chisnall    }
13037a984708SDavid Chisnall
13044ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13057a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
13067a984708SDavid Chisnall                  double __v) const
13077a984708SDavid Chisnall    {
13087a984708SDavid Chisnall        return do_put(__s, __iob, __fl, __v);
13097a984708SDavid Chisnall    }
13107a984708SDavid Chisnall
13114ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13127a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
13137a984708SDavid Chisnall                  long double __v) const
13147a984708SDavid Chisnall    {
13157a984708SDavid Chisnall        return do_put(__s, __iob, __fl, __v);
13167a984708SDavid Chisnall    }
13177a984708SDavid Chisnall
13184ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13197a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
13207a984708SDavid Chisnall                  const void* __v) const
13217a984708SDavid Chisnall    {
13227a984708SDavid Chisnall        return do_put(__s, __iob, __fl, __v);
13237a984708SDavid Chisnall    }
13247a984708SDavid Chisnall
13257a984708SDavid Chisnall    static locale::id id;
13267a984708SDavid Chisnall
13277a984708SDavid Chisnallprotected:
13284ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
13297a984708SDavid Chisnall    ~num_put() {}
13307a984708SDavid Chisnall
13317a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
13327a984708SDavid Chisnall                             bool __v) const;
13337a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
13347a984708SDavid Chisnall                             long __v) const;
13357a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
13367a984708SDavid Chisnall                             long long __v) const;
13377a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
13387a984708SDavid Chisnall                             unsigned long) const;
13397a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
13407a984708SDavid Chisnall                             unsigned long long) const;
13417a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
13427a984708SDavid Chisnall                             double __v) const;
13437a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
13447a984708SDavid Chisnall                             long double __v) const;
13457a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
13467a984708SDavid Chisnall                             const void* __v) const;
13477a984708SDavid Chisnall};
13487a984708SDavid Chisnall
13497a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
13507a984708SDavid Chisnalllocale::id
13517a984708SDavid Chisnallnum_put<_CharT, _OutputIterator>::id;
13527a984708SDavid Chisnall
13537a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
13547a984708SDavid Chisnall_LIBCPP_HIDDEN
13557a984708SDavid Chisnall_OutputIterator
13567a984708SDavid Chisnall__pad_and_output(_OutputIterator __s,
13577a984708SDavid Chisnall                 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
13587a984708SDavid Chisnall                 ios_base& __iob, _CharT __fl)
13597a984708SDavid Chisnall{
13607a984708SDavid Chisnall    streamsize __sz = __oe - __ob;
13617a984708SDavid Chisnall    streamsize __ns = __iob.width();
13627a984708SDavid Chisnall    if (__ns > __sz)
13637a984708SDavid Chisnall        __ns -= __sz;
13647a984708SDavid Chisnall    else
13657a984708SDavid Chisnall        __ns = 0;
13667a984708SDavid Chisnall    for (;__ob < __op; ++__ob, ++__s)
13677a984708SDavid Chisnall        *__s = *__ob;
13687a984708SDavid Chisnall    for (; __ns; --__ns, ++__s)
13697a984708SDavid Chisnall        *__s = __fl;
13707a984708SDavid Chisnall    for (; __ob < __oe; ++__ob, ++__s)
13717a984708SDavid Chisnall        *__s = *__ob;
13727a984708SDavid Chisnall    __iob.width(0);
13737a984708SDavid Chisnall    return __s;
13747a984708SDavid Chisnall}
13757a984708SDavid Chisnall
1376fb6c5de6SDavid Chisnall#if !defined(__APPLE__) || \
1377fb6c5de6SDavid Chisnall    (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_8) || \
1378fb6c5de6SDavid Chisnall    (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_0)
1379fb6c5de6SDavid Chisnall
1380936e9439SDimitry Andrictemplate <class _CharT, class _Traits>
1381936e9439SDimitry Andric_LIBCPP_HIDDEN
1382936e9439SDimitry Andricostreambuf_iterator<_CharT, _Traits>
1383936e9439SDimitry Andric__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1384936e9439SDimitry Andric                 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1385936e9439SDimitry Andric                 ios_base& __iob, _CharT __fl)
1386936e9439SDimitry Andric{
1387936e9439SDimitry Andric    if (__s.__sbuf_ == nullptr)
1388936e9439SDimitry Andric        return __s;
1389936e9439SDimitry Andric    streamsize __sz = __oe - __ob;
1390936e9439SDimitry Andric    streamsize __ns = __iob.width();
1391936e9439SDimitry Andric    if (__ns > __sz)
1392936e9439SDimitry Andric        __ns -= __sz;
1393936e9439SDimitry Andric    else
1394936e9439SDimitry Andric        __ns = 0;
1395936e9439SDimitry Andric    streamsize __np = __op - __ob;
1396936e9439SDimitry Andric    if (__np > 0)
1397936e9439SDimitry Andric    {
1398936e9439SDimitry Andric        if (__s.__sbuf_->sputn(__ob, __np) != __np)
1399936e9439SDimitry Andric        {
1400936e9439SDimitry Andric            __s.__sbuf_ = nullptr;
1401936e9439SDimitry Andric            return __s;
1402936e9439SDimitry Andric        }
1403936e9439SDimitry Andric    }
1404936e9439SDimitry Andric    if (__ns > 0)
1405936e9439SDimitry Andric    {
1406936e9439SDimitry Andric        basic_string<_CharT, _Traits> __sp(__ns, __fl);
1407936e9439SDimitry Andric        if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1408936e9439SDimitry Andric        {
1409936e9439SDimitry Andric            __s.__sbuf_ = nullptr;
1410936e9439SDimitry Andric            return __s;
1411936e9439SDimitry Andric        }
1412936e9439SDimitry Andric    }
1413936e9439SDimitry Andric    __np = __oe - __op;
1414936e9439SDimitry Andric    if (__np > 0)
1415936e9439SDimitry Andric    {
1416936e9439SDimitry Andric        if (__s.__sbuf_->sputn(__op, __np) != __np)
1417936e9439SDimitry Andric        {
1418936e9439SDimitry Andric            __s.__sbuf_ = nullptr;
1419936e9439SDimitry Andric            return __s;
1420936e9439SDimitry Andric        }
1421936e9439SDimitry Andric    }
1422936e9439SDimitry Andric    __iob.width(0);
1423936e9439SDimitry Andric    return __s;
1424936e9439SDimitry Andric}
1425936e9439SDimitry Andric
1426fb6c5de6SDavid Chisnall#endif
1427fb6c5de6SDavid Chisnall
14287a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
14297a984708SDavid Chisnall_OutputIterator
14307a984708SDavid Chisnallnum_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
14317a984708SDavid Chisnall                                         char_type __fl, bool __v) const
14327a984708SDavid Chisnall{
14337a984708SDavid Chisnall    if ((__iob.flags() & ios_base::boolalpha) == 0)
14347a984708SDavid Chisnall        return do_put(__s, __iob, __fl, (unsigned long)__v);
14357a984708SDavid Chisnall    const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
14367a984708SDavid Chisnall    typedef typename numpunct<char_type>::string_type string_type;
14374f7ab58eSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 2
14384f7ab58eSDimitry Andric    string_type __tmp(__v ? __np.truename() : __np.falsename());
14394f7ab58eSDimitry Andric    string_type __nm = _VSTD::move(__tmp);
14404f7ab58eSDimitry Andric#else
14417a984708SDavid Chisnall    string_type __nm = __v ? __np.truename() : __np.falsename();
14424f7ab58eSDimitry Andric#endif
14437a984708SDavid Chisnall    for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
14447a984708SDavid Chisnall        *__s = *__i;
14457a984708SDavid Chisnall    return __s;
14467a984708SDavid Chisnall}
14477a984708SDavid Chisnall
14487a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
14497a984708SDavid Chisnall_OutputIterator
14507a984708SDavid Chisnallnum_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
14517a984708SDavid Chisnall                                         char_type __fl, long __v) const
14527a984708SDavid Chisnall{
14537a984708SDavid Chisnall    // Stage 1 - Get number in narrow char
14547a984708SDavid Chisnall    char __fmt[6] = {'%', 0};
14557a984708SDavid Chisnall    const char* __len = "l";
14567a984708SDavid Chisnall    this->__format_int(__fmt+1, __len, true, __iob.flags());
14577a984708SDavid Chisnall    const unsigned __nbuf = (numeric_limits<long>::digits / 3)
14587a984708SDavid Chisnall                          + ((numeric_limits<long>::digits % 3) != 0)
14590f5676f4SDimitry Andric                          + ((__iob.flags() & ios_base::showbase) != 0)
14607c82a1ecSDimitry Andric                          + 2;
14617a984708SDavid Chisnall    char __nar[__nbuf];
14627c82a1ecSDimitry Andric    int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
14637a984708SDavid Chisnall    char* __ne = __nar + __nc;
14647a984708SDavid Chisnall    char* __np = this->__identify_padding(__nar, __ne, __iob);
14657a984708SDavid Chisnall    // Stage 2 - Widen __nar while adding thousands separators
14667a984708SDavid Chisnall    char_type __o[2*(__nbuf-1) - 1];
14677a984708SDavid Chisnall    char_type* __op;  // pad here
14687a984708SDavid Chisnall    char_type* __oe;  // end of output
14697a984708SDavid Chisnall    this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
14707a984708SDavid Chisnall    // [__o, __oe) contains thousands_sep'd wide number
14717a984708SDavid Chisnall    // Stage 3 & 4
14727a984708SDavid Chisnall    return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
14737a984708SDavid Chisnall}
14747a984708SDavid Chisnall
14757a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
14767a984708SDavid Chisnall_OutputIterator
14777a984708SDavid Chisnallnum_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
14787a984708SDavid Chisnall                                         char_type __fl, long long __v) const
14797a984708SDavid Chisnall{
14807a984708SDavid Chisnall    // Stage 1 - Get number in narrow char
14817a984708SDavid Chisnall    char __fmt[8] = {'%', 0};
14827a984708SDavid Chisnall    const char* __len = "ll";
14837a984708SDavid Chisnall    this->__format_int(__fmt+1, __len, true, __iob.flags());
14847a984708SDavid Chisnall    const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
14857a984708SDavid Chisnall                          + ((numeric_limits<long long>::digits % 3) != 0)
14860f5676f4SDimitry Andric                          + ((__iob.flags() & ios_base::showbase) != 0)
1487854fa44bSDimitry Andric                          + 2;
14887a984708SDavid Chisnall    char __nar[__nbuf];
14897c82a1ecSDimitry Andric    int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
14907a984708SDavid Chisnall    char* __ne = __nar + __nc;
14917a984708SDavid Chisnall    char* __np = this->__identify_padding(__nar, __ne, __iob);
14927a984708SDavid Chisnall    // Stage 2 - Widen __nar while adding thousands separators
14937a984708SDavid Chisnall    char_type __o[2*(__nbuf-1) - 1];
14947a984708SDavid Chisnall    char_type* __op;  // pad here
14957a984708SDavid Chisnall    char_type* __oe;  // end of output
14967a984708SDavid Chisnall    this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
14977a984708SDavid Chisnall    // [__o, __oe) contains thousands_sep'd wide number
14987a984708SDavid Chisnall    // Stage 3 & 4
14997a984708SDavid Chisnall    return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
15007a984708SDavid Chisnall}
15017a984708SDavid Chisnall
15027a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
15037a984708SDavid Chisnall_OutputIterator
15047a984708SDavid Chisnallnum_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
15057a984708SDavid Chisnall                                         char_type __fl, unsigned long __v) const
15067a984708SDavid Chisnall{
15077a984708SDavid Chisnall    // Stage 1 - Get number in narrow char
15087a984708SDavid Chisnall    char __fmt[6] = {'%', 0};
15097a984708SDavid Chisnall    const char* __len = "l";
15107a984708SDavid Chisnall    this->__format_int(__fmt+1, __len, false, __iob.flags());
15117a984708SDavid Chisnall    const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
15127a984708SDavid Chisnall                          + ((numeric_limits<unsigned long>::digits % 3) != 0)
15130f5676f4SDimitry Andric                          + ((__iob.flags() & ios_base::showbase) != 0)
15147a984708SDavid Chisnall                          + 1;
15157a984708SDavid Chisnall    char __nar[__nbuf];
15167c82a1ecSDimitry Andric    int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
15177a984708SDavid Chisnall    char* __ne = __nar + __nc;
15187a984708SDavid Chisnall    char* __np = this->__identify_padding(__nar, __ne, __iob);
15197a984708SDavid Chisnall    // Stage 2 - Widen __nar while adding thousands separators
15207a984708SDavid Chisnall    char_type __o[2*(__nbuf-1) - 1];
15217a984708SDavid Chisnall    char_type* __op;  // pad here
15227a984708SDavid Chisnall    char_type* __oe;  // end of output
15237a984708SDavid Chisnall    this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
15247a984708SDavid Chisnall    // [__o, __oe) contains thousands_sep'd wide number
15257a984708SDavid Chisnall    // Stage 3 & 4
15267a984708SDavid Chisnall    return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
15277a984708SDavid Chisnall}
15287a984708SDavid Chisnall
15297a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
15307a984708SDavid Chisnall_OutputIterator
15317a984708SDavid Chisnallnum_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
15327a984708SDavid Chisnall                                         char_type __fl, unsigned long long __v) const
15337a984708SDavid Chisnall{
15347a984708SDavid Chisnall    // Stage 1 - Get number in narrow char
15357a984708SDavid Chisnall    char __fmt[8] = {'%', 0};
15367a984708SDavid Chisnall    const char* __len = "ll";
15377a984708SDavid Chisnall    this->__format_int(__fmt+1, __len, false, __iob.flags());
15387a984708SDavid Chisnall    const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
15397a984708SDavid Chisnall                          + ((numeric_limits<unsigned long long>::digits % 3) != 0)
15400f5676f4SDimitry Andric                          + ((__iob.flags() & ios_base::showbase) != 0)
15417a984708SDavid Chisnall                          + 1;
15427a984708SDavid Chisnall    char __nar[__nbuf];
15437c82a1ecSDimitry Andric    int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
15447a984708SDavid Chisnall    char* __ne = __nar + __nc;
15457a984708SDavid Chisnall    char* __np = this->__identify_padding(__nar, __ne, __iob);
15467a984708SDavid Chisnall    // Stage 2 - Widen __nar while adding thousands separators
15477a984708SDavid Chisnall    char_type __o[2*(__nbuf-1) - 1];
15487a984708SDavid Chisnall    char_type* __op;  // pad here
15497a984708SDavid Chisnall    char_type* __oe;  // end of output
15507a984708SDavid Chisnall    this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
15517a984708SDavid Chisnall    // [__o, __oe) contains thousands_sep'd wide number
15527a984708SDavid Chisnall    // Stage 3 & 4
15537a984708SDavid Chisnall    return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
15547a984708SDavid Chisnall}
15557a984708SDavid Chisnall
15567a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
15577a984708SDavid Chisnall_OutputIterator
15587a984708SDavid Chisnallnum_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
15597a984708SDavid Chisnall                                         char_type __fl, double __v) const
15607a984708SDavid Chisnall{
15617a984708SDavid Chisnall    // Stage 1 - Get number in narrow char
15627a984708SDavid Chisnall    char __fmt[8] = {'%', 0};
15637a984708SDavid Chisnall    const char* __len = "";
15647a984708SDavid Chisnall    bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
15657a984708SDavid Chisnall    const unsigned __nbuf = 30;
15667a984708SDavid Chisnall    char __nar[__nbuf];
15677a984708SDavid Chisnall    char* __nb = __nar;
15687a984708SDavid Chisnall    int __nc;
15697a984708SDavid Chisnall    if (__specify_precision)
15707c82a1ecSDimitry Andric        __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
15717a984708SDavid Chisnall                                   (int)__iob.precision(), __v);
15727a984708SDavid Chisnall    else
15737c82a1ecSDimitry Andric        __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
15747a984708SDavid Chisnall    unique_ptr<char, void(*)(void*)> __nbh(0, free);
15757a984708SDavid Chisnall    if (__nc > static_cast<int>(__nbuf-1))
15767a984708SDavid Chisnall    {
15777a984708SDavid Chisnall        if (__specify_precision)
15787c82a1ecSDimitry Andric            __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
15797a984708SDavid Chisnall        else
15807c82a1ecSDimitry Andric            __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
15817a984708SDavid Chisnall        if (__nb == 0)
15827a984708SDavid Chisnall            __throw_bad_alloc();
15837a984708SDavid Chisnall        __nbh.reset(__nb);
15847a984708SDavid Chisnall    }
15857a984708SDavid Chisnall    char* __ne = __nb + __nc;
15867a984708SDavid Chisnall    char* __np = this->__identify_padding(__nb, __ne, __iob);
15877a984708SDavid Chisnall    // Stage 2 - Widen __nar while adding thousands separators
15887a984708SDavid Chisnall    char_type __o[2*(__nbuf-1) - 1];
15897a984708SDavid Chisnall    char_type* __ob = __o;
15907a984708SDavid Chisnall    unique_ptr<char_type, void(*)(void*)> __obh(0, free);
15917a984708SDavid Chisnall    if (__nb != __nar)
15927a984708SDavid Chisnall    {
159394e3ee44SDavid Chisnall        __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
15947a984708SDavid Chisnall        if (__ob == 0)
15957a984708SDavid Chisnall            __throw_bad_alloc();
15967a984708SDavid Chisnall        __obh.reset(__ob);
15977a984708SDavid Chisnall    }
15987a984708SDavid Chisnall    char_type* __op;  // pad here
15997a984708SDavid Chisnall    char_type* __oe;  // end of output
16007a984708SDavid Chisnall    this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
16017a984708SDavid Chisnall    // [__o, __oe) contains thousands_sep'd wide number
16027a984708SDavid Chisnall    // Stage 3 & 4
16037a984708SDavid Chisnall    __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
16047a984708SDavid Chisnall    return __s;
16057a984708SDavid Chisnall}
16067a984708SDavid Chisnall
16077a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
16087a984708SDavid Chisnall_OutputIterator
16097a984708SDavid Chisnallnum_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
16107a984708SDavid Chisnall                                         char_type __fl, long double __v) const
16117a984708SDavid Chisnall{
16127a984708SDavid Chisnall    // Stage 1 - Get number in narrow char
16137a984708SDavid Chisnall    char __fmt[8] = {'%', 0};
16147a984708SDavid Chisnall    const char* __len = "L";
16157a984708SDavid Chisnall    bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
16167a984708SDavid Chisnall    const unsigned __nbuf = 30;
16177a984708SDavid Chisnall    char __nar[__nbuf];
16187a984708SDavid Chisnall    char* __nb = __nar;
16197a984708SDavid Chisnall    int __nc;
16207a984708SDavid Chisnall    if (__specify_precision)
16217c82a1ecSDimitry Andric        __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
16227a984708SDavid Chisnall                                   (int)__iob.precision(), __v);
16237a984708SDavid Chisnall    else
16247c82a1ecSDimitry Andric        __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
16257a984708SDavid Chisnall    unique_ptr<char, void(*)(void*)> __nbh(0, free);
16267a984708SDavid Chisnall    if (__nc > static_cast<int>(__nbuf-1))
16277a984708SDavid Chisnall    {
16287a984708SDavid Chisnall        if (__specify_precision)
16297c82a1ecSDimitry Andric            __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
16307a984708SDavid Chisnall        else
16317c82a1ecSDimitry Andric            __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
16327a984708SDavid Chisnall        if (__nb == 0)
16337a984708SDavid Chisnall            __throw_bad_alloc();
16347a984708SDavid Chisnall        __nbh.reset(__nb);
16357a984708SDavid Chisnall    }
16367a984708SDavid Chisnall    char* __ne = __nb + __nc;
16377a984708SDavid Chisnall    char* __np = this->__identify_padding(__nb, __ne, __iob);
16387a984708SDavid Chisnall    // Stage 2 - Widen __nar while adding thousands separators
16397a984708SDavid Chisnall    char_type __o[2*(__nbuf-1) - 1];
16407a984708SDavid Chisnall    char_type* __ob = __o;
16417a984708SDavid Chisnall    unique_ptr<char_type, void(*)(void*)> __obh(0, free);
16427a984708SDavid Chisnall    if (__nb != __nar)
16437a984708SDavid Chisnall    {
164494e3ee44SDavid Chisnall        __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
16457a984708SDavid Chisnall        if (__ob == 0)
16467a984708SDavid Chisnall            __throw_bad_alloc();
16477a984708SDavid Chisnall        __obh.reset(__ob);
16487a984708SDavid Chisnall    }
16497a984708SDavid Chisnall    char_type* __op;  // pad here
16507a984708SDavid Chisnall    char_type* __oe;  // end of output
16517a984708SDavid Chisnall    this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
16527a984708SDavid Chisnall    // [__o, __oe) contains thousands_sep'd wide number
16537a984708SDavid Chisnall    // Stage 3 & 4
16547a984708SDavid Chisnall    __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
16557a984708SDavid Chisnall    return __s;
16567a984708SDavid Chisnall}
16577a984708SDavid Chisnall
16587a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
16597a984708SDavid Chisnall_OutputIterator
16607a984708SDavid Chisnallnum_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
16617a984708SDavid Chisnall                                         char_type __fl, const void* __v) const
16627a984708SDavid Chisnall{
16637a984708SDavid Chisnall    // Stage 1 - Get pointer in narrow char
16647a984708SDavid Chisnall    char __fmt[6] = "%p";
16657a984708SDavid Chisnall    const unsigned __nbuf = 20;
16667a984708SDavid Chisnall    char __nar[__nbuf];
16677c82a1ecSDimitry Andric    int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
16687a984708SDavid Chisnall    char* __ne = __nar + __nc;
16697a984708SDavid Chisnall    char* __np = this->__identify_padding(__nar, __ne, __iob);
16707a984708SDavid Chisnall    // Stage 2 - Widen __nar
16717a984708SDavid Chisnall    char_type __o[2*(__nbuf-1) - 1];
16727a984708SDavid Chisnall    char_type* __op;  // pad here
16737a984708SDavid Chisnall    char_type* __oe;  // end of output
16747a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
16757a984708SDavid Chisnall    __ct.widen(__nar, __ne, __o);
16767a984708SDavid Chisnall    __oe = __o + (__ne - __nar);
16777a984708SDavid Chisnall    if (__np == __ne)
16787a984708SDavid Chisnall        __op = __oe;
16797a984708SDavid Chisnall    else
16807a984708SDavid Chisnall        __op = __o + (__np - __nar);
16817a984708SDavid Chisnall    // [__o, __oe) contains wide number
16827a984708SDavid Chisnall    // Stage 3 & 4
16837a984708SDavid Chisnall    return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
16847a984708SDavid Chisnall}
16857a984708SDavid Chisnall
1686aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>)
1687aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<wchar_t>)
16887a984708SDavid Chisnall
16897a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
16907a984708SDavid Chisnall_LIBCPP_HIDDEN
16917a984708SDavid Chisnallint
16927a984708SDavid Chisnall__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
16937a984708SDavid Chisnall                     ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
16947a984708SDavid Chisnall{
16957a984708SDavid Chisnall    // Precondition:  __n >= 1
16967a984708SDavid Chisnall    if (__b == __e)
16977a984708SDavid Chisnall    {
16987a984708SDavid Chisnall        __err |= ios_base::eofbit | ios_base::failbit;
16997a984708SDavid Chisnall        return 0;
17007a984708SDavid Chisnall    }
17017a984708SDavid Chisnall    // get first digit
17027a984708SDavid Chisnall    _CharT __c = *__b;
17037a984708SDavid Chisnall    if (!__ct.is(ctype_base::digit, __c))
17047a984708SDavid Chisnall    {
17057a984708SDavid Chisnall        __err |= ios_base::failbit;
17067a984708SDavid Chisnall        return 0;
17077a984708SDavid Chisnall    }
17087a984708SDavid Chisnall    int __r = __ct.narrow(__c, 0) - '0';
1709d72607e9SDimitry Andric    for (++__b, (void) --__n; __b != __e && __n > 0; ++__b, (void) --__n)
17107a984708SDavid Chisnall    {
17117a984708SDavid Chisnall        // get next digit
17127a984708SDavid Chisnall        __c = *__b;
17137a984708SDavid Chisnall        if (!__ct.is(ctype_base::digit, __c))
17147a984708SDavid Chisnall            return __r;
17157a984708SDavid Chisnall        __r = __r * 10 + __ct.narrow(__c, 0) - '0';
17167a984708SDavid Chisnall    }
17177a984708SDavid Chisnall    if (__b == __e)
17187a984708SDavid Chisnall        __err |= ios_base::eofbit;
17197a984708SDavid Chisnall    return __r;
17207a984708SDavid Chisnall}
17217a984708SDavid Chisnall
17221bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS time_base
17237a984708SDavid Chisnall{
17247a984708SDavid Chisnallpublic:
17257a984708SDavid Chisnall    enum dateorder {no_order, dmy, mdy, ymd, ydm};
17267a984708SDavid Chisnall};
17277a984708SDavid Chisnall
17287a984708SDavid Chisnalltemplate <class _CharT>
1729aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __time_get_c_storage
17307a984708SDavid Chisnall{
17317a984708SDavid Chisnallprotected:
17327a984708SDavid Chisnall    typedef basic_string<_CharT> string_type;
17337a984708SDavid Chisnall
17347a984708SDavid Chisnall    virtual const string_type* __weeks() const;
17357a984708SDavid Chisnall    virtual const string_type* __months() const;
17367a984708SDavid Chisnall    virtual const string_type* __am_pm() const;
17377a984708SDavid Chisnall    virtual const string_type& __c() const;
17387a984708SDavid Chisnall    virtual const string_type& __r() const;
17397a984708SDavid Chisnall    virtual const string_type& __x() const;
17407a984708SDavid Chisnall    virtual const string_type& __X() const;
17419729cf09SDimitry Andric
17424ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
17439729cf09SDimitry Andric    ~__time_get_c_storage() {}
17447a984708SDavid Chisnall};
17457a984708SDavid Chisnall
17460f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__weeks() const;
17470f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__months() const;
17480f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__am_pm() const;
17490f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__c() const;
17500f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__r() const;
17510f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__x() const;
17520f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__X() const;
17530f5676f4SDimitry Andric
17540f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__weeks() const;
17550f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__months() const;
17560f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__am_pm() const;
17570f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__c() const;
17580f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__r() const;
17590f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__x() const;
17600f5676f4SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__X() const;
17610f5676f4SDimitry Andric
17627a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
1763aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS time_get
17647a984708SDavid Chisnall    : public locale::facet,
17657a984708SDavid Chisnall      public time_base,
17667a984708SDavid Chisnall      private __time_get_c_storage<_CharT>
17677a984708SDavid Chisnall{
17687a984708SDavid Chisnallpublic:
17697a984708SDavid Chisnall    typedef _CharT                  char_type;
17707a984708SDavid Chisnall    typedef _InputIterator          iter_type;
17717a984708SDavid Chisnall    typedef time_base::dateorder    dateorder;
17727a984708SDavid Chisnall    typedef basic_string<char_type> string_type;
17737a984708SDavid Chisnall
17744ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
17757a984708SDavid Chisnall    explicit time_get(size_t __refs = 0)
17767a984708SDavid Chisnall        : locale::facet(__refs) {}
17777a984708SDavid Chisnall
17784ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
17797a984708SDavid Chisnall    dateorder date_order() const
17807a984708SDavid Chisnall    {
17817a984708SDavid Chisnall        return this->do_date_order();
17827a984708SDavid Chisnall    }
17837a984708SDavid Chisnall
17844ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
17857a984708SDavid Chisnall    iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
17867a984708SDavid Chisnall                       ios_base::iostate& __err, tm* __tm) const
17877a984708SDavid Chisnall    {
17887a984708SDavid Chisnall        return do_get_time(__b, __e, __iob, __err, __tm);
17897a984708SDavid Chisnall    }
17907a984708SDavid Chisnall
17914ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
17927a984708SDavid Chisnall    iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
17937a984708SDavid Chisnall                       ios_base::iostate& __err, tm* __tm) const
17947a984708SDavid Chisnall    {
17957a984708SDavid Chisnall        return do_get_date(__b, __e, __iob, __err, __tm);
17967a984708SDavid Chisnall    }
17977a984708SDavid Chisnall
17984ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
17997a984708SDavid Chisnall    iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
18007a984708SDavid Chisnall                          ios_base::iostate& __err, tm* __tm) const
18017a984708SDavid Chisnall    {
18027a984708SDavid Chisnall        return do_get_weekday(__b, __e, __iob, __err, __tm);
18037a984708SDavid Chisnall    }
18047a984708SDavid Chisnall
18054ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
18067a984708SDavid Chisnall    iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
18077a984708SDavid Chisnall                            ios_base::iostate& __err, tm* __tm) const
18087a984708SDavid Chisnall    {
18097a984708SDavid Chisnall        return do_get_monthname(__b, __e, __iob, __err, __tm);
18107a984708SDavid Chisnall    }
18117a984708SDavid Chisnall
18124ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
18137a984708SDavid Chisnall    iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
18147a984708SDavid Chisnall                       ios_base::iostate& __err, tm* __tm) const
18157a984708SDavid Chisnall    {
18167a984708SDavid Chisnall        return do_get_year(__b, __e, __iob, __err, __tm);
18177a984708SDavid Chisnall    }
18187a984708SDavid Chisnall
18194ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
18207a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
18217a984708SDavid Chisnall                  ios_base::iostate& __err, tm *__tm,
18227a984708SDavid Chisnall                  char __fmt, char __mod = 0) const
18237a984708SDavid Chisnall    {
18247a984708SDavid Chisnall        return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
18257a984708SDavid Chisnall    }
18267a984708SDavid Chisnall
18277a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
18287a984708SDavid Chisnall                  ios_base::iostate& __err, tm* __tm,
18297a984708SDavid Chisnall                  const char_type* __fmtb, const char_type* __fmte) const;
18307a984708SDavid Chisnall
18317a984708SDavid Chisnall    static locale::id id;
18327a984708SDavid Chisnall
18337a984708SDavid Chisnallprotected:
18344ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
18357a984708SDavid Chisnall    ~time_get() {}
18367a984708SDavid Chisnall
18377a984708SDavid Chisnall    virtual dateorder do_date_order() const;
18387a984708SDavid Chisnall    virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
18397a984708SDavid Chisnall                                  ios_base::iostate& __err, tm* __tm) const;
18407a984708SDavid Chisnall    virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
18417a984708SDavid Chisnall                                  ios_base::iostate& __err, tm* __tm) const;
18427a984708SDavid Chisnall    virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
18437a984708SDavid Chisnall                                     ios_base::iostate& __err, tm* __tm) const;
18447a984708SDavid Chisnall    virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
18457a984708SDavid Chisnall                                       ios_base::iostate& __err, tm* __tm) const;
18467a984708SDavid Chisnall    virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
18477a984708SDavid Chisnall                                  ios_base::iostate& __err, tm* __tm) const;
18487a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
18497a984708SDavid Chisnall                             ios_base::iostate& __err, tm* __tm,
18507a984708SDavid Chisnall                             char __fmt, char __mod) const;
18517a984708SDavid Chisnallprivate:
18527a984708SDavid Chisnall    void __get_white_space(iter_type& __b, iter_type __e,
18537a984708SDavid Chisnall                           ios_base::iostate& __err, const ctype<char_type>& __ct) const;
18547a984708SDavid Chisnall    void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
18557a984708SDavid Chisnall                       const ctype<char_type>& __ct) const;
18567a984708SDavid Chisnall
18577a984708SDavid Chisnall    void __get_weekdayname(int& __m,
18587a984708SDavid Chisnall                           iter_type& __b, iter_type __e,
18597a984708SDavid Chisnall                           ios_base::iostate& __err,
18607a984708SDavid Chisnall                           const ctype<char_type>& __ct) const;
18617a984708SDavid Chisnall    void __get_monthname(int& __m,
18627a984708SDavid Chisnall                         iter_type& __b, iter_type __e,
18637a984708SDavid Chisnall                         ios_base::iostate& __err,
18647a984708SDavid Chisnall                         const ctype<char_type>& __ct) const;
18657a984708SDavid Chisnall    void __get_day(int& __d,
18667a984708SDavid Chisnall                   iter_type& __b, iter_type __e,
18677a984708SDavid Chisnall                   ios_base::iostate& __err,
18687a984708SDavid Chisnall                   const ctype<char_type>& __ct) const;
18697a984708SDavid Chisnall    void __get_month(int& __m,
18707a984708SDavid Chisnall                     iter_type& __b, iter_type __e,
18717a984708SDavid Chisnall                     ios_base::iostate& __err,
18727a984708SDavid Chisnall                     const ctype<char_type>& __ct) const;
18737a984708SDavid Chisnall    void __get_year(int& __y,
18747a984708SDavid Chisnall                   iter_type& __b, iter_type __e,
18757a984708SDavid Chisnall                   ios_base::iostate& __err,
18767a984708SDavid Chisnall                   const ctype<char_type>& __ct) const;
18777a984708SDavid Chisnall    void __get_year4(int& __y,
18787a984708SDavid Chisnall                    iter_type& __b, iter_type __e,
18797a984708SDavid Chisnall                    ios_base::iostate& __err,
18807a984708SDavid Chisnall                    const ctype<char_type>& __ct) const;
18817a984708SDavid Chisnall    void __get_hour(int& __d,
18827a984708SDavid Chisnall                    iter_type& __b, iter_type __e,
18837a984708SDavid Chisnall                    ios_base::iostate& __err,
18847a984708SDavid Chisnall                    const ctype<char_type>& __ct) const;
18857a984708SDavid Chisnall    void __get_12_hour(int& __h,
18867a984708SDavid Chisnall                       iter_type& __b, iter_type __e,
18877a984708SDavid Chisnall                       ios_base::iostate& __err,
18887a984708SDavid Chisnall                       const ctype<char_type>& __ct) const;
18897a984708SDavid Chisnall    void __get_am_pm(int& __h,
18907a984708SDavid Chisnall                     iter_type& __b, iter_type __e,
18917a984708SDavid Chisnall                     ios_base::iostate& __err,
18927a984708SDavid Chisnall                     const ctype<char_type>& __ct) const;
18937a984708SDavid Chisnall    void __get_minute(int& __m,
18947a984708SDavid Chisnall                      iter_type& __b, iter_type __e,
18957a984708SDavid Chisnall                      ios_base::iostate& __err,
18967a984708SDavid Chisnall                      const ctype<char_type>& __ct) const;
18977a984708SDavid Chisnall    void __get_second(int& __s,
18987a984708SDavid Chisnall                      iter_type& __b, iter_type __e,
18997a984708SDavid Chisnall                      ios_base::iostate& __err,
19007a984708SDavid Chisnall                      const ctype<char_type>& __ct) const;
19017a984708SDavid Chisnall    void __get_weekday(int& __w,
19027a984708SDavid Chisnall                       iter_type& __b, iter_type __e,
19037a984708SDavid Chisnall                       ios_base::iostate& __err,
19047a984708SDavid Chisnall                       const ctype<char_type>& __ct) const;
19057a984708SDavid Chisnall    void __get_day_year_num(int& __w,
19067a984708SDavid Chisnall                            iter_type& __b, iter_type __e,
19077a984708SDavid Chisnall                            ios_base::iostate& __err,
19087a984708SDavid Chisnall                            const ctype<char_type>& __ct) const;
19097a984708SDavid Chisnall};
19107a984708SDavid Chisnall
19117a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
19127a984708SDavid Chisnalllocale::id
19137a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::id;
19147a984708SDavid Chisnall
1915d72607e9SDimitry Andric// time_get primitives
19167a984708SDavid Chisnall
19177a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
19187a984708SDavid Chisnallvoid
19197a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
19207a984708SDavid Chisnall                                                    iter_type& __b, iter_type __e,
19217a984708SDavid Chisnall                                                    ios_base::iostate& __err,
19227a984708SDavid Chisnall                                                    const ctype<char_type>& __ct) const
19237a984708SDavid Chisnall{
19247a984708SDavid Chisnall    // Note:  ignoring case comes from the POSIX strptime spec
19257a984708SDavid Chisnall    const string_type* __wk = this->__weeks();
192694e3ee44SDavid Chisnall    ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
19277a984708SDavid Chisnall    if (__i < 14)
19287a984708SDavid Chisnall        __w = __i % 7;
19297a984708SDavid Chisnall}
19307a984708SDavid Chisnall
19317a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
19327a984708SDavid Chisnallvoid
19337a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_monthname(int& __m,
19347a984708SDavid Chisnall                                                  iter_type& __b, iter_type __e,
19357a984708SDavid Chisnall                                                  ios_base::iostate& __err,
19367a984708SDavid Chisnall                                                  const ctype<char_type>& __ct) const
19377a984708SDavid Chisnall{
19387a984708SDavid Chisnall    // Note:  ignoring case comes from the POSIX strptime spec
19397a984708SDavid Chisnall    const string_type* __month = this->__months();
194094e3ee44SDavid Chisnall    ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
19417a984708SDavid Chisnall    if (__i < 24)
19427a984708SDavid Chisnall        __m = __i % 12;
19437a984708SDavid Chisnall}
19447a984708SDavid Chisnall
19457a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
19467a984708SDavid Chisnallvoid
19477a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_day(int& __d,
19487a984708SDavid Chisnall                                            iter_type& __b, iter_type __e,
19497a984708SDavid Chisnall                                            ios_base::iostate& __err,
19507a984708SDavid Chisnall                                            const ctype<char_type>& __ct) const
19517a984708SDavid Chisnall{
19527a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
19537a984708SDavid Chisnall    if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
19547a984708SDavid Chisnall        __d = __t;
19557a984708SDavid Chisnall    else
19567a984708SDavid Chisnall        __err |= ios_base::failbit;
19577a984708SDavid Chisnall}
19587a984708SDavid Chisnall
19597a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
19607a984708SDavid Chisnallvoid
19617a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_month(int& __m,
19627a984708SDavid Chisnall                                              iter_type& __b, iter_type __e,
19637a984708SDavid Chisnall                                              ios_base::iostate& __err,
19647a984708SDavid Chisnall                                              const ctype<char_type>& __ct) const
19657a984708SDavid Chisnall{
19667a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
19677a984708SDavid Chisnall    if (!(__err & ios_base::failbit) && __t <= 11)
19687a984708SDavid Chisnall        __m = __t;
19697a984708SDavid Chisnall    else
19707a984708SDavid Chisnall        __err |= ios_base::failbit;
19717a984708SDavid Chisnall}
19727a984708SDavid Chisnall
19737a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
19747a984708SDavid Chisnallvoid
19757a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_year(int& __y,
19767a984708SDavid Chisnall                                             iter_type& __b, iter_type __e,
19777a984708SDavid Chisnall                                             ios_base::iostate& __err,
19787a984708SDavid Chisnall                                             const ctype<char_type>& __ct) const
19797a984708SDavid Chisnall{
19807a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
19817a984708SDavid Chisnall    if (!(__err & ios_base::failbit))
19827a984708SDavid Chisnall    {
19837a984708SDavid Chisnall        if (__t < 69)
19847a984708SDavid Chisnall            __t += 2000;
19857a984708SDavid Chisnall        else if (69 <= __t && __t <= 99)
19867a984708SDavid Chisnall            __t += 1900;
19877a984708SDavid Chisnall        __y = __t - 1900;
19887a984708SDavid Chisnall    }
19897a984708SDavid Chisnall}
19907a984708SDavid Chisnall
19917a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
19927a984708SDavid Chisnallvoid
19937a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_year4(int& __y,
19947a984708SDavid Chisnall                                              iter_type& __b, iter_type __e,
19957a984708SDavid Chisnall                                              ios_base::iostate& __err,
19967a984708SDavid Chisnall                                              const ctype<char_type>& __ct) const
19977a984708SDavid Chisnall{
19987a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
19997a984708SDavid Chisnall    if (!(__err & ios_base::failbit))
20007a984708SDavid Chisnall        __y = __t - 1900;
20017a984708SDavid Chisnall}
20027a984708SDavid Chisnall
20037a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
20047a984708SDavid Chisnallvoid
20057a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_hour(int& __h,
20067a984708SDavid Chisnall                                             iter_type& __b, iter_type __e,
20077a984708SDavid Chisnall                                             ios_base::iostate& __err,
20087a984708SDavid Chisnall                                             const ctype<char_type>& __ct) const
20097a984708SDavid Chisnall{
20107a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
20117a984708SDavid Chisnall    if (!(__err & ios_base::failbit) && __t <= 23)
20127a984708SDavid Chisnall        __h = __t;
20137a984708SDavid Chisnall    else
20147a984708SDavid Chisnall        __err |= ios_base::failbit;
20157a984708SDavid Chisnall}
20167a984708SDavid Chisnall
20177a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
20187a984708SDavid Chisnallvoid
20197a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
20207a984708SDavid Chisnall                                                iter_type& __b, iter_type __e,
20217a984708SDavid Chisnall                                                ios_base::iostate& __err,
20227a984708SDavid Chisnall                                                const ctype<char_type>& __ct) const
20237a984708SDavid Chisnall{
20247a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
20257a984708SDavid Chisnall    if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
20267a984708SDavid Chisnall        __h = __t;
20277a984708SDavid Chisnall    else
20287a984708SDavid Chisnall        __err |= ios_base::failbit;
20297a984708SDavid Chisnall}
20307a984708SDavid Chisnall
20317a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
20327a984708SDavid Chisnallvoid
20337a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_minute(int& __m,
20347a984708SDavid Chisnall                                               iter_type& __b, iter_type __e,
20357a984708SDavid Chisnall                                               ios_base::iostate& __err,
20367a984708SDavid Chisnall                                               const ctype<char_type>& __ct) const
20377a984708SDavid Chisnall{
20387a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
20397a984708SDavid Chisnall    if (!(__err & ios_base::failbit) && __t <= 59)
20407a984708SDavid Chisnall        __m = __t;
20417a984708SDavid Chisnall    else
20427a984708SDavid Chisnall        __err |= ios_base::failbit;
20437a984708SDavid Chisnall}
20447a984708SDavid Chisnall
20457a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
20467a984708SDavid Chisnallvoid
20477a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_second(int& __s,
20487a984708SDavid Chisnall                                               iter_type& __b, iter_type __e,
20497a984708SDavid Chisnall                                               ios_base::iostate& __err,
20507a984708SDavid Chisnall                                               const ctype<char_type>& __ct) const
20517a984708SDavid Chisnall{
20527a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
20537a984708SDavid Chisnall    if (!(__err & ios_base::failbit) && __t <= 60)
20547a984708SDavid Chisnall        __s = __t;
20557a984708SDavid Chisnall    else
20567a984708SDavid Chisnall        __err |= ios_base::failbit;
20577a984708SDavid Chisnall}
20587a984708SDavid Chisnall
20597a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
20607a984708SDavid Chisnallvoid
20617a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_weekday(int& __w,
20627a984708SDavid Chisnall                                                iter_type& __b, iter_type __e,
20637a984708SDavid Chisnall                                                ios_base::iostate& __err,
20647a984708SDavid Chisnall                                                const ctype<char_type>& __ct) const
20657a984708SDavid Chisnall{
20667a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
20677a984708SDavid Chisnall    if (!(__err & ios_base::failbit) && __t <= 6)
20687a984708SDavid Chisnall        __w = __t;
20697a984708SDavid Chisnall    else
20707a984708SDavid Chisnall        __err |= ios_base::failbit;
20717a984708SDavid Chisnall}
20727a984708SDavid Chisnall
20737a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
20747a984708SDavid Chisnallvoid
20757a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
20767a984708SDavid Chisnall                                                     iter_type& __b, iter_type __e,
20777a984708SDavid Chisnall                                                     ios_base::iostate& __err,
20787a984708SDavid Chisnall                                                     const ctype<char_type>& __ct) const
20797a984708SDavid Chisnall{
20807a984708SDavid Chisnall    int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
20817a984708SDavid Chisnall    if (!(__err & ios_base::failbit) && __t <= 365)
20827a984708SDavid Chisnall        __d = __t;
20837a984708SDavid Chisnall    else
20847a984708SDavid Chisnall        __err |= ios_base::failbit;
20857a984708SDavid Chisnall}
20867a984708SDavid Chisnall
20877a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
20887a984708SDavid Chisnallvoid
20897a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
20907a984708SDavid Chisnall                                                    ios_base::iostate& __err,
20917a984708SDavid Chisnall                                                    const ctype<char_type>& __ct) const
20927a984708SDavid Chisnall{
20937a984708SDavid Chisnall    for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
20947a984708SDavid Chisnall        ;
20957a984708SDavid Chisnall    if (__b == __e)
20967a984708SDavid Chisnall        __err |= ios_base::eofbit;
20977a984708SDavid Chisnall}
20987a984708SDavid Chisnall
20997a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
21007a984708SDavid Chisnallvoid
21017a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
21027a984708SDavid Chisnall                                              iter_type& __b, iter_type __e,
21037a984708SDavid Chisnall                                              ios_base::iostate& __err,
21047a984708SDavid Chisnall                                              const ctype<char_type>& __ct) const
21057a984708SDavid Chisnall{
21067a984708SDavid Chisnall    const string_type* __ap = this->__am_pm();
21077a984708SDavid Chisnall    if (__ap[0].size() + __ap[1].size() == 0)
21087a984708SDavid Chisnall    {
21097a984708SDavid Chisnall        __err |= ios_base::failbit;
21107a984708SDavid Chisnall        return;
21117a984708SDavid Chisnall    }
211294e3ee44SDavid Chisnall    ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
21137a984708SDavid Chisnall    if (__i == 0 && __h == 12)
21147a984708SDavid Chisnall        __h = 0;
21157a984708SDavid Chisnall    else if (__i == 1 && __h < 12)
21167a984708SDavid Chisnall        __h += 12;
21177a984708SDavid Chisnall}
21187a984708SDavid Chisnall
21197a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
21207a984708SDavid Chisnallvoid
21217a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
21227a984708SDavid Chisnall                                                ios_base::iostate& __err,
21237a984708SDavid Chisnall                                                const ctype<char_type>& __ct) const
21247a984708SDavid Chisnall{
21257a984708SDavid Chisnall    if (__b == __e)
21267a984708SDavid Chisnall    {
21277a984708SDavid Chisnall        __err |= ios_base::eofbit | ios_base::failbit;
21287a984708SDavid Chisnall        return;
21297a984708SDavid Chisnall    }
21307a984708SDavid Chisnall    if (__ct.narrow(*__b, 0) != '%')
21317a984708SDavid Chisnall        __err |= ios_base::failbit;
21327a984708SDavid Chisnall    else if(++__b == __e)
21337a984708SDavid Chisnall        __err |= ios_base::eofbit;
21347a984708SDavid Chisnall}
21357a984708SDavid Chisnall
2136d72607e9SDimitry Andric// time_get end primitives
21377a984708SDavid Chisnall
21387a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
21397a984708SDavid Chisnall_InputIterator
21407a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
21417a984708SDavid Chisnall                                      ios_base& __iob,
21427a984708SDavid Chisnall                                      ios_base::iostate& __err, tm* __tm,
21437a984708SDavid Chisnall                                      const char_type* __fmtb, const char_type* __fmte) const
21447a984708SDavid Chisnall{
21457a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
21467a984708SDavid Chisnall    __err = ios_base::goodbit;
21477a984708SDavid Chisnall    while (__fmtb != __fmte && __err == ios_base::goodbit)
21487a984708SDavid Chisnall    {
21497a984708SDavid Chisnall        if (__b == __e)
21507a984708SDavid Chisnall        {
21517a984708SDavid Chisnall            __err = ios_base::failbit;
21527a984708SDavid Chisnall            break;
21537a984708SDavid Chisnall        }
21547a984708SDavid Chisnall        if (__ct.narrow(*__fmtb, 0) == '%')
21557a984708SDavid Chisnall        {
21567a984708SDavid Chisnall            if (++__fmtb == __fmte)
21577a984708SDavid Chisnall            {
21587a984708SDavid Chisnall                __err = ios_base::failbit;
21597a984708SDavid Chisnall                break;
21607a984708SDavid Chisnall            }
21617a984708SDavid Chisnall            char __cmd = __ct.narrow(*__fmtb, 0);
21627a984708SDavid Chisnall            char __opt = '\0';
21637a984708SDavid Chisnall            if (__cmd == 'E' || __cmd == '0')
21647a984708SDavid Chisnall            {
21657a984708SDavid Chisnall                if (++__fmtb == __fmte)
21667a984708SDavid Chisnall                {
21677a984708SDavid Chisnall                    __err = ios_base::failbit;
21687a984708SDavid Chisnall                    break;
21697a984708SDavid Chisnall                }
21707a984708SDavid Chisnall                __opt = __cmd;
21717a984708SDavid Chisnall                __cmd = __ct.narrow(*__fmtb, 0);
21727a984708SDavid Chisnall            }
21737a984708SDavid Chisnall            __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
21747a984708SDavid Chisnall            ++__fmtb;
21757a984708SDavid Chisnall        }
21767a984708SDavid Chisnall        else if (__ct.is(ctype_base::space, *__fmtb))
21777a984708SDavid Chisnall        {
21787a984708SDavid Chisnall            for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
21797a984708SDavid Chisnall                ;
21807a984708SDavid Chisnall            for (        ;    __b != __e    && __ct.is(ctype_base::space, *__b);    ++__b)
21817a984708SDavid Chisnall                ;
21827a984708SDavid Chisnall        }
21837a984708SDavid Chisnall        else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
21847a984708SDavid Chisnall        {
21857a984708SDavid Chisnall            ++__b;
21867a984708SDavid Chisnall            ++__fmtb;
21877a984708SDavid Chisnall        }
21887a984708SDavid Chisnall        else
21897a984708SDavid Chisnall            __err = ios_base::failbit;
21907a984708SDavid Chisnall    }
21917a984708SDavid Chisnall    if (__b == __e)
21927a984708SDavid Chisnall        __err |= ios_base::eofbit;
21937a984708SDavid Chisnall    return __b;
21947a984708SDavid Chisnall}
21957a984708SDavid Chisnall
21967a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
21977a984708SDavid Chisnalltypename time_get<_CharT, _InputIterator>::dateorder
21987a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::do_date_order() const
21997a984708SDavid Chisnall{
22007a984708SDavid Chisnall    return mdy;
22017a984708SDavid Chisnall}
22027a984708SDavid Chisnall
22037a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
22047a984708SDavid Chisnall_InputIterator
22057a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
22067a984708SDavid Chisnall                                              ios_base& __iob,
22077a984708SDavid Chisnall                                              ios_base::iostate& __err,
22087a984708SDavid Chisnall                                              tm* __tm) const
22097a984708SDavid Chisnall{
22107a984708SDavid Chisnall    const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
22117a984708SDavid Chisnall    return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
22127a984708SDavid Chisnall}
22137a984708SDavid Chisnall
22147a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
22157a984708SDavid Chisnall_InputIterator
22167a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
22177a984708SDavid Chisnall                                              ios_base& __iob,
22187a984708SDavid Chisnall                                              ios_base::iostate& __err,
22197a984708SDavid Chisnall                                              tm* __tm) const
22207a984708SDavid Chisnall{
22217a984708SDavid Chisnall    const string_type& __fmt = this->__x();
22227a984708SDavid Chisnall    return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
22237a984708SDavid Chisnall}
22247a984708SDavid Chisnall
22257a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
22267a984708SDavid Chisnall_InputIterator
22277a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
22287a984708SDavid Chisnall                                                 ios_base& __iob,
22297a984708SDavid Chisnall                                                 ios_base::iostate& __err,
22307a984708SDavid Chisnall                                                 tm* __tm) const
22317a984708SDavid Chisnall{
22327a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
22337a984708SDavid Chisnall    __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
22347a984708SDavid Chisnall    return __b;
22357a984708SDavid Chisnall}
22367a984708SDavid Chisnall
22377a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
22387a984708SDavid Chisnall_InputIterator
22397a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
22407a984708SDavid Chisnall                                                   ios_base& __iob,
22417a984708SDavid Chisnall                                                   ios_base::iostate& __err,
22427a984708SDavid Chisnall                                                   tm* __tm) const
22437a984708SDavid Chisnall{
22447a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
22457a984708SDavid Chisnall    __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
22467a984708SDavid Chisnall    return __b;
22477a984708SDavid Chisnall}
22487a984708SDavid Chisnall
22497a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
22507a984708SDavid Chisnall_InputIterator
22517a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
22527a984708SDavid Chisnall                                              ios_base& __iob,
22537a984708SDavid Chisnall                                              ios_base::iostate& __err,
22547a984708SDavid Chisnall                                              tm* __tm) const
22557a984708SDavid Chisnall{
22567a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
22577a984708SDavid Chisnall    __get_year(__tm->tm_year, __b, __e, __err, __ct);
22587a984708SDavid Chisnall    return __b;
22597a984708SDavid Chisnall}
22607a984708SDavid Chisnall
22617a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
22627a984708SDavid Chisnall_InputIterator
22637a984708SDavid Chisnalltime_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
22647a984708SDavid Chisnall                                         ios_base& __iob,
22657a984708SDavid Chisnall                                         ios_base::iostate& __err, tm* __tm,
22667a984708SDavid Chisnall                                         char __fmt, char) const
22677a984708SDavid Chisnall{
22687a984708SDavid Chisnall    __err = ios_base::goodbit;
22697a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
22707a984708SDavid Chisnall    switch (__fmt)
22717a984708SDavid Chisnall    {
22727a984708SDavid Chisnall    case 'a':
22737a984708SDavid Chisnall    case 'A':
22747a984708SDavid Chisnall        __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
22757a984708SDavid Chisnall        break;
22767a984708SDavid Chisnall    case 'b':
22777a984708SDavid Chisnall    case 'B':
22787a984708SDavid Chisnall    case 'h':
22797a984708SDavid Chisnall        __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
22807a984708SDavid Chisnall        break;
22817a984708SDavid Chisnall    case 'c':
22827a984708SDavid Chisnall        {
228394e3ee44SDavid Chisnall        const string_type& __fm = this->__c();
228494e3ee44SDavid Chisnall        __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
22857a984708SDavid Chisnall        }
22867a984708SDavid Chisnall        break;
22877a984708SDavid Chisnall    case 'd':
22887a984708SDavid Chisnall    case 'e':
22897a984708SDavid Chisnall        __get_day(__tm->tm_mday, __b, __e, __err, __ct);
22907a984708SDavid Chisnall        break;
22917a984708SDavid Chisnall    case 'D':
22927a984708SDavid Chisnall        {
229394e3ee44SDavid Chisnall        const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
229494e3ee44SDavid Chisnall        __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
22957a984708SDavid Chisnall        }
22967a984708SDavid Chisnall        break;
22977a984708SDavid Chisnall    case 'F':
22987a984708SDavid Chisnall        {
229994e3ee44SDavid Chisnall        const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
230094e3ee44SDavid Chisnall        __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
23017a984708SDavid Chisnall        }
23027a984708SDavid Chisnall        break;
23037a984708SDavid Chisnall    case 'H':
23047a984708SDavid Chisnall        __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
23057a984708SDavid Chisnall        break;
23067a984708SDavid Chisnall    case 'I':
23077a984708SDavid Chisnall        __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
23087a984708SDavid Chisnall        break;
23097a984708SDavid Chisnall    case 'j':
23107a984708SDavid Chisnall        __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
23117a984708SDavid Chisnall        break;
23127a984708SDavid Chisnall    case 'm':
23137a984708SDavid Chisnall        __get_month(__tm->tm_mon, __b, __e, __err, __ct);
23147a984708SDavid Chisnall        break;
23157a984708SDavid Chisnall    case 'M':
23167a984708SDavid Chisnall        __get_minute(__tm->tm_min, __b, __e, __err, __ct);
23177a984708SDavid Chisnall        break;
23187a984708SDavid Chisnall    case 'n':
23197a984708SDavid Chisnall    case 't':
23207a984708SDavid Chisnall        __get_white_space(__b, __e, __err, __ct);
23217a984708SDavid Chisnall        break;
23227a984708SDavid Chisnall    case 'p':
23237a984708SDavid Chisnall        __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
23247a984708SDavid Chisnall        break;
23257a984708SDavid Chisnall    case 'r':
23267a984708SDavid Chisnall        {
232794e3ee44SDavid Chisnall        const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
232894e3ee44SDavid Chisnall        __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
23297a984708SDavid Chisnall        }
23307a984708SDavid Chisnall        break;
23317a984708SDavid Chisnall    case 'R':
23327a984708SDavid Chisnall        {
233394e3ee44SDavid Chisnall        const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
233494e3ee44SDavid Chisnall        __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
23357a984708SDavid Chisnall        }
23367a984708SDavid Chisnall        break;
23377a984708SDavid Chisnall    case 'S':
23387a984708SDavid Chisnall        __get_second(__tm->tm_sec, __b, __e, __err, __ct);
23397a984708SDavid Chisnall        break;
23407a984708SDavid Chisnall    case 'T':
23417a984708SDavid Chisnall        {
234294e3ee44SDavid Chisnall        const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
234394e3ee44SDavid Chisnall        __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
23447a984708SDavid Chisnall        }
23457a984708SDavid Chisnall        break;
23467a984708SDavid Chisnall    case 'w':
23477a984708SDavid Chisnall        __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
23487a984708SDavid Chisnall        break;
23497a984708SDavid Chisnall    case 'x':
23507a984708SDavid Chisnall        return do_get_date(__b, __e, __iob, __err, __tm);
23517a984708SDavid Chisnall    case 'X':
23527a984708SDavid Chisnall        {
235394e3ee44SDavid Chisnall        const string_type& __fm = this->__X();
235494e3ee44SDavid Chisnall        __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
23557a984708SDavid Chisnall        }
23567a984708SDavid Chisnall        break;
23577a984708SDavid Chisnall    case 'y':
23587a984708SDavid Chisnall        __get_year(__tm->tm_year, __b, __e, __err, __ct);
23597a984708SDavid Chisnall        break;
23607a984708SDavid Chisnall    case 'Y':
23617a984708SDavid Chisnall        __get_year4(__tm->tm_year, __b, __e, __err, __ct);
23627a984708SDavid Chisnall        break;
23637a984708SDavid Chisnall    case '%':
23647a984708SDavid Chisnall        __get_percent(__b, __e, __err, __ct);
23657a984708SDavid Chisnall        break;
23667a984708SDavid Chisnall    default:
23677a984708SDavid Chisnall        __err |= ios_base::failbit;
23687a984708SDavid Chisnall    }
23697a984708SDavid Chisnall    return __b;
23707a984708SDavid Chisnall}
23717a984708SDavid Chisnall
2372aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>)
2373aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>)
23747a984708SDavid Chisnall
23754f7ab58eSDimitry Andricclass _LIBCPP_TYPE_VIS __time_get
23767a984708SDavid Chisnall{
23777a984708SDavid Chisnallprotected:
23787a984708SDavid Chisnall    locale_t __loc_;
23797a984708SDavid Chisnall
23807a984708SDavid Chisnall    __time_get(const char* __nm);
23817a984708SDavid Chisnall    __time_get(const string& __nm);
23827a984708SDavid Chisnall    ~__time_get();
23837a984708SDavid Chisnall};
23847a984708SDavid Chisnall
23857a984708SDavid Chisnalltemplate <class _CharT>
2386aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __time_get_storage
23877a984708SDavid Chisnall    : public __time_get
23887a984708SDavid Chisnall{
23897a984708SDavid Chisnallprotected:
23907a984708SDavid Chisnall    typedef basic_string<_CharT> string_type;
23917a984708SDavid Chisnall
23927a984708SDavid Chisnall    string_type __weeks_[14];
23937a984708SDavid Chisnall    string_type __months_[24];
23947a984708SDavid Chisnall    string_type __am_pm_[2];
23957a984708SDavid Chisnall    string_type __c_;
23967a984708SDavid Chisnall    string_type __r_;
23977a984708SDavid Chisnall    string_type __x_;
23987a984708SDavid Chisnall    string_type __X_;
23997a984708SDavid Chisnall
24007a984708SDavid Chisnall    explicit __time_get_storage(const char* __nm);
24017a984708SDavid Chisnall    explicit __time_get_storage(const string& __nm);
24027a984708SDavid Chisnall
24034ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY ~__time_get_storage() {}
24047a984708SDavid Chisnall
24057a984708SDavid Chisnall    time_base::dateorder __do_date_order() const;
24067a984708SDavid Chisnall
24077a984708SDavid Chisnallprivate:
24087a984708SDavid Chisnall    void init(const ctype<_CharT>&);
24097a984708SDavid Chisnall    string_type __analyze(char __fmt, const ctype<_CharT>&);
24107a984708SDavid Chisnall};
24117a984708SDavid Chisnall
2412*b5893f02SDimitry Andric#define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \
2413*b5893f02SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
2414*b5893f02SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
2415*b5893f02SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
2416*b5893f02SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
2417*b5893f02SDimitry Andrictemplate <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
2418*b5893f02SDimitry Andricextern template _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
2419*b5893f02SDimitry Andricextern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
2420*b5893f02SDimitry Andricextern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
2421*b5893f02SDimitry Andricextern template _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
2422*b5893f02SDimitry Andricextern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
2423*b5893f02SDimitry Andric/**/
2424*b5893f02SDimitry Andric
2425*b5893f02SDimitry Andric_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char)
2426*b5893f02SDimitry Andric_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t)
2427*b5893f02SDimitry Andric#undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION
2428*b5893f02SDimitry Andric
24297a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
2430aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS time_get_byname
24317a984708SDavid Chisnall    : public time_get<_CharT, _InputIterator>,
24327a984708SDavid Chisnall      private __time_get_storage<_CharT>
24337a984708SDavid Chisnall{
24347a984708SDavid Chisnallpublic:
24357a984708SDavid Chisnall    typedef time_base::dateorder    dateorder;
24367a984708SDavid Chisnall    typedef _InputIterator          iter_type;
24377a984708SDavid Chisnall    typedef _CharT                  char_type;
24387a984708SDavid Chisnall    typedef basic_string<char_type> string_type;
24397a984708SDavid Chisnall
24407a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24417a984708SDavid Chisnall    explicit time_get_byname(const char* __nm, size_t __refs = 0)
24427a984708SDavid Chisnall        : time_get<_CharT, _InputIterator>(__refs),
24437a984708SDavid Chisnall          __time_get_storage<_CharT>(__nm) {}
24447a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24457a984708SDavid Chisnall    explicit time_get_byname(const string& __nm, size_t __refs = 0)
24467a984708SDavid Chisnall        : time_get<_CharT, _InputIterator>(__refs),
24477a984708SDavid Chisnall          __time_get_storage<_CharT>(__nm) {}
24487a984708SDavid Chisnall
24497a984708SDavid Chisnallprotected:
24507a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24517a984708SDavid Chisnall    ~time_get_byname() {}
24527a984708SDavid Chisnall
24537a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24547a984708SDavid Chisnall    virtual dateorder do_date_order() const {return this->__do_date_order();}
24557a984708SDavid Chisnallprivate:
24567a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24577a984708SDavid Chisnall    virtual const string_type* __weeks() const  {return this->__weeks_;}
24587a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24597a984708SDavid Chisnall    virtual const string_type* __months() const {return this->__months_;}
24607a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24617a984708SDavid Chisnall    virtual const string_type* __am_pm() const  {return this->__am_pm_;}
24627a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24637a984708SDavid Chisnall    virtual const string_type& __c() const      {return this->__c_;}
24647a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24657a984708SDavid Chisnall    virtual const string_type& __r() const      {return this->__r_;}
24667a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24677a984708SDavid Chisnall    virtual const string_type& __x() const      {return this->__x_;}
24687a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
24697a984708SDavid Chisnall    virtual const string_type& __X() const      {return this->__X_;}
24707a984708SDavid Chisnall};
24717a984708SDavid Chisnall
2472aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>)
2473aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>)
24747a984708SDavid Chisnall
24754f7ab58eSDimitry Andricclass _LIBCPP_TYPE_VIS __time_put
24767a984708SDavid Chisnall{
24777a984708SDavid Chisnall    locale_t __loc_;
24787a984708SDavid Chisnallprotected:
24794ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
24807a984708SDavid Chisnall    __time_put(const char* __nm);
24817a984708SDavid Chisnall    __time_put(const string& __nm);
24827a984708SDavid Chisnall    ~__time_put();
24837a984708SDavid Chisnall    void __do_put(char* __nb, char*& __ne, const tm* __tm,
24847a984708SDavid Chisnall                  char __fmt, char __mod) const;
24857a984708SDavid Chisnall    void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
24867a984708SDavid Chisnall                  char __fmt, char __mod) const;
24877a984708SDavid Chisnall};
24887a984708SDavid Chisnall
24897a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
2490aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS time_put
24917a984708SDavid Chisnall    : public locale::facet,
24927a984708SDavid Chisnall      private __time_put
24937a984708SDavid Chisnall{
24947a984708SDavid Chisnallpublic:
24957a984708SDavid Chisnall    typedef _CharT char_type;
24967a984708SDavid Chisnall    typedef _OutputIterator iter_type;
24977a984708SDavid Chisnall
24984ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
24997a984708SDavid Chisnall    explicit time_put(size_t __refs = 0)
25007a984708SDavid Chisnall        : locale::facet(__refs) {}
25017a984708SDavid Chisnall
25027a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
25037a984708SDavid Chisnall                  const char_type* __pb, const char_type* __pe) const;
25047a984708SDavid Chisnall
25054ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
25067a984708SDavid Chisnall    iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
25077a984708SDavid Chisnall                  const tm* __tm, char __fmt, char __mod = 0) const
25087a984708SDavid Chisnall    {
25097a984708SDavid Chisnall        return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
25107a984708SDavid Chisnall    }
25117a984708SDavid Chisnall
25127a984708SDavid Chisnall    static locale::id id;
25137a984708SDavid Chisnall
25147a984708SDavid Chisnallprotected:
25154ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
25167a984708SDavid Chisnall    ~time_put() {}
25177a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
25187a984708SDavid Chisnall                             char __fmt, char __mod) const;
25197a984708SDavid Chisnall
25204ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
25217a984708SDavid Chisnall    explicit time_put(const char* __nm, size_t __refs)
25227a984708SDavid Chisnall        : locale::facet(__refs),
25237a984708SDavid Chisnall          __time_put(__nm) {}
25244ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
25257a984708SDavid Chisnall    explicit time_put(const string& __nm, size_t __refs)
25267a984708SDavid Chisnall        : locale::facet(__refs),
25277a984708SDavid Chisnall          __time_put(__nm) {}
25287a984708SDavid Chisnall};
25297a984708SDavid Chisnall
25307a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
25317a984708SDavid Chisnalllocale::id
25327a984708SDavid Chisnalltime_put<_CharT, _OutputIterator>::id;
25337a984708SDavid Chisnall
25347a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
25357a984708SDavid Chisnall_OutputIterator
25367a984708SDavid Chisnalltime_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
25377a984708SDavid Chisnall                                       char_type __fl, const tm* __tm,
25387a984708SDavid Chisnall                                       const char_type* __pb,
25397a984708SDavid Chisnall                                       const char_type* __pe) const
25407a984708SDavid Chisnall{
25417a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
25427a984708SDavid Chisnall    for (; __pb != __pe; ++__pb)
25437a984708SDavid Chisnall    {
25447a984708SDavid Chisnall        if (__ct.narrow(*__pb, 0) == '%')
25457a984708SDavid Chisnall        {
25467a984708SDavid Chisnall            if (++__pb == __pe)
25477a984708SDavid Chisnall            {
25487a984708SDavid Chisnall                *__s++ = __pb[-1];
25497a984708SDavid Chisnall                break;
25507a984708SDavid Chisnall            }
25517a984708SDavid Chisnall            char __mod = 0;
25527a984708SDavid Chisnall            char __fmt = __ct.narrow(*__pb, 0);
25537a984708SDavid Chisnall            if (__fmt == 'E' || __fmt == 'O')
25547a984708SDavid Chisnall            {
25557a984708SDavid Chisnall                if (++__pb == __pe)
25567a984708SDavid Chisnall                {
25577a984708SDavid Chisnall                    *__s++ = __pb[-2];
25587a984708SDavid Chisnall                    *__s++ = __pb[-1];
25597a984708SDavid Chisnall                    break;
25607a984708SDavid Chisnall                }
25617a984708SDavid Chisnall                __mod = __fmt;
25627a984708SDavid Chisnall                __fmt = __ct.narrow(*__pb, 0);
25637a984708SDavid Chisnall            }
25647a984708SDavid Chisnall            __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
25657a984708SDavid Chisnall        }
25667a984708SDavid Chisnall        else
25677a984708SDavid Chisnall            *__s++ = *__pb;
25687a984708SDavid Chisnall    }
25697a984708SDavid Chisnall    return __s;
25707a984708SDavid Chisnall}
25717a984708SDavid Chisnall
25727a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
25737a984708SDavid Chisnall_OutputIterator
257494e3ee44SDavid Chisnalltime_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
25757a984708SDavid Chisnall                                          char_type, const tm* __tm,
25767a984708SDavid Chisnall                                          char __fmt, char __mod) const
25777a984708SDavid Chisnall{
25787a984708SDavid Chisnall    char_type __nar[100];
25797a984708SDavid Chisnall    char_type* __nb = __nar;
25807a984708SDavid Chisnall    char_type* __ne = __nb + 100;
25817a984708SDavid Chisnall    __do_put(__nb, __ne, __tm, __fmt, __mod);
25827a984708SDavid Chisnall    return _VSTD::copy(__nb, __ne, __s);
25837a984708SDavid Chisnall}
25847a984708SDavid Chisnall
2585aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<char>)
2586aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<wchar_t>)
25877a984708SDavid Chisnall
25887a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
2589aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS time_put_byname
25907a984708SDavid Chisnall    : public time_put<_CharT, _OutputIterator>
25917a984708SDavid Chisnall{
25927a984708SDavid Chisnallpublic:
25934ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
25947a984708SDavid Chisnall    explicit time_put_byname(const char* __nm, size_t __refs = 0)
25957a984708SDavid Chisnall        : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
25967a984708SDavid Chisnall
25974ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
25987a984708SDavid Chisnall    explicit time_put_byname(const string& __nm, size_t __refs = 0)
25997a984708SDavid Chisnall        : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
26007a984708SDavid Chisnall
26017a984708SDavid Chisnallprotected:
26024ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
26037a984708SDavid Chisnall    ~time_put_byname() {}
26047a984708SDavid Chisnall};
26057a984708SDavid Chisnall
2606aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<char>)
2607aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<wchar_t>)
26087a984708SDavid Chisnall
26097a984708SDavid Chisnall// money_base
26107a984708SDavid Chisnall
26111bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS money_base
26127a984708SDavid Chisnall{
26137a984708SDavid Chisnallpublic:
26147a984708SDavid Chisnall    enum part {none, space, symbol, sign, value};
26157a984708SDavid Chisnall    struct pattern {char field[4];};
26167a984708SDavid Chisnall
26174ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY money_base() {}
26187a984708SDavid Chisnall};
26197a984708SDavid Chisnall
26207a984708SDavid Chisnall// moneypunct
26217a984708SDavid Chisnall
26227a984708SDavid Chisnalltemplate <class _CharT, bool _International = false>
2623aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS moneypunct
26247a984708SDavid Chisnall    : public locale::facet,
26257a984708SDavid Chisnall      public money_base
26267a984708SDavid Chisnall{
26277a984708SDavid Chisnallpublic:
26287a984708SDavid Chisnall    typedef _CharT                  char_type;
26297a984708SDavid Chisnall    typedef basic_string<char_type> string_type;
26307a984708SDavid Chisnall
26314ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
26327a984708SDavid Chisnall    explicit moneypunct(size_t __refs = 0)
26337a984708SDavid Chisnall        : locale::facet(__refs) {}
26347a984708SDavid Chisnall
26354ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY char_type   decimal_point() const {return do_decimal_point();}
26364ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY char_type   thousands_sep() const {return do_thousands_sep();}
26374ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY string      grouping()      const {return do_grouping();}
26384ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY string_type curr_symbol()   const {return do_curr_symbol();}
26394ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY string_type positive_sign() const {return do_positive_sign();}
26404ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY string_type negative_sign() const {return do_negative_sign();}
26414ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY int         frac_digits()   const {return do_frac_digits();}
26424ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY pattern     pos_format()    const {return do_pos_format();}
26434ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY pattern     neg_format()    const {return do_neg_format();}
26447a984708SDavid Chisnall
26457a984708SDavid Chisnall    static locale::id id;
26467a984708SDavid Chisnall    static const bool intl = _International;
26477a984708SDavid Chisnall
26487a984708SDavid Chisnallprotected:
26494ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
26507a984708SDavid Chisnall    ~moneypunct() {}
26517a984708SDavid Chisnall
26527a984708SDavid Chisnall    virtual char_type   do_decimal_point() const {return numeric_limits<char_type>::max();}
26537a984708SDavid Chisnall    virtual char_type   do_thousands_sep() const {return numeric_limits<char_type>::max();}
26547a984708SDavid Chisnall    virtual string      do_grouping()      const {return string();}
26557a984708SDavid Chisnall    virtual string_type do_curr_symbol()   const {return string_type();}
26567a984708SDavid Chisnall    virtual string_type do_positive_sign() const {return string_type();}
26577a984708SDavid Chisnall    virtual string_type do_negative_sign() const {return string_type(1, '-');}
26587a984708SDavid Chisnall    virtual int         do_frac_digits()   const {return 0;}
26597a984708SDavid Chisnall    virtual pattern     do_pos_format()    const
2660d3c53822SDimitry Andric        {pattern __p = {{symbol, sign, none, value}}; return __p;}
26617a984708SDavid Chisnall    virtual pattern     do_neg_format()    const
2662d3c53822SDimitry Andric        {pattern __p = {{symbol, sign, none, value}}; return __p;}
26637a984708SDavid Chisnall};
26647a984708SDavid Chisnall
26657a984708SDavid Chisnalltemplate <class _CharT, bool _International>
26667a984708SDavid Chisnalllocale::id
26677a984708SDavid Chisnallmoneypunct<_CharT, _International>::id;
26687a984708SDavid Chisnall
2669cfdf2879SDavid Chisnalltemplate <class _CharT, bool _International>
2670cfdf2879SDavid Chisnallconst bool
2671cfdf2879SDavid Chisnallmoneypunct<_CharT, _International>::intl;
2672cfdf2879SDavid Chisnall
2673aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>)
2674aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>)
2675aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>)
2676aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>)
26777a984708SDavid Chisnall
26787a984708SDavid Chisnall// moneypunct_byname
26797a984708SDavid Chisnall
26807a984708SDavid Chisnalltemplate <class _CharT, bool _International = false>
2681aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS moneypunct_byname
26827a984708SDavid Chisnall    : public moneypunct<_CharT, _International>
26837a984708SDavid Chisnall{
26847a984708SDavid Chisnallpublic:
26857a984708SDavid Chisnall    typedef money_base::pattern  pattern;
26867a984708SDavid Chisnall    typedef _CharT                  char_type;
26877a984708SDavid Chisnall    typedef basic_string<char_type> string_type;
26887a984708SDavid Chisnall
26894ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
26907a984708SDavid Chisnall    explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
26917a984708SDavid Chisnall        : moneypunct<_CharT, _International>(__refs) {init(__nm);}
26927a984708SDavid Chisnall
26934ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
26947a984708SDavid Chisnall    explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
26957a984708SDavid Chisnall        : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
26967a984708SDavid Chisnall
26977a984708SDavid Chisnallprotected:
26984ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
26997a984708SDavid Chisnall    ~moneypunct_byname() {}
27007a984708SDavid Chisnall
27017a984708SDavid Chisnall    virtual char_type   do_decimal_point() const {return __decimal_point_;}
27027a984708SDavid Chisnall    virtual char_type   do_thousands_sep() const {return __thousands_sep_;}
27037a984708SDavid Chisnall    virtual string      do_grouping()      const {return __grouping_;}
27047a984708SDavid Chisnall    virtual string_type do_curr_symbol()   const {return __curr_symbol_;}
27057a984708SDavid Chisnall    virtual string_type do_positive_sign() const {return __positive_sign_;}
27067a984708SDavid Chisnall    virtual string_type do_negative_sign() const {return __negative_sign_;}
27077a984708SDavid Chisnall    virtual int         do_frac_digits()   const {return __frac_digits_;}
27087a984708SDavid Chisnall    virtual pattern     do_pos_format()    const {return __pos_format_;}
27097a984708SDavid Chisnall    virtual pattern     do_neg_format()    const {return __neg_format_;}
27107a984708SDavid Chisnall
27117a984708SDavid Chisnallprivate:
27127a984708SDavid Chisnall    char_type   __decimal_point_;
27137a984708SDavid Chisnall    char_type   __thousands_sep_;
27147a984708SDavid Chisnall    string      __grouping_;
27157a984708SDavid Chisnall    string_type __curr_symbol_;
27167a984708SDavid Chisnall    string_type __positive_sign_;
27177a984708SDavid Chisnall    string_type __negative_sign_;
27187a984708SDavid Chisnall    int         __frac_digits_;
27197a984708SDavid Chisnall    pattern     __pos_format_;
27207a984708SDavid Chisnall    pattern     __neg_format_;
27217a984708SDavid Chisnall
27227a984708SDavid Chisnall    void init(const char*);
27237a984708SDavid Chisnall};
27247a984708SDavid Chisnall
2725540d2a8bSDimitry Andrictemplate<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, false>::init(const char*);
2726540d2a8bSDimitry Andrictemplate<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, true>::init(const char*);
2727540d2a8bSDimitry Andrictemplate<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, false>::init(const char*);
2728540d2a8bSDimitry Andrictemplate<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, true>::init(const char*);
27297a984708SDavid Chisnall
2730aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>)
2731aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>)
2732aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>)
2733aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>)
27347a984708SDavid Chisnall
27357a984708SDavid Chisnall// money_get
27367a984708SDavid Chisnall
27377a984708SDavid Chisnalltemplate <class _CharT>
27387a984708SDavid Chisnallclass __money_get
27397a984708SDavid Chisnall{
27407a984708SDavid Chisnallprotected:
27417a984708SDavid Chisnall    typedef _CharT                  char_type;
27427a984708SDavid Chisnall    typedef basic_string<char_type> string_type;
27437a984708SDavid Chisnall
27444ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY __money_get() {}
27457a984708SDavid Chisnall
27467a984708SDavid Chisnall    static void __gather_info(bool __intl, const locale& __loc,
27477a984708SDavid Chisnall                              money_base::pattern& __pat, char_type& __dp,
27487a984708SDavid Chisnall                              char_type& __ts, string& __grp,
27497a984708SDavid Chisnall                              string_type& __sym, string_type& __psn,
27507a984708SDavid Chisnall                              string_type& __nsn, int& __fd);
27517a984708SDavid Chisnall};
27527a984708SDavid Chisnall
27537a984708SDavid Chisnalltemplate <class _CharT>
27547a984708SDavid Chisnallvoid
27557a984708SDavid Chisnall__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
27567a984708SDavid Chisnall                                   money_base::pattern& __pat, char_type& __dp,
27577a984708SDavid Chisnall                                   char_type& __ts, string& __grp,
27587a984708SDavid Chisnall                                   string_type& __sym, string_type& __psn,
27597a984708SDavid Chisnall                                   string_type& __nsn, int& __fd)
27607a984708SDavid Chisnall{
27617a984708SDavid Chisnall    if (__intl)
27627a984708SDavid Chisnall    {
27637a984708SDavid Chisnall        const moneypunct<char_type, true>& __mp =
27647a984708SDavid Chisnall            use_facet<moneypunct<char_type, true> >(__loc);
27657a984708SDavid Chisnall        __pat = __mp.neg_format();
27667a984708SDavid Chisnall        __nsn = __mp.negative_sign();
27677a984708SDavid Chisnall        __psn = __mp.positive_sign();
27687a984708SDavid Chisnall        __dp = __mp.decimal_point();
27697a984708SDavid Chisnall        __ts = __mp.thousands_sep();
27707a984708SDavid Chisnall        __grp = __mp.grouping();
27717a984708SDavid Chisnall        __sym = __mp.curr_symbol();
27727a984708SDavid Chisnall        __fd = __mp.frac_digits();
27737a984708SDavid Chisnall    }
27747a984708SDavid Chisnall    else
27757a984708SDavid Chisnall    {
27767a984708SDavid Chisnall        const moneypunct<char_type, false>& __mp =
27777a984708SDavid Chisnall            use_facet<moneypunct<char_type, false> >(__loc);
27787a984708SDavid Chisnall        __pat = __mp.neg_format();
27797a984708SDavid Chisnall        __nsn = __mp.negative_sign();
27807a984708SDavid Chisnall        __psn = __mp.positive_sign();
27817a984708SDavid Chisnall        __dp = __mp.decimal_point();
27827a984708SDavid Chisnall        __ts = __mp.thousands_sep();
27837a984708SDavid Chisnall        __grp = __mp.grouping();
27847a984708SDavid Chisnall        __sym = __mp.curr_symbol();
27857a984708SDavid Chisnall        __fd = __mp.frac_digits();
27867a984708SDavid Chisnall    }
27877a984708SDavid Chisnall}
27887a984708SDavid Chisnall
2789aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>)
2790aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>)
27917a984708SDavid Chisnall
27927a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
2793aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS money_get
27947a984708SDavid Chisnall    : public locale::facet,
27957a984708SDavid Chisnall      private __money_get<_CharT>
27967a984708SDavid Chisnall{
27977a984708SDavid Chisnallpublic:
27987a984708SDavid Chisnall    typedef _CharT                  char_type;
27997a984708SDavid Chisnall    typedef _InputIterator          iter_type;
28007a984708SDavid Chisnall    typedef basic_string<char_type> string_type;
28017a984708SDavid Chisnall
28024ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
28037a984708SDavid Chisnall    explicit money_get(size_t __refs = 0)
28047a984708SDavid Chisnall        : locale::facet(__refs) {}
28057a984708SDavid Chisnall
28064ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
28077a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
28087a984708SDavid Chisnall                  ios_base::iostate& __err, long double& __v) const
28097a984708SDavid Chisnall    {
28107a984708SDavid Chisnall        return do_get(__b, __e, __intl, __iob, __err, __v);
28117a984708SDavid Chisnall    }
28127a984708SDavid Chisnall
28134ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
28147a984708SDavid Chisnall    iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
28157a984708SDavid Chisnall                  ios_base::iostate& __err, string_type& __v) const
28167a984708SDavid Chisnall    {
28177a984708SDavid Chisnall        return do_get(__b, __e, __intl, __iob, __err, __v);
28187a984708SDavid Chisnall    }
28197a984708SDavid Chisnall
28207a984708SDavid Chisnall    static locale::id id;
28217a984708SDavid Chisnall
28227a984708SDavid Chisnallprotected:
28237a984708SDavid Chisnall
28244ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
28257a984708SDavid Chisnall    ~money_get() {}
28267a984708SDavid Chisnall
28277a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
28287a984708SDavid Chisnall                             ios_base& __iob, ios_base::iostate& __err,
28297a984708SDavid Chisnall                             long double& __v) const;
28307a984708SDavid Chisnall    virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
28317a984708SDavid Chisnall                             ios_base& __iob, ios_base::iostate& __err,
28327a984708SDavid Chisnall                             string_type& __v) const;
28337a984708SDavid Chisnall
28347a984708SDavid Chisnallprivate:
28357a984708SDavid Chisnall    static bool __do_get(iter_type& __b, iter_type __e,
28367a984708SDavid Chisnall                         bool __intl, const locale& __loc,
28377a984708SDavid Chisnall                         ios_base::fmtflags __flags, ios_base::iostate& __err,
28387a984708SDavid Chisnall                         bool& __neg, const ctype<char_type>& __ct,
28397a984708SDavid Chisnall                         unique_ptr<char_type, void(*)(void*)>& __wb,
28407a984708SDavid Chisnall                         char_type*& __wn, char_type* __we);
28417a984708SDavid Chisnall};
28427a984708SDavid Chisnall
28437a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
28447a984708SDavid Chisnalllocale::id
28457a984708SDavid Chisnallmoney_get<_CharT, _InputIterator>::id;
28467a984708SDavid Chisnall
28474f7ab58eSDimitry Andric_LIBCPP_FUNC_VIS void __do_nothing(void*);
28487a984708SDavid Chisnall
28497a984708SDavid Chisnalltemplate <class _Tp>
28507a984708SDavid Chisnall_LIBCPP_HIDDEN
28517a984708SDavid Chisnallvoid
28527a984708SDavid Chisnall__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
28537a984708SDavid Chisnall{
28547a984708SDavid Chisnall    bool __owns = __b.get_deleter() != __do_nothing;
285594e3ee44SDavid Chisnall    size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
28567a984708SDavid Chisnall    size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
28577a984708SDavid Chisnall                       2 * __cur_cap : numeric_limits<size_t>::max();
2858d72607e9SDimitry Andric    if (__new_cap == 0)
2859d72607e9SDimitry Andric        __new_cap = sizeof(_Tp);
286094e3ee44SDavid Chisnall    size_t __n_off = static_cast<size_t>(__n - __b.get());
28617a984708SDavid Chisnall    _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
28627a984708SDavid Chisnall    if (__t == 0)
28637a984708SDavid Chisnall        __throw_bad_alloc();
28647a984708SDavid Chisnall    if (__owns)
28657a984708SDavid Chisnall        __b.release();
28667a984708SDavid Chisnall    __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
28677a984708SDavid Chisnall    __new_cap /= sizeof(_Tp);
28687a984708SDavid Chisnall    __n = __b.get() + __n_off;
28697a984708SDavid Chisnall    __e = __b.get() + __new_cap;
28707a984708SDavid Chisnall}
28717a984708SDavid Chisnall
28727a984708SDavid Chisnall// true == success
28737a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
28747a984708SDavid Chisnallbool
28757a984708SDavid Chisnallmoney_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
28767a984708SDavid Chisnall                                            bool __intl, const locale& __loc,
28777a984708SDavid Chisnall                                            ios_base::fmtflags __flags,
28787a984708SDavid Chisnall                                            ios_base::iostate& __err,
28797a984708SDavid Chisnall                                            bool& __neg,
28807a984708SDavid Chisnall                                            const ctype<char_type>& __ct,
28817a984708SDavid Chisnall                                            unique_ptr<char_type, void(*)(void*)>& __wb,
28827a984708SDavid Chisnall                                            char_type*& __wn, char_type* __we)
28837a984708SDavid Chisnall{
28847a984708SDavid Chisnall    const unsigned __bz = 100;
28857a984708SDavid Chisnall    unsigned __gbuf[__bz];
28867a984708SDavid Chisnall    unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
28877a984708SDavid Chisnall    unsigned* __gn = __gb.get();
28887a984708SDavid Chisnall    unsigned* __ge = __gn + __bz;
28897a984708SDavid Chisnall    money_base::pattern __pat;
28907a984708SDavid Chisnall    char_type __dp;
28917a984708SDavid Chisnall    char_type __ts;
28927a984708SDavid Chisnall    string __grp;
28937a984708SDavid Chisnall    string_type __sym;
28947a984708SDavid Chisnall    string_type __psn;
28957a984708SDavid Chisnall    string_type __nsn;
289694e3ee44SDavid Chisnall    // Capture the spaces read into money_base::{space,none} so they
289794e3ee44SDavid Chisnall    // can be compared to initial spaces in __sym.
289894e3ee44SDavid Chisnall    string_type __spaces;
28997a984708SDavid Chisnall    int __fd;
29007a984708SDavid Chisnall    __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
29017a984708SDavid Chisnall                                       __sym, __psn, __nsn, __fd);
29027a984708SDavid Chisnall    const string_type* __trailing_sign = 0;
29037a984708SDavid Chisnall    __wn = __wb.get();
29047a984708SDavid Chisnall    for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
29057a984708SDavid Chisnall    {
29067a984708SDavid Chisnall        switch (__pat.field[__p])
29077a984708SDavid Chisnall        {
29087a984708SDavid Chisnall        case money_base::space:
29097a984708SDavid Chisnall            if (__p != 3)
29107a984708SDavid Chisnall            {
29117a984708SDavid Chisnall                if (__ct.is(ctype_base::space, *__b))
291294e3ee44SDavid Chisnall                    __spaces.push_back(*__b++);
29137a984708SDavid Chisnall                else
29147a984708SDavid Chisnall                {
29157a984708SDavid Chisnall                    __err |= ios_base::failbit;
29167a984708SDavid Chisnall                    return false;
29177a984708SDavid Chisnall                }
29187a984708SDavid Chisnall            }
29190f5676f4SDimitry Andric            _LIBCPP_FALLTHROUGH();
29207a984708SDavid Chisnall        case money_base::none:
29217a984708SDavid Chisnall            if (__p != 3)
29227a984708SDavid Chisnall            {
29237a984708SDavid Chisnall                while (__b != __e && __ct.is(ctype_base::space, *__b))
292494e3ee44SDavid Chisnall                    __spaces.push_back(*__b++);
29257a984708SDavid Chisnall            }
29267a984708SDavid Chisnall            break;
29277a984708SDavid Chisnall        case money_base::sign:
29287a984708SDavid Chisnall            if (__psn.size() + __nsn.size() > 0)
29297a984708SDavid Chisnall            {
29307a984708SDavid Chisnall                if (__psn.size() == 0 || __nsn.size() == 0)
29317a984708SDavid Chisnall                {   // sign is optional
29327a984708SDavid Chisnall                    if (__psn.size() > 0)
29337a984708SDavid Chisnall                    {   // __nsn.size() == 0
29347a984708SDavid Chisnall                        if (*__b == __psn[0])
29357a984708SDavid Chisnall                        {
29367a984708SDavid Chisnall                            ++__b;
29377a984708SDavid Chisnall                            if (__psn.size() > 1)
29387a984708SDavid Chisnall                                __trailing_sign = &__psn;
29397a984708SDavid Chisnall                        }
29407a984708SDavid Chisnall                        else
29417a984708SDavid Chisnall                            __neg = true;
29427a984708SDavid Chisnall                    }
29437a984708SDavid Chisnall                    else if (*__b == __nsn[0])  // __nsn.size() > 0 &&  __psn.size() == 0
29447a984708SDavid Chisnall                    {
29457a984708SDavid Chisnall                        ++__b;
29467a984708SDavid Chisnall                        __neg = true;
29477a984708SDavid Chisnall                        if (__nsn.size() > 1)
29487a984708SDavid Chisnall                            __trailing_sign = &__nsn;
29497a984708SDavid Chisnall                    }
29507a984708SDavid Chisnall                }
29517a984708SDavid Chisnall                else  // sign is required
29527a984708SDavid Chisnall                {
29537a984708SDavid Chisnall                    if (*__b == __psn[0])
29547a984708SDavid Chisnall                    {
29557a984708SDavid Chisnall                        ++__b;
29567a984708SDavid Chisnall                        if (__psn.size() > 1)
29577a984708SDavid Chisnall                            __trailing_sign = &__psn;
29587a984708SDavid Chisnall                    }
29597a984708SDavid Chisnall                    else if (*__b == __nsn[0])
29607a984708SDavid Chisnall                    {
29617a984708SDavid Chisnall                        ++__b;
29627a984708SDavid Chisnall                        __neg = true;
29637a984708SDavid Chisnall                        if (__nsn.size() > 1)
29647a984708SDavid Chisnall                            __trailing_sign = &__nsn;
29657a984708SDavid Chisnall                    }
29667a984708SDavid Chisnall                    else
29677a984708SDavid Chisnall                    {
29687a984708SDavid Chisnall                        __err |= ios_base::failbit;
29697a984708SDavid Chisnall                        return false;
29707a984708SDavid Chisnall                    }
29717a984708SDavid Chisnall                }
29727a984708SDavid Chisnall            }
29737a984708SDavid Chisnall            break;
29747a984708SDavid Chisnall        case money_base::symbol:
29757a984708SDavid Chisnall            {
29767a984708SDavid Chisnall            bool __more_needed = __trailing_sign ||
29777a984708SDavid Chisnall                                 (__p < 2)       ||
29787a984708SDavid Chisnall                                 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
29794f7ab58eSDimitry Andric            bool __sb = (__flags & ios_base::showbase) != 0;
29807a984708SDavid Chisnall            if (__sb || __more_needed)
29817a984708SDavid Chisnall            {
298294e3ee44SDavid Chisnall                typename string_type::const_iterator __sym_space_end = __sym.begin();
298394e3ee44SDavid Chisnall                if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
298494e3ee44SDavid Chisnall                                __pat.field[__p - 1] == money_base::space)) {
298594e3ee44SDavid Chisnall                    // Match spaces we've already read against spaces at
298694e3ee44SDavid Chisnall                    // the beginning of __sym.
298794e3ee44SDavid Chisnall                    while (__sym_space_end != __sym.end() &&
298894e3ee44SDavid Chisnall                           __ct.is(ctype_base::space, *__sym_space_end))
298994e3ee44SDavid Chisnall                        ++__sym_space_end;
299094e3ee44SDavid Chisnall                    const size_t __num_spaces = __sym_space_end - __sym.begin();
299194e3ee44SDavid Chisnall                    if (__num_spaces > __spaces.size() ||
299294e3ee44SDavid Chisnall                        !equal(__spaces.end() - __num_spaces, __spaces.end(),
299394e3ee44SDavid Chisnall                               __sym.begin())) {
299494e3ee44SDavid Chisnall                        // No match. Put __sym_space_end back at the
299594e3ee44SDavid Chisnall                        // beginning of __sym, which will prevent a
299694e3ee44SDavid Chisnall                        // match in the next loop.
299794e3ee44SDavid Chisnall                        __sym_space_end = __sym.begin();
299894e3ee44SDavid Chisnall                    }
299994e3ee44SDavid Chisnall                }
300094e3ee44SDavid Chisnall                typename string_type::const_iterator __sym_curr_char = __sym_space_end;
300194e3ee44SDavid Chisnall                while (__sym_curr_char != __sym.end() && __b != __e &&
300294e3ee44SDavid Chisnall                       *__b == *__sym_curr_char) {
300394e3ee44SDavid Chisnall                    ++__b;
300494e3ee44SDavid Chisnall                    ++__sym_curr_char;
300594e3ee44SDavid Chisnall                }
300694e3ee44SDavid Chisnall                if (__sb && __sym_curr_char != __sym.end())
30077a984708SDavid Chisnall                {
30087a984708SDavid Chisnall                    __err |= ios_base::failbit;
30097a984708SDavid Chisnall                    return false;
30107a984708SDavid Chisnall                }
30117a984708SDavid Chisnall            }
30127a984708SDavid Chisnall            }
30137a984708SDavid Chisnall            break;
30147a984708SDavid Chisnall        case money_base::value:
30157a984708SDavid Chisnall            {
30167a984708SDavid Chisnall            unsigned __ng = 0;
30177a984708SDavid Chisnall            for (; __b != __e; ++__b)
30187a984708SDavid Chisnall            {
30197a984708SDavid Chisnall                char_type __c = *__b;
30207a984708SDavid Chisnall                if (__ct.is(ctype_base::digit, __c))
30217a984708SDavid Chisnall                {
30227a984708SDavid Chisnall                    if (__wn == __we)
30237a984708SDavid Chisnall                        __double_or_nothing(__wb, __wn, __we);
30247a984708SDavid Chisnall                    *__wn++ = __c;
30257a984708SDavid Chisnall                    ++__ng;
30267a984708SDavid Chisnall                }
30277a984708SDavid Chisnall                else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
30287a984708SDavid Chisnall                {
30297a984708SDavid Chisnall                    if (__gn == __ge)
30307a984708SDavid Chisnall                        __double_or_nothing(__gb, __gn, __ge);
30317a984708SDavid Chisnall                    *__gn++ = __ng;
30327a984708SDavid Chisnall                    __ng = 0;
30337a984708SDavid Chisnall                }
30347a984708SDavid Chisnall                else
30357a984708SDavid Chisnall                    break;
30367a984708SDavid Chisnall            }
30377a984708SDavid Chisnall            if (__gb.get() != __gn && __ng > 0)
30387a984708SDavid Chisnall            {
30397a984708SDavid Chisnall                if (__gn == __ge)
30407a984708SDavid Chisnall                    __double_or_nothing(__gb, __gn, __ge);
30417a984708SDavid Chisnall                *__gn++ = __ng;
30427a984708SDavid Chisnall            }
30437a984708SDavid Chisnall            if (__fd > 0)
30447a984708SDavid Chisnall            {
30457a984708SDavid Chisnall                if (__b == __e || *__b != __dp)
30467a984708SDavid Chisnall                {
30477a984708SDavid Chisnall                    __err |= ios_base::failbit;
30487a984708SDavid Chisnall                    return false;
30497a984708SDavid Chisnall                }
30507a984708SDavid Chisnall                for (++__b; __fd > 0; --__fd, ++__b)
30517a984708SDavid Chisnall                {
30527a984708SDavid Chisnall                    if (__b == __e || !__ct.is(ctype_base::digit, *__b))
30537a984708SDavid Chisnall                    {
30547a984708SDavid Chisnall                        __err |= ios_base::failbit;
30557a984708SDavid Chisnall                        return false;
30567a984708SDavid Chisnall                    }
30577a984708SDavid Chisnall                    if (__wn == __we)
30587a984708SDavid Chisnall                        __double_or_nothing(__wb, __wn, __we);
30597a984708SDavid Chisnall                    *__wn++ = *__b;
30607a984708SDavid Chisnall                }
30617a984708SDavid Chisnall            }
30627a984708SDavid Chisnall            if (__wn == __wb.get())
30637a984708SDavid Chisnall            {
30647a984708SDavid Chisnall                __err |= ios_base::failbit;
30657a984708SDavid Chisnall                return false;
30667a984708SDavid Chisnall            }
30677a984708SDavid Chisnall            }
30687a984708SDavid Chisnall            break;
30697a984708SDavid Chisnall        }
30707a984708SDavid Chisnall    }
30717a984708SDavid Chisnall    if (__trailing_sign)
30727a984708SDavid Chisnall    {
30737a984708SDavid Chisnall        for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
30747a984708SDavid Chisnall        {
30757a984708SDavid Chisnall            if (__b == __e || *__b != (*__trailing_sign)[__i])
30767a984708SDavid Chisnall            {
30777a984708SDavid Chisnall                __err |= ios_base::failbit;
30787a984708SDavid Chisnall                return false;
30797a984708SDavid Chisnall            }
30807a984708SDavid Chisnall        }
30817a984708SDavid Chisnall    }
30827a984708SDavid Chisnall    if (__gb.get() != __gn)
30837a984708SDavid Chisnall    {
30847a984708SDavid Chisnall        ios_base::iostate __et = ios_base::goodbit;
30857a984708SDavid Chisnall        __check_grouping(__grp, __gb.get(), __gn, __et);
30867a984708SDavid Chisnall        if (__et)
30877a984708SDavid Chisnall        {
30887a984708SDavid Chisnall            __err |= ios_base::failbit;
30897a984708SDavid Chisnall            return false;
30907a984708SDavid Chisnall        }
30917a984708SDavid Chisnall    }
30927a984708SDavid Chisnall    return true;
30937a984708SDavid Chisnall}
30947a984708SDavid Chisnall
30957a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
30967a984708SDavid Chisnall_InputIterator
30977a984708SDavid Chisnallmoney_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
30987a984708SDavid Chisnall                                          bool __intl, ios_base& __iob,
30997a984708SDavid Chisnall                                          ios_base::iostate& __err,
31007a984708SDavid Chisnall                                          long double& __v) const
31017a984708SDavid Chisnall{
310294e3ee44SDavid Chisnall    const int __bz = 100;
31037a984708SDavid Chisnall    char_type __wbuf[__bz];
31047a984708SDavid Chisnall    unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
31057a984708SDavid Chisnall    char_type* __wn;
31067a984708SDavid Chisnall    char_type* __we = __wbuf + __bz;
31077a984708SDavid Chisnall    locale __loc = __iob.getloc();
31087a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
31097a984708SDavid Chisnall    bool __neg = false;
31107a984708SDavid Chisnall    if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
31117a984708SDavid Chisnall                 __wb, __wn, __we))
31127a984708SDavid Chisnall    {
31137a984708SDavid Chisnall        const char __src[] = "0123456789";
31147a984708SDavid Chisnall        char_type __atoms[sizeof(__src)-1];
31157a984708SDavid Chisnall        __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
31167a984708SDavid Chisnall        char __nbuf[__bz];
31177a984708SDavid Chisnall        char* __nc = __nbuf;
31187a984708SDavid Chisnall        unique_ptr<char, void(*)(void*)> __h(0, free);
31197a984708SDavid Chisnall        if (__wn - __wb.get() > __bz-2)
31207a984708SDavid Chisnall        {
312194e3ee44SDavid Chisnall            __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
31227a984708SDavid Chisnall            if (__h.get() == 0)
31237a984708SDavid Chisnall                __throw_bad_alloc();
31247a984708SDavid Chisnall            __nc = __h.get();
31257a984708SDavid Chisnall        }
31267a984708SDavid Chisnall        if (__neg)
31277a984708SDavid Chisnall            *__nc++ = '-';
31287a984708SDavid Chisnall        for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
31291bf9f7c1SDimitry Andric            *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms];
31307a984708SDavid Chisnall        *__nc = char();
31317a984708SDavid Chisnall        if (sscanf(__nbuf, "%Lf", &__v) != 1)
31327a984708SDavid Chisnall            __throw_runtime_error("money_get error");
31337a984708SDavid Chisnall    }
31347a984708SDavid Chisnall    if (__b == __e)
31357a984708SDavid Chisnall        __err |= ios_base::eofbit;
31367a984708SDavid Chisnall    return __b;
31377a984708SDavid Chisnall}
31387a984708SDavid Chisnall
31397a984708SDavid Chisnalltemplate <class _CharT, class _InputIterator>
31407a984708SDavid Chisnall_InputIterator
31417a984708SDavid Chisnallmoney_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
31427a984708SDavid Chisnall                                          bool __intl, ios_base& __iob,
31437a984708SDavid Chisnall                                          ios_base::iostate& __err,
31447a984708SDavid Chisnall                                          string_type& __v) const
31457a984708SDavid Chisnall{
314694e3ee44SDavid Chisnall    const int __bz = 100;
31477a984708SDavid Chisnall    char_type __wbuf[__bz];
31487a984708SDavid Chisnall    unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
31497a984708SDavid Chisnall    char_type* __wn;
31507a984708SDavid Chisnall    char_type* __we = __wbuf + __bz;
31517a984708SDavid Chisnall    locale __loc = __iob.getloc();
31527a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
31537a984708SDavid Chisnall    bool __neg = false;
31547a984708SDavid Chisnall    if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
31557a984708SDavid Chisnall                 __wb, __wn, __we))
31567a984708SDavid Chisnall    {
31577a984708SDavid Chisnall        __v.clear();
31587a984708SDavid Chisnall        if (__neg)
31597a984708SDavid Chisnall            __v.push_back(__ct.widen('-'));
31607a984708SDavid Chisnall        char_type __z = __ct.widen('0');
31617a984708SDavid Chisnall        char_type* __w;
31627a984708SDavid Chisnall        for (__w = __wb.get(); __w < __wn-1; ++__w)
31637a984708SDavid Chisnall            if (*__w != __z)
31647a984708SDavid Chisnall                break;
31657a984708SDavid Chisnall        __v.append(__w, __wn);
31667a984708SDavid Chisnall    }
31677a984708SDavid Chisnall    if (__b == __e)
31687a984708SDavid Chisnall        __err |= ios_base::eofbit;
31697a984708SDavid Chisnall    return __b;
31707a984708SDavid Chisnall}
31717a984708SDavid Chisnall
3172aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>)
3173aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>)
31747a984708SDavid Chisnall
31757a984708SDavid Chisnall// money_put
31767a984708SDavid Chisnall
31777a984708SDavid Chisnalltemplate <class _CharT>
31787a984708SDavid Chisnallclass __money_put
31797a984708SDavid Chisnall{
31807a984708SDavid Chisnallprotected:
31817a984708SDavid Chisnall    typedef _CharT                  char_type;
31827a984708SDavid Chisnall    typedef basic_string<char_type> string_type;
31837a984708SDavid Chisnall
31844ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY __money_put() {}
31857a984708SDavid Chisnall
31867a984708SDavid Chisnall    static void __gather_info(bool __intl, bool __neg, const locale& __loc,
31877a984708SDavid Chisnall                              money_base::pattern& __pat, char_type& __dp,
31887a984708SDavid Chisnall                              char_type& __ts, string& __grp,
31897a984708SDavid Chisnall                              string_type& __sym, string_type& __sn,
31907a984708SDavid Chisnall                              int& __fd);
31917a984708SDavid Chisnall    static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
31927a984708SDavid Chisnall                         ios_base::fmtflags __flags,
31937a984708SDavid Chisnall                         const char_type* __db, const char_type* __de,
31947a984708SDavid Chisnall                         const ctype<char_type>& __ct, bool __neg,
31957a984708SDavid Chisnall                         const money_base::pattern& __pat, char_type __dp,
31967a984708SDavid Chisnall                         char_type __ts, const string& __grp,
31977a984708SDavid Chisnall                         const string_type& __sym, const string_type& __sn,
31987a984708SDavid Chisnall                         int __fd);
31997a984708SDavid Chisnall};
32007a984708SDavid Chisnall
32017a984708SDavid Chisnalltemplate <class _CharT>
32027a984708SDavid Chisnallvoid
32037a984708SDavid Chisnall__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
32047a984708SDavid Chisnall                                   money_base::pattern& __pat, char_type& __dp,
32057a984708SDavid Chisnall                                   char_type& __ts, string& __grp,
32067a984708SDavid Chisnall                                   string_type& __sym, string_type& __sn,
32077a984708SDavid Chisnall                                   int& __fd)
32087a984708SDavid Chisnall{
32097a984708SDavid Chisnall    if (__intl)
32107a984708SDavid Chisnall    {
32117a984708SDavid Chisnall        const moneypunct<char_type, true>& __mp =
32127a984708SDavid Chisnall            use_facet<moneypunct<char_type, true> >(__loc);
32137a984708SDavid Chisnall        if (__neg)
32147a984708SDavid Chisnall        {
32157a984708SDavid Chisnall            __pat = __mp.neg_format();
32167a984708SDavid Chisnall            __sn = __mp.negative_sign();
32177a984708SDavid Chisnall        }
32187a984708SDavid Chisnall        else
32197a984708SDavid Chisnall        {
32207a984708SDavid Chisnall            __pat = __mp.pos_format();
32217a984708SDavid Chisnall            __sn = __mp.positive_sign();
32227a984708SDavid Chisnall        }
32237a984708SDavid Chisnall        __dp = __mp.decimal_point();
32247a984708SDavid Chisnall        __ts = __mp.thousands_sep();
32257a984708SDavid Chisnall        __grp = __mp.grouping();
32267a984708SDavid Chisnall        __sym = __mp.curr_symbol();
32277a984708SDavid Chisnall        __fd = __mp.frac_digits();
32287a984708SDavid Chisnall    }
32297a984708SDavid Chisnall    else
32307a984708SDavid Chisnall    {
32317a984708SDavid Chisnall        const moneypunct<char_type, false>& __mp =
32327a984708SDavid Chisnall            use_facet<moneypunct<char_type, false> >(__loc);
32337a984708SDavid Chisnall        if (__neg)
32347a984708SDavid Chisnall        {
32357a984708SDavid Chisnall            __pat = __mp.neg_format();
32367a984708SDavid Chisnall            __sn = __mp.negative_sign();
32377a984708SDavid Chisnall        }
32387a984708SDavid Chisnall        else
32397a984708SDavid Chisnall        {
32407a984708SDavid Chisnall            __pat = __mp.pos_format();
32417a984708SDavid Chisnall            __sn = __mp.positive_sign();
32427a984708SDavid Chisnall        }
32437a984708SDavid Chisnall        __dp = __mp.decimal_point();
32447a984708SDavid Chisnall        __ts = __mp.thousands_sep();
32457a984708SDavid Chisnall        __grp = __mp.grouping();
32467a984708SDavid Chisnall        __sym = __mp.curr_symbol();
32477a984708SDavid Chisnall        __fd = __mp.frac_digits();
32487a984708SDavid Chisnall    }
32497a984708SDavid Chisnall}
32507a984708SDavid Chisnall
32517a984708SDavid Chisnalltemplate <class _CharT>
32527a984708SDavid Chisnallvoid
32537a984708SDavid Chisnall__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
32547a984708SDavid Chisnall                              ios_base::fmtflags __flags,
32557a984708SDavid Chisnall                              const char_type* __db, const char_type* __de,
32567a984708SDavid Chisnall                              const ctype<char_type>& __ct, bool __neg,
32577a984708SDavid Chisnall                              const money_base::pattern& __pat, char_type __dp,
32587a984708SDavid Chisnall                              char_type __ts, const string& __grp,
32597a984708SDavid Chisnall                              const string_type& __sym, const string_type& __sn,
32607a984708SDavid Chisnall                              int __fd)
32617a984708SDavid Chisnall{
32627a984708SDavid Chisnall    __me = __mb;
32637a984708SDavid Chisnall    for (unsigned __p = 0; __p < 4; ++__p)
32647a984708SDavid Chisnall    {
32657a984708SDavid Chisnall        switch (__pat.field[__p])
32667a984708SDavid Chisnall        {
32677a984708SDavid Chisnall        case money_base::none:
32687a984708SDavid Chisnall            __mi = __me;
32697a984708SDavid Chisnall            break;
32707a984708SDavid Chisnall        case money_base::space:
32717a984708SDavid Chisnall            __mi = __me;
32727a984708SDavid Chisnall            *__me++ = __ct.widen(' ');
32737a984708SDavid Chisnall            break;
32747a984708SDavid Chisnall        case money_base::sign:
32757a984708SDavid Chisnall            if (!__sn.empty())
32767a984708SDavid Chisnall                *__me++ = __sn[0];
32777a984708SDavid Chisnall            break;
32787a984708SDavid Chisnall        case money_base::symbol:
32797a984708SDavid Chisnall            if (!__sym.empty() && (__flags & ios_base::showbase))
32807a984708SDavid Chisnall                __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
32817a984708SDavid Chisnall            break;
32827a984708SDavid Chisnall        case money_base::value:
32837a984708SDavid Chisnall            {
32847a984708SDavid Chisnall            // remember start of value so we can reverse it
32857a984708SDavid Chisnall            char_type* __t = __me;
32867a984708SDavid Chisnall            // find beginning of digits
32877a984708SDavid Chisnall            if (__neg)
32887a984708SDavid Chisnall                ++__db;
32897a984708SDavid Chisnall            // find end of digits
32907a984708SDavid Chisnall            const char_type* __d;
32917a984708SDavid Chisnall            for (__d = __db; __d < __de; ++__d)
32927a984708SDavid Chisnall                if (!__ct.is(ctype_base::digit, *__d))
32937a984708SDavid Chisnall                    break;
32947a984708SDavid Chisnall            // print fractional part
32957a984708SDavid Chisnall            if (__fd > 0)
32967a984708SDavid Chisnall            {
32977a984708SDavid Chisnall                int __f;
32987a984708SDavid Chisnall                for (__f = __fd; __d > __db && __f > 0; --__f)
32997a984708SDavid Chisnall                    *__me++ = *--__d;
33007a984708SDavid Chisnall                char_type __z = __f > 0 ? __ct.widen('0') : char_type();
33017a984708SDavid Chisnall                for (; __f > 0; --__f)
33027a984708SDavid Chisnall                    *__me++ = __z;
33037a984708SDavid Chisnall                *__me++ = __dp;
33047a984708SDavid Chisnall            }
33057a984708SDavid Chisnall            // print units part
33067a984708SDavid Chisnall            if (__d == __db)
33077a984708SDavid Chisnall            {
33087a984708SDavid Chisnall                *__me++ = __ct.widen('0');
33097a984708SDavid Chisnall            }
33107a984708SDavid Chisnall            else
33117a984708SDavid Chisnall            {
33127a984708SDavid Chisnall                unsigned __ng = 0;
33137a984708SDavid Chisnall                unsigned __ig = 0;
33147a984708SDavid Chisnall                unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
33157a984708SDavid Chisnall                                              : static_cast<unsigned>(__grp[__ig]);
33167a984708SDavid Chisnall                while (__d != __db)
33177a984708SDavid Chisnall                {
33187a984708SDavid Chisnall                    if (__ng == __gl)
33197a984708SDavid Chisnall                    {
33207a984708SDavid Chisnall                        *__me++ = __ts;
33217a984708SDavid Chisnall                        __ng = 0;
33227a984708SDavid Chisnall                        if (++__ig < __grp.size())
33237a984708SDavid Chisnall                            __gl = __grp[__ig] == numeric_limits<char>::max() ?
33247a984708SDavid Chisnall                                        numeric_limits<unsigned>::max() :
33257a984708SDavid Chisnall                                        static_cast<unsigned>(__grp[__ig]);
33267a984708SDavid Chisnall                    }
33277a984708SDavid Chisnall                    *__me++ = *--__d;
33287a984708SDavid Chisnall                    ++__ng;
33297a984708SDavid Chisnall                }
33307a984708SDavid Chisnall            }
33317a984708SDavid Chisnall            // reverse it
33327a984708SDavid Chisnall            reverse(__t, __me);
33337a984708SDavid Chisnall            }
33347a984708SDavid Chisnall            break;
33357a984708SDavid Chisnall        }
33367a984708SDavid Chisnall    }
33377a984708SDavid Chisnall    // print rest of sign, if any
33387a984708SDavid Chisnall    if (__sn.size() > 1)
33397a984708SDavid Chisnall        __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
33407a984708SDavid Chisnall    // set alignment
33417a984708SDavid Chisnall    if ((__flags & ios_base::adjustfield) == ios_base::left)
33427a984708SDavid Chisnall        __mi = __me;
33437a984708SDavid Chisnall    else if ((__flags & ios_base::adjustfield) != ios_base::internal)
33447a984708SDavid Chisnall        __mi = __mb;
33457a984708SDavid Chisnall}
33467a984708SDavid Chisnall
3347aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>)
3348aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>)
33497a984708SDavid Chisnall
33507a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
3351aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS money_put
33527a984708SDavid Chisnall    : public locale::facet,
33537a984708SDavid Chisnall      private __money_put<_CharT>
33547a984708SDavid Chisnall{
33557a984708SDavid Chisnallpublic:
33567a984708SDavid Chisnall    typedef _CharT                  char_type;
33577a984708SDavid Chisnall    typedef _OutputIterator         iter_type;
33587a984708SDavid Chisnall    typedef basic_string<char_type> string_type;
33597a984708SDavid Chisnall
33604ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
33617a984708SDavid Chisnall    explicit money_put(size_t __refs = 0)
33627a984708SDavid Chisnall        : locale::facet(__refs) {}
33637a984708SDavid Chisnall
33644ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
33657a984708SDavid Chisnall    iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
33667a984708SDavid Chisnall                  long double __units) const
33677a984708SDavid Chisnall    {
33687a984708SDavid Chisnall        return do_put(__s, __intl, __iob, __fl, __units);
33697a984708SDavid Chisnall    }
33707a984708SDavid Chisnall
33714ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
33727a984708SDavid Chisnall    iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
33737a984708SDavid Chisnall                  const string_type& __digits) const
33747a984708SDavid Chisnall    {
33757a984708SDavid Chisnall        return do_put(__s, __intl, __iob, __fl, __digits);
33767a984708SDavid Chisnall    }
33777a984708SDavid Chisnall
33787a984708SDavid Chisnall    static locale::id id;
33797a984708SDavid Chisnall
33807a984708SDavid Chisnallprotected:
33814ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
33827a984708SDavid Chisnall    ~money_put() {}
33837a984708SDavid Chisnall
33847a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
33857a984708SDavid Chisnall                             char_type __fl, long double __units) const;
33867a984708SDavid Chisnall    virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
33877a984708SDavid Chisnall                             char_type __fl, const string_type& __digits) const;
33887a984708SDavid Chisnall};
33897a984708SDavid Chisnall
33907a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
33917a984708SDavid Chisnalllocale::id
33927a984708SDavid Chisnallmoney_put<_CharT, _OutputIterator>::id;
33937a984708SDavid Chisnall
33947a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
33957a984708SDavid Chisnall_OutputIterator
33967a984708SDavid Chisnallmoney_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
33977a984708SDavid Chisnall                                           ios_base& __iob, char_type __fl,
33987a984708SDavid Chisnall                                           long double __units) const
33997a984708SDavid Chisnall{
34007a984708SDavid Chisnall    // convert to char
34017a984708SDavid Chisnall    const size_t __bs = 100;
34027a984708SDavid Chisnall    char __buf[__bs];
34037a984708SDavid Chisnall    char* __bb = __buf;
34047a984708SDavid Chisnall    char_type __digits[__bs];
34057a984708SDavid Chisnall    char_type* __db = __digits;
340694e3ee44SDavid Chisnall    size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
34077a984708SDavid Chisnall    unique_ptr<char, void(*)(void*)> __hn(0, free);
34087a984708SDavid Chisnall    unique_ptr<char_type, void(*)(void*)> __hd(0, free);
34097a984708SDavid Chisnall    // secure memory for digit storage
34107a984708SDavid Chisnall    if (__n > __bs-1)
34117a984708SDavid Chisnall    {
34127c82a1ecSDimitry Andric        __n = static_cast<size_t>(__libcpp_asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
34137a984708SDavid Chisnall        if (__bb == 0)
34147a984708SDavid Chisnall            __throw_bad_alloc();
34157a984708SDavid Chisnall        __hn.reset(__bb);
34167a984708SDavid Chisnall        __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
341794e3ee44SDavid Chisnall        if (__hd == nullptr)
34187a984708SDavid Chisnall            __throw_bad_alloc();
34197a984708SDavid Chisnall        __db = __hd.get();
34207a984708SDavid Chisnall    }
34217a984708SDavid Chisnall    // gather info
34227a984708SDavid Chisnall    locale __loc = __iob.getloc();
34237a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
34247a984708SDavid Chisnall    __ct.widen(__bb, __bb + __n, __db);
34257a984708SDavid Chisnall    bool __neg = __n > 0 && __bb[0] == '-';
34267a984708SDavid Chisnall    money_base::pattern __pat;
34277a984708SDavid Chisnall    char_type __dp;
34287a984708SDavid Chisnall    char_type __ts;
34297a984708SDavid Chisnall    string __grp;
34307a984708SDavid Chisnall    string_type __sym;
34317a984708SDavid Chisnall    string_type __sn;
34327a984708SDavid Chisnall    int __fd;
34337a984708SDavid Chisnall    this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
34347a984708SDavid Chisnall    // secure memory for formatting
34357a984708SDavid Chisnall    char_type __mbuf[__bs];
34367a984708SDavid Chisnall    char_type* __mb = __mbuf;
34377a984708SDavid Chisnall    unique_ptr<char_type, void(*)(void*)> __hw(0, free);
34387a984708SDavid Chisnall    size_t __exn = static_cast<int>(__n) > __fd ?
343994e3ee44SDavid Chisnall                   (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
344094e3ee44SDavid Chisnall                    __sym.size() + static_cast<size_t>(__fd) + 1
344194e3ee44SDavid Chisnall                 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
34427a984708SDavid Chisnall    if (__exn > __bs)
34437a984708SDavid Chisnall    {
34447a984708SDavid Chisnall        __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
34457a984708SDavid Chisnall        __mb = __hw.get();
34467a984708SDavid Chisnall        if (__mb == 0)
34477a984708SDavid Chisnall            __throw_bad_alloc();
34487a984708SDavid Chisnall    }
34497a984708SDavid Chisnall    // format
34507a984708SDavid Chisnall    char_type* __mi;
34517a984708SDavid Chisnall    char_type* __me;
34527a984708SDavid Chisnall    this->__format(__mb, __mi, __me, __iob.flags(),
34537a984708SDavid Chisnall                   __db, __db + __n, __ct,
34547a984708SDavid Chisnall                   __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
34557a984708SDavid Chisnall    return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
34567a984708SDavid Chisnall}
34577a984708SDavid Chisnall
34587a984708SDavid Chisnalltemplate <class _CharT, class _OutputIterator>
34597a984708SDavid Chisnall_OutputIterator
34607a984708SDavid Chisnallmoney_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
34617a984708SDavid Chisnall                                           ios_base& __iob, char_type __fl,
34627a984708SDavid Chisnall                                           const string_type& __digits) const
34637a984708SDavid Chisnall{
34647a984708SDavid Chisnall    // gather info
34657a984708SDavid Chisnall    locale __loc = __iob.getloc();
34667a984708SDavid Chisnall    const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
34677a984708SDavid Chisnall    bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
34687a984708SDavid Chisnall    money_base::pattern __pat;
34697a984708SDavid Chisnall    char_type __dp;
34707a984708SDavid Chisnall    char_type __ts;
34717a984708SDavid Chisnall    string __grp;
34727a984708SDavid Chisnall    string_type __sym;
34737a984708SDavid Chisnall    string_type __sn;
34747a984708SDavid Chisnall    int __fd;
34757a984708SDavid Chisnall    this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
34767a984708SDavid Chisnall    // secure memory for formatting
34777a984708SDavid Chisnall    char_type __mbuf[100];
34787a984708SDavid Chisnall    char_type* __mb = __mbuf;
34797a984708SDavid Chisnall    unique_ptr<char_type, void(*)(void*)> __h(0, free);
348094e3ee44SDavid Chisnall    size_t __exn = static_cast<int>(__digits.size()) > __fd ?
348194e3ee44SDavid Chisnall                   (__digits.size() - static_cast<size_t>(__fd)) * 2 +
348294e3ee44SDavid Chisnall                    __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
348394e3ee44SDavid Chisnall                 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
34847a984708SDavid Chisnall    if (__exn > 100)
34857a984708SDavid Chisnall    {
34867a984708SDavid Chisnall        __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
34877a984708SDavid Chisnall        __mb = __h.get();
34887a984708SDavid Chisnall        if (__mb == 0)
34897a984708SDavid Chisnall            __throw_bad_alloc();
34907a984708SDavid Chisnall    }
34917a984708SDavid Chisnall    // format
34927a984708SDavid Chisnall    char_type* __mi;
34937a984708SDavid Chisnall    char_type* __me;
34947a984708SDavid Chisnall    this->__format(__mb, __mi, __me, __iob.flags(),
34957a984708SDavid Chisnall                   __digits.data(), __digits.data() + __digits.size(), __ct,
34967a984708SDavid Chisnall                   __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
34977a984708SDavid Chisnall    return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
34987a984708SDavid Chisnall}
34997a984708SDavid Chisnall
3500aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>)
3501aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>)
35027a984708SDavid Chisnall
35037a984708SDavid Chisnall// messages
35047a984708SDavid Chisnall
35051bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS messages_base
35067a984708SDavid Chisnall{
35077a984708SDavid Chisnallpublic:
35087a984708SDavid Chisnall    typedef ptrdiff_t catalog;
35097a984708SDavid Chisnall
35104ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY messages_base() {}
35117a984708SDavid Chisnall};
35127a984708SDavid Chisnall
35137a984708SDavid Chisnalltemplate <class _CharT>
3514aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS messages
35157a984708SDavid Chisnall    : public locale::facet,
35167a984708SDavid Chisnall      public messages_base
35177a984708SDavid Chisnall{
35187a984708SDavid Chisnallpublic:
35197a984708SDavid Chisnall    typedef _CharT               char_type;
35207a984708SDavid Chisnall    typedef basic_string<_CharT> string_type;
35217a984708SDavid Chisnall
35224ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
35237a984708SDavid Chisnall    explicit messages(size_t __refs = 0)
35247a984708SDavid Chisnall        : locale::facet(__refs) {}
35257a984708SDavid Chisnall
35264ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
35277a984708SDavid Chisnall    catalog open(const basic_string<char>& __nm, const locale& __loc) const
35287a984708SDavid Chisnall    {
35297a984708SDavid Chisnall        return do_open(__nm, __loc);
35307a984708SDavid Chisnall    }
35317a984708SDavid Chisnall
35324ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
35337a984708SDavid Chisnall    string_type get(catalog __c, int __set, int __msgid,
35347a984708SDavid Chisnall                    const string_type& __dflt) const
35357a984708SDavid Chisnall    {
35367a984708SDavid Chisnall        return do_get(__c, __set, __msgid, __dflt);
35377a984708SDavid Chisnall    }
35387a984708SDavid Chisnall
35394ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
35407a984708SDavid Chisnall    void close(catalog __c) const
35417a984708SDavid Chisnall    {
35427a984708SDavid Chisnall        do_close(__c);
35437a984708SDavid Chisnall    }
35447a984708SDavid Chisnall
35457a984708SDavid Chisnall    static locale::id id;
35467a984708SDavid Chisnall
35477a984708SDavid Chisnallprotected:
35484ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
35497a984708SDavid Chisnall    ~messages() {}
35507a984708SDavid Chisnall
35517a984708SDavid Chisnall    virtual catalog do_open(const basic_string<char>&, const locale&) const;
35527a984708SDavid Chisnall    virtual string_type do_get(catalog, int __set, int __msgid,
35537a984708SDavid Chisnall                               const string_type& __dflt) const;
35547a984708SDavid Chisnall    virtual void do_close(catalog) const;
35557a984708SDavid Chisnall};
35567a984708SDavid Chisnall
35577a984708SDavid Chisnalltemplate <class _CharT>
35587a984708SDavid Chisnalllocale::id
35597a984708SDavid Chisnallmessages<_CharT>::id;
35607a984708SDavid Chisnall
35617a984708SDavid Chisnalltemplate <class _CharT>
35627a984708SDavid Chisnalltypename messages<_CharT>::catalog
35637a984708SDavid Chisnallmessages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
35647a984708SDavid Chisnall{
3565854fa44bSDimitry Andric#ifdef _LIBCPP_HAS_CATOPEN
35667a984708SDavid Chisnall    catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
35677a984708SDavid Chisnall    if (__cat != -1)
35687a984708SDavid Chisnall        __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
35697a984708SDavid Chisnall    return __cat;
3570854fa44bSDimitry Andric#else // !_LIBCPP_HAS_CATOPEN
3571*b5893f02SDimitry Andric    _LIBCPP_UNUSED_VAR(__nm);
3572854fa44bSDimitry Andric    return -1;
3573854fa44bSDimitry Andric#endif // _LIBCPP_HAS_CATOPEN
35747a984708SDavid Chisnall}
35757a984708SDavid Chisnall
35767a984708SDavid Chisnalltemplate <class _CharT>
35777a984708SDavid Chisnalltypename messages<_CharT>::string_type
35787a984708SDavid Chisnallmessages<_CharT>::do_get(catalog __c, int __set, int __msgid,
35797a984708SDavid Chisnall                         const string_type& __dflt) const
35807a984708SDavid Chisnall{
3581854fa44bSDimitry Andric#ifdef _LIBCPP_HAS_CATOPEN
35827a984708SDavid Chisnall    string __ndflt;
35837a984708SDavid Chisnall    __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
35847a984708SDavid Chisnall                                                       __dflt.c_str(),
35857a984708SDavid Chisnall                                                       __dflt.c_str() + __dflt.size());
35867a984708SDavid Chisnall    if (__c != -1)
35877a984708SDavid Chisnall        __c <<= 1;
35887a984708SDavid Chisnall    nl_catd __cat = (nl_catd)__c;
35897a984708SDavid Chisnall    char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
35907a984708SDavid Chisnall    string_type __w;
35917a984708SDavid Chisnall    __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
35927a984708SDavid Chisnall                                                        __n, __n + strlen(__n));
35937a984708SDavid Chisnall    return __w;
3594854fa44bSDimitry Andric#else // !_LIBCPP_HAS_CATOPEN
3595*b5893f02SDimitry Andric    _LIBCPP_UNUSED_VAR(__c);
3596*b5893f02SDimitry Andric    _LIBCPP_UNUSED_VAR(__set);
3597*b5893f02SDimitry Andric    _LIBCPP_UNUSED_VAR(__msgid);
3598854fa44bSDimitry Andric    return __dflt;
3599854fa44bSDimitry Andric#endif // _LIBCPP_HAS_CATOPEN
36007a984708SDavid Chisnall}
36017a984708SDavid Chisnall
36027a984708SDavid Chisnalltemplate <class _CharT>
36037a984708SDavid Chisnallvoid
36047a984708SDavid Chisnallmessages<_CharT>::do_close(catalog __c) const
36057a984708SDavid Chisnall{
3606854fa44bSDimitry Andric#ifdef _LIBCPP_HAS_CATOPEN
36077a984708SDavid Chisnall    if (__c != -1)
36087a984708SDavid Chisnall        __c <<= 1;
36097a984708SDavid Chisnall    nl_catd __cat = (nl_catd)__c;
36107a984708SDavid Chisnall    catclose(__cat);
3611*b5893f02SDimitry Andric#else // !_LIBCPP_HAS_CATOPEN
3612*b5893f02SDimitry Andric    _LIBCPP_UNUSED_VAR(__c);
3613854fa44bSDimitry Andric#endif // _LIBCPP_HAS_CATOPEN
36147a984708SDavid Chisnall}
36157a984708SDavid Chisnall
3616aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<char>)
3617aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<wchar_t>)
36187a984708SDavid Chisnall
36197a984708SDavid Chisnalltemplate <class _CharT>
3620aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS messages_byname
36217a984708SDavid Chisnall    : public messages<_CharT>
36227a984708SDavid Chisnall{
36237a984708SDavid Chisnallpublic:
36247a984708SDavid Chisnall    typedef messages_base::catalog catalog;
36257a984708SDavid Chisnall    typedef basic_string<_CharT> string_type;
36267a984708SDavid Chisnall
36274ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36287a984708SDavid Chisnall    explicit messages_byname(const char*, size_t __refs = 0)
36297a984708SDavid Chisnall        : messages<_CharT>(__refs) {}
36307a984708SDavid Chisnall
36314ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36327a984708SDavid Chisnall    explicit messages_byname(const string&, size_t __refs = 0)
36337a984708SDavid Chisnall        : messages<_CharT>(__refs) {}
36347a984708SDavid Chisnall
36357a984708SDavid Chisnallprotected:
36364ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36377a984708SDavid Chisnall    ~messages_byname() {}
36387a984708SDavid Chisnall};
36397a984708SDavid Chisnall
3640aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>)
3641aed8d94eSDimitry Andric_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<wchar_t>)
36427a984708SDavid Chisnall
36437a984708SDavid Chisnalltemplate<class _Codecvt, class _Elem = wchar_t,
36447a984708SDavid Chisnall         class _Wide_alloc = allocator<_Elem>,
36457a984708SDavid Chisnall         class _Byte_alloc = allocator<char> >
3646aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS wstring_convert
36477a984708SDavid Chisnall{
36487a984708SDavid Chisnallpublic:
36497a984708SDavid Chisnall    typedef basic_string<char, char_traits<char>, _Byte_alloc>   byte_string;
36507a984708SDavid Chisnall    typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
36517a984708SDavid Chisnall    typedef typename _Codecvt::state_type                        state_type;
36527a984708SDavid Chisnall    typedef typename wide_string::traits_type::int_type          int_type;
36537a984708SDavid Chisnall
36547a984708SDavid Chisnallprivate:
36557a984708SDavid Chisnall    byte_string __byte_err_string_;
36567a984708SDavid Chisnall    wide_string __wide_err_string_;
36577a984708SDavid Chisnall    _Codecvt* __cvtptr_;
36587a984708SDavid Chisnall    state_type __cvtstate_;
36597a984708SDavid Chisnall    size_t __cvtcount_;
36607a984708SDavid Chisnall
36617a984708SDavid Chisnall    wstring_convert(const wstring_convert& __wc);
36627a984708SDavid Chisnall    wstring_convert& operator=(const wstring_convert& __wc);
36637a984708SDavid Chisnallpublic:
36644ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36654f7ab58eSDimitry Andric    _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
36664ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36677a984708SDavid Chisnall    wstring_convert(_Codecvt* __pcvt, state_type __state);
36684f7ab58eSDimitry Andric    _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err,
36697a984708SDavid Chisnall                    const wide_string& __wide_err = wide_string());
3670540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
36714ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36727a984708SDavid Chisnall    wstring_convert(wstring_convert&& __wc);
36737a984708SDavid Chisnall#endif
36747a984708SDavid Chisnall    ~wstring_convert();
36757a984708SDavid Chisnall
36764ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36777a984708SDavid Chisnall    wide_string from_bytes(char __byte)
36787a984708SDavid Chisnall        {return from_bytes(&__byte, &__byte+1);}
36794ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36807a984708SDavid Chisnall    wide_string from_bytes(const char* __ptr)
36817a984708SDavid Chisnall        {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
36824ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36837a984708SDavid Chisnall    wide_string from_bytes(const byte_string& __str)
36847a984708SDavid Chisnall        {return from_bytes(__str.data(), __str.data() + __str.size());}
36857a984708SDavid Chisnall    wide_string from_bytes(const char* __first, const char* __last);
36867a984708SDavid Chisnall
36874ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36887a984708SDavid Chisnall    byte_string to_bytes(_Elem __wchar)
36897a984708SDavid Chisnall        {return to_bytes(&__wchar, &__wchar+1);}
36904ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36917a984708SDavid Chisnall    byte_string to_bytes(const _Elem* __wptr)
36927a984708SDavid Chisnall        {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
36934ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36947a984708SDavid Chisnall    byte_string to_bytes(const wide_string& __wstr)
36957a984708SDavid Chisnall        {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
36967a984708SDavid Chisnall    byte_string to_bytes(const _Elem* __first, const _Elem* __last);
36977a984708SDavid Chisnall
36984ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
36994f7ab58eSDimitry Andric    size_t converted() const _NOEXCEPT {return __cvtcount_;}
37004ba319b5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
37017a984708SDavid Chisnall    state_type state() const {return __cvtstate_;}
37027a984708SDavid Chisnall};
37037a984708SDavid Chisnall
37047a984708SDavid Chisnalltemplate<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
37059729cf09SDimitry Andricinline
37067a984708SDavid Chisnallwstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
37077a984708SDavid Chisnall    wstring_convert(_Codecvt* __pcvt)
37087a984708SDavid Chisnall        : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
37097a984708SDavid Chisnall{
37107a984708SDavid Chisnall}
37117a984708SDavid Chisnall
37127a984708SDavid Chisnalltemplate<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
37139729cf09SDimitry Andricinline
37147a984708SDavid Chisnallwstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
37157a984708SDavid Chisnall    wstring_convert(_Codecvt* __pcvt, state_type __state)
37167a984708SDavid Chisnall        : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
37177a984708SDavid Chisnall{
37187a984708SDavid Chisnall}
37197a984708SDavid Chisnall
37207a984708SDavid Chisnalltemplate<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
37217a984708SDavid Chisnallwstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
37227a984708SDavid Chisnall    wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
37237a984708SDavid Chisnall        : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
37247a984708SDavid Chisnall          __cvtstate_(), __cvtcount_(0)
37257a984708SDavid Chisnall{
37267a984708SDavid Chisnall    __cvtptr_ = new _Codecvt;
37277a984708SDavid Chisnall}
37287a984708SDavid Chisnall
3729540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
37307a984708SDavid Chisnall
37317a984708SDavid Chisnalltemplate<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
37329729cf09SDimitry Andricinline
37337a984708SDavid Chisnallwstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
37347a984708SDavid Chisnall    wstring_convert(wstring_convert&& __wc)
37357a984708SDavid Chisnall        : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
37367a984708SDavid Chisnall          __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
37377a984708SDavid Chisnall          __cvtptr_(__wc.__cvtptr_),
37387c82a1ecSDimitry Andric          __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtcount_)
37397a984708SDavid Chisnall{
37407a984708SDavid Chisnall    __wc.__cvtptr_ = nullptr;
37417a984708SDavid Chisnall}
37427a984708SDavid Chisnall
3743540d2a8bSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
37447a984708SDavid Chisnall
37457a984708SDavid Chisnalltemplate<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
37467a984708SDavid Chisnallwstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
37477a984708SDavid Chisnall{
37487a984708SDavid Chisnall    delete __cvtptr_;
37497a984708SDavid Chisnall}
37507a984708SDavid Chisnall
37517a984708SDavid Chisnalltemplate<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
37527a984708SDavid Chisnalltypename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
37537a984708SDavid Chisnallwstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
37547a984708SDavid Chisnall    from_bytes(const char* __frm, const char* __frm_end)
37557a984708SDavid Chisnall{
37567a984708SDavid Chisnall    __cvtcount_ = 0;
37577a984708SDavid Chisnall    if (__cvtptr_ != nullptr)
37587a984708SDavid Chisnall    {
37597a984708SDavid Chisnall        wide_string __ws(2*(__frm_end - __frm), _Elem());
3760936e9439SDimitry Andric        if (__frm != __frm_end)
37617a984708SDavid Chisnall            __ws.resize(__ws.capacity());
37627a984708SDavid Chisnall        codecvt_base::result __r = codecvt_base::ok;
37637a984708SDavid Chisnall        state_type __st = __cvtstate_;
37647a984708SDavid Chisnall        if (__frm != __frm_end)
37657a984708SDavid Chisnall        {
37667a984708SDavid Chisnall            _Elem* __to = &__ws[0];
37677a984708SDavid Chisnall            _Elem* __to_end = __to + __ws.size();
37687a984708SDavid Chisnall            const char* __frm_nxt;
37697a984708SDavid Chisnall            do
37707a984708SDavid Chisnall            {
37717a984708SDavid Chisnall                _Elem* __to_nxt;
37727a984708SDavid Chisnall                __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
37737a984708SDavid Chisnall                                          __to, __to_end, __to_nxt);
37747a984708SDavid Chisnall                __cvtcount_ += __frm_nxt - __frm;
37757a984708SDavid Chisnall                if (__frm_nxt == __frm)
37767a984708SDavid Chisnall                {
37777a984708SDavid Chisnall                    __r = codecvt_base::error;
37787a984708SDavid Chisnall                }
37797a984708SDavid Chisnall                else if (__r == codecvt_base::noconv)
37807a984708SDavid Chisnall                {
37817a984708SDavid Chisnall                    __ws.resize(__to - &__ws[0]);
37827a984708SDavid Chisnall                    // This only gets executed if _Elem is char
37837a984708SDavid Chisnall                    __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
37847a984708SDavid Chisnall                    __frm = __frm_nxt;
37857a984708SDavid Chisnall                    __r = codecvt_base::ok;
37867a984708SDavid Chisnall                }
37877a984708SDavid Chisnall                else if (__r == codecvt_base::ok)
37887a984708SDavid Chisnall                {
37897a984708SDavid Chisnall                    __ws.resize(__to_nxt - &__ws[0]);
37907a984708SDavid Chisnall                    __frm = __frm_nxt;
37917a984708SDavid Chisnall                }
37927a984708SDavid Chisnall                else if (__r == codecvt_base::partial)
37937a984708SDavid Chisnall                {
37947a984708SDavid Chisnall                    ptrdiff_t __s = __to_nxt - &__ws[0];
37957a984708SDavid Chisnall                    __ws.resize(2 * __s);
37967a984708SDavid Chisnall                    __to = &__ws[0] + __s;
37977a984708SDavid Chisnall                    __to_end = &__ws[0] + __ws.size();
37987a984708SDavid Chisnall                    __frm = __frm_nxt;
37997a984708SDavid Chisnall                }
38007a984708SDavid Chisnall            } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
38017a984708SDavid Chisnall        }
38027a984708SDavid Chisnall        if (__r == codecvt_base::ok)
38037a984708SDavid Chisnall            return __ws;
38047a984708SDavid Chisnall    }
3805aed8d94eSDimitry Andric
38067a984708SDavid Chisnall    if (__wide_err_string_.empty())
3807aed8d94eSDimitry Andric        __throw_range_error("wstring_convert: from_bytes error");
3808aed8d94eSDimitry Andric
38097a984708SDavid Chisnall    return __wide_err_string_;
38107a984708SDavid Chisnall}
38117a984708SDavid Chisnall
38127a984708SDavid Chisnalltemplate<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
38137a984708SDavid Chisnalltypename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
38147a984708SDavid Chisnallwstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
38157a984708SDavid Chisnall    to_bytes(const _Elem* __frm, const _Elem* __frm_end)
38167a984708SDavid Chisnall{
38177a984708SDavid Chisnall    __cvtcount_ = 0;
38187a984708SDavid Chisnall    if (__cvtptr_ != nullptr)
38197a984708SDavid Chisnall    {
38207a984708SDavid Chisnall        byte_string __bs(2*(__frm_end - __frm), char());
3821936e9439SDimitry Andric        if (__frm != __frm_end)
38227a984708SDavid Chisnall            __bs.resize(__bs.capacity());
38237a984708SDavid Chisnall        codecvt_base::result __r = codecvt_base::ok;
38247a984708SDavid Chisnall        state_type __st = __cvtstate_;
38257a984708SDavid Chisnall        if (__frm != __frm_end)
38267a984708SDavid Chisnall        {
38277a984708SDavid Chisnall            char* __to = &__bs[0];
38287a984708SDavid Chisnall            char* __to_end = __to + __bs.size();
38297a984708SDavid Chisnall            const _Elem* __frm_nxt;
38307a984708SDavid Chisnall            do
38317a984708SDavid Chisnall            {
38327a984708SDavid Chisnall                char* __to_nxt;
38337a984708SDavid Chisnall                __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
38347a984708SDavid Chisnall                                           __to, __to_end, __to_nxt);
38357a984708SDavid Chisnall                __cvtcount_ += __frm_nxt - __frm;
38367a984708SDavid Chisnall                if (__frm_nxt == __frm)
38377a984708SDavid Chisnall                {
38387a984708SDavid Chisnall                    __r = codecvt_base::error;
38397a984708SDavid Chisnall                }
38407a984708SDavid Chisnall                else if (__r == codecvt_base::noconv)
38417a984708SDavid Chisnall                {
38427a984708SDavid Chisnall                    __bs.resize(__to - &__bs[0]);
38437a984708SDavid Chisnall                    // This only gets executed if _Elem is char
38447a984708SDavid Chisnall                    __bs.append((const char*)__frm, (const char*)__frm_end);
38457a984708SDavid Chisnall                    __frm = __frm_nxt;
38467a984708SDavid Chisnall                    __r = codecvt_base::ok;
38477a984708SDavid Chisnall                }
38487a984708SDavid Chisnall                else if (__r == codecvt_base::ok)
38497a984708SDavid Chisnall                {
38507a984708SDavid Chisnall                    __bs.resize(__to_nxt - &__bs[0]);
38517a984708SDavid Chisnall                    __frm = __frm_nxt;
38527a984708SDavid Chisnall                }
38537a984708SDavid Chisnall                else if (__r == codecvt_base::partial)
38547a984708SDavid Chisnall                {
38557a984708SDavid Chisnall                    ptrdiff_t __s = __to_nxt - &__bs[0];
38567a984708SDavid Chisnall                    __bs.resize(2 * __s);
38577a984708SDavid Chisnall                    __to = &__bs[0] + __s;
38587a984708SDavid Chisnall                    __to_end = &__bs[0] + __bs.size();
38597a984708SDavid Chisnall                    __frm = __frm_nxt;
38607a984708SDavid Chisnall                }
38617a984708SDavid Chisnall            } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
38627a984708SDavid Chisnall        }
38637a984708SDavid Chisnall        if (__r == codecvt_base::ok)
38647a984708SDavid Chisnall        {
38657a984708SDavid Chisnall            size_t __s = __bs.size();
38667a984708SDavid Chisnall            __bs.resize(__bs.capacity());
38677a984708SDavid Chisnall            char* __to = &__bs[0] + __s;
38687a984708SDavid Chisnall            char* __to_end = __to + __bs.size();
38697a984708SDavid Chisnall            do
38707a984708SDavid Chisnall            {
38717a984708SDavid Chisnall                char* __to_nxt;
38727a984708SDavid Chisnall                __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
38737a984708SDavid Chisnall                if (__r == codecvt_base::noconv)
38747a984708SDavid Chisnall                {
38757a984708SDavid Chisnall                    __bs.resize(__to - &__bs[0]);
38767a984708SDavid Chisnall                    __r = codecvt_base::ok;
38777a984708SDavid Chisnall                }
38787a984708SDavid Chisnall                else if (__r == codecvt_base::ok)
38797a984708SDavid Chisnall                {
38807a984708SDavid Chisnall                    __bs.resize(__to_nxt - &__bs[0]);
38817a984708SDavid Chisnall                }
38827a984708SDavid Chisnall                else if (__r == codecvt_base::partial)
38837a984708SDavid Chisnall                {
388494e3ee44SDavid Chisnall                    ptrdiff_t __sp = __to_nxt - &__bs[0];
388594e3ee44SDavid Chisnall                    __bs.resize(2 * __sp);
388694e3ee44SDavid Chisnall                    __to = &__bs[0] + __sp;
38877a984708SDavid Chisnall                    __to_end = &__bs[0] + __bs.size();
38887a984708SDavid Chisnall                }
38897a984708SDavid Chisnall            } while (__r == codecvt_base::partial);
38907a984708SDavid Chisnall            if (__r == codecvt_base::ok)
38917a984708SDavid Chisnall                return __bs;
38927a984708SDavid Chisnall        }
38937a984708SDavid Chisnall    }
3894aed8d94eSDimitry Andric
38957a984708SDavid Chisnall    if (__byte_err_string_.empty())
3896aed8d94eSDimitry Andric        __throw_range_error("wstring_convert: to_bytes error");
3897aed8d94eSDimitry Andric
38987a984708SDavid Chisnall    return __byte_err_string_;
38997a984708SDavid Chisnall}
39007a984708SDavid Chisnall
39017a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
3902aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS wbuffer_convert
39037a984708SDavid Chisnall    : public basic_streambuf<_Elem, _Tr>
39047a984708SDavid Chisnall{
39057a984708SDavid Chisnallpublic:
39067a984708SDavid Chisnall    // types:
39077a984708SDavid Chisnall    typedef _Elem                          char_type;
39087a984708SDavid Chisnall    typedef _Tr                            traits_type;
39097a984708SDavid Chisnall    typedef typename traits_type::int_type int_type;
39107a984708SDavid Chisnall    typedef typename traits_type::pos_type pos_type;
39117a984708SDavid Chisnall    typedef typename traits_type::off_type off_type;
39127a984708SDavid Chisnall    typedef typename _Codecvt::state_type  state_type;
39137a984708SDavid Chisnall
39147a984708SDavid Chisnallprivate:
39157a984708SDavid Chisnall    char*       __extbuf_;
39167a984708SDavid Chisnall    const char* __extbufnext_;
39177a984708SDavid Chisnall    const char* __extbufend_;
39187a984708SDavid Chisnall    char __extbuf_min_[8];
39197a984708SDavid Chisnall    size_t __ebs_;
39207a984708SDavid Chisnall    char_type* __intbuf_;
39217a984708SDavid Chisnall    size_t __ibs_;
39227a984708SDavid Chisnall    streambuf* __bufptr_;
39237a984708SDavid Chisnall    _Codecvt* __cv_;
39247a984708SDavid Chisnall    state_type __st_;
39257a984708SDavid Chisnall    ios_base::openmode __cm_;
39267a984708SDavid Chisnall    bool __owns_eb_;
39277a984708SDavid Chisnall    bool __owns_ib_;
39287a984708SDavid Chisnall    bool __always_noconv_;
39297a984708SDavid Chisnall
39307a984708SDavid Chisnall    wbuffer_convert(const wbuffer_convert&);
39317a984708SDavid Chisnall    wbuffer_convert& operator=(const wbuffer_convert&);
39327a984708SDavid Chisnallpublic:
39334f7ab58eSDimitry Andric    _LIBCPP_EXPLICIT_AFTER_CXX11 wbuffer_convert(streambuf* __bytebuf = 0,
39344f7ab58eSDimitry Andric            _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type());
39357a984708SDavid Chisnall    ~wbuffer_convert();
39367a984708SDavid Chisnall
39377a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
39387a984708SDavid Chisnall    streambuf* rdbuf() const {return __bufptr_;}
39397a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
39407a984708SDavid Chisnall    streambuf* rdbuf(streambuf* __bytebuf)
39417a984708SDavid Chisnall    {
39427a984708SDavid Chisnall        streambuf* __r = __bufptr_;
39437a984708SDavid Chisnall        __bufptr_ = __bytebuf;
39447a984708SDavid Chisnall        return __r;
39457a984708SDavid Chisnall    }
39467a984708SDavid Chisnall
39477a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
39487a984708SDavid Chisnall    state_type state() const {return __st_;}
39497a984708SDavid Chisnall
39507a984708SDavid Chisnallprotected:
39517a984708SDavid Chisnall    virtual int_type underflow();
39527a984708SDavid Chisnall    virtual int_type pbackfail(int_type __c = traits_type::eof());
39537a984708SDavid Chisnall    virtual int_type overflow (int_type __c = traits_type::eof());
39547a984708SDavid Chisnall    virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
39557a984708SDavid Chisnall                                                            streamsize __n);
39567a984708SDavid Chisnall    virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
39577a984708SDavid Chisnall                             ios_base::openmode __wch = ios_base::in | ios_base::out);
39587a984708SDavid Chisnall    virtual pos_type seekpos(pos_type __sp,
39597a984708SDavid Chisnall                             ios_base::openmode __wch = ios_base::in | ios_base::out);
39607a984708SDavid Chisnall    virtual int sync();
39617a984708SDavid Chisnall
39627a984708SDavid Chisnallprivate:
39637a984708SDavid Chisnall    bool __read_mode();
39647a984708SDavid Chisnall    void __write_mode();
39657a984708SDavid Chisnall    wbuffer_convert* __close();
39667a984708SDavid Chisnall};
39677a984708SDavid Chisnall
39687a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
39697a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::
39707a984708SDavid Chisnall    wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
39717a984708SDavid Chisnall    : __extbuf_(0),
39727a984708SDavid Chisnall      __extbufnext_(0),
39737a984708SDavid Chisnall      __extbufend_(0),
39747a984708SDavid Chisnall      __ebs_(0),
39757a984708SDavid Chisnall      __intbuf_(0),
39767a984708SDavid Chisnall      __ibs_(0),
39777a984708SDavid Chisnall      __bufptr_(__bytebuf),
39787a984708SDavid Chisnall      __cv_(__pcvt),
39797a984708SDavid Chisnall      __st_(__state),
39807a984708SDavid Chisnall      __cm_(0),
39817a984708SDavid Chisnall      __owns_eb_(false),
39827a984708SDavid Chisnall      __owns_ib_(false),
39837a984708SDavid Chisnall      __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
39847a984708SDavid Chisnall{
39857a984708SDavid Chisnall    setbuf(0, 4096);
39867a984708SDavid Chisnall}
39877a984708SDavid Chisnall
39887a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
39897a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
39907a984708SDavid Chisnall{
39917a984708SDavid Chisnall    __close();
39927a984708SDavid Chisnall    delete __cv_;
39937a984708SDavid Chisnall    if (__owns_eb_)
39947a984708SDavid Chisnall        delete [] __extbuf_;
39957a984708SDavid Chisnall    if (__owns_ib_)
39967a984708SDavid Chisnall        delete [] __intbuf_;
39977a984708SDavid Chisnall}
39987a984708SDavid Chisnall
39997a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
40007a984708SDavid Chisnalltypename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
40017a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
40027a984708SDavid Chisnall{
40037a984708SDavid Chisnall    if (__cv_ == 0 || __bufptr_ == 0)
40047a984708SDavid Chisnall        return traits_type::eof();
40057a984708SDavid Chisnall    bool __initial = __read_mode();
40067a984708SDavid Chisnall    char_type __1buf;
40077a984708SDavid Chisnall    if (this->gptr() == 0)
40087a984708SDavid Chisnall        this->setg(&__1buf, &__1buf+1, &__1buf+1);
40097a984708SDavid Chisnall    const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
40107a984708SDavid Chisnall    int_type __c = traits_type::eof();
40117a984708SDavid Chisnall    if (this->gptr() == this->egptr())
40127a984708SDavid Chisnall    {
40137a984708SDavid Chisnall        memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
40147a984708SDavid Chisnall        if (__always_noconv_)
40157a984708SDavid Chisnall        {
40167a984708SDavid Chisnall            streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
40177a984708SDavid Chisnall            __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
40187a984708SDavid Chisnall            if (__nmemb != 0)
40197a984708SDavid Chisnall            {
40207a984708SDavid Chisnall                this->setg(this->eback(),
40217a984708SDavid Chisnall                           this->eback() + __unget_sz,
40227a984708SDavid Chisnall                           this->eback() + __unget_sz + __nmemb);
40237a984708SDavid Chisnall                __c = *this->gptr();
40247a984708SDavid Chisnall            }
40257a984708SDavid Chisnall        }
40267a984708SDavid Chisnall        else
40277a984708SDavid Chisnall        {
40287c82a1ecSDimitry Andric             _LIBCPP_ASSERT(!(__extbufnext_ == NULL && (__extbufend_ != __extbufnext_)), "underflow moving from NULL" );
40297c82a1ecSDimitry Andric             if (__extbufend_ != __extbufnext_)
40307a984708SDavid Chisnall                memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
40317a984708SDavid Chisnall            __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
40327a984708SDavid Chisnall            __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
40337a984708SDavid Chisnall            streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
40347a984708SDavid Chisnall                                 static_cast<streamsize>(__extbufend_ - __extbufnext_));
40357a984708SDavid Chisnall            codecvt_base::result __r;
4036aed8d94eSDimitry Andric            // FIXME: Do we ever need to restore the state here?
4037aed8d94eSDimitry Andric            //state_type __svs = __st_;
40387a984708SDavid Chisnall            streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
40397a984708SDavid Chisnall            if (__nr != 0)
40407a984708SDavid Chisnall            {
40417a984708SDavid Chisnall                __extbufend_ = __extbufnext_ + __nr;
40427a984708SDavid Chisnall                char_type*  __inext;
40437a984708SDavid Chisnall                __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
40447a984708SDavid Chisnall                                       this->eback() + __unget_sz,
40457a984708SDavid Chisnall                                       this->egptr(), __inext);
40467a984708SDavid Chisnall                if (__r == codecvt_base::noconv)
40477a984708SDavid Chisnall                {
404824d58133SDimitry Andric                    this->setg((char_type*)__extbuf_, (char_type*)__extbuf_,
404924d58133SDimitry Andric                               (char_type*) const_cast<char *>(__extbufend_));
40507a984708SDavid Chisnall                    __c = *this->gptr();
40517a984708SDavid Chisnall                }
40527a984708SDavid Chisnall                else if (__inext != this->eback() + __unget_sz)
40537a984708SDavid Chisnall                {
40547a984708SDavid Chisnall                    this->setg(this->eback(), this->eback() + __unget_sz, __inext);
40557a984708SDavid Chisnall                    __c = *this->gptr();
40567a984708SDavid Chisnall                }
40577a984708SDavid Chisnall            }
40587a984708SDavid Chisnall        }
40597a984708SDavid Chisnall    }
40607a984708SDavid Chisnall    else
40617a984708SDavid Chisnall        __c = *this->gptr();
40627a984708SDavid Chisnall    if (this->eback() == &__1buf)
40637a984708SDavid Chisnall        this->setg(0, 0, 0);
40647a984708SDavid Chisnall    return __c;
40657a984708SDavid Chisnall}
40667a984708SDavid Chisnall
40677a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
40687a984708SDavid Chisnalltypename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
40697a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
40707a984708SDavid Chisnall{
40717a984708SDavid Chisnall    if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
40727a984708SDavid Chisnall    {
40737a984708SDavid Chisnall        if (traits_type::eq_int_type(__c, traits_type::eof()))
40747a984708SDavid Chisnall        {
40757a984708SDavid Chisnall            this->gbump(-1);
40767a984708SDavid Chisnall            return traits_type::not_eof(__c);
40777a984708SDavid Chisnall        }
40787a984708SDavid Chisnall        if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
40797a984708SDavid Chisnall        {
40807a984708SDavid Chisnall            this->gbump(-1);
40817a984708SDavid Chisnall            *this->gptr() = traits_type::to_char_type(__c);
40827a984708SDavid Chisnall            return __c;
40837a984708SDavid Chisnall        }
40847a984708SDavid Chisnall    }
40857a984708SDavid Chisnall    return traits_type::eof();
40867a984708SDavid Chisnall}
40877a984708SDavid Chisnall
40887a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
40897a984708SDavid Chisnalltypename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
40907a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
40917a984708SDavid Chisnall{
40927a984708SDavid Chisnall    if (__cv_ == 0 || __bufptr_ == 0)
40937a984708SDavid Chisnall        return traits_type::eof();
40947a984708SDavid Chisnall    __write_mode();
40957a984708SDavid Chisnall    char_type __1buf;
40967a984708SDavid Chisnall    char_type* __pb_save = this->pbase();
40977a984708SDavid Chisnall    char_type* __epb_save = this->epptr();
40987a984708SDavid Chisnall    if (!traits_type::eq_int_type(__c, traits_type::eof()))
40997a984708SDavid Chisnall    {
41007a984708SDavid Chisnall        if (this->pptr() == 0)
41017a984708SDavid Chisnall            this->setp(&__1buf, &__1buf+1);
41027a984708SDavid Chisnall        *this->pptr() = traits_type::to_char_type(__c);
41037a984708SDavid Chisnall        this->pbump(1);
41047a984708SDavid Chisnall    }
41057a984708SDavid Chisnall    if (this->pptr() != this->pbase())
41067a984708SDavid Chisnall    {
41077a984708SDavid Chisnall        if (__always_noconv_)
41087a984708SDavid Chisnall        {
41097a984708SDavid Chisnall            streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
41107a984708SDavid Chisnall            if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
41117a984708SDavid Chisnall                return traits_type::eof();
41127a984708SDavid Chisnall        }
41137a984708SDavid Chisnall        else
41147a984708SDavid Chisnall        {
41157a984708SDavid Chisnall            char* __extbe = __extbuf_;
41167a984708SDavid Chisnall            codecvt_base::result __r;
41177a984708SDavid Chisnall            do
41187a984708SDavid Chisnall            {
41197a984708SDavid Chisnall                const char_type* __e;
41207a984708SDavid Chisnall                __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
41217a984708SDavid Chisnall                                        __extbuf_, __extbuf_ + __ebs_, __extbe);
41227a984708SDavid Chisnall                if (__e == this->pbase())
41237a984708SDavid Chisnall                    return traits_type::eof();
41247a984708SDavid Chisnall                if (__r == codecvt_base::noconv)
41257a984708SDavid Chisnall                {
41267a984708SDavid Chisnall                    streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
41277a984708SDavid Chisnall                    if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
41287a984708SDavid Chisnall                        return traits_type::eof();
41297a984708SDavid Chisnall                }
41307a984708SDavid Chisnall                else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
41317a984708SDavid Chisnall                {
41327a984708SDavid Chisnall                    streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
41337a984708SDavid Chisnall                    if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
41347a984708SDavid Chisnall                        return traits_type::eof();
41357a984708SDavid Chisnall                    if (__r == codecvt_base::partial)
41367a984708SDavid Chisnall                    {
413724d58133SDimitry Andric                        this->setp(const_cast<char_type *>(__e), this->pptr());
4138b2c7081bSDimitry Andric                        this->__pbump(this->epptr() - this->pbase());
41397a984708SDavid Chisnall                    }
41407a984708SDavid Chisnall                }
41417a984708SDavid Chisnall                else
41427a984708SDavid Chisnall                    return traits_type::eof();
41437a984708SDavid Chisnall            } while (__r == codecvt_base::partial);
41447a984708SDavid Chisnall        }
41457a984708SDavid Chisnall        this->setp(__pb_save, __epb_save);
41467a984708SDavid Chisnall    }
41477a984708SDavid Chisnall    return traits_type::not_eof(__c);
41487a984708SDavid Chisnall}
41497a984708SDavid Chisnall
41507a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
41517a984708SDavid Chisnallbasic_streambuf<_Elem, _Tr>*
41527a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
41537a984708SDavid Chisnall{
41547a984708SDavid Chisnall    this->setg(0, 0, 0);
41557a984708SDavid Chisnall    this->setp(0, 0);
41567a984708SDavid Chisnall    if (__owns_eb_)
41577a984708SDavid Chisnall        delete [] __extbuf_;
41587a984708SDavid Chisnall    if (__owns_ib_)
41597a984708SDavid Chisnall        delete [] __intbuf_;
41607a984708SDavid Chisnall    __ebs_ = __n;
41617a984708SDavid Chisnall    if (__ebs_ > sizeof(__extbuf_min_))
41627a984708SDavid Chisnall    {
41637a984708SDavid Chisnall        if (__always_noconv_ && __s)
41647a984708SDavid Chisnall        {
41657a984708SDavid Chisnall            __extbuf_ = (char*)__s;
41667a984708SDavid Chisnall            __owns_eb_ = false;
41677a984708SDavid Chisnall        }
41687a984708SDavid Chisnall        else
41697a984708SDavid Chisnall        {
41707a984708SDavid Chisnall            __extbuf_ = new char[__ebs_];
41717a984708SDavid Chisnall            __owns_eb_ = true;
41727a984708SDavid Chisnall        }
41737a984708SDavid Chisnall    }
41747a984708SDavid Chisnall    else
41757a984708SDavid Chisnall    {
41767a984708SDavid Chisnall        __extbuf_ = __extbuf_min_;
41777a984708SDavid Chisnall        __ebs_ = sizeof(__extbuf_min_);
41787a984708SDavid Chisnall        __owns_eb_ = false;
41797a984708SDavid Chisnall    }
41807a984708SDavid Chisnall    if (!__always_noconv_)
41817a984708SDavid Chisnall    {
41827a984708SDavid Chisnall        __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
41837a984708SDavid Chisnall        if (__s && __ibs_ >= sizeof(__extbuf_min_))
41847a984708SDavid Chisnall        {
41857a984708SDavid Chisnall            __intbuf_ = __s;
41867a984708SDavid Chisnall            __owns_ib_ = false;
41877a984708SDavid Chisnall        }
41887a984708SDavid Chisnall        else
41897a984708SDavid Chisnall        {
41907a984708SDavid Chisnall            __intbuf_ = new char_type[__ibs_];
41917a984708SDavid Chisnall            __owns_ib_ = true;
41927a984708SDavid Chisnall        }
41937a984708SDavid Chisnall    }
41947a984708SDavid Chisnall    else
41957a984708SDavid Chisnall    {
41967a984708SDavid Chisnall        __ibs_ = 0;
41977a984708SDavid Chisnall        __intbuf_ = 0;
41987a984708SDavid Chisnall        __owns_ib_ = false;
41997a984708SDavid Chisnall    }
42007a984708SDavid Chisnall    return this;
42017a984708SDavid Chisnall}
42027a984708SDavid Chisnall
42037a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
42047a984708SDavid Chisnalltypename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
42057a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
42067a984708SDavid Chisnall                                        ios_base::openmode __om)
42077a984708SDavid Chisnall{
42087a984708SDavid Chisnall    int __width = __cv_->encoding();
42097a984708SDavid Chisnall    if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
42107a984708SDavid Chisnall        return pos_type(off_type(-1));
42119729cf09SDimitry Andric    // __width > 0 || __off == 0, now check __way
42129729cf09SDimitry Andric    if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end)
42137a984708SDavid Chisnall        return pos_type(off_type(-1));
42147a984708SDavid Chisnall    pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
42157a984708SDavid Chisnall    __r.state(__st_);
42167a984708SDavid Chisnall    return __r;
42177a984708SDavid Chisnall}
42187a984708SDavid Chisnall
42197a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
42207a984708SDavid Chisnalltypename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
42217a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
42227a984708SDavid Chisnall{
42237a984708SDavid Chisnall    if (__cv_ == 0 || __bufptr_ == 0 || sync())
42247a984708SDavid Chisnall        return pos_type(off_type(-1));
42257a984708SDavid Chisnall    if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
42267a984708SDavid Chisnall        return pos_type(off_type(-1));
42277a984708SDavid Chisnall    return __sp;
42287a984708SDavid Chisnall}
42297a984708SDavid Chisnall
42307a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
42317a984708SDavid Chisnallint
42327a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
42337a984708SDavid Chisnall{
42347a984708SDavid Chisnall    if (__cv_ == 0 || __bufptr_ == 0)
42357a984708SDavid Chisnall        return 0;
42367a984708SDavid Chisnall    if (__cm_ & ios_base::out)
42377a984708SDavid Chisnall    {
42387a984708SDavid Chisnall        if (this->pptr() != this->pbase())
42397a984708SDavid Chisnall            if (overflow() == traits_type::eof())
42407a984708SDavid Chisnall                return -1;
42417a984708SDavid Chisnall        codecvt_base::result __r;
42427a984708SDavid Chisnall        do
42437a984708SDavid Chisnall        {
42447a984708SDavid Chisnall            char* __extbe;
42457a984708SDavid Chisnall            __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
42467a984708SDavid Chisnall            streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
42477a984708SDavid Chisnall            if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
42487a984708SDavid Chisnall                return -1;
42497a984708SDavid Chisnall        } while (__r == codecvt_base::partial);
42507a984708SDavid Chisnall        if (__r == codecvt_base::error)
42517a984708SDavid Chisnall            return -1;
42527a984708SDavid Chisnall        if (__bufptr_->pubsync())
42537a984708SDavid Chisnall            return -1;
42547a984708SDavid Chisnall    }
42557a984708SDavid Chisnall    else if (__cm_ & ios_base::in)
42567a984708SDavid Chisnall    {
42577a984708SDavid Chisnall        off_type __c;
42587a984708SDavid Chisnall        if (__always_noconv_)
42597a984708SDavid Chisnall            __c = this->egptr() - this->gptr();
42607a984708SDavid Chisnall        else
42617a984708SDavid Chisnall        {
42627a984708SDavid Chisnall            int __width = __cv_->encoding();
42637a984708SDavid Chisnall            __c = __extbufend_ - __extbufnext_;
42647a984708SDavid Chisnall            if (__width > 0)
42657a984708SDavid Chisnall                __c += __width * (this->egptr() - this->gptr());
42667a984708SDavid Chisnall            else
42677a984708SDavid Chisnall            {
42687a984708SDavid Chisnall                if (this->gptr() != this->egptr())
42697a984708SDavid Chisnall                {
42707a984708SDavid Chisnall                    reverse(this->gptr(), this->egptr());
42717a984708SDavid Chisnall                    codecvt_base::result __r;
42727a984708SDavid Chisnall                    const char_type* __e = this->gptr();
42737a984708SDavid Chisnall                    char* __extbe;
42747a984708SDavid Chisnall                    do
42757a984708SDavid Chisnall                    {
42767a984708SDavid Chisnall                        __r = __cv_->out(__st_, __e, this->egptr(), __e,
42777a984708SDavid Chisnall                                         __extbuf_, __extbuf_ + __ebs_, __extbe);
42787a984708SDavid Chisnall                        switch (__r)
42797a984708SDavid Chisnall                        {
42807a984708SDavid Chisnall                        case codecvt_base::noconv:
42817a984708SDavid Chisnall                            __c += this->egptr() - this->gptr();
42827a984708SDavid Chisnall                            break;
42837a984708SDavid Chisnall                        case codecvt_base::ok:
42847a984708SDavid Chisnall                        case codecvt_base::partial:
42857a984708SDavid Chisnall                            __c += __extbe - __extbuf_;
42867a984708SDavid Chisnall                            break;
42877a984708SDavid Chisnall                        default:
42887a984708SDavid Chisnall                            return -1;
42897a984708SDavid Chisnall                        }
42907a984708SDavid Chisnall                    } while (__r == codecvt_base::partial);
42917a984708SDavid Chisnall                }
42927a984708SDavid Chisnall            }
42937a984708SDavid Chisnall        }
42947a984708SDavid Chisnall        if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
42957a984708SDavid Chisnall            return -1;
42967a984708SDavid Chisnall        this->setg(0, 0, 0);
42977a984708SDavid Chisnall        __cm_ = 0;
42987a984708SDavid Chisnall    }
42997a984708SDavid Chisnall    return 0;
43007a984708SDavid Chisnall}
43017a984708SDavid Chisnall
43027a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
43037a984708SDavid Chisnallbool
43047a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
43057a984708SDavid Chisnall{
43067a984708SDavid Chisnall    if (!(__cm_ & ios_base::in))
43077a984708SDavid Chisnall    {
43087a984708SDavid Chisnall        this->setp(0, 0);
43097a984708SDavid Chisnall        if (__always_noconv_)
43107a984708SDavid Chisnall            this->setg((char_type*)__extbuf_,
43117a984708SDavid Chisnall                       (char_type*)__extbuf_ + __ebs_,
43127a984708SDavid Chisnall                       (char_type*)__extbuf_ + __ebs_);
43137a984708SDavid Chisnall        else
43147a984708SDavid Chisnall            this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
43157a984708SDavid Chisnall        __cm_ = ios_base::in;
43167a984708SDavid Chisnall        return true;
43177a984708SDavid Chisnall    }
43187a984708SDavid Chisnall    return false;
43197a984708SDavid Chisnall}
43207a984708SDavid Chisnall
43217a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
43227a984708SDavid Chisnallvoid
43237a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
43247a984708SDavid Chisnall{
43257a984708SDavid Chisnall    if (!(__cm_ & ios_base::out))
43267a984708SDavid Chisnall    {
43277a984708SDavid Chisnall        this->setg(0, 0, 0);
43287a984708SDavid Chisnall        if (__ebs_ > sizeof(__extbuf_min_))
43297a984708SDavid Chisnall        {
43307a984708SDavid Chisnall            if (__always_noconv_)
43317a984708SDavid Chisnall                this->setp((char_type*)__extbuf_,
43327a984708SDavid Chisnall                           (char_type*)__extbuf_ + (__ebs_ - 1));
43337a984708SDavid Chisnall            else
43347a984708SDavid Chisnall                this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
43357a984708SDavid Chisnall        }
43367a984708SDavid Chisnall        else
43377a984708SDavid Chisnall            this->setp(0, 0);
43387a984708SDavid Chisnall        __cm_ = ios_base::out;
43397a984708SDavid Chisnall    }
43407a984708SDavid Chisnall}
43417a984708SDavid Chisnall
43427a984708SDavid Chisnalltemplate <class _Codecvt, class _Elem, class _Tr>
43437a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>*
43447a984708SDavid Chisnallwbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
43457a984708SDavid Chisnall{
43467a984708SDavid Chisnall    wbuffer_convert* __rt = 0;
43477a984708SDavid Chisnall    if (__cv_ != 0 && __bufptr_ != 0)
43487a984708SDavid Chisnall    {
43497a984708SDavid Chisnall        __rt = this;
43507a984708SDavid Chisnall        if ((__cm_ & ios_base::out) && sync())
43517a984708SDavid Chisnall            __rt = 0;
43527a984708SDavid Chisnall    }
43537a984708SDavid Chisnall    return __rt;
43547a984708SDavid Chisnall}
43557a984708SDavid Chisnall
43567a984708SDavid Chisnall_LIBCPP_END_NAMESPACE_STD
43577a984708SDavid Chisnall
4358f9448bf3SDimitry Andric_LIBCPP_POP_MACROS
4359f9448bf3SDimitry Andric
43607a984708SDavid Chisnall#endif  // _LIBCPP_LOCALE
4361