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