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 bool __ret = false; 00075 if (_M_impl == __rhs._M_impl) 00076 __ret = true; 00077 else 00078 { 00079 const string __name = this->name(); 00080 if (__name != "*" && __name == __rhs.name()) 00081 __ret = true; 00082 } 00083 return __ret; 00084 } 00085 00086 const locale& 00087 locale::operator=(const locale& __other) throw() 00088 { 00089 __other._M_impl->_M_add_reference(); 00090 _M_impl->_M_remove_reference(); 00091 _M_impl = __other._M_impl; 00092 return *this; 00093 } 00094 00095 string 00096 locale::name() const 00097 { 00098 string __ret; 00099 if (_M_impl->_M_check_same_name()) 00100 __ret = _M_impl->_M_names[0]; 00101 else 00102 { 00103 __ret += _S_categories[0]; 00104 __ret += '='; 00105 __ret += _M_impl->_M_names[0]; 00106 for (size_t __i = 1; __i < _S_categories_size; ++__i) 00107 { 00108 __ret += ';'; 00109 __ret += _S_categories[__i]; 00110 __ret += '='; 00111 __ret += _M_impl->_M_names[__i]; 00112 } 00113 } 00114 return __ret; 00115 } 00116 00117 locale::category 00118 locale::_S_normalize_category(category __cat) 00119 { 00120 int __ret = 0; 00121 if (__cat == none || (__cat & all) && !(__cat & ~all)) 00122 __ret = __cat; 00123 else 00124 { 00125 // NB: May be a C-style "LC_ALL" category; convert. 00126 switch (__cat) 00127 { 00128 case LC_COLLATE: 00129 __ret = collate; 00130 break; 00131 case LC_CTYPE: 00132 __ret = ctype; 00133 break; 00134 case LC_MONETARY: 00135 __ret = monetary; 00136 break; 00137 case LC_NUMERIC: 00138 __ret = numeric; 00139 break; 00140 case LC_TIME: 00141 __ret = time; 00142 break; 00143 #ifdef _GLIBCXX_HAVE_LC_MESSAGES 00144 case LC_MESSAGES: 00145 __ret = messages; 00146 break; 00147 #endif 00148 case LC_ALL: 00149 __ret = all; 00150 break; 00151 default: 00152 __throw_runtime_error(__N("locale::_S_normalize_category " 00153 "category not found")); 00154 } 00155 } 00156 return __ret; 00157 } 00158 00159 // locale::facet 00160 __c_locale locale::facet::_S_c_locale; 00161 00162 const char locale::facet::_S_c_name[2] = "C"; 00163 00164 #ifdef __GTHREADS 00165 __gthread_once_t locale::facet::_S_once = __GTHREAD_ONCE_INIT; 00166 #endif 00167 00168 void 00169 locale::facet::_S_initialize_once() 00170 { 00171 // Initialize the underlying locale model. 00172 _S_create_c_locale(_S_c_locale, _S_c_name); 00173 } 00174 00175 __c_locale 00176 locale::facet::_S_get_c_locale() 00177 { 00178 #ifdef __GHTREADS 00179 if (__gthread_active_p()) 00180 __gthread_once(&_S_once, _S_initialize_once); 00181 else 00182 #endif 00183 { 00184 if (!_S_c_locale) 00185 _S_initialize_once(); 00186 } 00187 return _S_c_locale; 00188 } 00189 00190 const char* 00191 locale::facet::_S_get_c_name() 00192 { return _S_c_name; } 00193 00194 locale::facet:: 00195 ~facet() { } 00196 00197 // locale::_Impl 00198 locale::_Impl:: 00199 ~_Impl() throw() 00200 { 00201 if (_M_facets) 00202 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00203 if (_M_facets[__i]) 00204 _M_facets[__i]->_M_remove_reference(); 00205 delete [] _M_facets; 00206 00207 if (_M_caches) 00208 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00209 if (_M_caches[__i]) 00210 _M_caches[__i]->_M_remove_reference(); 00211 delete [] _M_caches; 00212 00213 if (_M_names) 00214 for (size_t __i = 0; __i < _S_categories_size; ++__i) 00215 delete [] _M_names[__i]; 00216 delete [] _M_names; 00217 } 00218 00219 // Clone existing _Impl object. 00220 locale::_Impl:: 00221 _Impl(const _Impl& __imp, size_t __refs) 00222 : _M_refcount(__refs), _M_facets(0), _M_facets_size(__imp._M_facets_size), 00223 _M_caches(0), _M_names(0) 00224 { 00225 try 00226 { 00227 _M_facets = new const facet*[_M_facets_size]; 00228 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00229 { 00230 _M_facets[__i] = __imp._M_facets[__i]; 00231 if (_M_facets[__i]) 00232 _M_facets[__i]->_M_add_reference(); 00233 } 00234 _M_caches = new const facet*[_M_facets_size]; 00235 for (size_t __j = 0; __j < _M_facets_size; ++__j) 00236 { 00237 _M_caches[__j] = __imp._M_caches[__j]; 00238 if (_M_caches[__j]) 00239 _M_caches[__j]->_M_add_reference(); 00240 } 00241 _M_names = new char*[_S_categories_size]; 00242 for (size_t __k = 0; __k < _S_categories_size; ++__k) 00243 _M_names[__k] = 0; 00244 00245 // Name all the categories. 00246 for (size_t __l = 0; __l < _S_categories_size; ++__l) 00247 { 00248 char* __new = new char[std::strlen(__imp._M_names[__l]) + 1]; 00249 std::strcpy(__new, __imp._M_names[__l]); 00250 _M_names[__l] = __new; 00251 } 00252 } 00253 catch(...) 00254 { 00255 this->~_Impl(); 00256 __throw_exception_again; 00257 } 00258 } 00259 00260 void 00261 locale::_Impl:: 00262 _M_replace_category(const _Impl* __imp, 00263 const locale::id* const* __idpp) 00264 { 00265 for (; *__idpp; ++__idpp) 00266 _M_replace_facet(__imp, *__idpp); 00267 } 00268 00269 void 00270 locale::_Impl:: 00271 _M_replace_facet(const _Impl* __imp, const locale::id* __idp) 00272 { 00273 size_t __index = __idp->_M_id(); 00274 if ((__index > (__imp->_M_facets_size - 1)) 00275 || !__imp->_M_facets[__index]) 00276 __throw_runtime_error(__N("locale::_Impl::_M_replace_facet")); 00277 _M_install_facet(__idp, __imp->_M_facets[__index]); 00278 } 00279 00280 void 00281 locale::_Impl:: 00282 _M_install_facet(const locale::id* __idp, const facet* __fp) 00283 { 00284 if (__fp) 00285 { 00286 size_t __index = __idp->_M_id(); 00287 00288 // Check size of facet vector to ensure adequate room. 00289 if (__index > _M_facets_size - 1) 00290 { 00291 const size_t __new_size = __index + 4; 00292 00293 // New facet array. 00294 const facet** __oldf = _M_facets; 00295 const facet** __newf; 00296 __newf = new const facet*[__new_size]; 00297 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00298 __newf[__i] = _M_facets[__i]; 00299 for (size_t __l = _M_facets_size; __l < __new_size; ++__l) 00300 __newf[__l] = 0; 00301 00302 // New cache array. 00303 const facet** __oldc = _M_caches; 00304 const facet** __newc; 00305 try 00306 { 00307 __newc = new const facet*[__new_size]; 00308 } 00309 catch(...) 00310 { 00311 delete [] __newf; 00312 __throw_exception_again; 00313 } 00314 for (size_t __j = 0; __j < _M_facets_size; ++__j) 00315 __newc[__j] = _M_caches[__j]; 00316 for (size_t __k = _M_facets_size; __k < __new_size; ++__k) 00317 __newc[__k] = 0; 00318 00319 _M_facets_size = __new_size; 00320 _M_facets = __newf; 00321 _M_caches = __newc; 00322 delete [] __oldf; 00323 delete [] __oldc; 00324 } 00325 00326 __fp->_M_add_reference(); 00327 const facet*& __fpr = _M_facets[__index]; 00328 if (__fpr) 00329 { 00330 // Replacing an existing facet. Order matters. 00331 __fpr->_M_remove_reference(); 00332 __fpr = __fp; 00333 } 00334 else 00335 { 00336 // Installing a newly created facet into an empty 00337 // _M_facets container, say a newly-constructed, 00338 // swanky-fresh _Impl. 00339 _M_facets[__index] = __fp; 00340 } 00341 00342 // Ideally, it would be nice to only remove the caches that 00343 // are now incorrect. However, some of the caches depend on 00344 // multiple facets, and we only know about one facet 00345 // here. It's no great loss: the first use of the new facet 00346 // will create a new, correctly cached facet anyway. 00347 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00348 { 00349 const facet* __cpr = _M_caches[__i]; 00350 if (__cpr) 00351 { 00352 __cpr->_M_remove_reference(); 00353 _M_caches[__i] = 0; 00354 } 00355 } 00356 } 00357 } 00358 00359 00360 // locale::id 00361 // Definitions for static const data members of locale::id 00362 _Atomic_word locale::id::_S_refcount; // init'd to 0 by linker 00363 00364 size_t 00365 locale::id::_M_id() const 00366 { 00367 if (!_M_index) 00368 _M_index = 1 + __gnu_cxx::__exchange_and_add(&_S_refcount, 1); 00369 return _M_index - 1; 00370 } 00371 } // namespace std 00372 00373

Generated on Tue Sep 7 10:05:08 2004 for libstdc++-v3 Source by doxygen 1.3.8