source: trunk/gcc/libstdc++-v3/src/localename.cc

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 13.7 KB
Line 
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 if (_M_facets)
88 {
89 for (size_t __i = 0; __i < _M_facets_size; ++__i)
90 if (_M_facets[__i])
91 _M_facets[__i]->_M_remove_reference();
92
93 for (size_t __i = _M_facets_size; __i < 2*_M_facets_size; ++__i)
94 if (_M_facets[__i])
95 delete (__locale_cache_base*)_M_facets[__i];
96 }
97 delete [] _M_facets;
98
99 for (size_t __i = 0;
100 __i < _S_categories_size + _S_extra_categories_size; ++__i)
101 delete [] _M_names[__i];
102 }
103
104 // Clone existing _Impl object.
105 locale::_Impl::
106 _Impl(const _Impl& __imp, size_t __refs)
107 : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX
108 {
109 _M_facets = 0;
110 for (size_t __i = 0; __i < _S_categories_size
111 + _S_extra_categories_size; ++__i)
112 _M_names[__i] = 0;
113 try
114 {
115 // Space for facets and matching caches
116 _M_facets = new facet*[2*_M_facets_size];
117 for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
118 _M_facets[__i] = 0;
119 for (size_t __i = 0; __i < _M_facets_size; ++__i)
120 {
121 _M_facets[__i] = __imp._M_facets[__i];
122 if (_M_facets[__i])
123 _M_facets[__i]->_M_add_reference();
124 }
125 for (size_t __i = 0;
126 __i < _S_categories_size + _S_extra_categories_size; ++__i)
127 {
128 char* __new = new char[strlen(__imp._M_names[__i]) + 1];
129 strcpy(__new, __imp._M_names[__i]);
130 _M_names[__i] = __new;
131 }
132 }
133 catch(...)
134 {
135 this->~_Impl();
136 __throw_exception_again;
137 }
138 }
139
140 // Construct named _Impl.
141 locale::_Impl::
142 _Impl(const char* __s, size_t __refs)
143 : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
144 {
145 // Initialize the underlying locale model, which also checks
146 // to see if the given name is valid.
147 __c_locale __cloc;
148 locale::facet::_S_create_c_locale(__cloc, __s);
149
150 _M_facets = 0;
151 for (size_t __i = 0; __i < _S_categories_size
152 + _S_extra_categories_size; ++__i)
153 _M_names[__i] = 0;
154 try
155 {
156 // Space for facets and matching caches
157 _M_facets = new facet*[2*_M_facets_size];
158 for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
159 _M_facets[__i] = 0;
160
161 // Name all the categories.
162 size_t __len = strlen(__s);
163 if (!strchr(__s, ';'))
164 {
165 for (size_t __i = 0;
166 __i < _S_categories_size + _S_extra_categories_size; ++__i)
167 {
168 _M_names[__i] = new char[__len + 1];
169 strcpy(_M_names[__i], __s);
170 }
171 }
172 else
173 {
174 const char* __beg = __s;
175 for (size_t __i = 0;
176 __i < _S_categories_size + _S_extra_categories_size; ++__i)
177 {
178 __beg = strchr(__beg, '=') + 1;
179 const char* __end = strchr(__beg, ';');
180 if (!__end)
181 __end = __s + __len;
182 char* __new = new char[__end - __beg + 1];
183 memcpy(__new, __beg, __end - __beg);
184 __new[__end - __beg] = '\0';
185 _M_names[__i] = __new;
186 }
187 }
188
189 // Construct all standard facets and add them to _M_facets.
190 _M_init_facet(new std::ctype<char>(__cloc, 0, false));
191 _M_init_facet(new codecvt<char, char, mbstate_t>);
192 _M_init_facet(new numpunct<char>(__cloc));
193 _M_init_facet(new num_get<char>);
194 _M_init_facet(new num_put<char>);
195 _M_init_facet(new std::collate<char>(__cloc));
196 _M_init_facet(new moneypunct<char, false>(__cloc, __s));
197 _M_init_facet(new moneypunct<char, true>(__cloc, __s));
198 _M_init_facet(new money_get<char>);
199 _M_init_facet(new money_put<char>);
200 _M_init_facet(new __timepunct<char>(__cloc, __s));
201 _M_init_facet(new time_get<char>);
202 _M_init_facet(new time_put<char>);
203 _M_init_facet(new std::messages<char>(__cloc, __s));
204
205#ifdef _GLIBCPP_USE_WCHAR_T
206 _M_init_facet(new std::ctype<wchar_t>(__cloc));
207 _M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
208 _M_init_facet(new numpunct<wchar_t>(__cloc));
209 _M_init_facet(new num_get<wchar_t>);
210 _M_init_facet(new num_put<wchar_t>);
211 _M_init_facet(new std::collate<wchar_t>(__cloc));
212 _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s));
213 _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s));
214 _M_init_facet(new money_get<wchar_t>);
215 _M_init_facet(new money_put<wchar_t>);
216 _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
217 _M_init_facet(new time_get<wchar_t>);
218 _M_init_facet(new time_put<wchar_t>);
219 _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
220#endif
221 locale::facet::_S_destroy_c_locale(__cloc);
222 }
223 catch(...)
224 {
225 locale::facet::_S_destroy_c_locale(__cloc);
226 this->~_Impl();
227 __throw_exception_again;
228 }
229 }
230
231 // Construct "C" _Impl.
232 locale::_Impl::
233 _Impl(facet**, size_t __refs, bool)
234 : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
235 {
236 // Initialize the underlying locale model.
237 locale::facet::_S_c_name[0] = 'C';
238 locale::facet::_S_c_name[1] = '\0';
239 locale::facet::_S_create_c_locale(locale::facet::_S_c_locale,
240 locale::facet::_S_c_name);
241
242 // Space for facets and matching caches
243 _M_facets = new(&facet_cache_vec) facet*[2*_M_facets_size];
244 for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
245 _M_facets[__i] = 0;
246
247 // Name all the categories.
248 for (size_t __i = 0;
249 __i < _S_categories_size + _S_extra_categories_size; ++__i)
250 {
251 _M_names[__i] = new (&facet_name[__i]) char[2];
252 strcpy(_M_names[__i], locale::facet::_S_c_name);
253 }
254
255 // This is needed as presently the C++ version of "C" locales
256 // != data in the underlying locale model for __timepunct,
257 // numpunct, and moneypunct. Also, the "C" locales must be
258 // constructed in a way such that they are pre-allocated.
259 // NB: Set locale::facets(ref) count to one so that each individual
260 // facet is not destroyed when the locale (and thus locale::_Impl) is
261 // destroyed.
262 _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
263 _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
264 _M_init_facet(new (&numpunct_c) numpunct<char>(1));
265 _M_init_facet(new (&num_get_c) num_get<char>(1));
266 _M_init_facet(new (&num_put_c) num_put<char>(1));
267 _M_init_facet(new (&collate_c) std::collate<char>(1));
268 _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1));
269 _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1));
270 _M_init_facet(new (&money_get_c) money_get<char>(1));
271 _M_init_facet(new (&money_put_c) money_put<char>(1));
272 _M_init_facet(new (&timepunct_c) __timepunct<char>(1));
273 _M_init_facet(new (&time_get_c) time_get<char>(1));
274 _M_init_facet(new (&time_put_c) time_put<char>(1));
275 _M_init_facet(new (&messages_c) std::messages<char>(1));
276#ifdef _GLIBCPP_USE_WCHAR_T
277 _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
278 _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
279 _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
280 _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
281 _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
282 _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
283 _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1));
284 _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1));
285 _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
286 _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
287 _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1));
288 _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
289 _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
290 _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
291#endif
292
293 // Initialize the static locale caches for C locale.
294
295 locale ltmp(this); // Doesn't bump refcount
296 _M_add_reference(); // Bump so destructor doesn't trash us
297
298 // These need to be built in static allocated memory. There must
299 // be a better way to do this!
300 __locale_cache<numpunct<char> >* __lc =
301 new (&locale_cache_np_c) __locale_cache<numpunct<char> >(ltmp, true);
302 _M_facets[numpunct<char>::id._M_id() + _M_facets_size] =
303 reinterpret_cast<locale::facet*>(__lc);
304
305#ifdef _GLIBCPP_USE_WCHAR_T
306 __locale_cache<numpunct<wchar_t> >* __wlc =
307 new (&locale_cache_np_w) __locale_cache<numpunct<wchar_t> >(ltmp, true);
308 _M_facets[numpunct<wchar_t>::id._M_id() + _M_facets_size] =
309 reinterpret_cast<locale::facet*>(__wlc);
310#endif
311 }
312
313 void
314 locale::_Impl::
315 _M_replace_categories(const _Impl* __imp, category __cat)
316 {
317 category __mask;
318 for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
319 {
320 __mask = 1 << __ix;
321 if (__mask & __cat)
322 {
323 // Need to replace entry in _M_facets with other locale's info.
324 _M_replace_category(__imp, _S_facet_categories[__ix]);
325 // If both have names, go ahead and mangle.
326 if (strcmp(_M_names[__ix], "*") != 0
327 && strcmp(__imp->_M_names[__ix], "*") != 0)
328 {
329 char* __new = new char[strlen(__imp->_M_names[__ix]) + 1];
330 strcpy(__new, __imp->_M_names[__ix]);
331 delete [] _M_names[__ix];
332 _M_names[__ix] = __new;
333 }
334 }
335 }
336 }
337
338 void
339 locale::_Impl::
340 _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
341 {
342 for (; *__idpp; ++__idpp)
343 _M_replace_facet(__imp, *__idpp);
344 }
345
346 void
347 locale::_Impl::
348 _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
349 {
350 size_t __index = __idp->_M_id();
351 if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index])
352 __throw_runtime_error("no locale facet");
353 _M_install_facet(__idp, __imp->_M_facets[__index]);
354 }
355
356 void
357 locale::_Impl::
358 _M_install_facet(const locale::id* __idp, facet* __fp)
359 {
360 if (__fp)
361 {
362 size_t __index = __idp->_M_id();
363
364 // Check size of facet vector to ensure adequate room.
365 if (__index > _M_facets_size - 1)
366 {
367 facet** __old = _M_facets;
368 facet** __new;
369 const size_t __new_size = __index + 4;
370 __new = new facet*[2 * __new_size];
371 for (size_t __i = 0; __i < _M_facets_size; ++__i)
372 __new[__i] = _M_facets[__i];
373 for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
374 __new[__i2] = 0;
375 // Also copy caches and clear extra space
376 for (size_t __i = 0; __i < _M_facets_size; ++__i)
377 __new[__i + __new_size] = _M_facets[__i + _M_facets_size];
378 for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
379 __new[__i2 + __new_size] = 0;
380
381 _M_facets_size = __new_size;
382 _M_facets = __new;
383 delete [] __old;
384 }
385
386 __fp->_M_add_reference();
387 facet*& __fpr = _M_facets[__index];
388 if (__fpr)
389 {
390 // Replacing an existing facet. Order matters.
391 __fpr->_M_remove_reference();
392 __fpr = __fp;
393 }
394 else
395 {
396 // Installing a newly created facet into an empty
397 // _M_facets container, say a newly-constructed,
398 // swanky-fresh _Impl.
399 _M_facets[__index] = __fp;
400 }
401 }
402 }
403} // namespace std
Note: See TracBrowser for help on using the repository browser.