locale.cc

00001 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 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 <cstdlib> // For getenv 00032 #include <cctype> 00033 #include <cwctype> // For towupper, etc. 00034 #include <locale> 00035 #include <bits/atomicity.h> 00036 00037 namespace std 00038 { 00039 // Definitions for static const data members of locale. 00040 const locale::category locale::none; 00041 const locale::category locale::ctype; 00042 const locale::category locale::numeric; 00043 const locale::category locale::collate; 00044 const locale::category locale::time; 00045 const locale::category locale::monetary; 00046 const locale::category locale::messages; 00047 const locale::category locale::all; 00048 00049 // These are no longer exported. 00050 locale::_Impl* locale::_S_classic; 00051 locale::_Impl* locale::_S_global; 00052 const size_t locale::_S_categories_size; 00053 00054 #ifdef __GTHREADS 00055 __gthread_once_t locale::_S_once = __GTHREAD_ONCE_INIT; 00056 #endif 00057 00058 locale::locale(const locale& __other) throw() 00059 : _M_impl(__other._M_impl) 00060 { _M_impl->_M_add_reference(); } 00061 00062 // This is used to initialize global and classic locales, and 00063 // assumes that the _Impl objects are constructed correctly. 00064 // The lack of a reference increment is intentional. 00065 locale::locale(_Impl* __ip) throw() : _M_impl(__ip) 00066 { } 00067 00068 locale::~locale() throw() 00069 { _M_impl->_M_remove_reference(); } 00070 00071 bool 00072 locale::operator==(const locale& __rhs) const throw() 00073 { 00074 // Deal first with the common cases, fast to process: refcopies, 00075 // unnamed (i.e., !_M_names[0]), "simple" (!_M_names[1] => all the 00076 // categories same name, i.e., _M_names[0]). Otherwise fall back 00077 // to the general locale::name(). 00078 bool __ret; 00079 if (_M_impl == __rhs._M_impl) 00080 __ret = true; 00081 else if (!_M_impl->_M_names[0] || !__rhs._M_impl->_M_names[0] 00082 || std::strcmp(_M_impl->_M_names[0], 00083 __rhs._M_impl->_M_names[0]) != 0) 00084 __ret = false; 00085 else if (!_M_impl->_M_names[1] && !__rhs._M_impl->_M_names[1]) 00086 __ret = true; 00087 else 00088 __ret = this->name() == __rhs.name(); 00089 return __ret; 00090 } 00091 00092 const locale& 00093 locale::operator=(const locale& __other) throw() 00094 { 00095 __other._M_impl->_M_add_reference(); 00096 _M_impl->_M_remove_reference(); 00097 _M_impl = __other._M_impl; 00098 return *this; 00099 } 00100 00101 string 00102 locale::name() const 00103 { 00104 string __ret; 00105 if (!_M_impl->_M_names[0]) 00106 __ret = '*'; 00107 else if (_M_impl->_M_check_same_name()) 00108 __ret = _M_impl->_M_names[0]; 00109 else 00110 { 00111 __ret.reserve(128); 00112 __ret += _S_categories[0]; 00113 __ret += '='; 00114 __ret += _M_impl->_M_names[0]; 00115 for (size_t __i = 1; __i < _S_categories_size; ++__i) 00116 { 00117 __ret += ';'; 00118 __ret += _S_categories[__i]; 00119 __ret += '='; 00120 __ret += _M_impl->_M_names[__i]; 00121 } 00122 } 00123 return __ret; 00124 } 00125 00126 locale::category 00127 locale::_S_normalize_category(category __cat) 00128 { 00129 int __ret = 0; 00130 if (__cat == none || (__cat & all) && !(__cat & ~all)) 00131 __ret = __cat; 00132 else 00133 { 00134 // NB: May be a C-style "LC_ALL" category; convert. 00135 switch (__cat) 00136 { 00137 case LC_COLLATE: 00138 __ret = collate; 00139 break; 00140 case LC_CTYPE: 00141 __ret = ctype; 00142 break; 00143 case LC_MONETARY: 00144 __ret = monetary; 00145 break; 00146 case LC_NUMERIC: 00147 __ret = numeric; 00148 break; 00149 case LC_TIME: 00150 __ret = time; 00151 break; 00152 #ifdef _GLIBCXX_HAVE_LC_MESSAGES 00153 case LC_MESSAGES: 00154 __ret = messages; 00155 break; 00156 #endif 00157 case LC_ALL: 00158 __ret = all; 00159 break; 00160 default: 00161 __throw_runtime_error(__N("locale::_S_normalize_category " 00162 "category not found")); 00163 } 00164 } 00165 return __ret; 00166 } 00167 00168 // locale::facet 00169 __c_locale locale::facet::_S_c_locale; 00170 00171 const char locale::facet::_S_c_name[2] = "C"; 00172 00173 #ifdef __GTHREADS 00174 __gthread_once_t locale::facet::_S_once = __GTHREAD_ONCE_INIT; 00175 #endif 00176 00177 void 00178 locale::facet::_S_initialize_once() 00179 { 00180 // Initialize the underlying locale model. 00181 _S_create_c_locale(_S_c_locale, _S_c_name); 00182 } 00183 00184 __c_locale 00185 locale::facet::_S_get_c_locale() 00186 { 00187 #ifdef __GHTREADS 00188 if (__gthread_active_p()) 00189 __gthread_once(&_S_once, _S_initialize_once); 00190 else 00191 #endif 00192 { 00193 if (!_S_c_locale) 00194 _S_initialize_once(); 00195 } 00196 return _S_c_locale; 00197 } 00198 00199 const char* 00200 locale::facet::_S_get_c_name() 00201 { return _S_c_name; } 00202 00203 locale::facet:: 00204 ~facet() { } 00205 00206 // locale::_Impl 00207 locale::_Impl:: 00208 ~_Impl() throw() 00209 { 00210 if (_M_facets) 00211 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00212 if (_M_facets[__i]) 00213 _M_facets[__i]->_M_remove_reference(); 00214 delete [] _M_facets; 00215 00216 if (_M_caches) 00217 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00218 if (_M_caches[__i]) 00219 _M_caches[__i]->_M_remove_reference(); 00220 delete [] _M_caches; 00221 00222 if (_M_names) 00223 for (size_t __i = 0; __i < _S_categories_size; ++__i) 00224 delete [] _M_names[__i]; 00225 delete [] _M_names; 00226 } 00227 00228 // Clone existing _Impl object. 00229 locale::_Impl:: 00230 _Impl(const _Impl& __imp, size_t __refs) 00231 : _M_refcount(__refs), _M_facets(0), _M_facets_size(__imp._M_facets_size), 00232 _M_caches(0), _M_names(0) 00233 { 00234 try 00235 { 00236 _M_facets = new const facet*[_M_facets_size]; 00237 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00238 { 00239 _M_facets[__i] = __imp._M_facets[__i]; 00240 if (_M_facets[__i]) 00241 _M_facets[__i]->_M_add_reference(); 00242 } 00243 _M_caches = new const facet*[_M_facets_size]; 00244 for (size_t __j = 0; __j < _M_facets_size; ++__j) 00245 { 00246 _M_caches[__j] = __imp._M_caches[__j]; 00247 if (_M_caches[__j]) 00248 _M_caches[__j]->_M_add_reference(); 00249 } 00250 _M_names = new char*[_S_categories_size]; 00251 for (size_t __k = 0; __k < _S_categories_size; ++__k) 00252 _M_names[__k] = 0; 00253 00254 // Name the categories. 00255 for (size_t __l = 0; (__l < _S_categories_size 00256 && __imp._M_names[__l]); ++__l) 00257 { 00258 const size_t __len = std::strlen(__imp._M_names[__l]) + 1; 00259 _M_names[__l] = new char[__len]; 00260 std::memcpy(_M_names[__l], __imp._M_names[__l], __len); 00261 } 00262 } 00263 catch(...) 00264 { 00265 this->~_Impl(); 00266 __throw_exception_again; 00267 } 00268 } 00269 00270 void 00271 locale::_Impl:: 00272 _M_replace_category(const _Impl* __imp, 00273 const locale::id* const* __idpp) 00274 { 00275 for (; *__idpp; ++__idpp) 00276 _M_replace_facet(__imp, *__idpp); 00277 } 00278 00279 void 00280 locale::_Impl:: 00281 _M_replace_facet(const _Impl* __imp, const locale::id* __idp) 00282 { 00283 size_t __index = __idp->_M_id(); 00284 if ((__index > (__imp->_M_facets_size - 1)) 00285 || !__imp->_M_facets[__index]) 00286 __throw_runtime_error(__N("locale::_Impl::_M_replace_facet")); 00287 _M_install_facet(__idp, __imp->_M_facets[__index]); 00288 } 00289 00290 void 00291 locale::_Impl:: 00292 _M_install_facet(const locale::id* __idp, const facet* __fp) 00293 { 00294 if (__fp) 00295 { 00296 size_t __index = __idp->_M_id(); 00297 00298 // Check size of facet vector to ensure adequate room. 00299 if (__index > _M_facets_size - 1) 00300 { 00301 const size_t __new_size = __index + 4; 00302 00303 // New facet array. 00304 const facet** __oldf = _M_facets; 00305 const facet** __newf; 00306 __newf = new const facet*[__new_size]; 00307 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00308 __newf[__i] = _M_facets[__i]; 00309 for (size_t __l = _M_facets_size; __l < __new_size; ++__l) 00310 __newf[__l] = 0; 00311 00312 // New cache array. 00313 const facet** __oldc = _M_caches; 00314 const facet** __newc; 00315 try 00316 { 00317 __newc = new const facet*[__new_size]; 00318 } 00319 catch(...) 00320 { 00321 delete [] __newf; 00322 __throw_exception_again; 00323 } 00324 for (size_t __j = 0; __j < _M_facets_size; ++__j) 00325 __newc[__j] = _M_caches[__j]; 00326 for (size_t __k = _M_facets_size; __k < __new_size; ++__k) 00327 __newc[__k] = 0; 00328 00329 _M_facets_size = __new_size; 00330 _M_facets = __newf; 00331 _M_caches = __newc; 00332 delete [] __oldf; 00333 delete [] __oldc; 00334 } 00335 00336 __fp->_M_add_reference(); 00337 const 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 // Ideally, it would be nice to only remove the caches that 00353 // are now incorrect. However, some of the caches depend on 00354 // multiple facets, and we only know about one facet 00355 // here. It's no great loss: the first use of the new facet 00356 // will create a new, correctly cached facet anyway. 00357 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00358 { 00359 const facet* __cpr = _M_caches[__i]; 00360 if (__cpr) 00361 { 00362 __cpr->_M_remove_reference(); 00363 _M_caches[__i] = 0; 00364 } 00365 } 00366 } 00367 } 00368 00369 // locale::id 00370 // Definitions for static const data members of locale::id 00371 _Atomic_word locale::id::_S_refcount; // init'd to 0 by linker 00372 00373 size_t 00374 locale::id::_M_id() const 00375 { 00376 if (!_M_index) 00377 _M_index = 1 + __gnu_cxx::__exchange_and_add(&_S_refcount, 1); 00378 return _M_index - 1; 00379 } 00380 } // namespace std 00381 00382

Generated on Wed Jun 9 11:18:39 2004 for libstdc++-v3 Source by doxygen 1.3.7