# 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 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     size_t __len = strlen(__s);
    00145     if (!strchr(__s, ';'))
    00146       {
    00147     for (size_t __i = 0;
    00148          __i < _S_categories_size + _S_extra_categories_size; ++__i)
    00149       {
    00150         _M_names[__i] = new char[__len + 1];
    00151         strcpy(_M_names[__i], __s);
    00152       }
    00153       }
    00154     else
    00155       {
    00156     const char* __beg = __s;
    00157     for (size_t __i = 0;
    00158          __i < _S_categories_size + _S_extra_categories_size; ++__i)
    00159       {
    00160         __beg = strchr(__beg, '=') + 1;
    00161         const char* __end = strchr(__beg, ';');
    00162         if (!__end)
    00163           __end = __s + __len;
    00164         char* __new = new char[__end - __beg + 1];
    00165         memcpy(__new, __beg, __end - __beg);
    00166         __new[__end - __beg] = '\0';
    00167         _M_names[__i] = __new;
    00168       }
    00169       }
    00170
    00171     // Construct all standard facets and add them to _M_facets.
    00172     _M_init_facet(new std::ctype<char>(__cloc, 0, false));
    00173     _M_init_facet(new codecvt<char, char, mbstate_t>);
    00174     _M_init_facet(new numpunct<char>(__cloc));
    00175     _M_init_facet(new num_get<char>);
    00176     _M_init_facet(new num_put<char>);
    00177     _M_init_facet(new std::collate<char>(__cloc));
    00178     _M_init_facet(new moneypunct<char, false>(__cloc, __s));
    00179     _M_init_facet(new moneypunct<char, true>(__cloc, __s));
    00180     _M_init_facet(new money_get<char>);
    00181     _M_init_facet(new money_put<char>);
    00182     _M_init_facet(new __timepunct<char>(__cloc, __s));
    00183     _M_init_facet(new time_get<char>);
    00184     _M_init_facet(new time_put<char>);
    00185     _M_init_facet(new std::messages<char>(__cloc, __s));
    00186
    00187 #ifdef  _GLIBCPP_USE_WCHAR_T
    00188     _M_init_facet(new std::ctype<wchar_t>(__cloc));
    00189     _M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
    00190     _M_init_facet(new numpunct<wchar_t>(__cloc));
    00191     _M_init_facet(new num_get<wchar_t>);
    00192     _M_init_facet(new num_put<wchar_t>);
    00193     _M_init_facet(new std::collate<wchar_t>(__cloc));
    00194     _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s));
    00195     _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s));
    00196     _M_init_facet(new money_get<wchar_t>);
    00197     _M_init_facet(new money_put<wchar_t>);
    00198     _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
    00199     _M_init_facet(new time_get<wchar_t>);
    00200     _M_init_facet(new time_put<wchar_t>);
    00201     _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
    00202 #endif
    00203     locale::facet::_S_destroy_c_locale(__cloc);
    00204   }
    00205
    00206   // Construct "C" _Impl.
    00207   locale::_Impl::
    00208   _Impl(facet**, size_t __refs, bool)
    00209   : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
    00210   {
    00211     // Initialize the underlying locale model.
    00212     locale::facet::_S_c_name[0] = 'C';
    00213     locale::facet::_S_c_name[1] = '\0';
    00214     locale::facet::_S_create_c_locale(locale::facet::_S_c_locale,
    00215                       locale::facet::_S_c_name);
    00216
    00217     _M_facets = new(&facet_vec) facet*[_M_facets_size];
    00218     for (size_t __i = 0; __i < _M_facets_size; ++__i)
    00219       _M_facets[__i] = 0;
    00220
    00221     // Name all the categories.
    00222     for (size_t __i = 0;
    00223      __i < _S_categories_size + _S_extra_categories_size; ++__i)
    00224       {
    00225     _M_names[__i]  = new (&facet_name[__i]) char[2];
    00226     strcpy(_M_names[__i], locale::facet::_S_c_name);
    00227       }
    00228
    00229     // This is needed as presently the C++ version of "C" locales
    00230     // != data in the underlying locale model for __timepunct,
    00231     // numpunct, and moneypunct. Also, the "C" locales must be
    00232     // constructed in a way such that they are pre-allocated.
    00233     // NB: Set locale::facets(ref) count to one so that each individual
    00234     // facet is not destroyed when the locale (and thus locale::_Impl) is
    00235     // destroyed.
    00236     _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
    00237     _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
    00238     _M_init_facet(new (&numpunct_c) numpunct<char>(1));
    00239     _M_init_facet(new (&num_get_c) num_get<char>(1));
    00240     _M_init_facet(new (&num_put_c) num_put<char>(1));
    00241     _M_init_facet(new (&collate_c) std::collate<char>(1));
    00242     _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1));
    00243     _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1));
    00244     _M_init_facet(new (&money_get_c) money_get<char>(1));
    00245     _M_init_facet(new (&money_put_c) money_put<char>(1));
    00246     _M_init_facet(new (&timepunct_c) __timepunct<char>(1));
    00247     _M_init_facet(new (&time_get_c) time_get<char>(1));
    00248     _M_init_facet(new (&time_put_c) time_put<char>(1));
    00249     _M_init_facet(new (&messages_c) std::messages<char>(1));
    00250 #ifdef  _GLIBCPP_USE_WCHAR_T
    00251     _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
    00252     _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
    00253     _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
    00254     _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
    00255     _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
    00256     _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
    00257     _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1));
    00258     _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1));
    00259     _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
    00260     _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
    00261     _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1));
    00262     _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
    00263     _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
    00264     _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
    00265 #endif
    00266   }
    00267
    00268   void
    00269   locale::_Impl::
    00270   _M_replace_categories(const _Impl* __imp, category __cat)
    00271   {
    00272     category __mask;
    00273     for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
    00274       {
    00275     __mask = 1 << __ix;
    00276     if (__mask & __cat)
    00277       {
    00278         // Need to replace entry in _M_facets with other locale's info.
    00279         _M_replace_category(__imp, _S_facet_categories[__ix]);
    00280         // If both have names, go ahead and mangle.
    00281         if (strcmp(_M_names[__ix], "*") != 0
    00282         && strcmp(__imp->_M_names[__ix], "*") != 0)
    00283           {
    00284         delete [] _M_names[__ix];
    00285         char* __new = new char[strlen(__imp->_M_names[__ix]) + 1];
    00286         strcpy(__new, __imp->_M_names[__ix]);
    00287         _M_names[__ix] = __new;
    00288           }
    00289       }
    00290       }
    00291   }
    00292
    00293   void
    00294   locale::_Impl::
    00295   _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
    00296   {
    00297     for (; *__idpp; ++__idpp)
    00298       _M_replace_facet(__imp, *__idpp);
    00299   }
    00300
    00301   void
    00302   locale::_Impl::
    00303   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
    00304   {
    00305     size_t __index = __idp->_M_id();
    00306     if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index])
    00307       __throw_runtime_error("no locale facet");
    00308     _M_install_facet(__idp, __imp->_M_facets[__index]);
    00309   }
    00310
    00311   void
    00312   locale::_Impl::
    00313   _M_install_facet(const locale::id* __idp, facet* __fp)
    00314   {
    00315     if (__fp)
    00316       {
    00317     size_t __index = __idp->_M_id();
    00318
    00319     // Check size of facet vector to ensure adequate room.
    00320     if (__index > _M_facets_size - 1)
    00321       {
    00322         facet** __old = _M_facets;
    00323         facet** __new;
    00324         const size_t __new_size = __index + 4;
    00325         __new = new facet*[__new_size];
    00326         for (size_t __i = 0; __i < _M_facets_size; ++__i)
    00327           __new[__i] = _M_facets[__i];
    00328         for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
    00329           __new[__i2] = 0;
    00330
    00331         _M_facets_size = __new_size;
    00332         _M_facets = __new;
    00333         delete [] __old;
    00334       }
    00335
    00336     __fp->_M_add_reference();
    00337     facet*& __fpr = _M_facets[__index];
    00338     if (__fpr)
    00339       {
    00340         // Replacing an existing facet. Order matters.
    00341         __fpr->_M_remove_reference();
    00342         __fpr = __fp;
    00343       }
    00344     else
    00345       {
    00346         // Installing a newly created facet into an empty
    00347         // _M_facets container, say a newly-constructed,
    00348         // swanky-fresh _Impl.
    00349         _M_facets[__index] = __fp;
    00350       }
    00351       }
    00352   }
    00353 } // namespace std