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 std
00034 {
00035   // Defined in globals.cc.
00036   extern std::ctype<char>           ctype_c;
00037   extern std::collate<char>             collate_c;
00038   extern numpunct<char>             numpunct_c;
00039   extern num_get<char>              num_get_c;
00040   extern num_put<char>              num_put_c;
00041   extern codecvt<char, char, mbstate_t>     codecvt_c;
00042   extern moneypunct<char, false>        moneypunct_fc;
00043   extern moneypunct<char, true>         moneypunct_tc;
00044   extern money_get<char>            money_get_c;
00045   extern money_put<char>            money_put_c;
00046   extern __timepunct<char>          timepunct_c;
00047   extern time_get<char>             time_get_c;
00048   extern time_put<char>             time_put_c;
00049   extern std::messages<char>            messages_c;
00050 #ifdef  _GLIBCPP_USE_WCHAR_T
00051   extern std::ctype<wchar_t>            ctype_w;
00052   extern std::collate<wchar_t>          collate_w;
00053   extern numpunct<wchar_t>          numpunct_w;
00054   extern num_get<wchar_t>           num_get_w;
00055   extern num_put<wchar_t>           num_put_w;
00056   extern codecvt<wchar_t, char, mbstate_t>  codecvt_w;
00057   extern moneypunct<wchar_t, false>         moneypunct_fw;
00058   extern moneypunct<wchar_t, true>      moneypunct_tw;
00059   extern money_get<wchar_t>             money_get_w;
00060   extern money_put<wchar_t>             money_put_w;
00061   extern __timepunct<wchar_t>           timepunct_w;
00062   extern time_get<wchar_t>          time_get_w;
00063   extern time_put<wchar_t>          time_put_w;
00064   extern std::messages<wchar_t>         messages_w;
00065 #endif
00066 
00067   locale::_Impl::
00068   ~_Impl() throw()
00069   {
00070     for (size_t __i = 0; __i < _M_facets_size; ++__i)
00071       if (_M_facets[__i])
00072     _M_facets[__i]->_M_remove_reference();
00073     delete [] _M_facets;
00074   }
00075 
00076   // Clone existing _Impl object.
00077   locale::_Impl::
00078   _Impl(const _Impl& __imp, size_t __refs)
00079   : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX
00080   {
00081     try
00082       { 
00083     _M_facets = new facet*[_M_facets_size]; 
00084     for (size_t __i = 0; __i < _M_facets_size; ++__i)
00085       _M_facets[__i] = 0;
00086       }
00087     catch(...) 
00088       {
00089     delete [] _M_facets;
00090     __throw_exception_again;
00091       }
00092     for (size_t __i = 0; __i < _M_facets_size; ++__i)
00093       {
00094     _M_facets[__i] = __imp._M_facets[__i];
00095     if (_M_facets[__i])
00096       _M_facets[__i]->_M_add_reference();
00097       }
00098     for (size_t __i = 0; __i < _S_num_categories; ++__i)
00099       _M_names[__i] = __imp._M_names[__i];
00100   }
00101 
00102   // Construct named _Impl.
00103   locale::_Impl::
00104   _Impl(const char* __s, size_t __refs) 
00105   : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) // XXX
00106   {
00107     // Initialize the underlying locale model, which also checks
00108     // to see if the given name is valid.
00109     __c_locale __cloc;
00110     locale::facet::_S_create_c_locale(__cloc, __s);
00111 
00112     try
00113       { 
00114     _M_facets = new facet*[_M_facets_size]; 
00115     for (size_t __i = 0; __i < _M_facets_size; ++__i)
00116       _M_facets[__i] = 0;
00117       }
00118     catch(...) 
00119       {
00120     delete [] _M_facets;
00121     __throw_exception_again;
00122       }
00123 
00124     // Name all the categories.
00125     for (size_t i = 0; i < _S_num_categories; ++i)
00126       _M_names[i] = __s;
00127 
00128     // Construct all standard facets and add them to _M_facets.
00129     _M_init_facet(new std::ctype<char>(__cloc));
00130     _M_init_facet(new codecvt<char, char, mbstate_t>);
00131     _M_init_facet(new numpunct<char>(__cloc));
00132     _M_init_facet(new num_get<char>);
00133     _M_init_facet(new num_put<char>);
00134     _M_init_facet(new std::collate<char>(__cloc));
00135     _M_init_facet(new moneypunct<char, false>(__cloc));
00136     _M_init_facet(new moneypunct<char, true>(__cloc));
00137     _M_init_facet(new money_get<char>);
00138     _M_init_facet(new money_put<char>);
00139     _M_init_facet(new __timepunct<char>(__cloc, __s));
00140     _M_init_facet(new time_get<char>);
00141     _M_init_facet(new time_put<char>);
00142     _M_init_facet(new std::messages<char>(__cloc, __s));
00143     
00144 #ifdef  _GLIBCPP_USE_WCHAR_T
00145     _M_init_facet(new std::ctype<wchar_t>(__cloc));
00146     _M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
00147     _M_init_facet(new numpunct<wchar_t>(__cloc));
00148     _M_init_facet(new num_get<wchar_t>);
00149     _M_init_facet(new num_put<wchar_t>);
00150     _M_init_facet(new std::collate<wchar_t>(__cloc));
00151     _M_init_facet(new moneypunct<wchar_t, false>(__cloc));
00152     _M_init_facet(new moneypunct<wchar_t, true>(__cloc));
00153     _M_init_facet(new money_get<wchar_t>);
00154     _M_init_facet(new money_put<wchar_t>);
00155     _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
00156     _M_init_facet(new time_get<wchar_t>);
00157     _M_init_facet(new time_put<wchar_t>);
00158     _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
00159 #endif    
00160     locale::facet::_S_destroy_c_locale(__cloc);
00161   }
00162 
00163   // Construct "C" _Impl.
00164   locale::_Impl::
00165   _Impl(facet** __f, size_t __refs, bool) 
00166   : _M_references(__refs), _M_facets(__f), _M_facets_size(_GLIBCPP_NUM_FACETS)
00167   {
00168     // Name all the categories.
00169     for (size_t i = 0; i < _S_num_categories; ++i)
00170       _M_names[i] = "C";
00171 
00172     // This is needed as presently the C++ version of "C" locales
00173     // != data in the underlying locale model for __timepunct,
00174     // numpunct, and moneypunct. Also, the "C" locales must be
00175     // constructed in a way such that they are pre-allocated.
00176     _M_init_facet(new (&ctype_c) std::ctype<char>);
00177     _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>);
00178     _M_init_facet(new (&numpunct_c) numpunct<char>);
00179     _M_init_facet(new (&num_get_c) num_get<char>);
00180     _M_init_facet(new (&num_put_c) num_put<char>);
00181     _M_init_facet(new (&collate_c) std::collate<char>);
00182     _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>);
00183     _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>);
00184     _M_init_facet(new (&money_get_c) money_get<char>);
00185     _M_init_facet(new (&money_put_c) money_put<char>);
00186     _M_init_facet(new (&timepunct_c) __timepunct<char>);
00187     _M_init_facet(new (&time_get_c) time_get<char>);
00188     _M_init_facet(new (&time_put_c) time_put<char>);
00189     _M_init_facet(new (&messages_c) std::messages<char>);   
00190 #ifdef  _GLIBCPP_USE_WCHAR_T
00191     _M_init_facet(new (&ctype_w) std::ctype<wchar_t>);
00192     _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>);
00193     _M_init_facet(new (&numpunct_w) numpunct<wchar_t>);
00194     _M_init_facet(new (&num_get_w) num_get<wchar_t>);
00195     _M_init_facet(new (&num_put_w) num_put<wchar_t>);
00196     _M_init_facet(new (&collate_w) std::collate<wchar_t>);
00197     _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>);
00198     _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>);
00199     _M_init_facet(new (&money_get_w) money_get<wchar_t>);
00200     _M_init_facet(new (&money_put_w) money_put<wchar_t>);
00201     _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>);
00202     _M_init_facet(new (&time_get_w) time_get<wchar_t>);
00203     _M_init_facet(new (&time_put_w) time_put<wchar_t>);
00204     _M_init_facet(new (&messages_w) std::messages<wchar_t>);
00205 #endif    
00206   }
00207   
00208   void
00209   locale::_Impl::
00210   _M_replace_categories(const _Impl* __imp, category __cat)
00211   {
00212     category __mask;
00213     for (unsigned int __ix = 0; __ix < _S_num_categories; ++__ix)
00214       {
00215     __mask = 1 << __ix;
00216     if (__mask & __cat)
00217       {
00218         // Need to replace entry in _M_facets with other locale's info.
00219         _M_replace_category(__imp, _S_facet_categories[__ix]);
00220         // If both have names, go ahead and mangle.
00221         if (strcmp(_M_names[__ix], "*") != 0 
00222         && strcmp(__imp->_M_names[__ix], "*") != 0)
00223           _M_names[__ix] = __imp->_M_names[__ix];
00224       }
00225       }
00226   }
00227 
00228   void
00229   locale::_Impl::
00230   _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
00231   {
00232     for (; *__idpp; ++__idpp)
00233       _M_replace_facet(__imp, *__idpp);
00234   }
00235   
00236   void
00237   locale::_Impl::
00238   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
00239   {
00240     size_t __index = __idp->_M_id();
00241     if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index])
00242       __throw_runtime_error("no locale facet");
00243     _M_install_facet(__idp, __imp->_M_facets[__index]); 
00244   }
00245 
00246   void
00247   locale::_Impl::
00248   _M_install_facet(const locale::id* __idp, facet* __fp)
00249   {
00250     if (__fp)
00251       {
00252     size_t __index = __idp->_M_id();
00253     if (__index > _M_facets_size - 1)
00254       {
00255         facet** __old = _M_facets;
00256         facet** __new;
00257         const size_t __new_size = __index + 4;
00258         try
00259           { __new = new facet*[__new_size]; }
00260         catch(...) 
00261           {
00262         delete [] __new;
00263         __throw_exception_again;
00264           }
00265         for (size_t __i = 0; __i < _M_facets_size; ++__i)
00266           __new[__i] = _M_facets[__i];
00267         for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
00268           __new[__i2] = 0;
00269 
00270         _M_facets_size = __new_size;
00271         _M_facets = __new;
00272         delete [] __old;
00273       }
00274 
00275     facet*& __fpr = _M_facets[__index];
00276     if (__fpr)
00277       {
00278         // Replacing an existing facet. Order matters.
00279         __fp->_M_add_reference();
00280         __fpr->_M_remove_reference();
00281         __fpr = __fp;
00282       }
00283     else
00284       {
00285         // Installing a newly created facet into an empty
00286         // _M_facets container, say a newly-constructed,
00287         // swanky-fresh _Impl.
00288         _M_facets[__index] = __fp;
00289       }
00290       }
00291   }
00292 } // namespace std

Generated on Wed May 1 19:19:33 2002 for libstdc++-v3 Source by doxygen1.2.15