localename.cc revision 117397
1// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 2// Free Software Foundation, Inc. 3// 4// This file is part of the GNU ISO C++ Library. This library is free 5// software; you can redistribute it and/or modify it under the 6// terms of the GNU General Public License as published by the 7// Free Software Foundation; either version 2, or (at your option) 8// any later version. 9 10// This library is distributed in the hope that it will be useful, 11// but WITHOUT ANY WARRANTY; without even the implied warranty of 12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13// GNU General Public License for more details. 14 15// You should have received a copy of the GNU General Public License along 16// with this library; see the file COPYING. If not, write to the Free 17// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 18// USA. 19 20// As a special exception, you may use this file as part of a free software 21// library without restriction. Specifically, if other files instantiate 22// templates or use macros or inline functions from this file, or you compile 23// this file and link it with other files to produce an executable, this 24// file does not by itself cause the resulting executable to be covered by 25// the GNU General Public License. This exception does not however 26// invalidate any other reasons why the executable file might be covered by 27// the GNU General Public License. 28 29#include <clocale> 30#include <cstring> 31#include <locale> 32 33namespace __gnu_cxx 34{ 35 using namespace std; 36 37 // Defined in globals.cc. 38 extern locale::facet* facet_vec[_GLIBCPP_NUM_FACETS]; 39 extern locale::facet* facet_cache_vec[2 * _GLIBCPP_NUM_FACETS]; 40 extern char* facet_name[6 + _GLIBCPP_NUM_CATEGORIES]; 41 42 extern std::ctype<char> ctype_c; 43 extern std::collate<char> collate_c; 44 extern numpunct<char> numpunct_c; 45 extern num_get<char> num_get_c; 46 extern num_put<char> num_put_c; 47 extern codecvt<char, char, mbstate_t> codecvt_c; 48 extern moneypunct<char, false> moneypunct_fc; 49 extern moneypunct<char, true> moneypunct_tc; 50 extern money_get<char> money_get_c; 51 extern money_put<char> money_put_c; 52 extern __timepunct<char> timepunct_c; 53 extern time_get<char> time_get_c; 54 extern time_put<char> time_put_c; 55 extern std::messages<char> messages_c; 56#ifdef _GLIBCPP_USE_WCHAR_T 57 extern std::ctype<wchar_t> ctype_w; 58 extern std::collate<wchar_t> collate_w; 59 extern numpunct<wchar_t> numpunct_w; 60 extern num_get<wchar_t> num_get_w; 61 extern num_put<wchar_t> num_put_w; 62 extern codecvt<wchar_t, char, mbstate_t> codecvt_w; 63 extern moneypunct<wchar_t, false> moneypunct_fw; 64 extern moneypunct<wchar_t, true> moneypunct_tw; 65 extern money_get<wchar_t> money_get_w; 66 extern money_put<wchar_t> money_put_w; 67 extern __timepunct<wchar_t> timepunct_w; 68 extern time_get<wchar_t> time_get_w; 69 extern time_put<wchar_t> time_put_w; 70 extern std::messages<wchar_t> messages_w; 71#endif 72 73 extern std::__locale_cache<numpunct<char> > locale_cache_np_c; 74#ifdef _GLIBCPP_USE_WCHAR_T 75 extern std::__locale_cache<numpunct<wchar_t> > locale_cache_np_w; 76#endif 77} // namespace __gnu_cxx 78 79namespace std 80{ 81 using namespace __gnu_cxx; 82 83 locale::_Impl:: 84 ~_Impl() throw() 85 { 86 // Clean up facets, then caches. No cache refcounts for now. 87 for (size_t __i = 0; __i < _M_facets_size; ++__i) 88 if (_M_facets[__i]) 89 _M_facets[__i]->_M_remove_reference(); 90 for (size_t __i = _M_facets_size; __i < 2*_M_facets_size; ++__i) 91 if (_M_facets[__i]) 92 delete (__locale_cache_base*)_M_facets[__i]; 93 delete [] _M_facets; 94 95 for (size_t __i = 0; 96 __i < _S_categories_size + _S_extra_categories_size; ++__i) 97 delete [] _M_names[__i]; 98 } 99 100 // Clone existing _Impl object. 101 locale::_Impl:: 102 _Impl(const _Impl& __imp, size_t __refs) 103 : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX 104 { 105 try 106 { 107 // Space for facets and matching caches 108 _M_facets = new facet*[2*_M_facets_size]; 109 for (size_t __i = 0; __i < 2*_M_facets_size; ++__i) 110 _M_facets[__i] = 0; 111 } 112 catch(...) 113 { 114 delete [] _M_facets; 115 __throw_exception_again; 116 } 117 for (size_t __i = 0; __i < _M_facets_size; ++__i) 118 { 119 _M_facets[__i] = __imp._M_facets[__i]; 120 if (_M_facets[__i]) 121 _M_facets[__i]->_M_add_reference(); 122 } 123 for (size_t __i = 0; 124 __i < _S_categories_size + _S_extra_categories_size; ++__i) 125 { 126 char* __new = new char[strlen(__imp._M_names[__i]) + 1]; 127 strcpy(__new, __imp._M_names[__i]); 128 _M_names[__i] = __new; 129 } 130 } 131 132 // Construct named _Impl. 133 locale::_Impl:: 134 _Impl(const char* __s, size_t __refs) 135 : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) 136 { 137 // Initialize the underlying locale model, which also checks 138 // to see if the given name is valid. 139 __c_locale __cloc; 140 locale::facet::_S_create_c_locale(__cloc, __s); 141 142 try 143 { 144 // Space for facets and matching caches 145 _M_facets = new facet*[2*_M_facets_size]; 146 for (size_t __i = 0; __i < 2*_M_facets_size; ++__i) 147 _M_facets[__i] = 0; 148 } 149 catch(...) 150 { 151 delete [] _M_facets; 152 __throw_exception_again; 153 } 154 155 // Name all the categories. 156 size_t __len = strlen(__s); 157 if (!strchr(__s, ';')) 158 { 159 for (size_t __i = 0; 160 __i < _S_categories_size + _S_extra_categories_size; ++__i) 161 { 162 _M_names[__i] = new char[__len + 1]; 163 strcpy(_M_names[__i], __s); 164 } 165 } 166 else 167 { 168 const char* __beg = __s; 169 for (size_t __i = 0; 170 __i < _S_categories_size + _S_extra_categories_size; ++__i) 171 { 172 __beg = strchr(__beg, '=') + 1; 173 const char* __end = strchr(__beg, ';'); 174 if (!__end) 175 __end = __s + __len; 176 char* __new = new char[__end - __beg + 1]; 177 memcpy(__new, __beg, __end - __beg); 178 __new[__end - __beg] = '\0'; 179 _M_names[__i] = __new; 180 } 181 } 182 183 // Construct all standard facets and add them to _M_facets. 184 _M_init_facet(new std::ctype<char>(__cloc, 0, false)); 185 _M_init_facet(new codecvt<char, char, mbstate_t>); 186 _M_init_facet(new numpunct<char>(__cloc)); 187 _M_init_facet(new num_get<char>); 188 _M_init_facet(new num_put<char>); 189 _M_init_facet(new std::collate<char>(__cloc)); 190 _M_init_facet(new moneypunct<char, false>(__cloc, __s)); 191 _M_init_facet(new moneypunct<char, true>(__cloc, __s)); 192 _M_init_facet(new money_get<char>); 193 _M_init_facet(new money_put<char>); 194 _M_init_facet(new __timepunct<char>(__cloc, __s)); 195 _M_init_facet(new time_get<char>); 196 _M_init_facet(new time_put<char>); 197 _M_init_facet(new std::messages<char>(__cloc, __s)); 198 199#ifdef _GLIBCPP_USE_WCHAR_T 200 _M_init_facet(new std::ctype<wchar_t>(__cloc)); 201 _M_init_facet(new codecvt<wchar_t, char, mbstate_t>); 202 _M_init_facet(new numpunct<wchar_t>(__cloc)); 203 _M_init_facet(new num_get<wchar_t>); 204 _M_init_facet(new num_put<wchar_t>); 205 _M_init_facet(new std::collate<wchar_t>(__cloc)); 206 _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s)); 207 _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s)); 208 _M_init_facet(new money_get<wchar_t>); 209 _M_init_facet(new money_put<wchar_t>); 210 _M_init_facet(new __timepunct<wchar_t>(__cloc, __s)); 211 _M_init_facet(new time_get<wchar_t>); 212 _M_init_facet(new time_put<wchar_t>); 213 _M_init_facet(new std::messages<wchar_t>(__cloc, __s)); 214#endif 215 locale::facet::_S_destroy_c_locale(__cloc); 216 } 217 218 // Construct "C" _Impl. 219 locale::_Impl:: 220 _Impl(facet**, size_t __refs, bool) 221 : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) 222 { 223 // Initialize the underlying locale model. 224 locale::facet::_S_c_name[0] = 'C'; 225 locale::facet::_S_c_name[1] = '\0'; 226 locale::facet::_S_create_c_locale(locale::facet::_S_c_locale, 227 locale::facet::_S_c_name); 228 229 // Space for facets and matching caches 230 _M_facets = new(&facet_cache_vec) facet*[2*_M_facets_size]; 231 for (size_t __i = 0; __i < 2*_M_facets_size; ++__i) 232 _M_facets[__i] = 0; 233 234 // Name all the categories. 235 for (size_t __i = 0; 236 __i < _S_categories_size + _S_extra_categories_size; ++__i) 237 { 238 _M_names[__i] = new (&facet_name[__i]) char[2]; 239 strcpy(_M_names[__i], locale::facet::_S_c_name); 240 } 241 242 // This is needed as presently the C++ version of "C" locales 243 // != data in the underlying locale model for __timepunct, 244 // numpunct, and moneypunct. Also, the "C" locales must be 245 // constructed in a way such that they are pre-allocated. 246 // NB: Set locale::facets(ref) count to one so that each individual 247 // facet is not destroyed when the locale (and thus locale::_Impl) is 248 // destroyed. 249 _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1)); 250 _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1)); 251 _M_init_facet(new (&numpunct_c) numpunct<char>(1)); 252 _M_init_facet(new (&num_get_c) num_get<char>(1)); 253 _M_init_facet(new (&num_put_c) num_put<char>(1)); 254 _M_init_facet(new (&collate_c) std::collate<char>(1)); 255 _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1)); 256 _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1)); 257 _M_init_facet(new (&money_get_c) money_get<char>(1)); 258 _M_init_facet(new (&money_put_c) money_put<char>(1)); 259 _M_init_facet(new (&timepunct_c) __timepunct<char>(1)); 260 _M_init_facet(new (&time_get_c) time_get<char>(1)); 261 _M_init_facet(new (&time_put_c) time_put<char>(1)); 262 _M_init_facet(new (&messages_c) std::messages<char>(1)); 263#ifdef _GLIBCPP_USE_WCHAR_T 264 _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1)); 265 _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1)); 266 _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1)); 267 _M_init_facet(new (&num_get_w) num_get<wchar_t>(1)); 268 _M_init_facet(new (&num_put_w) num_put<wchar_t>(1)); 269 _M_init_facet(new (&collate_w) std::collate<wchar_t>(1)); 270 _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1)); 271 _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1)); 272 _M_init_facet(new (&money_get_w) money_get<wchar_t>(1)); 273 _M_init_facet(new (&money_put_w) money_put<wchar_t>(1)); 274 _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1)); 275 _M_init_facet(new (&time_get_w) time_get<wchar_t>(1)); 276 _M_init_facet(new (&time_put_w) time_put<wchar_t>(1)); 277 _M_init_facet(new (&messages_w) std::messages<wchar_t>(1)); 278#endif 279 280 // Initialize the static locale caches for C locale. 281 282 locale ltmp(this); // Doesn't bump refcount 283 _M_add_reference(); // Bump so destructor doesn't trash us 284 285 // These need to be built in static allocated memory. There must 286 // be a better way to do this! 287 __locale_cache<numpunct<char> >* __lc = 288 new (&locale_cache_np_c) __locale_cache<numpunct<char> >(ltmp, true); 289 _M_facets[numpunct<char>::id._M_id() + _M_facets_size] = 290 reinterpret_cast<locale::facet*>(__lc); 291 292#ifdef _GLIBCPP_USE_WCHAR_T 293 __locale_cache<numpunct<wchar_t> >* __wlc = 294 new (&locale_cache_np_w) __locale_cache<numpunct<wchar_t> >(ltmp, true); 295 _M_facets[numpunct<wchar_t>::id._M_id() + _M_facets_size] = 296 reinterpret_cast<locale::facet*>(__wlc); 297#endif 298 } 299 300 void 301 locale::_Impl:: 302 _M_replace_categories(const _Impl* __imp, category __cat) 303 { 304 category __mask; 305 for (size_t __ix = 0; __ix < _S_categories_size; ++__ix) 306 { 307 __mask = 1 << __ix; 308 if (__mask & __cat) 309 { 310 // Need to replace entry in _M_facets with other locale's info. 311 _M_replace_category(__imp, _S_facet_categories[__ix]); 312 // If both have names, go ahead and mangle. 313 if (strcmp(_M_names[__ix], "*") != 0 314 && strcmp(__imp->_M_names[__ix], "*") != 0) 315 { 316 delete [] _M_names[__ix]; 317 char* __new = new char[strlen(__imp->_M_names[__ix]) + 1]; 318 strcpy(__new, __imp->_M_names[__ix]); 319 _M_names[__ix] = __new; 320 } 321 } 322 } 323 } 324 325 void 326 locale::_Impl:: 327 _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp) 328 { 329 for (; *__idpp; ++__idpp) 330 _M_replace_facet(__imp, *__idpp); 331 } 332 333 void 334 locale::_Impl:: 335 _M_replace_facet(const _Impl* __imp, const locale::id* __idp) 336 { 337 size_t __index = __idp->_M_id(); 338 if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index]) 339 __throw_runtime_error("no locale facet"); 340 _M_install_facet(__idp, __imp->_M_facets[__index]); 341 } 342 343 void 344 locale::_Impl:: 345 _M_install_facet(const locale::id* __idp, facet* __fp) 346 { 347 if (__fp) 348 { 349 size_t __index = __idp->_M_id(); 350 351 // Check size of facet vector to ensure adequate room. 352 if (__index > _M_facets_size - 1) 353 { 354 facet** __old = _M_facets; 355 facet** __new; 356 const size_t __new_size = __index + 4; 357 __new = new facet*[2 * __new_size]; 358 for (size_t __i = 0; __i < _M_facets_size; ++__i) 359 __new[__i] = _M_facets[__i]; 360 for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2) 361 __new[__i2] = 0; 362 // Also copy caches and clear extra space 363 for (size_t __i = 0; __i < _M_facets_size; ++__i) 364 __new[__i + __new_size] = _M_facets[__i + _M_facets_size]; 365 for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2) 366 __new[__i2 + __new_size] = 0; 367 368 _M_facets_size = __new_size; 369 _M_facets = __new; 370 delete [] __old; 371 } 372 373 __fp->_M_add_reference(); 374 facet*& __fpr = _M_facets[__index]; 375 if (__fpr) 376 { 377 // Replacing an existing facet. Order matters. 378 __fpr->_M_remove_reference(); 379 __fpr = __fp; 380 } 381 else 382 { 383 // Installing a newly created facet into an empty 384 // _M_facets container, say a newly-constructed, 385 // swanky-fresh _Impl. 386 _M_facets[__index] = __fp; 387 } 388 } 389 } 390} // namespace std 391