gcc:
[official-gcc.git] / libstdc++-v3 / src / localename.cc
blob424bc64fec7349727ecbf0e0c32d781b8703e249
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.
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.
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.
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.
29 #include <clocale>
30 #include <cstring>
31 #include <locale>
33 namespace __gnu_cxx
35 using namespace std;
37 // Defined in globals.cc.
38 extern locale::facet* facet_vec[_GLIBCPP_NUM_FACETS];
39 extern char* name_vec[6 + _GLIBCPP_NUM_CATEGORIES];
40 extern char name_c[6 + _GLIBCPP_NUM_CATEGORIES][2];
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
73 extern locale::facet* cache_vec[_GLIBCPP_NUM_FACETS];
74 extern std::__numpunct_cache<char> numpunct_cache_c;
75 #ifdef _GLIBCPP_USE_WCHAR_T
76 extern std::__numpunct_cache<wchar_t> numpunct_cache_w;
77 #endif
78 } // namespace __gnu_cxx
80 namespace std
82 using namespace __gnu_cxx;
84 locale::_Impl::
85 ~_Impl() throw()
87 for (size_t __i = 0; __i < _M_facets_size; ++__i)
88 if (_M_facets[__i])
89 _M_facets[__i]->_M_remove_reference();
90 delete [] _M_facets;
92 for (size_t __i = 0; __i < _M_facets_size; ++__i)
93 if (_M_caches[__i])
94 _M_caches[__i]->_M_remove_reference();
95 delete [] _M_caches;
97 for (size_t __i = 0; __i < _S_categories_size; ++__i)
98 delete [] _M_names[__i];
99 delete [] _M_names;
102 // Clone existing _Impl object.
103 locale::_Impl::
104 _Impl(const _Impl& __imp, size_t __refs)
105 : _M_references(__refs), _M_facets_size(__imp._M_facets_size)
109 _M_facets = new const facet*[_M_facets_size];
110 for (size_t __i = 0; __i < _M_facets_size; ++__i)
111 _M_facets[__i] = 0;
113 catch(...)
115 delete [] _M_facets;
116 __throw_exception_again;
118 for (size_t __i = 0; __i < _M_facets_size; ++__i)
120 _M_facets[__i] = __imp._M_facets[__i];
121 if (_M_facets[__i])
122 _M_facets[__i]->_M_add_reference();
125 try
127 _M_caches = new const facet*[_M_facets_size];
129 catch(...)
131 delete [] _M_caches;
132 __throw_exception_again;
134 for (size_t __i = 0; __i < _M_facets_size; ++__i)
136 _M_caches[__i] = __imp._M_caches[__i];
137 if (_M_caches[__i])
138 _M_caches[__i]->_M_add_reference();
141 try
143 _M_names = new char*[_S_categories_size];
145 catch(...)
147 delete [] _M_names;
148 __throw_exception_again;
150 for (size_t __i = 0; __i < _S_categories_size; ++__i)
152 char* __new = new char[strlen(__imp._M_names[__i]) + 1];
153 strcpy(__new, __imp._M_names[__i]);
154 _M_names[__i] = __new;
158 // Construct named _Impl.
159 locale::_Impl::
160 _Impl(const char* __s, size_t __refs)
161 : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
163 // Initialize the underlying locale model, which also checks to
164 // see if the given name is valid.
165 __c_locale __cloc;
166 locale::facet::_S_create_c_locale(__cloc, __s);
170 _M_facets = new const facet*[_M_facets_size];
171 for (size_t __i = 0; __i < _M_facets_size; ++__i)
172 _M_facets[__i] = 0;
174 catch(...)
176 delete [] _M_facets;
177 __throw_exception_again;
180 try
182 _M_caches = new const facet*[_M_facets_size];
183 for (size_t __i = 0; __i < _M_facets_size; ++__i)
184 _M_caches[__i] = 0;
186 catch(...)
188 delete [] _M_caches;
189 __throw_exception_again;
192 // Name all the categories.
193 try
195 _M_names = new char*[_S_categories_size];
197 catch(...)
199 delete [] _M_names;
200 __throw_exception_again;
202 size_t __len = strlen(__s);
203 if (!strchr(__s, ';'))
205 for (size_t __i = 0; __i < _S_categories_size; ++__i)
207 _M_names[__i] = new char[__len + 1];
208 strcpy(_M_names[__i], __s);
211 else
213 const char* __beg = __s;
214 for (size_t __i = 0; __i < _S_categories_size; ++__i)
216 __beg = strchr(__beg, '=') + 1;
217 const char* __end = strchr(__beg, ';');
218 if (!__end)
219 __end = __s + __len;
220 char* __new = new char[__end - __beg + 1];
221 memcpy(__new, __beg, __end - __beg);
222 __new[__end - __beg] = '\0';
223 _M_names[__i] = __new;
227 // Construct all standard facets and add them to _M_facets.
228 _M_init_facet(new std::ctype<char>(__cloc, 0, false));
229 _M_init_facet(new codecvt<char, char, mbstate_t>(__cloc));
230 _M_init_facet(new numpunct<char>(__cloc));
231 _M_init_facet(new num_get<char>);
232 _M_init_facet(new num_put<char>);
233 _M_init_facet(new std::collate<char>(__cloc));
234 _M_init_facet(new moneypunct<char, false>(__cloc, __s));
235 _M_init_facet(new moneypunct<char, true>(__cloc, __s));
236 _M_init_facet(new money_get<char>);
237 _M_init_facet(new money_put<char>);
238 _M_init_facet(new __timepunct<char>(__cloc, __s));
239 _M_init_facet(new time_get<char>);
240 _M_init_facet(new time_put<char>);
241 _M_init_facet(new std::messages<char>(__cloc, __s));
243 #ifdef _GLIBCPP_USE_WCHAR_T
244 _M_init_facet(new std::ctype<wchar_t>(__cloc));
245 _M_init_facet(new codecvt<wchar_t, char, mbstate_t>(__cloc));
246 _M_init_facet(new numpunct<wchar_t>(__cloc));
247 _M_init_facet(new num_get<wchar_t>);
248 _M_init_facet(new num_put<wchar_t>);
249 _M_init_facet(new std::collate<wchar_t>(__cloc));
250 _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s));
251 _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s));
252 _M_init_facet(new money_get<wchar_t>);
253 _M_init_facet(new money_put<wchar_t>);
254 _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
255 _M_init_facet(new time_get<wchar_t>);
256 _M_init_facet(new time_put<wchar_t>);
257 _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
258 #endif
259 locale::facet::_S_destroy_c_locale(__cloc);
262 // Construct "C" _Impl.
263 locale::_Impl::
264 _Impl(facet**, size_t __refs, bool)
265 : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
267 // Initialize the underlying locale model.
268 locale::facet::_S_c_name[0] = 'C';
269 locale::facet::_S_c_name[1] = '\0';
270 locale::facet::_S_create_c_locale(locale::facet::_S_c_locale,
271 locale::facet::_S_c_name);
273 _M_facets = new (&facet_vec) const facet*[_M_facets_size];
274 for (size_t __i = 0; __i < _M_facets_size; ++__i)
275 _M_facets[__i] = 0;
277 _M_caches = new (&cache_vec) const facet*[_M_facets_size];
278 for (size_t __i = 0; __i < _M_facets_size; ++__i)
279 _M_caches[__i] = 0;
281 // Name all the categories.
282 _M_names = new (&name_vec) char*[_S_categories_size];
283 for (size_t __i = 0; __i < _S_categories_size; ++__i)
285 _M_names[__i] = new (&name_c[__i]) char[2];
286 strcpy(_M_names[__i], locale::facet::_S_c_name);
289 // This is needed as presently the C++ version of "C" locales
290 // != data in the underlying locale model for __timepunct,
291 // numpunct, and moneypunct. Also, the "C" locales must be
292 // constructed in a way such that they are pre-allocated.
293 // NB: Set locale::facets(ref) count to one so that each individual
294 // facet is not destroyed when the locale (and thus locale::_Impl) is
295 // destroyed.
296 _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
297 _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
299 // Safe to cache this.
300 typedef __numpunct_cache<char> num_cache_c;
301 num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2);
302 _M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1));
304 _M_init_facet(new (&num_get_c) num_get<char>(1));
305 _M_init_facet(new (&num_put_c) num_put<char>(1));
306 _M_init_facet(new (&collate_c) std::collate<char>(1));
307 _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1));
308 _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1));
309 _M_init_facet(new (&money_get_c) money_get<char>(1));
310 _M_init_facet(new (&money_put_c) money_put<char>(1));
311 _M_init_facet(new (&timepunct_c) __timepunct<char>(1));
312 _M_init_facet(new (&time_get_c) time_get<char>(1));
313 _M_init_facet(new (&time_put_c) time_put<char>(1));
314 _M_init_facet(new (&messages_c) std::messages<char>(1));
316 #ifdef _GLIBCPP_USE_WCHAR_T
317 _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
318 _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
320 typedef __numpunct_cache<wchar_t> num_cache_w;
321 num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2);
322 _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1));
324 _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
325 _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
326 _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
327 _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1));
328 _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1));
329 _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
330 _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
331 _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1));
332 _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
333 _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
334 _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
335 #endif
337 // This locale is safe to pre-cache, after all the facets have
338 // been installed.
339 _M_caches[numpunct<char>::id._M_id()] = __npc;
340 #ifdef _GLIBCPP_USE_WCHAR_T
341 _M_caches[numpunct<wchar_t>::id._M_id()] = __npw;
342 #endif
345 void
346 locale::_Impl::
347 _M_replace_categories(const _Impl* __imp, category __cat)
349 category __mask;
350 for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
352 __mask = 1 << __ix;
353 if (__mask & __cat)
355 // Need to replace entry in _M_facets with other locale's info.
356 _M_replace_category(__imp, _S_facet_categories[__ix]);
357 // If both have names, go ahead and mangle.
358 if (strcmp(_M_names[__ix], "*") != 0
359 && strcmp(__imp->_M_names[__ix], "*") != 0)
361 delete [] _M_names[__ix];
362 char* __new = new char[strlen(__imp->_M_names[__ix]) + 1];
363 strcpy(__new, __imp->_M_names[__ix]);
364 _M_names[__ix] = __new;
370 void
371 locale::_Impl::
372 _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
374 for (; *__idpp; ++__idpp)
375 _M_replace_facet(__imp, *__idpp);
378 void
379 locale::_Impl::
380 _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
382 size_t __index = __idp->_M_id();
383 if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index])
384 __throw_runtime_error("locale::_Impl::_M_replace_facet");
385 _M_install_facet(__idp, __imp->_M_facets[__index]);
388 void
389 locale::_Impl::
390 _M_install_facet(const locale::id* __idp, const facet* __fp)
392 if (__fp)
394 size_t __index = __idp->_M_id();
396 // Check size of facet vector to ensure adequate room.
397 if (__index > _M_facets_size - 1)
399 const size_t __new_size = __index + 4;
401 // New facet array.
402 const facet** __oldf = _M_facets;
403 const facet** __newf;
404 __newf = new const facet*[__new_size];
405 for (size_t __i = 0; __i < _M_facets_size; ++__i)
406 __newf[__i] = _M_facets[__i];
407 for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
408 __newf[__i2] = 0;
410 // New cache array.
411 const facet** __oldc = _M_caches;
412 const facet** __newc;
413 __newc = new const facet*[__new_size];
414 for (size_t __i = 0; __i < _M_facets_size; ++__i)
415 __newc[__i] = _M_caches[__i];
416 for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
417 __newc[__i2] = 0;
419 _M_facets_size = __new_size;
420 _M_facets = __newf;
421 _M_caches = __newc;
422 delete [] __oldf;
423 delete [] __oldc;
426 __fp->_M_add_reference();
427 const facet*& __fpr = _M_facets[__index];
428 if (__fpr)
430 // Replacing an existing facet. Order matters.
431 __fpr->_M_remove_reference();
432 __fpr = __fp;
434 else
436 // Installing a newly created facet into an empty
437 // _M_facets container, say a newly-constructed,
438 // swanky-fresh _Impl.
439 _M_facets[__index] = __fp;
442 // Ideally, it would be nice to only remove the caches that
443 // are now incorrect. However, some of the caches depend on
444 // multiple facets, and we only know about one facet
445 // here. It's no great loss: the first use of the new facet
446 // will create a new, correctly cached facet anyway.
447 for (size_t __i = 0; __i < _M_facets_size; ++__i)
449 const facet* __cpr = _M_caches[__i];
450 if (__cpr)
452 __cpr->_M_remove_reference();
453 _M_caches[__i] = 0;
458 } // namespace std