Whole document tree
    

Whole document tree

locale.cc Source File
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 Mon Apr 8 03:11:28 2002 for libstdc++-v3 Source by doxygen1.2.15