1 // Locale support -*- C++ -*-
 
    3 // Copyright (C) 2007-2014 Free Software Foundation, Inc.
 
    5 // This file is part of the GNU ISO C++ Library.  This library is free
 
    6 // software; you can redistribute it and/or modify it under the
 
    7 // terms of the GNU General Public License as published by the
 
    8 // Free Software Foundation; either version 3, or (at your option)
 
   11 // This library is distributed in the hope that it will be useful,
 
   12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   14 // GNU General Public License for more details.
 
   16 // Under Section 7 of GPL version 3, you are granted additional
 
   17 // permissions described in the GCC Runtime Library Exception, version
 
   18 // 3.1, as published by the Free Software Foundation.
 
   20 // You should have received a copy of the GNU General Public License and
 
   21 // a copy of the GCC Runtime Library Exception along with this program;
 
   22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
   23 // <http://www.gnu.org/licenses/>.
 
   25 /** @file bits/locale_facets_nonio.tcc
 
   26  *  This is an internal header file, included by other library headers.
 
   27  *  Do not attempt to use it directly. @headername{locale}
 
   30 #ifndef _LOCALE_FACETS_NONIO_TCC
 
   31 #define _LOCALE_FACETS_NONIO_TCC 1
 
   33 #pragma GCC system_header
 
   35 namespace std _GLIBCXX_VISIBILITY(default)
 
   37 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   39   template<typename _CharT, bool _Intl>
 
   40     struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
 
   42       const __moneypunct_cache<_CharT, _Intl>*
 
   43       operator() (const locale& __loc) const
 
   45    const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
 
   46    const locale::facet** __caches = __loc._M_impl->_M_caches;
 
   49        __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
 
   52        __tmp = new __moneypunct_cache<_CharT, _Intl>;
 
   53        __tmp->_M_cache(__loc);
 
   58        __throw_exception_again;
 
   60        __loc._M_impl->_M_install_cache(__tmp, __i);
 
   63      const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
 
   67   template<typename _CharT, bool _Intl>
 
   69     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
 
   73       const moneypunct<_CharT, _Intl>& __mp =
 
   74    use_facet<moneypunct<_CharT, _Intl> >(__loc);
 
   76       _M_decimal_point = __mp.decimal_point();
 
   77       _M_thousands_sep = __mp.thousands_sep();
 
   78       _M_frac_digits = __mp.frac_digits();
 
   81       _CharT* __curr_symbol = 0;
 
   82       _CharT* __positive_sign = 0;
 
   83       _CharT* __negative_sign = 0;     
 
   86      _M_grouping_size = __mp.grouping().size();
 
   87      __grouping = new char[_M_grouping_size];
 
   88      __mp.grouping().copy(__grouping, _M_grouping_size);
 
   89      _M_grouping = __grouping;
 
   90      _M_use_grouping = (_M_grouping_size
 
   91                 && static_cast<signed char>(_M_grouping[0]) > 0
 
   93                 != __gnu_cxx::__numeric_traits<char>::__max));
 
   95      _M_curr_symbol_size = __mp.curr_symbol().size();
 
   96      __curr_symbol = new _CharT[_M_curr_symbol_size];
 
   97      __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
 
   98      _M_curr_symbol = __curr_symbol;
 
  100      _M_positive_sign_size = __mp.positive_sign().size();
 
  101      __positive_sign = new _CharT[_M_positive_sign_size];
 
  102      __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
 
  103      _M_positive_sign = __positive_sign;
 
  105      _M_negative_sign_size = __mp.negative_sign().size();
 
  106      __negative_sign = new _CharT[_M_negative_sign_size];
 
  107      __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
 
  108      _M_negative_sign = __negative_sign;
 
  110      _M_pos_format = __mp.pos_format();
 
  111      _M_neg_format = __mp.neg_format();
 
  113      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
 
  114      __ct.widen(money_base::_S_atoms,
 
  115             money_base::_S_atoms + money_base::_S_end, _M_atoms);
 
  119      delete [] __grouping;
 
  120      delete [] __curr_symbol;
 
  121      delete [] __positive_sign;
 
  122      delete [] __negative_sign;
 
  123      __throw_exception_again;
 
  127 _GLIBCXX_BEGIN_NAMESPACE_LDBL
 
  129   template<typename _CharT, typename _InIter>
 
  132       money_get<_CharT, _InIter>::
 
  133       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
 
  134         ios_base::iostate& __err, string& __units) const
 
  136    typedef char_traits<_CharT>           __traits_type;
 
  137    typedef typename string_type::size_type           size_type;    
 
  138    typedef money_base::part              part;
 
  139    typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
 
  141    const locale& __loc = __io._M_getloc();
 
  142    const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
  144    __use_cache<__cache_type> __uc;
 
  145    const __cache_type* __lc = __uc(__loc);
 
  146    const char_type* __lit = __lc->_M_atoms;
 
  149    bool __negative = false;
 
  151    size_type __sign_size = 0;
 
  152    // True if sign is mandatory.
 
  153    const bool __mandatory_sign = (__lc->_M_positive_sign_size
 
  154                       && __lc->_M_negative_sign_size);
 
  155    // String of grouping info from thousands_sep plucked from __units.
 
  156    string __grouping_tmp;
 
  157    if (__lc->_M_use_grouping)
 
  158      __grouping_tmp.reserve(32);
 
  159    // Last position before the decimal point.
 
  161    // Separator positions, then, possibly, fractional digits.
 
  163    // If input iterator is in a valid state.
 
  164    bool __testvalid = true;
 
  165    // Flag marking when a decimal point is found.
 
  166    bool __testdecfound = false;
 
  168    // The tentative returned string is stored here.
 
  172    const char_type* __lit_zero = __lit + money_base::_S_zero;
 
  173    const money_base::pattern __p = __lc->_M_neg_format;
 
  174    for (int __i = 0; __i < 4 && __testvalid; ++__i)
 
  176        const part __which = static_cast<part>(__p.field[__i]);
 
  179          case money_base::symbol:
 
  180        // According to 22.2.6.1.2, p2, symbol is required
 
  181        // if (__io.flags() & ios_base::showbase), otherwise
 
  182        // is optional and consumed only if other characters
 
  183        // are needed to complete the format.
 
  184        if (__io.flags() & ios_base::showbase || __sign_size > 1
 
  186            || (__i == 1 && (__mandatory_sign
 
  187                     || (static_cast<part>(__p.field[0])
 
  189                     || (static_cast<part>(__p.field[2])
 
  190                     == money_base::space)))
 
  191            || (__i == 2 && ((static_cast<part>(__p.field[3])
 
  192                      == money_base::value)
 
  194                     && (static_cast<part>(__p.field[3])
 
  195                         == money_base::sign)))))
 
  197            const size_type __len = __lc->_M_curr_symbol_size;
 
  199            for (; __beg != __end && __j < __len
 
  200               && *__beg == __lc->_M_curr_symbol[__j];
 
  203            && (__j || __io.flags() & ios_base::showbase))
 
  207          case money_base::sign:
 
  208        // Sign might not exist, or be more than one character long.
 
  209        if (__lc->_M_positive_sign_size && __beg != __end
 
  210            && *__beg == __lc->_M_positive_sign[0])
 
  212            __sign_size = __lc->_M_positive_sign_size;
 
  215        else if (__lc->_M_negative_sign_size && __beg != __end
 
  216             && *__beg == __lc->_M_negative_sign[0])
 
  219            __sign_size = __lc->_M_negative_sign_size;
 
  222        else if (__lc->_M_positive_sign_size
 
  223             && !__lc->_M_negative_sign_size)
 
  224          // "... if no sign is detected, the result is given the sign
 
  225          // that corresponds to the source of the empty string"
 
  227        else if (__mandatory_sign)
 
  230          case money_base::value:
 
  231        // Extract digits, remove and stash away the
 
  232        // grouping of found thousands separators.
 
  233        for (; __beg != __end; ++__beg)
 
  235            const char_type __c = *__beg;
 
  236            const char_type* __q = __traits_type::find(__lit_zero, 
 
  240            __res += money_base::_S_atoms[__q - __lit];
 
  243            else if (__c == __lc->_M_decimal_point 
 
  246            if (__lc->_M_frac_digits <= 0)
 
  251            __testdecfound = true;
 
  253            else if (__lc->_M_use_grouping
 
  254                 && __c == __lc->_M_thousands_sep
 
  259                // Mark position for later analysis.
 
  260                __grouping_tmp += static_cast<char>(__n);
 
  275          case money_base::space:
 
  276        // At least one space is required.
 
  277        if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
 
  281          case money_base::none:
 
  282        // Only if not at the end of the pattern.
 
  284          for (; __beg != __end
 
  285             && __ctype.is(ctype_base::space, *__beg); ++__beg);
 
  290    // Need to get the rest of the sign characters, if they exist.
 
  291    if (__sign_size > 1 && __testvalid)
 
  293        const char_type* __sign = __negative ? __lc->_M_negative_sign
 
  294                                             : __lc->_M_positive_sign;
 
  296        for (; __beg != __end && __i < __sign_size
 
  297           && *__beg == __sign[__i]; ++__beg, ++__i);
 
  299        if (__i != __sign_size)
 
  305        // Strip leading zeros.
 
  306        if (__res.size() > 1)
 
  308        const size_type __first = __res.find_first_not_of('0');
 
  309        const bool __only_zeros = __first == string::npos;
 
  311          __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
 
  315        if (__negative && __res[0] != '0')
 
  316          __res.insert(__res.begin(), '-');
 
  318        // Test for grouping fidelity.
 
  319        if (__grouping_tmp.size())
 
  321        // Add the ending grouping.
 
  322        __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
 
  324        if (!std::__verify_grouping(__lc->_M_grouping,
 
  325                        __lc->_M_grouping_size,
 
  327          __err |= ios_base::failbit;
 
  330        // Iff not enough digits were supplied after the decimal-point.
 
  331        if (__testdecfound && __n != __lc->_M_frac_digits)
 
  335    // Iff valid sequence is not recognized.
 
  337      __err |= ios_base::failbit;
 
  341    // Iff no more characters are available.
 
  343      __err |= ios_base::eofbit;
 
  347 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
 
  348   template<typename _CharT, typename _InIter>
 
  350     money_get<_CharT, _InIter>::
 
  351     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
 
  352         ios_base::iostate& __err, double& __units) const
 
  355       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
 
  356                      : _M_extract<false>(__beg, __end, __io, __err, __str);
 
  357       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
 
  362   template<typename _CharT, typename _InIter>
 
  364     money_get<_CharT, _InIter>::
 
  365     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
 
  366       ios_base::iostate& __err, long double& __units) const
 
  369       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
 
  370                 : _M_extract<false>(__beg, __end, __io, __err, __str);
 
  371       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
 
  375   template<typename _CharT, typename _InIter>
 
  377     money_get<_CharT, _InIter>::
 
  378     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
 
  379       ios_base::iostate& __err, string_type& __digits) const
 
  381       typedef typename string::size_type                  size_type;
 
  383       const locale& __loc = __io._M_getloc();
 
  384       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
  387       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
 
  388                 : _M_extract<false>(__beg, __end, __io, __err, __str);
 
  389       const size_type __len = __str.size();
 
  392      __digits.resize(__len);
 
  393      __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
 
  398   template<typename _CharT, typename _OutIter>
 
  401       money_put<_CharT, _OutIter>::
 
  402       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
 
  403        const string_type& __digits) const
 
  405    typedef typename string_type::size_type           size_type;
 
  406    typedef money_base::part                          part;
 
  407    typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
 
  409    const locale& __loc = __io._M_getloc();
 
  410    const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
  412    __use_cache<__cache_type> __uc;
 
  413    const __cache_type* __lc = __uc(__loc);
 
  414    const char_type* __lit = __lc->_M_atoms;
 
  416    // Determine if negative or positive formats are to be used, and
 
  417    // discard leading negative_sign if it is present.
 
  418    const char_type* __beg = __digits.data();
 
  420    money_base::pattern __p;
 
  421    const char_type* __sign;
 
  422    size_type __sign_size;
 
  423    if (!(*__beg == __lit[money_base::_S_minus]))
 
  425        __p = __lc->_M_pos_format;
 
  426        __sign = __lc->_M_positive_sign;
 
  427        __sign_size = __lc->_M_positive_sign_size;
 
  431        __p = __lc->_M_neg_format;
 
  432        __sign = __lc->_M_negative_sign;
 
  433        __sign_size = __lc->_M_negative_sign_size;
 
  438    // Look for valid numbers in the ctype facet within input digits.
 
  439    size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
 
  440                       __beg + __digits.size()) - __beg;
 
  443        // Assume valid input, and attempt to format.
 
  444        // Break down input numbers into base components, as follows:
 
  445        //   final_value = grouped units + (decimal point) + (digits)
 
  447        __value.reserve(2 * __len);
 
  449        // Add thousands separators to non-decimal digits, per
 
  451        long __paddec = __len - __lc->_M_frac_digits;
 
  454        if (__lc->_M_frac_digits < 0)
 
  456        if (__lc->_M_grouping_size)
 
  458            __value.assign(2 * __paddec, char_type());
 
  460              std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
 
  462                      __lc->_M_grouping_size,
 
  463                      __beg, __beg + __paddec);
 
  464            __value.erase(__vend - &__value[0]);
 
  467          __value.assign(__beg, __paddec);
 
  470        // Deal with decimal point, decimal digits.
 
  471        if (__lc->_M_frac_digits > 0)
 
  473        __value += __lc->_M_decimal_point;
 
  475          __value.append(__beg + __paddec, __lc->_M_frac_digits);
 
  478            // Have to pad zeros in the decimal position.
 
  479            __value.append(-__paddec, __lit[money_base::_S_zero]);
 
  480            __value.append(__beg, __len);
 
  484        // Calculate length of resulting string.
 
  485        const ios_base::fmtflags __f = __io.flags() 
 
  486                                       & ios_base::adjustfield;
 
  487        __len = __value.size() + __sign_size;
 
  488        __len += ((__io.flags() & ios_base::showbase)
 
  489              ? __lc->_M_curr_symbol_size : 0);
 
  492        __res.reserve(2 * __len);
 
  494        const size_type __width = static_cast<size_type>(__io.width());  
 
  495        const bool __testipad = (__f == ios_base::internal
 
  497        // Fit formatted digits into the required pattern.
 
  498        for (int __i = 0; __i < 4; ++__i)
 
  500        const part __which = static_cast<part>(__p.field[__i]);
 
  503          case money_base::symbol:
 
  504            if (__io.flags() & ios_base::showbase)
 
  505              __res.append(__lc->_M_curr_symbol,
 
  506                   __lc->_M_curr_symbol_size);
 
  508          case money_base::sign:
 
  509            // Sign might not exist, or be more than one
 
  510            // character long. In that case, add in the rest
 
  515          case money_base::value:
 
  518          case money_base::space:
 
  519            // At least one space is required, but if internal
 
  520            // formatting is required, an arbitrary number of
 
  521            // fill spaces will be necessary.
 
  523              __res.append(__width - __len, __fill);
 
  527          case money_base::none:
 
  529              __res.append(__width - __len, __fill);
 
  534        // Special case of multi-part sign parts.
 
  536          __res.append(__sign + 1, __sign_size - 1);
 
  538        // Pad, if still necessary.
 
  539        __len = __res.size();
 
  542        if (__f == ios_base::left)
 
  544          __res.append(__width - __len, __fill);
 
  547          __res.insert(0, __width - __len, __fill);
 
  551        // Write resulting, fully-formatted string to output iterator.
 
  552        __s = std::__write(__s, __res.data(), __len);
 
  558 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
 
  559   template<typename _CharT, typename _OutIter>
 
  561     money_put<_CharT, _OutIter>::
 
  562     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
 
  563         double __units) const
 
  564     { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
 
  567   template<typename _CharT, typename _OutIter>
 
  569     money_put<_CharT, _OutIter>::
 
  570     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
 
  571       long double __units) const
 
  573       const locale __loc = __io.getloc();
 
  574       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
  575 #ifdef _GLIBCXX_USE_C99
 
  576       // First try a buffer perhaps big enough.
 
  578       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
 
  579       // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  580       // 328. Bad sprintf format modifier in money_put<>::do_put()
 
  581       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
 
  582                    "%.*Lf", 0, __units);
 
  583       // If the buffer was not large enough, try again with the correct size.
 
  584       if (__len >= __cs_size)
 
  586      __cs_size = __len + 1;
 
  587      __cs = static_cast<char*>(__builtin_alloca(__cs_size));
 
  588      __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
 
  589                    "%.*Lf", 0, __units);
 
  592       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
 
  593       const int __cs_size =
 
  594    __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
 
  595       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
 
  596       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
 
  599       string_type __digits(__len, char_type());
 
  600       __ctype.widen(__cs, __cs + __len, &__digits[0]);
 
  601       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
 
  602                : _M_insert<false>(__s, __io, __fill, __digits);
 
  605   template<typename _CharT, typename _OutIter>
 
  607     money_put<_CharT, _OutIter>::
 
  608     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
 
  609       const string_type& __digits) const
 
  610     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
 
  611                : _M_insert<false>(__s, __io, __fill, __digits); }
 
  613 _GLIBCXX_END_NAMESPACE_LDBL
 
  615   // NB: Not especially useful. Without an ios_base object or some
 
  616   // kind of locale reference, we are left clawing at the air where
 
  617   // the side of the mountain used to be...
 
  618   template<typename _CharT, typename _InIter>
 
  620     time_get<_CharT, _InIter>::do_date_order() const
 
  621     { return time_base::no_order; }
 
  623   // Expand a strftime format string and parse it.  E.g., do_get_date() may
 
  624   // pass %m/%d/%Y => extracted characters.
 
  625   template<typename _CharT, typename _InIter>
 
  627     time_get<_CharT, _InIter>::
 
  628     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
 
  629              ios_base::iostate& __err, tm* __tm,
 
  630              const _CharT* __format) const
 
  632       const locale& __loc = __io._M_getloc();
 
  633       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
 
  634       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
  635       const size_t __len = char_traits<_CharT>::length(__format);
 
  637       ios_base::iostate __tmperr = ios_base::goodbit;
 
  639       for (; __beg != __end && __i < __len && !__tmperr; ++__i)
 
  641      if (__ctype.narrow(__format[__i], 0) == '%')
 
  643          // Verify valid formatting code, attempt to extract.
 
  644          char __c = __ctype.narrow(__format[++__i], 0);
 
  646          if (__c == 'E' || __c == 'O')
 
  647        __c = __ctype.narrow(__format[++__i], 0);
 
  653          // Abbreviated weekday name [tm_wday]
 
  654          const char_type*  __days1[7];
 
  655          __tp._M_days_abbreviated(__days1);
 
  656          __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
 
  660          // Weekday name [tm_wday].
 
  661          const char_type*  __days2[7];
 
  662          __tp._M_days(__days2);
 
  663          __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
 
  668          // Abbreviated month name [tm_mon]
 
  669          const char_type*  __months1[12];
 
  670          __tp._M_months_abbreviated(__months1);
 
  671          __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
 
  672                      __months1, 12, __io, __tmperr);
 
  675          // Month name [tm_mon].
 
  676          const char_type*  __months2[12];
 
  677          __tp._M_months(__months2);
 
  678          __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
 
  679                      __months2, 12, __io, __tmperr);
 
  682          // Default time and date representation.
 
  683          const char_type*  __dt[2];
 
  684          __tp._M_date_time_formats(__dt);
 
  685          __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
 
  689          // Day [01, 31]. [tm_mday]
 
  690          __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
 
  694          // Day [1, 31], with single digits preceded by
 
  696          if (__ctype.is(ctype_base::space, *__beg))
 
  697            __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
 
  700            __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
 
  704          // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
 
  706          __ctype.widen(__cs, __cs + 9, __wcs);
 
  707          __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
 
  711          // Hour [00, 23]. [tm_hour]
 
  712          __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
 
  716          // Hour [01, 12]. [tm_hour]
 
  717          __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
 
  721          // Month [01, 12]. [tm_mon]
 
  722          __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
 
  725            __tm->tm_mon = __mem - 1;
 
  728          // Minute [00, 59]. [tm_min]
 
  729          __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
 
  733          if (__ctype.narrow(*__beg, 0) == '\n')
 
  736            __tmperr |= ios_base::failbit;
 
  739          // Equivalent to (%H:%M).
 
  741          __ctype.widen(__cs, __cs + 6, __wcs);
 
  742          __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
 
  747          // [00, 60] in C99 (one leap-second), [00, 61] in C89.
 
  748 #ifdef _GLIBCXX_USE_C99
 
  749          __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
 
  751          __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
 
  756          if (__ctype.narrow(*__beg, 0) == '\t')
 
  759            __tmperr |= ios_base::failbit;
 
  762          // Equivalent to (%H:%M:%S).
 
  764          __ctype.widen(__cs, __cs + 9, __wcs);
 
  765          __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
 
  770          const char_type*  __dates[2];
 
  771          __tp._M_date_formats(__dates);
 
  772          __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
 
  777          const char_type*  __times[2];
 
  778          __tp._M_time_formats(__times);
 
  779          __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
 
  787          // NB: We parse either two digits, implicitly years since
 
  788          // 1900, or 4 digits, full year.  In both cases we can 
 
  789          // reconstruct [tm_year].  See also libstdc++/26701.
 
  790          __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
 
  793            __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
 
  797          if (__ctype.is(ctype_base::upper, *__beg))
 
  800              __beg = _M_extract_name(__beg, __end, __tmp,
 
  801                       __timepunct_cache<_CharT>::_S_timezones,
 
  804              // GMT requires special effort.
 
  805              if (__beg != __end && !__tmperr && __tmp == 0
 
  806              && (*__beg == __ctype.widen('-')
 
  807                  || *__beg == __ctype.widen('+')))
 
  809              __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
 
  811              __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
 
  816            __tmperr |= ios_base::failbit;
 
  820          __tmperr |= ios_base::failbit;
 
  825          // Verify format and input match, extract and discard.
 
  826          if (__format[__i] == *__beg)
 
  829        __tmperr |= ios_base::failbit;
 
  833       if (__tmperr || __i != __len)
 
  834    __err |= ios_base::failbit;
 
  839   template<typename _CharT, typename _InIter>
 
  841     time_get<_CharT, _InIter>::
 
  842     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
 
  843           int __min, int __max, size_t __len,
 
  844           ios_base& __io, ios_base::iostate& __err) const
 
  846       const locale& __loc = __io._M_getloc();
 
  847       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
  849       // As-is works for __len = 1, 2, 4, the values actually used.
 
  850       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
 
  855       for (; __beg != __end && __i < __len; ++__beg, ++__i)
 
  857      const char __c = __ctype.narrow(*__beg, '*');
 
  858      if (__c >= '0' && __c <= '9')
 
  860          __value = __value * 10 + (__c - '0');
 
  861          const int __valuec = __value * __mult;
 
  862          if (__valuec > __max || __valuec + __mult < __min)
 
  871       // Special encoding for do_get_year, 'y', and 'Y' above.
 
  872       else if (__len == 4 && __i == 2)
 
  873    __member = __value - 100;
 
  875    __err |= ios_base::failbit;
 
  881   // All elements in __names are unique.
 
  882   template<typename _CharT, typename _InIter>
 
  884     time_get<_CharT, _InIter>::
 
  885     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
 
  886            const _CharT** __names, size_t __indexlen,
 
  887            ios_base& __io, ios_base::iostate& __err) const
 
  889       typedef char_traits<_CharT>      __traits_type;
 
  890       const locale& __loc = __io._M_getloc();
 
  891       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
  893       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
 
  895       size_t __nmatches = 0;
 
  897       bool __testvalid = true;
 
  898       const char_type* __name;
 
  900       // Look for initial matches.
 
  901       // NB: Some of the locale data is in the form of all lowercase
 
  902       // names, and some is in the form of initially-capitalized
 
  903       // names. Look for both.
 
  906      const char_type __c = *__beg;
 
  907      for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
 
  908        if (__c == __names[__i1][0]
 
  909        || __c == __ctype.toupper(__names[__i1][0]))
 
  910          __matches[__nmatches++] = __i1;
 
  913       while (__nmatches > 1)
 
  915      // Find smallest matching string.
 
  916      size_t __minlen = __traits_type::length(__names[__matches[0]]);
 
  917      for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
 
  918        __minlen = std::min(__minlen,
 
  919                  __traits_type::length(__names[__matches[__i2]]));
 
  921      if (__pos < __minlen && __beg != __end)
 
  922        for (size_t __i3 = 0; __i3 < __nmatches;)
 
  924        __name = __names[__matches[__i3]];
 
  925        if (!(__name[__pos] == *__beg))
 
  926          __matches[__i3] = __matches[--__nmatches];
 
  936      // Make sure found name is completely extracted.
 
  938      __name = __names[__matches[0]];
 
  939      const size_t __len = __traits_type::length(__name);
 
  940      while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
 
  944        __member = __matches[0];
 
  951    __err |= ios_base::failbit;
 
  956   template<typename _CharT, typename _InIter>
 
  958     time_get<_CharT, _InIter>::
 
  959     _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
 
  960                 const _CharT** __names, size_t __indexlen,
 
  961                 ios_base& __io, ios_base::iostate& __err) const
 
  963       typedef char_traits<_CharT>      __traits_type;
 
  964       const locale& __loc = __io._M_getloc();
 
  965       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
  967       int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
 
  969       size_t __nmatches = 0;
 
  970       size_t* __matches_lengths = 0;
 
  975      const char_type __c = *__beg;
 
  976      for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
 
  977        if (__c == __names[__i][0]
 
  978        || __c == __ctype.toupper(__names[__i][0]))
 
  979          __matches[__nmatches++] = __i;
 
  987        = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
 
  989      for (size_t __i = 0; __i < __nmatches; ++__i)
 
  990        __matches_lengths[__i]
 
  991          = __traits_type::length(__names[__matches[__i]]);
 
  994       for (; __beg != __end; ++__beg, ++__pos)
 
  996      size_t __nskipped = 0;
 
  997      const char_type __c = *__beg;
 
  998      for (size_t __i = 0; __i < __nmatches;)
 
 1000          const char_type* __name = __names[__matches[__i]];
 
 1001          if (__pos >= __matches_lengths[__i])
 
 1002        ++__nskipped, ++__i;
 
 1003          else if (!(__name[__pos] == __c))
 
 1006          __matches[__i] = __matches[__nmatches];
 
 1007          __matches_lengths[__i] = __matches_lengths[__nmatches];
 
 1012      if (__nskipped == __nmatches)
 
 1016       if ((__nmatches == 1 && __matches_lengths[0] == __pos)
 
 1017      || (__nmatches == 2 && (__matches_lengths[0] == __pos
 
 1018                  || __matches_lengths[1] == __pos)))
 
 1019    __member = (__matches[0] >= __indexlen
 
 1020            ? __matches[0] - __indexlen : __matches[0]);
 
 1022    __err |= ios_base::failbit;
 
 1027   template<typename _CharT, typename _InIter>
 
 1029     time_get<_CharT, _InIter>::
 
 1030     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
 
 1031        ios_base::iostate& __err, tm* __tm) const
 
 1033       const locale& __loc = __io._M_getloc();
 
 1034       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
 
 1035       const char_type*  __times[2];
 
 1036       __tp._M_time_formats(__times);
 
 1037       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
 
 1040    __err |= ios_base::eofbit;
 
 1044   template<typename _CharT, typename _InIter>
 
 1046     time_get<_CharT, _InIter>::
 
 1047     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
 
 1048        ios_base::iostate& __err, tm* __tm) const
 
 1050       const locale& __loc = __io._M_getloc();
 
 1051       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
 
 1052       const char_type*  __dates[2];
 
 1053       __tp._M_date_formats(__dates);
 
 1054       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
 
 1057    __err |= ios_base::eofbit;
 
 1061   template<typename _CharT, typename _InIter>
 
 1063     time_get<_CharT, _InIter>::
 
 1064     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
 
 1065           ios_base::iostate& __err, tm* __tm) const
 
 1067       typedef char_traits<_CharT>      __traits_type;
 
 1068       const locale& __loc = __io._M_getloc();
 
 1069       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
 
 1070       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
 1071       const char_type* __days[14];
 
 1072       __tp._M_days_abbreviated(__days);
 
 1073       __tp._M_days(__days + 7);
 
 1075       ios_base::iostate __tmperr = ios_base::goodbit;
 
 1077       __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
 
 1080    __tm->tm_wday = __tmpwday;
 
 1082    __err |= ios_base::failbit;
 
 1085    __err |= ios_base::eofbit;
 
 1089   template<typename _CharT, typename _InIter>
 
 1091     time_get<_CharT, _InIter>::
 
 1092     do_get_monthname(iter_type __beg, iter_type __end,
 
 1093                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
 
 1095       typedef char_traits<_CharT>      __traits_type;
 
 1096       const locale& __loc = __io._M_getloc();
 
 1097       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
 
 1098       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
 1099       const char_type*  __months[24];
 
 1100       __tp._M_months_abbreviated(__months);
 
 1101       __tp._M_months(__months + 12);
 
 1103       ios_base::iostate __tmperr = ios_base::goodbit;
 
 1105       __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
 
 1108    __tm->tm_mon = __tmpmon;
 
 1110    __err |= ios_base::failbit;
 
 1113    __err |= ios_base::eofbit;
 
 1117   template<typename _CharT, typename _InIter>
 
 1119     time_get<_CharT, _InIter>::
 
 1120     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
 
 1121        ios_base::iostate& __err, tm* __tm) const
 
 1123       const locale& __loc = __io._M_getloc();
 
 1124       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
 1126       ios_base::iostate __tmperr = ios_base::goodbit;
 
 1128       __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
 
 1131    __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
 
 1133    __err |= ios_base::failbit;
 
 1136    __err |= ios_base::eofbit;
 
 1140   template<typename _CharT, typename _OutIter>
 
 1142     time_put<_CharT, _OutIter>::
 
 1143     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
 
 1144    const _CharT* __beg, const _CharT* __end) const
 
 1146       const locale& __loc = __io._M_getloc();
 
 1147       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
 
 1148       for (; __beg != __end; ++__beg)
 
 1149    if (__ctype.narrow(*__beg, 0) != '%')
 
 1154    else if (++__beg != __end)
 
 1158        const char __c = __ctype.narrow(*__beg, 0);
 
 1159        if (__c != 'E' && __c != 'O')
 
 1161        else if (++__beg != __end)
 
 1164        __format = __ctype.narrow(*__beg, 0);
 
 1168        __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
 
 1175   template<typename _CharT, typename _OutIter>
 
 1177     time_put<_CharT, _OutIter>::
 
 1178     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
 
 1179       char __format, char __mod) const
 
 1181       const locale& __loc = __io._M_getloc();
 
 1182       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
 
 1183       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
 
 1185       // NB: This size is arbitrary. Should this be a data member,
 
 1186       // initialized at construction?
 
 1187       const size_t __maxlen = 128;
 
 1188       char_type __res[__maxlen];
 
 1190       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
 
 1191       // is possible that the format character will be longer than one
 
 1192       // character. Possibilities include 'E' or 'O' followed by a
 
 1193       // format character: if __mod is not the default argument, assume
 
 1194       // it's a valid modifier.
 
 1196       __fmt[0] = __ctype.widen('%');
 
 1199      __fmt[1] = __format;
 
 1200      __fmt[2] = char_type();
 
 1205      __fmt[2] = __format;
 
 1206      __fmt[3] = char_type();
 
 1209       __tp._M_put(__res, __maxlen, __fmt, __tm);
 
 1211       // Write resulting, fully-formatted string to output iterator.
 
 1212       return std::__write(__s, __res, char_traits<char_type>::length(__res));
 
 1216   // Inhibit implicit instantiations for required instantiations,
 
 1217   // which are defined via explicit instantiations elsewhere.
 
 1218 #if _GLIBCXX_EXTERN_TEMPLATE
 
 1219   extern template class moneypunct<char, false>;
 
 1220   extern template class moneypunct<char, true>;
 
 1221   extern template class moneypunct_byname<char, false>;
 
 1222   extern template class moneypunct_byname<char, true>;
 
 1223   extern template class _GLIBCXX_NAMESPACE_LDBL money_get<char>;
 
 1224   extern template class _GLIBCXX_NAMESPACE_LDBL money_put<char>;
 
 1225   extern template class __timepunct<char>;
 
 1226   extern template class time_put<char>;
 
 1227   extern template class time_put_byname<char>;
 
 1228   extern template class time_get<char>;
 
 1229   extern template class time_get_byname<char>;
 
 1230   extern template class messages<char>;
 
 1231   extern template class messages_byname<char>;
 
 1234     const moneypunct<char, true>&
 
 1235     use_facet<moneypunct<char, true> >(const locale&);
 
 1238     const moneypunct<char, false>&
 
 1239     use_facet<moneypunct<char, false> >(const locale&);
 
 1242     const money_put<char>&
 
 1243     use_facet<money_put<char> >(const locale&);
 
 1246     const money_get<char>&
 
 1247     use_facet<money_get<char> >(const locale&);
 
 1250     const __timepunct<char>&
 
 1251     use_facet<__timepunct<char> >(const locale&);
 
 1254     const time_put<char>&
 
 1255     use_facet<time_put<char> >(const locale&);
 
 1258     const time_get<char>&
 
 1259     use_facet<time_get<char> >(const locale&);
 
 1262     const messages<char>&
 
 1263     use_facet<messages<char> >(const locale&);
 
 1267     has_facet<moneypunct<char> >(const locale&);
 
 1271     has_facet<money_put<char> >(const locale&);
 
 1275     has_facet<money_get<char> >(const locale&);
 
 1279     has_facet<__timepunct<char> >(const locale&);
 
 1283     has_facet<time_put<char> >(const locale&);
 
 1287     has_facet<time_get<char> >(const locale&);
 
 1291     has_facet<messages<char> >(const locale&);
 
 1293 #ifdef _GLIBCXX_USE_WCHAR_T
 
 1294   extern template class moneypunct<wchar_t, false>;
 
 1295   extern template class moneypunct<wchar_t, true>;
 
 1296   extern template class moneypunct_byname<wchar_t, false>;
 
 1297   extern template class moneypunct_byname<wchar_t, true>;
 
 1298   extern template class _GLIBCXX_NAMESPACE_LDBL money_get<wchar_t>;
 
 1299   extern template class _GLIBCXX_NAMESPACE_LDBL money_put<wchar_t>;
 
 1300   extern template class __timepunct<wchar_t>;
 
 1301   extern template class time_put<wchar_t>;
 
 1302   extern template class time_put_byname<wchar_t>;
 
 1303   extern template class time_get<wchar_t>;
 
 1304   extern template class time_get_byname<wchar_t>;
 
 1305   extern template class messages<wchar_t>;
 
 1306   extern template class messages_byname<wchar_t>;
 
 1309     const moneypunct<wchar_t, true>&
 
 1310     use_facet<moneypunct<wchar_t, true> >(const locale&);
 
 1313     const moneypunct<wchar_t, false>&
 
 1314     use_facet<moneypunct<wchar_t, false> >(const locale&);
 
 1317     const money_put<wchar_t>&
 
 1318     use_facet<money_put<wchar_t> >(const locale&);
 
 1321     const money_get<wchar_t>&
 
 1322     use_facet<money_get<wchar_t> >(const locale&);
 
 1325     const __timepunct<wchar_t>&
 
 1326     use_facet<__timepunct<wchar_t> >(const locale&);
 
 1329     const time_put<wchar_t>&
 
 1330     use_facet<time_put<wchar_t> >(const locale&);
 
 1333     const time_get<wchar_t>&
 
 1334     use_facet<time_get<wchar_t> >(const locale&);
 
 1337     const messages<wchar_t>&
 
 1338     use_facet<messages<wchar_t> >(const locale&);
 
 1342     has_facet<moneypunct<wchar_t> >(const locale&);
 
 1346     has_facet<money_put<wchar_t> >(const locale&);
 
 1350     has_facet<money_get<wchar_t> >(const locale&);
 
 1354     has_facet<__timepunct<wchar_t> >(const locale&);
 
 1358     has_facet<time_put<wchar_t> >(const locale&);
 
 1362     has_facet<time_get<wchar_t> >(const locale&);
 
 1366     has_facet<messages<wchar_t> >(const locale&);
 
 1370 _GLIBCXX_END_NAMESPACE_VERSION