]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/src/locale.cc
1 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
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)
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,
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>
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.
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
;
64 locale::id num_get
<char>::id
;
65 locale::id num_put
<char>::id
;
66 locale::id numpunct
<char>::id
;
67 locale::id collate
<char>::id
;
68 locale::id time_get
<char>::id
;
69 locale::id time_put
<char>::id
;
70 locale::id money_get
<char>::id
;
71 locale::id money_put
<char>::id
;
72 locale::id moneypunct
<char, false>::id
;
73 locale::id moneypunct
<char, true>::id
;
74 locale::id messages
<char>::id
;
76 #ifdef _GLIBCPP_USE_WCHAR_T
77 locale::id ctype
<wchar_t>::id
;
78 locale::id codecvt
<wchar_t, char, mbstate_t>::id
;
79 locale::id num_get
<wchar_t>::id
;
80 locale::id num_put
<wchar_t>::id
;
81 locale::id numpunct
<wchar_t>::id
;
82 locale::id collate
<wchar_t>::id
;
83 locale::id time_get
<wchar_t>::id
;
84 locale::id time_put
<wchar_t>::id
;
85 locale::id money_get
<wchar_t>::id
;
86 locale::id money_put
<wchar_t>::id
;
87 locale::id moneypunct
<wchar_t, false>::id
;
88 locale::id moneypunct
<wchar_t, true>::id
;
89 locale::id messages
<wchar_t>::id
;
92 // Definitions for static const data members of locale::id
93 size_t locale::id::_S_highwater
; // init'd to 0 by linker
95 // Definitions for static const data members of locale::_Impl
96 const locale::id
* const
97 locale::_Impl::_S_id_ctype
[] =
99 &std::ctype
<char>::id
,
100 &codecvt
<char, char, mbstate_t>::id
,
101 #ifdef _GLIBCPP_USE_WCHAR_T
102 &std::ctype
<wchar_t>::id
,
103 &codecvt
<wchar_t, char, mbstate_t>::id
,
108 const locale::id
* const
109 locale::_Impl::_S_id_numeric
[] =
114 #ifdef _GLIBCPP_USE_WCHAR_T
115 &num_get
<wchar_t>::id
,
116 &num_put
<wchar_t>::id
,
117 &numpunct
<wchar_t>::id
,
122 const locale::id
* const
123 locale::_Impl::_S_id_collate
[] =
125 &std::collate
<char>::id
,
126 #ifdef _GLIBCPP_USE_WCHAR_T
127 &std::collate
<wchar_t>::id
,
132 const locale::id
* const
133 locale::_Impl::_S_id_time
[] =
137 #ifdef _GLIBCPP_USE_WCHAR_T
138 &time_get
<wchar_t>::id
,
139 &time_put
<wchar_t>::id
,
144 const locale::id
* const
145 locale::_Impl::_S_id_monetary
[] =
147 &money_get
<char>::id
,
148 &money_put
<char>::id
,
149 &moneypunct
<char, false>::id
,
150 &moneypunct
<char, true >::id
,
151 #ifdef _GLIBCPP_USE_WCHAR_T
152 &money_get
<wchar_t>::id
,
153 &money_put
<wchar_t>::id
,
154 &moneypunct
<wchar_t, false>::id
,
155 &moneypunct
<wchar_t, true >::id
,
160 const locale::id
* const
161 locale::_Impl::_S_id_messages
[] =
163 &std::messages
<char>::id
,
164 #ifdef _GLIBCPP_USE_WCHAR_T
165 &std::messages
<wchar_t>::id
,
170 const locale::id
* const* const
171 locale::_Impl::_S_facet_categories
[] =
173 // Order must match the decl order in class locale.
174 locale::_Impl::_S_id_ctype
,
175 locale::_Impl::_S_id_numeric
,
176 locale::_Impl::_S_id_collate
,
177 locale::_Impl::_S_id_time
,
178 locale::_Impl::_S_id_monetary
,
179 locale::_Impl::_S_id_messages
,
183 // Construct and return valid pattern consisting of some combination of:
184 // space none symbol sign value
186 money_base::_S_construct_pattern(char __preceeds
, char __space
, char __posn
)
190 // This insanely complicated routine attempts to construct a valid
191 // pattern for use with monyepunct. A couple of invariants:
193 // if (__preceeds) symbol -> value
194 // else value -> symbol
196 // if (__space) space
199 // none == never first
200 // space never first or last
202 // Any elegant implementations of this are welcome.
206 // 1 The sign precedes the value and symbol.
209 // Pattern starts with sign.
212 __ret
.field
[1] = symbol
;
213 __ret
.field
[2] = space
;
214 __ret
.field
[3] = value
;
218 __ret
.field
[1] = value
;
219 __ret
.field
[2] = space
;
220 __ret
.field
[3] = symbol
;
222 __ret
.field
[0] = sign
;
226 // Pattern starts with sign and ends with none.
229 __ret
.field
[1] = symbol
;
230 __ret
.field
[2] = value
;
234 __ret
.field
[1] = value
;
235 __ret
.field
[2] = symbol
;
237 __ret
.field
[0] = sign
;
238 __ret
.field
[3] = none
;
242 // 2 The sign follows the value and symbol.
245 // Pattern either ends with sign.
248 __ret
.field
[0] = symbol
;
249 __ret
.field
[1] = space
;
250 __ret
.field
[2] = value
;
254 __ret
.field
[0] = value
;
255 __ret
.field
[1] = space
;
256 __ret
.field
[2] = symbol
;
258 __ret
.field
[3] = sign
;
262 // Pattern ends with sign then none.
265 __ret
.field
[0] = symbol
;
266 __ret
.field
[1] = value
;
270 __ret
.field
[0] = value
;
271 __ret
.field
[1] = symbol
;
273 __ret
.field
[2] = sign
;
274 __ret
.field
[3] = none
;
278 // 3 The sign immediately precedes the symbol.
284 __ret
.field
[0] = sign
;
285 __ret
.field
[1] = symbol
;
286 __ret
.field
[2] = space
;
287 __ret
.field
[3] = value
;
291 __ret
.field
[0] = value
;
292 __ret
.field
[1] = space
;
293 __ret
.field
[2] = sign
;
294 __ret
.field
[3] = symbol
;
302 __ret
.field
[0] = sign
;
303 __ret
.field
[1] = symbol
;
304 __ret
.field
[2] = value
;
308 __ret
.field
[0] = value
;
309 __ret
.field
[1] = sign
;
310 __ret
.field
[2] = symbol
;
312 __ret
.field
[3] = none
;
316 // 4 The sign immediately follows the symbol.
322 __ret
.field
[0] = symbol
;
323 __ret
.field
[1] = sign
;
324 __ret
.field
[2] = space
;
325 __ret
.field
[3] = value
;
329 __ret
.field
[0] = value
;
330 __ret
.field
[1] = space
;
331 __ret
.field
[2] = symbol
;
332 __ret
.field
[3] = sign
;
340 __ret
.field
[0] = symbol
;
341 __ret
.field
[1] = sign
;
342 __ret
.field
[2] = value
;
346 __ret
.field
[0] = value
;
347 __ret
.field
[1] = symbol
;
348 __ret
.field
[2] = sign
;
350 __ret
.field
[3] = none
;
359 locale::~locale() throw()
360 { _M_impl
->_M_remove_reference(); }
363 locale::_M_coalesce(const locale
& __base
, const locale
& __add
,
366 __cat
= _S_normalize_category(__cat
);
367 _M_impl
= new _Impl(*__base
._M_impl
, 1);
370 { _M_impl
->_M_replace_categories(__add
._M_impl
, __cat
); }
373 _M_impl
->_M_remove_reference();
378 locale::locale() throw()
381 (_M_impl
= _S_global
)->_M_add_reference();
384 locale::locale(const locale
& __other
) throw()
385 { (_M_impl
= __other
._M_impl
)->_M_add_reference(); }
387 locale::locale(_Impl
* __ip
) throw()
389 { __ip
->_M_add_reference(); }
391 locale::locale(const char* __s
)
395 if (strcmp(__s
, "C") == 0 || strcmp(__s
, "POSIX") == 0)
396 (_M_impl
= _S_classic
)->_M_add_reference();
398 _M_impl
= new _Impl(__s
, 1);
401 throw runtime_error("attempt to create locale from NULL name");
404 locale::locale(const locale
& __base
, const char* __s
, category __cat
)
406 // NB: There are complicated, yet more efficient ways to do
407 // this. Building up locales on a per-category way is tedious, so
408 // let's do it this way until people complain.
410 _M_coalesce(__base
, __add
, __cat
);
413 locale::locale(const locale
& __base
, const locale
& __add
, category __cat
)
414 { _M_coalesce(__base
, __add
, __cat
); }
417 locale::operator==(const locale
& __rhs
) const throw()
419 string __name
= this->name();
420 return (_M_impl
== __rhs
._M_impl
421 || (__name
!= "*" && __name
== __rhs
.name()));
425 locale::operator=(const locale
& __other
) throw()
427 __other
._M_impl
->_M_add_reference();
428 _M_impl
->_M_remove_reference();
429 _M_impl
= __other
._M_impl
;
434 locale::global(const locale
& __other
)
438 locale
__old(_S_global
);
439 __other
._M_impl
->_M_add_reference();
440 _S_global
->_M_remove_reference();
441 _S_global
= __other
._M_impl
;
442 if (_S_global
->_M_check_same_name() && _S_global
->_M_names
[0] != "*")
443 setlocale(LC_ALL
, __other
.name().c_str());
451 // Need some kind of separator character. This one was pretty much
452 // arbitrarily chosen as to not conflict with glibc locales: the
453 // exact formatting is not set in stone.
454 const char __separator
= '|';
456 if (_M_impl
->_M_check_same_name())
457 __ret
= _M_impl
->_M_names
[0];
460 for (size_t i
= 0; i
< _S_num_categories
; ++i
)
461 __ret
+= __separator
+ _M_impl
->_M_names
[i
];
469 static locale
* __classic_locale
;
475 // 26 Standard facets, 2 references.
476 // One reference for _M_classic, one for _M_global
477 _S_classic
= new _Impl("C", 2);
478 _S_global
= _S_classic
;
480 // Finesse static init order hassles
481 __classic_locale
= new locale(_S_classic
);
485 delete __classic_locale
;
488 _S_classic
->_M_remove_reference();
489 _S_global
->_M_remove_reference();
491 _S_classic
= _S_global
= 0;
496 return *__classic_locale
;
500 locale::_S_normalize_category(category __cat
)
503 if (__cat
== none
|| (__cat
& all
) && !(__cat
& ~all
))
507 // NB: May be a C-style "LC_ALL" category; convert.
525 #ifdef _GLIBCPP_HAVE_LC_MESSAGES
534 throw runtime_error("bad locale category");
541 facet(size_t __refs
) throw()
542 : _M_references(__refs
)
547 _M_add_reference() throw()
548 { ++_M_references
; } // XXX MT
552 _M_remove_reference() throw()
559 { delete this; } // XXX MT
565 // Definitions for static const data members of ctype_base.
566 const ctype_base::mask
ctype_base::space
;
567 const ctype_base::mask
ctype_base::print
;
568 const ctype_base::mask
ctype_base::cntrl
;
569 const ctype_base::mask
ctype_base::upper
;
570 const ctype_base::mask
ctype_base::lower
;
571 const ctype_base::mask
ctype_base::alpha
;
572 const ctype_base::mask
ctype_base::digit
;
573 const ctype_base::mask
ctype_base::punct
;
574 const ctype_base::mask
ctype_base::xdigit
;
575 const ctype_base::mask
ctype_base::alnum
;
576 const ctype_base::mask
ctype_base::graph
;
578 // Platform-specific initialization code for ctype tables.
579 #include <bits/ctype_noninline.h>
581 const size_t ctype
<char>::table_size
;
583 ctype
<char>::~ctype()
584 { if (_M_del
) delete[] this->table(); }
586 // These are dummy placeholders as these virtual functions are never called.
588 ctype
<char>::do_is(mask
, char_type
) const
592 ctype
<char>::do_is(const char_type
* __c
, const char_type
*, mask
*) const
596 ctype
<char>::do_scan_is(mask
, const char_type
* __c
, const char_type
*) const
600 ctype
<char>::do_scan_not(mask
, const char_type
* __c
, const char_type
*) const
604 ctype
<char>::do_widen(char __c
) const
608 ctype
<char>::do_widen(const char* __low
, const char* __high
,
611 memcpy(__dest
, __low
, __high
- __low
);
616 ctype
<char>::do_narrow(char __c
, char /*__dfault*/) const
620 ctype
<char>::do_narrow(const char* __low
, const char* __high
,
621 char /*__dfault*/, char* __dest
) const
623 memcpy(__dest
, __low
, __high
- __low
);
627 ctype_byname
<char>::ctype_byname(const char* /*__s*/, size_t __refs
)
628 : ctype
<char>(new mask
[table_size
], true, __refs
)
631 // Definitions for static const data members of money_base
632 const money_base::pattern
633 money_base::_S_default_pattern
= {{symbol
, sign
, none
, value
}};
636 _Format_cache
<char>::_Format_cache()
638 _M_decimal_point('.'), _M_thousands_sep(','),
639 _M_truename("true"), _M_falsename("false"), _M_use_grouping(false)
642 #ifdef _GLIBCPP_USE_WCHAR_T
644 _Format_cache
<wchar_t>::_Format_cache()
646 _M_decimal_point(L
'.'), _M_thousands_sep(L
','),
647 _M_truename(L
"true"), _M_falsename(L
"false"), _M_use_grouping(false)
653 use_facet
<ctype
<char> >(const locale
& __loc
)
655 size_t __i
= ctype
<char>::id
._M_index
;
656 const locale::_Impl
* __tmp
= __loc
._M_impl
;
657 return static_cast<const ctype
<char>&>(* (*(__tmp
->_M_facets
))[__i
]);
660 #ifdef _GLIBCPP_USE_WCHAR_T
662 const ctype
<wchar_t>&
663 use_facet
<ctype
<wchar_t> >(const locale
& __loc
)
665 size_t __i
= ctype
<wchar_t>::id
._M_index
;
666 const locale::_Impl
* __tmp
= __loc
._M_impl
;
667 return static_cast<const ctype
<wchar_t>&>(* (*(__tmp
->_M_facets
))[__i
]);
673 num_get
<char, istreambuf_iterator
<char> >::
674 _M_extract(istreambuf_iterator
<char> __beg
,
675 istreambuf_iterator
<char> __end
, ios_base
& __io
,
676 ios_base::iostate
& __err
, char* __xtrc
, int& __base
,
679 typedef _Format_cache
<char> __cache_type
;
681 // Prepare for possible failure
684 // Stage 1: determine a conversion specifier.
685 ios_base::fmtflags __basefield
= __io
.flags() & ios_base::basefield
;
686 if (__basefield
== ios_base::dec
)
688 else if (__basefield
== ios_base::oct
)
690 else if (__basefield
== ios_base::hex
)
694 // As far as I can tell, bases other than 10 are not available for
695 // floating point types
699 // Stage 2: extract characters.
700 __cache_type
const* __fmt
= __cache_type::_S_get(__io
);
701 bool __valid
= __beg
!= __end
;
702 // Fail quickly if !__valid
705 __err
|= (ios_base::eofbit
| ios_base::failbit
);
709 // Acceptable formats for numbers here are based on 22.2.3.1
713 const char* __lits
= __fmt
->_S_literals
;
716 // Check first for sign
717 bool __testsign
= false;
718 if ((__c
== __lits
[__cache_type::_S_minus
])
719 || (__c
== __lits
[__cache_type::_S_plus
]))
721 __xtrc
[__pos
++] = __c
;
724 // whitespace may follow a sign
725 while ((__beg
!= __end
) && (isspace(*__beg
)))
728 // There had better be more to come...
731 __xtrc
[__pos
] = '\0';
732 __err
|= (ios_base::eofbit
| ios_base::failbit
);
737 bool __testzero
= false; // Has there been a leading zero?
739 // Now check if first character is a zero
741 if (__c
== __lits
[__cache_type::_S_digits
])
746 // We have to check for __beg == __end here. If so,
747 // a plain '0' (possibly with a sign) can be got rid of now
750 __xtrc
[__pos
++] = __c
;
751 __xtrc
[__pos
] = '\0';
752 __err
|= ios_base::eofbit
;
756 // Figure out base for integer types only
757 // Based on Table 55 of 22.2.2.1.2
758 if (!__fp
&& __base
!= 10 && __base
!= 8)
760 // Here, __base == 0 or 16
762 if ((__c
== __lits
[__cache_type::_S_x
])
763 || (__c
== __lits
[__cache_type::_S_X
]))
767 __testzero
= false; // "0x" is not a leading zero
769 else if (__base
== 0)
773 // Remove any more leading zeros
774 while (__beg
!= __end
)
776 if (*__beg
== __lits
[__cache_type::_S_digits
])
785 else if (__base
== 0) // 1st character is not zero
788 // We now seek "units", i.e. digits and thousands separators.
789 // We may need to know if anything is found here. A leading zero
790 // (removed by now) would count.
791 bool __testunits
= __testzero
;
792 while (__valid
&& __beg
!= __end
)
796 const char* __p
= strchr(__fmt
->_S_literals
, __c
);
798 // NB: strchr returns true for __c == 0x0
801 // Try first for acceptable digit; record it if found
802 if ((__p
>= &__lits
[__cache_type::_S_digits
]
803 && __p
< &__lits
[__cache_type::_S_digits
+ __base
])
804 || (__p
>= &__lits
[__cache_type::_S_udigits
]
805 && __p
< &__lits
[__cache_type::_S_udigits
+ __base
]))
807 __xtrc
[__pos
++] = __c
;
813 else if (__c
== __fmt
->_M_thousands_sep
814 && __fmt
->_M_use_grouping
)
816 // NB: Thousands separator at the beginning of a string
817 // is a no-no, as is two consecutive thousands
821 __grp
+= static_cast<char>(__sep_pos
);
826 __err
|= ios_base::failbit
;
832 // Digit grouping is checked. If _M_groupings() doesn't
833 // match, then get very very upset, and set failbit.
834 if (__fmt
->_M_use_grouping
&& !__grp
.empty())
836 // Add the ending grouping
837 __grp
+= static_cast<char>(__sep_pos
);
839 // __grp is parsed L to R
840 // 1,222,444 == __grp of "/1/3/3"
841 // __fmt->_M_grouping is parsed R to L
842 // 1,222,444 == __fmt->_M_grouping of "/3" == "/3/3/3"
845 const int __len
= __fmt
->_M_grouping
.size();
846 int __n
= __grp
.size();
849 // Parsed number groupings have to match the
850 // numpunct::grouping string exactly, starting at the
851 // right-most point of the parsed sequence of elements ...
852 while (__test
&& __i
< __n
- 1)
853 for (__j
= 0; __test
&& __j
< __len
&& __i
< __n
- 1; ++__j
,++__i
)
854 __test
&= __fmt
->_M_grouping
[__j
] == __grp
[__n
- __i
- 1];
855 // ... but the last parsed grouping can be <= numpunct
857 __j
== __len
? __j
= 0 : __j
;
858 __test
&= __fmt
->_M_grouping
[__j
] >= __grp
[__n
- __i
- 1];
862 __err
|= ios_base::failbit
;
863 __xtrc
[__pos
] = '\0';
865 __err
|= ios_base::eofbit
;
870 // If there was nothing but zeros, put one in the output string
871 if (__testzero
&& (__pos
== 0 || (__pos
== 1 && __testsign
)))
872 __xtrc
[__pos
++] = __lits
[__cache_type::_S_digits
];
874 // That's it for integer types. Remaining code is for floating point
875 if (__fp
&& __beg
!= __end
)
878 // Check first for decimal point. There MUST be one if
879 // __testunits is false.
880 bool __testdec
= false; // Is there a decimal point
881 // with digits following it?
882 if (__c
== __fmt
->_M_decimal_point
)
884 __xtrc
[__pos
++] = '.';
886 // Now we get any digits after the decimal point
887 // There MUST be some if __testunits is false.
888 while (__beg
!= __end
)
891 const char* __p
= strchr(__fmt
->_S_literals
, __c
);
892 if ((__p
>= &__lits
[__cache_type::_S_digits
]
893 && __p
< &__lits
[__cache_type::_S_digits
+ __base
])
894 || (__p
>= &__lits
[__cache_type::_S_udigits
]
895 && __p
< &__lits
[__cache_type::_S_udigits
+ __base
]))
897 __xtrc
[__pos
++] = __c
;
905 if (!__testunits
&& !__testdec
) // Ill formed
907 __err
|= ios_base::failbit
;
908 __xtrc
[__pos
] = '\0';
910 __err
|= ios_base::eofbit
;
914 // Now we may find an exponent
918 if ((__c
== __lits
[__cache_type::_S_ee
])
919 || (__c
== __lits
[__cache_type::_S_Ee
]))
921 __xtrc
[__pos
++] = __c
;
923 // Now there may be a sign
927 if ((__c
== __lits
[__cache_type::_S_minus
])
928 || (__c
== __lits
[__cache_type::_S_plus
]))
930 __xtrc
[__pos
++] = __c
;
932 // whitespace may follow a sign
933 while ((__beg
!= __end
) && (isspace(*__beg
)))
938 // And now there must be some digits
941 __xtrc
[__pos
] = '\0';
942 __err
|= (ios_base::eofbit
| ios_base::failbit
);
945 while (__beg
!= __end
)
948 const char* __p
= strchr(__fmt
->_S_literals
, __c
);
949 if ((__p
>= &__lits
[__cache_type::_S_digits
]
950 && __p
< &__lits
[__cache_type::_S_digits
+ __base
])
951 || (__p
>= &__lits
[__cache_type::_S_udigits
]
952 && __p
< &__lits
[__cache_type::_S_udigits
+ __base
]))
954 __xtrc
[__pos
++] = __c
;
962 // Finally, that's it for floating point
966 __xtrc
[__pos
] = '\0';
968 __err
|= ios_base::eofbit
;
971 // The following code uses sprintf() to convert floating point
972 // values for insertion into a stream. The current implementation
973 // replicates the code in _S_pad_numeric() (in _S_output_float()) in
974 // order to prevent having to create a "wide" buffer in addition to
975 // the "narrow" buffer passed to sprintf(). An optimization would be
976 // to replace sprintf() with code that works directly on a wide
977 // buffer and then use _S_pad_numeric() to do the padding. It would
978 // be good to replace sprintf() anyway to avoid accidental buffer
979 // overruns and to gain back the efficiency that C++ provides by
980 // knowing up front the type of the values to insert. This
981 // implementation follows the C++ standard fairly directly as
982 // outlined in 22.2.2.2 [lib.locale.num.put]
984 _S_build_float_format(ios_base
& __io
, char* __fptr
, char __modifier
,
987 bool __incl_prec
= false;
988 ios_base::fmtflags __flags
= __io
.flags();
990 // [22.2.2.2.2] Table 60
991 if (__flags
& ios_base::showpos
)
993 if (__flags
& ios_base::showpoint
)
995 // As per [22.2.2.2.2.11]
996 if (__flags
& ios_base::fixed
|| __prec
> 0)
1003 *__fptr
++ = __modifier
;
1004 ios_base::fmtflags __fltfield
= __flags
& ios_base::floatfield
;
1005 // [22.2.2.2.2] Table 58
1006 if (__fltfield
== ios_base::fixed
)
1008 else if (__fltfield
== ios_base::scientific
)
1009 *__fptr
++ = (__flags
& ios_base::uppercase
) ? 'E' : 'e';
1011 *__fptr
++ = (__flags
& ios_base::uppercase
) ? 'G' : 'g';
1016 collate
<char>::collate(size_t __refs
)
1017 : locale::facet(__refs
) { }
1019 collate
<char>::~collate() { }
1022 collate
<char>::do_compare(const char* __lo1
, const char* __hi1
,
1023 const char* __lo2
, const char* __hi2
) const
1025 for (; __lo1
< __hi1
&& __lo2
< __hi2
; ++__lo1
, ++__lo2
)
1026 if (*__lo1
!= *__lo2
)
1027 return (*__lo1
< *__lo2
) ? -1 : 1;
1030 else if (__lo2
< __hi2
)
1038 do_transform(const char* __lo
, const char* __hi
) const
1039 { return string(__lo
, __hi
- __lo
); }
1043 do_hash(const char* __lo
, const char* __hi
) const
1045 unsigned long __val
= 0xdeadbeef;
1046 for (; __lo
< __hi
; ++__lo
)
1047 __val
= *__lo
^ ((__val
<< 7) &
1048 (__val
>> (numeric_limits
<unsigned long>::digits
- 1)));
1052 collate_byname
<char>::collate_byname(const char* /*__s*/, size_t __refs
)
1053 : collate
<char>(__refs
) { }
1055 moneypunct_byname
<char, false>::moneypunct_byname(const char* /*__s*/,
1057 : moneypunct
<char, false>(__refs
) { }
1059 moneypunct_byname
<char, true>::moneypunct_byname(const char* /*__s*/,
1061 : moneypunct
<char, true>(__refs
) { }
1063 messages_byname
<char>::
1064 messages_byname(const char* /*__s*/, size_t __refs
)
1065 : messages
<char>(__refs
) { }
1067 #ifdef _GLIBCPP_USE_WCHAR_T
1068 ctype
<wchar_t>::__wmask_type
1069 ctype
<wchar_t>::_M_convert_to_wmask(const mask __m
) const
1075 __ret
= wctype("space");
1078 __ret
= wctype("print");
1081 __ret
= wctype("cntrl");
1084 __ret
= wctype("upper");
1087 __ret
= wctype("lower");
1090 __ret
= wctype("alpha");
1093 __ret
= wctype("digit");
1096 __ret
= wctype("punct");
1099 __ret
= wctype("xdigit");
1102 __ret
= wctype("alnum");
1105 __ret
= wctype("graph");
1113 ctype
<wchar_t>::~ctype() { }
1115 // NB: These ctype<wchar_t> methods are not configuration-specific,
1116 // unlike the ctype<char> bits.
1117 ctype
<wchar_t>::ctype(size_t __refs
) : __ctype_abstract_base
<wchar_t>(__refs
)
1121 ctype
<wchar_t>::do_toupper(wchar_t __c
) const
1122 { return towupper(__c
); }
1125 ctype
<wchar_t>::do_toupper(wchar_t* __low
, const wchar_t* __high
) const
1127 while (__low
< __high
)
1129 *__low
= towupper(*__low
);
1136 ctype
<wchar_t>::do_tolower(wchar_t __c
) const
1137 { return towlower(__c
); }
1140 ctype
<wchar_t>::do_tolower(wchar_t* __low
, const wchar_t* __high
) const
1142 while (__low
< __high
)
1144 *__low
= towlower(*__low
);
1152 do_is(mask __m
, char_type __c
) const
1153 { return static_cast<bool>(iswctype(__c
, _M_convert_to_wmask(__m
))); }
1157 do_is(const wchar_t* __low
, const wchar_t* __high
, mask
* __m
) const
1159 while (__low
< __high
&& !this->is(*__m
, *__low
))
1166 do_scan_is(mask __m
, const wchar_t* __low
, const wchar_t* __high
) const
1168 while (__low
< __high
&& !this->is(__m
, *__low
))
1175 do_scan_not(mask __m
, const char_type
* __low
, const char_type
* __high
) const
1177 while (__low
< __high
&& this->is(__m
, *__low
) != 0)
1184 do_widen(char __c
) const
1185 { return btowc(__c
); }
1189 do_widen(const char* __low
, const char* __high
, wchar_t* __dest
) const
1192 memset(static_cast<void*>(&__state
), 0, sizeof(mbstate_t));
1193 mbsrtowcs(__dest
, &__low
, __high
- __low
, &__state
);
1199 do_narrow(wchar_t __wc
, char __dfault
) const
1201 int __c
= wctob(__wc
);
1202 return (__c
== EOF
? __dfault
: static_cast<char>(__c
));
1207 do_narrow(const wchar_t* __low
, const wchar_t* __high
, char __dfault
,
1211 memset(static_cast<void*>(&__state
), 0, sizeof(mbstate_t));
1212 size_t __len
= __high
- __low
;
1213 size_t __conv
= wcsrtombs(__dest
, &__low
, __len
, &__state
);
1214 if (__conv
== __len
)
1219 ctype_byname
<wchar_t>::
1220 ctype_byname(const char* /*__s*/, size_t __refs
)
1221 : ctype
<wchar_t>(__refs
) { }
1224 collate(size_t __refs
): locale::facet(__refs
) { }
1231 do_compare(const wchar_t* /*__lo1*/, const wchar_t* /*__hi1*/,
1232 const wchar_t* /*__lo2*/, const wchar_t* /*__hi2*/) const
1234 return 0; // XXX not done
1237 wstring collate
<wchar_t>::
1238 do_transform(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const
1240 return wstring(); // XXX not done
1243 long collate
<wchar_t>::
1244 do_hash(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const
1246 return 0; // XXX not done
1249 collate_byname
<wchar_t>::
1250 collate_byname(const char* /*__s*/, size_t __refs
)
1251 : collate
<wchar_t> (__refs
) { }
1253 messages_byname
<wchar_t>::
1254 messages_byname(const char* /*__s*/, size_t __refs
)
1255 : messages
<wchar_t> (__refs
) { }
1256 #endif // _GLIBCPP_USE_WCHAR_T