# locale_facets.tcc

Go to the documentation of this file.

    00001 // Locale support -*- C++ -*-
    00002
    00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    00004 // 2006, 2007
    00005 // Free Software Foundation, Inc.
    00006 //
    00007 // This file is part of the GNU ISO C++ Library.  This library is free
    00008 // software; you can redistribute it and/or modify it under the
    00009 // terms of the GNU General Public License as published by the
    00010 // Free Software Foundation; either version 2, or (at your option)
    00011 // any later version.
    00012
    00013 // This library is distributed in the hope that it will be useful,
    00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00016 // GNU General Public License for more details.
    00017
    00018 // You should have received a copy of the GNU General Public License along
    00019 // with this library; see the file COPYING.  If not, write to the Free
    00020 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
    00021 // USA.
    00022
    00023 // As a special exception, you may use this file as part of a free software
    00024 // library without restriction.  Specifically, if other files instantiate
    00025 // templates or use macros or inline functions from this file, or you compile
    00026 // this file and link it with other files to produce an executable, this
    00027 // file does not by itself cause the resulting executable to be covered by
    00028 // the GNU General Public License.  This exception does not however
    00029 // invalidate any other reasons why the executable file might be covered by
    00030 // the GNU General Public License.
    00031
    00032 /** @file locale_facets.tcc
    00033  *  This is an internal header file, included by other library headers.
    00034  *  You should not attempt to use it directly.
    00035  */
    00036
    00037 #ifndef _LOCALE_FACETS_TCC
    00038 #define _LOCALE_FACETS_TCC 1
    00039
    00040 #pragma GCC system_header
    00041
    00042 _GLIBCXX_BEGIN_NAMESPACE(std)
    00043
    00044   // Routine to access a cache for the facet.  If the cache didn't
    00045   // exist before, it gets constructed on the fly.
    00046   template<typename _Facet>
    00047     struct __use_cache
    00048     {
    00049       const _Facet*
    00050       operator() (const locale& __loc) const;
    00051     };
    00052
    00053   // Specializations.
    00054   template<typename _CharT>
    00055     struct __use_cache<__numpunct_cache<_CharT> >
    00056     {
    00057       const __numpunct_cache<_CharT>*
    00058       operator() (const locale& __loc) const
    00059       {
    00060     const size_t __i = numpunct<_CharT>::id._M_id();
    00061     const locale::facet** __caches = __loc._M_impl->_M_caches;
    00062     if (!__caches[__i])
    00063       {
    00064         __numpunct_cache<_CharT>* __tmp = NULL;
    00065         try
    00066           {
    00067         __tmp = new __numpunct_cache<_CharT>;
    00068         __tmp->_M_cache(__loc);
    00069           }
    00070         catch(...)
    00071           {
    00072         delete __tmp;
    00073         __throw_exception_again;
    00074           }
    00075         __loc._M_impl->_M_install_cache(__tmp, __i);
    00076       }
    00077     return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
    00078       }
    00079     };
    00080
    00081   template<typename _CharT>
    00082     void
    00083     __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
    00084     {
    00085       _M_allocated = true;
    00086
    00087       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
    00088
    00089       _M_grouping_size = __np.grouping().size();
    00090       char* __grouping = new char[_M_grouping_size];
    00091       __np.grouping().copy(__grouping, _M_grouping_size);
    00092       _M_grouping = __grouping;
    00093       _M_use_grouping = (_M_grouping_size
    00094              && static_cast<signed char>(__np.grouping()[0]) > 0);
    00095
    00096       _M_truename_size = __np.truename().size();
    00097       _CharT* __truename = new _CharT[_M_truename_size];
    00098       __np.truename().copy(__truename, _M_truename_size);
    00099       _M_truename = __truename;
    00100
    00101       _M_falsename_size = __np.falsename().size();
    00102       _CharT* __falsename = new _CharT[_M_falsename_size];
    00103       __np.falsename().copy(__falsename, _M_falsename_size);
    00104       _M_falsename = __falsename;
    00105
    00106       _M_decimal_point = __np.decimal_point();
    00107       _M_thousands_sep = __np.thousands_sep();
    00108
    00109       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
    00110       __ct.widen(__num_base::_S_atoms_out,
    00111          __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out);
    00112       __ct.widen(__num_base::_S_atoms_in,
    00113          __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in);
    00114     }
    00115
    00116   // Used by both numeric and monetary facets.
    00117   // Check to make sure that the __grouping_tmp string constructed in
    00118   // money_get or num_get matches the canonical grouping for a given
    00119   // locale.
    00120   // __grouping_tmp is parsed L to R
    00121   // 1,222,444 == __grouping_tmp of "\1\3\3"
    00122   // __grouping is parsed R to L
    00123   // 1,222,444 == __grouping of "\3" == "\3\3\3"
    00124   bool
    00125   __verify_grouping(const char* __grouping, size_t __grouping_size,
    00126             const string& __grouping_tmp);
    00127
    00128 _GLIBCXX_BEGIN_LDBL_NAMESPACE
    00129
    00130   template<typename _CharT, typename _InIter>
    00131     _InIter
    00132     num_get<_CharT, _InIter>::
    00133     _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
    00134              ios_base::iostate& __err, string& __xtrc) const
    00135     {
    00136       typedef char_traits<_CharT>           __traits_type;
    00137       typedef __numpunct_cache<_CharT>                  __cache_type;
    00138       __use_cache<__cache_type> __uc;
    00139       const locale& __loc = __io._M_getloc();
    00140       const __cache_type* __lc = __uc(__loc);
    00141       const _CharT* __lit = __lc->_M_atoms_in;
    00142       char_type __c = char_type();
    00143
    00144       // True if __beg becomes equal to __end.
    00145       bool __testeof = __beg == __end;
    00146
    00147       // First check for sign.
    00148       if (!__testeof)
    00149     {
    00150       __c = *__beg;
    00151       const bool __plus = __c == __lit[__num_base::_S_iplus];
    00152       if ((__plus || __c == __lit[__num_base::_S_iminus])
    00153           && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    00154           && !(__c == __lc->_M_decimal_point))
    00155         {
    00156           __xtrc += __plus ? '+' : '-';
    00157           if (++__beg != __end)
    00158         __c = *__beg;
    00159           else
    00160         __testeof = true;
    00161         }
    00162     }
    00163
    00164       // Next, look for leading zeros.
    00165       bool __found_mantissa = false;
    00166       int __sep_pos = 0;
    00167       while (!__testeof)
    00168     {
    00169       if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    00170           || __c == __lc->_M_decimal_point)
    00171         break;
    00172       else if (__c == __lit[__num_base::_S_izero])
    00173         {
    00174           if (!__found_mantissa)
    00175         {
    00176           __xtrc += '0';
    00177           __found_mantissa = true;
    00178         }
    00179           ++__sep_pos;
    00180
    00181           if (++__beg != __end)
    00182         __c = *__beg;
    00183           else
    00184         __testeof = true;
    00185         }
    00186       else
    00187         break;
    00188     }
    00189
    00190       // Only need acceptable digits for floating point numbers.
    00191       bool __found_dec = false;
    00192       bool __found_sci = false;
    00193       string __found_grouping;
    00194       if (__lc->_M_use_grouping)
    00195     __found_grouping.reserve(32);
    00196       const char_type* __lit_zero = __lit + __num_base::_S_izero;
    00197
    00198       if (!__lc->_M_allocated)
    00199     // "C" locale
    00200     while (!__testeof)
    00201       {
    00202         const int __digit = _M_find(__lit_zero, 10, __c);
    00203         if (__digit != -1)
    00204           {
    00205         __xtrc += '0' + __digit;
    00206         __found_mantissa = true;
    00207           }
    00208         else if (__c == __lc->_M_decimal_point
    00209              && !__found_dec && !__found_sci)
    00210           {
    00211         __xtrc += '.';
    00212         __found_dec = true;
    00213           }
    00214         else if ((__c == __lit[__num_base::_S_ie]
    00215               || __c == __lit[__num_base::_S_iE])
    00216              && !__found_sci && __found_mantissa)
    00217           {
    00218         // Scientific notation.
    00219         __xtrc += 'e';
    00220         __found_sci = true;
    00221
    00222         // Remove optional plus or minus sign, if they exist.
    00223         if (++__beg != __end)
    00224           {
    00225             __c = *__beg;
    00226             const bool __plus = __c == __lit[__num_base::_S_iplus];
    00227             if (__plus || __c == __lit[__num_base::_S_iminus])
    00228               __xtrc += __plus ? '+' : '-';
    00229             else
    00230               continue;
    00231           }
    00232         else
    00233           {
    00234             __testeof = true;
    00235             break;
    00236           }
    00237           }
    00238         else
    00239           break;
    00240
    00241         if (++__beg != __end)
    00242           __c = *__beg;
    00243         else
    00244           __testeof = true;
    00245       }
    00246       else
    00247     while (!__testeof)
    00248       {
    00249         // According to 22.2.2.1.2, p8-9, first look for thousands_sep
    00250         // and decimal_point.
    00251         if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    00252           {
    00253         if (!__found_dec && !__found_sci)
    00254           {
    00255             // NB: Thousands separator at the beginning of a string
    00256             // is a no-no, as is two consecutive thousands separators.
    00257             if (__sep_pos)
    00258               {
    00259             __found_grouping += static_cast<char>(__sep_pos);
    00260             __sep_pos = 0;
    00261               }
    00262             else
    00263               {
    00264             // NB: __convert_to_v will not assign __v and will
    00265             // set the failbit.
    00266             __xtrc.clear();
    00267             break;
    00268               }
    00269           }
    00270         else
    00271           break;
    00272           }
    00273         else if (__c == __lc->_M_decimal_point)
    00274           {
    00275         if (!__found_dec && !__found_sci)
    00276           {
    00277             // If no grouping chars are seen, no grouping check
    00278             // is applied. Therefore __found_grouping is adjusted
    00279             // only if decimal_point comes after some thousands_sep.
    00280             if (__found_grouping.size())
    00281               __found_grouping += static_cast<char>(__sep_pos);
    00282             __xtrc += '.';
    00283             __found_dec = true;
    00284           }
    00285         else
    00286           break;
    00287           }
    00288         else
    00289           {
    00290         const char_type* __q =
    00291           __traits_type::find(__lit_zero, 10, __c);
    00292         if (__q)
    00293           {
    00294             __xtrc += '0' + (__q - __lit_zero);
    00295             __found_mantissa = true;
    00296             ++__sep_pos;
    00297           }
    00298         else if ((__c == __lit[__num_base::_S_ie]
    00299               || __c == __lit[__num_base::_S_iE])
    00300              && !__found_sci && __found_mantissa)
    00301           {
    00302             // Scientific notation.
    00303             if (__found_grouping.size() && !__found_dec)
    00304               __found_grouping += static_cast<char>(__sep_pos);
    00305             __xtrc += 'e';
    00306             __found_sci = true;
    00307
    00308             // Remove optional plus or minus sign, if they exist.
    00309             if (++__beg != __end)
    00310               {
    00311             __c = *__beg;
    00312             const bool __plus = __c == __lit[__num_base::_S_iplus];
    00313             if ((__plus || __c == __lit[__num_base::_S_iminus])
    00314                 && !(__lc->_M_use_grouping
    00315                  && __c == __lc->_M_thousands_sep)
    00316                 && !(__c == __lc->_M_decimal_point))
    00317               __xtrc += __plus ? '+' : '-';
    00318             else
    00319               continue;
    00320               }
    00321             else
    00322               {
    00323             __testeof = true;
    00324             break;
    00325               }
    00326           }
    00327         else
    00328           break;
    00329           }
    00330
    00331         if (++__beg != __end)
    00332           __c = *__beg;
    00333         else
    00334           __testeof = true;
    00335       }
    00336
    00337       // Digit grouping is checked. If grouping and found_grouping don't
    00338       // match, then get very very upset, and set failbit.
    00339       if (__found_grouping.size())
    00340         {
    00341           // Add the ending grouping if a decimal or 'e'/'E' wasn't found.
    00342       if (!__found_dec && !__found_sci)
    00343         __found_grouping += static_cast<char>(__sep_pos);
    00344
    00345           if (!std::__verify_grouping(__lc->_M_grouping,
    00346                       __lc->_M_grouping_size,
    00347                       __found_grouping))
    00348         __err |= ios_base::failbit;
    00349         }
    00350
    00351       // Finish up.
    00352       if (__testeof)
    00353         __err |= ios_base::eofbit;
    00354       return __beg;
    00355     }
    00356
    00357   template<typename _CharT, typename _InIter>
    00358     template<typename _ValueT>
    00359       _InIter
    00360       num_get<_CharT, _InIter>::
    00361       _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
    00362              ios_base::iostate& __err, _ValueT& __v) const
    00363       {
    00364         typedef char_traits<_CharT>              __traits_type;
    00365     using __gnu_cxx::__add_unsigned;
    00366     typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
    00367     typedef __numpunct_cache<_CharT>                     __cache_type;
    00368     __use_cache<__cache_type> __uc;
    00369     const locale& __loc = __io._M_getloc();
    00370     const __cache_type* __lc = __uc(__loc);
    00371     const _CharT* __lit = __lc->_M_atoms_in;
    00372     char_type __c = char_type();
    00373
    00374     // NB: Iff __basefield == 0, __base can change based on contents.
    00375     const ios_base::fmtflags __basefield = __io.flags()
    00376                                            & ios_base::basefield;
    00377     const bool __oct = __basefield == ios_base::oct;
    00378     int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
    00379
    00380     // True if __beg becomes equal to __end.
    00381     bool __testeof = __beg == __end;
    00382
    00383     // First check for sign.
    00384     bool __negative = false;
    00385     if (!__testeof)
    00386       {
    00387         __c = *__beg;
    00388         if (__gnu_cxx::__numeric_traits<_ValueT>::__is_signed)
    00389           __negative = __c == __lit[__num_base::_S_iminus];
    00390         if ((__negative || __c == __lit[__num_base::_S_iplus])
    00391         && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    00392         && !(__c == __lc->_M_decimal_point))
    00393           {
    00394         if (++__beg != __end)
    00395           __c = *__beg;
    00396         else
    00397           __testeof = true;
    00398           }
    00399       }
    00400
    00401     // Next, look for leading zeros and check required digits
    00402     // for base formats.
    00403     bool __found_zero = false;
    00404     int __sep_pos = 0;
    00405     while (!__testeof)
    00406       {
    00407         if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    00408         || __c == __lc->_M_decimal_point)
    00409           break;
    00410         else if (__c == __lit[__num_base::_S_izero]
    00411              && (!__found_zero || __base == 10))
    00412           {
    00413         __found_zero = true;
    00414         ++__sep_pos;
    00415         if (__basefield == 0)
    00416           __base = 8;
    00417         if (__base == 8)
    00418           __sep_pos = 0;
    00419           }
    00420         else if (__found_zero
    00421              && (__c == __lit[__num_base::_S_ix]
    00422              || __c == __lit[__num_base::_S_iX]))
    00423           {
    00424         if (__basefield == 0)
    00425           __base = 16;
    00426         if (__base == 16)
    00427           {
    00428             __found_zero = false;
    00429             __sep_pos = 0;
    00430           }
    00431         else
    00432           break;
    00433           }
    00434         else
    00435           break;
    00436
    00437         if (++__beg != __end)
    00438           {
    00439         __c = *__beg;
    00440         if (!__found_zero)
    00441           break;
    00442           }
    00443         else
    00444           __testeof = true;
    00445       }
    00446
    00447     // At this point, base is determined. If not hex, only allow
    00448     // base digits as valid input.
    00449     const size_t __len = (__base == 16 ? __num_base::_S_iend
    00450                   - __num_base::_S_izero : __base);
    00451
    00452     // Extract.
    00453     string __found_grouping;
    00454     if (__lc->_M_use_grouping)
    00455       __found_grouping.reserve(32);
    00456     bool __testfail = false;
    00457     const __unsigned_type __max = __negative
    00458       ? -__gnu_cxx::__numeric_traits<_ValueT>::__min
    00459       : __gnu_cxx::__numeric_traits<_ValueT>::__max;
    00460     const __unsigned_type __smax = __max / __base;
    00461     __unsigned_type __result = 0;
    00462     int __digit = 0;
    00463     const char_type* __lit_zero = __lit + __num_base::_S_izero;
    00464
    00465     if (!__lc->_M_allocated)
    00466       // "C" locale
    00467       while (!__testeof)
    00468         {
    00469           __digit = _M_find(__lit_zero, __len, __c);
    00470           if (__digit == -1)
    00471         break;
    00472
    00473           if (__result > __smax)
    00474         __testfail = true;
    00475           else
    00476         {
    00477           __result *= __base;
    00478           __testfail |= __result > __max - __digit;
    00479           __result += __digit;
    00480           ++__sep_pos;
    00481         }
    00482
    00483           if (++__beg != __end)
    00484         __c = *__beg;
    00485           else
    00486         __testeof = true;
    00487         }
    00488     else
    00489       while (!__testeof)
    00490         {
    00491           // According to 22.2.2.1.2, p8-9, first look for thousands_sep
    00492           // and decimal_point.
    00493           if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    00494         {
    00495           // NB: Thousands separator at the beginning of a string
    00496           // is a no-no, as is two consecutive thousands separators.
    00497           if (__sep_pos)
    00498             {
    00499               __found_grouping += static_cast<char>(__sep_pos);
    00500               __sep_pos = 0;
    00501             }
    00502           else
    00503             {
    00504               __testfail = true;
    00505               break;
    00506             }
    00507         }
    00508           else if (__c == __lc->_M_decimal_point)
    00509         break;
    00510           else
    00511         {
    00512           const char_type* __q =
    00513             __traits_type::find(__lit_zero, __len, __c);
    00514           if (!__q)
    00515             break;
    00516
    00517           __digit = __q - __lit_zero;
    00518           if (__digit > 15)
    00519             __digit -= 6;
    00520           if (__result > __smax)
    00521             __testfail = true;
    00522           else
    00523             {
    00524               __result *= __base;
    00525               __testfail |= __result > __max - __digit;
    00526               __result += __digit;
    00527               ++__sep_pos;
    00528             }
    00529         }
    00530
    00531           if (++__beg != __end)
    00532         __c = *__beg;
    00533           else
    00534         __testeof = true;
    00535         }
    00536
    00537     // Digit grouping is checked. If grouping and found_grouping don't
    00538     // match, then get very very upset, and set failbit.
    00539     if (__found_grouping.size())
    00540       {
    00541         // Add the ending grouping.
    00542         __found_grouping += static_cast<char>(__sep_pos);
    00543
    00544         if (!std::__verify_grouping(__lc->_M_grouping,
    00545                     __lc->_M_grouping_size,
    00546                     __found_grouping))
    00547           __err |= ios_base::failbit;
    00548       }
    00549
    00550     if (!__testfail && (__sep_pos || __found_zero
    00551                 || __found_grouping.size()))
    00552       __v = __negative ? -__result : __result;
    00553     else
    00554       __err |= ios_base::failbit;
    00555
    00556     if (__testeof)
    00557       __err |= ios_base::eofbit;
    00558     return __beg;
    00559       }
    00560
    00561   // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00562   // 17.  Bad bool parsing
    00563   template<typename _CharT, typename _InIter>
    00564     _InIter
    00565     num_get<_CharT, _InIter>::
    00566     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00567            ios_base::iostate& __err, bool& __v) const
    00568     {
    00569       if (!(__io.flags() & ios_base::boolalpha))
    00570         {
    00571       // Parse bool values as long.
    00572           // NB: We can't just call do_get(long) here, as it might
    00573           // refer to a derived class.
    00574       long __l = -1;
    00575           __beg = _M_extract_int(__beg, __end, __io, __err, __l);
    00576       if (__l == 0 || __l == 1)
    00577         __v = bool(__l);
    00578       else
    00579             __err |= ios_base::failbit;
    00580         }
    00581       else
    00582         {
    00583       // Parse bool values as alphanumeric.
    00584       typedef __numpunct_cache<_CharT>              __cache_type;
    00585       __use_cache<__cache_type> __uc;
    00586       const locale& __loc = __io._M_getloc();
    00587       const __cache_type* __lc = __uc(__loc);
    00588
    00589       bool __testf = true;
    00590       bool __testt = true;
    00591       size_t __n;
    00592       bool __testeof = __beg == __end;
    00593           for (__n = 0; !__testeof; ++__n)
    00594             {
    00595           const char_type __c = *__beg;
    00596
    00597           if (__testf)
    00598             {
    00599           if (__n < __lc->_M_falsename_size)
    00600             __testf = __c == __lc->_M_falsename[__n];
    00601           else
    00602             break;
    00603         }
    00604
    00605           if (__testt)
    00606             {
    00607           if (__n < __lc->_M_truename_size)
    00608             __testt = __c == __lc->_M_truename[__n];
    00609           else
    00610             break;
    00611         }
    00612
    00613           if (!__testf && !__testt)
    00614         break;
    00615
    00616           if (++__beg == __end)
    00617         __testeof = true;
    00618             }
    00619       if (__testf && __n == __lc->_M_falsename_size)
    00620         __v = false;
    00621       else if (__testt && __n == __lc->_M_truename_size)
    00622         __v = true;
    00623       else
    00624         __err |= ios_base::failbit;
    00625
    00626           if (__testeof)
    00627             __err |= ios_base::eofbit;
    00628         }
    00629       return __beg;
    00630     }
    00631
    00632   template<typename _CharT, typename _InIter>
    00633     _InIter
    00634     num_get<_CharT, _InIter>::
    00635     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00636            ios_base::iostate& __err, long& __v) const
    00637     { return _M_extract_int(__beg, __end, __io, __err, __v); }
    00638
    00639   template<typename _CharT, typename _InIter>
    00640     _InIter
    00641     num_get<_CharT, _InIter>::
    00642     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00643            ios_base::iostate& __err, unsigned short& __v) const
    00644     { return _M_extract_int(__beg, __end, __io, __err, __v); }
    00645
    00646   template<typename _CharT, typename _InIter>
    00647     _InIter
    00648     num_get<_CharT, _InIter>::
    00649     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00650            ios_base::iostate& __err, unsigned int& __v) const
    00651     { return _M_extract_int(__beg, __end, __io, __err, __v); }
    00652
    00653   template<typename _CharT, typename _InIter>
    00654     _InIter
    00655     num_get<_CharT, _InIter>::
    00656     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00657            ios_base::iostate& __err, unsigned long& __v) const
    00658     { return _M_extract_int(__beg, __end, __io, __err, __v); }
    00659
    00660 #ifdef _GLIBCXX_USE_LONG_LONG
    00661   template<typename _CharT, typename _InIter>
    00662     _InIter
    00663     num_get<_CharT, _InIter>::
    00664     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00665            ios_base::iostate& __err, long long& __v) const
    00666     { return _M_extract_int(__beg, __end, __io, __err, __v); }
    00667
    00668   template<typename _CharT, typename _InIter>
    00669     _InIter
    00670     num_get<_CharT, _InIter>::
    00671     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00672            ios_base::iostate& __err, unsigned long long& __v) const
    00673     { return _M_extract_int(__beg, __end, __io, __err, __v); }
    00674 #endif
    00675
    00676   template<typename _CharT, typename _InIter>
    00677     _InIter
    00678     num_get<_CharT, _InIter>::
    00679     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00680        ios_base::iostate& __err, float& __v) const
    00681     {
    00682       string __xtrc;
    00683       __xtrc.reserve(32);
    00684       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
    00685       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
    00686       return __beg;
    00687     }
    00688
    00689   template<typename _CharT, typename _InIter>
    00690     _InIter
    00691     num_get<_CharT, _InIter>::
    00692     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00693            ios_base::iostate& __err, double& __v) const
    00694     {
    00695       string __xtrc;
    00696       __xtrc.reserve(32);
    00697       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
    00698       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
    00699       return __beg;
    00700     }
    00701
    00702 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
    00703   template<typename _CharT, typename _InIter>
    00704     _InIter
    00705     num_get<_CharT, _InIter>::
    00706     __do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00707          ios_base::iostate& __err, double& __v) const
    00708     {
    00709       string __xtrc;
    00710       __xtrc.reserve(32);
    00711       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
    00712       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
    00713       return __beg;
    00714     }
    00715 #endif
    00716
    00717   template<typename _CharT, typename _InIter>
    00718     _InIter
    00719     num_get<_CharT, _InIter>::
    00720     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00721            ios_base::iostate& __err, long double& __v) const
    00722     {
    00723       string __xtrc;
    00724       __xtrc.reserve(32);
    00725       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
    00726       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
    00727       return __beg;
    00728     }
    00729
    00730   template<typename _CharT, typename _InIter>
    00731     _InIter
    00732     num_get<_CharT, _InIter>::
    00733     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    00734            ios_base::iostate& __err, void*& __v) const
    00735     {
    00736       // Prepare for hex formatted input.
    00737       typedef ios_base::fmtflags        fmtflags;
    00738       const fmtflags __fmt = __io.flags();
    00739       __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex);
    00740
    00741       typedef __gnu_cxx::__conditional_type<(sizeof(void*)
    00742                          <= sizeof(unsigned long)),
    00743     unsigned long, unsigned long long>::__type _UIntPtrType;
    00744
    00745       _UIntPtrType __ul;
    00746       __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
    00747
    00748       // Reset from hex formatted input.
    00749       __io.flags(__fmt);
    00750
    00751       if (!(__err & ios_base::failbit))
    00752     __v = reinterpret_cast<void*>(__ul);
    00753       return __beg;
    00754     }
    00755
    00756   // For use by integer and floating-point types after they have been
    00757   // converted into a char_type string.
    00758   template<typename _CharT, typename _OutIter>
    00759     void
    00760     num_put<_CharT, _OutIter>::
    00761     _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
    00762        _CharT* __new, const _CharT* __cs, int& __len) const
    00763     {
    00764       // [22.2.2.2.2] Stage 3.
    00765       // If necessary, pad.
    00766       __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new,
    00767                           __cs, __w, __len);
    00768       __len = static_cast<int>(__w);
    00769     }
    00770
    00771 _GLIBCXX_END_LDBL_NAMESPACE
    00772
    00773   template<typename _CharT, typename _ValueT>
    00774     int
    00775     __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
    00776           ios_base::fmtflags __flags, bool __dec)
    00777     {
    00778       _CharT* __buf = __bufend;
    00779       if (__builtin_expect(__dec, true))
    00780     {
    00781       // Decimal.
    00782       do
    00783         {
    00784           *--__buf = __lit[(__v % 10) + __num_base::_S_odigits];
    00785           __v /= 10;
    00786         }
    00787       while (__v != 0);
    00788     }
    00789       else if ((__flags & ios_base::basefield) == ios_base::oct)
    00790     {
    00791       // Octal.
    00792       do
    00793         {
    00794           *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits];
    00795           __v >>= 3;
    00796         }
    00797       while (__v != 0);
    00798     }
    00799       else
    00800     {
    00801       // Hex.
    00802       const bool __uppercase = __flags & ios_base::uppercase;
    00803       const int __case_offset = __uppercase ? __num_base::_S_oudigits
    00804                                             : __num_base::_S_odigits;
    00805       do
    00806         {
    00807           *--__buf = __lit[(__v & 0xf) + __case_offset];
    00808           __v >>= 4;
    00809         }
    00810       while (__v != 0);
    00811     }
    00812       return __bufend - __buf;
    00813     }
    00814
    00815 _GLIBCXX_BEGIN_LDBL_NAMESPACE
    00816
    00817   template<typename _CharT, typename _OutIter>
    00818     void
    00819     num_put<_CharT, _OutIter>::
    00820     _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
    00821          ios_base&, _CharT* __new, _CharT* __cs, int& __len) const
    00822     {
    00823       _CharT* __p = std::__add_grouping(__new, __sep, __grouping,
    00824                     __grouping_size, __cs, __cs + __len);
    00825       __len = __p - __new;
    00826     }
    00827
    00828   template<typename _CharT, typename _OutIter>
    00829     template<typename _ValueT>
    00830       _OutIter
    00831       num_put<_CharT, _OutIter>::
    00832       _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
    00833             _ValueT __v) const
    00834       {
    00835     using __gnu_cxx::__add_unsigned;
    00836     typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
    00837     typedef __numpunct_cache<_CharT>                 __cache_type;
    00838     __use_cache<__cache_type> __uc;
    00839     const locale& __loc = __io._M_getloc();
    00840     const __cache_type* __lc = __uc(__loc);
    00841     const _CharT* __lit = __lc->_M_atoms_out;
    00842     const ios_base::fmtflags __flags = __io.flags();
    00843
    00844     // Long enough to hold hex, dec, and octal representations.
    00845     const int __ilen = 5 * sizeof(_ValueT);
    00846     _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    00847                                  * __ilen));
    00848
    00849     // [22.2.2.2.2] Stage 1, numeric conversion to character.
    00850     // Result is returned right-justified in the buffer.
    00851     const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
    00852     const bool __dec = (__basefield != ios_base::oct
    00853                 && __basefield != ios_base::hex);
    00854     const __unsigned_type __u = ((__v > 0 || !__dec)
    00855                      ? __unsigned_type(__v)
    00856                      : -__unsigned_type(__v));
    00857     int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec);
    00858     __cs += __ilen - __len;
    00859
    00860     // Add grouping, if necessary.
    00861     if (__lc->_M_use_grouping)
    00862       {
    00863         // Grouping can add (almost) as many separators as the number
    00864         // of digits + space is reserved for numeric base or sign.
    00865         _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    00866                                   * (__len + 1)
    00867                                   * 2));
    00868         _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
    00869              __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len);
    00870         __cs = __cs2 + 2;
    00871       }
    00872
    00873     // Complete Stage 1, prepend numeric base or sign.
    00874     if (__builtin_expect(__dec, true))
    00875       {
    00876         // Decimal.
    00877         if (__v >= 0)
    00878           {
    00879         if (bool(__flags & ios_base::showpos)
    00880             && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed)
    00881           *--__cs = __lit[__num_base::_S_oplus], ++__len;
    00882           }
    00883         else
    00884           *--__cs = __lit[__num_base::_S_ominus], ++__len;
    00885       }
    00886     else if (bool(__flags & ios_base::showbase) && __v)
    00887       {
    00888         if (__basefield == ios_base::oct)
    00889           *--__cs = __lit[__num_base::_S_odigits], ++__len;
    00890         else
    00891           {
    00892         // 'x' or 'X'
    00893         const bool __uppercase = __flags & ios_base::uppercase;
    00894         *--__cs = __lit[__num_base::_S_ox + __uppercase];
    00895         // '0'
    00896         *--__cs = __lit[__num_base::_S_odigits];
    00897         __len += 2;
    00898           }
    00899       }
    00900
    00901     // Pad.
    00902     const streamsize __w = __io.width();
    00903     if (__w > static_cast<streamsize>(__len))
    00904       {
    00905         _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    00906                                   * __w));
    00907         _M_pad(__fill, __w, __io, __cs3, __cs, __len);
    00908         __cs = __cs3;
    00909       }
    00910     __io.width(0);
    00911
    00912     // [22.2.2.2.2] Stage 4.
    00913     // Write resulting, fully-formatted string to output iterator.
    00914     return std::__write(__s, __cs, __len);
    00915       }
    00916
    00917   template<typename _CharT, typename _OutIter>
    00918     void
    00919     num_put<_CharT, _OutIter>::
    00920     _M_group_float(const char* __grouping, size_t __grouping_size,
    00921            _CharT __sep, const _CharT* __p, _CharT* __new,
    00922            _CharT* __cs, int& __len) const
    00923     {
    00924       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00925       // 282. What types does numpunct grouping refer to?
    00926       // Add grouping, if necessary.
    00927       const int __declen = __p ? __p - __cs : __len;
    00928       _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping,
    00929                      __grouping_size,
    00930                      __cs, __cs + __declen);
    00931
    00932       // Tack on decimal part.
    00933       int __newlen = __p2 - __new;
    00934       if (__p)
    00935     {
    00936       char_traits<_CharT>::copy(__p2, __p, __len - __declen);
    00937       __newlen += __len - __declen;
    00938     }
    00939       __len = __newlen;
    00940     }
    00941
    00942   // The following code uses vsnprintf (or vsprintf(), when
    00943   // _GLIBCXX_USE_C99 is not defined) to convert floating point values
    00944   // for insertion into a stream.  An optimization would be to replace
    00945   // them with code that works directly on a wide buffer and then use
    00946   // __pad to do the padding.  It would be good to replace them anyway
    00947   // to gain back the efficiency that C++ provides by knowing up front
    00948   // the type of the values to insert.  Also, sprintf is dangerous
    00949   // since may lead to accidental buffer overruns.  This
    00950   // implementation follows the C++ standard fairly directly as
    00951   // outlined in 22.2.2.2 [lib.locale.num.put]
    00952   template<typename _CharT, typename _OutIter>
    00953     template<typename _ValueT>
    00954       _OutIter
    00955       num_put<_CharT, _OutIter>::
    00956       _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
    00957                _ValueT __v) const
    00958       {
    00959     typedef __numpunct_cache<_CharT>                __cache_type;
    00960     __use_cache<__cache_type> __uc;
    00961     const locale& __loc = __io._M_getloc();
    00962     const __cache_type* __lc = __uc(__loc);
    00963
    00964     // Use default precision if out of range.
    00965     const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision();
    00966
    00967     const int __max_digits =
    00968       __gnu_cxx::__numeric_traits<_ValueT>::__digits10;
    00969
    00970     // [22.2.2.2.2] Stage 1, numeric conversion to character.
    00971     int __len;
    00972     // Long enough for the max format spec.
    00973     char __fbuf[16];
    00974     __num_base::_S_format_float(__io, __fbuf, __mod);
    00975
    00976 #ifdef _GLIBCXX_USE_C99
    00977     // First try a buffer perhaps big enough (most probably sufficient
    00978     // for non-ios_base::fixed outputs)
    00979     int __cs_size = __max_digits * 3;
    00980     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00981     __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
    00982                       __fbuf, __prec, __v);
    00983
    00984     // If the buffer was not large enough, try again with the correct size.
    00985     if (__len >= __cs_size)
    00986       {
    00987         __cs_size = __len + 1;
    00988         __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00989         __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
    00990                       __fbuf, __prec, __v);
    00991       }
    00992 #else
    00993     // Consider the possibility of long ios_base::fixed outputs
    00994     const bool __fixed = __io.flags() & ios_base::fixed;
    00995     const int __max_exp =
    00996       __gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10;
    00997
    00998     // The size of the output string is computed as follows.
    00999     // ios_base::fixed outputs may need up to __max_exp + 1 chars
    01000     // for the integer part + __prec chars for the fractional part
    01001     // + 3 chars for sign, decimal point, '\0'. On the other hand,
    01002     // for non-fixed outputs __max_digits * 2 + __prec chars are
    01003     // largely sufficient.
    01004     const int __cs_size = __fixed ? __max_exp + __prec + 4
    01005                                   : __max_digits * 2 + __prec;
    01006     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    01007     __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf,
    01008                       __prec, __v);
    01009 #endif
    01010
    01011     // [22.2.2.2.2] Stage 2, convert to char_type, using correct
    01012     // numpunct.decimal_point() values for '.' and adding grouping.
    01013     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    01014
    01015     _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    01016                                  * __len));
    01017     __ctype.widen(__cs, __cs + __len, __ws);
    01018
    01019     // Replace decimal point.
    01020     _CharT* __wp = 0;
    01021     const char* __p = char_traits<char>::find(__cs, __len, '.');
    01022     if (__p)
    01023       {
    01024         __wp = __ws + (__p - __cs);
    01025         *__wp = __lc->_M_decimal_point;
    01026       }
    01027
    01028     // Add grouping, if necessary.
    01029     // N.B. Make sure to not group things like 2e20, i.e., no decimal
    01030     // point, scientific notation.
    01031     if (__lc->_M_use_grouping
    01032         && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
    01033                       && __cs[1] >= '0' && __cs[2] >= '0')))
    01034       {
    01035         // Grouping can add (almost) as many separators as the
    01036         // number of digits, but no more.
    01037         _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    01038                                   * __len * 2));
    01039
    01040         streamsize __off = 0;
    01041         if (__cs[0] == '-' || __cs[0] == '+')
    01042           {
    01043         __off = 1;
    01044         __ws2[0] = __ws[0];
    01045         __len -= 1;
    01046           }
    01047
    01048         _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
    01049                __lc->_M_thousands_sep, __wp, __ws2 + __off,
    01050                __ws + __off, __len);
    01051         __len += __off;
    01052
    01053         __ws = __ws2;
    01054       }
    01055
    01056     // Pad.
    01057     const streamsize __w = __io.width();
    01058     if (__w > static_cast<streamsize>(__len))
    01059       {
    01060         _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    01061                                   * __w));
    01062         _M_pad(__fill, __w, __io, __ws3, __ws, __len);
    01063         __ws = __ws3;
    01064       }
    01065     __io.width(0);
    01066
    01067     // [22.2.2.2.2] Stage 4.
    01068     // Write resulting, fully-formatted string to output iterator.
    01069     return std::__write(__s, __ws, __len);
    01070       }
    01071
    01072   template<typename _CharT, typename _OutIter>
    01073     _OutIter
    01074     num_put<_CharT, _OutIter>::
    01075     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
    01076     {
    01077       const ios_base::fmtflags __flags = __io.flags();
    01078       if ((__flags & ios_base::boolalpha) == 0)
    01079         {
    01080           const long __l = __v;
    01081           __s = _M_insert_int(__s, __io, __fill, __l);
    01082         }
    01083       else
    01084         {
    01085       typedef __numpunct_cache<_CharT>              __cache_type;
    01086       __use_cache<__cache_type> __uc;
    01087       const locale& __loc = __io._M_getloc();
    01088       const __cache_type* __lc = __uc(__loc);
    01089
    01090       const _CharT* __name = __v ? __lc->_M_truename
    01091                                  : __lc->_M_falsename;
    01092       int __len = __v ? __lc->_M_truename_size
    01093                       : __lc->_M_falsename_size;
    01094
    01095       const streamsize __w = __io.width();
    01096       if (__w > static_cast<streamsize>(__len))
    01097         {
    01098           _CharT* __cs
    01099         = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    01100                             * __w));
    01101           _M_pad(__fill, __w, __io, __cs, __name, __len);
    01102           __name = __cs;
    01103         }
    01104       __io.width(0);
    01105       __s = std::__write(__s, __name, __len);
    01106     }
    01107       return __s;
    01108     }
    01109
    01110   template<typename _CharT, typename _OutIter>
    01111     _OutIter
    01112     num_put<_CharT, _OutIter>::
    01113     do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
    01114     { return _M_insert_int(__s, __io, __fill, __v); }
    01115
    01116   template<typename _CharT, typename _OutIter>
    01117     _OutIter
    01118     num_put<_CharT, _OutIter>::
    01119     do_put(iter_type __s, ios_base& __io, char_type __fill,
    01120            unsigned long __v) const
    01121     { return _M_insert_int(__s, __io, __fill, __v); }
    01122
    01123 #ifdef _GLIBCXX_USE_LONG_LONG
    01124   template<typename _CharT, typename _OutIter>
    01125     _OutIter
    01126     num_put<_CharT, _OutIter>::
    01127     do_put(iter_type __s, ios_base& __io, char_type __fill, long long __v) const
    01128     { return _M_insert_int(__s, __io, __fill, __v); }
    01129
    01130   template<typename _CharT, typename _OutIter>
    01131     _OutIter
    01132     num_put<_CharT, _OutIter>::
    01133     do_put(iter_type __s, ios_base& __io, char_type __fill,
    01134            unsigned long long __v) const
    01135     { return _M_insert_int(__s, __io, __fill, __v); }
    01136 #endif
    01137
    01138   template<typename _CharT, typename _OutIter>
    01139     _OutIter
    01140     num_put<_CharT, _OutIter>::
    01141     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
    01142     { return _M_insert_float(__s, __io, __fill, char(), __v); }
    01143
    01144 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
    01145   template<typename _CharT, typename _OutIter>
    01146     _OutIter
    01147     num_put<_CharT, _OutIter>::
    01148     __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
    01149     { return _M_insert_float(__s, __io, __fill, char(), __v); }
    01150 #endif
    01151
    01152   template<typename _CharT, typename _OutIter>
    01153     _OutIter
    01154     num_put<_CharT, _OutIter>::
    01155     do_put(iter_type __s, ios_base& __io, char_type __fill,
    01156        long double __v) const
    01157     { return _M_insert_float(__s, __io, __fill, 'L', __v); }
    01158
    01159   template<typename _CharT, typename _OutIter>
    01160     _OutIter
    01161     num_put<_CharT, _OutIter>::
    01162     do_put(iter_type __s, ios_base& __io, char_type __fill,
    01163            const void* __v) const
    01164     {
    01165       const ios_base::fmtflags __flags = __io.flags();
    01166       const ios_base::fmtflags __fmt = ~(ios_base::basefield
    01167                      | ios_base::uppercase
    01168                      | ios_base::internal);
    01169       __io.flags((__flags & __fmt) | (ios_base::hex | ios_base::showbase));
    01170
    01171       typedef __gnu_cxx::__conditional_type<(sizeof(const void*)
    01172                          <= sizeof(unsigned long)),
    01173     unsigned long, unsigned long long>::__type _UIntPtrType;
    01174
    01175       __s = _M_insert_int(__s, __io, __fill,
    01176               reinterpret_cast<_UIntPtrType>(__v));
    01177       __io.flags(__flags);
    01178       return __s;
    01179     }
    01180
    01181 _GLIBCXX_END_LDBL_NAMESPACE
    01182
    01183   // Construct correctly padded string, as per 22.2.2.2.2
    01184   // Assumes
    01185   // __newlen > __oldlen
    01186   // __news is allocated for __newlen size
    01187
    01188   // NB: Of the two parameters, _CharT can be deduced from the
    01189   // function arguments. The other (_Traits) has to be explicitly specified.
    01190   template<typename _CharT, typename _Traits>
    01191     void
    01192     __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
    01193                    _CharT* __news, const _CharT* __olds,
    01194                    const streamsize __newlen,
    01195                    const streamsize __oldlen)
    01196     {
    01197       const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
    01198       const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
    01199
    01200       // Padding last.
    01201       if (__adjust == ios_base::left)
    01202     {
    01203       _Traits::copy(__news, __olds, __oldlen);
    01204       _Traits::assign(__news + __oldlen, __plen, __fill);
    01205       return;
    01206     }
    01207
    01208       size_t __mod = 0;
    01209       if (__adjust == ios_base::internal)
    01210     {
    01211       // Pad after the sign, if there is one.
    01212       // Pad after 0[xX], if there is one.
    01213       // Who came up with these rules, anyway? Jeeze.
    01214           const locale& __loc = __io._M_getloc();
    01215       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    01216
    01217       if (__ctype.widen('-') == __olds[0]
    01218           || __ctype.widen('+') == __olds[0])
    01219         {
    01220           __news[0] = __olds[0];
    01221           __mod = 1;
    01222           ++__news;
    01223         }
    01224       else if (__ctype.widen('0') == __olds[0]
    01225            && __oldlen > 1
    01226            && (__ctype.widen('x') == __olds[1]
    01227                || __ctype.widen('X') == __olds[1]))
    01228         {
    01229           __news[0] = __olds[0];
    01230           __news[1] = __olds[1];
    01231           __mod = 2;
    01232           __news += 2;
    01233         }
    01234       // else Padding first.
    01235     }
    01236       _Traits::assign(__news, __plen, __fill);
    01237       _Traits::copy(__news + __plen, __olds + __mod, __oldlen - __mod);
    01238     }
    01239
    01240   template<typename _CharT>
    01241     _CharT*
    01242     __add_grouping(_CharT* __s, _CharT __sep,
    01243            const char* __gbeg, size_t __gsize,
    01244            const _CharT* __first, const _CharT* __last)
    01245     {
    01246       size_t __idx = 0;
    01247       size_t __ctr = 0;
    01248
    01249       while (__last - __first > __gbeg[__idx]
    01250          && static_cast<signed char>(__gbeg[__idx]) > 0)
    01251     {
    01252       __last -= __gbeg[__idx];
    01253       __idx < __gsize - 1 ? ++__idx : ++__ctr;
    01254     }
    01255
    01256       while (__first != __last)
    01257     *__s++ = *__first++;
    01258
    01259       while (__ctr--)
    01260     {
    01261       *__s++ = __sep;
    01262       for (char __i = __gbeg[__idx]; __i > 0; --__i)
    01263         *__s++ = *__first++;
    01264     }
    01265
    01266       while (__idx--)
    01267     {
    01268       *__s++ = __sep;
    01269       for (char __i = __gbeg[__idx]; __i > 0; --__i)
    01270         *__s++ = *__first++;
    01271     }
    01272
    01273       return __s;
    01274     }
    01275
    01276   // Inhibit implicit instantiations for required instantiations,
    01277   // which are defined via explicit instantiations elsewhere.
    01278   // NB: This syntax is a GNU extension.
    01279 #if _GLIBCXX_EXTERN_TEMPLATE
    01280   extern template class numpunct<char>;
    01281   extern template class numpunct_byname<char>;
    01282   extern template class _GLIBCXX_LDBL_NAMESPACE num_get<char>;
    01283   extern template class _GLIBCXX_LDBL_NAMESPACE num_put<char>;
    01284   extern template class ctype_byname<char>;
    01285
    01286   extern template
    01287     const numpunct<char>&
    01288     use_facet<numpunct<char> >(const locale&);
    01289
    01290   extern template
    01291     const num_put<char>&
    01292     use_facet<num_put<char> >(const locale&);
    01293
    01294   extern template
    01295     const num_get<char>&
    01296     use_facet<num_get<char> >(const locale&);
    01297
    01298   extern template
    01299     bool
    01300     has_facet<ctype<char> >(const locale&);
    01301
    01302   extern template
    01303     bool
    01304     has_facet<numpunct<char> >(const locale&);
    01305
    01306   extern template
    01307     bool
    01308     has_facet<num_put<char> >(const locale&);
    01309
    01310   extern template
    01311     bool
    01312     has_facet<num_get<char> >(const locale&);
    01313
    01314 #ifdef _GLIBCXX_USE_WCHAR_T
    01315   extern template class numpunct<wchar_t>;
    01316   extern template class numpunct_byname<wchar_t>;
    01317   extern template class _GLIBCXX_LDBL_NAMESPACE num_get<wchar_t>;
    01318   extern template class _GLIBCXX_LDBL_NAMESPACE num_put<wchar_t>;
    01319   extern template class ctype_byname<wchar_t>;
    01320
    01321   extern template
    01322     const numpunct<wchar_t>&
    01323     use_facet<numpunct<wchar_t> >(const locale&);
    01324
    01325   extern template
    01326     const num_put<wchar_t>&
    01327     use_facet<num_put<wchar_t> >(const locale&);
    01328
    01329   extern template
    01330     const num_get<wchar_t>&
    01331     use_facet<num_get<wchar_t> >(const locale&);
    01332
    01333  extern template
    01334     bool
    01335     has_facet<ctype<wchar_t> >(const locale&);
    01336
    01337   extern template
    01338     bool
    01339     has_facet<numpunct<wchar_t> >(const locale&);
    01340
    01341   extern template
    01342     bool
    01343     has_facet<num_put<wchar_t> >(const locale&);
    01344
    01345   extern template
    01346     bool
    01347     has_facet<num_get<wchar_t> >(const locale&);
    01348 #endif
    01349 #endif
    01350
    01351 _GLIBCXX_END_NAMESPACE
    01352
    01353 #endif