localename.cc

00001 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
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 <locale>
00032 
00033 namespace __gnu_cxx
00034 {
00035   using namespace std;
00036 
00037   // Defined in globals.cc.
00038   extern locale::facet* facet_vec[_GLIBCPP_NUM_FACETS];
00039   extern locale::facet* facet_cache_vec[2 * _GLIBCPP_NUM_FACETS];
00040   extern char* facet_name[6 + _GLIBCPP_NUM_CATEGORIES];
00041 
00042   extern std::ctype<char>           ctype_c;
00043   extern std::collate<char>             collate_c;
00044   extern numpunct<char>             numpunct_c;
00045   extern num_get<char>              num_get_c;
00046   extern num_put<char>              num_put_c;
00047   extern codecvt<char, char, mbstate_t>     codecvt_c;
00048   extern moneypunct<char, false>        moneypunct_fc;
00049   extern moneypunct<char, true>         moneypunct_tc;
00050   extern money_get<char>            money_get_c;
00051   extern money_put<char>            money_put_c;
00052   extern __timepunct<char>          timepunct_c;
00053   extern time_get<char>             time_get_c;
00054   extern time_put<char>             time_put_c;
00055   extern std::messages<char>            messages_c;
00056 #ifdef  _GLIBCPP_USE_WCHAR_T
00057   extern std::ctype<wchar_t>            ctype_w;
00058   extern std::collate<wchar_t>          collate_w;
00059   extern numpunct<wchar_t>          numpunct_w;
00060   extern num_get<wchar_t>           num_get_w;
00061   extern num_put<wchar_t>           num_put_w;
00062   extern codecvt<wchar_t, char, mbstate_t>  codecvt_w;
00063   extern moneypunct<wchar_t, false>         moneypunct_fw;
00064   extern moneypunct<wchar_t, true>      moneypunct_tw;
00065   extern money_get<wchar_t>             money_get_w;
00066   extern money_put<wchar_t>             money_put_w;
00067   extern __timepunct<wchar_t>           timepunct_w;
00068   extern time_get<wchar_t>          time_get_w;
00069   extern time_put<wchar_t>          time_put_w;
00070   extern std::messages<wchar_t>         messages_w;
00071 #endif
00072 
00073   extern std::__locale_cache<numpunct<char> >   locale_cache_np_c;
00074 #ifdef  _GLIBCPP_USE_WCHAR_T
00075   extern std::__locale_cache<numpunct<wchar_t> >    locale_cache_np_w;
00076 #endif
00077 } // namespace __gnu_cxx
00078 
00079 namespace std
00080 {
00081   using namespace __gnu_cxx;
00082 
00083   locale::_Impl::
00084   ~_Impl() throw()
00085   {
00086     // Clean up facets, then caches.  No cache refcounts for now.
00087     if (_M_facets)
00088       {
00089     for (size_t __i = 0; __i < _M_facets_size; ++__i)
00090       if (_M_facets[__i])
00091         _M_facets[__i]->_M_remove_reference();
00092 
00093     for (size_t __i = _M_facets_size; __i < 2*_M_facets_size; ++__i)
00094       if (_M_facets[__i])
00095         delete (__locale_cache_base*)_M_facets[__i];
00096       }
00097     delete [] _M_facets;
00098 
00099     for (size_t __i = 0; 
00100      __i < _S_categories_size + _S_extra_categories_size; ++__i)
00101       delete [] _M_names[__i];
00102   }
00103 
00104   // Clone existing _Impl object.
00105   locale::_Impl::
00106   _Impl(const _Impl& __imp, size_t __refs)
00107   : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX
00108   {
00109     _M_facets = 0;
00110     for (size_t __i = 0; __i < _S_categories_size
00111                      + _S_extra_categories_size; ++__i)
00112       _M_names[__i] = 0;
00113     try
00114       { 
00115     // Space for facets and matching caches
00116     _M_facets = new facet*[2*_M_facets_size]; 
00117     for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
00118       _M_facets[__i] = 0;
00119     for (size_t __i = 0; __i < _M_facets_size; ++__i)
00120       {
00121         _M_facets[__i] = __imp._M_facets[__i];
00122         if (_M_facets[__i])
00123           _M_facets[__i]->_M_add_reference();
00124       }
00125     for (size_t __i = 0; 
00126          __i < _S_categories_size + _S_extra_categories_size; ++__i)
00127       {
00128         char* __new = new char[strlen(__imp._M_names[__i]) + 1];
00129         strcpy(__new, __imp._M_names[__i]);
00130         _M_names[__i] = __new;
00131       }
00132       }
00133     catch(...)
00134       {
00135     this->~_Impl();
00136     __throw_exception_again;    
00137       }
00138   }
00139 
00140   // Construct named _Impl.
00141   locale::_Impl::
00142   _Impl(const char* __s, size_t __refs) 
00143   : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) 
00144   {
00145     // Initialize the underlying locale model, which also checks
00146     // to see if the given name is valid.
00147     __c_locale __cloc;
00148     locale::facet::_S_create_c_locale(__cloc, __s);
00149 
00150     _M_facets = 0;
00151     for (size_t __i = 0; __i < _S_categories_size
00152                      + _S_extra_categories_size; ++__i)
00153       _M_names[__i] = 0;    
00154     try
00155       {
00156     // Space for facets and matching caches
00157     _M_facets = new facet*[2*_M_facets_size]; 
00158     for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
00159       _M_facets[__i] = 0;
00160 
00161     // Name all the categories.
00162     size_t __len = strlen(__s);
00163     if (!strchr(__s, ';'))
00164       {
00165         for (size_t __i = 0; 
00166          __i < _S_categories_size + _S_extra_categories_size; ++__i)
00167           {
00168         _M_names[__i] = new char[__len + 1];
00169         strcpy(_M_names[__i], __s);
00170           }
00171       }
00172     else
00173       {
00174         const char* __end = __s;
00175         for (size_t __i = 0; 
00176          __i < _S_categories_size + _S_extra_categories_size; ++__i)
00177           {
00178         const char* __beg = strchr(__end + 1, '=') + 1;
00179         __end = strchr(__beg, ';');
00180         if (!__end)
00181           __end = __s + __len;
00182         _M_names[__i] = new char[__end - __beg + 1];
00183         memcpy(_M_names[__i], __beg, __end - __beg);
00184         _M_names[__i][__end - __beg] = '\0';
00185           }
00186       }
00187 
00188     // Construct all standard facets and add them to _M_facets.  
00189     _M_init_facet(new std::ctype<char>(__cloc, 0, false));
00190     _M_init_facet(new codecvt<char, char, mbstate_t>);
00191     _M_init_facet(new numpunct<char>(__cloc));
00192     _M_init_facet(new num_get<char>);
00193     _M_init_facet(new num_put<char>);
00194     _M_init_facet(new std::collate<char>(__cloc));
00195     _M_init_facet(new moneypunct<char, false>(__cloc, __s));
00196     _M_init_facet(new moneypunct<char, true>(__cloc, __s));
00197     _M_init_facet(new money_get<char>);
00198     _M_init_facet(new money_put<char>);
00199     _M_init_facet(new __timepunct<char>(__cloc, __s));
00200     _M_init_facet(new time_get<char>);
00201     _M_init_facet(new time_put<char>);
00202     _M_init_facet(new std::messages<char>(__cloc, __s));
00203     
00204 #ifdef  _GLIBCPP_USE_WCHAR_T
00205     _M_init_facet(new std::ctype<wchar_t>(__cloc));
00206     _M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
00207     _M_init_facet(new numpunct<wchar_t>(__cloc));
00208     _M_init_facet(new num_get<wchar_t>);
00209     _M_init_facet(new num_put<wchar_t>);
00210     _M_init_facet(new std::collate<wchar_t>(__cloc));
00211     _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s));
00212     _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s));
00213     _M_init_facet(new money_get<wchar_t>);
00214     _M_init_facet(new money_put<wchar_t>);
00215     _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
00216     _M_init_facet(new time_get<wchar_t>);
00217     _M_init_facet(new time_put<wchar_t>);
00218     _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
00219 #endif    
00220     locale::facet::_S_destroy_c_locale(__cloc);
00221       }
00222     catch(...)
00223       {
00224     locale::facet::_S_destroy_c_locale(__cloc);
00225     this->~_Impl();
00226     __throw_exception_again;
00227       }    
00228   }
00229 
00230   // Construct "C" _Impl.
00231   locale::_Impl::
00232   _Impl(facet**, size_t __refs, bool) 
00233   : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
00234   {
00235     // Initialize the underlying locale model.
00236     locale::facet::_S_c_name[0] = 'C';
00237     locale::facet::_S_c_name[1] = '\0';
00238     locale::facet::_S_create_c_locale(locale::facet::_S_c_locale, 
00239                       locale::facet::_S_c_name);
00240 
00241     // Space for facets and matching caches
00242     _M_facets = new(&facet_cache_vec) facet*[2*_M_facets_size];
00243     for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
00244       _M_facets[__i] = 0;
00245 
00246     // Name all the categories.
00247     for (size_t __i = 0; 
00248      __i < _S_categories_size + _S_extra_categories_size; ++__i)
00249       {
00250     _M_names[__i]  = new (&facet_name[__i]) char[2];
00251     strcpy(_M_names[__i], locale::facet::_S_c_name);
00252       }
00253 
00254     // This is needed as presently the C++ version of "C" locales
00255     // != data in the underlying locale model for __timepunct,
00256     // numpunct, and moneypunct. Also, the "C" locales must be
00257     // constructed in a way such that they are pre-allocated.
00258     // NB: Set locale::facets(ref) count to one so that each individual
00259     // facet is not destroyed when the locale (and thus locale::_Impl) is
00260     // destroyed.
00261     _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
00262     _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
00263     _M_init_facet(new (&numpunct_c) numpunct<char>(1));
00264     _M_init_facet(new (&num_get_c) num_get<char>(1));
00265     _M_init_facet(new (&num_put_c) num_put<char>(1));
00266     _M_init_facet(new (&collate_c) std::collate<char>(1));
00267     _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1));
00268     _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1));
00269     _M_init_facet(new (&money_get_c) money_get<char>(1));
00270     _M_init_facet(new (&money_put_c) money_put<char>(1));
00271     _M_init_facet(new (&timepunct_c) __timepunct<char>(1));
00272     _M_init_facet(new (&time_get_c) time_get<char>(1));
00273     _M_init_facet(new (&time_put_c) time_put<char>(1));
00274     _M_init_facet(new (&messages_c) std::messages<char>(1));    
00275 #ifdef  _GLIBCPP_USE_WCHAR_T
00276     _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
00277     _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
00278     _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
00279     _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
00280     _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
00281     _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
00282     _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1));
00283     _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1));
00284     _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
00285     _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
00286     _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1));
00287     _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
00288     _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
00289     _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
00290 #endif 
00291 
00292     // Initialize the static locale caches for C locale.
00293 
00294     locale ltmp(this);      // Doesn't bump refcount
00295     _M_add_reference();     // Bump so destructor doesn't trash us
00296 
00297     // These need to be built in static allocated memory.  There must
00298     // be a better way to do this!
00299     __locale_cache<numpunct<char> >* __lc =
00300       new (&locale_cache_np_c) __locale_cache<numpunct<char> >(ltmp, true);
00301     _M_facets[numpunct<char>::id._M_id() + _M_facets_size] =
00302       reinterpret_cast<locale::facet*>(__lc);
00303       
00304 #ifdef  _GLIBCPP_USE_WCHAR_T
00305     __locale_cache<numpunct<wchar_t> >* __wlc =
00306       new (&locale_cache_np_w) __locale_cache<numpunct<wchar_t> >(ltmp, true);
00307     _M_facets[numpunct<wchar_t>::id._M_id() + _M_facets_size] =
00308       reinterpret_cast<locale::facet*>(__wlc);
00309 #endif    
00310   }
00311   
00312   void
00313   locale::_Impl::
00314   _M_replace_categories(const _Impl* __imp, category __cat)
00315   {
00316     category __mask;
00317     for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
00318       {
00319     __mask = 1 << __ix;
00320     if (__mask & __cat)
00321       {
00322         // Need to replace entry in _M_facets with other locale's info.
00323         _M_replace_category(__imp, _S_facet_categories[__ix]);
00324         // If both have names, go ahead and mangle.
00325         if (strcmp(_M_names[__ix], "*") != 0 
00326         && strcmp(__imp->_M_names[__ix], "*") != 0)
00327           {
00328         char* __new = new char[strlen(__imp->_M_names[__ix]) + 1];
00329         strcpy(__new, __imp->_M_names[__ix]);
00330         delete [] _M_names[__ix];
00331         _M_names[__ix] = __new;
00332           }
00333       }
00334       }
00335   }
00336 
00337   void
00338   locale::_Impl::
00339   _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
00340   {
00341     for (; *__idpp; ++__idpp)
00342       _M_replace_facet(__imp, *__idpp);
00343   }
00344   
00345   void
00346   locale::_Impl::
00347   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
00348   {
00349     size_t __index = __idp->_M_id();
00350     if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index])
00351       __throw_runtime_error("no locale facet");
00352     _M_install_facet(__idp, __imp->_M_facets[__index]); 
00353   }
00354 
00355   void
00356   locale::_Impl::
00357   _M_install_facet(const locale::id* __idp, facet* __fp)
00358   {
00359     if (__fp)
00360       {
00361     size_t __index = __idp->_M_id();
00362 
00363     // Check size of facet vector to ensure adequate room.
00364     if (__index > _M_facets_size - 1)
00365       {
00366         facet** __old = _M_facets;
00367         facet** __new;
00368         const size_t __new_size = __index + 4;
00369         __new = new facet*[2 * __new_size]; 
00370         for (size_t __i = 0; __i < _M_facets_size; ++__i)
00371           __new[__i] = _M_facets[__i];
00372         for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
00373           __new[__i2] = 0;
00374         // Also copy caches and clear extra space
00375         for (size_t __i = 0; __i < _M_facets_size; ++__i)
00376           __new[__i + __new_size] = _M_facets[__i + _M_facets_size];
00377         for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
00378           __new[__i2 + __new_size] = 0;
00379 
00380         _M_facets_size = __new_size;
00381         _M_facets = __new;
00382         delete [] __old;
00383       }
00384 
00385     __fp->_M_add_reference();
00386     facet*& __fpr = _M_facets[__index];
00387     if (__fpr)
00388       {
00389         // Replacing an existing facet. Order matters.
00390         __fpr->_M_remove_reference();
00391         __fpr = __fp;
00392       }
00393     else
00394       {
00395         // Installing a newly created facet into an empty
00396         // _M_facets container, say a newly-constructed,
00397         // swanky-fresh _Impl.
00398         _M_facets[__index] = __fp;
00399       }
00400       }
00401   }
00402 } // namespace std

Generated on Sat Mar 19 18:32:18 2005 for libstdc++-v3 Source by  doxygen 1.4.1