* invoke.texi (-fno-builtin): Document that this is always on
[official-gcc.git] / libstdc++-v3 / src / locale.cc
blob26bbc56da4d4d5cfc658bcdbc264bbd12bc2293f
1 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
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.
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.
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.
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.
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>
33 #include <exception>
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
40 #ifdef _GLIBCPP_USE_WCHAR_T
41 # include <bits/std_cwctype.h> // for towupper, etc.
42 #endif
44 namespace std
46 // Definitions for static const data members of locale.
47 const locale::category locale::none;
48 const locale::category locale::ctype;
49 const locale::category locale::numeric;
50 const locale::category locale::collate;
51 const locale::category locale::time;
52 const locale::category locale::monetary;
53 const locale::category locale::messages;
54 const locale::category locale::all;
56 locale::_Impl* locale::_S_classic;
57 locale::_Impl* locale::_S_global;
58 const size_t locale::_S_num_categories;
59 const size_t locale::_S_num_facets;
61 // Definitions for locale::id of standard facets.
62 locale::id ctype<char>::id;
63 locale::id codecvt<char, char, mbstate_t>::id;
65 #ifdef _GLIBCPP_USE_WCHAR_T
66 locale::id ctype<wchar_t>::id;
67 locale::id codecvt<wchar_t, char, mbstate_t>::id;
68 #endif
70 // Definitions for static const data members of locale::id
71 size_t locale::id::_S_highwater; // init'd to 0 by linker
73 // Definitions for static const data members of locale::_Impl
74 const locale::id* const
75 locale::_Impl::_S_id_ctype[] =
77 &std::ctype<char>::id,
78 &codecvt<char, char, mbstate_t>::id,
79 #ifdef _GLIBCPP_USE_WCHAR_T
80 &std::ctype<wchar_t>::id,
81 &codecvt<wchar_t, char, mbstate_t>::id,
82 #endif
86 const locale::id* const
87 locale::_Impl::_S_id_numeric[] =
89 &num_get<char>::id,
90 &num_put<char>::id,
91 &numpunct<char>::id,
92 #ifdef _GLIBCPP_USE_WCHAR_T
93 &num_get<wchar_t>::id,
94 &num_put<wchar_t>::id,
95 &numpunct<wchar_t>::id,
96 #endif
100 const locale::id* const
101 locale::_Impl::_S_id_collate[] =
103 &std::collate<char>::id,
104 #ifdef _GLIBCPP_USE_WCHAR_T
105 &std::collate<wchar_t>::id,
106 #endif
110 const locale::id* const
111 locale::_Impl::_S_id_time[] =
113 &time_get<char>::id,
114 &time_put<char>::id,
115 #ifdef _GLIBCPP_USE_WCHAR_T
116 &time_get<wchar_t>::id,
117 &time_put<wchar_t>::id,
118 #endif
122 const locale::id* const
123 locale::_Impl::_S_id_monetary[] =
125 &money_get<char>::id,
126 &money_put<char>::id,
127 &moneypunct<char, false>::id,
128 &moneypunct<char, true >::id,
129 #ifdef _GLIBCPP_USE_WCHAR_T
130 &money_get<wchar_t>::id,
131 &money_put<wchar_t>::id,
132 &moneypunct<wchar_t, false>::id,
133 &moneypunct<wchar_t, true >::id,
134 #endif
138 const locale::id* const
139 locale::_Impl::_S_id_messages[] =
141 &std::messages<char>::id,
142 #ifdef _GLIBCPP_USE_WCHAR_T
143 &std::messages<wchar_t>::id,
144 #endif
148 const locale::id* const* const
149 locale::_Impl::_S_facet_categories[] =
151 // Order must match the decl order in class locale.
152 locale::_Impl::_S_id_ctype,
153 locale::_Impl::_S_id_numeric,
154 locale::_Impl::_S_id_collate,
155 locale::_Impl::_S_id_time,
156 locale::_Impl::_S_id_monetary,
157 locale::_Impl::_S_id_messages,
161 // Construct and return valid pattern consisting of some combination of:
162 // space none symbol sign value
163 money_base::pattern
164 money_base::_S_construct_pattern(char __preceeds, char __space, char __posn)
166 pattern __ret;
168 // This insanely complicated routine attempts to construct a valid
169 // pattern for use with monyepunct. A couple of invariants:
171 // if (__preceeds) symbol -> value
172 // else value -> symbol
174 // if (__space) space
175 // else none
177 // none == never first
178 // space never first or last
180 // Any elegant implementations of this are welcome.
181 switch (__posn)
183 case 1:
184 // 1 The sign precedes the value and symbol.
185 if (__space)
187 // Pattern starts with sign.
188 if (__preceeds)
190 __ret.field[1] = symbol;
191 __ret.field[2] = space;
192 __ret.field[3] = value;
194 else
196 __ret.field[1] = value;
197 __ret.field[2] = space;
198 __ret.field[3] = symbol;
200 __ret.field[0] = sign;
202 else
204 // Pattern starts with sign and ends with none.
205 if (__preceeds)
207 __ret.field[1] = symbol;
208 __ret.field[2] = value;
210 else
212 __ret.field[1] = value;
213 __ret.field[2] = symbol;
215 __ret.field[0] = sign;
216 __ret.field[3] = none;
218 break;
219 case 2:
220 // 2 The sign follows the value and symbol.
221 if (__space)
223 // Pattern either ends with sign.
224 if (__preceeds)
226 __ret.field[0] = symbol;
227 __ret.field[1] = space;
228 __ret.field[2] = value;
230 else
232 __ret.field[0] = value;
233 __ret.field[1] = space;
234 __ret.field[2] = symbol;
236 __ret.field[3] = sign;
238 else
240 // Pattern ends with sign then none.
241 if (__preceeds)
243 __ret.field[0] = symbol;
244 __ret.field[1] = value;
246 else
248 __ret.field[0] = value;
249 __ret.field[1] = symbol;
251 __ret.field[2] = sign;
252 __ret.field[3] = none;
254 break;
255 case 3:
256 // 3 The sign immediately precedes the symbol.
257 if (__space)
259 // Have space.
260 if (__preceeds)
262 __ret.field[0] = sign;
263 __ret.field[1] = symbol;
264 __ret.field[2] = space;
265 __ret.field[3] = value;
267 else
269 __ret.field[0] = value;
270 __ret.field[1] = space;
271 __ret.field[2] = sign;
272 __ret.field[3] = symbol;
275 else
277 // Have none.
278 if (__preceeds)
280 __ret.field[0] = sign;
281 __ret.field[1] = symbol;
282 __ret.field[2] = value;
284 else
286 __ret.field[0] = value;
287 __ret.field[1] = sign;
288 __ret.field[2] = symbol;
290 __ret.field[3] = none;
292 break;
293 case 4:
294 // 4 The sign immediately follows the symbol.
295 if (__space)
297 // Have space.
298 if (__preceeds)
300 __ret.field[0] = symbol;
301 __ret.field[1] = sign;
302 __ret.field[2] = space;
303 __ret.field[3] = value;
305 else
307 __ret.field[0] = value;
308 __ret.field[1] = space;
309 __ret.field[2] = symbol;
310 __ret.field[3] = sign;
313 else
315 // Have none.
316 if (__preceeds)
318 __ret.field[0] = symbol;
319 __ret.field[1] = sign;
320 __ret.field[2] = value;
322 else
324 __ret.field[0] = value;
325 __ret.field[1] = symbol;
326 __ret.field[2] = sign;
328 __ret.field[3] = none;
330 break;
331 default:
334 return __ret;
337 locale::~locale() throw()
338 { _M_impl->_M_remove_reference(); }
340 void
341 locale::_M_coalesce(const locale& __base, const locale& __add,
342 category __cat)
344 __cat = _S_normalize_category(__cat);
345 _M_impl = new _Impl(*__base._M_impl, 1);
347 try
348 { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
349 catch (...)
351 _M_impl->_M_remove_reference();
352 __throw_exception_again;
356 locale::locale() throw()
358 _S_initialize();
359 (_M_impl = _S_global)->_M_add_reference();
360 } // XXX MT
362 locale::locale(const locale& __other) throw()
363 { (_M_impl = __other._M_impl)->_M_add_reference(); }
365 locale::locale(_Impl* __ip) throw()
366 : _M_impl(__ip)
367 { __ip->_M_add_reference(); }
369 locale::locale(const char* __s)
371 if (__s)
373 if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0)
374 (_M_impl = _S_classic)->_M_add_reference();
375 else
376 _M_impl = new _Impl(__s, 1);
378 else
379 __throw_runtime_error("attempt to create locale from NULL name");
382 locale::locale(const locale& __base, const char* __s, category __cat)
384 // NB: There are complicated, yet more efficient ways to do
385 // this. Building up locales on a per-category way is tedious, so
386 // let's do it this way until people complain.
387 locale __add(__s);
388 _M_coalesce(__base, __add, __cat);
391 locale::locale(const locale& __base, const locale& __add, category __cat)
392 { _M_coalesce(__base, __add, __cat); }
394 bool
395 locale::operator==(const locale& __rhs) const throw()
397 string __name = this->name();
398 return (_M_impl == __rhs._M_impl
399 || (__name != "*" && __name == __rhs.name()));
402 const locale&
403 locale::operator=(const locale& __other) throw()
405 __other._M_impl->_M_add_reference();
406 _M_impl->_M_remove_reference();
407 _M_impl = __other._M_impl;
408 return *this;
411 locale
412 locale::global(const locale& __other)
414 // XXX MT
415 _S_initialize();
416 locale __old(_S_global);
417 __other._M_impl->_M_add_reference();
418 _S_global->_M_remove_reference();
419 _S_global = __other._M_impl;
420 if (_S_global->_M_check_same_name() && _S_global->_M_names[0] != "*")
421 setlocale(LC_ALL, __other.name().c_str());
422 return __old;
425 string
426 locale::name() const
428 string __ret;
429 // Need some kind of separator character. This one was pretty much
430 // arbitrarily chosen as to not conflict with glibc locales: the
431 // exact formatting is not set in stone.
432 const char __separator = '|';
434 if (_M_impl->_M_check_same_name())
435 __ret = _M_impl->_M_names[0];
436 else
438 for (size_t i = 0; i < _S_num_categories; ++i)
439 __ret += __separator + _M_impl->_M_names[i];
441 return __ret;
444 locale const&
445 locale::classic()
447 static locale* __classic_locale;
448 // XXX MT
449 if (!_S_classic)
451 try
453 // 26 Standard facets, 2 references.
454 // One reference for _M_classic, one for _M_global
455 _S_classic = new _Impl("C", 2);
456 _S_global = _S_classic;
458 // Finesse static init order hassles
459 __classic_locale = new locale(_S_classic);
461 catch(...)
463 delete __classic_locale;
464 if (_S_classic)
466 _S_classic->_M_remove_reference();
467 _S_global->_M_remove_reference();
469 _S_classic = _S_global = 0;
470 // XXX MT
471 __throw_exception_again;
474 return *__classic_locale;
477 locale::category
478 locale::_S_normalize_category(category __cat)
480 int __ret = 0;
481 if (__cat == none || (__cat & all) && !(__cat & ~all))
482 __ret = __cat;
483 else
485 // NB: May be a C-style "LC_ALL" category; convert.
486 switch (__cat)
488 case LC_COLLATE:
489 __ret = collate;
490 break;
491 case LC_CTYPE:
492 __ret = ctype;
493 break;
494 case LC_MONETARY:
495 __ret = monetary;
496 break;
497 case LC_NUMERIC:
498 __ret = numeric;
499 break;
500 case LC_TIME:
501 __ret = time;
502 break;
503 #ifdef _GLIBCPP_HAVE_LC_MESSAGES
504 case LC_MESSAGES:
505 __ret = messages;
506 break;
507 #endif
508 case LC_ALL:
509 __ret = all;
510 break;
511 default:
512 __throw_runtime_error("bad locale category");
515 return __ret;
518 locale::facet::
519 facet(size_t __refs) throw()
520 : _M_references(__refs)
523 void
524 locale::facet::
525 _M_add_reference() throw()
526 { ++_M_references; } // XXX MT
528 void
529 locale::facet::
530 _M_remove_reference() throw()
532 if (_M_references)
533 --_M_references;
534 else
536 try
537 { delete this; } // XXX MT
538 catch (...)
543 // Definitions for static const data members of ctype_base.
544 const ctype_base::mask ctype_base::space;
545 const ctype_base::mask ctype_base::print;
546 const ctype_base::mask ctype_base::cntrl;
547 const ctype_base::mask ctype_base::upper;
548 const ctype_base::mask ctype_base::lower;
549 const ctype_base::mask ctype_base::alpha;
550 const ctype_base::mask ctype_base::digit;
551 const ctype_base::mask ctype_base::punct;
552 const ctype_base::mask ctype_base::xdigit;
553 const ctype_base::mask ctype_base::alnum;
554 const ctype_base::mask ctype_base::graph;
556 // Platform-specific initialization code for ctype tables.
557 #include <bits/ctype_noninline.h>
559 const size_t ctype<char>::table_size;
561 ctype<char>::~ctype()
562 { if (_M_del) delete[] this->table(); }
564 // These are dummy placeholders as these virtual functions are never called.
565 bool
566 ctype<char>::do_is(mask, char_type) const
567 { return false; }
569 const char*
570 ctype<char>::do_is(const char_type* __c, const char_type*, mask*) const
571 { return __c; }
573 const char*
574 ctype<char>::do_scan_is(mask, const char_type* __c, const char_type*) const
575 { return __c; }
577 const char*
578 ctype<char>::do_scan_not(mask, const char_type* __c, const char_type*) const
579 { return __c; }
581 char
582 ctype<char>::do_widen(char __c) const
583 { return __c; }
585 const char*
586 ctype<char>::do_widen(const char* __low, const char* __high,
587 char* __dest) const
589 memcpy(__dest, __low, __high - __low);
590 return __high;
593 char
594 ctype<char>::do_narrow(char __c, char /*__dfault*/) const
595 { return __c; }
597 const char*
598 ctype<char>::do_narrow(const char* __low, const char* __high,
599 char /*__dfault*/, char* __dest) const
601 memcpy(__dest, __low, __high - __low);
602 return __high;
605 ctype_byname<char>::ctype_byname(const char* /*__s*/, size_t __refs)
606 : ctype<char>(new mask[table_size], true, __refs)
609 // Definitions for static const data members of money_base
610 const money_base::pattern
611 money_base::_S_default_pattern = {{symbol, sign, none, value}};
613 template<>
614 _Format_cache<char>::_Format_cache()
615 : _M_valid(true),
616 _M_decimal_point('.'), _M_thousands_sep(','),
617 _M_truename("true"), _M_falsename("false"), _M_use_grouping(false)
620 #ifdef _GLIBCPP_USE_WCHAR_T
621 template<>
622 _Format_cache<wchar_t>::_Format_cache()
623 : _M_valid(true),
624 _M_decimal_point(L'.'), _M_thousands_sep(L','),
625 _M_truename(L"true"), _M_falsename(L"false"), _M_use_grouping(false)
627 #endif
629 template<>
630 const ctype<char>&
631 use_facet<ctype<char> >(const locale& __loc)
633 size_t __i = ctype<char>::id._M_index;
634 const locale::_Impl* __tmp = __loc._M_impl;
635 return static_cast<const ctype<char>&>(* (*(__tmp->_M_facets))[__i]);
638 #ifdef _GLIBCPP_USE_WCHAR_T
639 template<>
640 const ctype<wchar_t>&
641 use_facet<ctype<wchar_t> >(const locale& __loc)
643 size_t __i = ctype<wchar_t>::id._M_index;
644 const locale::_Impl* __tmp = __loc._M_impl;
645 return static_cast<const ctype<wchar_t>&>(* (*(__tmp->_M_facets))[__i]);
647 #endif
649 template<>
650 void
651 num_get<char, istreambuf_iterator<char> >::
652 _M_extract(istreambuf_iterator<char> __beg,
653 istreambuf_iterator<char> __end, ios_base& __io,
654 ios_base::iostate& __err, char* __xtrc, int& __base,
655 bool __fp) const
657 typedef _Format_cache<char> __cache_type;
659 // Prepare for possible failure
660 __xtrc[0] = '\0';
662 // Stage 1: determine a conversion specifier.
663 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
664 if (__basefield == ios_base::dec)
665 __base = 10;
666 else if (__basefield == ios_base::oct)
667 __base = 8;
668 else if (__basefield == ios_base::hex)
669 __base = 16;
670 else
671 __base = 0;
672 // As far as I can tell, bases other than 10 are not available for
673 // floating point types
674 if (__fp)
675 __base = 10;
677 // Stage 2: extract characters.
678 __cache_type const* __fmt = __cache_type::_S_get(__io);
680 // Fail quickly if !__valid
681 if (__beg == __end)
683 __err |= (ios_base::eofbit | ios_base::failbit);
684 return;
687 // Acceptable formats for numbers here are based on 22.2.3.1
688 string __grp;
689 int __sep_pos = 0;
690 int __pos = 0;
691 const char* __lits = __fmt->_S_literals;
692 char __c = *__beg;
694 // Check first for sign
695 bool __testsign = false;
696 if ((__c == __lits[__cache_type::_S_minus])
697 || (__c == __lits[__cache_type::_S_plus]))
699 __testsign = true;
700 __xtrc[__pos++] = __c;
701 ++__beg;
702 __c = * __beg;
704 // Whitespace may follow a sign
705 while ((__beg != __end) && (isspace(__c)))
707 ++__beg;
708 __c = *__beg;
711 // There had better be more to come...
712 if (__beg == __end)
714 __xtrc[__pos] = '\0';
715 __err |= (ios_base::eofbit | ios_base::failbit);
716 return;
720 // Now check if first character is a zero.
721 bool __testzero = false;
722 if (__c == __lits[__cache_type::_S_digits])
724 __testzero = true;
725 ++__beg;
726 __c = *__beg;
728 // We have to check for __beg == __end here. If so,
729 // a plain '0' (possibly with a sign) can be got rid of now
730 if (__beg == __end)
732 __xtrc[__pos++] = __lits[__cache_type::_S_digits];
733 __xtrc[__pos] = '\0';
734 __err |= ios_base::eofbit;
735 return;
738 // Figure out base for integer types only
739 // Based on Table 55 of 22.2.2.1.2
740 if (!__fp && __base != 10 && __base != 8)
742 // Here, __base == 0 or 16
743 if ((__c == __lits[__cache_type::_S_x])
744 || (__c == __lits[__cache_type::_S_X]))
746 ++__beg;
747 __c = *__beg;
748 __base = 16;
749 __testzero = false; // "0x" is not a leading zero
751 else if (__base == 0)
752 __base = 8;
755 // Remove any more leading zeros
756 while (__beg != __end)
758 if (__c == __lits[__cache_type::_S_digits])
760 ++__beg;
761 __c = *__beg;
762 __testzero = true;
764 else
765 break;
768 else if (__base == 0) // 1st character is not zero
769 __base = 10;
771 // We now seek "units", i.e. digits and thousands separators.
772 // We may need to know if anything is found here. A leading zero
773 // (removed by now) would count.
774 bool __testunits = __testzero;
775 while (__beg != __end)
777 const char* __p = strchr(__lits, __c);
779 // NB: strchr returns true for __c == 0x0
780 if (__p && __c
781 &&((__p >= &__lits[__cache_type::_S_digits]
782 && __p < &__lits[__cache_type::_S_digits + __base])
783 || (__p >= &__lits[__cache_type::_S_udigits]
784 && __p < &__lits[__cache_type::_S_udigits + __base])))
786 // Try first for acceptable digit; record it if found.
787 __xtrc[__pos++] = __c;
788 ++__sep_pos;
789 __testunits = true;
790 ++__beg;
791 __c = *__beg;
793 else if (__c == __fmt->_M_thousands_sep && __fmt->_M_use_grouping)
795 // NB: Thousands separator at the beginning of a string
796 // is a no-no, as is two consecutive thousands
797 // separators.
798 if (__sep_pos)
800 __grp += static_cast<char>(__sep_pos);
801 __sep_pos = 0;
802 ++__beg;
803 __c = *__beg;
805 else
807 __err |= ios_base::failbit;
808 break;
811 else
812 // Not a valid input item.
813 break;
816 // Digit grouping is checked. If _M_groupings() doesn't
817 // match, then get very very upset, and set failbit.
818 if (__fmt->_M_use_grouping && !__grp.empty())
820 // Add the ending grouping
821 __grp += static_cast<char>(__sep_pos);
823 // __grp is parsed L to R
824 // 1,222,444 == __grp of "/1/3/3"
825 // __fmt->_M_grouping is parsed R to L
826 // 1,222,444 == __fmt->_M_grouping of "/3" == "/3/3/3"
827 int __i = 0;
828 int __j = 0;
829 const int __len = __fmt->_M_grouping.size();
830 int __n = __grp.size();
831 bool __test = true;
833 // Parsed number groupings have to match the
834 // numpunct::grouping string exactly, starting at the
835 // right-most point of the parsed sequence of elements ...
836 while (__test && __i < __n - 1)
837 for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
838 __test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1];
839 // ... but the last parsed grouping can be <= numpunct
840 // grouping.
841 __j == __len ? __j = 0 : __j;
842 __test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1];
844 if (!__test)
846 __err |= ios_base::failbit;
847 __xtrc[__pos] = '\0';
848 if (__beg == __end)
849 __err |= ios_base::eofbit;
850 return;
854 // If there was nothing but zeros, put one in the output string
855 if (__testzero && (__pos == 0 || (__pos == 1 && __testsign)))
856 __xtrc[__pos++] = __lits[__cache_type::_S_digits];
858 // That's it for integer types. Remaining code is for floating point
859 if (__fp && __beg != __end)
861 // Check first for decimal point. There MUST be one if
862 // __testunits is false.
863 bool __testdec = false; // Is there a decimal point
864 // with digits following it?
865 if (__c == __fmt->_M_decimal_point)
867 __xtrc[__pos++] = '.';
868 ++__beg;
869 __c = *__beg;
871 // Now we get any digits after the decimal point
872 // There MUST be some if __testunits is false.
873 while (__beg != __end)
875 const char* __p = strchr(__lits, __c);
876 if ((__p >= &__lits[__cache_type::_S_digits]
877 && __p < &__lits[__cache_type::_S_digits + __base])
878 || (__p >= &__lits[__cache_type::_S_udigits]
879 && __p < &__lits[__cache_type::_S_udigits + __base]))
881 __xtrc[__pos++] = __c;
882 ++__beg;
883 __c = *__beg;
884 __testdec = true;
886 else
887 break;
890 if (!__testunits && !__testdec) // Ill formed
892 __err |= ios_base::failbit;
893 __xtrc[__pos] = '\0';
894 if (__beg == __end)
895 __err |= ios_base::eofbit;
896 return;
899 // Now we may find an exponent
900 if (__beg != __end)
902 if ((__c == __lits[__cache_type::_S_ee])
903 || (__c == __lits[__cache_type::_S_Ee]))
905 __xtrc[__pos++] = __c;
906 ++__beg;
907 __c = *__beg;
909 // Now there may be a sign
910 if (__beg != __end)
912 if ((__c == __lits[__cache_type::_S_minus])
913 || (__c == __lits[__cache_type::_S_plus]))
915 __xtrc[__pos++] = __c;
916 ++__beg;
917 __c = *__beg;
918 // whitespace may follow a sign
919 while ((__beg != __end) && (isspace(__c)))
921 ++__beg;
922 __c = *__beg;
926 // And now there must be some digits
927 if (__beg == __end)
929 __xtrc[__pos] = '\0';
930 __err |= (ios_base::eofbit | ios_base::failbit);
931 return;
933 while (__beg != __end)
935 const char* __p = strchr(__lits, __c);
936 if ((__p >= &__lits[__cache_type::_S_digits]
937 && __p < &__lits[__cache_type::_S_digits + __base])
938 || (__p >= &__lits[__cache_type::_S_udigits]
939 && __p < &__lits[__cache_type::_S_udigits + __base]))
941 __xtrc[__pos++] = __c;
942 ++__beg;
943 __c = *__beg;
945 else
946 break;
950 // Finally, that's it for floating point
953 // Finish up
954 __xtrc[__pos] = '\0';
955 if (__beg == __end)
956 __err |= ios_base::eofbit;
959 // The following code uses sprintf() to convert floating point
960 // values for insertion into a stream. The current implementation
961 // replicates the code in _S_pad_numeric() (in _S_output_float()) in
962 // order to prevent having to create a "wide" buffer in addition to
963 // the "narrow" buffer passed to sprintf(). An optimization would be
964 // to replace sprintf() with code that works directly on a wide
965 // buffer and then use _S_pad_numeric() to do the padding. It would
966 // be good to replace sprintf() anyway to avoid accidental buffer
967 // overruns and to gain back the efficiency that C++ provides by
968 // knowing up front the type of the values to insert. This
969 // implementation follows the C++ standard fairly directly as
970 // outlined in 22.2.2.2 [lib.locale.num.put]
971 bool
972 __build_float_format(ios_base& __io, char* __fptr, char __modifier,
973 streamsize __prec)
975 bool __incl_prec = false;
976 ios_base::fmtflags __flags = __io.flags();
977 *__fptr++ = '%';
978 // [22.2.2.2.2] Table 60
979 if (__flags & ios_base::showpos)
980 *__fptr++ = '+';
981 if (__flags & ios_base::showpoint)
982 *__fptr++ = '#';
983 // As per [22.2.2.2.2.11]
984 if (__flags & ios_base::fixed || __prec > 0)
986 *__fptr++ = '.';
987 *__fptr++ = '*';
988 __incl_prec = true;
990 if (__modifier)
991 *__fptr++ = __modifier;
992 ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
993 // [22.2.2.2.2] Table 58
994 if (__fltfield == ios_base::fixed)
995 *__fptr++ = 'f';
996 else if (__fltfield == ios_base::scientific)
997 *__fptr++ = (__flags & ios_base::uppercase) ? 'E' : 'e';
998 else
999 *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g';
1000 *__fptr = '\0';
1001 return __incl_prec;
1004 collate<char>::collate(size_t __refs)
1005 : locale::facet(__refs) { }
1007 collate<char>::~collate() { }
1009 int
1010 collate<char>::do_compare(const char* __lo1, const char* __hi1,
1011 const char* __lo2, const char* __hi2) const
1013 for (; __lo1 < __hi1 && __lo2 < __hi2; ++__lo1, ++__lo2)
1014 if (*__lo1 != *__lo2)
1015 return (*__lo1 < *__lo2) ? -1 : 1;
1016 if (__lo1 < __hi1)
1017 return 1;
1018 else if (__lo2 < __hi2)
1019 return -1;
1020 else
1021 return 0;
1024 string
1025 collate<char>::
1026 do_transform(const char* __lo, const char* __hi) const
1027 { return string(__lo, __hi - __lo); }
1029 long
1030 collate<char>::
1031 do_hash(const char* __lo, const char* __hi) const
1033 unsigned long __val = 0xdeadbeef;
1034 for (; __lo < __hi; ++__lo)
1035 __val = *__lo ^ ((__val << 7) &
1036 (__val >> (numeric_limits<unsigned long>::digits - 1)));
1037 return __val;
1040 collate_byname<char>::collate_byname(const char* /*__s*/, size_t __refs)
1041 : collate<char>(__refs) { }
1043 moneypunct_byname<char, false>::moneypunct_byname(const char* /*__s*/,
1044 size_t __refs)
1045 : moneypunct<char, false>(__refs) { }
1047 moneypunct_byname<char, true>::moneypunct_byname(const char* /*__s*/,
1048 size_t __refs)
1049 : moneypunct<char, true>(__refs) { }
1051 messages_byname<char>::
1052 messages_byname(const char* /*__s*/, size_t __refs)
1053 : messages<char>(__refs) { }
1055 #ifdef _GLIBCPP_USE_WCHAR_T
1056 ctype<wchar_t>::__wmask_type
1057 ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
1059 __wmask_type __ret;
1060 switch (__m)
1062 case space:
1063 __ret = wctype("space");
1064 break;
1065 case print:
1066 __ret = wctype("print");
1067 break;
1068 case cntrl:
1069 __ret = wctype("cntrl");
1070 break;
1071 case upper:
1072 __ret = wctype("upper");
1073 break;
1074 case lower:
1075 __ret = wctype("lower");
1076 break;
1077 case alpha:
1078 __ret = wctype("alpha");
1079 break;
1080 case digit:
1081 __ret = wctype("digit");
1082 break;
1083 case punct:
1084 __ret = wctype("punct");
1085 break;
1086 case xdigit:
1087 __ret = wctype("xdigit");
1088 break;
1089 case alnum:
1090 __ret = wctype("alnum");
1091 break;
1092 case graph:
1093 __ret = wctype("graph");
1094 break;
1095 default:
1096 __ret = 0;
1098 return __ret;
1101 ctype<wchar_t>::~ctype() { }
1103 // NB: These ctype<wchar_t> methods are not configuration-specific,
1104 // unlike the ctype<char> bits.
1105 ctype<wchar_t>::ctype(size_t __refs) : __ctype_abstract_base<wchar_t>(__refs)
1108 wchar_t
1109 ctype<wchar_t>::do_toupper(wchar_t __c) const
1110 { return towupper(__c); }
1112 const wchar_t*
1113 ctype<wchar_t>::do_toupper(wchar_t* __low, const wchar_t* __high) const
1115 while (__low < __high)
1117 *__low = towupper(*__low);
1118 ++__low;
1120 return __high;
1123 wchar_t
1124 ctype<wchar_t>::do_tolower(wchar_t __c) const
1125 { return towlower(__c); }
1127 const wchar_t*
1128 ctype<wchar_t>::do_tolower(wchar_t* __low, const wchar_t* __high) const
1130 while (__low < __high)
1132 *__low = towlower(*__low);
1133 ++__low;
1135 return __high;
1138 bool
1139 ctype<wchar_t>::
1140 do_is(mask __m, char_type __c) const
1141 { return static_cast<bool>(iswctype(__c, _M_convert_to_wmask(__m))); }
1143 const wchar_t*
1144 ctype<wchar_t>::
1145 do_is(const wchar_t* __low, const wchar_t* __high, mask* __m) const
1147 while (__low < __high && !this->is(*__m, *__low))
1148 ++__low;
1149 return __low;
1152 const wchar_t*
1153 ctype<wchar_t>::
1154 do_scan_is(mask __m, const wchar_t* __low, const wchar_t* __high) const
1156 while (__low < __high && !this->is(__m, *__low))
1157 ++__low;
1158 return __low;
1161 const wchar_t*
1162 ctype<wchar_t>::
1163 do_scan_not(mask __m, const char_type* __low, const char_type* __high) const
1165 while (__low < __high && this->is(__m, *__low) != 0)
1166 ++__low;
1167 return __low;
1170 wchar_t
1171 ctype<wchar_t>::
1172 do_widen(char __c) const
1173 { return btowc(__c); }
1175 const char*
1176 ctype<wchar_t>::
1177 do_widen(const char* __low, const char* __high, wchar_t* __dest) const
1179 mbstate_t __state;
1180 memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
1181 mbsrtowcs(__dest, &__low, __high - __low, &__state);
1182 return __high;
1185 char
1186 ctype<wchar_t>::
1187 do_narrow(wchar_t __wc, char __dfault) const
1189 int __c = wctob(__wc);
1190 return (__c == EOF ? __dfault : static_cast<char>(__c));
1193 const wchar_t*
1194 ctype<wchar_t>::
1195 do_narrow(const wchar_t* __low, const wchar_t* __high, char __dfault,
1196 char* __dest) const
1198 mbstate_t __state;
1199 memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
1200 size_t __len = __high - __low;
1201 size_t __conv = wcsrtombs(__dest, &__low, __len, &__state);
1202 if (__conv == __len)
1203 *__dest = __dfault;
1204 return __high;
1207 ctype_byname<wchar_t>::
1208 ctype_byname(const char* /*__s*/, size_t __refs)
1209 : ctype<wchar_t>(__refs) { }
1211 collate<wchar_t>::
1212 collate(size_t __refs): locale::facet(__refs) { }
1214 collate<wchar_t>::
1215 ~collate() { }
1217 int
1218 collate<wchar_t>::
1219 do_compare(const wchar_t* /*__lo1*/, const wchar_t* /*__hi1*/,
1220 const wchar_t* /*__lo2*/, const wchar_t* /*__hi2*/) const
1222 return 0; // XXX not done
1225 wstring collate<wchar_t>::
1226 do_transform(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const
1228 return wstring(); // XXX not done
1231 long collate<wchar_t>::
1232 do_hash(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const
1234 return 0; // XXX not done
1237 collate_byname<wchar_t>::
1238 collate_byname(const char* /*__s*/, size_t __refs)
1239 : collate<wchar_t> (__refs) { }
1241 messages_byname<wchar_t>::
1242 messages_byname(const char* /*__s*/, size_t __refs)
1243 : messages<wchar_t> (__refs) { }
1244 #endif // _GLIBCPP_USE_WCHAR_T
1245 } // namespace std