Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

locale.cc

Go to the documentation of this file.
00001 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
00002 //
00003 // This file is part of the GNU ISO C++ Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the
00005 // terms of the GNU General Public License as published by the
00006 // Free Software Foundation; either version 2, or (at your option)
00007 // any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 
00014 // You should have received a copy of the GNU General Public License along
00015 // with this library; see the file COPYING.  If not, write to the Free
00016 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00017 // USA.
00018 
00019 // As a special exception, you may use this file as part of a free software
00020 // library without restriction.  Specifically, if other files instantiate
00021 // templates or use macros or inline functions from this file, or you compile
00022 // this file and link it with other files to produce an executable, this
00023 // file does not by itself cause the resulting executable to be covered by
00024 // the GNU General Public License.  This exception does not however
00025 // invalidate any other reasons why the executable file might be covered by
00026 // the GNU General Public License.
00027 
00028 #include <bits/std_clocale.h>
00029 #include <bits/std_cstring.h>
00030 #include <bits/std_cassert.h>
00031 #include <bits/std_cctype.h>
00032 #include <bits/std_limits.h>
00033 #include <exception>
00034 #include <bits/std_stdexcept.h>
00035 #include <bits/std_locale.h>
00036 #include <bits/std_istream.h>
00037 #include <bits/std_ostream.h>
00038 #include <bits/std_vector.h>
00039 #include <bits/std_memory.h>      // for auto_ptr
00040 #ifdef _GLIBCPP_USE_WCHAR_T  
00041 # include <bits/std_cwctype.h>     // for towupper, etc.
00042 #endif
00043 
00044 namespace std 
00045 {
00046   // Definitions for static const data members of locale.
00047   const locale::category    locale::none;
00048   const locale::category    locale::ctype;
00049   const locale::category    locale::numeric;
00050   const locale::category    locale::collate;
00051   const locale::category    locale::time;
00052   const locale::category    locale::monetary;
00053   const locale::category    locale::messages;
00054   const locale::category    locale::all;
00055 
00056   locale::_Impl*        locale::_S_classic;
00057   locale::_Impl*        locale::_S_global; 
00058   const size_t          locale::_S_num_categories;
00059   const size_t          locale::_S_num_facets;
00060 
00061   // Definitions for locale::id of standard facets. 
00062   locale::id ctype<char>::id;
00063   locale::id codecvt<char, char, mbstate_t>::id;
00064 
00065 #ifdef _GLIBCPP_USE_WCHAR_T  
00066   locale::id ctype<wchar_t>::id;
00067   locale::id codecvt<wchar_t, char, mbstate_t>::id;
00068 #endif
00069 
00070   // Definitions for static const data members of locale::id
00071   size_t locale::id::_S_highwater;  // init'd to 0 by linker
00072 
00073   // Definitions for static const data members of locale::_Impl
00074   const locale::id* const
00075   locale::_Impl::_S_id_ctype[] =
00076   {
00077     &std::ctype<char>::id, 
00078     &codecvt<char, char, mbstate_t>::id,
00079 #ifdef _GLIBCPP_USE_WCHAR_T
00080     &std::ctype<wchar_t>::id,
00081     &codecvt<wchar_t, char, mbstate_t>::id,
00082 #endif
00083     0
00084   };
00085 
00086   const locale::id* const
00087   locale::_Impl::_S_id_numeric[] =
00088   {
00089     &num_get<char>::id,  
00090     &num_put<char>::id,  
00091     &numpunct<char>::id, 
00092 #ifdef _GLIBCPP_USE_WCHAR_T
00093     &num_get<wchar_t>::id,
00094     &num_put<wchar_t>::id,
00095     &numpunct<wchar_t>::id,
00096 #endif
00097     0
00098   };
00099   
00100   const locale::id* const
00101   locale::_Impl::_S_id_collate[] =
00102   {
00103     &std::collate<char>::id,
00104 #ifdef _GLIBCPP_USE_WCHAR_T
00105     &std::collate<wchar_t>::id,
00106 #endif
00107     0
00108   };
00109 
00110   const locale::id* const
00111   locale::_Impl::_S_id_time[] =
00112   {
00113     &time_get<char>::id, 
00114     &time_put<char>::id, 
00115 #ifdef _GLIBCPP_USE_WCHAR_T
00116     &time_get<wchar_t>::id,
00117     &time_put<wchar_t>::id,
00118 #endif
00119     0
00120   };
00121   
00122   const locale::id* const
00123   locale::_Impl::_S_id_monetary[] =
00124   {
00125     &money_get<char>::id,        
00126     &money_put<char>::id,        
00127     &moneypunct<char, false>::id, 
00128     &moneypunct<char, true >::id, 
00129 #ifdef _GLIBCPP_USE_WCHAR_T
00130     &money_get<wchar_t>::id,
00131     &money_put<wchar_t>::id,
00132     &moneypunct<wchar_t, false>::id,
00133     &moneypunct<wchar_t, true >::id,
00134 #endif
00135     0
00136   };
00137 
00138   const locale::id* const
00139   locale::_Impl::_S_id_messages[] =
00140   {
00141     &std::messages<char>::id, 
00142 #ifdef _GLIBCPP_USE_WCHAR_T
00143     &std::messages<wchar_t>::id,
00144 #endif
00145     0
00146   };
00147   
00148   const locale::id* const* const
00149   locale::_Impl::_S_facet_categories[] =
00150   {
00151     // Order must match the decl order in class locale.
00152     locale::_Impl::_S_id_ctype,
00153     locale::_Impl::_S_id_numeric,
00154     locale::_Impl::_S_id_collate,
00155     locale::_Impl::_S_id_time,
00156     locale::_Impl::_S_id_monetary,
00157     locale::_Impl::_S_id_messages,
00158     0
00159   };
00160 
00161   // Construct and return valid pattern consisting of some combination of:
00162   // space none symbol sign value
00163   money_base::pattern
00164   money_base::_S_construct_pattern(char __preceeds, char __space, char __posn)
00165   { 
00166     pattern __ret;
00167 
00168     // This insanely complicated routine attempts to construct a valid
00169     // pattern for use with monyepunct. A couple of invariants:
00170 
00171     // if (__preceeds) symbol -> value
00172     // else value -> symbol
00173     
00174     // if (__space) space
00175     // else none
00176 
00177     // none == never first
00178     // space never first or last
00179 
00180     // Any elegant implementations of this are welcome.
00181     switch (__posn)
00182       {
00183       case 1:
00184     // 1 The sign precedes the value and symbol.
00185     if (__space)
00186       {
00187         // Pattern starts with sign.
00188         if (__preceeds)
00189           {
00190         __ret.field[1] = symbol;
00191         __ret.field[2] = space;
00192         __ret.field[3] = value;
00193           }
00194         else
00195           {
00196         __ret.field[1] = value;
00197         __ret.field[2] = space;
00198         __ret.field[3] = symbol;
00199           }
00200         __ret.field[0] = sign;
00201       }
00202     else
00203       {
00204         // Pattern starts with sign and ends with none.
00205         if (__preceeds)
00206           {
00207         __ret.field[1] = symbol;
00208         __ret.field[2] = value;
00209           }
00210         else
00211           {
00212         __ret.field[1] = value;
00213         __ret.field[2] = symbol;
00214           }
00215         __ret.field[0] = sign;
00216         __ret.field[3] = none;
00217       }
00218     break;
00219       case 2:
00220     // 2 The sign follows the value and symbol.
00221     if (__space)
00222       {
00223         // Pattern either ends with sign.
00224         if (__preceeds)
00225           {
00226         __ret.field[0] = symbol;
00227         __ret.field[1] = space;
00228         __ret.field[2] = value;
00229           }
00230         else
00231           {
00232         __ret.field[0] = value;
00233         __ret.field[1] = space;
00234         __ret.field[2] = symbol;
00235           }
00236         __ret.field[3] = sign;
00237       }
00238     else
00239       {
00240         // Pattern ends with sign then none.
00241         if (__preceeds)
00242           {
00243         __ret.field[0] = symbol;
00244         __ret.field[1] = value;
00245           }
00246         else
00247           {
00248         __ret.field[0] = value;
00249         __ret.field[1] = symbol;
00250           }
00251         __ret.field[2] = sign;
00252         __ret.field[3] = none;
00253       }
00254     break;
00255       case 3:
00256     // 3 The sign immediately precedes the symbol.
00257     if (__space)
00258       {
00259         // Have space.
00260         if (__preceeds)
00261           {
00262         __ret.field[0] = sign;
00263         __ret.field[1] = symbol;
00264         __ret.field[2] = space;
00265         __ret.field[3] = value;
00266           }
00267         else
00268           {
00269         __ret.field[0] = value;
00270         __ret.field[1] = space;
00271         __ret.field[2] = sign;
00272         __ret.field[3] = symbol;
00273           }
00274       }
00275     else
00276       {
00277         // Have none.
00278         if (__preceeds)
00279           {
00280         __ret.field[0] = sign;
00281         __ret.field[1] = symbol;
00282         __ret.field[2] = value;
00283           }
00284         else
00285           {
00286         __ret.field[0] = value;
00287         __ret.field[1] = sign;
00288         __ret.field[2] = symbol;
00289           }
00290         __ret.field[3] = none;
00291       }
00292     break;
00293       case 4:
00294     // 4 The sign immediately follows the symbol. 
00295     if (__space)
00296       {
00297         // Have space.
00298         if (__preceeds)
00299           {
00300         __ret.field[0] = symbol;
00301         __ret.field[1] = sign;
00302         __ret.field[2] = space;
00303         __ret.field[3] = value;
00304           }
00305         else
00306           {
00307         __ret.field[0] = value;
00308         __ret.field[1] = space;
00309         __ret.field[2] = symbol;
00310         __ret.field[3] = sign;
00311           }
00312       }
00313     else
00314       {
00315         // Have none.
00316         if (__preceeds)
00317           {
00318         __ret.field[0] = symbol;
00319         __ret.field[1] = sign;
00320         __ret.field[2] = value;
00321           }
00322         else
00323           {
00324         __ret.field[0] = value;
00325         __ret.field[1] = symbol;
00326         __ret.field[2] = sign;
00327           }
00328         __ret.field[3] = none;
00329       }
00330     break;
00331       default:
00332     ;
00333       }
00334     return __ret;
00335   }
00336 
00337   locale::~locale() throw()
00338   { _M_impl->_M_remove_reference(); }
00339 
00340   void
00341   locale::_M_coalesce(const locale& __base, const locale& __add, 
00342               category __cat)
00343   {
00344     __cat = _S_normalize_category(__cat);  
00345     _M_impl = new _Impl(*__base._M_impl, 1);  
00346 
00347     try 
00348       { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
00349     catch (...) 
00350       { 
00351     _M_impl->_M_remove_reference(); 
00352     __throw_exception_again;
00353       }
00354   }
00355 
00356   locale::locale() throw()
00357   { 
00358     _S_initialize(); 
00359     (_M_impl = _S_global)->_M_add_reference(); 
00360   } // XXX MT
00361 
00362   locale::locale(const locale& __other) throw()
00363   { (_M_impl = __other._M_impl)->_M_add_reference(); }
00364 
00365   locale::locale(_Impl* __ip) throw()
00366   : _M_impl(__ip)
00367   { __ip->_M_add_reference(); }
00368 
00369   locale::locale(const char* __s)
00370   {
00371     if (__s)
00372       {
00373     if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0)
00374       (_M_impl = _S_classic)->_M_add_reference();
00375     else
00376       _M_impl = new _Impl(__s, 1);
00377       }
00378     else
00379       __throw_runtime_error("attempt to create locale from NULL name");
00380   }
00381 
00382   locale::locale(const locale& __base, const char* __s, category __cat)
00383   { 
00384     // NB: There are complicated, yet more efficient ways to do
00385     // this. Building up locales on a per-category way is tedious, so
00386     // let's do it this way until people complain.
00387     locale __add(__s);
00388     _M_coalesce(__base, __add, __cat);
00389   }
00390 
00391   locale::locale(const locale& __base, const locale& __add, category __cat)
00392   { _M_coalesce(__base, __add, __cat); }
00393 
00394   bool
00395   locale::operator==(const locale& __rhs) const throw()
00396   {
00397     string __name = this->name();
00398     return (_M_impl == __rhs._M_impl 
00399         || (__name != "*" && __name == __rhs.name()));
00400   }
00401 
00402   const locale&
00403   locale::operator=(const locale& __other) throw()
00404   {
00405     __other._M_impl->_M_add_reference();
00406     _M_impl->_M_remove_reference();
00407     _M_impl = __other._M_impl;
00408     return *this;
00409   }
00410 
00411   locale
00412   locale::global(const locale& __other)
00413   {
00414     // XXX MT
00415     _S_initialize();
00416     locale __old(_S_global);
00417     __other._M_impl->_M_add_reference();
00418     _S_global->_M_remove_reference();
00419     _S_global = __other._M_impl; 
00420     if (_S_global->_M_check_same_name() && _S_global->_M_names[0] != "*")
00421       setlocale(LC_ALL, __other.name().c_str());
00422     return __old;
00423   }
00424 
00425   string
00426   locale::name() const
00427   {
00428     string __ret;
00429     // Need some kind of separator character. This one was pretty much
00430     // arbitrarily chosen as to not conflict with glibc locales: the
00431     // exact formatting is not set in stone.
00432     const char __separator = '|';
00433 
00434     if (_M_impl->_M_check_same_name())
00435       __ret = _M_impl->_M_names[0];
00436     else
00437       {
00438     for (size_t i = 0; i < _S_num_categories; ++i)
00439       __ret += __separator + _M_impl->_M_names[i];
00440       }
00441     return __ret;
00442   }
00443 
00444   locale const&
00445   locale::classic()
00446   {
00447     static locale* __classic_locale;
00448     // XXX MT
00449     if (!_S_classic)
00450       {
00451     try 
00452       {
00453         // 26 Standard facets, 2 references.
00454         // One reference for _M_classic, one for _M_global
00455         _S_classic = new _Impl("C", 2);
00456         _S_global = _S_classic;         
00457 
00458         // Finesse static init order hassles
00459         __classic_locale = new locale(_S_classic);
00460       }
00461     catch(...) 
00462       {
00463         delete __classic_locale;
00464         if (_S_classic)
00465           {
00466         _S_classic->_M_remove_reference();
00467         _S_global->_M_remove_reference();
00468           }
00469         _S_classic = _S_global = 0;
00470         // XXX MT
00471         __throw_exception_again;
00472       }
00473       }
00474     return *__classic_locale;
00475   }
00476 
00477   locale::category
00478   locale::_S_normalize_category(category __cat) 
00479   {
00480     int __ret = 0;
00481     if (__cat == none || (__cat & all) && !(__cat & ~all))
00482       __ret = __cat;
00483     else
00484       {
00485     // NB: May be a C-style "LC_ALL" category; convert.
00486     switch (__cat)
00487       {
00488       case LC_COLLATE:  
00489         __ret = collate; 
00490         break;
00491       case LC_CTYPE:    
00492         __ret = ctype;
00493         break;
00494       case LC_MONETARY: 
00495         __ret = monetary;
00496         break;
00497       case LC_NUMERIC:  
00498         __ret = numeric;
00499         break;
00500       case LC_TIME:     
00501         __ret = time; 
00502         break;
00503 #ifdef _GLIBCPP_HAVE_LC_MESSAGES
00504       case LC_MESSAGES: 
00505         __ret = messages;
00506         break;
00507 #endif  
00508       case LC_ALL:      
00509         __ret = all;
00510         break;
00511       default:
00512         __throw_runtime_error("bad locale category");
00513       }
00514       }
00515     return __ret;
00516   }
00517 
00518   locale::facet::
00519   facet(size_t __refs) throw()
00520   : _M_references(__refs) 
00521   { }
00522 
00523   void  
00524   locale::facet::
00525   _M_add_reference() throw()
00526   { ++_M_references; }                     // XXX MT
00527 
00528   void  
00529   locale::facet::
00530   _M_remove_reference() throw()
00531   {
00532     if (_M_references)
00533       --_M_references;
00534     else
00535       {
00536         try 
00537       { delete this; }  // XXX MT
00538     catch (...) 
00539       { }
00540       }
00541   }
00542   
00543   // Definitions for static const data members of ctype_base.
00544   const ctype_base::mask ctype_base::space;
00545   const ctype_base::mask ctype_base::print;
00546   const ctype_base::mask ctype_base::cntrl;
00547   const ctype_base::mask ctype_base::upper;
00548   const ctype_base::mask ctype_base::lower;
00549   const ctype_base::mask ctype_base::alpha;
00550   const ctype_base::mask ctype_base::digit;
00551   const ctype_base::mask ctype_base::punct;
00552   const ctype_base::mask ctype_base::xdigit;
00553   const ctype_base::mask ctype_base::alnum;
00554   const ctype_base::mask ctype_base::graph;
00555 
00556   // Platform-specific initialization code for ctype tables.
00557   #include <bits/ctype_noninline.h>
00558 
00559   const size_t ctype<char>::table_size;
00560 
00561   ctype<char>::~ctype()
00562   { if (_M_del) delete[] this->table(); }
00563 
00564   // These are dummy placeholders as these virtual functions are never called.
00565   bool 
00566   ctype<char>::do_is(mask, char_type) const 
00567   { return false; }
00568   
00569   const char*
00570   ctype<char>::do_is(const char_type* __c, const char_type*, mask*) const 
00571   { return __c; }
00572   
00573   const char*
00574   ctype<char>::do_scan_is(mask, const char_type* __c, const char_type*) const 
00575   { return __c; }
00576 
00577   const char* 
00578   ctype<char>::do_scan_not(mask, const char_type* __c, const char_type*) const
00579   { return __c; }
00580 
00581   char
00582   ctype<char>::do_widen(char __c) const
00583   { return __c; }
00584   
00585   const char* 
00586   ctype<char>::do_widen(const char* __lo, const char* __hi, char* __dest) const
00587   {
00588     memcpy(__dest, __lo, __hi - __lo);
00589     return __hi;
00590   }
00591   
00592   char
00593   ctype<char>::do_narrow(char __c, char /*__dfault*/) const
00594   { return __c; }
00595   
00596   const char* 
00597   ctype<char>::do_narrow(const char* __lo, const char* __hi, 
00598              char /*__dfault*/, char* __dest) const
00599   {
00600     memcpy(__dest, __lo, __hi - __lo);
00601     return __hi;
00602   }
00603 
00604   template<>
00605   ctype_byname<char>::ctype_byname(const char* /*__s*/, size_t __refs)
00606   : ctype<char>(new mask[table_size], true, __refs)
00607   { }
00608 
00609   // Definitions for static const data members of money_base
00610   const money_base::pattern 
00611   money_base::_S_default_pattern =  {{symbol, sign, none, value}};
00612 
00613   template<>
00614     _Format_cache<char>::_Format_cache()
00615     : _M_valid(true),
00616     _M_decimal_point('.'), _M_thousands_sep(','),
00617     _M_truename("true"), _M_falsename("false"), _M_use_grouping(false)
00618     { }
00619 
00620 #ifdef _GLIBCPP_USE_WCHAR_T
00621   template<>
00622     _Format_cache<wchar_t>::_Format_cache()
00623     : _M_valid(true),
00624     _M_decimal_point(L'.'), _M_thousands_sep(L','),
00625     _M_truename(L"true"), _M_falsename(L"false"), _M_use_grouping(false)
00626     { }
00627 #endif
00628 
00629   template<>
00630     const ctype<char>&
00631     use_facet<ctype<char> >(const locale& __loc)
00632     {
00633       size_t __i = ctype<char>::id._M_index;
00634       const locale::_Impl* __tmp = __loc._M_impl;
00635       return static_cast<const ctype<char>&>(* (*(__tmp->_M_facets))[__i]);
00636     }
00637 
00638 #ifdef _GLIBCPP_USE_WCHAR_T
00639   template<>
00640     const ctype<wchar_t>&
00641     use_facet<ctype<wchar_t> >(const locale& __loc)
00642     {
00643       size_t __i = ctype<wchar_t>::id._M_index;
00644       const locale::_Impl* __tmp = __loc._M_impl;
00645       return static_cast<const ctype<wchar_t>&>(* (*(__tmp->_M_facets))[__i]);
00646     }
00647 #endif
00648 
00649   // This interface passes a fixed size buffer. The function cannot handle
00650   // input longer than the buffer and sets failbit in that case. This is
00651   // not strictly compliant since the input may be valid, but we are stuck
00652   // with this ABI on the 3.0 branch. Since leading zeros are discarded all
00653   // valid integer input should be OK, only floating point input can exceed
00654   // the buffer.
00655   template<>
00656     void
00657     num_get<char, istreambuf_iterator<char> >::
00658     _M_extract(istreambuf_iterator<char> __beg, 
00659            istreambuf_iterator<char> __end, ios_base& __io, 
00660            ios_base::iostate& __err, char* __xtrc, int& __base, 
00661            bool __fp) const
00662     {
00663       typedef _Format_cache<char> __cache_type; 
00664 
00665       // Prepare for possible failure
00666       __xtrc[0] = '\0';
00667 
00668       // Stage 1: determine a conversion specifier.
00669       ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
00670       if (__basefield == ios_base::dec)
00671         __base = 10;
00672       else if (__basefield == ios_base::oct)
00673         __base = 8;
00674       else if (__basefield == ios_base::hex)
00675         __base = 16;
00676       else
00677         __base = 0;
00678       // As far as I can tell, bases other than 10 are not available for
00679       // floating point types
00680       if (__fp)
00681         __base = 10;
00682 
00683       // Stage 2: extract characters.
00684       __cache_type const* __fmt = __cache_type::_S_get(__io);
00685 
00686       // Fail quickly if !__valid
00687       if (__beg == __end)
00688         {
00689           __err |= (ios_base::eofbit | ios_base::failbit);
00690           return;
00691         }
00692 
00693       // Acceptable formats for numbers here are based on 22.2.3.1
00694       string __grp;
00695       int __sep_pos = 0;
00696       int __pos = 0;
00697       const char* __lits = __fmt->_S_literals;
00698       char __c = *__beg;
00699 
00700       // Check first for sign
00701       bool __testsign = false;
00702       if ((__c == __lits[__cache_type::_S_minus])
00703       || (__c == __lits[__cache_type::_S_plus]))
00704         {
00705           __testsign = true;
00706           __xtrc[__pos++] = __c;
00707           ++__beg;
00708       __c = * __beg;
00709 
00710           // Whitespace may follow a sign
00711           while ((__beg != __end) && (isspace(__c)))
00712         {
00713           ++__beg;
00714           __c = *__beg;
00715         }
00716 
00717           // There had better be more to come...
00718           if (__beg == __end)
00719             {
00720               __xtrc[__pos] = '\0';
00721               __err |= (ios_base::eofbit | ios_base::failbit);
00722               return;
00723             }
00724         }
00725 
00726       // Now check if first character is a zero.
00727       bool __testzero = false;    
00728       if (__c == __lits[__cache_type::_S_digits])
00729         {
00730            __testzero = true;
00731            ++__beg;
00732        __c = *__beg;
00733 
00734            // We have to check for __beg == __end here. If so,
00735            // a plain '0' (possibly with a sign) can be got rid of now
00736            if (__beg == __end)
00737              {
00738                __xtrc[__pos++] = __lits[__cache_type::_S_digits];
00739                __xtrc[__pos] = '\0';
00740                __err |= ios_base::eofbit;
00741                return;
00742              }
00743 
00744           // Figure out base for integer types only
00745           // Based on Table 55 of 22.2.2.1.2
00746           if (!__fp && __base != 10 && __base != 8)
00747             {
00748               // Here, __base == 0 or 16
00749               if ((__c == __lits[__cache_type::_S_x])
00750                  || (__c == __lits[__cache_type::_S_X]))
00751                 {
00752                   ++__beg;
00753           __c = *__beg;
00754                   __base = 16;
00755                   __testzero = false; // "0x" is not a leading zero
00756                 }
00757               else if (__base == 0)
00758                 __base = 8;
00759             }
00760 
00761           // Remove any more leading zeros
00762           while (__beg != __end)
00763             {
00764               if (__c == __lits[__cache_type::_S_digits])
00765                 {
00766                   ++__beg;
00767           __c = *__beg;
00768                   __testzero = true;
00769                 }
00770               else
00771                 break;
00772             }
00773         }
00774       else if (__base == 0) // 1st character is not zero
00775         __base = 10;
00776 
00777       // We now seek "units", i.e. digits and thousands separators.
00778       // We may need to know if anything is found here. A leading zero
00779       // (removed by now) would count.
00780       bool __testunits = __testzero;
00781       while (__beg != __end)
00782         {
00783           const char* __p = strchr(__lits, __c);
00784 
00785           // NB: strchr returns true for __c == 0x0
00786           if (__p && __c
00787           &&((__p >= &__lits[__cache_type::_S_digits]
00788           && __p < &__lits[__cache_type::_S_digits + __base])
00789          || (__p >= &__lits[__cache_type::_S_udigits]
00790              && __p < &__lits[__cache_type::_S_udigits + __base])))
00791         {
00792           // Try first for acceptable digit; record it if found.
00793           __xtrc[__pos++] = __c;
00794               if (__pos == _M_extract_buffer_length)
00795                 {
00796                   // XXX This is non-compliant, but our fixed-size
00797                   // buffer is full.
00798                   __xtrc[_M_extract_buffer_length-1] = '\0';
00799           __err |= ios_base::failbit;
00800                   return;
00801                 }
00802           ++__sep_pos;
00803           __testunits = true;
00804           ++__beg;
00805           __c = *__beg;
00806         }
00807           else if (__c == __fmt->_M_thousands_sep && __fmt->_M_use_grouping)
00808         {
00809               // NB: Thousands separator at the beginning of a string
00810               // is a no-no, as is two consecutive thousands
00811               // separators.
00812               if (__sep_pos)
00813                 {
00814                   __grp += static_cast<char>(__sep_pos);
00815                   __sep_pos = 0;
00816           ++__beg;
00817           __c = *__beg;
00818                 }
00819               else
00820         {
00821           __err |= ios_base::failbit;
00822           break;
00823         }
00824             }
00825       else
00826         // Not a valid input item.
00827         break;
00828         }
00829 
00830       // Digit grouping is checked. If _M_groupings() doesn't
00831       // match, then get very very upset, and set failbit.
00832       if (__fmt->_M_use_grouping && !__grp.empty())
00833         {
00834           // Add the ending grouping
00835           __grp += static_cast<char>(__sep_pos);
00836 
00837           // __grp is parsed L to R
00838           // 1,222,444 == __grp of "/1/3/3"
00839           // __fmt->_M_grouping is parsed R to L
00840           // 1,222,444 == __fmt->_M_grouping of "/3" == "/3/3/3"
00841           int __i = 0;
00842           int __j = 0;
00843           const int __len = __fmt->_M_grouping.size();
00844           int __n = __grp.size();
00845           bool __test = true;
00846 
00847           // Parsed number groupings have to match the
00848           // numpunct::grouping string exactly, starting at the
00849           // right-most point of the parsed sequence of elements ...
00850           while (__test && __i < __n - 1)
00851             for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
00852               __test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1];
00853           // ... but the last parsed grouping can be <= numpunct
00854           // grouping.
00855           __j == __len ? __j = 0 : __j;
00856           __test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1];
00857 
00858           if (!__test)
00859             {
00860               __err |= ios_base::failbit;
00861               __xtrc[__pos] = '\0';
00862               if (__beg == __end)
00863                 __err |= ios_base::eofbit;
00864               return;
00865             }
00866         }
00867 
00868       // If there was nothing but zeros, put one in the output string
00869       if (__testzero && (__pos == 0 || (__pos == 1 && __testsign)))
00870         __xtrc[__pos++] = __lits[__cache_type::_S_digits];
00871 
00872       // That's it for integer types. Remaining code is for floating point
00873       if (__fp && __beg != __end)
00874         {
00875           // Check first for decimal point. There MUST be one if
00876           // __testunits is false.
00877           bool __testdec = false;    // Is there a decimal point
00878                                      // with digits following it?
00879           if (__c == __fmt->_M_decimal_point)
00880             {
00881               __xtrc[__pos++] = '.';
00882               if (__pos == _M_extract_buffer_length)
00883                 {
00884                   // XXX This is non-compliant, but our fixed-size
00885                   // buffer is full.
00886                   __xtrc[_M_extract_buffer_length-1] = '\0';
00887           __err |= ios_base::failbit;
00888                   return;
00889                 }
00890               ++__beg;
00891           __c = *__beg;
00892 
00893               // Now we get any digits after the decimal point
00894               // There MUST be some if __testunits is false.
00895               while (__beg != __end)
00896                 {
00897                   const char* __p = strchr(__lits, __c);
00898                   if ((__p >= &__lits[__cache_type::_S_digits]
00899                         && __p < &__lits[__cache_type::_S_digits + __base])
00900                        || (__p >= &__lits[__cache_type::_S_udigits]
00901                            && __p < &__lits[__cache_type::_S_udigits + __base]))
00902                     {
00903                       __xtrc[__pos++] = __c;
00904                       if (__pos == _M_extract_buffer_length)
00905                         {
00906                           // XXX This is non-compliant, but our fixed-size
00907                           // buffer is full.
00908                           __xtrc[_M_extract_buffer_length-1] = '\0';
00909                   __err |= ios_base::failbit;
00910                           return;
00911                         }
00912                       ++__beg;
00913               __c = *__beg;
00914                       __testdec = true;
00915                     }
00916                   else
00917                     break;
00918                 }
00919             }
00920           if (!__testunits && !__testdec) // Ill formed
00921             {
00922               __err |= ios_base::failbit;
00923               __xtrc[__pos] = '\0';
00924               if (__beg == __end)
00925                 __err |= ios_base::eofbit;
00926               return;
00927             }
00928 
00929           // Now we may find an exponent
00930           if (__beg != __end)
00931             {
00932               if ((__c == __lits[__cache_type::_S_ee])
00933                    || (__c == __lits[__cache_type::_S_Ee]))
00934                 {
00935                   __xtrc[__pos++] = __c;
00936                   if (__pos == _M_extract_buffer_length)
00937                     {
00938                       // XXX This is non-compliant, but our fixed-size
00939                       // buffer is full.
00940                       __xtrc[_M_extract_buffer_length-1] = '\0';
00941                   __err |= ios_base::failbit;
00942                       return;
00943                     }
00944                   ++__beg;
00945           __c = *__beg;
00946 
00947                   // Now there may be a sign
00948                   if (__beg != __end)
00949                     {
00950                       if ((__c == __lits[__cache_type::_S_minus])
00951                           || (__c == __lits[__cache_type::_S_plus]))
00952                         {
00953                           __xtrc[__pos++] = __c;
00954                           if (__pos == _M_extract_buffer_length)
00955                             {
00956                               // XXX This is non-compliant, but our fixed-size
00957                               // buffer is full.
00958                               __xtrc[_M_extract_buffer_length-1] = '\0';
00959                           __err |= ios_base::failbit;
00960                               return;
00961                             }
00962                           ++__beg;
00963               __c = *__beg;
00964                           // whitespace may follow a sign
00965                           while ((__beg != __end) && (isspace(__c)))
00966                 {
00967                   ++__beg;
00968                   __c = *__beg;
00969                 }
00970                         }
00971                     }
00972                   // And now there must be some digits
00973                   if (__beg == __end)
00974                     {
00975                       __xtrc[__pos] = '\0';
00976                       __err |= (ios_base::eofbit | ios_base::failbit);
00977                       return;
00978                     }
00979                   while (__beg != __end)
00980                     {
00981                       const char* __p = strchr(__lits, __c);
00982                       if ((__p >= &__lits[__cache_type::_S_digits]
00983                             && __p < &__lits[__cache_type::_S_digits + __base])
00984                            || (__p >= &__lits[__cache_type::_S_udigits]
00985                                && __p < &__lits[__cache_type::_S_udigits + __base]))
00986                         {
00987                           __xtrc[__pos++] = __c;
00988                           if (__pos == _M_extract_buffer_length)
00989                             {
00990                               // XXX This is non-compliant, but our fixed-size
00991                               // buffer is full.
00992                               __xtrc[_M_extract_buffer_length-1] = '\0';
00993                           __err |= ios_base::failbit;
00994                               return;
00995                             }
00996                           ++__beg;
00997               __c = *__beg;
00998                         }
00999                       else
01000                         break;
01001                     }
01002                 }
01003             }
01004           // Finally, that's it for floating point
01005         }
01006 
01007       // Finish up
01008       __xtrc[__pos] = '\0';
01009       if (__beg == __end)
01010         __err |= ios_base::eofbit;
01011     }
01012 
01013   // The following code uses sprintf() to convert floating point
01014   // values for insertion into a stream. The current implementation
01015   // replicates the code in _S_pad_numeric() (in _S_output_float()) in
01016   // order to prevent having to create a "wide" buffer in addition to
01017   // the "narrow" buffer passed to sprintf(). An optimization would be
01018   // to replace sprintf() with code that works directly on a wide
01019   // buffer and then use _S_pad_numeric() to do the padding. It would
01020   // be good to replace sprintf() anyway to avoid accidental buffer
01021   // overruns and to gain back the efficiency that C++ provides by
01022   // knowing up front the type of the values to insert. This
01023   // implementation follows the C++ standard fairly directly as
01024   // outlined in 22.2.2.2 [lib.locale.num.put]
01025   bool
01026   __build_float_format(ios_base& __io, char* __fptr, char __modifier,
01027                streamsize __prec)
01028   {
01029     bool __incl_prec = false;
01030     ios_base::fmtflags __flags = __io.flags();
01031     *__fptr++ = '%';
01032     // [22.2.2.2.2] Table 60
01033     if (__flags & ios_base::showpos)
01034       *__fptr++ = '+';
01035     if (__flags & ios_base::showpoint)
01036       *__fptr++ = '#';
01037     // As per [22.2.2.2.2.11]
01038     if (__flags & ios_base::fixed || __prec > 0)
01039       {
01040         *__fptr++ = '.';
01041         *__fptr++ = '*';
01042         __incl_prec = true;
01043       }
01044     if (__modifier)
01045       *__fptr++ = __modifier;
01046     ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
01047     // [22.2.2.2.2] Table 58
01048     if (__fltfield == ios_base::fixed)
01049       *__fptr++ = 'f';
01050     else if (__fltfield == ios_base::scientific)
01051       *__fptr++ = (__flags & ios_base::uppercase) ? 'E' : 'e';
01052     else
01053       *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g';
01054     *__fptr = '\0';
01055     return __incl_prec;
01056   }
01057 
01058   template <>
01059   collate<char>::collate(size_t __refs)
01060   : locale::facet(__refs) { }
01061   
01062   template<>
01063   collate<char>::~collate() { }
01064   
01065   template<>
01066   int 
01067   collate<char>::do_compare(const char* __lo1, const char* __hi1, 
01068                 const char* __lo2, const char* __hi2) const
01069   {
01070     for (; __lo1 < __hi1 && __lo2 < __hi2; ++__lo1, ++__lo2) 
01071       if (*__lo1 != *__lo2) 
01072     return (*__lo1 < *__lo2) ? -1 : 1;
01073     if (__lo1 < __hi1) 
01074       return 1;
01075     else if (__lo2 < __hi2) 
01076       return -1;
01077     else 
01078       return 0;
01079   }
01080   
01081   template<>
01082   string
01083   collate<char>::
01084   do_transform(const char* __lo, const char* __hi) const
01085   { return string(__lo, __hi - __lo); }
01086   
01087   template<>
01088   long
01089   collate<char>::
01090   do_hash(const char* __lo, const char* __hi) const
01091   {
01092     unsigned long __val = 0xdeadbeef;
01093     for (; __lo < __hi; ++__lo)
01094       __val = *__lo ^ ((__val << 7) & 
01095            (__val >> (numeric_limits<unsigned long>::digits - 1)));
01096     return __val;
01097   }
01098 
01099   template<>  
01100   collate_byname<char>::collate_byname(const char* /*__s*/, size_t __refs)
01101   : collate<char>(__refs) { }
01102 
01103   template<>
01104   moneypunct_byname<char, false>::moneypunct_byname(const char* /*__s*/, 
01105                             size_t __refs)
01106   : moneypunct<char, false>(__refs) { }
01107   
01108   template<>
01109   moneypunct_byname<char, true>::moneypunct_byname(const char* /*__s*/, 
01110                            size_t __refs)
01111   : moneypunct<char, true>(__refs) { }
01112   
01113   template<>
01114   messages_byname<char>::
01115   messages_byname(const char* /*__s*/, size_t __refs)
01116   : messages<char>(__refs) { }
01117 
01118 #ifdef _GLIBCPP_USE_WCHAR_T  
01119   ctype<wchar_t>::__wmask_type
01120   ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
01121   {
01122     __wmask_type __ret;
01123     switch (__m)
01124       {
01125       case space:
01126     __ret = wctype("space");
01127     break;
01128       case print:
01129     __ret = wctype("print");
01130     break;
01131       case cntrl:
01132     __ret = wctype("cntrl");
01133     break;
01134       case upper:
01135     __ret = wctype("upper");
01136     break;
01137       case lower:
01138     __ret = wctype("lower");
01139     break;
01140       case alpha:
01141     __ret = wctype("alpha");
01142     break;
01143       case digit:
01144     __ret = wctype("digit");
01145     break;
01146       case punct:
01147     __ret = wctype("punct");
01148     break;
01149       case xdigit:
01150     __ret = wctype("xdigit");
01151     break;
01152       case alnum:
01153     __ret = wctype("alnum");
01154     break;
01155       case graph:
01156     __ret = wctype("graph");
01157     break;
01158       default:
01159     __ret = 0;
01160       }
01161     return __ret;
01162   };
01163   
01164   ctype<wchar_t>::~ctype() { }
01165 
01166   // NB: These ctype<wchar_t> methods are not configuration-specific,
01167   // unlike the ctype<char> bits.
01168   ctype<wchar_t>::ctype(size_t __refs) : __ctype_abstract_base<wchar_t>(__refs)
01169   { }
01170 
01171   wchar_t
01172   ctype<wchar_t>::do_toupper(wchar_t __c) const
01173   { return towupper(__c); }
01174 
01175   const wchar_t*
01176   ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
01177   {
01178     while (__lo < __hi)
01179       {
01180         *__lo = towupper(*__lo);
01181         ++__lo;
01182       }
01183     return __hi;
01184   }
01185   
01186   wchar_t
01187   ctype<wchar_t>::do_tolower(wchar_t __c) const
01188   { return towlower(__c); }
01189   
01190   const wchar_t*
01191   ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
01192   {
01193     while (__lo < __hi)
01194       {
01195         *__lo = towlower(*__lo);
01196         ++__lo;
01197       }
01198     return __hi;
01199   }
01200 
01201   bool
01202   ctype<wchar_t>::
01203   do_is(mask __m, char_type __c) const
01204   { return static_cast<bool>(iswctype(__c, _M_convert_to_wmask(__m))); }
01205   
01206   const wchar_t* 
01207   ctype<wchar_t>::
01208   do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __m) const
01209   {
01210     while (__lo < __hi && !this->is(*__m, *__lo))
01211       ++__lo;
01212     return __lo;
01213   }
01214   
01215   const wchar_t* 
01216   ctype<wchar_t>::
01217   do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
01218   {
01219     while (__lo < __hi && !this->is(__m, *__lo))
01220       ++__lo;
01221     return __lo;
01222   }
01223 
01224   const wchar_t*
01225   ctype<wchar_t>::
01226   do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
01227   {
01228     while (__lo < __hi && this->is(__m, *__lo) != 0)
01229       ++__lo;
01230     return __lo;
01231   }
01232 
01233   wchar_t
01234   ctype<wchar_t>::
01235   do_widen(char __c) const
01236   { return btowc(__c); }
01237   
01238   const char* 
01239   ctype<wchar_t>::
01240   do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
01241   {
01242     mbstate_t __state;
01243     memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
01244     mbsrtowcs(__dest, &__lo, __hi - __lo, &__state);
01245     return __hi;
01246   }
01247 
01248   char
01249   ctype<wchar_t>::
01250   do_narrow(wchar_t __wc, char __dfault) const
01251   { 
01252     int __c = wctob(__wc);
01253     return (__c == EOF ? __dfault : static_cast<char>(__c)); 
01254   }
01255 
01256   const wchar_t*
01257   ctype<wchar_t>::
01258   do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, 
01259         char* __dest) const
01260   {
01261     mbstate_t __state;
01262     memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
01263     size_t __len = __hi - __lo;
01264     size_t __conv = wcsrtombs(__dest, &__lo, __len, &__state);
01265     if (__conv == __len)
01266       *__dest = __dfault;
01267     return __hi;
01268   }
01269 
01270   template<>
01271   ctype_byname<wchar_t>::
01272   ctype_byname(const char* /*__s*/, size_t __refs)
01273   : ctype<wchar_t>(__refs) { }
01274 
01275   template<>
01276   collate<wchar_t>::
01277   collate(size_t __refs): locale::facet(__refs) { }
01278   
01279   template<>
01280   collate<wchar_t>::
01281   ~collate() { }
01282 
01283   template<>
01284   int 
01285   collate<wchar_t>::
01286   do_compare(const wchar_t* /*__lo1*/, const wchar_t* /*__hi1*/,
01287          const wchar_t* /*__lo2*/, const wchar_t* /*__hi2*/) const
01288   {
01289     return 0; // XXX not done
01290   }
01291 
01292   template<>  
01293   wstring collate<wchar_t>::
01294   do_transform(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const
01295   {
01296     return wstring(); // XXX not done
01297   }
01298   
01299   template<>
01300   long collate<wchar_t>::
01301   do_hash(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const
01302   {
01303     return 0; // XXX not done
01304   }
01305 
01306   template<>
01307   collate_byname<wchar_t>::
01308   collate_byname(const char* /*__s*/, size_t __refs)
01309   : collate<wchar_t> (__refs) { }
01310   
01311   template<>
01312   messages_byname<wchar_t>::
01313   messages_byname(const char* /*__s*/, size_t __refs)
01314   : messages<wchar_t> (__refs) { }
01315 #endif //  _GLIBCPP_USE_WCHAR_T
01316 } // namespace std
01317 

Generated on Sat Apr 19 07:14:23 2003 for libstdc++-v3 Source by doxygen1.2.15