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
;
65 #ifdef _GLIBCPP_USE_WCHAR_T
66 locale::id ctype
<wchar_t>::id
;
67 locale::id codecvt
<wchar_t, char, mbstate_t>::id
;
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
,
86 const locale::id
* const
87 locale::_Impl::_S_id_numeric
[] =
92 #ifdef _GLIBCPP_USE_WCHAR_T
93 &num_get
<wchar_t>::id
,
94 &num_put
<wchar_t>::id
,
95 &numpunct
<wchar_t>::id
,
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
,
110 const locale::id
* const
111 locale::_Impl::_S_id_time
[] =
115 #ifdef _GLIBCPP_USE_WCHAR_T
116 &time_get
<wchar_t>::id
,
117 &time_put
<wchar_t>::id
,
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
,
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
,
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
164 money_base::_S_construct_pattern(char __preceeds
, char __space
, char __posn
)
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
177 // none == never first
178 // space never first or last
180 // Any elegant implementations of this are welcome.
184 // 1 The sign precedes the value and symbol.
187 // Pattern starts with sign.
190 __ret
.field
[1] = symbol
;
191 __ret
.field
[2] = space
;
192 __ret
.field
[3] = value
;
196 __ret
.field
[1] = value
;
197 __ret
.field
[2] = space
;
198 __ret
.field
[3] = symbol
;
200 __ret
.field
[0] = sign
;
204 // Pattern starts with sign and ends with none.
207 __ret
.field
[1] = symbol
;
208 __ret
.field
[2] = value
;
212 __ret
.field
[1] = value
;
213 __ret
.field
[2] = symbol
;
215 __ret
.field
[0] = sign
;
216 __ret
.field
[3] = none
;
220 // 2 The sign follows the value and symbol.
223 // Pattern either ends with sign.
226 __ret
.field
[0] = symbol
;
227 __ret
.field
[1] = space
;
228 __ret
.field
[2] = value
;
232 __ret
.field
[0] = value
;
233 __ret
.field
[1] = space
;
234 __ret
.field
[2] = symbol
;
236 __ret
.field
[3] = sign
;
240 // Pattern ends with sign then none.
243 __ret
.field
[0] = symbol
;
244 __ret
.field
[1] = value
;
248 __ret
.field
[0] = value
;
249 __ret
.field
[1] = symbol
;
251 __ret
.field
[2] = sign
;
252 __ret
.field
[3] = none
;
256 // 3 The sign immediately precedes the symbol.
262 __ret
.field
[0] = sign
;
263 __ret
.field
[1] = symbol
;
264 __ret
.field
[2] = space
;
265 __ret
.field
[3] = value
;
269 __ret
.field
[0] = value
;
270 __ret
.field
[1] = space
;
271 __ret
.field
[2] = sign
;
272 __ret
.field
[3] = symbol
;
280 __ret
.field
[0] = sign
;
281 __ret
.field
[1] = symbol
;
282 __ret
.field
[2] = value
;
286 __ret
.field
[0] = value
;
287 __ret
.field
[1] = sign
;
288 __ret
.field
[2] = symbol
;
290 __ret
.field
[3] = none
;
294 // 4 The sign immediately follows the symbol.
300 __ret
.field
[0] = symbol
;
301 __ret
.field
[1] = sign
;
302 __ret
.field
[2] = space
;
303 __ret
.field
[3] = value
;
307 __ret
.field
[0] = value
;
308 __ret
.field
[1] = space
;
309 __ret
.field
[2] = symbol
;
310 __ret
.field
[3] = sign
;
318 __ret
.field
[0] = symbol
;
319 __ret
.field
[1] = sign
;
320 __ret
.field
[2] = value
;
324 __ret
.field
[0] = value
;
325 __ret
.field
[1] = symbol
;
326 __ret
.field
[2] = sign
;
328 __ret
.field
[3] = none
;
337 locale::~locale() throw()
338 { _M_impl
->_M_remove_reference(); }
341 locale::_M_coalesce(const locale
& __base
, const locale
& __add
,
344 __cat
= _S_normalize_category(__cat
);
345 _M_impl
= new _Impl(*__base
._M_impl
, 1);
348 { _M_impl
->_M_replace_categories(__add
._M_impl
, __cat
); }
351 _M_impl
->_M_remove_reference();
352 __throw_exception_again
;
356 locale::locale() throw()
359 (_M_impl
= _S_global
)->_M_add_reference();
362 locale::locale(const locale
& __other
) throw()
363 { (_M_impl
= __other
._M_impl
)->_M_add_reference(); }
365 locale::locale(_Impl
* __ip
) throw()
367 { __ip
->_M_add_reference(); }
369 locale::locale(const char* __s
)
373 if (strcmp(__s
, "C") == 0 || strcmp(__s
, "POSIX") == 0)
374 (_M_impl
= _S_classic
)->_M_add_reference();
376 _M_impl
= new _Impl(__s
, 1);
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.
388 _M_coalesce(__base
, __add
, __cat
);
391 locale::locale(const locale
& __base
, const locale
& __add
, category __cat
)
392 { _M_coalesce(__base
, __add
, __cat
); }
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()));
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
;
412 locale::global(const locale
& __other
)
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());
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];
438 for (size_t i
= 0; i
< _S_num_categories
; ++i
)
439 __ret
+= __separator
+ _M_impl
->_M_names
[i
];
447 static locale
* __classic_locale
;
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
);
463 delete __classic_locale
;
466 _S_classic
->_M_remove_reference();
467 _S_global
->_M_remove_reference();
469 _S_classic
= _S_global
= 0;
471 __throw_exception_again
;
474 return *__classic_locale
;
478 locale::_S_normalize_category(category __cat
)
481 if (__cat
== none
|| (__cat
& all
) && !(__cat
& ~all
))
485 // NB: May be a C-style "LC_ALL" category; convert.
503 #ifdef _GLIBCPP_HAVE_LC_MESSAGES
512 __throw_runtime_error("bad locale category");
519 facet(size_t __refs
) throw()
520 : _M_references(__refs
)
525 _M_add_reference() throw()
526 { ++_M_references
; } // XXX MT
530 _M_remove_reference() throw()
537 { delete this; } // XXX MT
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.
566 ctype
<char>::do_is(mask
, char_type
) const
570 ctype
<char>::do_is(const char_type
* __c
, const char_type
*, mask
*) const
574 ctype
<char>::do_scan_is(mask
, const char_type
* __c
, const char_type
*) const
578 ctype
<char>::do_scan_not(mask
, const char_type
* __c
, const char_type
*) const
582 ctype
<char>::do_widen(char __c
) const
586 ctype
<char>::do_widen(const char* __low
, const char* __high
,
589 memcpy(__dest
, __low
, __high
- __low
);
594 ctype
<char>::do_narrow(char __c
, char /*__dfault*/) const
598 ctype
<char>::do_narrow(const char* __low
, const char* __high
,
599 char /*__dfault*/, char* __dest
) const
601 memcpy(__dest
, __low
, __high
- __low
);
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
}};
614 _Format_cache
<char>::_Format_cache()
616 _M_decimal_point('.'), _M_thousands_sep(','),
617 _M_truename("true"), _M_falsename("false"), _M_use_grouping(false)
620 #ifdef _GLIBCPP_USE_WCHAR_T
622 _Format_cache
<wchar_t>::_Format_cache()
624 _M_decimal_point(L
'.'), _M_thousands_sep(L
','),
625 _M_truename(L
"true"), _M_falsename(L
"false"), _M_use_grouping(false)
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
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
]);
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
,
657 typedef _Format_cache
<char> __cache_type
;
659 // Prepare for possible failure
662 // Stage 1: determine a conversion specifier.
663 ios_base::fmtflags __basefield
= __io
.flags() & ios_base::basefield
;
664 if (__basefield
== ios_base::dec
)
666 else if (__basefield
== ios_base::oct
)
668 else if (__basefield
== ios_base::hex
)
672 // As far as I can tell, bases other than 10 are not available for
673 // floating point types
677 // Stage 2: extract characters.
678 __cache_type
const* __fmt
= __cache_type::_S_get(__io
);
680 // Fail quickly if !__valid
683 __err
|= (ios_base::eofbit
| ios_base::failbit
);
687 // Acceptable formats for numbers here are based on 22.2.3.1
691 const char* __lits
= __fmt
->_S_literals
;
694 // Check first for sign
695 bool __testsign
= false;
696 if ((__c
== __lits
[__cache_type::_S_minus
])
697 || (__c
== __lits
[__cache_type::_S_plus
]))
700 __xtrc
[__pos
++] = __c
;
704 // Whitespace may follow a sign
705 while ((__beg
!= __end
) && (isspace(__c
)))
711 // There had better be more to come...
714 __xtrc
[__pos
] = '\0';
715 __err
|= (ios_base::eofbit
| ios_base::failbit
);
720 // Now check if first character is a zero.
721 bool __testzero
= false;
722 if (__c
== __lits
[__cache_type::_S_digits
])
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
732 __xtrc
[__pos
++] = __lits
[__cache_type::_S_digits
];
733 __xtrc
[__pos
] = '\0';
734 __err
|= ios_base::eofbit
;
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
]))
749 __testzero
= false; // "0x" is not a leading zero
751 else if (__base
== 0)
755 // Remove any more leading zeros
756 while (__beg
!= __end
)
758 if (__c
== __lits
[__cache_type::_S_digits
])
768 else if (__base
== 0) // 1st character is not zero
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
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
;
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
800 __grp
+= static_cast<char>(__sep_pos
);
807 __err
|= ios_base::failbit
;
812 // Not a valid input item.
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"
829 const int __len
= __fmt
->_M_grouping
.size();
830 int __n
= __grp
.size();
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
841 __j
== __len
? __j
= 0 : __j
;
842 __test
&= __fmt
->_M_grouping
[__j
] >= __grp
[__n
- __i
- 1];
846 __err
|= ios_base::failbit
;
847 __xtrc
[__pos
] = '\0';
849 __err
|= ios_base::eofbit
;
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
++] = '.';
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
;
890 if (!__testunits
&& !__testdec
) // Ill formed
892 __err
|= ios_base::failbit
;
893 __xtrc
[__pos
] = '\0';
895 __err
|= ios_base::eofbit
;
899 // Now we may find an exponent
902 if ((__c
== __lits
[__cache_type::_S_ee
])
903 || (__c
== __lits
[__cache_type::_S_Ee
]))
905 __xtrc
[__pos
++] = __c
;
909 // Now there may be a sign
912 if ((__c
== __lits
[__cache_type::_S_minus
])
913 || (__c
== __lits
[__cache_type::_S_plus
]))
915 __xtrc
[__pos
++] = __c
;
918 // whitespace may follow a sign
919 while ((__beg
!= __end
) && (isspace(__c
)))
926 // And now there must be some digits
929 __xtrc
[__pos
] = '\0';
930 __err
|= (ios_base::eofbit
| ios_base::failbit
);
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
;
950 // Finally, that's it for floating point
954 __xtrc
[__pos
] = '\0';
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]
972 __build_float_format(ios_base
& __io
, char* __fptr
, char __modifier
,
975 bool __incl_prec
= false;
976 ios_base::fmtflags __flags
= __io
.flags();
978 // [22.2.2.2.2] Table 60
979 if (__flags
& ios_base::showpos
)
981 if (__flags
& ios_base::showpoint
)
983 // As per [22.2.2.2.2.11]
984 if (__flags
& ios_base::fixed
|| __prec
> 0)
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
)
996 else if (__fltfield
== ios_base::scientific
)
997 *__fptr
++ = (__flags
& ios_base::uppercase
) ? 'E' : 'e';
999 *__fptr
++ = (__flags
& ios_base::uppercase
) ? 'G' : 'g';
1004 collate
<char>::collate(size_t __refs
)
1005 : locale::facet(__refs
) { }
1007 collate
<char>::~collate() { }
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;
1018 else if (__lo2
< __hi2
)
1026 do_transform(const char* __lo
, const char* __hi
) const
1027 { return string(__lo
, __hi
- __lo
); }
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)));
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*/,
1045 : moneypunct
<char, false>(__refs
) { }
1047 moneypunct_byname
<char, true>::moneypunct_byname(const char* /*__s*/,
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
1063 __ret
= wctype("space");
1066 __ret
= wctype("print");
1069 __ret
= wctype("cntrl");
1072 __ret
= wctype("upper");
1075 __ret
= wctype("lower");
1078 __ret
= wctype("alpha");
1081 __ret
= wctype("digit");
1084 __ret
= wctype("punct");
1087 __ret
= wctype("xdigit");
1090 __ret
= wctype("alnum");
1093 __ret
= wctype("graph");
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
)
1109 ctype
<wchar_t>::do_toupper(wchar_t __c
) const
1110 { return towupper(__c
); }
1113 ctype
<wchar_t>::do_toupper(wchar_t* __low
, const wchar_t* __high
) const
1115 while (__low
< __high
)
1117 *__low
= towupper(*__low
);
1124 ctype
<wchar_t>::do_tolower(wchar_t __c
) const
1125 { return towlower(__c
); }
1128 ctype
<wchar_t>::do_tolower(wchar_t* __low
, const wchar_t* __high
) const
1130 while (__low
< __high
)
1132 *__low
= towlower(*__low
);
1140 do_is(mask __m
, char_type __c
) const
1141 { return static_cast<bool>(iswctype(__c
, _M_convert_to_wmask(__m
))); }
1145 do_is(const wchar_t* __low
, const wchar_t* __high
, mask
* __m
) const
1147 while (__low
< __high
&& !this->is(*__m
, *__low
))
1154 do_scan_is(mask __m
, const wchar_t* __low
, const wchar_t* __high
) const
1156 while (__low
< __high
&& !this->is(__m
, *__low
))
1163 do_scan_not(mask __m
, const char_type
* __low
, const char_type
* __high
) const
1165 while (__low
< __high
&& this->is(__m
, *__low
) != 0)
1172 do_widen(char __c
) const
1173 { return btowc(__c
); }
1177 do_widen(const char* __low
, const char* __high
, wchar_t* __dest
) const
1180 memset(static_cast<void*>(&__state
), 0, sizeof(mbstate_t));
1181 mbsrtowcs(__dest
, &__low
, __high
- __low
, &__state
);
1187 do_narrow(wchar_t __wc
, char __dfault
) const
1189 int __c
= wctob(__wc
);
1190 return (__c
== EOF
? __dfault
: static_cast<char>(__c
));
1195 do_narrow(const wchar_t* __low
, const wchar_t* __high
, char __dfault
,
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
)
1207 ctype_byname
<wchar_t>::
1208 ctype_byname(const char* /*__s*/, size_t __refs
)
1209 : ctype
<wchar_t>(__refs
) { }
1212 collate(size_t __refs
): locale::facet(__refs
) { }
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