diff options
Diffstat (limited to 'libstdc++-v3/include/bits/locale_facets.tcc')
-rw-r--r-- | libstdc++-v3/include/bits/locale_facets.tcc | 914 |
1 files changed, 636 insertions, 278 deletions
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index ce6f3d7d5ff..44b81433234 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -36,13 +36,13 @@ #pragma GCC system_header #include <cerrno> -#include <clocale> // For localeconv -#include <cstdlib> // For strof, strtold -#include <cmath> // For ceil -#include <cctype> // For isspace -#include <limits> // For numeric_limits +#include <clocale> // For localeconv +#include <cstdlib> // For strof, strtold +#include <cmath> // For ceil +#include <cctype> // For isspace +#include <limits> // For numeric_limits +#include <typeinfo> // For bad_cast. #include <bits/streambuf_iterator.h> -#include <typeinfo> // For bad_cast. namespace std { @@ -113,7 +113,7 @@ namespace std } // Next, strip leading zeros. - const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); + const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); bool __found_zero = false; while (__traits_type::eq(__c, __zero) && __beg != __end) { @@ -122,14 +122,14 @@ namespace std } if (__found_zero) { - __xtrc += _S_atoms[_M_zero]; + __xtrc += _S_atoms_in[_M_zero]; ++__pos; } // Only need acceptable digits for floating point numbers. const size_t __len = _M_E - _M_zero + 1; char_type __watoms[__len]; - __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); + __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); bool __found_dec = false; bool __found_sci = false; const char_type __dec = __np.decimal_point(); @@ -150,7 +150,7 @@ namespace std { // Try first for acceptable digit; record it if found. ++__pos; - __xtrc += _S_atoms[__p - __watoms]; + __xtrc += _S_atoms_in[__p - __watoms]; ++__sep_pos; __c = *(++__beg); } @@ -261,7 +261,7 @@ namespace std } // Next, strip leading zeros and check required digits for base formats. - const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); + const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); const char_type __x = __ctype.widen('x'); const char_type __X = __ctype.widen('X'); if (__base == 10) @@ -274,7 +274,7 @@ namespace std } if (__found_zero) { - __xtrc += _S_atoms[_M_zero]; + __xtrc += _S_atoms_in[_M_zero]; ++__pos; if (__basefield == 0) { @@ -296,7 +296,7 @@ namespace std { if (__traits_type::eq(__c, __zero) && __beg != __end) { - __xtrc += _S_atoms[_M_zero]; + __xtrc += _S_atoms_in[_M_zero]; ++__pos; __c = *(++__beg); if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) @@ -319,7 +319,7 @@ namespace std // Extract. char_type __watoms[_M_size]; - __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); + __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); string __found_grouping; const string __grouping = __np.grouping(); bool __check_grouping = __grouping.size(); @@ -333,7 +333,7 @@ namespace std if (__p && !__traits_type::eq(__c, char_type())) { // Try first for acceptable digit; record it if found. - __xtrc += _S_atoms[__p - __watoms]; + __xtrc += _S_atoms_in[__p - __watoms]; ++__pos; ++__sep_pos; __c = *(++__beg); @@ -606,14 +606,249 @@ namespace std return __beg; } - // The following code uses snprintf (or sprintf(), when _GLIBCPP_USE_C99 - // is not defined) to convert floating point values for insertion into a - // stream. An optimization would be to replace them with code that works - // directly on a wide buffer and then use __pad to do the padding. - // It would be good to replace them anyway to gain back the efficiency - // that C++ provides by knowing up front the type of the values to insert. - // Also, sprintf is dangerous since may lead to accidental buffer overruns. - // This implementation follows the C++ standard fairly directly as + // For use by integer and floating-point types after they have been + // converted into a char_type string. + template<typename _CharT, typename _OutIter> + void + num_put<_CharT, _OutIter>:: + _M_pad(_CharT __fill, streamsize __w, ios_base& __io, + _CharT* __new, const _CharT* __cs, int& __len) const + { + // [22.2.2.2.2] Stage 3. + // If necessary, pad. + __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, + __w, __len, true); + __len = static_cast<int>(__w); + } + + // Forwarding functions to peel signed from unsigned integer types. + template<typename _CharT> + inline int + __int_to_char(_CharT* __out, const int __size, long __v, + const _CharT* __lit, ios_base::fmtflags __flags) + { + unsigned long __ul = static_cast<unsigned long>(__v); + bool __neg = false; + if (__v < 0) + { + __ul = -__ul; + __neg = true; + } + return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); + } + + template<typename _CharT> + inline int + __int_to_char(_CharT* __out, const int __size, unsigned long __v, + const _CharT* __lit, ios_base::fmtflags __flags) + { return __int_to_char(__out, __size, __v, __lit, __flags, false); } + +#ifdef _GLIBCPP_USE_LONG_LONG + template<typename _CharT> + inline int + __int_to_char(_CharT* __out, const int __size, long long __v, + const _CharT* __lit, ios_base::fmtflags __flags) + { + unsigned long long __ull = static_cast<unsigned long long>(__v); + bool __neg = false; + if (__v < 0) + { + __ull = -__ull; + __neg = true; + } + return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); + } + + template<typename _CharT> + inline int + __int_to_char(_CharT* __out, const int __size, unsigned long long __v, + const _CharT* __lit, ios_base::fmtflags __flags) + { return __int_to_char(__out, __size, __v, __lit, __flags, false); } +#endif + + template<typename _CharT, typename _ValueT> + int + __int_to_char(_CharT* __out, const int __size, _ValueT __v, + const _CharT* __lit, ios_base::fmtflags __flags, bool __neg) + { + // Don't write base if already 0. + const bool __showbase = (__flags & ios_base::showbase) && __v; + const ios_base::fmtflags __basefield = __flags & ios_base::basefield; + _CharT* __buf = __out + __size - 1; + _CharT* __bufend = __out + __size; + + if (__builtin_expect(__basefield == ios_base::oct, false)) + { + // Octal. + do + { + *__buf-- = __lit[(__v & 0x7) + __num_base::_S_digits]; + __v >>= 3; + } + while (__v != 0); + if (__showbase) + *__buf-- = __lit[__num_base::_S_digits]; + } + else if (__builtin_expect(__basefield == ios_base::hex, false)) + { + // Hex. + const bool __uppercase = __flags & ios_base::uppercase; + int __case_offset = __uppercase + ? __num_base::_S_udigits : __num_base::_S_digits; + do + { + *__buf-- = __lit[(__v & 0xf) + __case_offset]; + __v >>= 4; + } + while (__v != 0); + if (__showbase) + { + // 'x' or 'X' + *__buf-- = __lit[__num_base::_S_x + __uppercase]; + // '0' + *__buf-- = __lit[__num_base::_S_digits]; + } + } + else + { + // Decimal. + do + { + *__buf-- = __lit[(__v % 10) + __num_base::_S_digits]; + __v /= 10; + } + while (__v != 0); + if (__neg) + *__buf-- = __lit[__num_base::_S_minus]; + else if (__flags & ios_base::showpos) + *__buf-- = __lit[__num_base::_S_plus]; + } + int __ret = __bufend - __buf - 1; + return __ret; + } + + template<typename _CharT, typename _OutIter> + void + num_put<_CharT, _OutIter>:: + _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, + _CharT* __new, _CharT* __cs, int& __len) const + { + // By itself __add_grouping cannot deal correctly with __ws when + // ios::showbase is set and ios_base::oct || ios_base::hex. + // Therefore we take care "by hand" of the initial 0, 0x or 0X. + // However, remember that the latter do not occur if the number + // printed is '0' (__len == 1). + streamsize __off = 0; + const ios_base::fmtflags __basefield = __io.flags() + & ios_base::basefield; + if ((__io.flags() & ios_base::showbase) && __len > 1) + if (__basefield == ios_base::oct) + { + __off = 1; + *__new = *__cs; + } + else if (__basefield == ios_base::hex) + { + __off = 2; + *__new = *__cs; + *(__new + 1) = *(__cs + 1); + } + _CharT* __p; + __p = __add_grouping(__new + __off, __sep, + __grouping.c_str(), + __grouping.c_str() + __grouping.size(), + __cs + __off, __cs + __len); + __len = __p - __new; + } + + template<typename _CharT, typename _OutIter> + template<typename _ValueT> + _OutIter + num_put<_CharT, _OutIter>:: + _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, + _ValueT __v) const + { + typedef __locale_cache<_CharT> __cache_type; + __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache()); + _CharT* __lit = __lc._M_literals; + + // Long enough to hold hex, dec, and octal representations. + int __ilen = 4 * sizeof(_ValueT); + _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __ilen)); + + // [22.2.2.2.2] Stage 1, numeric conversion to character. + // Result is returned right-justified in the buffer. + int __len; + __len = __int_to_char(&__cs[0], __ilen, __v, __lit, __io.flags()); + __cs = __cs + __ilen - __len; + + // Add grouping, if necessary. + _CharT* __cs2; + if (__lc._M_use_grouping) + { + // Grouping can add (almost) as many separators as the + // number of digits, but no more. + __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); + _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, + __cs2, __cs, __len); + __cs = __cs2; + } + + // Pad. + _CharT* __cs3; + streamsize __w = __io.width(); + if (__w > static_cast<streamsize>(__len)) + { + __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __w)); + _M_pad(__fill, __w, __io, __cs3, __cs, __len); + __cs = __cs3; + } + __io.width(0); + + // [22.2.2.2.2] Stage 4. + // Write resulting, fully-formatted string to output iterator. + return __write(__s, __cs, __len); + } + + template<typename _CharT, typename _OutIter> + void + num_put<_CharT, _OutIter>:: + _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, + _CharT* __new, _CharT* __cs, int& __len) const + { +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + //282. What types does numpunct grouping refer to? + // Add grouping, if necessary. + _CharT* __p2; + int __declen = __p ? __p - __cs : __len; + __p2 = __add_grouping(__new, __sep, + __grouping.c_str(), + __grouping.c_str() + __grouping.size(), + __cs, __cs + __declen); + + // Tack on decimal part. + int __newlen = __p2 - __new; + if (__p) + { + char_traits<_CharT>::copy(__p2, __p, __len - __declen); + __newlen += __len - __declen; + } + __len = __newlen; +#endif + } + + // The following code uses snprintf (or sprintf(), when + // _GLIBCPP_USE_C99 is not defined) to convert floating point values + // for insertion into a stream. An optimization would be to replace + // them with code that works directly on a wide buffer and then use + // __pad to do the padding. It would be good to replace them anyway + // to gain back the efficiency that C++ provides by knowing up front + // the type of the values to insert. Also, sprintf is dangerous + // since may lead to accidental buffer overruns. This + // implementation follows the C++ standard fairly directly as // outlined in 22.2.2.2 [lib.locale.num.put] template<typename _CharT, typename _OutIter> template<typename _ValueT> @@ -622,48 +857,53 @@ namespace std _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, _ValueT __v) const { - // Note: digits10 is rounded down. We need to add 1 to ensure - // we get the full available precision. - const int __max_digits = numeric_limits<_ValueT>::digits10 + 1; + // Note: digits10 is rounded down: add 1 to ensure the maximum + // available precision. Then, in general, one more 1 needs to + // be added since, when the %{g,G} conversion specifiers are + // chosen inside _S_format_float, the precision field is "the + // maximum number of significant digits", *not* the "number of + // digits to appear after the decimal point", as happens for + // %{e,E,f,F} (C99, 7.19.6.1,4). + const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; + + // Use default precision if out of range. streamsize __prec = __io.precision(); - if (__prec > static_cast<streamsize>(__max_digits)) __prec = static_cast<streamsize>(__max_digits); + else if (__prec < static_cast<streamsize>(0)) + __prec = static_cast<streamsize>(6); - // Long enough for the max format spec. - char __fbuf[16]; + typedef __locale_cache<_CharT> __cache_type; + __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache()); // [22.2.2.2.2] Stage 1, numeric conversion to character. int __len; + // Long enough for the max format spec. + char __fbuf[16]; + #ifdef _GLIBCPP_USE_C99 - // First try a buffer perhaps big enough (for sure sufficient for - // non-ios_base::fixed outputs) + // First try a buffer perhaps big enough (for sure sufficient + // for non-ios_base::fixed outputs) int __cs_size = __max_digits * 3; char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); - const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec); - if (__fp) - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale, __prec); - else - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale); + _S_format_float(__io, __fbuf, __mod, __prec); + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale, __prec); // If the buffer was not large enough, try again with the correct size. if (__len >= __cs_size) { __cs_size = __len + 1; __cs = static_cast<char*>(__builtin_alloca(__cs_size)); - if (__fp) - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale, __prec); - else - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale); + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale, __prec); } #else // Consider the possibility of long ios_base::fixed outputs const bool __fixed = __io.flags() & ios_base::fixed; const int __max_exp = numeric_limits<_ValueT>::max_exponent10; + // ios_base::fixed outputs may need up to __max_exp+1 chars // for the integer part + up to __max_digits chars for the // fractional part + 3 chars for sign, decimal point, '\0'. On @@ -673,187 +913,54 @@ namespace std : __max_digits * 3; char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); - if (_S_format_float(__io, __fbuf, __mod, __prec)) - __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); - else - __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); + _S_format_float(__io, __fbuf, __mod, __prec); + __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); #endif - return _M_widen_float(__s, __io, __fill, __cs, __len); - } - - template<typename _CharT, typename _OutIter> - template<typename _ValueT> - _OutIter - num_put<_CharT, _OutIter>:: - _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, - char __modl, _ValueT __v) const - { - // [22.2.2.2.2] Stage 1, numeric conversion to character. - // Long enough for the max format spec. - char __fbuf[16]; - _S_format_int(__io, __fbuf, __mod, __modl); -#ifdef _GLIBCPP_USE_C99 - // First try a buffer perhaps big enough. - int __cs_size = 64; - char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); - int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale); - // If the buffer was not large enough, try again with the correct size. - if (__len >= __cs_size) - { - __cs_size = __len + 1; - __cs = static_cast<char*>(__builtin_alloca(__cs_size)); - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale); - } -#else - // Leave room for "+/-," "0x," and commas. This size is - // arbitrary, but should be largely sufficient. - char __cs[128]; - int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); -#endif - return _M_widen_int(__s, __io, __fill, __cs, __len); - } - - template<typename _CharT, typename _OutIter> - _OutIter - num_put<_CharT, _OutIter>:: - _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, - int __len) const - { - typedef char_traits<_CharT> __traits_type; // [22.2.2.2.2] Stage 2, convert to char_type, using correct // numpunct.decimal_point() values for '.' and adding grouping. const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); - // Grouping can add (almost) as many separators as the number of - // digits, but no more. - _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __len * 2)); __ctype.widen(__cs, __cs + __len, __ws); // Replace decimal point. + const _CharT __cdec = __ctype.widen('.'); + const _CharT __dec = __lc._M_decimal_point; const _CharT* __p; - const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); - if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) - __ws[__p - __ws] = __np.decimal_point(); - -#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS -//282. What types does numpunct grouping refer to? - // Add grouping, if necessary. - const string __grouping = __np.grouping(); - ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; - if (__grouping.size()) - { - _CharT* __p2; - int __declen = __p ? __p - __ws : __len; - __p2 = __add_grouping(__ws2, __np.thousands_sep(), - __grouping.c_str(), - __grouping.c_str() + __grouping.size(), - __ws, __ws + __declen); - int __newlen = __p2 - __ws2; - - // Tack on decimal part. - if (__p) - { - __traits_type::copy(__p2, __p, __len - __declen); - __newlen += __len - __declen; - } - - // Switch strings, establish correct new length. - __ws = __ws2; - __len = __newlen; - } -#endif - return _M_insert(__s, __io, __fill, __ws, __len); - } - - template<typename _CharT, typename _OutIter> - _OutIter - num_put<_CharT, _OutIter>:: - _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, - int __len) const - { - // [22.2.2.2.2] Stage 2, convert to char_type, using correct - // numpunct.decimal_point() values for '.' and adding grouping. - const locale __loc = __io.getloc(); - const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __len)); - // Grouping can add (almost) as many separators as the number of - // digits, but no more. - _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __len * 2)); - __ctype.widen(__cs, __cs + __len, __ws); + if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) + __ws[__p - __ws] = __dec; // Add grouping, if necessary. - const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); - const string __grouping = __np.grouping(); - const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; - if (__grouping.size()) + _CharT* __ws2; + if (__lc._M_use_grouping) { - // By itself __add_grouping cannot deal correctly with __ws when - // ios::showbase is set and ios_base::oct || ios_base::hex. - // Therefore we take care "by hand" of the initial 0, 0x or 0X. - // However, remember that the latter do not occur if the number - // printed is '0' (__len == 1). - streamsize __off = 0; - if ((__io.flags() & ios_base::showbase) && __len > 1) - if (__basefield == ios_base::oct) - { - __off = 1; - *__ws2 = *__ws; - } - else if (__basefield == ios_base::hex) - { - __off = 2; - *__ws2 = *__ws; - *(__ws2 + 1) = *(__ws + 1); - } - _CharT* __p; - __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), - __grouping.c_str(), - __grouping.c_str() + __grouping.size(), - __ws + __off, __ws + __len); - __len = __p - __ws2; - // Switch strings. - __ws = __ws2; + // Grouping can add (almost) as many separators as the + // number of digits, but no more. + __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); + _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p, + __ws2, __ws, __len); + __ws = __ws2; } - return _M_insert(__s, __io, __fill, __ws, __len); - } - // For use by integer and floating-point types after they have been - // converted into a char_type string. - template<typename _CharT, typename _OutIter> - _OutIter - num_put<_CharT, _OutIter>:: - _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, - int __len) const - { - typedef char_traits<_CharT> __traits_type; - // [22.2.2.2.2] Stage 3. + // Pad. + _CharT* __ws3; streamsize __w = __io.width(); - _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __w)); if (__w > static_cast<streamsize>(__len)) { - __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, - __w, __len, true); - __len = static_cast<int>(__w); - // Switch strings. - __ws = __ws2; + __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); + _M_pad(__fill, __w, __io, __ws3, __ws, __len); + __ws = __ws3; } __io.width(0); - + // [22.2.2.2.2] Stage 4. // Write resulting, fully-formatted string to output iterator. - for (int __j = 0; __j < __len; ++__j, ++__s) - *__s = __ws[__j]; - return __s; - } + return __write(__s, __ws, __len); + } template<typename _CharT, typename _OutIter> _OutIter @@ -864,19 +971,32 @@ namespace std if ((__flags & ios_base::boolalpha) == 0) { unsigned long __uv = __v; - __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv); + __s = _M_convert_int(__s, __io, __fill, __uv); } else { - typedef basic_string<_CharT> __string_type; - locale __loc = __io.getloc(); - const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + typedef __locale_cache<_CharT> __cache_type; + __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache()); + typedef basic_string<_CharT> __string_type; __string_type __name; if (__v) - __name = __np.truename(); + __name = __lc._M_truename; else - __name = __np.falsename(); - __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); + __name = __lc._M_falsename; + + const _CharT* __cs = __name.c_str(); + int __len = __name.size(); + _CharT* __cs3; + streamsize __w = __io.width(); + if (__w > static_cast<streamsize>(__len)) + { + __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __w)); + _M_pad(__fill, __w, __io, __cs3, __cs, __len); + __cs = __cs3; + } + __io.width(0); + __s = __write(__s, __cs, __len); } return __s; } @@ -885,28 +1005,28 @@ namespace std _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const - { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); } + { return _M_convert_int(__s, __io, __fill, __v); } template<typename _CharT, typename _OutIter> _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, unsigned long __v) const - { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); } + { return _M_convert_int(__s, __io, __fill, __v); } #ifdef _GLIBCPP_USE_LONG_LONG template<typename _CharT, typename _OutIter> _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const - { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); } + { return _M_convert_int(__s, __b, __fill, __v); } template<typename _CharT, typename _OutIter> _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, unsigned long long __v) const - { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); } + { return _M_convert_int(__s, __io, __fill, __v); } #endif template<typename _CharT, typename _OutIter> @@ -934,7 +1054,7 @@ namespace std __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); try { - __s = _M_convert_int(__s, __io, __fill, 'u', char(), + __s = _M_convert_int(__s, __io, __fill, reinterpret_cast<unsigned long>(__v)); __io.flags(__flags); } @@ -1191,7 +1311,8 @@ namespace std char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); #endif - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size)); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __cs_size)); __ctype.widen(__cs, __cs + __len, __ws); string_type __digits(__ws); return this->do_put(__s, __intl, __io, __fill, __digits); @@ -1285,7 +1406,7 @@ namespace std const char* __gend = __gbeg + __grouping.size(); const int __n = (__end - __beg) * 2; _CharT* __ws2 = - static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); + static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, __gend, __beg, __end); __value.insert(0, __ws2, __ws_end - __ws2); @@ -1354,8 +1475,7 @@ namespace std } // Write resulting, fully-formatted string to output iterator. - for (size_type __j = 0; __j < __len; ++__j, ++__s) - *__s = __res[__j]; + __s = __write(__s, __res.c_str(), __len); } __io.width(0); return __s; @@ -1611,7 +1731,8 @@ namespace std ios_base::iostate& __err) const { typedef char_traits<_CharT> __traits_type; - int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen)); + int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) + * __indexlen)); size_t __nmatches = 0; size_t __pos = 0; bool __testvalid = true; @@ -1623,12 +1744,12 @@ namespace std if (__c == __names[__i1][0]) __matches[__nmatches++] = __i1; - while(__nmatches > 1) + while (__nmatches > 1) { // Find smallest matching string. size_t __minlen = 10; for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) - __minlen = min(__minlen, + __minlen = min(__minlen, __traits_type::length(__names[__matches[__i2]])); if (__pos < __minlen && __beg != __end) @@ -1848,8 +1969,7 @@ namespace std } else __format = __c; - __s = this->do_put(__s, __io, char_type(), __tm, __format, - __mod); + __s = this->do_put(__s, __io, _CharT(), __tm, __format, __mod); } else { @@ -1873,8 +1993,7 @@ namespace std // NB: This size is arbitrary. Should this be a data member, // initialized at construction? const size_t __maxlen = 64; - char_type* __res = - static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); + char_type* __res = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); // NB: In IEE 1003.1-200x, and perhaps other locale models, it // is possible that the format character will be longer than one @@ -1898,10 +2017,7 @@ namespace std __tp._M_put(__res, __maxlen, __fmt, __tm); // Write resulting, fully-formatted string to output iterator. - size_t __len = char_traits<char_type>::length(__res); - for (size_t __i = 0; __i < __len; ++__i, ++__s) - *__s = __res[__i]; - return __s; + return __write(__s, __res, char_traits<char_type>::length(__res)); } @@ -1923,9 +2039,37 @@ namespace std do_compare(const _CharT* __lo1, const _CharT* __hi1, const _CharT* __lo2, const _CharT* __hi2) const { + // strcoll assumes zero-terminated strings so we make a copy + // and then put a zero at the end. const string_type __one(__lo1, __hi1); const string_type __two(__lo2, __hi2); - return _M_compare(__one.c_str(), __two.c_str()); + + const _CharT* __p = __one.c_str(); + const _CharT* __pend = __one.c_str() + __one.length(); + const _CharT* __q = __two.c_str(); + const _CharT* __qend = __two.c_str() + __two.length(); + + // strcoll stops when it sees a nul character so we break + // the strings into zero-terminated substrings and pass those + // to strcoll. + for (;;) + { + int __res = _M_compare(__p, __q); + if (__res) + return __res; + + __p += char_traits<_CharT>::length(__p); + __q += char_traits<_CharT>::length(__q); + if (__p == __pend && __q == __qend) + return 0; + else if (__p == __pend) + return -1; + else if (__q == __qend) + return 1; + + __p++; + __q++; + } } template<typename _CharT> @@ -1933,19 +2077,43 @@ namespace std collate<_CharT>:: do_transform(const _CharT* __lo, const _CharT* __hi) const { + // strxfrm assumes zero-terminated strings so we make a copy + string_type __str(__lo, __hi); + + const _CharT* __p = __str.c_str(); + const _CharT* __pend = __str.c_str() + __str.length(); + size_t __len = (__hi - __lo) * 2; - // First try a buffer perhaps big enough. - _CharT* __c = - static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); - size_t __res = _M_transform(__c, __lo, __len); - // If the buffer was not large enough, try again with the correct size. - if (__res >= __len) + + string_type __ret; + + // strxfrm stops when it sees a nul character so we break + // the string into zero-terminated substrings and pass those + // to strxfrm. + for (;;) { - __c = - static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1))); - _M_transform(__c, __lo, __res + 1); + // First try a buffer perhaps big enough. + _CharT* __c = + static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); + size_t __res = _M_transform(__c, __p, __len); + // If the buffer was not large enough, try again with the + // correct size. + if (__res >= __len) + { + __len = __res + 1; + __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len)); + __res = _M_transform(__c, __p, __res + 1); + } + + __ret.append(__c, __res); + __p += char_traits<_CharT>::length(__p); + if (__p == __pend) + return __ret; + + __p++; + __ret.push_back(_CharT()); } - return string_type(__c); } template<typename _CharT> @@ -1960,22 +2128,6 @@ namespace std return static_cast<long>(__val); } - // Convert string to numeric value of type _Tv and store results. - // NB: This is specialized for all required types, there is no - // generic definition. - template<typename _Tv> - void - __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, - const __c_locale& __cloc, int __base = 10); - - // Convert numeric value of type _Tv to string and return length of string. - // If snprintf is available use it, otherwise fall back to the unsafe sprintf - // which, in general, can be dangerous and should be avoided. - template<typename _Tv> - int - __convert_from_v(char* __out, const int __size, const char* __fmt, - _Tv __v, const __c_locale&, int __prec = -1); - // Construct correctly padded string, as per 22.2.2.2.2 // Assumes // __newlen > __oldlen @@ -1988,15 +2140,6 @@ namespace std // NB: Of the two parameters, _CharT can be deduced from the // function arguments. The other (_Traits) has to be explicitly specified. template<typename _CharT, typename _Traits> - struct __pad - { - static void - _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, - const _CharT* __olds, const streamsize __newlen, - const streamsize __oldlen, const bool __num); - }; - - template<typename _CharT, typename _Traits> void __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds, @@ -2004,7 +2147,8 @@ namespace std const streamsize __oldlen, const bool __num) { size_t __plen = static_cast<size_t>(__newlen - __oldlen); - _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen)); + _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __plen)); _Traits::assign(__pads, __plen, __fill); _CharT* __beg; @@ -2074,14 +2218,6 @@ namespace std __newlen - __beglen - __mod); } - // Used by both numeric and monetary facets. - // Check to make sure that the __grouping_tmp string constructed in - // money_get or num_get matches the canonical grouping for a given - // locale. - // __grouping_tmp is parsed L to R - // 1,222,444 == __grouping_tmp of "/1/3/3" - // __grouping is parsed R to L - // 1,222,444 == __grouping of "/3" == "/3/3/3" template<typename _CharT> bool __verify_grouping(const basic_string<_CharT>& __grouping, @@ -2106,11 +2242,6 @@ namespace std return __test; } - // Used by both numeric and monetary facets. - // Inserts "group separator" characters into an array of characters. - // It's recursive, one iteration per group. It moves the characters - // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this - // only with __gbeg != __gend. template<typename _CharT> _CharT* __add_grouping(_CharT* __s, _CharT __sep, @@ -2131,9 +2262,235 @@ namespace std return __s; } + template<typename _CharT> + void + __locale_cache<_CharT>::_M_init(const locale& __loc) + { + if (__builtin_expect(has_facet<numpunct<_CharT> >(__loc), true)) + { + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + _M_falsename = __np.falsename(); + _M_truename = __np.truename(); + _M_thousands_sep = __np.thousands_sep(); + _M_decimal_point = __np.decimal_point(); + _M_grouping = __np.grouping(); + _M_use_grouping = _M_grouping.size() != 0 + && _M_grouping.data()[0] != 0; + } + if (__builtin_expect(has_facet<ctype<_CharT> >(__loc), true)) + { + const ctype<_CharT>& __ct = use_facet< ctype<_CharT> >(__loc); + __ct.widen(__num_base::_S_atoms_out, + __num_base::_S_atoms_out + __num_base::_S_end, + _M_literals); + } + } + + template<typename _CharT> + void + __locale_cache<_CharT>::_S_callback(ios_base::event __ev, ios_base& __io, int) + { + switch (__ev) + { + case ios_base::erase_event: + if (__io.pword(0)) + delete &__io._M_cache(); + break; + + case ios_base::imbue_event: + break; + + case ios_base::copyfmt_event: + // This routine is called with the new ios_base, but pword(0) still + // points to the cache from the old ios_base. This replaces it with + // a new cache. Done here, so we don't get an extra callback from + // basic_ios::_M_cache_locale. + typedef __locale_cache<_CharT> __cache_t; + __io.pword(0) = auto_ptr<__cache_t>(new __cache_t()).release(); + break; + } + } + +#if 1 + // XXX GLIBCXX_ABI Deprecated, compatibility only. + template<typename _CharT, typename _OutIter> + template<typename _ValueT> + _OutIter + num_put<_CharT, _OutIter>:: + _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, + char __modl, _ValueT __v) const + { + // [22.2.2.2.2] Stage 1, numeric conversion to character. + + // Long enough for the max format spec. + char __fbuf[16]; + _S_format_int(__io, __fbuf, __mod, __modl); +#ifdef _GLIBCPP_USE_C99 + // First try a buffer perhaps big enough. + int __cs_size = 64; + char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale); + // If the buffer was not large enough, try again with the correct size. + if (__len >= __cs_size) + { + __cs_size = __len + 1; + __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale); + } +#else + // Leave room for "+/-," "0x," and commas. This size is + // arbitrary, but should be largely sufficient. + char __cs[128]; + int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); +#endif + return _M_widen_int(__s, __io, __fill, __cs, __len); + } + + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, + int __len) const + { + typedef char_traits<_CharT> __traits_type; + // [22.2.2.2.2] Stage 2, convert to char_type, using correct + // numpunct.decimal_point() values for '.' and adding grouping. + const locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len)); + // Grouping can add (almost) as many separators as the number of + // digits, but no more. + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); + __ctype.widen(__cs, __cs + __len, __ws); + + // Replace decimal point. + const _CharT* __p; + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) + __ws[__p - __ws] = __np.decimal_point(); + +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//282. What types does numpunct grouping refer to? + // Add grouping, if necessary. + const string __grouping = __np.grouping(); + if (__grouping.size()) + { + _CharT* __p2; + int __declen = __p ? __p - __ws : __len; + __p2 = __add_grouping(__ws2, __np.thousands_sep(), + __grouping.c_str(), + __grouping.c_str() + __grouping.size(), + __ws, __ws + __declen); + int __newlen = __p2 - __ws2; + + // Tack on decimal part. + if (__p) + { + __traits_type::copy(__p2, __p, __len - __declen); + __newlen += __len - __declen; + } + + // Switch strings, establish correct new length. + __ws = __ws2; + __len = __newlen; + } +#endif + return _M_insert(__s, __io, __fill, __ws, __len); + } + + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, + int __len) const + { + // [22.2.2.2.2] Stage 2, convert to char_type, using correct + // numpunct.decimal_point() values for '.' and adding grouping. + const locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len)); + // Grouping can add (almost) as many separators as the number of + // digits, but no more. + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); + __ctype.widen(__cs, __cs + __len, __ws); + + // Add grouping, if necessary. + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + const string __grouping = __np.grouping(); + if (__grouping.size()) + { + // By itself __add_grouping cannot deal correctly with __ws when + // ios::showbase is set and ios_base::oct || ios_base::hex. + // Therefore we take care "by hand" of the initial 0, 0x or 0X. + // However, remember that the latter do not occur if the number + // printed is '0' (__len == 1). + streamsize __off = 0; + const ios_base::fmtflags __basefield = __io.flags() + & ios_base::basefield; + if ((__io.flags() & ios_base::showbase) && __len > 1) + if (__basefield == ios_base::oct) + { + __off = 1; + *__ws2 = *__ws; + } + else if (__basefield == ios_base::hex) + { + __off = 2; + *__ws2 = *__ws; + *(__ws2 + 1) = *(__ws + 1); + } + _CharT* __p; + __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), + __grouping.c_str(), + __grouping.c_str() + __grouping.size(), + __ws + __off, __ws + __len); + __len = __p - __ws2; + // Switch strings. + __ws = __ws2; + } + return _M_insert(__s, __io, __fill, __ws, __len); + } + + // For use by integer and floating-point types after they have been + // converted into a char_type string. + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, + int __len) const + { + typedef char_traits<_CharT> __traits_type; + // [22.2.2.2.2] Stage 3. + // If necessary, pad. + streamsize __w = __io.width(); + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __w)); + if (__w > static_cast<streamsize>(__len)) + { + __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, + __w, __len, true); + __len = static_cast<int>(__w); + // Switch strings. + __ws = __ws2; + } + __io.width(0); + + // [22.2.2.2.2] Stage 4. + // Write resulting, fully-formatted string to output iterator. + return __write(__s, __ws, __len); + } +#endif + // Inhibit implicit instantiations for required instantiations, // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. +#if _GLIBCPP_EXTERN_TEMPLATE extern template class moneypunct<char, false>; extern template class moneypunct<char, true>; extern template class moneypunct_byname<char, false>; @@ -2387,6 +2744,7 @@ namespace std bool has_facet<messages<wchar_t> >(const locale&); #endif +#endif } // namespace std #endif |