locale.cc

00001 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
00002 // Free Software Foundation, Inc.
00003 //
00004 // This file is part of the GNU ISO C++ Library.  This library is free
00005 // software; you can redistribute it and/or modify it under the
00006 // terms of the GNU General Public License as published by the
00007 // Free Software Foundation; either version 2, or (at your option)
00008 // any later version.
00009 
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License along
00016 // with this library; see the file COPYING.  If not, write to the Free
00017 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00018 // USA.
00019 
00020 // As a special exception, you may use this file as part of a free software
00021 // library without restriction.  Specifically, if other files instantiate
00022 // templates or use macros or inline functions from this file, or you compile
00023 // this file and link it with other files to produce an executable, this
00024 // file does not by itself cause the resulting executable to be covered by
00025 // the GNU General Public License.  This exception does not however
00026 // invalidate any other reasons why the executable file might be covered by
00027 // the GNU General Public License.
00028 
00029 #include <clocale>
00030 #include <cstring>
00031 #include <cstdlib>     // For getenv
00032 #include <cctype>
00033 #include <cwctype>     // For towupper, etc.
00034 #include <locale>
00035 #include <bits/atomicity.h>
00036 
00037 namespace std 
00038 {
00039   // Definitions for static const data members of locale.
00040   const locale::category    locale::none;
00041   const locale::category    locale::ctype;
00042   const locale::category    locale::numeric;
00043   const locale::category    locale::collate;
00044   const locale::category    locale::time;
00045   const locale::category    locale::monetary;
00046   const locale::category    locale::messages;
00047   const locale::category    locale::all;
00048 
00049   // These are no longer exported.
00050   locale::_Impl*                locale::_S_classic;
00051   locale::_Impl*        locale::_S_global; 
00052   const size_t          locale::_S_categories_size;
00053 
00054 #ifdef __GTHREADS
00055   __gthread_once_t      locale::_S_once = __GTHREAD_ONCE_INIT;
00056 #endif
00057 
00058   locale::locale(const locale& __other) throw()
00059   : _M_impl(__other._M_impl)
00060   { _M_impl->_M_add_reference(); }
00061 
00062   // This is used to initialize global and classic locales, and
00063   // assumes that the _Impl objects are constructed correctly.
00064   // The lack of a reference increment is intentional.
00065   locale::locale(_Impl* __ip) throw() : _M_impl(__ip)
00066   { }
00067 
00068   locale::~locale() throw()
00069   { _M_impl->_M_remove_reference(); }
00070 
00071   bool
00072   locale::operator==(const locale& __rhs) const throw()
00073   {
00074     bool __ret = false;
00075     if (_M_impl == __rhs._M_impl)
00076       __ret = true;
00077     else
00078       {
00079     const string __name = this->name();
00080     if (__name != "*" && __name == __rhs.name())
00081       __ret = true;
00082       }
00083     return __ret;
00084   }
00085 
00086   const locale&
00087   locale::operator=(const locale& __other) throw()
00088   {
00089     __other._M_impl->_M_add_reference();
00090     _M_impl->_M_remove_reference();
00091     _M_impl = __other._M_impl;
00092     return *this;
00093   }
00094 
00095   string
00096   locale::name() const
00097   {
00098     string __ret;
00099     if (_M_impl->_M_check_same_name())
00100       __ret = _M_impl->_M_names[0];
00101     else
00102       {
00103     __ret += _S_categories[0];
00104     __ret += '=';
00105     __ret += _M_impl->_M_names[0]; 
00106     for (size_t __i = 1; __i < _S_categories_size; ++__i)
00107       {
00108         __ret += ';';
00109         __ret += _S_categories[__i];
00110         __ret += '=';
00111         __ret += _M_impl->_M_names[__i];
00112       }
00113       }
00114     return __ret;
00115   }
00116 
00117   locale::category
00118   locale::_S_normalize_category(category __cat) 
00119   {
00120     int __ret = 0;
00121     if (__cat == none || (__cat & all) && !(__cat & ~all))
00122       __ret = __cat;
00123     else
00124       {
00125     // NB: May be a C-style "LC_ALL" category; convert.
00126     switch (__cat)
00127       {
00128       case LC_COLLATE:  
00129         __ret = collate; 
00130         break;
00131       case LC_CTYPE:    
00132         __ret = ctype;
00133         break;
00134       case LC_MONETARY: 
00135         __ret = monetary;
00136         break;
00137       case LC_NUMERIC:  
00138         __ret = numeric;
00139         break;
00140       case LC_TIME:     
00141         __ret = time; 
00142         break;
00143 #ifdef _GLIBCXX_HAVE_LC_MESSAGES
00144       case LC_MESSAGES: 
00145         __ret = messages;
00146         break;
00147 #endif  
00148       case LC_ALL:      
00149         __ret = all;
00150         break;
00151       default:
00152         __throw_runtime_error(__N("locale::_S_normalize_category "
00153                   "category not found"));
00154       }
00155       }
00156     return __ret;
00157   }
00158 
00159   // locale::facet
00160   __c_locale locale::facet::_S_c_locale;
00161 
00162   const char locale::facet::_S_c_name[2] = "C";
00163 
00164 #ifdef __GTHREADS
00165   __gthread_once_t locale::facet::_S_once = __GTHREAD_ONCE_INIT;
00166 #endif
00167 
00168   void
00169   locale::facet::_S_initialize_once()
00170   {
00171     // Initialize the underlying locale model.
00172     _S_create_c_locale(_S_c_locale, _S_c_name);
00173   }
00174 
00175   __c_locale
00176   locale::facet::_S_get_c_locale()
00177   {
00178 #ifdef __GHTREADS
00179     if (__gthread_active_p())
00180       __gthread_once(&_S_once, _S_initialize_once);
00181     else
00182 #endif
00183       {
00184     if (!_S_c_locale)
00185       _S_initialize_once();
00186       }
00187     return _S_c_locale;
00188   }
00189 
00190   const char*
00191   locale::facet::_S_get_c_name()
00192   { return _S_c_name; }
00193 
00194   locale::facet::
00195   ~facet() { }
00196 
00197   // locale::_Impl
00198   locale::_Impl::
00199   ~_Impl() throw()
00200   {
00201     if (_M_facets)
00202       for (size_t __i = 0; __i < _M_facets_size; ++__i)
00203     if (_M_facets[__i])
00204       _M_facets[__i]->_M_remove_reference();
00205     delete [] _M_facets;
00206 
00207     if (_M_caches)
00208       for (size_t __i = 0; __i < _M_facets_size; ++__i)
00209     if (_M_caches[__i])
00210       _M_caches[__i]->_M_remove_reference(); 
00211     delete [] _M_caches;
00212 
00213     if (_M_names)
00214       for (size_t __i = 0; __i < _S_categories_size; ++__i)
00215     delete [] _M_names[__i];  
00216     delete [] _M_names;
00217   }
00218 
00219   // Clone existing _Impl object.
00220   locale::_Impl::
00221   _Impl(const _Impl& __imp, size_t __refs)
00222   : _M_refcount(__refs), _M_facets(0), _M_facets_size(__imp._M_facets_size),
00223   _M_caches(0), _M_names(0)
00224   {
00225     try
00226       {
00227     _M_facets = new const facet*[_M_facets_size];
00228     for (size_t __i = 0; __i < _M_facets_size; ++__i)
00229       {
00230         _M_facets[__i] = __imp._M_facets[__i];
00231         if (_M_facets[__i])
00232           _M_facets[__i]->_M_add_reference();
00233       }
00234     _M_caches = new const facet*[_M_facets_size];
00235     for (size_t __j = 0; __j < _M_facets_size; ++__j)
00236       {
00237         _M_caches[__j] = __imp._M_caches[__j];
00238         if (_M_caches[__j])
00239           _M_caches[__j]->_M_add_reference();   
00240       }
00241     _M_names = new char*[_S_categories_size];
00242     for (size_t __k = 0; __k < _S_categories_size; ++__k)
00243       _M_names[__k] = 0;
00244 
00245     // Name all the categories.
00246     for (size_t __l = 0; __l < _S_categories_size; ++__l)
00247       {
00248         char* __new = new char[std::strlen(__imp._M_names[__l]) + 1];
00249         std::strcpy(__new, __imp._M_names[__l]);
00250         _M_names[__l] = __new;
00251       }
00252       }
00253     catch(...)
00254       {
00255     this->~_Impl();
00256     __throw_exception_again;
00257       }
00258   }
00259 
00260   void
00261   locale::_Impl::
00262   _M_replace_category(const _Impl* __imp, 
00263               const locale::id* const* __idpp)
00264   {
00265     for (; *__idpp; ++__idpp)
00266       _M_replace_facet(__imp, *__idpp);
00267   }
00268   
00269   void
00270   locale::_Impl::
00271   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
00272   {
00273     size_t __index = __idp->_M_id();
00274     if ((__index > (__imp->_M_facets_size - 1)) 
00275     || !__imp->_M_facets[__index])
00276       __throw_runtime_error(__N("locale::_Impl::_M_replace_facet"));
00277     _M_install_facet(__idp, __imp->_M_facets[__index]); 
00278   }
00279 
00280   void
00281   locale::_Impl::
00282   _M_install_facet(const locale::id* __idp, const facet* __fp)
00283   {
00284     if (__fp)
00285       {
00286     size_t __index = __idp->_M_id();
00287 
00288     // Check size of facet vector to ensure adequate room.
00289     if (__index > _M_facets_size - 1)
00290       {
00291         const size_t __new_size = __index + 4;
00292 
00293         // New facet array.
00294         const facet** __oldf = _M_facets;
00295         const facet** __newf;
00296         __newf = new const facet*[__new_size]; 
00297         for (size_t __i = 0; __i < _M_facets_size; ++__i)
00298           __newf[__i] = _M_facets[__i];
00299         for (size_t __l = _M_facets_size; __l < __new_size; ++__l)
00300           __newf[__l] = 0;
00301 
00302         // New cache array.
00303         const facet** __oldc = _M_caches;
00304         const facet** __newc;
00305         try
00306           {
00307         __newc = new const facet*[__new_size];
00308           }
00309         catch(...)
00310           {
00311         delete [] __newf;
00312         __throw_exception_again;
00313           }
00314         for (size_t __j = 0; __j < _M_facets_size; ++__j)
00315           __newc[__j] = _M_caches[__j];
00316         for (size_t __k = _M_facets_size; __k < __new_size; ++__k)
00317           __newc[__k] = 0;
00318 
00319         _M_facets_size = __new_size;
00320         _M_facets = __newf;
00321         _M_caches = __newc;
00322         delete [] __oldf;
00323         delete [] __oldc;
00324       }
00325 
00326     __fp->_M_add_reference();
00327     const facet*& __fpr = _M_facets[__index];
00328     if (__fpr)
00329       {
00330         // Replacing an existing facet. Order matters.
00331         __fpr->_M_remove_reference();
00332         __fpr = __fp;
00333       }
00334     else
00335       {
00336         // Installing a newly created facet into an empty
00337         // _M_facets container, say a newly-constructed,
00338         // swanky-fresh _Impl.
00339         _M_facets[__index] = __fp;
00340       }
00341 
00342     // Ideally, it would be nice to only remove the caches that
00343     // are now incorrect. However, some of the caches depend on
00344     // multiple facets, and we only know about one facet
00345     // here. It's no great loss: the first use of the new facet
00346     // will create a new, correctly cached facet anyway.
00347     for (size_t __i = 0; __i < _M_facets_size; ++__i)
00348       {
00349         const facet* __cpr = _M_caches[__i];
00350         if (__cpr)
00351           {
00352         __cpr->_M_remove_reference();
00353         _M_caches[__i] = 0;
00354           }
00355       }
00356       }
00357   }
00358 
00359 
00360   // locale::id
00361   // Definitions for static const data members of locale::id
00362   _Atomic_word locale::id::_S_refcount;  // init'd to 0 by linker
00363 
00364   size_t
00365   locale::id::_M_id() const
00366   {
00367     if (!_M_index)
00368       _M_index = 1 + __gnu_cxx::__exchange_and_add(&_S_refcount, 1);
00369     return _M_index - 1;
00370   }
00371 } // namespace std
00372 
00373 

Generated on Fri May 6 01:09:00 2005 for libstdc++-v3 Source by  doxygen 1.4.2