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* __beg = __s; 00175 for (size_t __i = 0; 00176 __i < _S_categories_size + _S_extra_categories_size; ++__i) 00177 { 00178 __beg = strchr(__beg, '=') + 1; 00179 const char* __end = strchr(__beg, ';'); 00180 if (!__end) 00181 __end = __s + __len; 00182 char* __new = new char[__end - __beg + 1]; 00183 memcpy(__new, __beg, __end - __beg); 00184 __new[__end - __beg] = '\0'; 00185 _M_names[__i] = __new; 00186 } 00187 } 00188 00189 // Construct all standard facets and add them to _M_facets. 00190 _M_init_facet(new std::ctype<char>(__cloc, 0, false)); 00191 _M_init_facet(new codecvt<char, char, mbstate_t>); 00192 _M_init_facet(new numpunct<char>(__cloc)); 00193 _M_init_facet(new num_get<char>); 00194 _M_init_facet(new num_put<char>); 00195 _M_init_facet(new std::collate<char>(__cloc)); 00196 _M_init_facet(new moneypunct<char, false>(__cloc, __s)); 00197 _M_init_facet(new moneypunct<char, true>(__cloc, __s)); 00198 _M_init_facet(new money_get<char>); 00199 _M_init_facet(new money_put<char>); 00200 _M_init_facet(new __timepunct<char>(__cloc, __s)); 00201 _M_init_facet(new time_get<char>); 00202 _M_init_facet(new time_put<char>); 00203 _M_init_facet(new std::messages<char>(__cloc, __s)); 00204 00205 #ifdef _GLIBCPP_USE_WCHAR_T 00206 _M_init_facet(new std::ctype<wchar_t>(__cloc)); 00207 _M_init_facet(new codecvt<wchar_t, char, mbstate_t>); 00208 _M_init_facet(new numpunct<wchar_t>(__cloc)); 00209 _M_init_facet(new num_get<wchar_t>); 00210 _M_init_facet(new num_put<wchar_t>); 00211 _M_init_facet(new std::collate<wchar_t>(__cloc)); 00212 _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s)); 00213 _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s)); 00214 _M_init_facet(new money_get<wchar_t>); 00215 _M_init_facet(new money_put<wchar_t>); 00216 _M_init_facet(new __timepunct<wchar_t>(__cloc, __s)); 00217 _M_init_facet(new time_get<wchar_t>); 00218 _M_init_facet(new time_put<wchar_t>); 00219 _M_init_facet(new std::messages<wchar_t>(__cloc, __s)); 00220 #endif 00221 locale::facet::_S_destroy_c_locale(__cloc); 00222 } 00223 catch(...) 00224 { 00225 locale::facet::_S_destroy_c_locale(__cloc); 00226 this->~_Impl(); 00227 __throw_exception_again; 00228 } 00229 } 00230 00231 // Construct "C" _Impl. 00232 locale::_Impl:: 00233 _Impl(facet**, size_t __refs, bool) 00234 : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) 00235 { 00236 // Initialize the underlying locale model. 00237 locale::facet::_S_c_name[0] = 'C'; 00238 locale::facet::_S_c_name[1] = '\0'; 00239 locale::facet::_S_create_c_locale(locale::facet::_S_c_locale, 00240 locale::facet::_S_c_name); 00241 00242 // Space for facets and matching caches 00243 _M_facets = new(&facet_cache_vec) facet*[2*_M_facets_size]; 00244 for (size_t __i = 0; __i < 2*_M_facets_size; ++__i) 00245 _M_facets[__i] = 0; 00246 00247 // Name all the categories. 00248 for (size_t __i = 0; 00249 __i < _S_categories_size + _S_extra_categories_size; ++__i) 00250 { 00251 _M_names[__i] = new (&facet_name[__i]) char[2]; 00252 strcpy(_M_names[__i], locale::facet::_S_c_name); 00253 } 00254 00255 // This is needed as presently the C++ version of "C" locales 00256 // != data in the underlying locale model for __timepunct, 00257 // numpunct, and moneypunct. Also, the "C" locales must be 00258 // constructed in a way such that they are pre-allocated. 00259 // NB: Set locale::facets(ref) count to one so that each individual 00260 // facet is not destroyed when the locale (and thus locale::_Impl) is 00261 // destroyed. 00262 _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1)); 00263 _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1)); 00264 _M_init_facet(new (&numpunct_c) numpunct<char>(1)); 00265 _M_init_facet(new (&num_get_c) num_get<char>(1)); 00266 _M_init_facet(new (&num_put_c) num_put<char>(1)); 00267 _M_init_facet(new (&collate_c) std::collate<char>(1)); 00268 _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1)); 00269 _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1)); 00270 _M_init_facet(new (&money_get_c) money_get<char>(1)); 00271 _M_init_facet(new (&money_put_c) money_put<char>(1)); 00272 _M_init_facet(new (&timepunct_c) __timepunct<char>(1)); 00273 _M_init_facet(new (&time_get_c) time_get<char>(1)); 00274 _M_init_facet(new (&time_put_c) time_put<char>(1)); 00275 _M_init_facet(new (&messages_c) std::messages<char>(1)); 00276 #ifdef _GLIBCPP_USE_WCHAR_T 00277 _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1)); 00278 _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1)); 00279 _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1)); 00280 _M_init_facet(new (&num_get_w) num_get<wchar_t>(1)); 00281 _M_init_facet(new (&num_put_w) num_put<wchar_t>(1)); 00282 _M_init_facet(new (&collate_w) std::collate<wchar_t>(1)); 00283 _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1)); 00284 _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1)); 00285 _M_init_facet(new (&money_get_w) money_get<wchar_t>(1)); 00286 _M_init_facet(new (&money_put_w) money_put<wchar_t>(1)); 00287 _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1)); 00288 _M_init_facet(new (&time_get_w) time_get<wchar_t>(1)); 00289 _M_init_facet(new (&time_put_w) time_put<wchar_t>(1)); 00290 _M_init_facet(new (&messages_w) std::messages<wchar_t>(1)); 00291 #endif 00292 00293 // Initialize the static locale caches for C locale. 00294 00295 locale ltmp(this); // Doesn't bump refcount 00296 _M_add_reference(); // Bump so destructor doesn't trash us 00297 00298 // These need to be built in static allocated memory. There must 00299 // be a better way to do this! 00300 __locale_cache<numpunct<char> >* __lc = 00301 new (&locale_cache_np_c) __locale_cache<numpunct<char> >(ltmp, true); 00302 _M_facets[numpunct<char>::id._M_id() + _M_facets_size] = 00303 reinterpret_cast<locale::facet*>(__lc); 00304 00305 #ifdef _GLIBCPP_USE_WCHAR_T 00306 __locale_cache<numpunct<wchar_t> >* __wlc = 00307 new (&locale_cache_np_w) __locale_cache<numpunct<wchar_t> >(ltmp, true); 00308 _M_facets[numpunct<wchar_t>::id._M_id() + _M_facets_size] = 00309 reinterpret_cast<locale::facet*>(__wlc); 00310 #endif 00311 } 00312 00313 void 00314 locale::_Impl:: 00315 _M_replace_categories(const _Impl* __imp, category __cat) 00316 { 00317 category __mask; 00318 for (size_t __ix = 0; __ix < _S_categories_size; ++__ix) 00319 { 00320 __mask = 1 << __ix; 00321 if (__mask & __cat) 00322 { 00323 // Need to replace entry in _M_facets with other locale's info. 00324 _M_replace_category(__imp, _S_facet_categories[__ix]); 00325 // If both have names, go ahead and mangle. 00326 if (strcmp(_M_names[__ix], "*") != 0 00327 && strcmp(__imp->_M_names[__ix], "*") != 0) 00328 { 00329 char* __new = new char[strlen(__imp->_M_names[__ix]) + 1]; 00330 strcpy(__new, __imp->_M_names[__ix]); 00331 delete [] _M_names[__ix]; 00332 _M_names[__ix] = __new; 00333 } 00334 } 00335 } 00336 } 00337 00338 void 00339 locale::_Impl:: 00340 _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp) 00341 { 00342 for (; *__idpp; ++__idpp) 00343 _M_replace_facet(__imp, *__idpp); 00344 } 00345 00346 void 00347 locale::_Impl:: 00348 _M_replace_facet(const _Impl* __imp, const locale::id* __idp) 00349 { 00350 size_t __index = __idp->_M_id(); 00351 if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index]) 00352 __throw_runtime_error("no locale facet"); 00353 _M_install_facet(__idp, __imp->_M_facets[__index]); 00354 } 00355 00356 void 00357 locale::_Impl:: 00358 _M_install_facet(const locale::id* __idp, facet* __fp) 00359 { 00360 if (__fp) 00361 { 00362 size_t __index = __idp->_M_id(); 00363 00364 // Check size of facet vector to ensure adequate room. 00365 if (__index > _M_facets_size - 1) 00366 { 00367 facet** __old = _M_facets; 00368 facet** __new; 00369 const size_t __new_size = __index + 4; 00370 __new = new facet*[2 * __new_size]; 00371 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00372 __new[__i] = _M_facets[__i]; 00373 for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2) 00374 __new[__i2] = 0; 00375 // Also copy caches and clear extra space 00376 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00377 __new[__i + __new_size] = _M_facets[__i + _M_facets_size]; 00378 for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2) 00379 __new[__i2 + __new_size] = 0; 00380 00381 _M_facets_size = __new_size; 00382 _M_facets = __new; 00383 delete [] __old; 00384 } 00385 00386 __fp->_M_add_reference(); 00387 facet*& __fpr = _M_facets[__index]; 00388 if (__fpr) 00389 { 00390 // Replacing an existing facet. Order matters. 00391 __fpr->_M_remove_reference(); 00392 __fpr = __fp; 00393 } 00394 else 00395 { 00396 // Installing a newly created facet into an empty 00397 // _M_facets container, say a newly-constructed, 00398 // swanky-fresh _Impl. 00399 _M_facets[__index] = __fp; 00400 } 00401 } 00402 } 00403 } // namespace std

Generated on Wed Aug 4 21:43:13 2004 for libstdc++-v3 Source by doxygen 1.3.8