localename.cc revision 97403
1// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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 std 34{ 35 // Defined in globals.cc. 36 extern std::ctype<char> ctype_c; 37 extern std::collate<char> collate_c; 38 extern numpunct<char> numpunct_c; 39 extern num_get<char> num_get_c; 40 extern num_put<char> num_put_c; 41 extern codecvt<char, char, mbstate_t> codecvt_c; 42 extern moneypunct<char, false> moneypunct_fc; 43 extern moneypunct<char, true> moneypunct_tc; 44 extern money_get<char> money_get_c; 45 extern money_put<char> money_put_c; 46 extern __timepunct<char> timepunct_c; 47 extern time_get<char> time_get_c; 48 extern time_put<char> time_put_c; 49 extern std::messages<char> messages_c; 50#ifdef _GLIBCPP_USE_WCHAR_T 51 extern std::ctype<wchar_t> ctype_w; 52 extern std::collate<wchar_t> collate_w; 53 extern numpunct<wchar_t> numpunct_w; 54 extern num_get<wchar_t> num_get_w; 55 extern num_put<wchar_t> num_put_w; 56 extern codecvt<wchar_t, char, mbstate_t> codecvt_w; 57 extern moneypunct<wchar_t, false> moneypunct_fw; 58 extern moneypunct<wchar_t, true> moneypunct_tw; 59 extern money_get<wchar_t> money_get_w; 60 extern money_put<wchar_t> money_put_w; 61 extern __timepunct<wchar_t> timepunct_w; 62 extern time_get<wchar_t> time_get_w; 63 extern time_put<wchar_t> time_put_w; 64 extern std::messages<wchar_t> messages_w; 65#endif 66 67 locale::_Impl:: 68 ~_Impl() throw() 69 { 70 for (size_t __i = 0; __i < _M_facets_size; ++__i) 71 if (_M_facets[__i]) 72 _M_facets[__i]->_M_remove_reference(); 73 delete [] _M_facets; 74 } 75 76 // Clone existing _Impl object. 77 locale::_Impl:: 78 _Impl(const _Impl& __imp, size_t __refs) 79 : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX 80 { 81 try 82 { 83 _M_facets = new facet*[_M_facets_size]; 84 for (size_t __i = 0; __i < _M_facets_size; ++__i) 85 _M_facets[__i] = 0; 86 } 87 catch(...) 88 { 89 delete [] _M_facets; 90 __throw_exception_again; 91 } 92 for (size_t __i = 0; __i < _M_facets_size; ++__i) 93 { 94 _M_facets[__i] = __imp._M_facets[__i]; 95 if (_M_facets[__i]) 96 _M_facets[__i]->_M_add_reference(); 97 } 98 for (size_t __i = 0; __i < _S_num_categories; ++__i) 99 _M_names[__i] = __imp._M_names[__i]; 100 } 101 102 // Construct named _Impl. 103 locale::_Impl:: 104 _Impl(const char* __s, size_t __refs) 105 : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) // XXX 106 { 107 // Initialize the underlying locale model, which also checks 108 // to see if the given name is valid. 109 __c_locale __cloc; 110 locale::facet::_S_create_c_locale(__cloc, __s); 111 112 try 113 { 114 _M_facets = new facet*[_M_facets_size]; 115 for (size_t __i = 0; __i < _M_facets_size; ++__i) 116 _M_facets[__i] = 0; 117 } 118 catch(...) 119 { 120 delete [] _M_facets; 121 __throw_exception_again; 122 } 123 124 // Name all the categories. 125 for (size_t i = 0; i < _S_num_categories; ++i) 126 _M_names[i] = __s; 127 128 // Construct all standard facets and add them to _M_facets. 129 _M_init_facet(new std::ctype<char>(__cloc)); 130 _M_init_facet(new codecvt<char, char, mbstate_t>); 131 _M_init_facet(new numpunct<char>(__cloc)); 132 _M_init_facet(new num_get<char>); 133 _M_init_facet(new num_put<char>); 134 _M_init_facet(new std::collate<char>(__cloc)); 135 _M_init_facet(new moneypunct<char, false>(__cloc)); 136 _M_init_facet(new moneypunct<char, true>(__cloc)); 137 _M_init_facet(new money_get<char>); 138 _M_init_facet(new money_put<char>); 139 _M_init_facet(new __timepunct<char>(__cloc, __s)); 140 _M_init_facet(new time_get<char>); 141 _M_init_facet(new time_put<char>); 142 _M_init_facet(new std::messages<char>(__cloc, __s)); 143 144#ifdef _GLIBCPP_USE_WCHAR_T 145 _M_init_facet(new std::ctype<wchar_t>(__cloc)); 146 _M_init_facet(new codecvt<wchar_t, char, mbstate_t>); 147 _M_init_facet(new numpunct<wchar_t>(__cloc)); 148 _M_init_facet(new num_get<wchar_t>); 149 _M_init_facet(new num_put<wchar_t>); 150 _M_init_facet(new std::collate<wchar_t>(__cloc)); 151 _M_init_facet(new moneypunct<wchar_t, false>(__cloc)); 152 _M_init_facet(new moneypunct<wchar_t, true>(__cloc)); 153 _M_init_facet(new money_get<wchar_t>); 154 _M_init_facet(new money_put<wchar_t>); 155 _M_init_facet(new __timepunct<wchar_t>(__cloc, __s)); 156 _M_init_facet(new time_get<wchar_t>); 157 _M_init_facet(new time_put<wchar_t>); 158 _M_init_facet(new std::messages<wchar_t>(__cloc, __s)); 159#endif 160 locale::facet::_S_destroy_c_locale(__cloc); 161 } 162 163 // Construct "C" _Impl. 164 locale::_Impl:: 165 _Impl(facet** __f, size_t __refs, bool) 166 : _M_references(__refs), _M_facets(__f), _M_facets_size(_GLIBCPP_NUM_FACETS) 167 { 168 // Name all the categories. 169 for (size_t i = 0; i < _S_num_categories; ++i) 170 _M_names[i] = "C"; 171 172 // This is needed as presently the C++ version of "C" locales 173 // != data in the underlying locale model for __timepunct, 174 // numpunct, and moneypunct. Also, the "C" locales must be 175 // constructed in a way such that they are pre-allocated. 176 _M_init_facet(new (&ctype_c) std::ctype<char>); 177 _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>); 178 _M_init_facet(new (&numpunct_c) numpunct<char>); 179 _M_init_facet(new (&num_get_c) num_get<char>); 180 _M_init_facet(new (&num_put_c) num_put<char>); 181 _M_init_facet(new (&collate_c) std::collate<char>); 182 _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>); 183 _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>); 184 _M_init_facet(new (&money_get_c) money_get<char>); 185 _M_init_facet(new (&money_put_c) money_put<char>); 186 _M_init_facet(new (&timepunct_c) __timepunct<char>); 187 _M_init_facet(new (&time_get_c) time_get<char>); 188 _M_init_facet(new (&time_put_c) time_put<char>); 189 _M_init_facet(new (&messages_c) std::messages<char>); 190#ifdef _GLIBCPP_USE_WCHAR_T 191 _M_init_facet(new (&ctype_w) std::ctype<wchar_t>); 192 _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>); 193 _M_init_facet(new (&numpunct_w) numpunct<wchar_t>); 194 _M_init_facet(new (&num_get_w) num_get<wchar_t>); 195 _M_init_facet(new (&num_put_w) num_put<wchar_t>); 196 _M_init_facet(new (&collate_w) std::collate<wchar_t>); 197 _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>); 198 _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>); 199 _M_init_facet(new (&money_get_w) money_get<wchar_t>); 200 _M_init_facet(new (&money_put_w) money_put<wchar_t>); 201 _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>); 202 _M_init_facet(new (&time_get_w) time_get<wchar_t>); 203 _M_init_facet(new (&time_put_w) time_put<wchar_t>); 204 _M_init_facet(new (&messages_w) std::messages<wchar_t>); 205#endif 206 } 207 208 void 209 locale::_Impl:: 210 _M_replace_categories(const _Impl* __imp, category __cat) 211 { 212 category __mask; 213 for (unsigned int __ix = 0; __ix < _S_num_categories; ++__ix) 214 { 215 __mask = 1 << __ix; 216 if (__mask & __cat) 217 { 218 // Need to replace entry in _M_facets with other locale's info. 219 _M_replace_category(__imp, _S_facet_categories[__ix]); 220 // If both have names, go ahead and mangle. 221 if (strcmp(_M_names[__ix], "*") != 0 222 && strcmp(__imp->_M_names[__ix], "*") != 0) 223 _M_names[__ix] = __imp->_M_names[__ix]; 224 } 225 } 226 } 227 228 void 229 locale::_Impl:: 230 _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp) 231 { 232 for (; *__idpp; ++__idpp) 233 _M_replace_facet(__imp, *__idpp); 234 } 235 236 void 237 locale::_Impl:: 238 _M_replace_facet(const _Impl* __imp, const locale::id* __idp) 239 { 240 size_t __index = __idp->_M_id(); 241 if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index]) 242 __throw_runtime_error("no locale facet"); 243 _M_install_facet(__idp, __imp->_M_facets[__index]); 244 } 245 246 void 247 locale::_Impl:: 248 _M_install_facet(const locale::id* __idp, facet* __fp) 249 { 250 if (__fp) 251 { 252 size_t __index = __idp->_M_id(); 253 if (__index > _M_facets_size - 1) 254 { 255 facet** __old = _M_facets; 256 facet** __new; 257 const size_t __new_size = __index + 4; 258 try 259 { __new = new facet*[__new_size]; } 260 catch(...) 261 { 262 delete [] __new; 263 __throw_exception_again; 264 } 265 for (size_t __i = 0; __i < _M_facets_size; ++__i) 266 __new[__i] = _M_facets[__i]; 267 for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2) 268 __new[__i2] = 0; 269 270 _M_facets_size = __new_size; 271 _M_facets = __new; 272 delete [] __old; 273 } 274 275 facet*& __fpr = _M_facets[__index]; 276 if (__fpr) 277 { 278 // Replacing an existing facet. Order matters. 279 __fp->_M_add_reference(); 280 __fpr->_M_remove_reference(); 281 __fpr = __fp; 282 } 283 else 284 { 285 // Installing a newly created facet into an empty 286 // _M_facets container, say a newly-constructed, 287 // swanky-fresh _Impl. 288 _M_facets[__index] = __fp; 289 } 290 } 291 } 292} // namespace std 293