]>
Commit | Line | Data |
---|---|---|
0214010c | 1 | // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
b2dad0e3 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 | |
6 | // Free Software Foundation; either version 2, or (at your option) | |
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 | ||
14 | // You should have received a copy of the GNU General Public License along | |
15 | // with this library; see the file COPYING. If not, write to the Free | |
16 | // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
17 | // USA. | |
18 | ||
19 | // As a special exception, you may use this file as part of a free software | |
20 | // library without restriction. Specifically, if other files instantiate | |
21 | // templates or use macros or inline functions from this file, or you compile | |
22 | // this file and link it with other files to produce an executable, this | |
23 | // file does not by itself cause the resulting executable to be covered by | |
24 | // the GNU General Public License. This exception does not however | |
25 | // invalidate any other reasons why the executable file might be covered by | |
26 | // the GNU General Public License. | |
27 | ||
28 | #include <bits/std_clocale.h> | |
29 | #include <bits/std_cstring.h> | |
30 | #include <bits/std_cassert.h> | |
31 | #include <bits/std_cctype.h> | |
32 | #include <bits/std_limits.h> | |
a6863e25 | 33 | #include <exception> |
b2dad0e3 BK |
34 | #include <bits/std_stdexcept.h> |
35 | #include <bits/std_locale.h> | |
36 | #include <bits/std_istream.h> | |
37 | #include <bits/std_ostream.h> | |
38 | #include <bits/std_vector.h> | |
39 | #include <bits/std_memory.h> // for auto_ptr | |
088eb5a2 | 40 | #ifdef _GLIBCPP_USE_WCHAR_T |
0517cb99 | 41 | # include <bits/std_cwctype.h> // for towupper, etc. |
088eb5a2 | 42 | #endif |
e4cc8659 | 43 | |
0a31609b BK |
44 | namespace std |
45 | { | |
1f46fc8e BK |
46 | // Defined in globals.cc. |
47 | extern locale::_Impl locale_impl_c; | |
48 | extern locale locale_c; | |
49 | ||
0479a462 | 50 | // Definitions for static const data members of locale. |
b75bedeb | 51 | const locale::category locale::none; |
b75bedeb | 52 | const locale::category locale::ctype; |
b75bedeb | 53 | const locale::category locale::numeric; |
0a31609b | 54 | const locale::category locale::collate; |
b75bedeb | 55 | const locale::category locale::time; |
0a31609b | 56 | const locale::category locale::monetary; |
b75bedeb BK |
57 | const locale::category locale::messages; |
58 | const locale::category locale::all; | |
59 | ||
b75bedeb | 60 | locale::_Impl* locale::_S_classic; |
d83c7eb4 | 61 | locale::_Impl* locale::_S_global; |
0214010c BK |
62 | const size_t locale::_S_num_categories; |
63 | const size_t locale::_S_num_facets; | |
0479a462 | 64 | |
0a31609b BK |
65 | // Definitions for locale::id of standard facets. |
66 | locale::id ctype<char>::id; | |
67 | locale::id codecvt<char, char, mbstate_t>::id; | |
0a31609b BK |
68 | |
69 | #ifdef _GLIBCPP_USE_WCHAR_T | |
70 | locale::id ctype<wchar_t>::id; | |
71 | locale::id codecvt<wchar_t, char, mbstate_t>::id; | |
0479a462 | 72 | #endif |
0a31609b BK |
73 | |
74 | // Definitions for static const data members of locale::id | |
75 | size_t locale::id::_S_highwater; // init'd to 0 by linker | |
76 | ||
77 | // Definitions for static const data members of locale::_Impl | |
0479a462 BK |
78 | const locale::id* const |
79 | locale::_Impl::_S_id_ctype[] = | |
80 | { | |
81 | &std::ctype<char>::id, | |
7dc08a20 | 82 | &codecvt<char, char, mbstate_t>::id, |
0479a462 | 83 | #ifdef _GLIBCPP_USE_WCHAR_T |
0a31609b | 84 | &std::ctype<wchar_t>::id, |
7dc08a20 | 85 | &codecvt<wchar_t, char, mbstate_t>::id, |
0479a462 BK |
86 | #endif |
87 | 0 | |
88 | }; | |
89 | ||
90 | const locale::id* const | |
0a31609b | 91 | locale::_Impl::_S_id_numeric[] = |
0479a462 | 92 | { |
0a31609b BK |
93 | &num_get<char>::id, |
94 | &num_put<char>::id, | |
95 | &numpunct<char>::id, | |
0479a462 | 96 | #ifdef _GLIBCPP_USE_WCHAR_T |
0a31609b BK |
97 | &num_get<wchar_t>::id, |
98 | &num_put<wchar_t>::id, | |
99 | &numpunct<wchar_t>::id, | |
0479a462 BK |
100 | #endif |
101 | 0 | |
102 | }; | |
0a31609b | 103 | |
0479a462 | 104 | const locale::id* const |
0a31609b | 105 | locale::_Impl::_S_id_collate[] = |
0479a462 | 106 | { |
0a31609b | 107 | &std::collate<char>::id, |
0479a462 | 108 | #ifdef _GLIBCPP_USE_WCHAR_T |
0a31609b | 109 | &std::collate<wchar_t>::id, |
0479a462 BK |
110 | #endif |
111 | 0 | |
112 | }; | |
0a31609b | 113 | |
0479a462 BK |
114 | const locale::id* const |
115 | locale::_Impl::_S_id_time[] = | |
116 | { | |
7dc08a20 | 117 | &time_get<char>::id, |
7dc08a20 | 118 | &time_put<char>::id, |
0479a462 | 119 | #ifdef _GLIBCPP_USE_WCHAR_T |
0a31609b | 120 | &time_get<wchar_t>::id, |
7dc08a20 | 121 | &time_put<wchar_t>::id, |
0479a462 BK |
122 | #endif |
123 | 0 | |
124 | }; | |
125 | ||
126 | const locale::id* const | |
0a31609b | 127 | locale::_Impl::_S_id_monetary[] = |
0479a462 | 128 | { |
0a31609b BK |
129 | &money_get<char>::id, |
130 | &money_put<char>::id, | |
131 | &moneypunct<char, false>::id, | |
132 | &moneypunct<char, true >::id, | |
0479a462 | 133 | #ifdef _GLIBCPP_USE_WCHAR_T |
0a31609b BK |
134 | &money_get<wchar_t>::id, |
135 | &money_put<wchar_t>::id, | |
136 | &moneypunct<wchar_t, false>::id, | |
137 | &moneypunct<wchar_t, true >::id, | |
0479a462 | 138 | #endif |
0a31609b BK |
139 | 0 |
140 | }; | |
141 | ||
142 | const locale::id* const | |
143 | locale::_Impl::_S_id_messages[] = | |
144 | { | |
145 | &std::messages<char>::id, | |
0479a462 | 146 | #ifdef _GLIBCPP_USE_WCHAR_T |
0a31609b | 147 | &std::messages<wchar_t>::id, |
0479a462 BK |
148 | #endif |
149 | 0 | |
150 | }; | |
151 | ||
152 | const locale::id* const* const | |
153 | locale::_Impl::_S_facet_categories[] = | |
154 | { | |
7dc08a20 | 155 | // Order must match the decl order in class locale. |
0479a462 | 156 | locale::_Impl::_S_id_ctype, |
0479a462 | 157 | locale::_Impl::_S_id_numeric, |
0a31609b | 158 | locale::_Impl::_S_id_collate, |
0479a462 | 159 | locale::_Impl::_S_id_time, |
0a31609b | 160 | locale::_Impl::_S_id_monetary, |
0479a462 BK |
161 | locale::_Impl::_S_id_messages, |
162 | 0 | |
163 | }; | |
164 | ||
0214010c BK |
165 | // Construct and return valid pattern consisting of some combination of: |
166 | // space none symbol sign value | |
167 | money_base::pattern | |
168 | money_base::_S_construct_pattern(char __preceeds, char __space, char __posn) | |
169 | { | |
170 | pattern __ret; | |
171 | ||
172 | // This insanely complicated routine attempts to construct a valid | |
173 | // pattern for use with monyepunct. A couple of invariants: | |
174 | ||
175 | // if (__preceeds) symbol -> value | |
176 | // else value -> symbol | |
177 | ||
178 | // if (__space) space | |
179 | // else none | |
180 | ||
181 | // none == never first | |
182 | // space never first or last | |
183 | ||
184 | // Any elegant implementations of this are welcome. | |
185 | switch (__posn) | |
186 | { | |
187 | case 1: | |
188 | // 1 The sign precedes the value and symbol. | |
189 | if (__space) | |
190 | { | |
191 | // Pattern starts with sign. | |
192 | if (__preceeds) | |
193 | { | |
194 | __ret.field[1] = symbol; | |
195 | __ret.field[2] = space; | |
196 | __ret.field[3] = value; | |
197 | } | |
198 | else | |
199 | { | |
200 | __ret.field[1] = value; | |
201 | __ret.field[2] = space; | |
202 | __ret.field[3] = symbol; | |
203 | } | |
204 | __ret.field[0] = sign; | |
205 | } | |
206 | else | |
207 | { | |
208 | // Pattern starts with sign and ends with none. | |
209 | if (__preceeds) | |
210 | { | |
211 | __ret.field[1] = symbol; | |
212 | __ret.field[2] = value; | |
213 | } | |
214 | else | |
215 | { | |
216 | __ret.field[1] = value; | |
217 | __ret.field[2] = symbol; | |
218 | } | |
219 | __ret.field[0] = sign; | |
220 | __ret.field[3] = none; | |
221 | } | |
222 | break; | |
223 | case 2: | |
224 | // 2 The sign follows the value and symbol. | |
225 | if (__space) | |
226 | { | |
227 | // Pattern either ends with sign. | |
228 | if (__preceeds) | |
229 | { | |
230 | __ret.field[0] = symbol; | |
231 | __ret.field[1] = space; | |
232 | __ret.field[2] = value; | |
233 | } | |
234 | else | |
235 | { | |
236 | __ret.field[0] = value; | |
237 | __ret.field[1] = space; | |
238 | __ret.field[2] = symbol; | |
239 | } | |
240 | __ret.field[3] = sign; | |
241 | } | |
242 | else | |
243 | { | |
244 | // Pattern ends with sign then none. | |
245 | if (__preceeds) | |
246 | { | |
247 | __ret.field[0] = symbol; | |
248 | __ret.field[1] = value; | |
249 | } | |
250 | else | |
251 | { | |
252 | __ret.field[0] = value; | |
253 | __ret.field[1] = symbol; | |
254 | } | |
255 | __ret.field[2] = sign; | |
256 | __ret.field[3] = none; | |
257 | } | |
258 | break; | |
259 | case 3: | |
260 | // 3 The sign immediately precedes the symbol. | |
261 | if (__space) | |
262 | { | |
263 | // Have space. | |
264 | if (__preceeds) | |
265 | { | |
266 | __ret.field[0] = sign; | |
267 | __ret.field[1] = symbol; | |
268 | __ret.field[2] = space; | |
269 | __ret.field[3] = value; | |
270 | } | |
271 | else | |
272 | { | |
273 | __ret.field[0] = value; | |
274 | __ret.field[1] = space; | |
275 | __ret.field[2] = sign; | |
276 | __ret.field[3] = symbol; | |
277 | } | |
278 | } | |
279 | else | |
280 | { | |
281 | // Have none. | |
282 | if (__preceeds) | |
283 | { | |
284 | __ret.field[0] = sign; | |
285 | __ret.field[1] = symbol; | |
286 | __ret.field[2] = value; | |
287 | } | |
288 | else | |
289 | { | |
290 | __ret.field[0] = value; | |
291 | __ret.field[1] = sign; | |
292 | __ret.field[2] = symbol; | |
293 | } | |
294 | __ret.field[3] = none; | |
295 | } | |
296 | break; | |
297 | case 4: | |
298 | // 4 The sign immediately follows the symbol. | |
299 | if (__space) | |
300 | { | |
301 | // Have space. | |
302 | if (__preceeds) | |
303 | { | |
304 | __ret.field[0] = symbol; | |
305 | __ret.field[1] = sign; | |
306 | __ret.field[2] = space; | |
307 | __ret.field[3] = value; | |
308 | } | |
309 | else | |
310 | { | |
311 | __ret.field[0] = value; | |
312 | __ret.field[1] = space; | |
313 | __ret.field[2] = symbol; | |
314 | __ret.field[3] = sign; | |
315 | } | |
316 | } | |
317 | else | |
318 | { | |
319 | // Have none. | |
320 | if (__preceeds) | |
321 | { | |
322 | __ret.field[0] = symbol; | |
323 | __ret.field[1] = sign; | |
324 | __ret.field[2] = value; | |
325 | } | |
326 | else | |
327 | { | |
328 | __ret.field[0] = value; | |
329 | __ret.field[1] = symbol; | |
330 | __ret.field[2] = sign; | |
331 | } | |
332 | __ret.field[3] = none; | |
333 | } | |
334 | break; | |
335 | default: | |
336 | ; | |
337 | } | |
338 | return __ret; | |
339 | } | |
340 | ||
341 | locale::~locale() throw() | |
342 | { _M_impl->_M_remove_reference(); } | |
343 | ||
344 | void | |
345 | locale::_M_coalesce(const locale& __base, const locale& __add, | |
346 | category __cat) | |
347 | { | |
348 | __cat = _S_normalize_category(__cat); | |
349 | _M_impl = new _Impl(*__base._M_impl, 1); | |
350 | ||
351 | try | |
352 | { _M_impl->_M_replace_categories(__add._M_impl, __cat); } | |
353 | catch (...) | |
354 | { | |
355 | _M_impl->_M_remove_reference(); | |
e2c09482 | 356 | __throw_exception_again; |
0214010c BK |
357 | } |
358 | } | |
359 | ||
360 | locale::locale() throw() | |
361 | { | |
362 | _S_initialize(); | |
363 | (_M_impl = _S_global)->_M_add_reference(); | |
364 | } // XXX MT | |
365 | ||
366 | locale::locale(const locale& __other) throw() | |
367 | { (_M_impl = __other._M_impl)->_M_add_reference(); } | |
368 | ||
1f46fc8e BK |
369 | // This is used to initialize global and classic locales, and |
370 | // assumes that the _Impl objects are constructed correctly. | |
371 | locale::locale(_Impl* __ip) throw() : _M_impl(__ip) | |
372 | { } | |
0214010c BK |
373 | |
374 | locale::locale(const char* __s) | |
375 | { | |
376 | if (__s) | |
377 | { | |
213c2316 | 378 | _S_initialize(); |
0214010c BK |
379 | if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0) |
380 | (_M_impl = _S_classic)->_M_add_reference(); | |
381 | else | |
382 | _M_impl = new _Impl(__s, 1); | |
383 | } | |
384 | else | |
e2c09482 | 385 | __throw_runtime_error("attempt to create locale from NULL name"); |
0214010c BK |
386 | } |
387 | ||
388 | locale::locale(const locale& __base, const char* __s, category __cat) | |
389 | { | |
390 | // NB: There are complicated, yet more efficient ways to do | |
391 | // this. Building up locales on a per-category way is tedious, so | |
392 | // let's do it this way until people complain. | |
393 | locale __add(__s); | |
394 | _M_coalesce(__base, __add, __cat); | |
395 | } | |
396 | ||
397 | locale::locale(const locale& __base, const locale& __add, category __cat) | |
398 | { _M_coalesce(__base, __add, __cat); } | |
399 | ||
400 | bool | |
401 | locale::operator==(const locale& __rhs) const throw() | |
402 | { | |
403 | string __name = this->name(); | |
404 | return (_M_impl == __rhs._M_impl | |
405 | || (__name != "*" && __name == __rhs.name())); | |
406 | } | |
407 | ||
408 | const locale& | |
409 | locale::operator=(const locale& __other) throw() | |
410 | { | |
411 | __other._M_impl->_M_add_reference(); | |
412 | _M_impl->_M_remove_reference(); | |
413 | _M_impl = __other._M_impl; | |
414 | return *this; | |
415 | } | |
416 | ||
417 | locale | |
418 | locale::global(const locale& __other) | |
419 | { | |
420 | // XXX MT | |
421 | _S_initialize(); | |
1f46fc8e | 422 | _Impl* __old = _S_global; |
0214010c | 423 | __other._M_impl->_M_add_reference(); |
0214010c BK |
424 | _S_global = __other._M_impl; |
425 | if (_S_global->_M_check_same_name() && _S_global->_M_names[0] != "*") | |
426 | setlocale(LC_ALL, __other.name().c_str()); | |
1f46fc8e BK |
427 | |
428 | // Reference count sanity check: one reference removed for the | |
429 | // subsition of __other locale, one added by return-by-value. Net | |
430 | // difference: zero. When the returned locale object's destrutor | |
431 | // is called, then the reference count is decremented and possibly | |
432 | // destroyed. | |
433 | return locale(__old); | |
0214010c BK |
434 | } |
435 | ||
436 | string | |
437 | locale::name() const | |
438 | { | |
439 | string __ret; | |
440 | // Need some kind of separator character. This one was pretty much | |
441 | // arbitrarily chosen as to not conflict with glibc locales: the | |
442 | // exact formatting is not set in stone. | |
443 | const char __separator = '|'; | |
444 | ||
445 | if (_M_impl->_M_check_same_name()) | |
446 | __ret = _M_impl->_M_names[0]; | |
447 | else | |
448 | { | |
449 | for (size_t i = 0; i < _S_num_categories; ++i) | |
450 | __ret += __separator + _M_impl->_M_names[i]; | |
451 | } | |
452 | return __ret; | |
453 | } | |
454 | ||
455 | locale const& | |
456 | locale::classic() | |
457 | { | |
0214010c BK |
458 | // XXX MT |
459 | if (!_S_classic) | |
460 | { | |
461 | try | |
462 | { | |
463 | // 26 Standard facets, 2 references. | |
464 | // One reference for _M_classic, one for _M_global | |
1f46fc8e | 465 | _S_classic = new (&locale_impl_c) _Impl("C", 2); |
0214010c | 466 | _S_global = _S_classic; |
1f46fc8e | 467 | new (&locale_c) locale(_S_classic); |
0214010c BK |
468 | } |
469 | catch(...) | |
470 | { | |
1f46fc8e BK |
471 | // Just call destructor, so that locale_impl_c's memory is |
472 | // not deallocated via a call to delete. | |
0214010c | 473 | if (_S_classic) |
1f46fc8e | 474 | _S_classic->~_Impl(); |
0214010c | 475 | _S_classic = _S_global = 0; |
e2c09482 | 476 | __throw_exception_again; |
0214010c BK |
477 | } |
478 | } | |
1f46fc8e | 479 | return locale_c; |
0214010c BK |
480 | } |
481 | ||
482 | locale::category | |
483 | locale::_S_normalize_category(category __cat) | |
484 | { | |
758c46c9 | 485 | int __ret = 0; |
0214010c BK |
486 | if (__cat == none || (__cat & all) && !(__cat & ~all)) |
487 | __ret = __cat; | |
488 | else | |
489 | { | |
490 | // NB: May be a C-style "LC_ALL" category; convert. | |
491 | switch (__cat) | |
492 | { | |
493 | case LC_COLLATE: | |
494 | __ret = collate; | |
495 | break; | |
496 | case LC_CTYPE: | |
497 | __ret = ctype; | |
498 | break; | |
499 | case LC_MONETARY: | |
500 | __ret = monetary; | |
501 | break; | |
502 | case LC_NUMERIC: | |
503 | __ret = numeric; | |
504 | break; | |
505 | case LC_TIME: | |
506 | __ret = time; | |
507 | break; | |
508 | #ifdef _GLIBCPP_HAVE_LC_MESSAGES | |
509 | case LC_MESSAGES: | |
510 | __ret = messages; | |
511 | break; | |
512 | #endif | |
513 | case LC_ALL: | |
514 | __ret = all; | |
515 | break; | |
516 | default: | |
e2c09482 | 517 | __throw_runtime_error("bad locale category"); |
0214010c BK |
518 | } |
519 | } | |
520 | return __ret; | |
521 | } | |
522 | ||
523 | locale::facet:: | |
1f46fc8e | 524 | facet(size_t __refs) throw() : _M_references(__refs) |
0214010c BK |
525 | { } |
526 | ||
527 | void | |
528 | locale::facet:: | |
529 | _M_add_reference() throw() | |
530 | { ++_M_references; } // XXX MT | |
531 | ||
532 | void | |
533 | locale::facet:: | |
534 | _M_remove_reference() throw() | |
535 | { | |
1f46fc8e | 536 | if (_M_references-- == 0) |
0214010c BK |
537 | { |
538 | try | |
1f46fc8e | 539 | { delete this; } |
0214010c BK |
540 | catch (...) |
541 | { } | |
542 | } | |
543 | } | |
544 | ||
545 | // Definitions for static const data members of ctype_base. | |
546 | const ctype_base::mask ctype_base::space; | |
547 | const ctype_base::mask ctype_base::print; | |
548 | const ctype_base::mask ctype_base::cntrl; | |
549 | const ctype_base::mask ctype_base::upper; | |
550 | const ctype_base::mask ctype_base::lower; | |
551 | const ctype_base::mask ctype_base::alpha; | |
552 | const ctype_base::mask ctype_base::digit; | |
553 | const ctype_base::mask ctype_base::punct; | |
554 | const ctype_base::mask ctype_base::xdigit; | |
555 | const ctype_base::mask ctype_base::alnum; | |
556 | const ctype_base::mask ctype_base::graph; | |
557 | ||
558 | // Platform-specific initialization code for ctype tables. | |
559 | #include <bits/ctype_noninline.h> | |
560 | ||
561 | const size_t ctype<char>::table_size; | |
562 | ||
563 | ctype<char>::~ctype() | |
564 | { if (_M_del) delete[] this->table(); } | |
565 | ||
566 | // These are dummy placeholders as these virtual functions are never called. | |
567 | bool | |
568 | ctype<char>::do_is(mask, char_type) const | |
569 | { return false; } | |
570 | ||
571 | const char* | |
572 | ctype<char>::do_is(const char_type* __c, const char_type*, mask*) const | |
573 | { return __c; } | |
574 | ||
575 | const char* | |
576 | ctype<char>::do_scan_is(mask, const char_type* __c, const char_type*) const | |
577 | { return __c; } | |
578 | ||
579 | const char* | |
580 | ctype<char>::do_scan_not(mask, const char_type* __c, const char_type*) const | |
581 | { return __c; } | |
582 | ||
583 | char | |
584 | ctype<char>::do_widen(char __c) const | |
585 | { return __c; } | |
586 | ||
587 | const char* | |
fdf1b60d | 588 | ctype<char>::do_widen(const char* __lo, const char* __hi, char* __dest) const |
0214010c | 589 | { |
fdf1b60d BK |
590 | memcpy(__dest, __lo, __hi - __lo); |
591 | return __hi; | |
0214010c BK |
592 | } |
593 | ||
594 | char | |
595 | ctype<char>::do_narrow(char __c, char /*__dfault*/) const | |
596 | { return __c; } | |
597 | ||
598 | const char* | |
fdf1b60d | 599 | ctype<char>::do_narrow(const char* __lo, const char* __hi, |
0214010c BK |
600 | char /*__dfault*/, char* __dest) const |
601 | { | |
fdf1b60d BK |
602 | memcpy(__dest, __lo, __hi - __lo); |
603 | return __hi; | |
0214010c BK |
604 | } |
605 | ||
31bfa177 | 606 | template<> |
0214010c BK |
607 | ctype_byname<char>::ctype_byname(const char* /*__s*/, size_t __refs) |
608 | : ctype<char>(new mask[table_size], true, __refs) | |
609 | { } | |
610 | ||
0479a462 BK |
611 | // Definitions for static const data members of money_base |
612 | const money_base::pattern | |
0214010c | 613 | money_base::_S_default_pattern = {{symbol, sign, none, value}}; |
0479a462 BK |
614 | |
615 | template<> | |
616 | _Format_cache<char>::_Format_cache() | |
617 | : _M_valid(true), | |
618 | _M_decimal_point('.'), _M_thousands_sep(','), | |
619 | _M_truename("true"), _M_falsename("false"), _M_use_grouping(false) | |
620 | { } | |
621 | ||
622 | #ifdef _GLIBCPP_USE_WCHAR_T | |
623 | template<> | |
624 | _Format_cache<wchar_t>::_Format_cache() | |
625 | : _M_valid(true), | |
626 | _M_decimal_point(L'.'), _M_thousands_sep(L','), | |
627 | _M_truename(L"true"), _M_falsename(L"false"), _M_use_grouping(false) | |
628 | { } | |
629 | #endif | |
630 | ||
631 | template<> | |
632 | const ctype<char>& | |
697649ea | 633 | use_facet<ctype<char> >(const locale& __loc) |
0479a462 BK |
634 | { |
635 | size_t __i = ctype<char>::id._M_index; | |
636 | const locale::_Impl* __tmp = __loc._M_impl; | |
637 | return static_cast<const ctype<char>&>(* (*(__tmp->_M_facets))[__i]); | |
638 | } | |
639 | ||
640 | #ifdef _GLIBCPP_USE_WCHAR_T | |
641 | template<> | |
642 | const ctype<wchar_t>& | |
697649ea | 643 | use_facet<ctype<wchar_t> >(const locale& __loc) |
0479a462 BK |
644 | { |
645 | size_t __i = ctype<wchar_t>::id._M_index; | |
646 | const locale::_Impl* __tmp = __loc._M_impl; | |
647 | return static_cast<const ctype<wchar_t>&>(* (*(__tmp->_M_facets))[__i]); | |
648 | } | |
649 | #endif | |
650 | ||
651 | template<> | |
652 | void | |
653 | num_get<char, istreambuf_iterator<char> >:: | |
654 | _M_extract(istreambuf_iterator<char> __beg, | |
655 | istreambuf_iterator<char> __end, ios_base& __io, | |
656 | ios_base::iostate& __err, char* __xtrc, int& __base, | |
657 | bool __fp) const | |
658 | { | |
659 | typedef _Format_cache<char> __cache_type; | |
660 | ||
661 | // Prepare for possible failure | |
662 | __xtrc[0] = '\0'; | |
663 | ||
664 | // Stage 1: determine a conversion specifier. | |
665 | ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; | |
666 | if (__basefield == ios_base::dec) | |
667 | __base = 10; | |
668 | else if (__basefield == ios_base::oct) | |
669 | __base = 8; | |
670 | else if (__basefield == ios_base::hex) | |
671 | __base = 16; | |
672 | else | |
673 | __base = 0; | |
674 | // As far as I can tell, bases other than 10 are not available for | |
675 | // floating point types | |
676 | if (__fp) | |
677 | __base = 10; | |
678 | ||
679 | // Stage 2: extract characters. | |
680 | __cache_type const* __fmt = __cache_type::_S_get(__io); | |
39003c99 | 681 | |
0479a462 | 682 | // Fail quickly if !__valid |
39003c99 | 683 | if (__beg == __end) |
0479a462 BK |
684 | { |
685 | __err |= (ios_base::eofbit | ios_base::failbit); | |
686 | return; | |
687 | } | |
688 | ||
689 | // Acceptable formats for numbers here are based on 22.2.3.1 | |
690 | string __grp; | |
691 | int __sep_pos = 0; | |
692 | int __pos = 0; | |
693 | const char* __lits = __fmt->_S_literals; | |
694 | char __c = *__beg; | |
695 | ||
696 | // Check first for sign | |
697 | bool __testsign = false; | |
698 | if ((__c == __lits[__cache_type::_S_minus]) | |
39003c99 | 699 | || (__c == __lits[__cache_type::_S_plus])) |
0479a462 | 700 | { |
39003c99 | 701 | __testsign = true; |
0479a462 BK |
702 | __xtrc[__pos++] = __c; |
703 | ++__beg; | |
39003c99 BK |
704 | __c = * __beg; |
705 | ||
706 | // Whitespace may follow a sign | |
707 | while ((__beg != __end) && (isspace(__c))) | |
708 | { | |
709 | ++__beg; | |
710 | __c = *__beg; | |
711 | } | |
0479a462 BK |
712 | |
713 | // There had better be more to come... | |
714 | if (__beg == __end) | |
715 | { | |
716 | __xtrc[__pos] = '\0'; | |
717 | __err |= (ios_base::eofbit | ios_base::failbit); | |
718 | return; | |
719 | } | |
720 | } | |
721 | ||
39003c99 BK |
722 | // Now check if first character is a zero. |
723 | bool __testzero = false; | |
0479a462 BK |
724 | if (__c == __lits[__cache_type::_S_digits]) |
725 | { | |
726 | __testzero = true; | |
727 | ++__beg; | |
39003c99 | 728 | __c = *__beg; |
0479a462 BK |
729 | |
730 | // We have to check for __beg == __end here. If so, | |
731 | // a plain '0' (possibly with a sign) can be got rid of now | |
732 | if (__beg == __end) | |
733 | { | |
39003c99 | 734 | __xtrc[__pos++] = __lits[__cache_type::_S_digits]; |
0479a462 BK |
735 | __xtrc[__pos] = '\0'; |
736 | __err |= ios_base::eofbit; | |
737 | return; | |
738 | } | |
739 | ||
740 | // Figure out base for integer types only | |
741 | // Based on Table 55 of 22.2.2.1.2 | |
742 | if (!__fp && __base != 10 && __base != 8) | |
743 | { | |
744 | // Here, __base == 0 or 16 | |
0479a462 BK |
745 | if ((__c == __lits[__cache_type::_S_x]) |
746 | || (__c == __lits[__cache_type::_S_X])) | |
747 | { | |
748 | ++__beg; | |
39003c99 | 749 | __c = *__beg; |
0479a462 BK |
750 | __base = 16; |
751 | __testzero = false; // "0x" is not a leading zero | |
752 | } | |
753 | else if (__base == 0) | |
754 | __base = 8; | |
755 | } | |
756 | ||
757 | // Remove any more leading zeros | |
758 | while (__beg != __end) | |
759 | { | |
39003c99 | 760 | if (__c == __lits[__cache_type::_S_digits]) |
0479a462 BK |
761 | { |
762 | ++__beg; | |
39003c99 | 763 | __c = *__beg; |
0479a462 BK |
764 | __testzero = true; |
765 | } | |
766 | else | |
767 | break; | |
768 | } | |
769 | } | |
770 | else if (__base == 0) // 1st character is not zero | |
771 | __base = 10; | |
772 | ||
773 | // We now seek "units", i.e. digits and thousands separators. | |
774 | // We may need to know if anything is found here. A leading zero | |
775 | // (removed by now) would count. | |
776 | bool __testunits = __testzero; | |
39003c99 | 777 | while (__beg != __end) |
0479a462 | 778 | { |
39003c99 | 779 | const char* __p = strchr(__lits, __c); |
0479a462 BK |
780 | |
781 | // NB: strchr returns true for __c == 0x0 | |
39003c99 BK |
782 | if (__p && __c |
783 | &&((__p >= &__lits[__cache_type::_S_digits] | |
784 | && __p < &__lits[__cache_type::_S_digits + __base]) | |
785 | || (__p >= &__lits[__cache_type::_S_udigits] | |
786 | && __p < &__lits[__cache_type::_S_udigits + __base]))) | |
787 | { | |
788 | // Try first for acceptable digit; record it if found. | |
789 | __xtrc[__pos++] = __c; | |
790 | ++__sep_pos; | |
791 | __testunits = true; | |
792 | ++__beg; | |
793 | __c = *__beg; | |
794 | } | |
795 | else if (__c == __fmt->_M_thousands_sep && __fmt->_M_use_grouping) | |
796 | { | |
0479a462 BK |
797 | // NB: Thousands separator at the beginning of a string |
798 | // is a no-no, as is two consecutive thousands | |
39003c99 | 799 | // separators. |
0479a462 BK |
800 | if (__sep_pos) |
801 | { | |
802 | __grp += static_cast<char>(__sep_pos); | |
803 | __sep_pos = 0; | |
39003c99 BK |
804 | ++__beg; |
805 | __c = *__beg; | |
0479a462 BK |
806 | } |
807 | else | |
39003c99 BK |
808 | { |
809 | __err |= ios_base::failbit; | |
810 | break; | |
811 | } | |
0479a462 | 812 | } |
39003c99 BK |
813 | else |
814 | // Not a valid input item. | |
815 | break; | |
0479a462 BK |
816 | } |
817 | ||
818 | // Digit grouping is checked. If _M_groupings() doesn't | |
819 | // match, then get very very upset, and set failbit. | |
820 | if (__fmt->_M_use_grouping && !__grp.empty()) | |
821 | { | |
822 | // Add the ending grouping | |
823 | __grp += static_cast<char>(__sep_pos); | |
824 | ||
825 | // __grp is parsed L to R | |
826 | // 1,222,444 == __grp of "/1/3/3" | |
827 | // __fmt->_M_grouping is parsed R to L | |
828 | // 1,222,444 == __fmt->_M_grouping of "/3" == "/3/3/3" | |
829 | int __i = 0; | |
830 | int __j = 0; | |
831 | const int __len = __fmt->_M_grouping.size(); | |
832 | int __n = __grp.size(); | |
833 | bool __test = true; | |
834 | ||
835 | // Parsed number groupings have to match the | |
836 | // numpunct::grouping string exactly, starting at the | |
837 | // right-most point of the parsed sequence of elements ... | |
838 | while (__test && __i < __n - 1) | |
839 | for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) | |
840 | __test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1]; | |
841 | // ... but the last parsed grouping can be <= numpunct | |
842 | // grouping. | |
843 | __j == __len ? __j = 0 : __j; | |
844 | __test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1]; | |
845 | ||
846 | if (!__test) | |
847 | { | |
848 | __err |= ios_base::failbit; | |
849 | __xtrc[__pos] = '\0'; | |
850 | if (__beg == __end) | |
851 | __err |= ios_base::eofbit; | |
852 | return; | |
853 | } | |
854 | } | |
855 | ||
856 | // If there was nothing but zeros, put one in the output string | |
857 | if (__testzero && (__pos == 0 || (__pos == 1 && __testsign))) | |
858 | __xtrc[__pos++] = __lits[__cache_type::_S_digits]; | |
859 | ||
860 | // That's it for integer types. Remaining code is for floating point | |
861 | if (__fp && __beg != __end) | |
862 | { | |
0479a462 BK |
863 | // Check first for decimal point. There MUST be one if |
864 | // __testunits is false. | |
865 | bool __testdec = false; // Is there a decimal point | |
866 | // with digits following it? | |
867 | if (__c == __fmt->_M_decimal_point) | |
868 | { | |
869 | __xtrc[__pos++] = '.'; | |
870 | ++__beg; | |
39003c99 BK |
871 | __c = *__beg; |
872 | ||
0479a462 BK |
873 | // Now we get any digits after the decimal point |
874 | // There MUST be some if __testunits is false. | |
875 | while (__beg != __end) | |
876 | { | |
39003c99 | 877 | const char* __p = strchr(__lits, __c); |
0479a462 BK |
878 | if ((__p >= &__lits[__cache_type::_S_digits] |
879 | && __p < &__lits[__cache_type::_S_digits + __base]) | |
880 | || (__p >= &__lits[__cache_type::_S_udigits] | |
881 | && __p < &__lits[__cache_type::_S_udigits + __base])) | |
882 | { | |
883 | __xtrc[__pos++] = __c; | |
884 | ++__beg; | |
39003c99 | 885 | __c = *__beg; |
0479a462 BK |
886 | __testdec = true; |
887 | } | |
888 | else | |
889 | break; | |
890 | } | |
891 | } | |
892 | if (!__testunits && !__testdec) // Ill formed | |
893 | { | |
894 | __err |= ios_base::failbit; | |
895 | __xtrc[__pos] = '\0'; | |
896 | if (__beg == __end) | |
897 | __err |= ios_base::eofbit; | |
898 | return; | |
899 | } | |
900 | ||
901 | // Now we may find an exponent | |
902 | if (__beg != __end) | |
903 | { | |
0479a462 BK |
904 | if ((__c == __lits[__cache_type::_S_ee]) |
905 | || (__c == __lits[__cache_type::_S_Ee])) | |
906 | { | |
907 | __xtrc[__pos++] = __c; | |
908 | ++__beg; | |
39003c99 BK |
909 | __c = *__beg; |
910 | ||
0479a462 BK |
911 | // Now there may be a sign |
912 | if (__beg != __end) | |
913 | { | |
0479a462 BK |
914 | if ((__c == __lits[__cache_type::_S_minus]) |
915 | || (__c == __lits[__cache_type::_S_plus])) | |
916 | { | |
917 | __xtrc[__pos++] = __c; | |
918 | ++__beg; | |
39003c99 | 919 | __c = *__beg; |
0479a462 | 920 | // whitespace may follow a sign |
39003c99 BK |
921 | while ((__beg != __end) && (isspace(__c))) |
922 | { | |
923 | ++__beg; | |
924 | __c = *__beg; | |
925 | } | |
0479a462 BK |
926 | } |
927 | } | |
928 | // And now there must be some digits | |
929 | if (__beg == __end) | |
930 | { | |
931 | __xtrc[__pos] = '\0'; | |
932 | __err |= (ios_base::eofbit | ios_base::failbit); | |
933 | return; | |
934 | } | |
935 | while (__beg != __end) | |
936 | { | |
39003c99 | 937 | const char* __p = strchr(__lits, __c); |
0479a462 BK |
938 | if ((__p >= &__lits[__cache_type::_S_digits] |
939 | && __p < &__lits[__cache_type::_S_digits + __base]) | |
940 | || (__p >= &__lits[__cache_type::_S_udigits] | |
941 | && __p < &__lits[__cache_type::_S_udigits + __base])) | |
942 | { | |
943 | __xtrc[__pos++] = __c; | |
944 | ++__beg; | |
39003c99 | 945 | __c = *__beg; |
0479a462 BK |
946 | } |
947 | else | |
948 | break; | |
949 | } | |
950 | } | |
951 | } | |
952 | // Finally, that's it for floating point | |
953 | } | |
954 | ||
955 | // Finish up | |
956 | __xtrc[__pos] = '\0'; | |
957 | if (__beg == __end) | |
958 | __err |= ios_base::eofbit; | |
959 | } | |
960 | ||
961 | // The following code uses sprintf() to convert floating point | |
962 | // values for insertion into a stream. The current implementation | |
963 | // replicates the code in _S_pad_numeric() (in _S_output_float()) in | |
964 | // order to prevent having to create a "wide" buffer in addition to | |
965 | // the "narrow" buffer passed to sprintf(). An optimization would be | |
966 | // to replace sprintf() with code that works directly on a wide | |
967 | // buffer and then use _S_pad_numeric() to do the padding. It would | |
968 | // be good to replace sprintf() anyway to avoid accidental buffer | |
969 | // overruns and to gain back the efficiency that C++ provides by | |
970 | // knowing up front the type of the values to insert. This | |
971 | // implementation follows the C++ standard fairly directly as | |
972 | // outlined in 22.2.2.2 [lib.locale.num.put] | |
973 | bool | |
72ed2836 BK |
974 | __build_float_format(ios_base& __io, char* __fptr, char __modifier, |
975 | streamsize __prec) | |
0479a462 BK |
976 | { |
977 | bool __incl_prec = false; | |
978 | ios_base::fmtflags __flags = __io.flags(); | |
979 | *__fptr++ = '%'; | |
980 | // [22.2.2.2.2] Table 60 | |
981 | if (__flags & ios_base::showpos) | |
982 | *__fptr++ = '+'; | |
983 | if (__flags & ios_base::showpoint) | |
984 | *__fptr++ = '#'; | |
985 | // As per [22.2.2.2.2.11] | |
986 | if (__flags & ios_base::fixed || __prec > 0) | |
987 | { | |
988 | *__fptr++ = '.'; | |
989 | *__fptr++ = '*'; | |
990 | __incl_prec = true; | |
991 | } | |
992 | if (__modifier) | |
993 | *__fptr++ = __modifier; | |
994 | ios_base::fmtflags __fltfield = __flags & ios_base::floatfield; | |
995 | // [22.2.2.2.2] Table 58 | |
996 | if (__fltfield == ios_base::fixed) | |
997 | *__fptr++ = 'f'; | |
998 | else if (__fltfield == ios_base::scientific) | |
999 | *__fptr++ = (__flags & ios_base::uppercase) ? 'E' : 'e'; | |
1000 | else | |
1001 | *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g'; | |
1002 | *__fptr = '\0'; | |
1003 | return __incl_prec; | |
1004 | } | |
1005 | ||
31bfa177 | 1006 | template<> |
b75bedeb BK |
1007 | moneypunct_byname<char, false>::moneypunct_byname(const char* /*__s*/, |
1008 | size_t __refs) | |
cc4316b5 | 1009 | : moneypunct<char, false>(__refs) { } |
b2dad0e3 | 1010 | |
31bfa177 | 1011 | template<> |
b75bedeb BK |
1012 | moneypunct_byname<char, true>::moneypunct_byname(const char* /*__s*/, |
1013 | size_t __refs) | |
cc4316b5 | 1014 | : moneypunct<char, true>(__refs) { } |
b2dad0e3 | 1015 | |
b2dad0e3 | 1016 | #ifdef _GLIBCPP_USE_WCHAR_T |
167ed88f BK |
1017 | ctype<wchar_t>::__wmask_type |
1018 | ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const | |
1019 | { | |
1020 | __wmask_type __ret; | |
1021 | switch (__m) | |
1022 | { | |
1023 | case space: | |
1024 | __ret = wctype("space"); | |
1025 | break; | |
1026 | case print: | |
1027 | __ret = wctype("print"); | |
1028 | break; | |
1029 | case cntrl: | |
1030 | __ret = wctype("cntrl"); | |
1031 | break; | |
1032 | case upper: | |
1033 | __ret = wctype("upper"); | |
1034 | break; | |
1035 | case lower: | |
1036 | __ret = wctype("lower"); | |
1037 | break; | |
1038 | case alpha: | |
1039 | __ret = wctype("alpha"); | |
1040 | break; | |
1041 | case digit: | |
1042 | __ret = wctype("digit"); | |
1043 | break; | |
1044 | case punct: | |
1045 | __ret = wctype("punct"); | |
1046 | break; | |
1047 | case xdigit: | |
1048 | __ret = wctype("xdigit"); | |
1049 | break; | |
1050 | case alnum: | |
1051 | __ret = wctype("alnum"); | |
1052 | break; | |
1053 | case graph: | |
1054 | __ret = wctype("graph"); | |
1055 | break; | |
1056 | default: | |
1057 | __ret = 0; | |
1058 | } | |
1059 | return __ret; | |
1060 | }; | |
1061 | ||
205c6f17 | 1062 | ctype<wchar_t>::~ctype() { } |
b2dad0e3 | 1063 | |
088eb5a2 BK |
1064 | // NB: These ctype<wchar_t> methods are not configuration-specific, |
1065 | // unlike the ctype<char> bits. | |
167ed88f BK |
1066 | ctype<wchar_t>::ctype(size_t __refs) : __ctype_abstract_base<wchar_t>(__refs) |
1067 | { } | |
088eb5a2 BK |
1068 | |
1069 | wchar_t | |
1070 | ctype<wchar_t>::do_toupper(wchar_t __c) const | |
8c81504d | 1071 | { return towupper(__c); } |
088eb5a2 BK |
1072 | |
1073 | const wchar_t* | |
fdf1b60d | 1074 | ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const |
088eb5a2 | 1075 | { |
fdf1b60d | 1076 | while (__lo < __hi) |
088eb5a2 | 1077 | { |
fdf1b60d BK |
1078 | *__lo = towupper(*__lo); |
1079 | ++__lo; | |
088eb5a2 | 1080 | } |
fdf1b60d | 1081 | return __hi; |
088eb5a2 BK |
1082 | } |
1083 | ||
1084 | wchar_t | |
1085 | ctype<wchar_t>::do_tolower(wchar_t __c) const | |
8c81504d | 1086 | { return towlower(__c); } |
088eb5a2 BK |
1087 | |
1088 | const wchar_t* | |
fdf1b60d | 1089 | ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const |
088eb5a2 | 1090 | { |
fdf1b60d | 1091 | while (__lo < __hi) |
088eb5a2 | 1092 | { |
fdf1b60d BK |
1093 | *__lo = towlower(*__lo); |
1094 | ++__lo; | |
088eb5a2 | 1095 | } |
fdf1b60d | 1096 | return __hi; |
088eb5a2 BK |
1097 | } |
1098 | ||
b2dad0e3 | 1099 | bool |
cc4316b5 | 1100 | ctype<wchar_t>:: |
8c81504d | 1101 | do_is(mask __m, char_type __c) const |
bf6a6113 | 1102 | { return static_cast<bool>(iswctype(__c, _M_convert_to_wmask(__m))); } |
b2dad0e3 BK |
1103 | |
1104 | const wchar_t* | |
cc4316b5 | 1105 | ctype<wchar_t>:: |
fdf1b60d | 1106 | do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __m) const |
b2dad0e3 | 1107 | { |
fdf1b60d BK |
1108 | while (__lo < __hi && !this->is(*__m, *__lo)) |
1109 | ++__lo; | |
1110 | return __lo; | |
b2dad0e3 BK |
1111 | } |
1112 | ||
1113 | const wchar_t* | |
cc4316b5 | 1114 | ctype<wchar_t>:: |
fdf1b60d | 1115 | do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const |
b2dad0e3 | 1116 | { |
fdf1b60d BK |
1117 | while (__lo < __hi && !this->is(__m, *__lo)) |
1118 | ++__lo; | |
1119 | return __lo; | |
b2dad0e3 BK |
1120 | } |
1121 | ||
1122 | const wchar_t* | |
cc4316b5 | 1123 | ctype<wchar_t>:: |
fdf1b60d | 1124 | do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const |
b2dad0e3 | 1125 | { |
fdf1b60d BK |
1126 | while (__lo < __hi && this->is(__m, *__lo) != 0) |
1127 | ++__lo; | |
1128 | return __lo; | |
b2dad0e3 BK |
1129 | } |
1130 | ||
1131 | wchar_t | |
cc4316b5 BK |
1132 | ctype<wchar_t>:: |
1133 | do_widen(char __c) const | |
8c81504d | 1134 | { return btowc(__c); } |
b2dad0e3 BK |
1135 | |
1136 | const char* | |
cc4316b5 | 1137 | ctype<wchar_t>:: |
fdf1b60d | 1138 | do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const |
b2dad0e3 | 1139 | { |
8c81504d | 1140 | mbstate_t __state; |
0517cb99 | 1141 | memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t)); |
fdf1b60d BK |
1142 | mbsrtowcs(__dest, &__lo, __hi - __lo, &__state); |
1143 | return __hi; | |
b2dad0e3 BK |
1144 | } |
1145 | ||
1146 | char | |
cc4316b5 | 1147 | ctype<wchar_t>:: |
8c81504d | 1148 | do_narrow(wchar_t __wc, char __dfault) const |
b2dad0e3 | 1149 | { |
8c81504d BK |
1150 | int __c = wctob(__wc); |
1151 | return (__c == EOF ? __dfault : static_cast<char>(__c)); | |
b2dad0e3 BK |
1152 | } |
1153 | ||
1154 | const wchar_t* | |
cc4316b5 | 1155 | ctype<wchar_t>:: |
fdf1b60d | 1156 | do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, |
8c81504d | 1157 | char* __dest) const |
b2dad0e3 | 1158 | { |
8c81504d | 1159 | mbstate_t __state; |
0517cb99 | 1160 | memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t)); |
fdf1b60d BK |
1161 | size_t __len = __hi - __lo; |
1162 | size_t __conv = wcsrtombs(__dest, &__lo, __len, &__state); | |
8c81504d BK |
1163 | if (__conv == __len) |
1164 | *__dest = __dfault; | |
fdf1b60d | 1165 | return __hi; |
b2dad0e3 BK |
1166 | } |
1167 | ||
31bfa177 | 1168 | template<> |
cc4316b5 BK |
1169 | ctype_byname<wchar_t>:: |
1170 | ctype_byname(const char* /*__s*/, size_t __refs) | |
1171 | : ctype<wchar_t>(__refs) { } | |
b2dad0e3 | 1172 | #endif // _GLIBCPP_USE_WCHAR_T |
b2dad0e3 | 1173 | } // namespace std |