]>
Commit | Line | Data |
---|---|---|
aa118a03 | 1 | // Copyright (C) 1997-2014 Free Software Foundation, Inc. |
c755e77d BK |
2 | // |
3 | // This file is part of the GNU ISO C++ Library. This library is free | |
4 | // software; you can redistribute it and/or modify it under the | |
5 | // terms of the GNU General Public License as published by the | |
748086b7 | 6 | // Free Software Foundation; either version 3, or (at your option) |
c755e77d BK |
7 | // any later version. |
8 | ||
9 | // This library is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | ||
748086b7 JJ |
14 | // Under Section 7 of GPL version 3, you are granted additional |
15 | // permissions described in the GCC Runtime Library Exception, version | |
16 | // 3.1, as published by the Free Software Foundation. | |
c755e77d | 17 | |
748086b7 JJ |
18 | // You should have received a copy of the GNU General Public License and |
19 | // a copy of the GCC Runtime Library Exception along with this program; | |
20 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
21 | // <http://www.gnu.org/licenses/>. | |
c755e77d | 22 | |
34a2b755 | 23 | #define _GLIBCXX_USE_CXX11_ABI 1 |
c755e77d BK |
24 | #include <clocale> |
25 | #include <cstring> | |
26 | #include <cstdlib> // For getenv, free. | |
27 | #include <cctype> | |
28 | #include <cwctype> // For towupper, etc. | |
29 | #include <locale> | |
2e362c74 | 30 | #include <ext/concurrence.h> |
c755e77d | 31 | |
34a2b755 JW |
32 | #if _GLIBCXX_USE_DUAL_ABI |
33 | // This file is compiled with the new std::string ABI so std::numpunct<char> | |
34 | // refers to std::__cxx11::numpunct<char>. These declarations let us refer | |
35 | // to the other facets instantiated with the old ABI. | |
36 | # define _GLIBCXX_LOC_ID(mangled) extern std::locale::id mangled | |
37 | _GLIBCXX_LOC_ID(_ZNSt8numpunctIcE2idE); | |
38 | _GLIBCXX_LOC_ID(_ZNSt7collateIcE2idE); | |
39 | _GLIBCXX_LOC_ID(_ZNSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE); | |
40 | _GLIBCXX_LOC_ID(_ZNSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE); | |
41 | _GLIBCXX_LOC_ID(_ZNSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE); | |
42 | _GLIBCXX_LOC_ID(_ZNSt10moneypunctIcLb0EE2idE); | |
43 | _GLIBCXX_LOC_ID(_ZNSt10moneypunctIcLb1EE2idE); | |
44 | _GLIBCXX_LOC_ID(_ZNSt8messagesIcE2idE); | |
45 | # ifdef _GLIBCXX_USE_WCHAR_T | |
46 | _GLIBCXX_LOC_ID(_ZNSt8numpunctIwE2idE); | |
47 | _GLIBCXX_LOC_ID(_ZNSt7collateIwE2idE); | |
48 | _GLIBCXX_LOC_ID(_ZNSt8time_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE); | |
49 | _GLIBCXX_LOC_ID(_ZNSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE); | |
50 | _GLIBCXX_LOC_ID(_ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE); | |
51 | _GLIBCXX_LOC_ID(_ZNSt10moneypunctIwLb0EE2idE); | |
52 | _GLIBCXX_LOC_ID(_ZNSt10moneypunctIwLb1EE2idE); | |
53 | _GLIBCXX_LOC_ID(_ZNSt8messagesIwE2idE); | |
54 | # endif | |
55 | #endif | |
56 | ||
57 | ||
b82f782b | 58 | namespace |
c755e77d | 59 | { |
34a2b755 JW |
60 | const int num_facets = _GLIBCXX_NUM_FACETS |
61 | + (_GLIBCXX_USE_DUAL_ABI ? _GLIBCXX_NUM_CXX11_FACETS : 0); | |
62 | ||
8ba9f013 | 63 | __gnu_cxx::__mutex& |
e64690af | 64 | get_locale_mutex() |
8ba9f013 BK |
65 | { |
66 | static __gnu_cxx::__mutex locale_mutex; | |
67 | return locale_mutex; | |
68 | } | |
69 | ||
b82f782b BK |
70 | using namespace std; |
71 | ||
72 | typedef char fake_locale_Impl[sizeof(locale::_Impl)] | |
73 | __attribute__ ((aligned(__alignof__(locale::_Impl)))); | |
74 | fake_locale_Impl c_locale_impl; | |
75 | ||
76 | typedef char fake_locale[sizeof(locale)] | |
77 | __attribute__ ((aligned(__alignof__(locale)))); | |
78 | fake_locale c_locale; | |
79 | ||
80 | typedef char fake_name_vec[sizeof(char*)] | |
81 | __attribute__ ((aligned(__alignof__(char*)))); | |
82 | fake_name_vec name_vec[6 + _GLIBCXX_NUM_CATEGORIES]; | |
83 | ||
84 | typedef char fake_names[sizeof(char[2])] | |
85 | __attribute__ ((aligned(__alignof__(char[2])))); | |
86 | fake_names name_c[6 + _GLIBCXX_NUM_CATEGORIES]; | |
87 | ||
88 | typedef char fake_facet_vec[sizeof(locale::facet*)] | |
89 | __attribute__ ((aligned(__alignof__(locale::facet*)))); | |
34a2b755 | 90 | fake_facet_vec facet_vec[num_facets]; |
b82f782b BK |
91 | |
92 | typedef char fake_cache_vec[sizeof(locale::facet*)] | |
93 | __attribute__ ((aligned(__alignof__(locale::facet*)))); | |
34a2b755 | 94 | fake_cache_vec cache_vec[num_facets]; |
b82f782b BK |
95 | |
96 | typedef char fake_ctype_c[sizeof(std::ctype<char>)] | |
97 | __attribute__ ((aligned(__alignof__(std::ctype<char>)))); | |
98 | fake_ctype_c ctype_c; | |
99 | ||
100 | typedef char fake_collate_c[sizeof(std::collate<char>)] | |
101 | __attribute__ ((aligned(__alignof__(std::collate<char>)))); | |
102 | fake_collate_c collate_c; | |
103 | ||
104 | typedef char fake_numpunct_c[sizeof(numpunct<char>)] | |
105 | __attribute__ ((aligned(__alignof__(numpunct<char>)))); | |
106 | fake_numpunct_c numpunct_c; | |
107 | ||
108 | typedef char fake_num_get_c[sizeof(num_get<char>)] | |
109 | __attribute__ ((aligned(__alignof__(num_get<char>)))); | |
110 | fake_num_get_c num_get_c; | |
111 | ||
112 | typedef char fake_num_put_c[sizeof(num_put<char>)] | |
113 | __attribute__ ((aligned(__alignof__(num_put<char>)))); | |
114 | fake_num_put_c num_put_c; | |
115 | ||
116 | typedef char fake_codecvt_c[sizeof(codecvt<char, char, mbstate_t>)] | |
117 | __attribute__ ((aligned(__alignof__(codecvt<char, char, mbstate_t>)))); | |
118 | fake_codecvt_c codecvt_c; | |
119 | ||
120 | typedef char fake_moneypunct_c[sizeof(moneypunct<char, true>)] | |
121 | __attribute__ ((aligned(__alignof__(moneypunct<char, true>)))); | |
122 | fake_moneypunct_c moneypunct_ct; | |
123 | fake_moneypunct_c moneypunct_cf; | |
124 | ||
125 | typedef char fake_money_get_c[sizeof(money_get<char>)] | |
126 | __attribute__ ((aligned(__alignof__(money_get<char>)))); | |
127 | fake_money_get_c money_get_c; | |
128 | ||
129 | typedef char fake_money_put_c[sizeof(money_put<char>)] | |
130 | __attribute__ ((aligned(__alignof__(money_put<char>)))); | |
131 | fake_money_put_c money_put_c; | |
132 | ||
133 | typedef char fake_timepunct_c[sizeof(__timepunct<char>)] | |
134 | __attribute__ ((aligned(__alignof__(__timepunct<char>)))); | |
135 | fake_timepunct_c timepunct_c; | |
136 | ||
137 | typedef char fake_time_get_c[sizeof(time_get<char>)] | |
138 | __attribute__ ((aligned(__alignof__(time_get<char>)))); | |
139 | fake_time_get_c time_get_c; | |
140 | ||
141 | typedef char fake_time_put_c[sizeof(time_put<char>)] | |
142 | __attribute__ ((aligned(__alignof__(time_put<char>)))); | |
143 | fake_time_put_c time_put_c; | |
144 | ||
145 | typedef char fake_messages_c[sizeof(messages<char>)] | |
146 | __attribute__ ((aligned(__alignof__(messages<char>)))); | |
147 | fake_messages_c messages_c; | |
148 | ||
c755e77d | 149 | #ifdef _GLIBCXX_USE_WCHAR_T |
b82f782b BK |
150 | typedef char fake_wtype_w[sizeof(std::ctype<wchar_t>)] |
151 | __attribute__ ((aligned(__alignof__(std::ctype<wchar_t>)))); | |
152 | fake_wtype_w ctype_w; | |
153 | ||
154 | typedef char fake_wollate_w[sizeof(std::collate<wchar_t>)] | |
155 | __attribute__ ((aligned(__alignof__(std::collate<wchar_t>)))); | |
156 | fake_wollate_w collate_w; | |
157 | ||
158 | typedef char fake_numpunct_w[sizeof(numpunct<wchar_t>)] | |
159 | __attribute__ ((aligned(__alignof__(numpunct<wchar_t>)))); | |
160 | fake_numpunct_w numpunct_w; | |
161 | ||
162 | typedef char fake_num_get_w[sizeof(num_get<wchar_t>)] | |
163 | __attribute__ ((aligned(__alignof__(num_get<wchar_t>)))); | |
164 | fake_num_get_w num_get_w; | |
165 | ||
166 | typedef char fake_num_put_w[sizeof(num_put<wchar_t>)] | |
167 | __attribute__ ((aligned(__alignof__(num_put<wchar_t>)))); | |
168 | fake_num_put_w num_put_w; | |
169 | ||
170 | typedef char fake_wodecvt_w[sizeof(codecvt<wchar_t, char, mbstate_t>)] | |
171 | __attribute__ ((aligned(__alignof__(codecvt<wchar_t, char, mbstate_t>)))); | |
172 | fake_wodecvt_w codecvt_w; | |
173 | ||
174 | typedef char fake_moneypunct_w[sizeof(moneypunct<wchar_t, true>)] | |
175 | __attribute__ ((aligned(__alignof__(moneypunct<wchar_t, true>)))); | |
176 | fake_moneypunct_w moneypunct_wt; | |
177 | fake_moneypunct_w moneypunct_wf; | |
178 | ||
179 | typedef char fake_money_get_w[sizeof(money_get<wchar_t>)] | |
180 | __attribute__ ((aligned(__alignof__(money_get<wchar_t>)))); | |
181 | fake_money_get_w money_get_w; | |
182 | ||
183 | typedef char fake_money_put_w[sizeof(money_put<wchar_t>)] | |
184 | __attribute__ ((aligned(__alignof__(money_put<wchar_t>)))); | |
185 | fake_money_put_w money_put_w; | |
186 | ||
187 | typedef char fake_timepunct_w[sizeof(__timepunct<wchar_t>)] | |
188 | __attribute__ ((aligned(__alignof__(__timepunct<wchar_t>)))); | |
189 | fake_timepunct_w timepunct_w; | |
190 | ||
191 | typedef char fake_time_get_w[sizeof(time_get<wchar_t>)] | |
192 | __attribute__ ((aligned(__alignof__(time_get<wchar_t>)))); | |
193 | fake_time_get_w time_get_w; | |
194 | ||
195 | typedef char fake_time_put_w[sizeof(time_put<wchar_t>)] | |
196 | __attribute__ ((aligned(__alignof__(time_put<wchar_t>)))); | |
197 | fake_time_put_w time_put_w; | |
198 | ||
199 | typedef char fake_messages_w[sizeof(messages<wchar_t>)] | |
200 | __attribute__ ((aligned(__alignof__(messages<wchar_t>)))); | |
201 | fake_messages_w messages_w; | |
c755e77d BK |
202 | #endif |
203 | ||
b82f782b BK |
204 | // Storage for "C" locale caches. |
205 | typedef char fake_num_cache_c[sizeof(std::__numpunct_cache<char>)] | |
206 | __attribute__ ((aligned(__alignof__(std::__numpunct_cache<char>)))); | |
207 | fake_num_cache_c numpunct_cache_c; | |
208 | ||
209 | typedef char fake_money_cache_c[sizeof(std::__moneypunct_cache<char, true>)] | |
210 | __attribute__ ((aligned(__alignof__(std::__moneypunct_cache<char, true>)))); | |
211 | fake_money_cache_c moneypunct_cache_ct; | |
212 | fake_money_cache_c moneypunct_cache_cf; | |
213 | ||
214 | typedef char fake_time_cache_c[sizeof(std::__timepunct_cache<char>)] | |
215 | __attribute__ ((aligned(__alignof__(std::__timepunct_cache<char>)))); | |
216 | fake_time_cache_c timepunct_cache_c; | |
217 | ||
218 | #ifdef _GLIBCXX_USE_WCHAR_T | |
219 | typedef char fake_num_cache_w[sizeof(std::__numpunct_cache<wchar_t>)] | |
220 | __attribute__ ((aligned(__alignof__(std::__numpunct_cache<wchar_t>)))); | |
221 | fake_num_cache_w numpunct_cache_w; | |
222 | ||
223 | typedef char fake_money_cache_w[sizeof(std::__moneypunct_cache<wchar_t,true>)] | |
224 | __attribute__ ((aligned(__alignof__(std::__moneypunct_cache<wchar_t,true>)))); | |
225 | fake_money_cache_w moneypunct_cache_wt; | |
226 | fake_money_cache_w moneypunct_cache_wf; | |
227 | ||
228 | typedef char fake_time_cache_w[sizeof(std::__timepunct_cache<wchar_t>)] | |
229 | __attribute__ ((aligned(__alignof__(std::__timepunct_cache<wchar_t>)))); | |
230 | fake_time_cache_w timepunct_cache_w; | |
c755e77d | 231 | #endif |
b82f782b | 232 | } // anonymous namespace |
c755e77d | 233 | |
12ffa228 BK |
234 | namespace std _GLIBCXX_VISIBILITY(default) |
235 | { | |
236 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
3cbc7af0 | 237 | |
26c691a8 | 238 | locale::locale() throw() : _M_impl(0) |
c755e77d | 239 | { |
838d4309 | 240 | _S_initialize(); |
4ef89725 JG |
241 | |
242 | // Checked locking to optimize the common case where _S_global | |
243 | // still points to _S_classic (locale::_S_initialize_once()): | |
244 | // - If they are the same, just increment the reference count and | |
245 | // we are done. This effectively constructs a C locale object | |
246 | // identical to the static c_locale. | |
247 | // - Otherwise, _S_global can and may be destroyed due to | |
248 | // locale::global() call on another thread, in which case we | |
249 | // fall back to lock protected access to both _S_global and | |
250 | // its reference count. | |
3fe13738 | 251 | _M_impl = _S_global; |
4ef89725 JG |
252 | if (_M_impl == _S_classic) |
253 | _M_impl->_M_add_reference(); | |
254 | else | |
255 | { | |
256 | __gnu_cxx::__scoped_lock sentry(get_locale_mutex()); | |
257 | _S_global->_M_add_reference(); | |
258 | _M_impl = _S_global; | |
259 | } | |
c755e77d BK |
260 | } |
261 | ||
262 | locale | |
263 | locale::global(const locale& __other) | |
264 | { | |
265 | _S_initialize(); | |
838d4309 BK |
266 | _Impl* __old; |
267 | { | |
e64690af | 268 | __gnu_cxx::__scoped_lock sentry(get_locale_mutex()); |
838d4309 BK |
269 | __old = _S_global; |
270 | __other._M_impl->_M_add_reference(); | |
271 | _S_global = __other._M_impl; | |
272 | const string __other_name = __other.name(); | |
273 | if (__other_name != "*") | |
274 | setlocale(LC_ALL, __other_name.c_str()); | |
275 | } | |
c755e77d BK |
276 | |
277 | // Reference count sanity check: one reference removed for the | |
278 | // subsition of __other locale, one added by return-by-value. Net | |
279 | // difference: zero. When the returned locale object's destrutor | |
280 | // is called, then the reference count is decremented and possibly | |
281 | // destroyed. | |
282 | return locale(__old); | |
283 | } | |
284 | ||
285 | const locale& | |
286 | locale::classic() | |
238e3a40 | 287 | { |
c755e77d | 288 | _S_initialize(); |
238e3a40 | 289 | return *(new (&c_locale) locale(_S_classic)); |
c755e77d BK |
290 | } |
291 | ||
292 | void | |
32ade559 | 293 | locale::_S_initialize_once() throw() |
c755e77d BK |
294 | { |
295 | // 2 references. | |
296 | // One reference for _S_classic, one for _S_global | |
297 | _S_classic = new (&c_locale_impl) _Impl(2); | |
298 | _S_global = _S_classic; | |
c755e77d BK |
299 | } |
300 | ||
301 | void | |
302 | locale::_S_initialize() | |
303 | { | |
304 | #ifdef __GTHREADS | |
305 | if (__gthread_active_p()) | |
306 | __gthread_once(&_S_once, _S_initialize_once); | |
c755e77d | 307 | #endif |
8f4c7b67 AT |
308 | if (!_S_classic) |
309 | _S_initialize_once(); | |
c755e77d BK |
310 | } |
311 | ||
312 | // Definitions for static const data members of locale::_Impl | |
313 | const locale::id* const | |
314 | locale::_Impl::_S_id_ctype[] = | |
315 | { | |
316 | &std::ctype<char>::id, | |
317 | &codecvt<char, char, mbstate_t>::id, | |
318 | #ifdef _GLIBCXX_USE_WCHAR_T | |
319 | &std::ctype<wchar_t>::id, | |
320 | &codecvt<wchar_t, char, mbstate_t>::id, | |
321 | #endif | |
322 | 0 | |
323 | }; | |
324 | ||
325 | const locale::id* const | |
326 | locale::_Impl::_S_id_numeric[] = | |
327 | { | |
328 | &num_get<char>::id, | |
329 | &num_put<char>::id, | |
330 | &numpunct<char>::id, | |
331 | #ifdef _GLIBCXX_USE_WCHAR_T | |
332 | &num_get<wchar_t>::id, | |
333 | &num_put<wchar_t>::id, | |
334 | &numpunct<wchar_t>::id, | |
335 | #endif | |
336 | 0 | |
337 | }; | |
338 | ||
339 | const locale::id* const | |
340 | locale::_Impl::_S_id_collate[] = | |
341 | { | |
342 | &std::collate<char>::id, | |
343 | #ifdef _GLIBCXX_USE_WCHAR_T | |
344 | &std::collate<wchar_t>::id, | |
345 | #endif | |
346 | 0 | |
347 | }; | |
348 | ||
349 | const locale::id* const | |
350 | locale::_Impl::_S_id_time[] = | |
351 | { | |
352 | &__timepunct<char>::id, | |
353 | &time_get<char>::id, | |
354 | &time_put<char>::id, | |
355 | #ifdef _GLIBCXX_USE_WCHAR_T | |
356 | &__timepunct<wchar_t>::id, | |
357 | &time_get<wchar_t>::id, | |
358 | &time_put<wchar_t>::id, | |
359 | #endif | |
360 | 0 | |
361 | }; | |
362 | ||
363 | const locale::id* const | |
364 | locale::_Impl::_S_id_monetary[] = | |
365 | { | |
366 | &money_get<char>::id, | |
367 | &money_put<char>::id, | |
368 | &moneypunct<char, false>::id, | |
369 | &moneypunct<char, true >::id, | |
370 | #ifdef _GLIBCXX_USE_WCHAR_T | |
371 | &money_get<wchar_t>::id, | |
372 | &money_put<wchar_t>::id, | |
373 | &moneypunct<wchar_t, false>::id, | |
374 | &moneypunct<wchar_t, true >::id, | |
375 | #endif | |
376 | 0 | |
377 | }; | |
378 | ||
379 | const locale::id* const | |
380 | locale::_Impl::_S_id_messages[] = | |
381 | { | |
382 | &std::messages<char>::id, | |
383 | #ifdef _GLIBCXX_USE_WCHAR_T | |
384 | &std::messages<wchar_t>::id, | |
385 | #endif | |
386 | 0 | |
387 | }; | |
34a2b755 | 388 | |
c755e77d BK |
389 | const locale::id* const* const |
390 | locale::_Impl::_S_facet_categories[] = | |
391 | { | |
392 | // Order must match the decl order in class locale. | |
393 | locale::_Impl::_S_id_ctype, | |
394 | locale::_Impl::_S_id_numeric, | |
395 | locale::_Impl::_S_id_collate, | |
396 | locale::_Impl::_S_id_time, | |
397 | locale::_Impl::_S_id_monetary, | |
398 | locale::_Impl::_S_id_messages, | |
399 | 0 | |
400 | }; | |
401 | ||
34a2b755 JW |
402 | #if _GLIBCXX_USE_DUAL_ABI |
403 | // Facets that are instantiated for both the COW and SSO std::string ABIs. | |
404 | // The COW ABI version must come first, followed by its SSO twin. | |
405 | const locale::id* const locale::_S_twinned_facets[] = { | |
406 | &::_ZNSt8numpunctIcE2idE, | |
407 | &numpunct<char>::id, | |
408 | &::_ZNSt7collateIcE2idE, | |
409 | &std::collate<char>::id, | |
410 | &::_ZNSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE, | |
411 | &time_get<char>::id, | |
412 | &::_ZNSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE, | |
413 | &money_get<char>::id, | |
414 | &::_ZNSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE, | |
415 | &money_put<char>::id, | |
416 | &::_ZNSt10moneypunctIcLb0EE2idE, | |
417 | &moneypunct<char, false>::id, | |
418 | &::_ZNSt10moneypunctIcLb1EE2idE, | |
419 | &moneypunct<char, true >::id, | |
420 | &::_ZNSt8messagesIcE2idE, | |
421 | &std::messages<char>::id, | |
422 | # ifdef _GLIBCXX_USE_WCHAR_T | |
423 | &::_ZNSt8numpunctIwE2idE, | |
424 | &numpunct<wchar_t>::id, | |
425 | &::_ZNSt7collateIwE2idE, | |
426 | &std::collate<wchar_t>::id, | |
427 | &::_ZNSt8time_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE, | |
428 | &time_get<wchar_t>::id, | |
429 | &::_ZNSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE, | |
430 | &money_get<wchar_t>::id, | |
431 | &::_ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE, | |
432 | &money_put<wchar_t>::id, | |
433 | &::_ZNSt10moneypunctIwLb0EE2idE, | |
434 | &moneypunct<wchar_t, false>::id, | |
435 | &::_ZNSt10moneypunctIwLb1EE2idE, | |
436 | &moneypunct<wchar_t, true >::id, | |
437 | &::_ZNSt8messagesIwE2idE, | |
438 | &std::messages<wchar_t>::id, | |
439 | # endif | |
440 | 0, 0 | |
441 | }; | |
442 | #endif | |
443 | ||
c755e77d BK |
444 | // Construct "C" _Impl. |
445 | locale::_Impl:: | |
446 | _Impl(size_t __refs) throw() | |
34a2b755 | 447 | : _M_refcount(__refs), _M_facets(0), _M_facets_size(num_facets), |
26c691a8 | 448 | _M_caches(0), _M_names(0) |
c755e77d | 449 | { |
38dbb2a5 JW |
450 | _M_facets = new (&facet_vec) const facet*[_M_facets_size](); |
451 | _M_caches = new (&cache_vec) const facet*[_M_facets_size](); | |
c755e77d | 452 | |
4df9c41d | 453 | // Name the categories. |
38dbb2a5 | 454 | _M_names = new (&name_vec) char*[_S_categories_size](); |
4df9c41d PC |
455 | _M_names[0] = new (&name_c[0]) char[2]; |
456 | std::memcpy(_M_names[0], locale::facet::_S_get_c_name(), 2); | |
c755e77d BK |
457 | |
458 | // This is needed as presently the C++ version of "C" locales | |
459 | // != data in the underlying locale model for __timepunct, | |
460 | // numpunct, and moneypunct. Also, the "C" locales must be | |
461 | // constructed in a way such that they are pre-allocated. | |
462 | // NB: Set locale::facets(ref) count to one so that each individual | |
463 | // facet is not destroyed when the locale (and thus locale::_Impl) is | |
464 | // destroyed. | |
465 | _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1)); | |
466 | _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1)); | |
467 | ||
468 | typedef __numpunct_cache<char> num_cache_c; | |
469 | num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2); | |
470 | _M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1)); | |
471 | ||
472 | _M_init_facet(new (&num_get_c) num_get<char>(1)); | |
473 | _M_init_facet(new (&num_put_c) num_put<char>(1)); | |
474 | _M_init_facet(new (&collate_c) std::collate<char>(1)); | |
475 | ||
fe932e50 PC |
476 | typedef __moneypunct_cache<char, false> money_cache_cf; |
477 | typedef __moneypunct_cache<char, true> money_cache_ct; | |
478 | money_cache_cf* __mpcf = new (&moneypunct_cache_cf) money_cache_cf(2); | |
c755e77d | 479 | _M_init_facet(new (&moneypunct_cf) moneypunct<char, false>(__mpcf, 1)); |
fe932e50 | 480 | money_cache_ct* __mpct = new (&moneypunct_cache_ct) money_cache_ct(2); |
c755e77d BK |
481 | _M_init_facet(new (&moneypunct_ct) moneypunct<char, true>(__mpct, 1)); |
482 | ||
483 | _M_init_facet(new (&money_get_c) money_get<char>(1)); | |
484 | _M_init_facet(new (&money_put_c) money_put<char>(1)); | |
485 | ||
486 | typedef __timepunct_cache<char> time_cache_c; | |
487 | time_cache_c* __tpc = new (&timepunct_cache_c) time_cache_c(2); | |
488 | _M_init_facet(new (&timepunct_c) __timepunct<char>(__tpc, 1)); | |
489 | ||
490 | _M_init_facet(new (&time_get_c) time_get<char>(1)); | |
491 | _M_init_facet(new (&time_put_c) time_put<char>(1)); | |
492 | _M_init_facet(new (&messages_c) std::messages<char>(1)); | |
493 | ||
494 | #ifdef _GLIBCXX_USE_WCHAR_T | |
495 | _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1)); | |
496 | _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1)); | |
497 | ||
498 | typedef __numpunct_cache<wchar_t> num_cache_w; | |
499 | num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2); | |
500 | _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1)); | |
501 | ||
502 | _M_init_facet(new (&num_get_w) num_get<wchar_t>(1)); | |
503 | _M_init_facet(new (&num_put_w) num_put<wchar_t>(1)); | |
504 | _M_init_facet(new (&collate_w) std::collate<wchar_t>(1)); | |
505 | ||
fe932e50 PC |
506 | typedef __moneypunct_cache<wchar_t, false> money_cache_wf; |
507 | typedef __moneypunct_cache<wchar_t, true> money_cache_wt; | |
508 | money_cache_wf* __mpwf = new (&moneypunct_cache_wf) money_cache_wf(2); | |
c755e77d | 509 | _M_init_facet(new (&moneypunct_wf) moneypunct<wchar_t, false>(__mpwf, 1)); |
fe932e50 | 510 | money_cache_wt* __mpwt = new (&moneypunct_cache_wt) money_cache_wt(2); |
c755e77d BK |
511 | _M_init_facet(new (&moneypunct_wt) moneypunct<wchar_t, true>(__mpwt, 1)); |
512 | ||
513 | _M_init_facet(new (&money_get_w) money_get<wchar_t>(1)); | |
514 | _M_init_facet(new (&money_put_w) money_put<wchar_t>(1)); | |
515 | ||
516 | typedef __timepunct_cache<wchar_t> time_cache_w; | |
517 | time_cache_w* __tpw = new (&timepunct_cache_w) time_cache_w(2); | |
518 | _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(__tpw, 1)); | |
519 | ||
520 | _M_init_facet(new (&time_get_w) time_get<wchar_t>(1)); | |
521 | _M_init_facet(new (&time_put_w) time_put<wchar_t>(1)); | |
522 | _M_init_facet(new (&messages_w) std::messages<wchar_t>(1)); | |
34a2b755 JW |
523 | #endif |
524 | ||
525 | #if _GLIBCXX_USE_DUAL_ABI | |
526 | facet* extra[] = { __npc, __mpcf, __mpct | |
527 | # ifdef _GLIBCXX_USE_WCHAR_T | |
528 | , __npw, __mpwf, __mpwt | |
529 | # endif | |
530 | }; | |
531 | ||
532 | _M_init_extra(extra); | |
533 | #endif | |
534 | ||
c755e77d BK |
535 | // This locale is safe to pre-cache, after all the facets have |
536 | // been created and installed. | |
537 | _M_caches[numpunct<char>::id._M_id()] = __npc; | |
538 | _M_caches[moneypunct<char, false>::id._M_id()] = __mpcf; | |
539 | _M_caches[moneypunct<char, true>::id._M_id()] = __mpct; | |
540 | _M_caches[__timepunct<char>::id._M_id()] = __tpc; | |
541 | #ifdef _GLIBCXX_USE_WCHAR_T | |
542 | _M_caches[numpunct<wchar_t>::id._M_id()] = __npw; | |
543 | _M_caches[moneypunct<wchar_t, false>::id._M_id()] = __mpwf; | |
544 | _M_caches[moneypunct<wchar_t, true>::id._M_id()] = __mpwt; | |
545 | _M_caches[__timepunct<wchar_t>::id._M_id()] = __tpw; | |
546 | #endif | |
547 | } | |
3cbc7af0 | 548 | |
12ffa228 BK |
549 | _GLIBCXX_END_NAMESPACE_VERSION |
550 | } // namespace |