locale_facets.tcc

00001 // Locale support -*- C++ -*-
00002 
00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
00004 // Free Software Foundation, Inc.
00005 //
00006 // This file is part of the GNU ISO C++ Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 // Warning: this file is not meant for user inclusion. Use <locale>.
00032 
00033 #ifndef _LOCALE_FACETS_TCC
00034 #define _LOCALE_FACETS_TCC 1
00035 
00036 #pragma GCC system_header
00037 
00038 #include <limits>       // For numeric_limits
00039 #include <typeinfo>     // For bad_cast.
00040 #include <bits/streambuf_iterator.h>
00041 
00042 namespace std
00043 {
00044   template<typename _Facet>
00045     locale
00046     locale::combine(const locale& __other) const
00047     {
00048       _Impl* __tmp = new _Impl(*_M_impl, 1);
00049       try
00050     {
00051       __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
00052     }
00053       catch(...)
00054     {
00055       __tmp->_M_remove_reference();
00056       __throw_exception_again;
00057     }
00058       return locale(__tmp);
00059     }
00060 
00061   template<typename _CharT, typename _Traits, typename _Alloc>
00062     bool
00063     locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
00064                        const basic_string<_CharT, _Traits, _Alloc>& __s2) const
00065     {
00066       typedef std::collate<_CharT> __collate_type;
00067       const __collate_type& __collate = use_facet<__collate_type>(*this);
00068       return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
00069                 __s2.data(), __s2.data() + __s2.length()) < 0);
00070     }
00071 
00072   /**
00073    *  @brief  Test for the presence of a facet.
00074    *
00075    *  has_facet tests the locale argument for the presence of the facet type
00076    *  provided as the template parameter.  Facets derived from the facet
00077    *  parameter will also return true.
00078    *
00079    *  @param  Facet  The facet type to test the presence of.
00080    *  @param  locale  The locale to test.
00081    *  @return  true if locale contains a facet of type Facet, else false.
00082   */
00083   template<typename _Facet>
00084     inline bool
00085     has_facet(const locale& __loc) throw()
00086     {
00087       const size_t __i = _Facet::id._M_id();
00088       const locale::facet** __facets = __loc._M_impl->_M_facets;
00089       return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
00090     }
00091 
00092   /**
00093    *  @brief  Return a facet.
00094    *
00095    *  use_facet looks for and returns a reference to a facet of type Facet
00096    *  where Facet is the template parameter.  If has_facet(locale) is true,
00097    *  there is a suitable facet to return.  It throws std::bad_cast if the
00098    *  locale doesn't contain a facet of type Facet.
00099    *
00100    *  @param  Facet  The facet type to access.
00101    *  @param  locale  The locale to use.
00102    *  @return  Reference to facet of type Facet.
00103    *  @throw  std::bad_cast if locale doesn't contain a facet of type Facet.
00104   */
00105   template<typename _Facet>
00106     inline const _Facet&
00107     use_facet(const locale& __loc)
00108     {
00109       const size_t __i = _Facet::id._M_id();
00110       const locale::facet** __facets = __loc._M_impl->_M_facets;
00111       if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
00112         __throw_bad_cast();
00113       return static_cast<const _Facet&>(*__facets[__i]);
00114     }
00115 
00116   // Routine to access a cache for the facet.  If the cache didn't
00117   // exist before, it gets constructed on the fly.
00118   template<typename _Facet>
00119     struct __use_cache
00120     {
00121       const _Facet*
00122       operator() (const locale& __loc) const;
00123     };
00124 
00125   // Specializations.
00126   template<typename _CharT>
00127     struct __use_cache<__numpunct_cache<_CharT> >
00128     {
00129       const __numpunct_cache<_CharT>*
00130       operator() (const locale& __loc) const
00131       {
00132     const size_t __i = numpunct<_CharT>::id._M_id();
00133     const locale::facet** __caches = __loc._M_impl->_M_caches;
00134     if (!__caches[__i])
00135       {
00136         __numpunct_cache<_CharT>* __tmp = NULL;
00137         try
00138           {
00139         __tmp = new __numpunct_cache<_CharT>;
00140         __tmp->_M_cache(__loc);
00141           }
00142         catch(...)
00143           {
00144         delete __tmp;
00145         __throw_exception_again;
00146           }
00147         __loc._M_impl->_M_install_cache(__tmp, __i);
00148       }
00149     return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
00150       }
00151     };
00152 
00153   template<typename _CharT, bool _Intl>
00154     struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
00155     {
00156       const __moneypunct_cache<_CharT, _Intl>*
00157       operator() (const locale& __loc) const
00158       {
00159     const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
00160     const locale::facet** __caches = __loc._M_impl->_M_caches;
00161     if (!__caches[__i])
00162       {
00163         __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
00164         try
00165           {
00166         __tmp = new __moneypunct_cache<_CharT, _Intl>;
00167         __tmp->_M_cache(__loc);
00168           }
00169         catch(...)
00170           {
00171         delete __tmp;
00172         __throw_exception_again;
00173           }
00174         __loc._M_impl->_M_install_cache(__tmp, __i);
00175       }
00176     return static_cast<
00177       const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
00178       }
00179     };
00180 
00181   template<typename _CharT>
00182     void
00183     __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
00184     {
00185       _M_allocated = true;
00186 
00187       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
00188 
00189       _M_grouping_size = __np.grouping().size();
00190       char* __grouping = new char[_M_grouping_size];
00191       __np.grouping().copy(__grouping, _M_grouping_size);
00192       _M_grouping = __grouping;
00193       _M_use_grouping = _M_grouping_size && __np.grouping()[0] != 0;
00194 
00195       _M_truename_size = __np.truename().size();
00196       _CharT* __truename = new _CharT[_M_truename_size];
00197       __np.truename().copy(__truename, _M_truename_size);
00198       _M_truename = __truename;
00199 
00200       _M_falsename_size = __np.falsename().size();
00201       _CharT* __falsename = new _CharT[_M_falsename_size];
00202       __np.falsename().copy(__falsename, _M_falsename_size);
00203       _M_falsename = __falsename;
00204 
00205       _M_decimal_point = __np.decimal_point();
00206       _M_thousands_sep = __np.thousands_sep();
00207 
00208       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
00209       __ct.widen(__num_base::_S_atoms_out,
00210          __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out);
00211       __ct.widen(__num_base::_S_atoms_in,
00212          __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in);
00213     }
00214 
00215   template<typename _CharT, bool _Intl>
00216     void
00217     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
00218     {
00219       _M_allocated = true;
00220 
00221       const moneypunct<_CharT, _Intl>& __mp =
00222     use_facet<moneypunct<_CharT, _Intl> >(__loc);
00223 
00224       _M_grouping_size = __mp.grouping().size();
00225       char* __grouping = new char[_M_grouping_size];
00226       __mp.grouping().copy(__grouping, _M_grouping_size);
00227       _M_grouping = __grouping;
00228       _M_use_grouping = _M_grouping_size && __mp.grouping()[0] != 0;
00229       
00230       _M_decimal_point = __mp.decimal_point();
00231       _M_thousands_sep = __mp.thousands_sep();
00232       _M_frac_digits = __mp.frac_digits();
00233       
00234       _M_curr_symbol_size = __mp.curr_symbol().size();
00235       _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
00236       __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
00237       _M_curr_symbol = __curr_symbol;
00238       
00239       _M_positive_sign_size = __mp.positive_sign().size();
00240       _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
00241       __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
00242       _M_positive_sign = __positive_sign;
00243 
00244       _M_negative_sign_size = __mp.negative_sign().size();
00245       _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
00246       __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
00247       _M_negative_sign = __negative_sign;
00248       
00249       _M_pos_format = __mp.pos_format();
00250       _M_neg_format = __mp.neg_format();
00251 
00252       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
00253       __ct.widen(money_base::_S_atoms,
00254          money_base::_S_atoms + money_base::_S_end, _M_atoms);
00255     }
00256 
00257 
00258   // Used by both numeric and monetary facets.
00259   // Check to make sure that the __grouping_tmp string constructed in
00260   // money_get or num_get matches the canonical grouping for a given
00261   // locale.
00262   // __grouping_tmp is parsed L to R
00263   // 1,222,444 == __grouping_tmp of "\1\3\3"
00264   // __grouping is parsed R to L
00265   // 1,222,444 == __grouping of "\3" == "\3\3\3"
00266   static bool
00267   __verify_grouping(const char* __grouping, size_t __grouping_size,
00268             const string& __grouping_tmp);
00269 
00270   template<typename _CharT, typename _InIter>
00271     _InIter
00272     num_get<_CharT, _InIter>::
00273     _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
00274              ios_base::iostate& __err, string& __xtrc) const
00275     {
00276       typedef char_traits<_CharT>           __traits_type;
00277       typedef typename numpunct<_CharT>::__cache_type   __cache_type;
00278       __use_cache<__cache_type> __uc;
00279       const locale& __loc = __io._M_getloc();
00280       const __cache_type* __lc = __uc(__loc);
00281       const _CharT* __lit = __lc->_M_atoms_in;
00282 
00283       // True if a mantissa is found.
00284       bool __found_mantissa = false;
00285 
00286       // First check for sign.
00287       if (__beg != __end)
00288     {
00289       const char_type __c = *__beg;
00290       const bool __plus = __c == __lit[__num_base::_S_iplus];
00291       if ((__plus || __c == __lit[__num_base::_S_iminus])
00292           && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00293           && !(__c == __lc->_M_decimal_point))
00294         {
00295           __xtrc += __plus ? '+' : '-';
00296           ++__beg;
00297         }
00298     }
00299 
00300       // Next, look for leading zeros.
00301       while (__beg != __end)
00302     {
00303       const char_type __c = *__beg;
00304       if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
00305           || __c == __lc->_M_decimal_point)
00306         break;
00307       else if (__c == __lit[__num_base::_S_izero])
00308         {
00309           if (!__found_mantissa)
00310         {
00311           __xtrc += '0';
00312           __found_mantissa = true;
00313         }
00314           ++__beg;
00315         }
00316       else
00317         break;
00318     }
00319 
00320       // Only need acceptable digits for floating point numbers.
00321       bool __found_dec = false;
00322       bool __found_sci = false;
00323       string __found_grouping;
00324       if (__lc->_M_use_grouping)
00325     __found_grouping.reserve(32);
00326       int __sep_pos = 0;
00327       const char_type* __lit_zero = __lit + __num_base::_S_izero;
00328       const char_type* __q;
00329       while (__beg != __end)
00330         {
00331       // According to 22.2.2.1.2, p8-9, first look for thousands_sep
00332       // and decimal_point.
00333       const char_type __c = *__beg;
00334           if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00335         {
00336           if (!__found_dec && !__found_sci)
00337         {
00338           // NB: Thousands separator at the beginning of a string
00339           // is a no-no, as is two consecutive thousands separators.
00340           if (__sep_pos)
00341             {
00342               __found_grouping += static_cast<char>(__sep_pos);
00343               __sep_pos = 0;
00344               ++__beg;
00345             }
00346           else
00347             {
00348               __err |= ios_base::failbit;
00349               break;
00350             }
00351         }
00352           else
00353         break;
00354             }
00355       else if (__c == __lc->_M_decimal_point)
00356         {
00357           if (!__found_dec && !__found_sci)
00358         {
00359           // If no grouping chars are seen, no grouping check
00360           // is applied. Therefore __found_grouping is adjusted
00361           // only if decimal_point comes after some thousands_sep.
00362           if (__found_grouping.size())
00363             __found_grouping += static_cast<char>(__sep_pos);
00364           __xtrc += '.';
00365           __found_dec = true;
00366           ++__beg;
00367         }
00368           else
00369         break;
00370         }
00371           else if (__q = __traits_type::find(__lit_zero, 10, __c))
00372         {
00373           __xtrc += __num_base::_S_atoms_in[__q - __lit];
00374           __found_mantissa = true;
00375           ++__sep_pos;
00376           ++__beg;
00377         }
00378       else if ((__c == __lit[__num_base::_S_ie] 
00379             || __c == __lit[__num_base::_S_iE])
00380            && __found_mantissa && !__found_sci)
00381         {
00382           // Scientific notation.
00383           if (__found_grouping.size() && !__found_dec)
00384         __found_grouping += static_cast<char>(__sep_pos);
00385           __xtrc += 'e';
00386           __found_sci = true;
00387 
00388           // Remove optional plus or minus sign, if they exist.
00389           if (++__beg != __end)
00390         {
00391           const bool __plus = *__beg == __lit[__num_base::_S_iplus];
00392           if ((__plus || *__beg == __lit[__num_base::_S_iminus])
00393               && !(__lc->_M_use_grouping
00394                && *__beg == __lc->_M_thousands_sep)
00395               && !(*__beg == __lc->_M_decimal_point))
00396             {
00397               __xtrc += __plus ? '+' : '-';
00398               ++__beg;
00399             }
00400         }
00401         }
00402       else
00403         // Not a valid input item.
00404         break;
00405         }
00406 
00407       // Digit grouping is checked. If grouping and found_grouping don't
00408       // match, then get very very upset, and set failbit.
00409       if (__lc->_M_use_grouping && __found_grouping.size())
00410         {
00411           // Add the ending grouping if a decimal or 'e'/'E' wasn't found.
00412       if (!__found_dec && !__found_sci)
00413         __found_grouping += static_cast<char>(__sep_pos);
00414 
00415           if (!std::__verify_grouping(__lc->_M_grouping, 
00416                       __lc->_M_grouping_size,
00417                       __found_grouping))
00418         __err |= ios_base::failbit;
00419         }
00420 
00421       // Finish up.
00422       if (__beg == __end)
00423         __err |= ios_base::eofbit;
00424       return __beg;
00425     }
00426 
00427   template<typename _CharT, typename _InIter>
00428     template<typename _ValueT>
00429       _InIter
00430       num_get<_CharT, _InIter>::
00431       _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
00432              ios_base::iostate& __err, _ValueT& __v) const
00433       {
00434         typedef char_traits<_CharT>         __traits_type;
00435     typedef typename numpunct<_CharT>::__cache_type __cache_type;
00436     __use_cache<__cache_type> __uc;
00437     const locale& __loc = __io._M_getloc();
00438     const __cache_type* __lc = __uc(__loc);
00439     const _CharT* __lit = __lc->_M_atoms_in;
00440 
00441     // NB: Iff __basefield == 0, __base can change based on contents.
00442     const ios_base::fmtflags __basefield = __io.flags()
00443                                            & ios_base::basefield;
00444     const bool __oct = __basefield == ios_base::oct;
00445     int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
00446 
00447     // True if numeric digits are found.
00448     bool __found_num = false;
00449 
00450     // First check for sign.
00451     bool __negative = false;
00452     if (__beg != __end)
00453       {
00454         const char_type __c = *__beg;
00455         if (numeric_limits<_ValueT>::is_signed)
00456           __negative = __c == __lit[__num_base::_S_iminus];
00457         if ((__negative || __c == __lit[__num_base::_S_iplus])
00458         && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00459         && !(__c == __lc->_M_decimal_point))
00460           ++__beg;
00461       }
00462 
00463     // Next, look for leading zeros and check required digits
00464     // for base formats.
00465     while (__beg != __end)
00466       {
00467         const char_type __c = *__beg;
00468         if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
00469         || __c == __lc->_M_decimal_point)
00470           break;
00471         else if (__c == __lit[__num_base::_S_izero] 
00472              && (!__found_num || __base == 10))
00473           {
00474         __found_num = true;
00475         ++__beg;
00476           }
00477         else if (__found_num)
00478           {
00479         if (__c == __lit[__num_base::_S_ix] 
00480             || __c == __lit[__num_base::_S_iX])
00481           {
00482             if (__basefield == 0)
00483               __base = 16;
00484             if (__base == 16)
00485               {
00486             __found_num = false;
00487             ++__beg;
00488               }
00489           }
00490         else if (__basefield == 0)
00491           __base = 8;
00492         break;
00493           }
00494         else
00495           break;
00496       }
00497 
00498     // At this point, base is determined. If not hex, only allow
00499     // base digits as valid input.
00500     const size_t __len = __base == 16 ? (__num_base::_S_iend
00501                          - __num_base::_S_izero)
00502                                       : __base;
00503 
00504     // Extract.
00505     string __found_grouping;
00506     if (__lc->_M_use_grouping)
00507       __found_grouping.reserve(32);
00508     int __sep_pos = 0;
00509     bool __overflow = false;
00510     _ValueT __result = 0;
00511     const char_type* __lit_zero = __lit + __num_base::_S_izero;
00512     const char_type* __q;
00513     if (__negative)
00514       {
00515         const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
00516         for (; __beg != __end; ++__beg)
00517           {
00518         // According to 22.2.2.1.2, p8-9, first look for thousands_sep
00519         // and decimal_point.
00520         const char_type __c = *__beg;
00521         if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00522           {
00523             // NB: Thousands separator at the beginning of a string
00524             // is a no-no, as is two consecutive thousands separators.
00525             if (__sep_pos)
00526               {
00527             __found_grouping += static_cast<char>(__sep_pos);
00528             __sep_pos = 0;
00529               }
00530             else
00531               {
00532             __err |= ios_base::failbit;
00533             break;
00534               }
00535           }
00536         else if (__c == __lc->_M_decimal_point)
00537           break;
00538         else if (__q = __traits_type::find(__lit_zero, __len, __c))
00539           {
00540             int __digit = __q - __lit_zero;
00541             if (__digit > 15)
00542               __digit -= 6;
00543             if (__result < __min)
00544               __overflow = true;
00545             else
00546               {
00547             const _ValueT __new_result = __result * __base
00548                                          - __digit;
00549             __overflow |= __new_result > __result;
00550             __result = __new_result;
00551             ++__sep_pos;
00552             __found_num = true;
00553               }
00554           }
00555         else
00556           // Not a valid input item.
00557           break;
00558           }
00559       }
00560     else
00561       {
00562         const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
00563         for (; __beg != __end; ++__beg)
00564           {
00565         const char_type __c = *__beg;
00566         if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00567           {
00568             if (__sep_pos)
00569               {
00570             __found_grouping += static_cast<char>(__sep_pos);
00571             __sep_pos = 0;
00572               }
00573             else
00574               {
00575             __err |= ios_base::failbit;
00576             break;
00577               }
00578           }
00579         else if (__c == __lc->_M_decimal_point)
00580           break;
00581         else if (__q = __traits_type::find(__lit_zero, __len, __c))
00582           {
00583             int __digit = __q - __lit_zero;
00584             if (__digit > 15)
00585               __digit -= 6;
00586             if (__result > __max)
00587               __overflow = true;
00588             else
00589               {
00590             const _ValueT __new_result = __result * __base
00591                                          + __digit;
00592             __overflow |= __new_result < __result;
00593             __result = __new_result;
00594             ++__sep_pos;
00595             __found_num = true;
00596               }
00597           }
00598         else
00599           break;
00600           }
00601       }
00602 
00603     // Digit grouping is checked. If grouping and found_grouping don't
00604     // match, then get very very upset, and set failbit.
00605     if (__lc->_M_use_grouping && __found_grouping.size())
00606       {
00607         // Add the ending grouping.
00608         __found_grouping += static_cast<char>(__sep_pos);
00609 
00610         if (!std::__verify_grouping(__lc->_M_grouping,
00611                     __lc->_M_grouping_size,
00612                     __found_grouping))
00613           __err |= ios_base::failbit;
00614       }
00615 
00616     if (!(__err & ios_base::failbit) && !__overflow
00617         && __found_num)
00618       __v = __result;
00619     else
00620       __err |= ios_base::failbit;
00621 
00622     if (__beg == __end)
00623       __err |= ios_base::eofbit;
00624     return __beg;
00625       }
00626 
00627   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00628   // 17.  Bad bool parsing
00629   template<typename _CharT, typename _InIter>
00630     _InIter
00631     num_get<_CharT, _InIter>::
00632     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00633            ios_base::iostate& __err, bool& __v) const
00634     {
00635       if (!(__io.flags() & ios_base::boolalpha))
00636         {
00637       // Parse bool values as long.
00638           // NB: We can't just call do_get(long) here, as it might
00639           // refer to a derived class.
00640       long __l = -1;
00641           __beg = _M_extract_int(__beg, __end, __io, __err, __l);
00642       if (__l == 0 || __l == 1)
00643         __v = __l;
00644       else
00645             __err |= ios_base::failbit;
00646         }
00647       else
00648         {
00649       // Parse bool values as alphanumeric.
00650       typedef char_traits<_CharT>                     __traits_type;
00651       typedef typename numpunct<_CharT>::__cache_type __cache_type;
00652       __use_cache<__cache_type> __uc;
00653       const locale& __loc = __io._M_getloc();
00654       const __cache_type* __lc = __uc(__loc);
00655 
00656       bool __testf = true;
00657       bool __testt = true;
00658       size_t __n;
00659           for (__n = 0; __beg != __end; ++__n, ++__beg)
00660             {
00661           if (__testf)
00662         if (__n < __lc->_M_falsename_size)
00663           __testf = *__beg == __lc->_M_falsename[__n];
00664         else
00665           break;
00666 
00667           if (__testt)
00668         if (__n < __lc->_M_truename_size)
00669           __testt = *__beg == __lc->_M_truename[__n];
00670         else
00671           break;
00672 
00673           if (!__testf && !__testt)
00674         break;
00675             }
00676       if (__testf && __n == __lc->_M_falsename_size)
00677         __v = 0;
00678       else if (__testt && __n == __lc->_M_truename_size)
00679         __v = 1;
00680       else
00681         __err |= ios_base::failbit;
00682 
00683           if (__beg == __end)
00684             __err |= ios_base::eofbit;
00685         }
00686       return __beg;
00687     }
00688 
00689   template<typename _CharT, typename _InIter>
00690     _InIter
00691     num_get<_CharT, _InIter>::
00692     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00693            ios_base::iostate& __err, long& __v) const
00694     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00695 
00696   template<typename _CharT, typename _InIter>
00697     _InIter
00698     num_get<_CharT, _InIter>::
00699     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00700            ios_base::iostate& __err, unsigned short& __v) const
00701     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00702 
00703   template<typename _CharT, typename _InIter>
00704     _InIter
00705     num_get<_CharT, _InIter>::
00706     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00707            ios_base::iostate& __err, unsigned int& __v) const
00708     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00709 
00710   template<typename _CharT, typename _InIter>
00711     _InIter
00712     num_get<_CharT, _InIter>::
00713     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00714            ios_base::iostate& __err, unsigned long& __v) const
00715     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00716 
00717 #ifdef _GLIBCXX_USE_LONG_LONG
00718   template<typename _CharT, typename _InIter>
00719     _InIter
00720     num_get<_CharT, _InIter>::
00721     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00722            ios_base::iostate& __err, long long& __v) const
00723     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00724 
00725   template<typename _CharT, typename _InIter>
00726     _InIter
00727     num_get<_CharT, _InIter>::
00728     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00729            ios_base::iostate& __err, unsigned long long& __v) const
00730     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00731 #endif
00732 
00733   template<typename _CharT, typename _InIter>
00734     _InIter
00735     num_get<_CharT, _InIter>::
00736     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00737        ios_base::iostate& __err, float& __v) const
00738     {
00739       string __xtrc;
00740       __xtrc.reserve(32);
00741       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00742       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00743       return __beg;
00744     }
00745 
00746   template<typename _CharT, typename _InIter>
00747     _InIter
00748     num_get<_CharT, _InIter>::
00749     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00750            ios_base::iostate& __err, double& __v) const
00751     {
00752       string __xtrc;
00753       __xtrc.reserve(32);
00754       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00755       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00756       return __beg;
00757     }
00758 
00759   template<typename _CharT, typename _InIter>
00760     _InIter
00761     num_get<_CharT, _InIter>::
00762     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00763            ios_base::iostate& __err, long double& __v) const
00764     {
00765       string __xtrc;
00766       __xtrc.reserve(32);
00767       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00768       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00769       return __beg;
00770     }
00771 
00772   template<typename _CharT, typename _InIter>
00773     _InIter
00774     num_get<_CharT, _InIter>::
00775     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00776            ios_base::iostate& __err, void*& __v) const
00777     {
00778       // Prepare for hex formatted input.
00779       typedef ios_base::fmtflags        fmtflags;
00780       const fmtflags __fmt = __io.flags();
00781       __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
00782 
00783       unsigned long __ul;
00784       __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
00785 
00786       // Reset from hex formatted input.
00787       __io.flags(__fmt);
00788 
00789       if (!(__err & ios_base::failbit))
00790     __v = reinterpret_cast<void*>(__ul);
00791       else
00792     __err |= ios_base::failbit;
00793       return __beg;
00794     }
00795 
00796   // For use by integer and floating-point types after they have been
00797   // converted into a char_type string.
00798   template<typename _CharT, typename _OutIter>
00799     void
00800     num_put<_CharT, _OutIter>::
00801     _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
00802        _CharT* __new, const _CharT* __cs, int& __len) const
00803     {
00804       // [22.2.2.2.2] Stage 3.
00805       // If necessary, pad.
00806       __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs,
00807                           __w, __len, true);
00808       __len = static_cast<int>(__w);
00809     }
00810 
00811   // Forwarding functions to peel signed from unsigned integer types.
00812   template<typename _CharT>
00813     inline int
00814     __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
00815           ios_base::fmtflags __flags)
00816     {
00817       unsigned long __ul = static_cast<unsigned long>(__v);
00818       bool __neg = false;
00819       if (__v < 0)
00820     {
00821       __ul = -__ul;
00822       __neg = true;
00823     }
00824       return __int_to_char(__bufend, __ul, __lit, __flags, __neg);
00825     }
00826 
00827   template<typename _CharT>
00828     inline int
00829     __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
00830           ios_base::fmtflags __flags)
00831     {
00832       // About showpos, see Table 60 and C99 7.19.6.1, p6 (+).
00833       return __int_to_char(__bufend, __v, __lit,
00834                __flags & ~ios_base::showpos, false);
00835     }
00836 
00837 #ifdef _GLIBCXX_USE_LONG_LONG
00838   template<typename _CharT>
00839     inline int
00840     __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
00841           ios_base::fmtflags __flags)
00842     {
00843       unsigned long long __ull = static_cast<unsigned long long>(__v);
00844       bool __neg = false;
00845       if (__v < 0)
00846     {
00847       __ull = -__ull;
00848       __neg = true;
00849     }
00850       return __int_to_char(__bufend, __ull, __lit, __flags, __neg);
00851     }
00852 
00853   template<typename _CharT>
00854     inline int
00855     __int_to_char(_CharT* __bufend, unsigned long long __v, 
00856           const _CharT* __lit, ios_base::fmtflags __flags)
00857     { return __int_to_char(__bufend, __v, __lit,
00858                __flags & ~ios_base::showpos, false); }
00859 #endif
00860 
00861   template<typename _CharT, typename _ValueT>
00862     int
00863     __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
00864           ios_base::fmtflags __flags, bool __neg)
00865     {
00866       // Don't write base if already 0.
00867       const bool __showbase = (__flags & ios_base::showbase) && __v;
00868       const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
00869       _CharT* __buf = __bufend - 1;
00870 
00871       if (__builtin_expect(__basefield != ios_base::oct &&
00872                __basefield != ios_base::hex, true))
00873     {
00874       // Decimal.
00875       do
00876         {
00877           *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits];
00878           __v /= 10;
00879         }
00880       while (__v != 0);
00881       if (__neg)
00882         *__buf-- = __lit[__num_base::_S_ominus];
00883       else if (__flags & ios_base::showpos)
00884         *__buf-- = __lit[__num_base::_S_oplus];
00885     }
00886       else if (__basefield == ios_base::oct)
00887     {
00888       // Octal.
00889       do
00890         {
00891           *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits];
00892           __v >>= 3;
00893         }
00894       while (__v != 0);
00895       if (__showbase)
00896         *__buf-- = __lit[__num_base::_S_odigits];
00897     }
00898       else
00899     {
00900       // Hex.
00901       const bool __uppercase = __flags & ios_base::uppercase;
00902       const int __case_offset = __uppercase ? __num_base::_S_oudigits
00903                                             : __num_base::_S_odigits;
00904       do
00905         {
00906           *__buf-- = __lit[(__v & 0xf) + __case_offset];
00907           __v >>= 4;
00908         }
00909       while (__v != 0);
00910       if (__showbase)
00911         {
00912           // 'x' or 'X'
00913           *__buf-- = __lit[__num_base::_S_ox + __uppercase];
00914           // '0'
00915           *__buf-- = __lit[__num_base::_S_odigits];
00916         }
00917     }
00918       return __bufend - __buf - 1;
00919     }
00920 
00921   template<typename _CharT, typename _OutIter>
00922     void
00923     num_put<_CharT, _OutIter>::
00924     _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
00925          ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const
00926     {
00927       // By itself __add_grouping cannot deal correctly with __cs when
00928       // ios::showbase is set and ios_base::oct || ios_base::hex.
00929       // Therefore we take care "by hand" of the initial 0, 0x or 0X.
00930       // However, remember that the latter do not occur if the number
00931       // printed is '0' (__len == 1).
00932       streamsize __off = 0;
00933       const ios_base::fmtflags __basefield = __io.flags()
00934                                          & ios_base::basefield;
00935       if ((__io.flags() & ios_base::showbase) && __len > 1)
00936     if (__basefield == ios_base::oct)
00937       {
00938         __off = 1;
00939         __new[0] = __cs[0];
00940       }
00941     else if (__basefield == ios_base::hex)
00942       {
00943         __off = 2;
00944         __new[0] = __cs[0];
00945         __new[1] = __cs[1];
00946       }
00947       _CharT* __p;
00948       __p = std::__add_grouping(__new + __off, __sep, __grouping,
00949                 __grouping_size, __cs + __off,
00950                 __cs + __len);
00951       __len = __p - __new;
00952     }
00953 
00954   template<typename _CharT, typename _OutIter>
00955     template<typename _ValueT>
00956       _OutIter
00957       num_put<_CharT, _OutIter>::
00958       _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
00959             _ValueT __v) const
00960       {
00961     typedef typename numpunct<_CharT>::__cache_type __cache_type;
00962     __use_cache<__cache_type> __uc;
00963     const locale& __loc = __io._M_getloc();
00964     const __cache_type* __lc = __uc(__loc);
00965     const _CharT* __lit = __lc->_M_atoms_out;
00966 
00967     // Long enough to hold hex, dec, and octal representations.
00968     const int __ilen = 4 * sizeof(_ValueT);
00969     _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
00970                                  * __ilen));
00971 
00972     // [22.2.2.2.2] Stage 1, numeric conversion to character.
00973     // Result is returned right-justified in the buffer.
00974     int __len;
00975     __len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags());
00976     __cs += __ilen - __len;
00977 
00978     // Add grouping, if necessary.
00979     if (__lc->_M_use_grouping)
00980       {
00981         // Grouping can add (almost) as many separators as the
00982         // number of digits, but no more.
00983         _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
00984                                   * __len * 2));
00985         _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
00986              __lc->_M_thousands_sep, __io, __cs2, __cs, __len);
00987         __cs = __cs2;
00988       }
00989 
00990     // Pad.
00991     const streamsize __w = __io.width();
00992     if (__w > static_cast<streamsize>(__len))
00993       {
00994         _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
00995                                   * __w));
00996         _M_pad(__fill, __w, __io, __cs3, __cs, __len);
00997         __cs = __cs3;
00998       }
00999     __io.width(0);
01000 
01001     // [22.2.2.2.2] Stage 4.
01002     // Write resulting, fully-formatted string to output iterator.
01003     return std::__write(__s, __cs, __len);
01004       }
01005 
01006   template<typename _CharT, typename _OutIter>
01007     void
01008     num_put<_CharT, _OutIter>::
01009     _M_group_float(const char* __grouping, size_t __grouping_size,
01010            _CharT __sep, const _CharT* __p, _CharT* __new,
01011            _CharT* __cs, int& __len) const
01012     {
01013       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01014       // 282. What types does numpunct grouping refer to?
01015       // Add grouping, if necessary.
01016       _CharT* __p2;
01017       const int __declen = __p ? __p - __cs : __len;
01018       __p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size,
01019                  __cs, __cs + __declen);
01020 
01021       // Tack on decimal part.
01022       int __newlen = __p2 - __new;
01023       if (__p)
01024     {
01025       char_traits<_CharT>::copy(__p2, __p, __len - __declen);
01026       __newlen += __len - __declen;
01027     }
01028       __len = __newlen;
01029     }
01030 
01031   // The following code uses snprintf (or sprintf(), when
01032   // _GLIBCXX_USE_C99 is not defined) to convert floating point values
01033   // for insertion into a stream.  An optimization would be to replace
01034   // them with code that works directly on a wide buffer and then use
01035   // __pad to do the padding.  It would be good to replace them anyway
01036   // to gain back the efficiency that C++ provides by knowing up front
01037   // the type of the values to insert.  Also, sprintf is dangerous
01038   // since may lead to accidental buffer overruns.  This
01039   // implementation follows the C++ standard fairly directly as
01040   // outlined in 22.2.2.2 [lib.locale.num.put]
01041   template<typename _CharT, typename _OutIter>
01042     template<typename _ValueT>
01043       _OutIter
01044       num_put<_CharT, _OutIter>::
01045       _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
01046                _ValueT __v) const
01047       {
01048     typedef typename numpunct<_CharT>::__cache_type __cache_type;
01049     __use_cache<__cache_type> __uc;
01050     const locale& __loc = __io._M_getloc();
01051     const __cache_type* __lc = __uc(__loc);
01052 
01053     // Use default precision if out of range.
01054     streamsize __prec = __io.precision();
01055     if (__prec < static_cast<streamsize>(0))
01056       __prec = static_cast<streamsize>(6);
01057 
01058     const int __max_digits = numeric_limits<_ValueT>::digits10;
01059 
01060     // [22.2.2.2.2] Stage 1, numeric conversion to character.
01061     int __len;
01062     // Long enough for the max format spec.
01063     char __fbuf[16];
01064 
01065 #ifdef _GLIBCXX_USE_C99
01066     // First try a buffer perhaps big enough (most probably sufficient
01067     // for non-ios_base::fixed outputs)
01068     int __cs_size = __max_digits * 3;
01069     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01070 
01071     __num_base::_S_format_float(__io, __fbuf, __mod);
01072     __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
01073                       _S_get_c_locale(), __prec);
01074 
01075     // If the buffer was not large enough, try again with the correct size.
01076     if (__len >= __cs_size)
01077       {
01078         __cs_size = __len + 1;
01079         __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01080         __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
01081                       _S_get_c_locale(), __prec);
01082       }
01083 #else
01084     // Consider the possibility of long ios_base::fixed outputs
01085     const bool __fixed = __io.flags() & ios_base::fixed;
01086     const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
01087 
01088     // The size of the output string is computed as follows.
01089     // ios_base::fixed outputs may need up to __max_exp + 1 chars
01090     // for the integer part + __prec chars for the fractional part
01091     // + 3 chars for sign, decimal point, '\0'. On the other hand,
01092     // for non-fixed outputs __max_digits * 2 + __prec chars are
01093     // largely sufficient.
01094     const int __cs_size = __fixed ? __max_exp + __prec + 4
01095                                   : __max_digits * 2 + __prec;
01096     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01097 
01098     __num_base::_S_format_float(__io, __fbuf, __mod);
01099     __len = std::__convert_from_v(__cs, 0, __fbuf, __v,
01100                       _S_get_c_locale(), __prec);
01101 #endif
01102 
01103       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
01104       // numpunct.decimal_point() values for '.' and adding grouping.
01105       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01106 
01107       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01108                                * __len));
01109       __ctype.widen(__cs, __cs + __len, __ws);
01110 
01111       // Replace decimal point.
01112       const _CharT __cdec = __ctype.widen('.');
01113       const _CharT __dec = __lc->_M_decimal_point;
01114       const _CharT* __p;
01115       if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
01116     __ws[__p - __ws] = __dec;
01117 
01118       // Add grouping, if necessary.
01119       if (__lc->_M_use_grouping)
01120     {
01121       // Grouping can add (almost) as many separators as the
01122       // number of digits, but no more.
01123       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01124                                 * __len * 2));
01125       _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
01126              __lc->_M_thousands_sep, __p, __ws2, __ws, __len);
01127       __ws = __ws2;
01128     }
01129 
01130       // Pad.
01131       const streamsize __w = __io.width();
01132       if (__w > static_cast<streamsize>(__len))
01133     {
01134       _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01135                                 * __w));
01136       _M_pad(__fill, __w, __io, __ws3, __ws, __len);
01137       __ws = __ws3;
01138     }
01139       __io.width(0);
01140 
01141       // [22.2.2.2.2] Stage 4.
01142       // Write resulting, fully-formatted string to output iterator.
01143       return std::__write(__s, __ws, __len);
01144       }
01145 
01146   template<typename _CharT, typename _OutIter>
01147     _OutIter
01148     num_put<_CharT, _OutIter>::
01149     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
01150     {
01151       const ios_base::fmtflags __flags = __io.flags();
01152       if ((__flags & ios_base::boolalpha) == 0)
01153         {
01154           const long __l = __v;
01155           __s = _M_insert_int(__s, __io, __fill, __l);
01156         }
01157       else
01158         {
01159       typedef typename numpunct<_CharT>::__cache_type __cache_type;
01160       __use_cache<__cache_type> __uc;
01161       const locale& __loc = __io._M_getloc();
01162       const __cache_type* __lc = __uc(__loc);
01163 
01164       const _CharT* __name = __v ? __lc->_M_truename
01165                                  : __lc->_M_falsename;
01166       int __len = __v ? __lc->_M_truename_size
01167                       : __lc->_M_falsename_size;
01168 
01169       const streamsize __w = __io.width();
01170       if (__w > static_cast<streamsize>(__len))
01171         {
01172           _CharT* __cs
01173         = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01174                             * __w));
01175           _M_pad(__fill, __w, __io, __cs, __name, __len);
01176           __name = __cs;
01177         }
01178       __io.width(0);
01179       __s = std::__write(__s, __name, __len);
01180     }
01181       return __s;
01182     }
01183 
01184   template<typename _CharT, typename _OutIter>
01185     _OutIter
01186     num_put<_CharT, _OutIter>::
01187     do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
01188     { return _M_insert_int(__s, __io, __fill, __v); }
01189 
01190   template<typename _CharT, typename _OutIter>
01191     _OutIter
01192     num_put<_CharT, _OutIter>::
01193     do_put(iter_type __s, ios_base& __io, char_type __fill,
01194            unsigned long __v) const
01195     { return _M_insert_int(__s, __io, __fill, __v); }
01196 
01197 #ifdef _GLIBCXX_USE_LONG_LONG
01198   template<typename _CharT, typename _OutIter>
01199     _OutIter
01200     num_put<_CharT, _OutIter>::
01201     do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
01202     { return _M_insert_int(__s, __b, __fill, __v); }
01203 
01204   template<typename _CharT, typename _OutIter>
01205     _OutIter
01206     num_put<_CharT, _OutIter>::
01207     do_put(iter_type __s, ios_base& __io, char_type __fill,
01208            unsigned long long __v) const
01209     { return _M_insert_int(__s, __io, __fill, __v); }
01210 #endif
01211 
01212   template<typename _CharT, typename _OutIter>
01213     _OutIter
01214     num_put<_CharT, _OutIter>::
01215     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
01216     { return _M_insert_float(__s, __io, __fill, char(), __v); }
01217 
01218   template<typename _CharT, typename _OutIter>
01219     _OutIter
01220     num_put<_CharT, _OutIter>::
01221     do_put(iter_type __s, ios_base& __io, char_type __fill,
01222        long double __v) const
01223     { return _M_insert_float(__s, __io, __fill, 'L', __v); }
01224 
01225   template<typename _CharT, typename _OutIter>
01226     _OutIter
01227     num_put<_CharT, _OutIter>::
01228     do_put(iter_type __s, ios_base& __io, char_type __fill,
01229            const void* __v) const
01230     {
01231       const ios_base::fmtflags __flags = __io.flags();
01232       const ios_base::fmtflags __fmt = ~(ios_base::basefield
01233                      | ios_base::uppercase
01234                      | ios_base::internal);
01235       __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
01236 
01237       __s = _M_insert_int(__s, __io, __fill,
01238               reinterpret_cast<unsigned long>(__v));
01239       __io.flags(__flags);
01240       return __s;
01241     }
01242 
01243   template<typename _CharT, typename _InIter>
01244     template<bool _Intl>
01245       _InIter
01246       money_get<_CharT, _InIter>::
01247       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
01248          ios_base::iostate& __err, string& __units) const
01249       {
01250     typedef char_traits<_CharT>           __traits_type;
01251     typedef typename string_type::size_type           size_type;    
01252     typedef money_base::part              part;
01253     typedef moneypunct<_CharT, _Intl>         __moneypunct_type;
01254     typedef typename __moneypunct_type::__cache_type  __cache_type;
01255     
01256     const locale& __loc = __io._M_getloc();
01257     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01258 
01259     __use_cache<__cache_type> __uc;
01260     const __cache_type* __lc = __uc(__loc);
01261     const char_type* __lit = __lc->_M_atoms;
01262 
01263     // Deduced sign.
01264     bool __negative = false;
01265     // Sign size.
01266     size_type __sign_size = 0;
01267     // True if sign is mandatory.
01268     const bool __mandatory_sign = (__lc->_M_positive_sign_size
01269                        && __lc->_M_negative_sign_size);
01270     // String of grouping info from thousands_sep plucked from __units.
01271     string __grouping_tmp;
01272     if (__lc->_M_use_grouping)
01273       __grouping_tmp.reserve(32);
01274     // Last position before the decimal point.
01275     int __last_pos = 0;
01276     // Separator positions, then, possibly, fractional digits.
01277     int __n = 0;
01278     // If input iterator is in a valid state.
01279     bool __testvalid = true;
01280     // Flag marking when a decimal point is found.
01281     bool __testdecfound = false;
01282 
01283     // The tentative returned string is stored here.
01284     string __res;
01285     __res.reserve(32);
01286 
01287     const char_type* __lit_zero = __lit + money_base::_S_zero;
01288     const char_type* __q;
01289     const money_base::pattern __p = __lc->_M_neg_format;    
01290     for (int __i = 0; __i < 4 && __testvalid; ++__i)
01291       {
01292         const part __which = static_cast<part>(__p.field[__i]);
01293         switch (__which)
01294           {
01295           case money_base::symbol:
01296         // According to 22.2.6.1.2, p2, symbol is required
01297         // if (__io.flags() & ios_base::showbase), otherwise
01298         // is optional and consumed only if other characters
01299         // are needed to complete the format.
01300         if (__io.flags() & ios_base::showbase || __sign_size > 1
01301             || __i == 0
01302             || (__i == 1 && (__mandatory_sign
01303                      || (static_cast<part>(__p.field[0])
01304                      == money_base::sign)
01305                      || (static_cast<part>(__p.field[2])
01306                      == money_base::space)))
01307             || (__i == 2 && ((static_cast<part>(__p.field[3])
01308                       == money_base::value)
01309                      || __mandatory_sign
01310                      && (static_cast<part>(__p.field[3])
01311                      == money_base::sign))))
01312           {
01313             const size_type __len = __lc->_M_curr_symbol_size;
01314             size_type __j = 0;
01315             for (; __beg != __end && __j < __len
01316                && *__beg == __lc->_M_curr_symbol[__j];
01317              ++__beg, ++__j);
01318             if (__j != __len
01319             && (__j || __io.flags() & ios_base::showbase))
01320               __testvalid = false;
01321           }
01322         break;
01323           case money_base::sign:
01324         // Sign might not exist, or be more than one character long.
01325         if (__lc->_M_positive_sign_size && __beg != __end
01326             && *__beg == __lc->_M_positive_sign[0])
01327           {
01328             __sign_size = __lc->_M_positive_sign_size;
01329             ++__beg;
01330           }
01331         else if (__lc->_M_negative_sign_size && __beg != __end
01332              && *__beg == __lc->_M_negative_sign[0])
01333           {
01334             __negative = true;
01335             __sign_size = __lc->_M_negative_sign_size;
01336             ++__beg;
01337           }
01338         else if (__lc->_M_positive_sign_size
01339              && !__lc->_M_negative_sign_size)
01340           // "... if no sign is detected, the result is given the sign
01341           // that corresponds to the source of the empty string"
01342           __negative = true;
01343         else if (__mandatory_sign)
01344           __testvalid = false;
01345         break;
01346           case money_base::value:
01347         // Extract digits, remove and stash away the
01348         // grouping of found thousands separators.
01349         for (; __beg != __end; ++__beg)
01350           if (__q = __traits_type::find(__lit_zero, 10, *__beg))
01351             {
01352               __res += money_base::_S_atoms[__q - __lit];
01353               ++__n;
01354             }
01355           else if (*__beg == __lc->_M_decimal_point && !__testdecfound)
01356             {
01357               __last_pos = __n;
01358               __n = 0;
01359               __testdecfound = true;
01360             }
01361           else if (__lc->_M_use_grouping
01362                && *__beg == __lc->_M_thousands_sep
01363                && !__testdecfound)
01364             {
01365               if (__n)
01366             {
01367               // Mark position for later analysis.
01368               __grouping_tmp += static_cast<char>(__n);
01369               __n = 0;
01370             }
01371               else
01372             {
01373               __testvalid = false;
01374               break;
01375             }
01376             }
01377           else
01378             break;
01379         if (__res.empty())
01380           __testvalid = false;
01381         break;
01382           case money_base::space:
01383         // At least one space is required.
01384         if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
01385           ++__beg;
01386         else
01387           __testvalid = false;
01388           case money_base::none:
01389         // Only if not at the end of the pattern.
01390         if (__i != 3)
01391           for (; __beg != __end
01392              && __ctype.is(ctype_base::space, *__beg); ++__beg);
01393         break;
01394           }
01395       }
01396 
01397     // Need to get the rest of the sign characters, if they exist.
01398     if (__sign_size > 1 && __testvalid)
01399       {
01400         const char_type* __sign = __negative ? __lc->_M_negative_sign
01401                                              : __lc->_M_positive_sign;
01402         size_type __i = 1;
01403         for (; __beg != __end && __i < __sign_size
01404            && *__beg == __sign[__i]; ++__beg, ++__i);
01405         
01406         if (__i != __sign_size)
01407           __testvalid = false;
01408       }
01409 
01410     if (__testvalid)
01411       {
01412         // Strip leading zeros.
01413         if (__res.size() > 1)
01414           {
01415         const size_type __first = __res.find_first_not_of('0');
01416         const bool __only_zeros = __first == string::npos;
01417         if (__first)
01418           __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
01419           }
01420 
01421         // 22.2.6.1.2, p4
01422         if (__negative && __res[0] != '0')
01423           __res.insert(__res.begin(), '-');
01424         
01425         // Test for grouping fidelity.
01426         if (__grouping_tmp.size())
01427           {
01428         // Add the ending grouping.
01429         __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
01430                                            : __n);
01431         if (!std::__verify_grouping(__lc->_M_grouping,
01432                         __lc->_M_grouping_size,
01433                         __grouping_tmp))
01434           __testvalid = false;
01435           }
01436         
01437         // Iff not enough digits were supplied after the decimal-point.
01438         if (__testdecfound && __lc->_M_frac_digits > 0
01439         && __n != __lc->_M_frac_digits)
01440           __testvalid = false;
01441       }
01442     
01443     // Iff no more characters are available.
01444     if (__beg == __end)
01445       __err |= ios_base::eofbit;
01446     
01447     // Iff valid sequence is not recognized.
01448     if (!__testvalid)
01449       __err |= ios_base::failbit;
01450     else
01451       __units.swap(__res);
01452     
01453     return __beg;
01454       }
01455 
01456   template<typename _CharT, typename _InIter>
01457     _InIter
01458     money_get<_CharT, _InIter>::
01459     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
01460        ios_base::iostate& __err, long double& __units) const
01461     {
01462       string __str;
01463       if (__intl)
01464     __beg = _M_extract<true>(__beg, __end, __io, __err, __str);
01465       else
01466     __beg = _M_extract<false>(__beg, __end, __io, __err, __str);
01467       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
01468       return __beg;
01469     }
01470 
01471   template<typename _CharT, typename _InIter>
01472     _InIter
01473     money_get<_CharT, _InIter>::
01474     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
01475        ios_base::iostate& __err, string_type& __units) const
01476     {
01477       typedef typename string::size_type                  size_type;
01478 
01479       const locale& __loc = __io._M_getloc();
01480       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01481 
01482       string __str;
01483       const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io,
01484                             __err, __str)
01485                                  : _M_extract<false>(__beg, __end, __io,
01486                              __err, __str);
01487       const size_type __len = __str.size();
01488       if (__len)
01489     {
01490       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01491                                    * __len));
01492       __ctype.widen(__str.data(), __str.data() + __len, __ws);
01493       __units.assign(__ws, __len);
01494     }
01495 
01496       return __ret;
01497     }
01498 
01499   template<typename _CharT, typename _OutIter>
01500     template<bool _Intl>
01501       _OutIter
01502       money_put<_CharT, _OutIter>::
01503       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
01504         const string_type& __digits) const
01505       {
01506     typedef typename string_type::size_type           size_type;
01507     typedef money_base::part                          part;
01508     typedef moneypunct<_CharT, _Intl>                 __moneypunct_type;
01509     typedef typename __moneypunct_type::__cache_type  __cache_type;
01510       
01511     const locale& __loc = __io._M_getloc();
01512     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01513 
01514     __use_cache<__cache_type> __uc;
01515     const __cache_type* __lc = __uc(__loc);
01516     const char_type* __lit = __lc->_M_atoms;
01517 
01518     // Determine if negative or positive formats are to be used, and
01519     // discard leading negative_sign if it is present.
01520     const char_type* __beg = __digits.data();
01521 
01522     money_base::pattern __p;
01523     const char_type* __sign;
01524     size_type __sign_size;
01525     if (*__beg != __lit[money_base::_S_minus])
01526       {
01527         __p = __lc->_M_pos_format;
01528         __sign = __lc->_M_positive_sign;
01529         __sign_size = __lc->_M_positive_sign_size;
01530       }
01531     else
01532       {
01533         __p = __lc->_M_neg_format;
01534         __sign = __lc->_M_negative_sign;
01535         __sign_size = __lc->_M_negative_sign_size;
01536         if (__digits.size())
01537           ++__beg;
01538       }
01539        
01540     // Look for valid numbers in the ctype facet within input digits.
01541     size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
01542                        __beg + __digits.size()) - __beg;
01543     if (__len)
01544       {
01545         // Assume valid input, and attempt to format.
01546         // Break down input numbers into base components, as follows:
01547         //   final_value = grouped units + (decimal point) + (digits)
01548         string_type __value;
01549         __value.reserve(2 * __len);
01550 
01551         // Add thousands separators to non-decimal digits, per
01552         // grouping rules.
01553         int __paddec = __len - __lc->_M_frac_digits;
01554         if (__paddec > 0)
01555           {
01556         if (__lc->_M_frac_digits < 0)
01557           __paddec = __len;
01558         if (__lc->_M_grouping_size)
01559           {
01560             _CharT* __ws =
01561               static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01562                                 * 2 * __len));
01563             _CharT* __ws_end =
01564               std::__add_grouping(__ws, __lc->_M_thousands_sep,
01565                       __lc->_M_grouping,
01566                       __lc->_M_grouping_size,
01567                       __beg, __beg + __paddec);
01568             __value.assign(__ws, __ws_end - __ws);
01569           }
01570         else
01571           __value.assign(__beg, __paddec);
01572           }
01573 
01574         // Deal with decimal point, decimal digits.
01575         if (__lc->_M_frac_digits > 0)
01576           {
01577         __value += __lc->_M_decimal_point;
01578         if (__paddec >= 0)
01579           __value.append(__beg + __paddec, __lc->_M_frac_digits);
01580         else
01581           {
01582             // Have to pad zeros in the decimal position.
01583             __value.append(-__paddec, __lit[money_base::_S_zero]);
01584             __value.append(__beg, __len);
01585           }
01586           }
01587   
01588         // Calculate length of resulting string.
01589         const ios_base::fmtflags __f = __io.flags() 
01590                                        & ios_base::adjustfield;
01591         __len = __value.size() + __sign_size;
01592         __len += ((__io.flags() & ios_base::showbase)
01593               ? __lc->_M_curr_symbol_size : 0);
01594 
01595         string_type __res;
01596         __res.reserve(2 * __len);
01597         
01598         const size_type __width = static_cast<size_type>(__io.width());  
01599         const bool __testipad = (__f == ios_base::internal
01600                      && __len < __width);
01601         // Fit formatted digits into the required pattern.
01602         for (int __i = 0; __i < 4; ++__i)
01603           {
01604         const part __which = static_cast<part>(__p.field[__i]);
01605         switch (__which)
01606           {
01607           case money_base::symbol:
01608             if (__io.flags() & ios_base::showbase)
01609               __res.append(__lc->_M_curr_symbol,
01610                    __lc->_M_curr_symbol_size);
01611             break;
01612           case money_base::sign:
01613             // Sign might not exist, or be more than one
01614             // charater long. In that case, add in the rest
01615             // below.
01616             if (__sign_size)
01617               __res += __sign[0];
01618             break;
01619           case money_base::value:
01620             __res += __value;
01621             break;
01622           case money_base::space:
01623             // At least one space is required, but if internal
01624             // formatting is required, an arbitrary number of
01625             // fill spaces will be necessary.
01626             if (__testipad)
01627               __res.append(__width - __len, __fill);
01628             else
01629               __res += __fill;
01630             break;
01631           case money_base::none:
01632             if (__testipad)
01633               __res.append(__width - __len, __fill);
01634             break;
01635           }
01636           }
01637         
01638         // Special case of multi-part sign parts.
01639         if (__sign_size > 1)
01640           __res.append(__sign + 1, __sign_size - 1);
01641         
01642         // Pad, if still necessary.
01643         __len = __res.size();
01644         if (__width > __len)
01645           {
01646         if (__f == ios_base::left)
01647           // After.
01648           __res.append(__width - __len, __fill);
01649         else
01650           // Before.
01651           __res.insert(0, __width - __len, __fill);
01652         __len = __width;
01653           }
01654         
01655         // Write resulting, fully-formatted string to output iterator.
01656         __s = std::__write(__s, __res.data(), __len);
01657       }
01658     __io.width(0);
01659     return __s;    
01660       }
01661   
01662   template<typename _CharT, typename _OutIter>
01663     _OutIter
01664     money_put<_CharT, _OutIter>::
01665     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01666        long double __units) const
01667     {
01668       const locale __loc = __io.getloc();
01669       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01670 #ifdef _GLIBCXX_USE_C99
01671       // First try a buffer perhaps big enough.
01672       int __cs_size = 64;
01673       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01674       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01675       // 328. Bad sprintf format modifier in money_put<>::do_put()
01676       int __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
01677                     _S_get_c_locale(), 0);
01678       // If the buffer was not large enough, try again with the correct size.
01679       if (__len >= __cs_size)
01680     {
01681       __cs_size = __len + 1;
01682       __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01683       __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
01684                     _S_get_c_locale(), 0);
01685     }
01686 #else
01687       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
01688       const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
01689       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01690       int __len = std::__convert_from_v(__cs, 0, "%.*Lf", __units,
01691                     _S_get_c_locale(), 0);
01692 #endif
01693       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01694                                * __cs_size));
01695       __ctype.widen(__cs, __cs + __len, __ws);
01696       const string_type __digits(__ws, __len);
01697       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
01698                 : _M_insert<false>(__s, __io, __fill, __digits);
01699     }
01700 
01701   template<typename _CharT, typename _OutIter>
01702     _OutIter
01703     money_put<_CharT, _OutIter>::
01704     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01705        const string_type& __digits) const
01706     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
01707                 : _M_insert<false>(__s, __io, __fill, __digits); }
01708 
01709 
01710   // NB: Not especially useful. Without an ios_base object or some
01711   // kind of locale reference, we are left clawing at the air where
01712   // the side of the mountain used to be...
01713   template<typename _CharT, typename _InIter>
01714     time_base::dateorder
01715     time_get<_CharT, _InIter>::do_date_order() const
01716     { return time_base::no_order; }
01717 
01718   // Expand a strftime format string and parse it.  E.g., do_get_date() may
01719   // pass %m/%d/%Y => extracted characters.
01720   template<typename _CharT, typename _InIter>
01721     _InIter
01722     time_get<_CharT, _InIter>::
01723     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
01724               ios_base::iostate& __err, tm* __tm,
01725               const _CharT* __format) const
01726     {
01727       const locale& __loc = __io._M_getloc();
01728       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01729       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01730       const size_t __len = char_traits<_CharT>::length(__format);
01731 
01732       for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
01733     {
01734       if (__ctype.narrow(__format[__i], 0) == '%')
01735         {
01736           // Verify valid formatting code, attempt to extract.
01737           char __c = __ctype.narrow(__format[++__i], 0);
01738           int __mem = 0;
01739           if (__c == 'E' || __c == 'O')
01740         __c = __ctype.narrow(__format[++__i], 0);
01741           switch (__c)
01742         {
01743           const char* __cs;
01744           _CharT __wcs[10];
01745         case 'a':
01746           // Abbreviated weekday name [tm_wday]
01747           const char_type*  __days1[7];
01748           __tp._M_days_abbreviated(__days1);
01749           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
01750                       7, __io, __err);
01751           break;
01752         case 'A':
01753           // Weekday name [tm_wday].
01754           const char_type*  __days2[7];
01755           __tp._M_days(__days2);
01756           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
01757                       7, __io, __err);
01758           break;
01759         case 'h':
01760         case 'b':
01761           // Abbreviated month name [tm_mon]
01762           const char_type*  __months1[12];
01763           __tp._M_months_abbreviated(__months1);
01764           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
01765                       __months1, 12, __io, __err);
01766           break;
01767         case 'B':
01768           // Month name [tm_mon].
01769           const char_type*  __months2[12];
01770           __tp._M_months(__months2);
01771           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
01772                       __months2, 12, __io, __err);
01773           break;
01774         case 'c':
01775           // Default time and date representation.
01776           const char_type*  __dt[2];
01777           __tp._M_date_time_formats(__dt);
01778           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01779                         __tm, __dt[0]);
01780           break;
01781         case 'd':
01782           // Day [01, 31]. [tm_mday]
01783           __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
01784                      __io, __err);
01785           break;
01786         case 'e':
01787           // Day [1, 31], with single digits preceded by
01788           // space. [tm_mday]
01789           if (__ctype.is(ctype_base::space, *__beg))
01790             __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
01791                        1, __io, __err);
01792           else
01793             __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
01794                        2, __io, __err);
01795           break;
01796         case 'D':
01797           // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
01798           __cs = "%m/%d/%y";
01799           __ctype.widen(__cs, __cs + 9, __wcs);
01800           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01801                         __tm, __wcs);
01802           break;
01803         case 'H':
01804           // Hour [00, 23]. [tm_hour]
01805           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
01806                      __io, __err);
01807           break;
01808         case 'I':
01809           // Hour [01, 12]. [tm_hour]
01810           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
01811                      __io, __err);
01812           break;
01813         case 'm':
01814           // Month [01, 12]. [tm_mon]
01815           __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
01816                      __io, __err);
01817           if (!__err)
01818             __tm->tm_mon = __mem - 1;
01819           break;
01820         case 'M':
01821           // Minute [00, 59]. [tm_min]
01822           __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
01823                      __io, __err);
01824           break;
01825         case 'n':
01826           if (__ctype.narrow(*__beg, 0) == '\n')
01827             ++__beg;
01828           else
01829             __err |= ios_base::failbit;
01830           break;
01831         case 'R':
01832           // Equivalent to (%H:%M).
01833           __cs = "%H:%M";
01834           __ctype.widen(__cs, __cs + 6, __wcs);
01835           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01836                         __tm, __wcs);
01837           break;
01838         case 'S':
01839           // Seconds. [tm_sec]
01840           // [00, 60] in C99 (one leap-second), [00, 61] in C89.
01841 #ifdef _GLIBCXX_USE_C99
01842           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
01843 #else
01844           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
01845 #endif
01846                      __io, __err);
01847           break;
01848         case 't':
01849           if (__ctype.narrow(*__beg, 0) == '\t')
01850             ++__beg;
01851           else
01852             __err |= ios_base::failbit;
01853           break;
01854         case 'T':
01855           // Equivalent to (%H:%M:%S).
01856           __cs = "%H:%M:%S";
01857           __ctype.