localename.cc

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

Generated on Thu Nov 21 03:12:48 2002 for libstdc++-v3 Source by doxygen1.2.18-20021030