Whole document tree
    

Whole document tree

locale_facets.tcc Source File
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

locale_facets.tcc

Go to the documentation of this file.
00001 // Locale support -*- C++ -*-
00002 
00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 // Warning: this file is not meant for user inclusion.  Use <locale>.
00031 
00032 #ifndef _CPP_BITS_LOCFACETS_TCC
00033 #define _CPP_BITS_LOCFACETS_TCC 1
00034 
00035 #include <bits/std_cerrno.h>
00036 #include <bits/std_clocale.h>   // For localeconv
00037 #include <bits/std_cstdlib.h>   // For strof, strtold
00038 #include <bits/std_limits.h>    // For numeric_limits
00039 #include <bits/std_memory.h>    // For auto_ptr
00040 #include <bits/sbuf_iter.h>     // For streambuf_iterators
00041 #include <bits/std_cctype.h>    // For isspace
00042 #include <typeinfo>         // For bad_cast
00043 #include <bits/std_vector.h>    
00044 
00045 
00046 namespace std
00047 {
00048   template<typename _Facet>
00049     locale
00050     locale::combine(const locale& __other)
00051     {
00052       locale __copy(*this);
00053       __copy._M_impl->_M_replace_facet(__other._M_impl, &_Facet::id);
00054       return __copy;
00055     }
00056 
00057   template<typename _CharT, typename _Traits, typename _Alloc>
00058     bool
00059     locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
00060                        const basic_string<_CharT, _Traits, _Alloc>& __s2) const
00061     {
00062       typedef std::collate<_CharT> __collate_type;
00063       const __collate_type* __fcoll = &use_facet<__collate_type>(*this);
00064       return (__fcoll->compare(__s1.data(), __s1.data() + __s1.length(),
00065                                __s2.data(), __s2.data() + __s2.length()) < 0);
00066     }
00067 
00068   template<typename _Facet>
00069     const _Facet&
00070     use_facet(const locale& __loc)
00071     {
00072       typedef locale::_Impl::__vec_facet        __vec_facet;
00073       size_t __i = _Facet::id._M_index;
00074       __vec_facet* __facet = __loc._M_impl->_M_facets;
00075       const locale::facet* __fp = (*__facet)[__i]; 
00076       if (__fp == 0 || __i >= __facet->size())
00077         __throw_bad_cast();
00078       return static_cast<const _Facet&>(*__fp);
00079     }
00080 
00081   template<typename _Facet>
00082     bool
00083     has_facet(const locale& __loc) throw()
00084     {
00085       typedef locale::_Impl::__vec_facet        __vec_facet;
00086       size_t __i = _Facet::id._M_index;
00087       __vec_facet* __facet = __loc._M_impl->_M_facets;
00088       return (__i < __facet->size() && (*__facet)[__i] != 0);
00089     }
00090 
00091   // __match_parallel
00092   // matches input __s against a set of __ntargs strings in __targets,
00093   // placing in __matches a vector of indices into __targets which
00094   // match, and in __remain the number of such matches. If it hits
00095   // end of sequence before it minimizes the set, sets __eof.
00096   // Empty strings are never matched.
00097   template<typename _InIter, typename _CharT>
00098     _InIter
00099     __match_parallel(_InIter __s, _InIter __end, int __ntargs,
00100                      const basic_string<_CharT>* __targets,
00101                      int* __matches, int& __remain, bool& __eof)
00102     {
00103       typedef basic_string<_CharT> __string_type;
00104       __eof = false;
00105       for (int __ti = 0; __ti < __ntargs; ++__ti)
00106         __matches[__ti] = __ti;
00107       __remain = __ntargs;
00108       size_t __pos = 0;
00109       do
00110         {
00111       int __ti = 0;
00112       while (__ti < __remain && __pos == __targets[__matches[__ti]].size())
00113         ++__ti;
00114       if (__ti == __remain)
00115         {
00116           if (__pos == 0) __remain = 0;
00117           return __s;
00118         }
00119           if (__s == __end)
00120             __eof = true;
00121           bool __matched = false;
00122           for (int __ti2 = 0; __ti2 < __remain; )
00123             {
00124               const __string_type& __target = __targets[__matches[__ti2]];
00125               if (__pos < __target.size())
00126                 {
00127                   if (__eof || __target[__pos] != *__s)
00128                     {
00129                       __matches[__ti2] = __matches[--__remain];
00130                       continue;
00131                     }
00132                   __matched = true;
00133                 }
00134               ++__ti2;
00135             }
00136           if (__matched)
00137             {
00138               ++__s;
00139               ++__pos;
00140             }
00141           for (int __ti3 = 0; __ti3 < __remain;)
00142             {
00143               if (__pos > __targets[__matches[__ti3]].size())
00144                 {
00145                   __matches[__ti3] = __matches[--__remain];
00146                   continue;
00147                 }
00148               ++__ti3;
00149             }
00150         }
00151       while (__remain);
00152       return __s;
00153     }
00154 
00155   template<typename _CharT>
00156     _Format_cache<_CharT>::_Format_cache()
00157     : _M_valid(true), _M_use_grouping(false)
00158     { }
00159 
00160   template<>
00161     _Format_cache<char>::_Format_cache();
00162 
00163   template<>
00164     _Format_cache<wchar_t>::_Format_cache();
00165 
00166   template<typename _CharT>
00167     void
00168     _Format_cache<_CharT>::_M_populate(ios_base& __io)
00169     {
00170       locale __loc = __io.getloc ();
00171       numpunct<_CharT> const& __np = use_facet<numpunct<_CharT> >(__loc);
00172       _M_truename = __np.truename();
00173       _M_falsename = __np.falsename();
00174       _M_thousands_sep = __np.thousands_sep();
00175       _M_decimal_point = __np.decimal_point();
00176       _M_grouping = __np.grouping();
00177       _M_use_grouping = _M_grouping.size() != 0 && _M_grouping.data()[0] != 0;
00178       _M_valid = true;
00179     }
00180 
00181   // This function is always called via a pointer installed in
00182   // an ios_base by ios_base::register_callback.
00183   template<typename _CharT>
00184     void
00185     _Format_cache<_CharT>::
00186     _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw()
00187     {
00188       void*& __p = __ios.pword(__ix);
00189       switch (__ev)
00190         {
00191         case ios_base::erase_event:
00192           delete static_cast<_Format_cache<_CharT>*>(__p);
00193       __p = 0;
00194           break;
00195         case ios_base::copyfmt_event:
00196           // If just stored zero, the callback would get registered again.
00197           try 
00198         { __p = new _Format_cache<_CharT>; }
00199           catch(...) 
00200         { }
00201           break;
00202         case ios_base::imbue_event:
00203           static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false;
00204           break;
00205         }
00206     }
00207 
00208   template<typename _CharT>
00209     _Format_cache<_CharT>*
00210     _Format_cache<_CharT>::_S_get(ios_base& __ios)
00211     {
00212       if (!_S_pword_ix)
00213         _S_pword_ix = ios_base::xalloc();  // XXX MT
00214       void*& __p = __ios.pword(_S_pword_ix);
00215 
00216       // XXX What if pword fails? must check failbit, throw.
00217       if (__p == 0)  // XXX MT?  maybe sentry takes care of it
00218         {
00219           auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>);
00220           __ios.register_callback(&_Format_cache<_CharT>::_S_callback,
00221                                   _S_pword_ix);
00222           __p = __ap.release();
00223         }
00224       _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p);
00225       if (!__ncp->_M_valid)
00226         __ncp->_M_populate(__ios);
00227 
00228       return __ncp;
00229     }
00230 
00231   // This member function takes an (w)istreambuf_iterator object and
00232   // parses it into a generic char array suitable for parsing with
00233   // strto[l,ll,f,d]. The thought was to encapsulate the conversion
00234   // into this one function, and thus the num_get::do_get member
00235   // functions can just adjust for the type of the overloaded
00236   // argument and process the char array returned from _M_extract.
00237   // Other things were also considered, including a fused
00238   // multiply-add loop that would obviate the need for any call to
00239   // strto... at all: however, it would b e a bit of a pain, because
00240   // you'd have to be able to return either floating or integral
00241   // types, etc etc. The current approach seems to be smack dab in
00242   // the middle between an unoptimized approach using sscanf, and
00243   // some kind of hyper-optimized approach alluded to above.
00244 
00245   // XXX
00246   // Need to do partial specialization to account for differences
00247   // between character sets. For char, this is pretty
00248   // straightforward, but for wchar_t, the conversion to a plain-jane
00249   // char type is a bit more involved.
00250   template<typename _CharT, typename _InIter>
00251     void
00252     num_get<_CharT, _InIter>::
00253     _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/,
00254                ios_base::iostate& /*__err*/, char* /*__xtrc*/,
00255                int& /*__base*/, bool /*__fp*/) const
00256     {
00257       // XXX Not currently done: need to expand upon char version below.
00258     }
00259 
00260   template<>
00261     void
00262     num_get<char, istreambuf_iterator<char> >::
00263     _M_extract(istreambuf_iterator<char> __beg, 
00264            istreambuf_iterator<char> __end, ios_base& __io, 
00265            ios_base::iostate& __err, char* __xtrc, int& __base, 
00266            bool __fp) const;
00267 
00268 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
00269   // NB: This is an unresolved library defect #17
00270   template<typename _CharT, typename _InIter>
00271     _InIter
00272     num_get<_CharT, _InIter>::
00273     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00274            ios_base::iostate& __err, bool& __v) const
00275     {
00276       // Parse bool values as long
00277       if (!(__io.flags() & ios_base::boolalpha))
00278         {
00279           // NB: We can't just call do_get(long) here, as it might
00280           // refer to a derived class.
00281 
00282           // Stage 1: extract and determine the conversion specifier.
00283           // Assuming leading zeros eliminated, thus the size of 32 for
00284           // integral types.
00285           char __xtrc[_M_extract_buffer_length] = {'\0'};
00286           int __base;
00287           _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00288 
00289           // Stage 2: convert and store results.
00290           char* __sanity;
00291           errno = 0;
00292           long __l = strtol(__xtrc, &__sanity, __base);
00293           if (!(__err & ios_base::failbit)
00294               && __l <= 1
00295               && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
00296             __v = __l;
00297           else
00298             __err |= ios_base::failbit;
00299         }
00300 
00301       // Parse bool values as alphanumeric
00302       else
00303         {
00304           typedef _Format_cache<char_type> __fcache_type;
00305           __fcache_type* __fmt = __fcache_type::_S_get(__io);
00306           const char_type* __true = __fmt->_M_truename.c_str();
00307           const char_type* __false = __fmt->_M_falsename.c_str();
00308           const size_t __truelen =  __traits_type::length(__true) - 1;
00309           const size_t __falselen =  __traits_type::length(__false) - 1;
00310 
00311           for (size_t __pos = 0; __beg != __end; ++__pos)
00312             {
00313               char_type __c = *__beg++;
00314               bool __testf = __c == __false[__pos];
00315               bool __testt = __c == __true[__pos];
00316               if (!(__testf || __testt))
00317                 {
00318                   __err |= ios_base::failbit;
00319                   break;
00320                 }
00321               else if (__testf && __pos == __falselen)
00322                 {
00323                   __v = 0;
00324                   break;
00325                 }
00326               else if (__testt && __pos == __truelen)
00327                 {
00328                   __v = 1;
00329                   break;
00330                 }
00331             }
00332           if (__beg == __end)
00333             __err |= ios_base::eofbit;
00334         }
00335 
00336       return __beg;
00337     }
00338 #endif
00339 
00340 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
00341   template<typename _CharT, typename _InIter>
00342     _InIter
00343     num_get<_CharT, _InIter>::
00344     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00345            ios_base::iostate& __err, short& __v) const
00346     {
00347       // Stage 1: extract and determine the conversion specifier.
00348       // Assuming leading zeros eliminated, thus the size of 32 for
00349       // integral types.
00350       char __xtrc[_M_extract_buffer_length]= {'\0'};
00351       int __base;
00352       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00353 
00354       // Stage 2: convert and store results.
00355       char* __sanity;
00356       errno = 0;
00357       long __l = strtol(__xtrc, &__sanity, __base);
00358       if (!(__err & ios_base::failbit)
00359           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
00360           && __l >= SHRT_MIN && __l <= SHRT_MAX)
00361         __v = static_cast<short>(__l);
00362       else
00363         __err |= ios_base::failbit;
00364 
00365       return __beg;
00366     }
00367 
00368   template<typename _CharT, typename _InIter>
00369     _InIter
00370     num_get<_CharT, _InIter>::
00371     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00372            ios_base::iostate& __err, int& __v) const
00373     {
00374       // Stage 1: extract and determine the conversion specifier.
00375       // Assuming leading zeros eliminated, thus the size of 32 for
00376       // integral types.
00377       char __xtrc[_M_extract_buffer_length] = {'\0'};
00378       int __base;
00379       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00380 
00381       // Stage 2: convert and store results.
00382       char* __sanity;
00383       errno = 0;
00384       long __l = strtol(__xtrc, &__sanity, __base);
00385       if (!(__err & ios_base::failbit)
00386           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
00387           && __l >= INT_MIN && __l <= INT_MAX)
00388         __v = static_cast<int>(__l);
00389       else
00390         __err |= ios_base::failbit;
00391 
00392       return __beg;
00393     }
00394 #endif
00395 
00396   template<typename _CharT, typename _InIter>
00397     _InIter
00398     num_get<_CharT, _InIter>::
00399     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00400            ios_base::iostate& __err, long& __v) const
00401     {
00402       // Stage 1: extract and determine the conversion specifier.
00403       // Assuming leading zeros eliminated, thus the size of 32 for
00404       // integral types.
00405       char __xtrc[_M_extract_buffer_length]= {'\0'};
00406       int __base;
00407       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00408 
00409       // Stage 2: convert and store results.
00410       char* __sanity;
00411       errno = 0;
00412       long __l = strtol(__xtrc, &__sanity, __base);
00413       if (!(__err & ios_base::failbit)
00414           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
00415         __v = __l;
00416       else
00417         __err |= ios_base::failbit;
00418 
00419       return __beg;
00420     }
00421 
00422 #ifdef _GLIBCPP_USE_LONG_LONG
00423   template<typename _CharT, typename _InIter>
00424     _InIter
00425     num_get<_CharT, _InIter>::
00426     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00427            ios_base::iostate& __err, long long& __v) const
00428     {
00429       // Stage 1: extract and determine the conversion specifier.
00430       // Assuming leading zeros eliminated, thus the size of 32 for
00431       // integral types.
00432       char __xtrc[_M_extract_buffer_length]= {'\0'};
00433       int __base;
00434       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00435 
00436       // Stage 2: convert and store results.
00437       char* __sanity;
00438       errno = 0;
00439       long long __ll = strtoll(__xtrc, &__sanity, __base);
00440       if (!(__err & ios_base::failbit)
00441           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
00442         __v = __ll;
00443       else
00444         __err |= ios_base::failbit;
00445 
00446       return __beg;
00447     }
00448 #endif
00449 
00450   template<typename _CharT, typename _InIter>
00451     _InIter
00452     num_get<_CharT, _InIter>::
00453     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00454            ios_base::iostate& __err, unsigned short& __v) const
00455     {
00456       // Stage 1: extract and determine the conversion specifier.
00457       // Assuming leading zeros eliminated, thus the size of 32 for
00458       // integral types.
00459       char __xtrc[_M_extract_buffer_length]= {'\0'};
00460       int __base;
00461       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00462 
00463       // Stage 2: convert and store results.
00464       char* __sanity;
00465       errno = 0;
00466       unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
00467       if (!(__err & ios_base::failbit)
00468           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
00469           && __ul <= USHRT_MAX)
00470         __v = static_cast<unsigned short>(__ul);
00471       else
00472         __err |= ios_base::failbit;
00473 
00474       return __beg;
00475     }
00476 
00477   template<typename _CharT, typename _InIter>
00478     _InIter
00479     num_get<_CharT, _InIter>::
00480     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00481            ios_base::iostate& __err, unsigned int& __v) const
00482     {
00483       // Stage 1: extract and determine the conversion specifier.
00484       // Assuming leading zeros eliminated, thus the size of 32 for
00485       // integral types.
00486       char __xtrc[_M_extract_buffer_length]= {'\0'};
00487       int __base;
00488       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00489 
00490       // Stage 2: convert and store results.
00491       char* __sanity;
00492       errno = 0;
00493       unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
00494       if (!(__err & ios_base::failbit)
00495           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
00496           && __ul <= UINT_MAX)
00497         __v = static_cast<unsigned int>(__ul);
00498       else
00499         __err |= ios_base::failbit;
00500 
00501       return __beg;
00502     }
00503 
00504   template<typename _CharT, typename _InIter>
00505     _InIter
00506     num_get<_CharT, _InIter>::
00507     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00508            ios_base::iostate& __err, unsigned long& __v) const
00509     {
00510       // Stage 1: extract and determine the conversion specifier.
00511       // Assuming leading zeros eliminated, thus the size of 32 for
00512       // integral types.
00513       char __xtrc[_M_extract_buffer_length] = {'\0'};
00514       int __base;
00515       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00516 
00517       // Stage 2: convert and store results.
00518       char* __sanity;
00519       errno = 0;
00520       unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
00521       if (!(__err & ios_base::failbit)
00522           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
00523         __v = __ul;
00524       else
00525         __err |= ios_base::failbit;
00526 
00527       return __beg;
00528     }
00529 
00530 #ifdef _GLIBCPP_USE_LONG_LONG
00531   template<typename _CharT, typename _InIter>
00532     _InIter
00533     num_get<_CharT, _InIter>::
00534     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00535            ios_base::iostate& __err, unsigned long long& __v) const
00536     {
00537       // Stage 1: extract and determine the conversion specifier.
00538       // Assuming leading zeros eliminated, thus the size of 32 for
00539       // integral types.
00540       char __xtrc[_M_extract_buffer_length]= {'\0'};
00541       int __base;
00542       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00543 
00544       // Stage 2: convert and store results.
00545       char* __sanity;
00546       errno = 0;
00547       unsigned long long __ull = strtoull(__xtrc, &__sanity, __base);
00548       if (!(__err & ios_base::failbit)
00549           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
00550         __v = __ull;
00551       else
00552         __err |= ios_base::failbit;
00553 
00554       return __beg;
00555     }
00556 #endif
00557 
00558   template<typename _CharT, typename _InIter>
00559     _InIter
00560     num_get<_CharT, _InIter>::
00561     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00562            ios_base::iostate& __err, float& __v) const
00563     {
00564       // Stage 1: extract and determine the conversion specifier.
00565       // Assuming leading zeros eliminated, thus the size of 256 for
00566       // floating-point types.
00567       char __xtrc[_M_extract_buffer_length]= {'\0'};
00568       int __base;
00569       _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
00570 
00571       // Stage 2: convert and store results.
00572       char* __sanity;
00573       errno = 0;
00574 #ifdef _GLIBCPP_USE_C99
00575       float __f = strtof(__xtrc, &__sanity);
00576 #else
00577       float __f = static_cast<float>(strtod(__xtrc, &__sanity));
00578 #endif
00579       if (!(__err & ios_base::failbit)
00580           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
00581         __v = __f;
00582       else
00583         __err |= ios_base::failbit;
00584 
00585       return __beg;
00586     }
00587 
00588   template<typename _CharT, typename _InIter>
00589     _InIter
00590     num_get<_CharT, _InIter>::
00591     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00592            ios_base::iostate& __err, double& __v) const
00593     {
00594       // Stage 1: extract and determine the conversion specifier.
00595       // Assuming leading zeros eliminated, thus the size of 256 for
00596       // floating-point types.
00597       char __xtrc[_M_extract_buffer_length]= {'\0'};
00598       int __base;
00599       _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
00600 
00601       // Stage 2: convert and store results.
00602       char* __sanity;
00603       errno = 0;
00604       double __d = strtod(__xtrc, &__sanity);
00605       if (!(__err & ios_base::failbit)
00606           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
00607         __v = __d;
00608       else
00609         __err |= ios_base::failbit;
00610 
00611       return __beg;
00612     }
00613 
00614 #if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
00615   template<typename _CharT, typename _InIter>
00616     _InIter
00617     num_get<_CharT, _InIter>::
00618     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00619            ios_base::iostate& __err, long double& __v) const
00620     {
00621       // Stage 1: extract and determine the conversion specifier.
00622       // Assuming leading zeros eliminated, thus the size of 256 for
00623       // floating-point types.
00624       char __xtrc[_M_extract_buffer_length]= {'\0'};
00625       int __base;
00626       _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
00627 
00628       // Stage 2: convert and store results.
00629       char* __sanity;
00630       errno = 0;
00631       long double __ld = strtold(__xtrc, &__sanity);
00632       if (!(__err & ios_base::failbit)
00633           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
00634         __v = __ld;
00635       else
00636         __err |= ios_base::failbit;
00637 
00638       return __beg;
00639     }
00640 #else
00641   template<typename _CharT, typename _InIter>
00642     _InIter
00643     num_get<_CharT, _InIter>::
00644     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00645            ios_base::iostate& __err, long double& __v) const
00646     {
00647       // Stage 1: extract
00648       char __xtrc[_M_extract_buffer_length]= {'\0'};
00649       int __base;
00650       _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
00651 
00652       // Stage 2: determine a conversion specifier.
00653       ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
00654       const char* __conv;
00655       if (__basefield == ios_base::oct)
00656         __conv = "%Lo";
00657       else if (__basefield == ios_base::hex)
00658         __conv = "%LX";
00659       else if (__basefield == 0)
00660         __conv = "%Li";
00661       else
00662         __conv = "%Lg";
00663 
00664       // Stage 3: store results.
00665       long double __ld;
00666       int __p = sscanf(__xtrc, __conv, &__ld);
00667       if (__p
00668           && static_cast<typename __traits_type::int_type>(__p)
00669         != __traits_type::eof())
00670         __v = __ld;
00671       else
00672         __err |= ios_base::failbit;
00673 
00674       return __beg;
00675     }
00676 #endif
00677 
00678   template<typename _CharT, typename _InIter>
00679     _InIter
00680     num_get<_CharT, _InIter>::
00681     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00682            ios_base::iostate& __err, void*& __v) const
00683     {
00684       // Prepare for hex formatted input
00685       typedef ios_base::fmtflags        fmtflags;
00686       fmtflags __fmt = __io.flags();
00687       fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
00688                              | ios_base::uppercase | ios_base::internal);
00689       __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
00690 
00691       // Stage 1: extract and determine the conversion specifier.
00692       // Assuming leading zeros eliminated, thus the size of 32 for
00693       // integral types.
00694       char __xtrc[_M_extract_buffer_length]= {'\0'};
00695       int __base;
00696       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
00697 
00698       // Stage 2: convert and store results.
00699       char* __sanity;
00700       errno = 0;
00701       void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base));
00702       if (!(__err & ios_base::failbit)
00703           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
00704         __v = __vp;
00705       else
00706         __err |= ios_base::failbit;
00707 
00708       // Reset from hex formatted input
00709       __io.flags(__fmt);
00710       return __beg;
00711     }
00712 
00713   // __pad is specialized for ostreambuf_iterator, random access iterator.
00714   template <typename _CharT, typename _OutIter>
00715     inline _OutIter
00716     __pad(_OutIter __s, _CharT __fill, int __padding);
00717 
00718   template <typename _CharT, typename _RaIter>
00719     _RaIter
00720     __pad(_RaIter __s, _CharT __fill, int __padding, 
00721       random_access_iterator_tag)
00722     {
00723       fill_n(__s, __fill);
00724       return __s + __padding;
00725     }
00726 
00727   template <typename _CharT, typename _OutIter, typename _Tag>
00728     _OutIter
00729     __pad(_OutIter __s, _CharT __fill, int __padding, _Tag)
00730     {
00731       while (--__padding >= 0) { *__s = __fill; ++__s; }
00732       return __s;
00733     }
00734 
00735   template <typename _CharT, typename _OutIter>
00736     inline _OutIter
00737     __pad(_OutIter __s, _CharT __fill, int __padding)
00738     {
00739       return __pad(__s, __fill, __padding, 
00740            typename iterator_traits<_OutIter>::iterator_category());
00741     }
00742 
00743   template <typename _CharT, typename _OutIter>
00744     _OutIter
00745     __pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/,
00746           _CharT /*__fill*/, int /*__width*/, 
00747           _CharT const* /*__first*/, _CharT const* /*__middle*/, 
00748           _CharT const* /*__last*/)
00749   {
00750       // XXX Not currently done: non streambuf_iterator
00751       return __s;
00752     }
00753 
00754   // Partial specialization for ostreambuf_iterator.
00755   template <typename _CharT>   
00756     ostreambuf_iterator<_CharT>
00757     __pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags,
00758           _CharT __fill, int __width, _CharT const* __first,
00759           _CharT const* __middle, _CharT const* __last)
00760     {
00761       typedef ostreambuf_iterator<_CharT>   __out_iter;
00762       int __padding = __width - (__last - __first);
00763       if (__padding < 0)
00764         __padding = 0;
00765       ios_base::fmtflags __aflags = __flags & ios_base::adjustfield;
00766       bool __testfield = __padding == 0 || __aflags == ios_base::left
00767                          || __aflags == ios_base::internal;
00768 
00769       // This was needlessly complicated.
00770       if (__first != __middle)
00771         {
00772           if (!__testfield)
00773             {
00774               __pad(__s, __fill, __padding);
00775               __padding = 0;
00776             }
00777           copy(__first, __middle, __s);
00778         }
00779       __out_iter __s2 = __s;
00780 
00781       if (__padding && __aflags != ios_base::left)
00782         {
00783           __pad(__s2, __fill, __padding);
00784           __padding = 0;
00785         }
00786       __out_iter __s3 = copy(__middle, __last, __s2);
00787       if (__padding)
00788         __pad(__s3, __fill, __padding);
00789       return __s3;
00790     }
00791 
00792   template <typename _CharT, typename _OutIter>
00793     _OutIter
00794     num_put<_CharT, _OutIter>::
00795     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
00796     {
00797       const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
00798       ios_base::fmtflags __flags = __io.flags();
00799 
00800       if ((__flags & ios_base::boolalpha) == 0)
00801         {
00802           unsigned long __uv = __v;
00803           return __output_integer(__s, __io, __fill, false, __uv);
00804         }
00805       else
00806         {
00807           const char_type* __first;
00808           const char_type* __last;
00809           if (__v)
00810             {
00811               __first = __fmt->_M_truename.data();
00812               __last = __first + __fmt->_M_truename.size();
00813             }
00814           else
00815             {
00816               __first = __fmt->_M_falsename.data();
00817               __last = __first + __fmt->_M_falsename.size();
00818             }
00819           copy(__first, __last, __s);
00820         }
00821       return __s;
00822     }
00823 
00824   // __group_digits inserts "group separator" characters into an array
00825   // of characters.  It's recursive, one iteration per group.  It moves
00826   // the characters in the buffer this way: "xxxx12345" -> "12,345xxx".
00827   // Call this only with __grouping != __grend.
00828   template <typename _CharT>
00829     _CharT*
00830     __group_digits(_CharT* __s, _CharT __grsep,  char const* __grouping,
00831                     char const* __grend, _CharT const* __first,
00832                     _CharT const* __last)
00833     {
00834       if (__last - __first > *__grouping)
00835         {
00836           __s = __group_digits(__s,  __grsep,
00837               (__grouping + 1 == __grend ? __grouping : __grouping + 1),
00838               __grend, __first, __last - *__grouping);
00839           __first = __last - *__grouping;
00840           *__s++ = __grsep;
00841         }
00842       do
00843         {
00844           *__s++ = *__first++;
00845         }
00846       while (__first != __last);
00847       return __s;
00848     }
00849 
00850   template <typename _CharT, typename _OutIter, typename _ValueT>
00851     _OutIter
00852     __output_integer(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg,
00853               _ValueT __v)
00854     {
00855       // Leave room for "+/-," "0x," and commas.
00856       const long _M_room = numeric_limits<_ValueT>::digits10 * 2 + 4;
00857       _CharT __digits[_M_room];
00858       _CharT* __front = __digits + _M_room;
00859       ios_base::fmtflags __flags = __io.flags();
00860       const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
00861       char const* __table = __fmt->_S_literals + __fmt->_S_digits;
00862 
00863       ios_base::fmtflags __basefield = (__flags & __io.basefield);
00864       _CharT* __sign_end = __front;
00865       if (__basefield == ios_base::hex)
00866         {
00867           if (__flags & ios_base::uppercase)
00868             __table += 16;  // use ABCDEF
00869           do
00870             *--__front = __table[__v & 15];
00871           while ((__v >>= 4) != 0);
00872           __sign_end = __front;
00873           if (__flags & ios_base::showbase)
00874             {
00875               *--__front = __fmt->_S_literals[__fmt->_S_x +
00876                        ((__flags & ios_base::uppercase) ? 1 : 0)];
00877               *--__front = __table[0];
00878             }
00879         }
00880       else if (__basefield == ios_base::oct)
00881         {
00882           do
00883             *--__front = __table[__v & 7];
00884           while ((__v >>= 3) != 0);
00885           if (__flags & ios_base::showbase
00886               && static_cast<char>(*__front) != __table[0])
00887             *--__front = __table[0];
00888           __sign_end = __front;
00889         }
00890       else
00891         {
00892           // NB: This is _lots_ faster than using ldiv.
00893           do
00894             *--__front = __table[__v % 10];
00895           while ((__v /= 10) != 0);
00896           __sign_end = __front;
00897           // NB: ios_base:hex || ios_base::oct assumed to be unsigned.
00898           if (__neg || (__flags & ios_base::showpos))
00899             *--__front = __fmt->_S_literals[__fmt->_S_plus - __neg];
00900         }
00901 
00902       // XXX should specialize!
00903       if (!__fmt->_M_use_grouping && !__io.width())
00904         return copy(__front, __digits + _M_room, __s);
00905 
00906       if (!__fmt->_M_use_grouping)
00907         return __pad_numeric(__s, __flags, __fill, __io.width(0),
00908                  __front, __sign_end, __digits + _M_room);
00909 
00910       _CharT* __p = __digits;
00911       while (__front < __sign_end)
00912         *__p++ = *__front++;
00913       const char* __gr = __fmt->_M_grouping.data();
00914       __front = __group_digits(__p, __fmt->_M_thousands_sep, __gr,
00915         __gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room);
00916       return __pad_numeric(__s, __flags, __fill, __io.width(0),
00917                __digits, __p, __front);
00918     }
00919 
00920   template <typename _CharT, typename _OutIter>
00921     _OutIter
00922     num_put<_CharT, _OutIter>::
00923     do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
00924     {
00925       unsigned long __uv = __v;
00926       bool __neg = false;
00927       if (__v < 0)
00928         {
00929           __neg = true;
00930           __uv = -__uv;
00931         }
00932       return __output_integer(__s, __io, __fill, __neg, __uv);
00933     }
00934 
00935   template <typename _CharT, typename _OutIter>
00936     _OutIter
00937     num_put<_CharT, _OutIter>::
00938     do_put(iter_type __s, ios_base& __io, char_type __fill,
00939            unsigned long __v) const
00940     { return __output_integer(__s, __io, __fill, false, __v); }
00941 
00942 #ifdef _GLIBCPP_USE_LONG_LONG
00943   template <typename _CharT, typename _OutIter>
00944     _OutIter
00945     num_put<_CharT, _OutIter>::
00946     do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
00947     {
00948       unsigned long long __uv = __v;
00949       bool __neg = false;
00950       if (__v < 0)
00951         {
00952           __neg = true;
00953           __uv = -__uv;
00954         }
00955       return __output_integer(__s, __b, __fill, __neg, __uv);
00956     }
00957 
00958   template <typename _CharT, typename _OutIter>
00959     _OutIter
00960     num_put<_CharT, _OutIter>::
00961     do_put(iter_type __s, ios_base& __io, char_type __fill,
00962            unsigned long long __v) const
00963     { return __output_integer(__s, __io, __fill, false, __v); }
00964 #endif
00965 
00966   // Generic helper function
00967   template<typename _CharT, typename _Traits, typename _OutIter>
00968     _OutIter
00969     __output_float(_OutIter __s, ios_base& __io, _CharT __fill,
00970                     const char* __sptr, size_t __slen)
00971     {
00972       // XXX Not currently done: non streambuf_iterator
00973       return __s;
00974     }
00975 
00976   // Partial specialization for ostreambuf_iterator.
00977   template<typename _CharT, typename _Traits>
00978     ostreambuf_iterator<_CharT, _Traits>
00979     __output_float(ostreambuf_iterator<_CharT, _Traits> __s, ios_base& __io, 
00980            _CharT __fill, const char* __sptr, size_t __slen)
00981     {
00982       size_t __padding = __io.width() > streamsize(__slen) ?
00983                          __io.width() -__slen : 0;
00984       locale __loc = __io.getloc();
00985       ctype<_CharT> const& __ct = use_facet<ctype<_CharT> >(__loc);
00986       ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield;
00987       const char* const __eptr = __sptr + __slen;
00988       // [22.2.2.2.2.19] Table 61
00989       if (__adjfield == ios_base::internal)
00990        {
00991          // [22.2.2.2.2.14]; widen()
00992          if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-'))
00993            {
00994              __s = __ct.widen(*__sptr);
00995              ++__s;
00996              ++__sptr;
00997            }
00998          __s = __pad(__s, __fill, __padding);
00999          __padding = 0;
01000        }
01001       else if (__adjfield != ios_base::left)
01002         {
01003           __s = __pad(__s, __fill, __padding);
01004           __padding = 0;
01005         }
01006       // the "C" locale decimal character
01007       char __decimal_point = *(localeconv()->decimal_point);
01008       const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
01009       for (; __sptr != __eptr; ++__s, ++__sptr)
01010        {
01011          // [22.2.2.2.2.17]; decimal point conversion
01012          if (*__sptr == __decimal_point)
01013            __s = __fmt->_M_decimal_point;
01014          // [22.2.2.2.2.14]; widen()
01015          else
01016            __s = __ct.widen(*__sptr);
01017        }
01018       // [22.2.2.2.2.19] Table 61
01019       if (__padding)
01020         __pad(__s, __fill, __padding);
01021       __io.width(0);
01022       return __s;
01023     }
01024 
01025   bool
01026   __build_float_format(ios_base& __io, char* __fptr, char __modifier,
01027                streamsize __prec);
01028 
01029   template <typename _CharT, typename _OutIter>
01030     _OutIter
01031     num_put<_CharT, _OutIter>::
01032     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
01033     {
01034       const streamsize __max_prec = numeric_limits<double>::digits10 + 3;
01035       streamsize __prec = __io.precision();
01036       // Protect against sprintf() buffer overflows.
01037       if (__prec > __max_prec)
01038         __prec = __max_prec;
01039       // The *2 provides for signs, exp, 'E', and pad.
01040       char __sbuf[__max_prec * 2];
01041       size_t __slen;
01042       // Long enough for the max format spec.
01043       char __fbuf[16];
01044       if (__build_float_format(__io, __fbuf, 0, __prec))
01045         __slen = sprintf(__sbuf, __fbuf, __prec, __v);
01046       else
01047         __slen = sprintf(__sbuf, __fbuf, __v);
01048       // [22.2.2.2.2] Stages 2-4.
01049       return __output_float(__s, __io, __fill, __sbuf, __slen);
01050     }
01051 
01052   template <typename _CharT, typename _OutIter>
01053     _OutIter
01054     num_put<_CharT, _OutIter>::
01055     do_put(iter_type __s, ios_base& __io, char_type __fill,
01056            long double __v) const
01057     {
01058       const streamsize __max_prec = numeric_limits<long double>::digits10 + 3;
01059       streamsize __prec = __io.precision();
01060       // Protect against sprintf() buffer overflows.
01061       if (__prec > __max_prec)
01062         __prec = __max_prec;
01063       // The *2 provides for signs, exp, 'E', and pad.
01064       char __sbuf[__max_prec * 2];
01065       size_t __slen;
01066       // Long enough for the max format spec.
01067       char __fbuf[16];
01068       // 'L' as per [22.2.2.2.2] Table 59
01069       if (__build_float_format(__io, __fbuf, 'L', __prec))
01070         __slen = sprintf(__sbuf, __fbuf, __prec, __v);
01071       else
01072         __slen = sprintf(__sbuf, __fbuf, __v);
01073       // [22.2.2.2.2] Stages 2-4
01074       return __output_float(__s, __io, __fill, __sbuf, __slen);
01075     }
01076 
01077   template <typename _CharT, typename _OutIter>
01078     _OutIter
01079     num_put<_CharT, _OutIter>::
01080     do_put(iter_type __s, ios_base& __io, char_type __fill,
01081            const void* __v) const
01082     {
01083       typedef ios_base::fmtflags        fmtflags;
01084       fmtflags __fmt = __io.flags();
01085       fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
01086                              | ios_base::uppercase | ios_base::internal);
01087       __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
01088       try {
01089         _OutIter __s2 = __output_integer(__s, __io, __fill, false,
01090                                   reinterpret_cast<unsigned long>(__v));
01091         __io.flags(__fmt);
01092         return __s2;
01093       }
01094       catch (...) {
01095         __io.flags(__fmt);
01096         __throw_exception_again;
01097       }
01098     }
01099 
01100   // Support for time_get:
01101   // Note that these partial specializations could, and maybe should,
01102   // be changed to full specializations (by eliminating the _Dummy
01103   // argument) and moved to a .cc file.
01104   template<typename _CharT, typename _Dummy = int>
01105     struct _Weekdaynames;
01106 
01107   template<typename _Dummy>
01108     struct _Weekdaynames<char, _Dummy>
01109     { static const char* const _S_names[14]; };
01110 
01111   template<typename _Dummy>
01112     const char* const
01113     _Weekdaynames<char, _Dummy>::_S_names[14] =
01114     {
01115       "Sun", "Sunday",
01116       "Mon", "Monday",   "Tue", "Tuesday", "Wed", "Wednesday",
01117       "Thu", "Thursday", "Fri", "Friday",  "Sat", "Saturday"
01118     };
01119 
01120 #ifdef _GLIBCPP_USE_WCHAR_T
01121   template<typename _Dummy>
01122     struct _Weekdaynames<wchar_t, _Dummy>
01123     { static const wchar_t* const _S_names[14]; };
01124 
01125   template<typename _Dummy>
01126     const wchar_t* const
01127     _Weekdaynames<wchar_t, _Dummy>::_S_names[14] =
01128     {
01129       L"Sun", L"Sunday",
01130       L"Mon", L"Monday",   L"Tue", L"Tuesday", L"Wed", L"Wednesday",
01131       L"Thu", L"Thursday", L"Fri", L"Friday",  L"Sat", L"Saturday"
01132     };
01133 #endif
01134 
01135   template<typename _CharT, typename _Dummy = int>
01136     struct _Monthnames;
01137 
01138   template<typename _Dummy>
01139     struct _Monthnames<char,_Dummy>
01140     { static const char* const _S_names[24]; };
01141 
01142   template<typename _Dummy>
01143     const char* const
01144     _Monthnames<char,_Dummy>::_S_names[24] =
01145     {
01146       "Jan", "January", "Feb", "February", "Mar", "March",
01147       "Apr", "April",   "May", "May",      "Jun", "June",
01148       "Jul", "July",    "Aug", "August",   "Sep", "September",
01149       "Oct", "October", "Nov", "November", "Dec", "December"
01150     };
01151 
01152 #ifdef _GLIBCPP_USE_WCHAR_T
01153   template<typename _Dummy>
01154     struct _Monthnames<wchar_t, _Dummy>
01155     { static const wchar_t* const _S_names[24]; };
01156 
01157   template<typename _Dummy>
01158     const wchar_t* const
01159     _Monthnames<wchar_t,_Dummy>::_S_names[24] =
01160     {
01161       L"Jan", L"January", L"Feb", L"February", L"Mar", L"March",
01162       L"Apr", L"April",   L"May", L"May",      L"Jun", L"June",
01163       L"Jul", L"July",    L"Aug", L"August",   L"Sep", L"September",
01164       L"Oct", L"October", L"Nov", L"November", L"Dec", L"December"
01165     };
01166 #endif
01167 
01168   template<typename _CharT, typename _InIter>
01169     _InIter
01170     time_get<_CharT, _InIter>::
01171     do_get_weekday(iter_type __s, iter_type __end,
01172                    ios_base& __io, ios_base::iostate& __err, tm* __t) const
01173     {
01174       if (!_M_daynames)
01175         {
01176           _M_daynames = new basic_string<_CharT>[14];
01177           for (int __i = 0; __i < 14; ++__i)
01178             _M_daynames[__i] = _Weekdaynames<_CharT>::_S_names[__i];
01179         }
01180       bool __at_eof = false;
01181       int __remain = 0;
01182       int __matches[14];
01183       iter_type __out = __match_parallel(__s, __end, 14, _M_daynames,
01184                                          __matches, __remain, __at_eof);
01185       __err = ios_base::iostate(0);
01186       if (__at_eof) __err |= __io.eofbit;
01187       if (__remain == 1 ||
01188           __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
01189         __t->tm_wday = (__matches[0]>>1);
01190       else
01191         __err |= __io.failbit;
01192       return __out;
01193     }
01194 
01195   template<typename _CharT, typename _InIter>
01196     _InIter
01197     time_get<_CharT, _InIter>::
01198     do_get_monthname(iter_type __s, iter_type __end,
01199                      ios_base& __io, ios_base::iostate& __err, tm* __t) const
01200     {
01201       if (!_M_monthnames)
01202         {
01203           _M_monthnames = new basic_string<_CharT>[24];
01204           for (int __i = 0; __i < 24; ++__i)
01205             _M_monthnames[__i] = _Monthnames<_CharT>::_S_names[__i];
01206         }
01207       bool __at_eof = false;
01208       int __remain = 0;
01209       int __matches[24];
01210       iter_type __out = __match_parallel( __s, __end, 24, _M_monthnames,
01211                                           __matches, __remain, __at_eof);
01212       __err = ios_base::iostate(0);
01213       if (__at_eof) __err |= __io.eofbit;
01214       if (__remain == 1 ||
01215           __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
01216         __t->tm_mon = (__matches[0]>>1);
01217       else
01218         __err |= __io.failbit;
01219       return __out;
01220     }
01221 } // std::
01222 
01223 #endif /* _CPP_BITS_LOCFACETS_TCC */
01224 
01225 // Local Variables:
01226 // mode:c++
01227 // End:

Generated on Mon Apr 8 03:11:29 2002 for libstdc++-v3 Source by doxygen1.2.15