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