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 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

Generated on Wed Sep 29 13:54:49 2004 for libstdc++-v3 Source by doxygen 1.3.7