locale_facets.tcc

Go to the documentation of this file.
00001 // Locale support -*- C++ -*-
00002 
00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
00004 // 2006, 2007, 2008
00005 // Free Software Foundation, Inc.
00006 //
00007 // This file is part of the GNU ISO C++ Library.  This library is free
00008 // software; you can redistribute it and/or modify it under the
00009 // terms of the GNU General Public License as published by the
00010 // Free Software Foundation; either version 2, or (at your option)
00011 // any later version.
00012 
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 
00018 // You should have received a copy of the GNU General Public License along
00019 // with this library; see the file COPYING.  If not, write to the Free
00020 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00021 // USA.
00022 
00023 // As a special exception, you may use this file as part of a free software
00024 // library without restriction.  Specifically, if other files instantiate
00025 // templates or use macros or inline functions from this file, or you compile
00026 // this file and link it with other files to produce an executable, this
00027 // file does not by itself cause the resulting executable to be covered by
00028 // the GNU General Public License.  This exception does not however
00029 // invalidate any other reasons why the executable file might be covered by
00030 // the GNU General Public License.
00031 
00032 /** @file locale_facets.tcc
00033  *  This is an internal header file, included by other library headers.
00034  *  You should not attempt to use it directly.
00035  */
00036 
00037 #ifndef _LOCALE_FACETS_TCC
00038 #define _LOCALE_FACETS_TCC 1
00039 
00040 #pragma GCC system_header
00041 
00042 #include <limits>       // For numeric_limits
00043 #include <typeinfo>     // For bad_cast.
00044 #include <bits/streambuf_iterator.h>
00045 #include <ext/type_traits.h>
00046 
00047 _GLIBCXX_BEGIN_NAMESPACE(std)
00048 
00049   template<typename _Facet>
00050     locale
00051     locale::combine(const locale& __other) const
00052     {
00053       _Impl* __tmp = new _Impl(*_M_impl, 1);
00054       try
00055     {
00056       __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
00057     }
00058       catch(...)
00059     {
00060       __tmp->_M_remove_reference();
00061       __throw_exception_again;
00062     }
00063       return locale(__tmp);
00064     }
00065 
00066   template<typename _CharT, typename _Traits, typename _Alloc>
00067     bool
00068     locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
00069                        const basic_string<_CharT, _Traits, _Alloc>& __s2) const
00070     {
00071       typedef std::collate<_CharT> __collate_type;
00072       const __collate_type& __collate = use_facet<__collate_type>(*this);
00073       return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
00074                 __s2.data(), __s2.data() + __s2.length()) < 0);
00075     }
00076 
00077   /**
00078    *  @brief  Test for the presence of a facet.
00079    *
00080    *  has_facet tests the locale argument for the presence of the facet type
00081    *  provided as the template parameter.  Facets derived from the facet
00082    *  parameter will also return true.
00083    *
00084    *  @param  Facet  The facet type to test the presence of.
00085    *  @param  locale  The locale to test.
00086    *  @return  true if locale contains a facet of type Facet, else false.
00087   */
00088   template<typename _Facet>
00089     inline bool
00090     has_facet(const locale& __loc) throw()
00091     {
00092       const size_t __i = _Facet::id._M_id();
00093       const locale::facet** __facets = __loc._M_impl->_M_facets;
00094       return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
00095     }
00096 
00097   /**
00098    *  @brief  Return a facet.
00099    *
00100    *  use_facet looks for and returns a reference to a facet of type Facet
00101    *  where Facet is the template parameter.  If has_facet(locale) is true,
00102    *  there is a suitable facet to return.  It throws std::bad_cast if the
00103    *  locale doesn't contain a facet of type Facet.
00104    *
00105    *  @param  Facet  The facet type to access.
00106    *  @param  locale  The locale to use.
00107    *  @return  Reference to facet of type Facet.
00108    *  @throw  std::bad_cast if locale doesn't contain a facet of type Facet.
00109   */
00110   template<typename _Facet>
00111     inline const _Facet&
00112     use_facet(const locale& __loc)
00113     {
00114       const size_t __i = _Facet::id._M_id();
00115       const locale::facet** __facets = __loc._M_impl->_M_facets;
00116       if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
00117         __throw_bad_cast();
00118       return static_cast<const _Facet&>(*__facets[__i]);
00119     }
00120 
00121 
00122   // Routine to access a cache for the facet.  If the cache didn't
00123   // exist before, it gets constructed on the fly.
00124   template<typename _Facet>
00125     struct __use_cache
00126     {
00127       const _Facet*
00128       operator() (const locale& __loc) const;
00129     };
00130 
00131   // Specializations.
00132   template<typename _CharT>
00133     struct __use_cache<__numpunct_cache<_CharT> >
00134     {
00135       const __numpunct_cache<_CharT>*
00136       operator() (const locale& __loc) const
00137       {
00138     const size_t __i = numpunct<_CharT>::id._M_id();
00139     const locale::facet** __caches = __loc._M_impl->_M_caches;
00140     if (!__caches[__i])
00141       {
00142         __numpunct_cache<_CharT>* __tmp = NULL;
00143         try
00144           {
00145         __tmp = new __numpunct_cache<_CharT>;
00146         __tmp->_M_cache(__loc);
00147           }
00148         catch(...)
00149           {
00150         delete __tmp;
00151         __throw_exception_again;
00152           }
00153         __loc._M_impl->_M_install_cache(__tmp, __i);
00154       }
00155     return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
00156       }
00157     };
00158 
00159   template<typename _CharT, bool _Intl>
00160     struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
00161     {
00162       const __moneypunct_cache<_CharT, _Intl>*
00163       operator() (const locale& __loc) const
00164       {
00165     const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
00166     const locale::facet** __caches = __loc._M_impl->_M_caches;
00167     if (!__caches[__i])
00168       {
00169         __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
00170         try
00171           {
00172         __tmp = new __moneypunct_cache<_CharT, _Intl>;
00173         __tmp->_M_cache(__loc);
00174           }
00175         catch(...)
00176           {
00177         delete __tmp;
00178         __throw_exception_again;
00179           }
00180         __loc._M_impl->_M_install_cache(__tmp, __i);
00181       }
00182     return static_cast<
00183       const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
00184       }
00185     };
00186 
00187   template<typename _CharT>
00188     void
00189     __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
00190     {
00191       _M_allocated = true;
00192 
00193       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
00194 
00195       _M_grouping_size = __np.grouping().size();
00196       char* __grouping = new char[_M_grouping_size];
00197       __np.grouping().copy(__grouping, _M_grouping_size);
00198       _M_grouping = __grouping;
00199       _M_use_grouping = (_M_grouping_size
00200              && static_cast<signed char>(__np.grouping()[0]) > 0);
00201 
00202       _M_truename_size = __np.truename().size();
00203       _CharT* __truename = new _CharT[_M_truename_size];
00204       __np.truename().copy(__truename, _M_truename_size);
00205       _M_truename = __truename;
00206 
00207       _M_falsename_size = __np.falsename().size();
00208       _CharT* __falsename = new _CharT[_M_falsename_size];
00209       __np.falsename().copy(__falsename, _M_falsename_size);
00210       _M_falsename = __falsename;
00211 
00212       _M_decimal_point = __np.decimal_point();
00213       _M_thousands_sep = __np.thousands_sep();
00214 
00215       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
00216       __ct.widen(__num_base::_S_atoms_out,
00217          __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out);
00218       __ct.widen(__num_base::_S_atoms_in,
00219          __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in);
00220     }
00221 
00222   template<typename _CharT, bool _Intl>
00223     void
00224     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
00225     {
00226       _M_allocated = true;
00227 
00228       const moneypunct<_CharT, _Intl>& __mp =
00229     use_facet<moneypunct<_CharT, _Intl> >(__loc);
00230 
00231       _M_grouping_size = __mp.grouping().size();
00232       char* __grouping = new char[_M_grouping_size];
00233       __mp.grouping().copy(__grouping, _M_grouping_size);
00234       _M_grouping = __grouping;
00235       _M_use_grouping = (_M_grouping_size
00236              && static_cast<signed char>(__mp.grouping()[0]) > 0);
00237       
00238       _M_decimal_point = __mp.decimal_point();
00239       _M_thousands_sep = __mp.thousands_sep();
00240       _M_frac_digits = __mp.frac_digits();
00241       
00242       _M_curr_symbol_size = __mp.curr_symbol().size();
00243       _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
00244       __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
00245       _M_curr_symbol = __curr_symbol;
00246       
00247       _M_positive_sign_size = __mp.positive_sign().size();
00248       _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
00249       __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
00250       _M_positive_sign = __positive_sign;
00251 
00252       _M_negative_sign_size = __mp.negative_sign().size();
00253       _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
00254       __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
00255       _M_negative_sign = __negative_sign;
00256       
00257       _M_pos_format = __mp.pos_format();
00258       _M_neg_format = __mp.neg_format();
00259 
00260       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
00261       __ct.widen(money_base::_S_atoms,
00262          money_base::_S_atoms + money_base::_S_end, _M_atoms);
00263     }
00264 
00265 
00266   // Used by both numeric and monetary facets.
00267   // Check to make sure that the __grouping_tmp string constructed in
00268   // money_get or num_get matches the canonical grouping for a given
00269   // locale.
00270   // __grouping_tmp is parsed L to R
00271   // 1,222,444 == __grouping_tmp of "\1\3\3"
00272   // __grouping is parsed R to L
00273   // 1,222,444 == __grouping of "\3" == "\3\3\3"
00274   static bool
00275   __verify_grouping(const char* __grouping, size_t __grouping_size,
00276             const string& __grouping_tmp);
00277 
00278 _GLIBCXX_BEGIN_LDBL_NAMESPACE
00279 
00280   template<typename _CharT, typename _InIter>
00281     _InIter
00282     num_get<_CharT, _InIter>::
00283     _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
00284              ios_base::iostate& __err, string& __xtrc) const
00285     {
00286       typedef char_traits<_CharT>           __traits_type;
00287       typedef __numpunct_cache<_CharT>                  __cache_type;
00288       __use_cache<__cache_type> __uc;
00289       const locale& __loc = __io._M_getloc();
00290       const __cache_type* __lc = __uc(__loc);
00291       const _CharT* __lit = __lc->_M_atoms_in;
00292       char_type __c = char_type();
00293 
00294       // True if __beg becomes equal to __end.
00295       bool __testeof = __beg == __end;
00296 
00297       // First check for sign.
00298       if (!__testeof)
00299     {
00300       __c = *__beg;
00301       const bool __plus = __c == __lit[__num_base::_S_iplus];
00302       if ((__plus || __c == __lit[__num_base::_S_iminus])
00303           && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00304           && !(__c == __lc->_M_decimal_point))
00305         {
00306           __xtrc += __plus ? '+' : '-';
00307           if (++__beg != __end)
00308         __c = *__beg;
00309           else
00310         __testeof = true;
00311         }
00312     }
00313 
00314       // Next, look for leading zeros.
00315       bool __found_mantissa = false;
00316       int __sep_pos = 0;
00317       while (!__testeof)
00318     {
00319       if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
00320           || __c == __lc->_M_decimal_point)
00321         break;
00322       else if (__c == __lit[__num_base::_S_izero])
00323         {
00324           if (!__found_mantissa)
00325         {
00326           __xtrc += '0';
00327           __found_mantissa = true;
00328         }
00329           ++__sep_pos;
00330 
00331           if (++__beg != __end)
00332         __c = *__beg;
00333           else
00334         __testeof = true;
00335         }
00336       else
00337         break;
00338     }
00339 
00340       // Only need acceptable digits for floating point numbers.
00341       bool __found_dec = false;
00342       bool __found_sci = false;
00343       string __found_grouping;
00344       if (__lc->_M_use_grouping)
00345     __found_grouping.reserve(32);
00346       const char_type* __lit_zero = __lit + __num_base::_S_izero;
00347 
00348       if (!__lc->_M_allocated)
00349     // "C" locale
00350     while (!__testeof)
00351       {
00352         const int __digit = _M_find(__lit_zero, 10, __c);
00353         if (__digit != -1)
00354           {
00355         __xtrc += '0' + __digit;
00356         __found_mantissa = true;
00357           }
00358         else if (__c == __lc->_M_decimal_point
00359              && !__found_dec && !__found_sci)
00360           {
00361         __xtrc += '.';
00362         __found_dec = true;
00363           }
00364         else if ((__c == __lit[__num_base::_S_ie] 
00365               || __c == __lit[__num_base::_S_iE])
00366              && !__found_sci && __found_mantissa)
00367           {
00368         // Scientific notation.
00369         __xtrc += 'e';
00370         __found_sci = true;
00371         
00372         // Remove optional plus or minus sign, if they exist.
00373         if (++__beg != __end)
00374           {
00375             __c = *__beg;
00376             const bool __plus = __c == __lit[__num_base::_S_iplus];
00377             if (__plus || __c == __lit[__num_base::_S_iminus])
00378               __xtrc += __plus ? '+' : '-';
00379             else
00380               continue;
00381           }
00382         else
00383           {
00384             __testeof = true;
00385             break;
00386           }
00387           }
00388         else
00389           break;
00390 
00391         if (++__beg != __end)
00392           __c = *__beg;
00393         else
00394           __testeof = true;
00395       }
00396       else
00397     while (!__testeof)
00398       {
00399         // According to 22.2.2.1.2, p8-9, first look for thousands_sep
00400         // and decimal_point.
00401         if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00402           {
00403         if (!__found_dec && !__found_sci)
00404           {
00405             // NB: Thousands separator at the beginning of a string
00406             // is a no-no, as is two consecutive thousands separators.
00407             if (__sep_pos)
00408               {
00409             __found_grouping += static_cast<char>(__sep_pos);
00410             __sep_pos = 0;
00411               }
00412             else
00413               {
00414             // NB: __convert_to_v will not assign __v and will
00415             // set the failbit.
00416             __xtrc.clear();
00417             break;
00418               }
00419           }
00420         else
00421           break;
00422           }
00423         else if (__c == __lc->_M_decimal_point)
00424           {
00425         if (!__found_dec && !__found_sci)
00426           {
00427             // If no grouping chars are seen, no grouping check
00428             // is applied. Therefore __found_grouping is adjusted
00429             // only if decimal_point comes after some thousands_sep.
00430             if (__found_grouping.size())
00431               __found_grouping += static_cast<char>(__sep_pos);
00432             __xtrc += '.';
00433             __found_dec = true;
00434           }
00435         else
00436           break;
00437           }
00438         else
00439           {
00440         const char_type* __q =
00441           __traits_type::find(__lit_zero, 10, __c);
00442         if (__q)
00443           {
00444             __xtrc += '0' + (__q - __lit_zero);
00445             __found_mantissa = true;
00446             ++__sep_pos;
00447           }
00448         else if ((__c == __lit[__num_base::_S_ie] 
00449               || __c == __lit[__num_base::_S_iE])
00450              && !__found_sci && __found_mantissa)
00451           {
00452             // Scientific notation.
00453             if (__found_grouping.size() && !__found_dec)
00454               __found_grouping += static_cast<char>(__sep_pos);
00455             __xtrc += 'e';
00456             __found_sci = true;
00457             
00458             // Remove optional plus or minus sign, if they exist.
00459             if (++__beg != __end)
00460               {
00461             __c = *__beg;
00462             const bool __plus = __c == __lit[__num_base::_S_iplus];
00463             if ((__plus || __c == __lit[__num_base::_S_iminus])
00464                 && !(__lc->_M_use_grouping
00465                  && __c == __lc->_M_thousands_sep)
00466                 && !(__c == __lc->_M_decimal_point))
00467               __xtrc += __plus ? '+' : '-';
00468             else
00469               continue;
00470               }
00471             else
00472               {
00473             __testeof = true;
00474             break;
00475               }
00476           }
00477         else
00478           break;
00479           }
00480         
00481         if (++__beg != __end)
00482           __c = *__beg;
00483         else
00484           __testeof = true;
00485       }
00486 
00487       // Digit grouping is checked. If grouping and found_grouping don't
00488       // match, then get very very upset, and set failbit.
00489       if (__found_grouping.size())
00490         {
00491           // Add the ending grouping if a decimal or 'e'/'E' wasn't found.
00492       if (!__found_dec && !__found_sci)
00493         __found_grouping += static_cast<char>(__sep_pos);
00494 
00495           if (!std::__verify_grouping(__lc->_M_grouping, 
00496                       __lc->_M_grouping_size,
00497                       __found_grouping))
00498         __err |= ios_base::failbit;
00499         }
00500 
00501       // Finish up.
00502       if (__testeof)
00503         __err |= ios_base::eofbit;
00504       return __beg;
00505     }
00506 
00507 _GLIBCXX_END_LDBL_NAMESPACE
00508 
00509 _GLIBCXX_BEGIN_LDBL_NAMESPACE
00510 
00511   template<typename _CharT, typename _InIter>
00512     template<typename _ValueT>
00513       _InIter
00514       num_get<_CharT, _InIter>::
00515       _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
00516              ios_base::iostate& __err, _ValueT& __v) const
00517       {
00518         typedef char_traits<_CharT>              __traits_type;
00519     using __gnu_cxx::__add_unsigned;
00520     typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
00521     typedef __numpunct_cache<_CharT>                     __cache_type;
00522     __use_cache<__cache_type> __uc;
00523     const locale& __loc = __io._M_getloc();
00524     const __cache_type* __lc = __uc(__loc);
00525     const _CharT* __lit = __lc->_M_atoms_in;
00526     char_type __c = char_type();
00527 
00528     // NB: Iff __basefield == 0, __base can change based on contents.
00529     const ios_base::fmtflags __basefield = __io.flags()
00530                                            & ios_base::basefield;
00531     const bool __oct = __basefield == ios_base::oct;
00532     int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
00533 
00534     // True if __beg becomes equal to __end.
00535     bool __testeof = __beg == __end;
00536 
00537     // First check for sign.
00538     bool __negative = false;
00539     if (!__testeof)
00540       {
00541         __c = *__beg;
00542         if (numeric_limits<_ValueT>::is_signed)
00543           __negative = __c == __lit[__num_base::_S_iminus];
00544         if ((__negative || __c == __lit[__num_base::_S_iplus])
00545         && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00546         && !(__c == __lc->_M_decimal_point))
00547           {
00548         if (++__beg != __end)
00549           __c = *__beg;
00550         else
00551           __testeof = true;
00552           }
00553       }
00554 
00555     // Next, look for leading zeros and check required digits
00556     // for base formats.
00557     bool __found_zero = false;
00558     int __sep_pos = 0;
00559     while (!__testeof)
00560       {
00561         if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
00562         || __c == __lc->_M_decimal_point)
00563           break;
00564         else if (__c == __lit[__num_base::_S_izero] 
00565              && (!__found_zero || __base == 10))
00566           {
00567         __found_zero = true;
00568         ++__sep_pos;
00569         if (__basefield == 0)
00570           __base = 8;
00571         if (__base == 8)
00572           __sep_pos = 0;
00573           }
00574         else if (__found_zero
00575              && (__c == __lit[__num_base::_S_ix]
00576              || __c == __lit[__num_base::_S_iX]))
00577           {
00578         if (__basefield == 0)
00579           __base = 16;
00580         if (__base == 16)
00581           {
00582             __found_zero = false;
00583             __sep_pos = 0;
00584           }
00585         else
00586           break;
00587           }
00588         else
00589           break;
00590 
00591         if (++__beg != __end)
00592           {
00593         __c = *__beg;
00594         if (!__found_zero)
00595           break;
00596           }
00597         else
00598           __testeof = true;
00599       }
00600     
00601     // At this point, base is determined. If not hex, only allow
00602     // base digits as valid input.
00603     const size_t __len = (__base == 16 ? __num_base::_S_iend
00604                   - __num_base::_S_izero : __base);
00605 
00606     // Extract.
00607     string __found_grouping;
00608     if (__lc->_M_use_grouping)
00609       __found_grouping.reserve(32);
00610     bool __testfail = false;
00611     const __unsigned_type __max = __negative ?
00612       -numeric_limits<_ValueT>::min() : numeric_limits<_ValueT>::max();
00613     const __unsigned_type __smax = __max / __base;
00614     __unsigned_type __result = 0;
00615     int __digit = 0;
00616     const char_type* __lit_zero = __lit + __num_base::_S_izero;
00617 
00618     if (!__lc->_M_allocated)
00619       // "C" locale
00620       while (!__testeof)
00621         {
00622           __digit = _M_find(__lit_zero, __len, __c);
00623           if (__digit == -1)
00624         break;
00625           
00626           if (__result > __smax)
00627         __testfail = true;
00628           else
00629         {
00630           __result *= __base;
00631           __testfail |= __result > __max - __digit;
00632           __result += __digit;
00633           ++__sep_pos;
00634         }
00635           
00636           if (++__beg != __end)
00637         __c = *__beg;
00638           else
00639         __testeof = true;
00640         }
00641     else
00642       while (!__testeof)
00643         {
00644           // According to 22.2.2.1.2, p8-9, first look for thousands_sep
00645           // and decimal_point.
00646           if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00647         {
00648           // NB: Thousands separator at the beginning of a string
00649           // is a no-no, as is two consecutive thousands separators.
00650           if (__sep_pos)
00651             {
00652               __found_grouping += static_cast<char>(__sep_pos);
00653               __sep_pos = 0;
00654             }
00655           else
00656             {
00657               __testfail = true;
00658               break;
00659             }
00660         }
00661           else if (__c == __lc->_M_decimal_point)
00662         break;
00663           else
00664         {
00665           const char_type* __q =
00666             __traits_type::find(__lit_zero, __len, __c);
00667           if (!__q)
00668             break;
00669           
00670           __digit = __q - __lit_zero;
00671           if (__digit > 15)
00672             __digit -= 6;
00673           if (__result > __smax)
00674             __testfail = true;
00675           else
00676             {
00677               __result *= __base;
00678               __testfail |= __result > __max - __digit;
00679               __result += __digit;
00680               ++__sep_pos;
00681             }
00682         }
00683           
00684           if (++__beg != __end)
00685         __c = *__beg;
00686           else
00687         __testeof = true;
00688         }
00689     
00690     // Digit grouping is checked. If grouping and found_grouping don't
00691     // match, then get very very upset, and set failbit.
00692     if (__found_grouping.size())
00693       {
00694         // Add the ending grouping.
00695         __found_grouping += static_cast<char>(__sep_pos);
00696 
00697         if (!std::__verify_grouping(__lc->_M_grouping,
00698                     __lc->_M_grouping_size,
00699                     __found_grouping))
00700           __err |= ios_base::failbit;
00701       }
00702 
00703     if (!__testfail && (__sep_pos || __found_zero 
00704                 || __found_grouping.size()))
00705       __v = __negative ? -__result : __result;
00706     else
00707       __err |= ios_base::failbit;
00708 
00709     if (__testeof)
00710       __err |= ios_base::eofbit;
00711     return __beg;
00712       }
00713 
00714   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00715   // 17.  Bad bool parsing
00716   template<typename _CharT, typename _InIter>
00717     _InIter
00718     num_get<_CharT, _InIter>::
00719     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00720            ios_base::iostate& __err, bool& __v) const
00721     {
00722       if (!(__io.flags() & ios_base::boolalpha))
00723         {
00724       // Parse bool values as long.
00725           // NB: We can't just call do_get(long) here, as it might
00726           // refer to a derived class.
00727       long __l = -1;
00728           __beg = _M_extract_int(__beg, __end, __io, __err, __l);
00729       if (__l == 0 || __l == 1)
00730         __v = __l;
00731       else
00732             __err |= ios_base::failbit;
00733         }
00734       else
00735         {
00736       // Parse bool values as alphanumeric.
00737       typedef __numpunct_cache<_CharT>              __cache_type;
00738       __use_cache<__cache_type> __uc;
00739       const locale& __loc = __io._M_getloc();
00740       const __cache_type* __lc = __uc(__loc);
00741 
00742       bool __testf = true;
00743       bool __testt = true;
00744       size_t __n;
00745       bool __testeof = __beg == __end;
00746           for (__n = 0; !__testeof; ++__n)
00747             {
00748           const char_type __c = *__beg;
00749 
00750           if (__testf)
00751         if (__n < __lc->_M_falsename_size)
00752           __testf = __c == __lc->_M_falsename[__n];
00753         else
00754           break;
00755 
00756           if (__testt)
00757         if (__n < __lc->_M_truename_size)
00758           __testt = __c == __lc->_M_truename[__n];
00759         else
00760           break;
00761 
00762           if (!__testf && !__testt)
00763         break;
00764           
00765           if (++__beg == __end)
00766         __testeof = true;
00767             }
00768       if (__testf && __n == __lc->_M_falsename_size)
00769         __v = 0;
00770       else if (__testt && __n == __lc->_M_truename_size)
00771         __v = 1;
00772       else
00773         __err |= ios_base::failbit;
00774 
00775           if (__testeof)
00776             __err |= ios_base::eofbit;
00777         }
00778       return __beg;
00779     }
00780 
00781   template<typename _CharT, typename _InIter>
00782     _InIter
00783     num_get<_CharT, _InIter>::
00784     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00785            ios_base::iostate& __err, long& __v) const
00786     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00787 
00788   template<typename _CharT, typename _InIter>
00789     _InIter
00790     num_get<_CharT, _InIter>::
00791     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00792            ios_base::iostate& __err, unsigned short& __v) const
00793     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00794 
00795   template<typename _CharT, typename _InIter>
00796     _InIter
00797     num_get<_CharT, _InIter>::
00798     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00799            ios_base::iostate& __err, unsigned int& __v) const
00800     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00801 
00802   template<typename _CharT, typename _InIter>
00803     _InIter
00804     num_get<_CharT, _InIter>::
00805     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00806            ios_base::iostate& __err, unsigned long& __v) const
00807     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00808 
00809 #ifdef _GLIBCXX_USE_LONG_LONG
00810   template<typename _CharT, typename _InIter>
00811     _InIter
00812     num_get<_CharT, _InIter>::
00813     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00814            ios_base::iostate& __err, long long& __v) const
00815     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00816 
00817   template<typename _CharT, typename _InIter>
00818     _InIter
00819     num_get<_CharT, _InIter>::
00820     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00821            ios_base::iostate& __err, unsigned long long& __v) const
00822     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00823 #endif
00824 
00825   template<typename _CharT, typename _InIter>
00826     _InIter
00827     num_get<_CharT, _InIter>::
00828     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00829        ios_base::iostate& __err, float& __v) const
00830     {
00831       string __xtrc;
00832       __xtrc.reserve(32);
00833       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00834       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00835       return __beg;
00836     }
00837 
00838   template<typename _CharT, typename _InIter>
00839     _InIter
00840     num_get<_CharT, _InIter>::
00841     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00842            ios_base::iostate& __err, double& __v) const
00843     {
00844       string __xtrc;
00845       __xtrc.reserve(32);
00846       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00847       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00848       return __beg;
00849     }
00850 
00851 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
00852   template<typename _CharT, typename _InIter>
00853     _InIter
00854     num_get<_CharT, _InIter>::
00855     __do_get(iter_type __beg, iter_type __end, ios_base& __io,
00856          ios_base::iostate& __err, double& __v) const
00857     {
00858       string __xtrc;
00859       __xtrc.reserve(32);
00860       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00861       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00862       return __beg;
00863     }
00864 #endif
00865 
00866   template<typename _CharT, typename _InIter>
00867     _InIter
00868     num_get<_CharT, _InIter>::
00869     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00870            ios_base::iostate& __err, long double& __v) const
00871     {
00872       string __xtrc;
00873       __xtrc.reserve(32);
00874       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00875       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00876       return __beg;
00877     }
00878 
00879   template<typename _CharT, typename _InIter>
00880     _InIter
00881     num_get<_CharT, _InIter>::
00882     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00883            ios_base::iostate& __err, void*& __v) const
00884     {
00885       // Prepare for hex formatted input.
00886       typedef ios_base::fmtflags        fmtflags;
00887       const fmtflags __fmt = __io.flags();
00888       __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
00889 
00890       unsigned long __ul;
00891       __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
00892 
00893       // Reset from hex formatted input.
00894       __io.flags(__fmt);
00895 
00896       if (!(__err & ios_base::failbit))
00897     __v = reinterpret_cast<void*>(__ul);
00898       return __beg;
00899     }
00900 
00901   // For use by integer and floating-point types after they have been
00902   // converted into a char_type string.
00903   template<typename _CharT, typename _OutIter>
00904     void
00905     num_put<_CharT, _OutIter>::
00906     _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
00907        _CharT* __new, const _CharT* __cs, int& __len) const
00908     {
00909       // [22.2.2.2.2] Stage 3.
00910       // If necessary, pad.
00911       __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs,
00912                           __w, __len, true);
00913       __len = static_cast<int>(__w);
00914     }
00915 
00916 _GLIBCXX_END_LDBL_NAMESPACE
00917 
00918   template<typename _CharT, typename _ValueT>
00919     int
00920     __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
00921           ios_base::fmtflags __flags, bool __dec)
00922     {
00923       _CharT* __buf = __bufend;
00924       if (__builtin_expect(__dec, true))
00925     {
00926       // Decimal.
00927       do
00928         {
00929           *--__buf = __lit[(__v % 10) + __num_base::_S_odigits];
00930           __v /= 10;
00931         }
00932       while (__v != 0);
00933     }
00934       else if ((__flags & ios_base::basefield) == ios_base::oct)
00935     {
00936       // Octal.
00937       do
00938         {
00939           *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits];
00940           __v >>= 3;
00941         }
00942       while (__v != 0);
00943     }
00944       else
00945     {
00946       // Hex.
00947       const bool __uppercase = __flags & ios_base::uppercase;
00948       const int __case_offset = __uppercase ? __num_base::_S_oudigits
00949                                             : __num_base::_S_odigits;
00950       do
00951         {
00952           *--__buf = __lit[(__v & 0xf) + __case_offset];
00953           __v >>= 4;
00954         }
00955       while (__v != 0);
00956     }
00957       return __bufend - __buf;
00958     }
00959 
00960 _GLIBCXX_BEGIN_LDBL_NAMESPACE
00961 
00962   template<typename _CharT, typename _OutIter>
00963     void
00964     num_put<_CharT, _OutIter>::
00965     _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
00966          ios_base&, _CharT* __new, _CharT* __cs, int& __len) const
00967     {
00968       _CharT* __p = std::__add_grouping(__new, __sep, __grouping,
00969                     __grouping_size, __cs, __cs + __len);
00970       __len = __p - __new;
00971     }
00972   
00973   template<typename _CharT, typename _OutIter>
00974     template<typename _ValueT>
00975       _OutIter
00976       num_put<_CharT, _OutIter>::
00977       _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
00978             _ValueT __v) const
00979       {
00980     using __gnu_cxx::__add_unsigned;
00981     typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
00982     typedef __numpunct_cache<_CharT>                 __cache_type;
00983     __use_cache<__cache_type> __uc;
00984     const locale& __loc = __io._M_getloc();
00985     const __cache_type* __lc = __uc(__loc);
00986     const _CharT* __lit = __lc->_M_atoms_out;
00987     const ios_base::fmtflags __flags = __io.flags();
00988 
00989     // Long enough to hold hex, dec, and octal representations.
00990     const int __ilen = 5 * sizeof(_ValueT);
00991     _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
00992                                  * __ilen));
00993 
00994     // [22.2.2.2.2] Stage 1, numeric conversion to character.
00995     // Result is returned right-justified in the buffer.
00996     const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
00997     const bool __dec = (__basefield != ios_base::oct
00998                 && __basefield != ios_base::hex);
00999     const __unsigned_type __u = (__v > 0 || !__dec) ? __v : -__v;
01000     int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec);
01001     __cs += __ilen - __len;
01002 
01003     // Add grouping, if necessary.
01004     if (__lc->_M_use_grouping)
01005       {
01006         // Grouping can add (almost) as many separators as the number
01007         // of digits + space is reserved for numeric base or sign.
01008         _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01009                                   * (__len + 1)
01010                                   * 2));
01011         _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
01012              __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len);
01013         __cs = __cs2 + 2;
01014       }
01015 
01016     // Complete Stage 1, prepend numeric base or sign.
01017     if (__builtin_expect(__dec, true))
01018       {
01019         // Decimal.
01020         if (__v >= 0)
01021           {
01022         if (__flags & ios_base::showpos
01023             && numeric_limits<_ValueT>::is_signed)
01024           *--__cs = __lit[__num_base::_S_oplus], ++__len;
01025           }
01026         else
01027           *--__cs = __lit[__num_base::_S_ominus], ++__len;
01028       }
01029     else if (__flags & ios_base::showbase && __v)
01030       {
01031         if (__basefield == ios_base::oct)
01032           *--__cs = __lit[__num_base::_S_odigits], ++__len;
01033         else
01034           {
01035         // 'x' or 'X'
01036         const bool __uppercase = __flags & ios_base::uppercase;
01037         *--__cs = __lit[__num_base::_S_ox + __uppercase];
01038         // '0'
01039         *--__cs = __lit[__num_base::_S_odigits];
01040         __len += 2;
01041           }
01042       }
01043 
01044     // Pad.
01045     const streamsize __w = __io.width();
01046     if (__w > static_cast<streamsize>(__len))
01047       {
01048         _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01049                                   * __w));
01050         _M_pad(__fill, __w, __io, __cs3, __cs, __len);
01051         __cs = __cs3;
01052       }
01053     __io.width(0);
01054 
01055     // [22.2.2.2.2] Stage 4.
01056     // Write resulting, fully-formatted string to output iterator.
01057     return std::__write(__s, __cs, __len);
01058       }
01059 
01060   template<typename _CharT, typename _OutIter>
01061     void
01062     num_put<_CharT, _OutIter>::
01063     _M_group_float(const char* __grouping, size_t __grouping_size,
01064            _CharT __sep, const _CharT* __p, _CharT* __new,
01065            _CharT* __cs, int& __len) const
01066     {
01067       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01068       // 282. What types does numpunct grouping refer to?
01069       // Add grouping, if necessary.
01070       const int __declen = __p ? __p - __cs : __len;
01071       _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping,
01072                      __grouping_size,
01073                      __cs, __cs + __declen);
01074 
01075       // Tack on decimal part.
01076       int __newlen = __p2 - __new;
01077       if (__p)
01078     {
01079       char_traits<_CharT>::copy(__p2, __p, __len - __declen);
01080       __newlen += __len - __declen;
01081     }
01082       __len = __newlen;
01083     }
01084 
01085   // The following code uses vsnprintf (or vsprintf(), when
01086   // _GLIBCXX_USE_C99 is not defined) to convert floating point values
01087   // for insertion into a stream.  An optimization would be to replace
01088   // them with code that works directly on a wide buffer and then use
01089   // __pad to do the padding.  It would be good to replace them anyway
01090   // to gain back the efficiency that C++ provides by knowing up front
01091   // the type of the values to insert.  Also, sprintf is dangerous
01092   // since may lead to accidental buffer overruns.  This
01093   // implementation follows the C++ standard fairly directly as
01094   // outlined in 22.2.2.2 [lib.locale.num.put]
01095   template<typename _CharT, typename _OutIter>
01096     template<typename _ValueT>
01097       _OutIter
01098       num_put<_CharT, _OutIter>::
01099       _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
01100                _ValueT __v) const
01101       {
01102     typedef __numpunct_cache<_CharT>                __cache_type;
01103     __use_cache<__cache_type> __uc;
01104     const locale& __loc = __io._M_getloc();
01105     const __cache_type* __lc = __uc(__loc);
01106 
01107     // Use default precision if out of range.
01108     const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision();
01109 
01110     const int __max_digits = numeric_limits<_ValueT>::digits10;
01111 
01112     // [22.2.2.2.2] Stage 1, numeric conversion to character.
01113     int __len;
01114     // Long enough for the max format spec.
01115     char __fbuf[16];
01116     __num_base::_S_format_float(__io, __fbuf, __mod);
01117 
01118 #ifdef _GLIBCXX_USE_C99
01119     // First try a buffer perhaps big enough (most probably sufficient
01120     // for non-ios_base::fixed outputs)
01121     int __cs_size = __max_digits * 3;
01122     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01123     __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
01124                       __fbuf, __prec, __v);
01125 
01126     // If the buffer was not large enough, try again with the correct size.
01127     if (__len >= __cs_size)
01128       {
01129         __cs_size = __len + 1;
01130         __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01131         __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
01132                       __fbuf, __prec, __v);
01133       }
01134 #else
01135     // Consider the possibility of long ios_base::fixed outputs
01136     const bool __fixed = __io.flags() & ios_base::fixed;
01137     const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
01138 
01139     // The size of the output string is computed as follows.
01140     // ios_base::fixed outputs may need up to __max_exp + 1 chars
01141     // for the integer part + __prec chars for the fractional part
01142     // + 3 chars for sign, decimal point, '\0'. On the other hand,
01143     // for non-fixed outputs __max_digits * 2 + __prec chars are
01144     // largely sufficient.
01145     const int __cs_size = __fixed ? __max_exp + __prec + 4
01146                                   : __max_digits * 2 + __prec;
01147     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01148     __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf, 
01149                       __prec, __v);
01150 #endif
01151 
01152     // [22.2.2.2.2] Stage 2, convert to char_type, using correct
01153     // numpunct.decimal_point() values for '.' and adding grouping.
01154     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01155     
01156     _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01157                                  * __len));
01158     __ctype.widen(__cs, __cs + __len, __ws);
01159     
01160     // Replace decimal point.
01161     _CharT* __wp = 0;
01162     const char* __p = char_traits<char>::find(__cs, __len, '.');
01163     if (__p)
01164       {
01165         __wp = __ws + (__p - __cs);
01166         *__wp = __lc->_M_decimal_point;
01167       }
01168     
01169     // Add grouping, if necessary.
01170     // N.B. Make sure to not group things like 2e20, i.e., no decimal
01171     // point, scientific notation.
01172     if (__lc->_M_use_grouping
01173         && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
01174                       && __cs[1] >= '0' && __cs[2] >= '0')))
01175       {
01176         // Grouping can add (almost) as many separators as the
01177         // number of digits, but no more.
01178         _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01179                                   * __len * 2));
01180         
01181         streamsize __off = 0;
01182         if (__cs[0] == '-' || __cs[0] == '+')
01183           {
01184         __off = 1;
01185         __ws2[0] = __ws[0];
01186         __len -= 1;
01187           }
01188         
01189         _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
01190                __lc->_M_thousands_sep, __wp, __ws2 + __off,
01191                __ws + __off, __len);
01192         __len += __off;
01193         
01194         __ws = __ws2;
01195       }
01196 
01197     // Pad.
01198     const streamsize __w = __io.width();
01199     if (__w > static_cast<streamsize>(__len))
01200       {
01201         _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01202                                   * __w));
01203         _M_pad(__fill, __w, __io, __ws3, __ws, __len);
01204         __ws = __ws3;
01205       }
01206     __io.width(0);
01207     
01208     // [22.2.2.2.2] Stage 4.
01209     // Write resulting, fully-formatted string to output iterator.
01210     return std::__write(__s, __ws, __len);
01211       }
01212   
01213   template<typename _CharT, typename _OutIter>
01214     _OutIter
01215     num_put<_CharT, _OutIter>::
01216     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
01217     {
01218       const ios_base::fmtflags __flags = __io.flags();
01219       if ((__flags & ios_base::boolalpha) == 0)
01220         {
01221           const long __l = __v;
01222           __s = _M_insert_int(__s, __io, __fill, __l);
01223         }
01224       else
01225         {
01226       typedef __numpunct_cache<_CharT>              __cache_type;
01227       __use_cache<__cache_type> __uc;
01228       const locale& __loc = __io._M_getloc();
01229       const __cache_type* __lc = __uc(__loc);
01230 
01231       const _CharT* __name = __v ? __lc->_M_truename
01232                                  : __lc->_M_falsename;
01233       int __len = __v ? __lc->_M_truename_size
01234                       : __lc->_M_falsename_size;
01235 
01236       const streamsize __w = __io.width();
01237       if (__w > static_cast<streamsize>(__len))
01238         {
01239           _CharT* __cs
01240         = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01241                             * __w));
01242           _M_pad(__fill, __w, __io, __cs, __name, __len);
01243           __name = __cs;
01244         }
01245       __io.width(0);
01246       __s = std::__write(__s, __name, __len);
01247     }
01248       return __s;
01249     }
01250 
01251   template<typename _CharT, typename _OutIter>
01252     _OutIter
01253     num_put<_CharT, _OutIter>::
01254     do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
01255     { return _M_insert_int(__s, __io, __fill, __v); }
01256 
01257   template<typename _CharT, typename _OutIter>
01258     _OutIter
01259     num_put<_CharT, _OutIter>::
01260     do_put(iter_type __s, ios_base& __io, char_type __fill,
01261            unsigned long __v) const
01262     { return _M_insert_int(__s, __io, __fill, __v); }
01263 
01264 #ifdef _GLIBCXX_USE_LONG_LONG
01265   template<typename _CharT, typename _OutIter>
01266     _OutIter
01267     num_put<_CharT, _OutIter>::
01268     do_put(iter_type __s, ios_base& __io, char_type __fill, long long __v) const
01269     { return _M_insert_int(__s, __io, __fill, __v); }
01270 
01271   template<typename _CharT, typename _OutIter>
01272     _OutIter
01273     num_put<_CharT, _OutIter>::
01274     do_put(iter_type __s, ios_base& __io, char_type __fill,
01275            unsigned long long __v) const
01276     { return _M_insert_int(__s, __io, __fill, __v); }
01277 #endif
01278 
01279   template<typename _CharT, typename _OutIter>
01280     _OutIter
01281     num_put<_CharT, _OutIter>::
01282     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
01283     { return _M_insert_float(__s, __io, __fill, char(), __v); }
01284 
01285 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
01286   template<typename _CharT, typename _OutIter>
01287     _OutIter
01288     num_put<_CharT, _OutIter>::
01289     __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
01290     { return _M_insert_float(__s, __io, __fill, char(), __v); }
01291 #endif
01292 
01293   template<typename _CharT, typename _OutIter>
01294     _OutIter
01295     num_put<_CharT, _OutIter>::
01296     do_put(iter_type __s, ios_base& __io, char_type __fill,
01297        long double __v) const
01298     { return _M_insert_float(__s, __io, __fill, 'L', __v); }
01299 
01300   template<typename _CharT, typename _OutIter>
01301     _OutIter
01302     num_put<_CharT, _OutIter>::
01303     do_put(iter_type __s, ios_base& __io, char_type __fill,
01304            const void* __v) const
01305     {
01306       const ios_base::fmtflags __flags = __io.flags();
01307       const ios_base::fmtflags __fmt = ~(ios_base::basefield
01308                      | ios_base::uppercase
01309                      | ios_base::internal);
01310       __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
01311 
01312       __s = _M_insert_int(__s, __io, __fill,
01313               reinterpret_cast<unsigned long>(__v));
01314       __io.flags(__flags);
01315       return __s;
01316     }
01317 
01318   template<typename _CharT, typename _InIter>
01319     template<bool _Intl>
01320       _InIter
01321       money_get<_CharT, _InIter>::
01322       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
01323          ios_base::iostate& __err, string& __units) const
01324       {
01325     typedef char_traits<_CharT>           __traits_type;
01326     typedef typename string_type::size_type           size_type;    
01327     typedef money_base::part              part;
01328     typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
01329     
01330     const locale& __loc = __io._M_getloc();
01331     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01332 
01333     __use_cache<__cache_type> __uc;
01334     const __cache_type* __lc = __uc(__loc);
01335     const char_type* __lit = __lc->_M_atoms;
01336 
01337     // Deduced sign.
01338     bool __negative = false;
01339     // Sign size.
01340     size_type __sign_size = 0;
01341     // True if sign is mandatory.
01342     const bool __mandatory_sign = (__lc->_M_positive_sign_size
01343                        && __lc->_M_negative_sign_size);
01344     // String of grouping info from thousands_sep plucked from __units.
01345     string __grouping_tmp;
01346     if (__lc->_M_use_grouping)
01347       __grouping_tmp.reserve(32);
01348     // Last position before the decimal point.
01349     int __last_pos = 0;
01350     // Separator positions, then, possibly, fractional digits.
01351     int __n = 0;
01352     // If input iterator is in a valid state.
01353     bool __testvalid = true;
01354     // Flag marking when a decimal point is found.
01355     bool __testdecfound = false;
01356 
01357     // The tentative returned string is stored here.
01358     string __res;
01359     __res.reserve(32);
01360 
01361     const char_type* __lit_zero = __lit + money_base::_S_zero;
01362     const money_base::pattern __p = __lc->_M_neg_format;
01363     for (int __i = 0; __i < 4 && __testvalid; ++__i)
01364       {
01365         const part __which = static_cast<part>(__p.field[__i]);
01366         switch (__which)
01367           {
01368           case money_base::symbol:
01369         // According to 22.2.6.1.2, p2, symbol is required
01370         // if (__io.flags() & ios_base::showbase), otherwise
01371         // is optional and consumed only if other characters
01372         // are needed to complete the format.
01373         if (__io.flags() & ios_base::showbase || __sign_size > 1
01374             || __i == 0
01375             || (__i == 1 && (__mandatory_sign
01376                      || (static_cast<part>(__p.field[0])
01377                      == money_base::sign)
01378                      || (static_cast<part>(__p.field[2])
01379                      == money_base::space)))
01380             || (__i == 2 && ((static_cast<part>(__p.field[3])
01381                       == money_base::value)
01382                      || __mandatory_sign
01383                      && (static_cast<part>(__p.field[3])
01384                      == money_base::sign))))
01385           {
01386             const size_type __len = __lc->_M_curr_symbol_size;
01387             size_type __j = 0;
01388             for (; __beg != __end && __j < __len
01389                && *__beg == __lc->_M_curr_symbol[__j];
01390              ++__beg, ++__j);
01391             if (__j != __len
01392             && (__j || __io.flags() & ios_base::showbase))
01393               __testvalid = false;
01394           }
01395         break;
01396           case money_base::sign:
01397         // Sign might not exist, or be more than one character long.
01398         if (__lc->_M_positive_sign_size && __beg != __end
01399             && *__beg == __lc->_M_positive_sign[0])
01400           {
01401             __sign_size = __lc->_M_positive_sign_size;
01402             ++__beg;
01403           }
01404         else if (__lc->_M_negative_sign_size && __beg != __end
01405              && *__beg == __lc->_M_negative_sign[0])
01406           {
01407             __negative = true;
01408             __sign_size = __lc->_M_negative_sign_size;
01409             ++__beg;
01410           }
01411         else if (__lc->_M_positive_sign_size
01412              && !__lc->_M_negative_sign_size)
01413           // "... if no sign is detected, the result is given the sign
01414           // that corresponds to the source of the empty string"
01415           __negative = true;
01416         else if (__mandatory_sign)
01417           __testvalid = false;
01418         break;
01419           case money_base::value:
01420         // Extract digits, remove and stash away the
01421         // grouping of found thousands separators.
01422         for (; __beg != __end; ++__beg)
01423           {
01424             const char_type __c = *__beg;
01425             const char_type* __q = __traits_type::find(__lit_zero, 
01426                                    10, __c);
01427             if (__q != 0)
01428               {
01429             __res += money_base::_S_atoms[__q - __lit];
01430             ++__n;
01431               }
01432             else if (__c == __lc->_M_decimal_point 
01433                  && !__testdecfound)
01434               {
01435             __last_pos = __n;
01436             __n = 0;
01437             __testdecfound = true;
01438               }
01439             else if (__lc->_M_use_grouping
01440                  && __c == __lc->_M_thousands_sep
01441                  && !__testdecfound)
01442               {
01443             if (__n)
01444               {
01445                 // Mark position for later analysis.
01446                 __grouping_tmp += static_cast<char>(__n);
01447                 __n = 0;
01448               }
01449             else
01450               {
01451                 __testvalid = false;
01452                 break;
01453               }
01454               }
01455             else
01456               break;
01457           }
01458         if (__res.empty())
01459           __testvalid = false;
01460         break;
01461           case money_base::space:
01462         // At least one space is required.
01463         if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
01464           ++__beg;
01465         else
01466           __testvalid = false;
01467           case money_base::none:
01468         // Only if not at the end of the pattern.
01469         if (__i != 3)
01470           for (; __beg != __end
01471              && __ctype.is(ctype_base::space, *__beg); ++__beg);
01472         break;
01473           }
01474       }
01475 
01476     // Need to get the rest of the sign characters, if they exist.
01477     if (__sign_size > 1 && __testvalid)
01478       {
01479         const char_type* __sign = __negative ? __lc->_M_negative_sign
01480                                              : __lc->_M_positive_sign;
01481         size_type __i = 1;
01482         for (; __beg != __end && __i < __sign_size
01483            && *__beg == __sign[__i]; ++__beg, ++__i);
01484         
01485         if (__i != __sign_size)
01486           __testvalid = false;
01487       }
01488 
01489     if (__testvalid)
01490       {
01491         // Strip leading zeros.
01492         if (__res.size() > 1)
01493           {
01494         const size_type __first = __res.find_first_not_of('0');
01495         const bool __only_zeros = __first == string::npos;
01496         if (__first)
01497           __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
01498           }
01499 
01500         // 22.2.6.1.2, p4
01501         if (__negative && __res[0] != '0')
01502           __res.insert(__res.begin(), '-');
01503         
01504         // Test for grouping fidelity.
01505         if (__grouping_tmp.size())
01506           {
01507         // Add the ending grouping.
01508         __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
01509                                            : __n);
01510         if (!std::__verify_grouping(__lc->_M_grouping,
01511                         __lc->_M_grouping_size,
01512                         __grouping_tmp))
01513           __err |= ios_base::failbit;
01514           }
01515         
01516         // Iff not enough digits were supplied after the decimal-point.
01517         if (__testdecfound && __lc->_M_frac_digits > 0
01518         && __n != __lc->_M_frac_digits)
01519           __testvalid = false;
01520       }
01521     
01522     // Iff valid sequence is not recognized.
01523     if (!__testvalid)
01524       __err |= ios_base::failbit;
01525     else
01526       __units.swap(__res);
01527     
01528     // Iff no more characters are available.
01529     if (__beg == __end)
01530       __err |= ios_base::eofbit;
01531     return __beg;
01532       }
01533 
01534 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
01535   template<typename _CharT, typename _InIter>
01536     _InIter
01537     money_get<_CharT, _InIter>::
01538     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
01539          ios_base::iostate& __err, double& __units) const
01540     {
01541       string __str;
01542       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
01543                      : _M_extract<false>(__beg, __end, __io, __err, __str);
01544       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
01545       return __beg;
01546     }
01547 #endif
01548 
01549   template<typename _CharT, typename _InIter>
01550     _InIter
01551     money_get<_CharT, _InIter>::
01552     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
01553        ios_base::iostate& __err, long double& __units) const
01554     {
01555       string __str;
01556       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
01557                  : _M_extract<false>(__beg, __end, __io, __err, __str);
01558       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
01559       return __beg;
01560     }
01561 
01562   template<typename _CharT, typename _InIter>
01563     _InIter
01564     money_get<_CharT, _InIter>::
01565     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
01566        ios_base::iostate& __err, string_type& __digits) const
01567     {
01568       typedef typename string::size_type                  size_type;
01569 
01570       const locale& __loc = __io._M_getloc();
01571       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01572 
01573       string __str;
01574       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
01575                  : _M_extract<false>(__beg, __end, __io, __err, __str);
01576       const size_type __len = __str.size();
01577       if (__len)
01578     {
01579       __digits.resize(__len);
01580       __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
01581     }
01582       return __beg;
01583     }
01584 
01585   template<typename _CharT, typename _OutIter>
01586     template<bool _Intl>
01587       _OutIter
01588       money_put<_CharT, _OutIter>::
01589       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
01590         const string_type& __digits) const
01591       {
01592     typedef typename string_type::size_type           size_type;
01593     typedef money_base::part                          part;
01594     typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
01595       
01596     const locale& __loc = __io._M_getloc();
01597     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01598 
01599     __use_cache<__cache_type> __uc;
01600     const __cache_type* __lc = __uc(__loc);
01601     const char_type* __lit = __lc->_M_atoms;
01602 
01603     // Determine if negative or positive formats are to be used, and
01604     // discard leading negative_sign if it is present.
01605     const char_type* __beg = __digits.data();
01606 
01607     money_base::pattern __p;
01608     const char_type* __sign;
01609     size_type __sign_size;
01610     if (!(*__beg == __lit[money_base::_S_minus]))
01611       {
01612         __p = __lc->_M_pos_format;
01613         __sign = __lc->_M_positive_sign;
01614         __sign_size = __lc->_M_positive_sign_size;
01615       }
01616     else
01617       {
01618         __p = __lc->_M_neg_format;
01619         __sign = __lc->_M_negative_sign;
01620         __sign_size = __lc->_M_negative_sign_size;
01621         if (__digits.size())
01622           ++__beg;
01623       }
01624        
01625     // Look for valid numbers in the ctype facet within input digits.
01626     size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
01627                        __beg + __digits.size()) - __beg;
01628     if (__len)
01629       {
01630         // Assume valid input, and attempt to format.
01631         // Break down input numbers into base components, as follows:
01632         //   final_value = grouped units + (decimal point) + (digits)
01633         string_type __value;
01634         __value.reserve(2 * __len);
01635 
01636         // Add thousands separators to non-decimal digits, per
01637         // grouping rules.
01638         long __paddec = __len - __lc->_M_frac_digits;
01639         if (__paddec > 0)
01640           {
01641         if (__lc->_M_frac_digits < 0)
01642           __paddec = __len;
01643         if (__lc->_M_grouping_size)
01644           {
01645             __value.assign(2 * __paddec, char_type());
01646             _CharT* __vend = 
01647               std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
01648                       __lc->_M_grouping,
01649                       __lc->_M_grouping_size,
01650                       __beg, __beg + __paddec);
01651             __value.erase(__vend - &__value[0]);
01652           }
01653         else
01654           __value.assign(__beg, __paddec);
01655           }
01656 
01657         // Deal with decimal point, decimal digits.
01658         if (__lc->_M_frac_digits > 0)
01659           {
01660         __value += __lc->_M_decimal_point;
01661         if (__paddec >= 0)
01662           __value.append(__beg + __paddec, __lc->_M_frac_digits);
01663         else
01664           {
01665             // Have to pad zeros in the decimal position.
01666             __value.append(-__paddec, __lit[money_base::_S_zero]);
01667             __value.append(__beg, __len);
01668           }
01669           }
01670   
01671         // Calculate length of resulting string.
01672         const ios_base::fmtflags __f = __io.flags() 
01673                                        & ios_base::adjustfield;
01674         __len = __value.size() + __sign_size;
01675         __len += ((__io.flags() & ios_base::showbase)
01676               ? __lc->_M_curr_symbol_size : 0);
01677 
01678         string_type __res;
01679         __res.reserve(2 * __len);
01680         
01681         const size_type __width = static_cast<size_type>(__io.width());  
01682         const bool __testipad = (__f == ios_base::internal
01683                      && __len < __width);
01684         // Fit formatted digits into the required pattern.
01685         for (int __i = 0; __i < 4; ++__i)
01686           {
01687         const part __which = static_cast<part>(__p.field[__i]);
01688         switch (__which)
01689           {
01690           case money_base::symbol:
01691             if (__io.flags() & ios_base::showbase)
01692               __res.append(__lc->_M_curr_symbol,
01693                    __lc->_M_curr_symbol_size);
01694             break;
01695           case money_base::sign:
01696             // Sign might not exist, or be more than one
01697             // charater long. In that case, add in the rest
01698             // below.
01699             if (__sign_size)
01700               __res += __sign[0];
01701             break;
01702           case money_base::value:
01703             __res += __value;
01704             break;
01705           case money_base::space:
01706             // At least one space is required, but if internal
01707             // formatting is required, an arbitrary number of
01708             // fill spaces will be necessary.
01709             if (__testipad)
01710               __res.append(__width - __len, __fill);
01711             else
01712               __res += __fill;
01713             break;
01714           case money_base::none:
01715             if (__testipad)
01716               __res.append(__width - __len, __fill);
01717             break;
01718           }
01719           }
01720         
01721         // Special case of multi-part sign parts.
01722         if (__sign_size > 1)
01723           __res.append(__sign + 1, __sign_size - 1);
01724         
01725         // Pad, if still necessary.
01726         __len = __res.size();
01727         if (__width > __len)
01728           {
01729         if (__f == ios_base::left)
01730           // After.
01731           __res.append(__width - __len, __fill);
01732         else
01733           // Before.
01734           __res.insert(0, __width - __len, __fill);
01735         __len = __width;
01736           }
01737         
01738         // Write resulting, fully-formatted string to output iterator.
01739         __s = std::__write(__s, __res.data(), __len);
01740       }
01741     __io.width(0);
01742     return __s;    
01743       }
01744 
01745 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
01746   template<typename _CharT, typename _OutIter>
01747     _OutIter
01748     money_put<_CharT, _OutIter>::
01749     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01750          double __units) const
01751     { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
01752 #endif
01753 
01754   template<typename _CharT, typename _OutIter>
01755     _OutIter
01756     money_put<_CharT, _OutIter>::
01757     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01758        long double __units) const
01759     {
01760       const locale __loc = __io.getloc();
01761       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01762 #ifdef _GLIBCXX_USE_C99
01763       // First try a buffer perhaps big enough.
01764       int __cs_size = 64;
01765       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01766       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01767       // 328. Bad sprintf format modifier in money_put<>::do_put()
01768       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
01769                     "%.*Lf", 0, __units);
01770       // If the buffer was not large enough, try again with the correct size.
01771       if (__len >= __cs_size)
01772     {
01773       __cs_size = __len + 1;
01774       __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01775       __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
01776                     "%.*Lf", 0, __units);
01777     }
01778 #else
01779       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
01780       const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
01781       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01782       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
01783                     0, __units);
01784 #endif
01785       string_type __digits(__len, char_type());
01786       __ctype.widen(__cs, __cs + __len, &__digits[0]);
01787       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
01788                 : _M_insert<false>(__s, __io, __fill, __digits);
01789     }
01790 
01791   template<typename _CharT, typename _OutIter>
01792     _OutIter
01793     money_put<_CharT, _OutIter>::
01794     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01795        const string_type& __digits) const
01796     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
01797                 : _M_insert<false>(__s, __io, __fill, __digits); }
01798 
01799 _GLIBCXX_END_LDBL_NAMESPACE
01800 
01801   // NB: Not especially useful. Without an ios_base object or some
01802   // kind of locale reference, we are left clawing at the air where
01803   // the side of the mountain used to be...
01804   template<typename _CharT, typename _InIter>
01805     time_base::dateorder
01806     time_get<_CharT, _InIter>::do_date_order() const
01807     { return time_base::no_order; }
01808 
01809   // Expand a strftime format string and parse it.  E.g., do_get_date() may
01810   // pass %m/%d/%Y => extracted characters.
01811   template<typename _CharT, typename _InIter>
01812     _InIter
01813     time_get<_CharT, _InIter>::
01814     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
01815               ios_base::iostate& __err, tm* __tm,
01816               const _CharT* __format) const
01817     {
01818       const locale& __loc = __io._M_getloc();
01819       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01820       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01821       const size_t __len = char_traits<_CharT>::length(__format);
01822 
01823       ios_base::iostate __tmperr = ios_base::goodbit;
01824       for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
01825     {
01826       if (__ctype.narrow(__format[__i], 0) == '%')
01827         {
01828           // Verify valid formatting code, attempt to extract.
01829           char __c = __ctype.narrow(__format[++__i], 0);
01830           int __mem = 0;
01831           if (__c == 'E' || __c == 'O')
01832         __c = __ctype.narrow(__format[++__i], 0);
01833           switch (__c)
01834         {
01835           const char* __cs;
01836           _CharT __wcs[10];
01837         case 'a':
01838           // Abbreviated weekday name [tm_wday]
01839           const char_type*  __days1[7];
01840           __tp._M_days_abbreviated(__days1);
01841           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
01842                       7, __io, __tmperr);
01843           break;
01844         case 'A':
01845           // Weekday name [tm_wday].
01846           const char_type*  __days2[7];
01847           __tp._M_days(__days2);
01848           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
01849                       7, __io, __tmperr);
01850           break;
01851         case 'h':
01852         case 'b':
01853           // Abbreviated month name [tm_mon]
01854           const char_type*  __months1[12];
01855           __tp._M_months_abbreviated(__months1);
01856           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
01857                       __months1, 12, __io, __tmperr);
01858           break;
01859         case 'B':
01860           // Month name [tm_mon].
01861           const char_type*  __months2[12];
01862           __tp._M_months(__months2);
01863           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
01864                       __months2, 12, __io, __tmperr);
01865           break;
01866         case 'c':
01867           // Default time and date representation.
01868           const char_type*  __dt[2];
01869           __tp._M_date_time_formats(__dt);
01870           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
01871                         __tm, __dt[0]);
01872           break;
01873         case 'd':
01874           // Day [01, 31]. [tm_mday]
01875           __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
01876                      __io, __tmperr);
01877           break;
01878         case 'e':
01879           // Day [1, 31], with single digits preceded by
01880           // space. [tm_mday]
01881           if (__ctype.is(ctype_base::space, *__beg))
01882             __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
01883                        1, __io, __tmperr);
01884           else
01885             __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
01886                        2, __io, __tmperr);
01887           break;
01888         case 'D':
01889           // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
01890           __cs = "%m/%d/%y";
01891           __ctype.widen(__cs, __cs + 9, __wcs);
01892           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
01893                         __tm, __wcs);
01894           break;
01895         case 'H':
01896           // Hour [00, 23]. [tm_hour]
01897           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
01898                      __io, __tmperr);
01899           break;
01900         case 'I':
01901           // Hour [01, 12]. [tm_hour]
01902           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
01903                      __io, __tmperr);
01904           break;
01905         case 'm':
01906           // Month [01, 12]. [tm_mon]
01907           __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
01908                      __io, __tmperr);
01909           if (!__tmperr)
01910             __tm->tm_mon = __mem - 1;
01911           break;
01912         case 'M':
01913           // Minute [00, 59]. [tm_min]
01914           __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
01915                      __io, __tmperr);
01916           break;
01917         case 'n':
01918           if (__ctype.narrow(*__beg, 0) == '\n')
01919             ++__beg;
01920           else
01921             __tmperr |= ios_base::failbit;
01922           break;
01923         case 'R':
01924           // Equivalent to (%H:%M).
01925           __cs = "%H:%M";
01926           __ctype.widen(__cs, __cs + 6, __wcs);
01927           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
01928                         __tm, __wcs);
01929           break;
01930         case 'S':
01931           // Seconds. [tm_sec]
01932           // [00, 60] in C99 (one leap-second), [00, 61] in C89.
01933 #ifdef _GLIBCXX_USE_C99
01934           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
01935 #else
01936           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
01937 #endif
01938                      __io, __tmperr);
01939           break;
01940         case 't':
01941           if (__ctype.narrow(*__beg, 0) == '\t')
01942             ++__beg;
01943           else
01944             __tmperr |= ios_base::failbit;
01945           break;
01946         case 'T':
01947           // Equivalent to (%H:%M:%S).
01948           __cs = "%H:%M:%S";
01949           __ctype.widen(__cs, __cs + 9, __wcs);
01950           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
01951                         __tm, __wcs);
01952           break;
01953         case 'x':
01954           // Locale's date.
01955           const char_type*  __dates[2];
01956           __tp._M_date_formats(__dates);
01957           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
01958                         __tm, __dates[0]);
01959           break;
01960         case 'X':
01961           // Locale's time.
01962           const char_type*  __times[2];
01963           __tp._M_time_formats(__times);
01964           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
01965                         __tm, __times[0]);
01966           break;
01967         case 'y':
01968         case 'C': // C99
01969           // Two digit year. [tm_year]
01970           __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
01971                      __io, __tmperr);
01972           break;
01973         case 'Y':
01974           // Year [1900). [tm_year]
01975           __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
01976                      __io, __tmperr);
01977           if (!__tmperr)
01978             __tm->tm_year = __mem - 1900;
01979           break;
01980         case 'Z':
01981           // Timezone info.
01982           if (__ctype.is(ctype_base::upper, *__beg))
01983             {
01984               int __tmp;
01985               __beg = _M_extract_name(__beg, __end, __tmp,
01986                        __timepunct_cache<_CharT>::_S_timezones,
01987                           14, __io, __tmperr);
01988 
01989               // GMT requires special effort.
01990               if (__beg != __end && !__tmperr && __tmp == 0
01991               && (*__beg == __ctype.widen('-')
01992                   || *__beg == __ctype.widen('+')))
01993             {
01994               __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
01995                          __io, __tmperr);
01996               __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
01997                          __io, __tmperr);
01998             }
01999             }
02000           else
02001             __tmperr |= ios_base::failbit;
02002           break;
02003         default:
02004           // Not recognized.
02005           __tmperr |= ios_base::failbit;
02006         }
02007         }
02008       else
02009         {
02010           // Verify format and input match, extract and discard.
02011           if (__format[__i] == *__beg)
02012         ++__beg;
02013           else
02014         __tmperr |= ios_base::failbit;
02015         }
02016     }
02017 
02018       if (__tmperr)
02019     __err |= ios_base::failbit;
02020   
02021       return __beg;
02022     }
02023 
02024   template<typename _CharT, typename _InIter>
02025     _InIter
02026     time_get<_CharT, _InIter>::
02027     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
02028            int __min, int __max, size_t __len,
02029            ios_base& __io, ios_base::iostate& __err) const
02030     {
02031       const locale& __loc = __io._M_getloc();
02032       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02033 
02034       // As-is works for __len = 1, 2, 4, the values actually used.
02035       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
02036 
02037       ++__min;
02038       size_t __i = 0;
02039       int __value = 0;
02040       for (; __beg != __end && __i < __len; ++__beg, ++__i)
02041     {
02042       const char __c = __ctype.narrow(*__beg, '*');
02043       if (__c >= '0' && __c <= '9')
02044         {
02045           __value = __value * 10 + (__c - '0');
02046           const int __valuec = __value * __mult;
02047           if (__valuec > __max || __valuec + __mult < __min)
02048         break;
02049           __mult /= 10;
02050         }
02051       else
02052         break;
02053     }
02054       if (__i == __len)
02055     __member = __value;
02056       else
02057     __err |= ios_base::failbit;
02058 
02059       return __beg;
02060     }
02061 
02062   // Assumptions:
02063   // All elements in __names are unique.
02064   template<typename _CharT, typename _InIter>
02065     _InIter
02066     time_get<_CharT, _InIter>::
02067     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
02068             const _CharT** __names, size_t __indexlen,
02069             ios_base& __io, ios_base::iostate& __err) const
02070     {
02071       typedef char_traits<_CharT>       __traits_type;
02072       const locale& __loc = __io._M_getloc();
02073       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02074 
02075       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
02076                               * __indexlen));
02077       size_t __nmatches = 0;
02078       size_t __pos = 0;
02079       bool __testvalid = true;
02080       const char_type* __name;
02081 
02082       // Look for initial matches.
02083       // NB: Some of the locale data is in the form of all lowercase
02084       // names, and some is in the form of initially-capitalized
02085       // names. Look for both.
02086       if (__beg != __end)
02087     {
02088       const char_type __c = *__beg;
02089       for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
02090         if (__c == __names[__i1][0]
02091         || __c == __ctype.toupper(__names[__i1][0]))
02092           __matches[__nmatches++] = __i1;
02093     }
02094 
02095       while (__nmatches > 1)
02096     {
02097       // Find smallest matching string.
02098       size_t __minlen = __traits_type::length(__names[__matches[0]]);
02099       for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
02100         __minlen = std::min(__minlen,
02101                   __traits_type::length(__names[__matches[__i2]]));
02102       ++__beg, ++__pos;
02103       if (__pos < __minlen && __beg != __end)
02104         for (size_t __i3 = 0; __i3 < __nmatches;)
02105           {
02106         __name = __names[__matches[__i3]];
02107         if (!(__name[__pos] == *__beg))
02108           __matches[__i3] = __matches[--__nmatches];
02109         else
02110           ++__i3;
02111           }
02112       else
02113         break;
02114     }
02115 
02116       if (__nmatches == 1)
02117     {
02118       // Make sure found name is completely extracted.
02119       ++__beg, ++__pos;
02120       __name = __names[__matches[0]];
02121       const size_t __len = __traits_type::length(__name);
02122       while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
02123         ++__beg, ++__pos;
02124 
02125       if (__len == __pos)
02126         __member = __matches[0];
02127       else
02128         __testvalid = false;
02129     }
02130       else
02131     __testvalid = false;
02132       if (!__testvalid)
02133     __err |= ios_base::failbit;
02134 
02135       return __beg;
02136     }
02137 
02138   template<typename _CharT, typename _InIter>
02139     _InIter
02140     time_get<_CharT, _InIter>::
02141     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
02142         ios_base::iostate& __err, tm* __tm) const
02143     {
02144       const locale& __loc = __io._M_getloc();
02145       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02146       const char_type*  __times[2];
02147       __tp._M_time_formats(__times);
02148       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
02149                     __tm, __times[0]);
02150       if (__beg == __end)
02151     __err |= ios_base::eofbit;
02152       return __beg;
02153     }
02154 
02155   template<typename _CharT, typename _InIter>
02156     _InIter
02157     time_get<_CharT, _InIter>::
02158     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
02159         ios_base::iostate& __err, tm* __tm) const
02160     {
02161       const locale& __loc = __io._M_getloc();
02162       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02163       const char_type*  __dates[2];
02164       __tp._M_date_formats(__dates);
02165       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
02166                     __tm, __dates[0]);
02167       if (__beg == __end)
02168     __err |= ios_base::eofbit;
02169       return __beg;
02170     }
02171 
02172   template<typename _CharT, typename _InIter>
02173     _InIter
02174     time_get<_CharT, _InIter>::
02175     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
02176            ios_base::iostate& __err, tm* __tm) const
02177     {
02178       typedef char_traits<_CharT>       __traits_type;
02179       const locale& __loc = __io._M_getloc();
02180       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02181       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02182       const char_type*  __days[7];
02183       __tp._M_days_abbreviated(__days);
02184       int __tmpwday;
02185       ios_base::iostate __tmperr = ios_base::goodbit;
02186       __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
02187                   __io, __tmperr);
02188 
02189       // Check to see if non-abbreviated name exists, and extract.
02190       // NB: Assumes both _M_days and _M_days_abbreviated organized in
02191       // exact same order, first to last, such that the resulting
02192       // __days array with the same index points to a day, and that
02193       // day's abbreviated form.
02194       // NB: Also assumes that an abbreviated name is a subset of the name.
02195       if (!__tmperr && __beg != __end)
02196     {
02197       size_t __pos = __traits_type::length(__days[__tmpwday]);
02198       __tp._M_days(__days);
02199       const char_type* __name = __days[__tmpwday];
02200       if (__name[__pos] == *__beg)
02201         {
02202           // Extract the rest of it.
02203           const size_t __len = __traits_type::length(__name);
02204           while (__pos < __len && __beg != __end
02205              && __name[__pos] == *__beg)
02206         ++__beg, ++__pos;
02207           if (__len != __pos)
02208         __tmperr |= ios_base::failbit;
02209         }
02210     }
02211       if (!__tmperr)
02212     __tm->tm_wday = __tmpwday;
02213       else
02214     __err |= ios_base::failbit;
02215 
02216       if (__beg == __end)
02217     __err |= ios_base::eofbit;
02218       return __beg;
02219      }
02220 
02221   template<typename _CharT, typename _InIter>
02222     _InIter
02223     time_get<_CharT, _InIter>::
02224     do_get_monthname(iter_type __beg, iter_type __end,
02225                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
02226     {
02227       typedef char_traits<_CharT>       __traits_type;
02228       const locale& __loc = __io._M_getloc();
02229       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02230       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02231       const char_type*  __months[12];
02232       __tp._M_months_abbreviated(__months);
02233       int __tmpmon;
02234       ios_base::iostate __tmperr = ios_base::goodbit;
02235       __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
02236                   __io, __tmperr);
02237 
02238       // Check to see if non-abbreviated name exists, and extract.
02239       // NB: Assumes both _M_months and _M_months_abbreviated organized in
02240       // exact same order, first to last, such that the resulting
02241       // __months array with the same index points to a month, and that
02242       // month's abbreviated form.
02243       // NB: Also assumes that an abbreviated name is a subset of the name.
02244       if (!__tmperr && __beg != __end)
02245     {
02246       size_t __pos = __traits_type::length(__months[__tmpmon]);
02247       __tp._M_months(__months);
02248       const char_type* __name = __months[__tmpmon];
02249       if (__name[__pos] == *__beg)
02250         {
02251           // Extract the rest of it.
02252           const size_t __len = __traits_type::length(__name);
02253           while (__pos < __len && __beg != __end
02254              && __name[__pos] == *__beg)
02255         ++__beg, ++__pos;
02256           if (__len != __pos)
02257         __tmperr |= ios_base::failbit;
02258         }
02259     }
02260       if (!__tmperr)
02261     __tm->tm_mon = __tmpmon;
02262       else
02263     __err |= ios_base::failbit;
02264 
02265       if (__beg == __end)
02266     __err |= ios_base::eofbit;
02267       return __beg;
02268     }
02269 
02270   template<typename _CharT, typename _InIter>
02271     _InIter
02272     time_get<_CharT, _InIter>::
02273     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
02274         ios_base::iostate& __err, tm* __tm) const
02275     {
02276       const locale& __loc = __io._M_getloc();
02277       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02278 
02279       size_t __i = 0;
02280       int __value = 0;
02281       for (; __beg != __end && __i < 4; ++__beg, ++__i)
02282     {
02283       const char __c = __ctype.narrow(*__beg, '*');
02284       if (__c >= '0' && __c <= '9')
02285         __value = __value * 10 + (__c - '0');
02286       else
02287         break;
02288     }
02289       if (__i == 2 || __i == 4)
02290     __tm->tm_year = __i == 2 ? __value : __value - 1900;
02291       else
02292     __err |= ios_base::failbit;
02293 
02294       if (__beg == __end)
02295     __err |= ios_base::eofbit;
02296       return __beg;
02297     }
02298 
02299   template<typename _CharT, typename _OutIter>
02300     _OutIter
02301     time_put<_CharT, _OutIter>::
02302     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
02303     const _CharT* __beg, const _CharT* __end) const
02304     {
02305       const locale& __loc = __io._M_getloc();
02306       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
02307       for (; __beg != __end; ++__beg)
02308     if (__ctype.narrow(*__beg, 0) != '%')
02309       {
02310         *__s = *__beg;
02311         ++__s;
02312       }
02313     else if (++__beg != __end)
02314       {
02315         char __format;
02316         char __mod = 0;
02317         const char __c = __ctype.narrow(*__beg, 0);
02318         if (__c != 'E' && __c != 'O')
02319           __format = __c;
02320         else if (++__beg != __end)
02321           {
02322         __mod = __c;
02323         __format = __ctype.narrow(*__beg, 0);
02324           }
02325         else
02326           break;
02327         __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
02328       }
02329     else
02330       break;
02331       return __s;
02332     }
02333 
02334   template<typename _CharT, typename _OutIter>
02335     _OutIter
02336     time_put<_CharT, _OutIter>::
02337     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
02338        char __format, char __mod) const
02339     {
02340       const locale& __loc = __io._M_getloc();
02341       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
02342       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
02343 
02344       // NB: This size is arbitrary. Should this be a data member,
02345       // initialized at construction?
02346       const size_t __maxlen = 128;
02347       char_type* __res = 
02348        static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
02349 
02350       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
02351       // is possible that the format character will be longer than one
02352       // character. Possibilities include 'E' or 'O' followed by a
02353       // format character: if __mod is not the default argument, assume
02354       // it's a valid modifier.
02355       char_type __fmt[4];
02356       __fmt[0] = __ctype.widen('%');
02357       if (!__mod)
02358     {
02359       __fmt[1] = __format;
02360       __fmt[2] = char_type();
02361     }
02362       else
02363     {
02364       __fmt[1] = __mod;
02365       __fmt[2] = __format;
02366       __fmt[3] = char_type();
02367     }
02368 
02369       __tp._M_put(__res, __maxlen, __fmt, __tm);
02370 
02371       // Write resulting, fully-formatted string to output iterator.
02372       return std::__write(__s, __res, char_traits<char_type>::length(__res));
02373     }
02374 
02375   // Generic version does nothing.
02376   template<typename _CharT>
02377     int
02378     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
02379     { return 0; }
02380 
02381   // Generic version does nothing.
02382   template<typename _CharT>
02383     size_t
02384     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
02385     { return 0; }
02386 
02387   template<typename _CharT>
02388     int
02389     collate<_CharT>::
02390     do_compare(const _CharT* __lo1, const _CharT* __hi1,
02391            const _CharT* __lo2, const _CharT* __hi2) const
02392     {
02393       // strcoll assumes zero-terminated strings so we make a copy
02394       // and then put a zero at the end.
02395       const string_type __one(__lo1, __hi1);
02396       const string_type __two(__lo2, __hi2);
02397 
02398       const _CharT* __p = __one.c_str();
02399       const _CharT* __pend = __one.data() + __one.length();
02400       const _CharT* __q = __two.c_str();
02401       const _CharT* __qend = __two.data() + __two.length();
02402 
02403       // strcoll stops when it sees a nul character so we break
02404       // the strings into zero-terminated substrings and pass those
02405       // to strcoll.
02406       for (;;)
02407     {
02408       const int __res = _M_compare(__p, __q);
02409       if (__res)
02410         return __res;
02411 
02412       __p += char_traits<_CharT>::length(__p);
02413       __q += char_traits<_CharT>::length(__q);
02414       if (__p == __pend && __q == __qend)
02415         return 0;
02416       else if (__p == __pend)
02417         return -1;
02418       else if (__q == __qend)
02419         return 1;
02420 
02421       __p++;
02422       __q++;
02423     }
02424     }
02425 
02426   template<typename _CharT>
02427     typename collate<_CharT>::string_type
02428     collate<_CharT>::
02429     do_transform(const _CharT* __lo, const _CharT* __hi) const
02430     {
02431       string_type __ret;
02432 
02433       // strxfrm assumes zero-terminated strings so we make a copy
02434       const string_type __str(__lo, __hi);
02435 
02436       const _CharT* __p = __str.c_str();
02437       const _CharT* __pend = __str.data() + __str.length();
02438 
02439       size_t __len = (__hi - __lo) * 2;
02440 
02441       _CharT* __c = new _CharT[__len];
02442 
02443       try
02444     {
02445       // strxfrm stops when it sees a nul character so we break
02446       // the string into zero-terminated substrings and pass those
02447       // to strxfrm.
02448       for (;;)
02449         {
02450           // First try a buffer perhaps big enough.
02451           size_t __res = _M_transform(__c, __p, __len);
02452           // If the buffer was not large enough, try again with the
02453           // correct size.
02454           if (__res >= __len)
02455         {
02456           __len = __res + 1;
02457           delete [] __c, __c = 0;
02458           __c = new _CharT[__len];
02459           __res = _M_transform(__c, __p, __len);
02460         }
02461 
02462           __ret.append(__c, __res);
02463           __p += char_traits<_CharT>::length(__p);
02464           if (__p == __pend)
02465         break;
02466 
02467           __p++;
02468           __ret.push_back(_CharT());
02469         }
02470     }
02471       catch(...)
02472     {
02473       delete [] __c;
02474       __throw_exception_again;
02475     }
02476 
02477       delete [] __c;
02478 
02479       return __ret;
02480     }
02481 
02482   template<typename _CharT>
02483     long
02484     collate<_CharT>::
02485     do_hash(const _CharT* __lo, const _CharT* __hi) const
02486     {
02487       unsigned long __val = 0;
02488       for (; __lo < __hi; ++__lo)
02489     __val = *__lo + ((__val << 7) |
02490                (__val >> (numeric_limits<unsigned long>::digits - 7)));
02491       return static_cast<long>(__val);
02492     }
02493 
02494   // Construct correctly padded string, as per 22.2.2.2.2
02495   // Assumes
02496   // __newlen > __oldlen
02497   // __news is allocated for __newlen size
02498   // Used by both num_put and ostream inserters: if __num,
02499   // internal-adjusted objects are padded according to the rules below
02500   // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
02501   // ones are.
02502 
02503   // NB: Of the two parameters, _CharT can be deduced from the
02504   // function arguments. The other (_Traits) has to be explicitly specified.
02505   template<typename _CharT, typename _Traits>
02506     void
02507     __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
02508                    _CharT* __news, const _CharT* __olds,
02509                    const streamsize __newlen,
02510                    const streamsize __oldlen, const bool __num)
02511     {
02512       const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
02513       const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
02514 
02515       // Padding last.
02516       if (__adjust == ios_base::left)
02517     {
02518       _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
02519       _Traits::assign(__news + __oldlen, __plen, __fill);
02520       return;
02521     }
02522 
02523       size_t __mod = 0;
02524       if (__adjust == ios_base::internal && __num)
02525     {
02526       // Pad after the sign, if there is one.
02527       // Pad after 0[xX], if there is one.
02528       // Who came up with these rules, anyway? Jeeze.
02529           const locale& __loc = __io._M_getloc();
02530       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02531 
02532       const bool __testsign = (__ctype.widen('-') == __olds[0]
02533                    || __ctype.widen('+') == __olds[0]);
02534       const bool __testhex = (__ctype.widen('0') == __olds[0]
02535                   && __oldlen > 1
02536                   && (__ctype.widen('x') == __olds[1]
02537                       || __ctype.widen('X') == __olds[1]));
02538       if (__testhex)
02539         {
02540           __news[0] = __olds[0];
02541           __news[1] = __olds[1];
02542           __mod = 2;
02543           __news += 2;
02544         }
02545       else if (__testsign)
02546         {
02547           __news[0] = __olds[0];
02548           __mod = 1;
02549           ++__news;
02550         }
02551       // else Padding first.
02552     }
02553       _Traits::assign(__news, __plen, __fill);
02554       _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
02555             __oldlen - __mod);
02556     }
02557 
02558   bool
02559   __verify_grouping(const char* __grouping, size_t __grouping_size,
02560             const string& __grouping_tmp)
02561   {
02562     const size_t __n = __grouping_tmp.size() - 1;
02563     const size_t __min = std::min(__n, size_t(__grouping_size - 1));
02564     size_t __i = __n;
02565     bool __test = true;
02566     
02567     // Parsed number groupings have to match the
02568     // numpunct::grouping string exactly, starting at the
02569     // right-most point of the parsed sequence of elements ...
02570     for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
02571       __test = __grouping_tmp[__i] == __grouping[__j];
02572     for (; __i && __test; --__i)
02573       __test = __grouping_tmp[__i] == __grouping[__min];
02574     // ... but the first parsed grouping can be <= numpunct
02575     // grouping (only do the check if the numpunct char is > 0
02576     // because <= 0 means any size is ok).
02577     if (static_cast<signed char>(__grouping[__min]) > 0)
02578       __test &= __grouping_tmp[0] <= __grouping[__min];
02579     return __test;
02580   }
02581 
02582   template<typename _CharT>
02583     _CharT*
02584     __add_grouping(_CharT* __s, _CharT __sep,
02585            const char* __gbeg, size_t __gsize,
02586            const _CharT* __first, const _CharT* __last)
02587     {
02588       size_t __idx = 0;
02589       size_t __ctr = 0;
02590 
02591       while (__last - __first > __gbeg[__idx]
02592          && static_cast<signed char>(__gbeg[__idx]) > 0)
02593     {
02594       __last -= __gbeg[__idx];
02595       __idx < __gsize - 1 ? ++__idx : ++__ctr;
02596     }
02597 
02598       while (__first != __last)
02599     *__s++ = *__first++;
02600 
02601       while (__ctr--)
02602     {
02603       *__s++ = __sep;     
02604       for (char __i = __gbeg[__idx]; __i > 0; --__i)
02605         *__s++ = *__first++;
02606     }
02607 
02608       while (__idx--)
02609     {
02610       *__s++ = __sep;     
02611       for (char __i = __gbeg[__idx]; __i > 0; --__i)
02612         *__s++ = *__first++;
02613     }
02614 
02615       return __s;
02616     }
02617 
02618   // Inhibit implicit instantiations for required instantiations,
02619   // which are defined via explicit instantiations elsewhere.
02620   // NB: This syntax is a GNU extension.
02621 #if _GLIBCXX_EXTERN_TEMPLATE
02622   extern template class moneypunct<char, false>;
02623   extern template class moneypunct<char, true>;
02624   extern template class moneypunct_byname<char, false>;
02625   extern template class moneypunct_byname<char, true>;
02626   extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
02627   extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
02628   extern template class numpunct<char>;
02629   extern template class numpunct_byname<char>;
02630   extern template class _GLIBCXX_LDBL_NAMESPACE num_get<char>;
02631   extern template class _GLIBCXX_LDBL_NAMESPACE num_put<char>;
02632   extern template class __timepunct<char>;
02633   extern template class time_put<char>;
02634   extern template class time_put_byname<char>;
02635   extern template class time_get<char>;
02636   extern template class time_get_byname<char>;
02637   extern template class messages<char>;
02638   extern template class messages_byname<char>;
02639   extern template class ctype_byname<char>;
02640   extern template class codecvt_byname<char, char, mbstate_t>;
02641   extern template class collate<char>;
02642   extern template class collate_byname<char>;
02643 
02644   extern template
02645     const codecvt<char, char, mbstate_t>&
02646     use_facet<codecvt<char, char, mbstate_t> >(const locale&);
02647 
02648   extern template
02649     const collate<char>&
02650     use_facet<collate<char> >(const locale&);
02651 
02652   extern template
02653     const numpunct<char>&
02654     use_facet<numpunct<char> >(const locale&);
02655 
02656   extern template
02657     const num_put<char>&
02658     use_facet<num_put<char> >(const locale&);
02659 
02660   extern template
02661     const num_get<char>&
02662     use_facet<num_get<char> >(const locale&);
02663 
02664   extern template
02665     const moneypunct<char, true>&
02666     use_facet<moneypunct<char, true> >(const locale&);
02667 
02668   extern template
02669     const moneypunct<char, false>&
02670     use_facet<moneypunct<char, false> >(const locale&);
02671 
02672   extern template
02673     const money_put<char>&
02674     use_facet<money_put<char> >(const locale&);
02675 
02676   extern template
02677     const money_get<char>&
02678     use_facet<money_get<char> >(const locale&);
02679 
02680   extern template
02681     const __timepunct<char>&
02682     use_facet<__timepunct<char> >(const locale&);
02683 
02684   extern template
02685     const time_put<char>&
02686     use_facet<time_put<char> >(const locale&);
02687 
02688   extern template
02689     const time_get<char>&
02690     use_facet<time_get<char> >(const locale&);
02691 
02692   extern template
02693     const messages<char>&
02694     use_facet<messages<char> >(const locale&);
02695 
02696   extern template
02697     bool
02698     has_facet<ctype<char> >(const locale&);
02699 
02700   extern template
02701     bool
02702     has_facet<codecvt<char, char, mbstate_t> >(const locale&);
02703 
02704   extern template
02705     bool
02706     has_facet<collate<char> >(const locale&);
02707 
02708   extern template
02709     bool
02710     has_facet<numpunct<char> >(const locale&);
02711 
02712   extern template
02713     bool
02714     has_facet<num_put<char> >(const locale&);
02715 
02716   extern template
02717     bool
02718     has_facet<num_get<char> >(const locale&);
02719 
02720   extern template
02721     bool
02722     has_facet<moneypunct<char> >(const locale&);
02723 
02724   extern template
02725     bool
02726     has_facet<money_put<char> >(const locale&);
02727 
02728   extern template
02729     bool
02730     has_facet<money_get<char> >(const locale&);
02731 
02732   extern template
02733     bool
02734     has_facet<__timepunct<char> >(const locale&);
02735 
02736   extern template
02737     bool
02738     has_facet<time_put<char> >(const locale&);
02739 
02740   extern template
02741     bool
02742     has_facet<time_get<char> >(const locale&);
02743 
02744   extern template
02745     bool
02746     has_facet<messages<char> >(const locale&);
02747 
02748 #ifdef _GLIBCXX_USE_WCHAR_T
02749   extern template class moneypunct<wchar_t, false>;
02750   extern template class moneypunct<wchar_t, true>;
02751   extern template class moneypunct_byname<wchar_t, false>;
02752   extern template class moneypunct_byname<wchar_t, true>;
02753   extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
02754   extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
02755   extern template class numpunct<wchar_t>;
02756   extern template class numpunct_byname<wchar_t>;
02757   extern template class _GLIBCXX_LDBL_NAMESPACE num_get<wchar_t>;
02758   extern template class _GLIBCXX_LDBL_NAMESPACE num_put<wchar_t>;
02759   extern template class __timepunct<wchar_t>;
02760   extern template class time_put<wchar_t>;
02761   extern template class time_put_byname<wchar_t>;
02762   extern template class time_get<wchar_t>;
02763   extern template class time_get_byname<wchar_t>;
02764   extern template class messages<wchar_t>;
02765   extern template class messages_byname<wchar_t>;
02766   extern template class ctype_byname<wchar_t>;
02767   extern template class codecvt_byname<wchar_t, char, mbstate_t>;
02768   extern template class collate<wchar_t>;
02769   extern template class collate_byname<wchar_t>;
02770 
02771   extern template
02772     const codecvt<wchar_t, char, mbstate_t>&
02773     use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
02774 
02775   extern template
02776     const collate<wchar_t>&
02777     use_facet<collate<wchar_t> >(const locale&);
02778 
02779   extern template
02780     const numpunct<wchar_t>&
02781     use_facet<numpunct<wchar_t> >(const locale&);
02782 
02783   extern template
02784     const num_put<wchar_t>&
02785     use_facet<num_put<wchar_t> >(const locale&);
02786 
02787   extern template
02788     const num_get<wchar_t>&
02789     use_facet<num_get<wchar_t> >(const locale&);
02790 
02791   extern template
02792     const moneypunct<wchar_t, true>&
02793     use_facet<moneypunct<wchar_t, true> >(const locale&);
02794 
02795   extern template
02796     const moneypunct<wchar_t, false>&
02797     use_facet<moneypunct<wchar_t, false> >(const locale&);
02798 
02799   extern template
02800     const money_put<wchar_t>&
02801     use_facet<money_put<wchar_t> >(const locale&);
02802 
02803   extern template
02804     const money_get<wchar_t>&
02805     use_facet<money_get<wchar_t> >(const locale&);
02806 
02807   extern template
02808     const __timepunct<wchar_t>&
02809     use_facet<__timepunct<wchar_t> >(const locale&);
02810 
02811   extern template
02812     const time_put<wchar_t>&
02813     use_facet<time_put<wchar_t> >(const locale&);
02814 
02815   extern template
02816     const time_get<wchar_t>&
02817     use_facet<time_get<wchar_t> >(const locale&);
02818 
02819   extern template
02820     const messages<wchar_t>&
02821     use_facet<messages<wchar_t> >(const locale&);
02822 
02823  extern template
02824     bool
02825     has_facet<ctype<wchar_t> >(const locale&);
02826 
02827   extern template
02828     bool
02829     has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
02830 
02831   extern template
02832     bool
02833     has_facet<collate<wchar_t> >(const locale&);
02834 
02835   extern template
02836     bool
02837     has_facet<numpunct<wchar_t> >(const locale&);
02838 
02839   extern template
02840     bool
02841     has_facet<num_put<wchar_t> >(const locale&);
02842 
02843   extern template
02844     bool
02845     has_facet<num_get<wchar_t> >(const locale&);
02846 
02847   extern template
02848     bool
02849     has_facet<moneypunct<wchar_t> >(const locale&);
02850 
02851   extern template
02852     bool
02853     has_facet<money_put<wchar_t> >(const locale&);
02854 
02855   extern template
02856     bool
02857     has_facet<money_get<wchar_t> >(const locale&);
02858 
02859   extern template
02860     bool
02861     has_facet<__timepunct<wchar_t> >(const locale&);
02862 
02863   extern template
02864     bool
02865     has_facet<time_put<wchar_t> >(const locale&);
02866 
02867   extern template
02868     bool
02869     has_facet<time_get<wchar_t> >(const locale&);
02870 
02871   extern template
02872     bool
02873     has_facet<messages<wchar_t> >(const locale&);
02874 #endif
02875 #endif
02876 
02877 _GLIBCXX_END_NAMESPACE
02878 
02879 #endif

Generated on Fri Oct 10 19:33:28 2008 for libstdc++ by  doxygen 1.5.5