# locale_facets.tcc

Go to the documentation of this file.

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