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 |
|
---|
33 | namespace __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 |
|
---|
79 | namespace 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
|
---|