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

Generated on Thu Nov 1 13:12:04 2007 for libstdc++ by  doxygen 1.5.1