X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Finclude%2Fbits%2Flocale_facets.tcc;h=cb6dccd19e674df28d2248bea1058070d7f62fc5;hb=8c726f8b0ccd895f08cb2b1e53c5ab6b13cf5e09;hp=95cbee5d8f14446ffe8e6764663bdabb8e2b73d7;hpb=1e17e73d9ec782d727fb91d99133a964dbf7fd91;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 95cbee5d8f1..cb6dccd19e6 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -1,6 +1,7 @@ // Locale support -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// 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 // software; you can redistribute it and/or modify it under the @@ -27,20 +28,21 @@ // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. -// Warning: this file is not meant for user inclusion. Use . +// Warning: this file is not meant for user inclusion. Use . #ifndef _CPP_BITS_LOCFACETS_TCC #define _CPP_BITS_LOCFACETS_TCC 1 -#include -#include // For localeconv -#include // For strof, strtold -#include // For numeric_limits -#include // For auto_ptr -#include // For streambuf_iterators -#include // For isspace -#include // For bad_cast -#include +#pragma GCC system_header + +#include +#include // For localeconv +#include // For strof, strtold +#include // For ceil +#include // For isspace +#include // For numeric_limits +#include // For bad_cast. +#include namespace std { @@ -68,60 +70,66 @@ namespace std const _Facet& use_facet(const locale& __loc) { - size_t __i = _Facet::id._M_index; - locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets; - const locale::facet* __fp = (*__facet)[__i]; - if (__fp == 0 || __i >= __facet->size()) + size_t __i = _Facet::id._M_id(); + const locale::facet** __facets = __loc._M_impl->_M_facets; + if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) __throw_bad_cast(); - return static_cast(*__fp); + return static_cast(*__facets[__i]); } template bool has_facet(const locale& __loc) throw() { - size_t __i = _Facet::id._M_index; - locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets; - return (__i < __facet->size() && (*__facet)[__i] != 0); + size_t __i = _Facet::id._M_id(); + const locale::facet** __facets = __loc._M_impl->_M_facets; + return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); } + // Stage 1: Determine a conversion specifier. template - void + _InIter num_get<_CharT, _InIter>:: _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, - ios_base::iostate& __err, char* __xtrc) const + ios_base::iostate& __err, string& __xtrc) const { + typedef char_traits<_CharT> __traits_type; const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet >(__loc); const numpunct<_CharT>& __np = use_facet >(__loc); - int __pos = 0; - char_type __c = *__beg; - // Check first for sign. + // First check for sign. const char_type __plus = __ctype.widen('+'); const char_type __minus = __ctype.widen('-'); - if ((__c == __plus || __c == __minus) && __beg != __end) + int __pos = 0; + char_type __c = *__beg; + if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) + && __beg != __end) { - __xtrc[__pos++] = __ctype.narrow(__c, char()); + __xtrc += __ctype.narrow(__c, char()); + ++__pos; __c = *(++__beg); } // 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 (__c == __zero && __beg != __end) + while (__traits_type::eq(__c, __zero) && __beg != __end) { __c = *(++__beg); __found_zero = true; } if (__found_zero) - __xtrc[__pos++] = _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(); @@ -135,18 +143,19 @@ namespace std while (__beg != __end) { // Only look in digits. - typedef char_traits<_CharT> __traits_type; const char_type* __p = __traits_type::find(__watoms, 10, __c); // NB: strchr returns true for __c == 0x0 - if (__p && __c) + if (__p && !__traits_type::eq(__c, char_type())) { // Try first for acceptable digit; record it if found. - __xtrc[__pos++] = _S_atoms[__p - __watoms]; + ++__pos; + __xtrc += _S_atoms_in[__p - __watoms]; ++__sep_pos; __c = *(++__beg); } - else if (__c == __sep && __check_grouping && !__found_dec) + else if (__traits_type::eq(__c, __sep) + && __check_grouping && !__found_dec) { // NB: Thousands separator at the beginning of a string // is a no-no, as is two consecutive thousands separators. @@ -162,24 +171,33 @@ namespace std break; } } - else if (__c == __dec && !__found_dec) + else if (__traits_type::eq(__c, __dec) && !__found_dec) { - __found_grouping += static_cast(__sep_pos); - __xtrc[__pos++] = '.'; + // According to the standard, if no grouping chars are seen, + // no grouping check is applied. Therefore __found_grouping + // must be adjusted only if __dec comes after some __sep. + if (__found_grouping.size()) + __found_grouping += static_cast(__sep_pos); + ++__pos; + __xtrc += '.'; __c = *(++__beg); __found_dec = true; } - else if ((__c == __watoms[_M_e] || __c == __watoms[_M_E]) + else if ((__traits_type::eq(__c, __watoms[_M_e]) + || __traits_type::eq(__c, __watoms[_M_E])) && !__found_sci && __pos) { // Scientific notation. - __xtrc[__pos++] = __ctype.narrow(__c, char()); + ++__pos; + __xtrc += __ctype.narrow(__c, char()); __c = *(++__beg); // Remove optional plus or minus sign, if they exist. - if (__c == __plus || __c == __minus) + if (__traits_type::eq(__c, __plus) + || __traits_type::eq(__c, __minus)) { - __xtrc[__pos++] = __ctype.narrow(__c, char()); + ++__pos; + __xtrc += __ctype.narrow(__c, char()); __c = *(++__beg); } __found_sci = true; @@ -196,30 +214,30 @@ namespace std // Add the ending grouping if a decimal wasn't found. if (!__found_dec) __found_grouping += static_cast(__sep_pos); - if (!__verify_grouping(__grouping, __found_grouping)) - { - __err |= ios_base::failbit; - __xtrc[__pos] = '\0'; - if (__beg == __end) - __err |= ios_base::eofbit; - return; - } + __err |= ios_base::failbit; } // Finish up - __xtrc[__pos] = char_type(); + __xtrc += char(); if (__beg == __end) __err |= ios_base::eofbit; + return __beg; } + // Stage 1: Determine a conversion specifier. template - void + _InIter num_get<_CharT, _InIter>:: _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, - ios_base::iostate& __err, char* __xtrc, int& __base) const + ios_base::iostate& __err, string& __xtrc, int& __base) const { - // Stage 1: determine a conversion specifier. + typedef char_traits<_CharT> __traits_type; + const locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet >(__loc); + const numpunct<_CharT>& __np = use_facet >(__loc); + + // NB: Iff __basefield == 0, this can change based on contents. ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; if (__basefield == ios_base::oct) __base = 8; @@ -228,38 +246,66 @@ namespace std else __base = 10; - const locale __loc = __io.getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - const numpunct<_CharT>& __np = use_facet >(__loc); + // First check for sign. int __pos = 0; char_type __c = *__beg; + const char_type __plus = __ctype.widen('+'); + const char_type __minus = __ctype.widen('-'); - // Check first for sign. - if ((__c == __ctype.widen('+') || __c == __ctype.widen('-')) + if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) && __beg != __end) { - __xtrc[__pos++] = __ctype.narrow(__c, char()); + __xtrc += __ctype.narrow(__c, char()); + ++__pos; __c = *(++__beg); } - // Next, strip leading zeros - const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); - bool __found_zero = false; - while (__base == 10 && __c == __zero && __beg != __end) + // Next, strip leading zeros and check required digits for base formats. + 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) { - __c = *(++__beg); - __found_zero = true; + bool __found_zero = false; + while (__traits_type::eq(__c, __zero) && __beg != __end) + { + __c = *(++__beg); + __found_zero = true; + } + if (__found_zero) + { + __xtrc += _S_atoms_in[_M_zero]; + ++__pos; + if (__basefield == 0) + { + if ((__traits_type::eq(__c, __x) + || __traits_type::eq(__c, __X)) + && __beg != __end) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + __base = 16; + } + else + __base = 8; + } + } } - if (__found_zero) + else if (__base == 16) { - __xtrc[__pos++] = _S_atoms[_M_zero]; - if (__basefield == 0) + if (__traits_type::eq(__c, __zero) && __beg != __end) { - // Depending on what is discovered, the base may change. - if (__c == __ctype.widen('x') || __c == __ctype.widen('X')) - __base = 16; - else - __base = 8; + __xtrc += _S_atoms_in[_M_zero]; + ++__pos; + __c = *(++__beg); + if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) + && __beg != __end) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + } } } @@ -271,27 +317,28 @@ namespace std else __len = __base; - char_type __watoms[_M_size]; - __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); + // Extract. + char_type __watoms[_M_size]; + __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); string __found_grouping; const string __grouping = __np.grouping(); - bool __check_grouping = __grouping.size() && __base == 10; + bool __check_grouping = __grouping.size(); int __sep_pos = 0; const char_type __sep = __np.thousands_sep(); while (__beg != __end) { - typedef char_traits<_CharT> __traits_type; const char_type* __p = __traits_type::find(__watoms, __len, __c); // NB: strchr returns true for __c == 0x0 - if (__p && __c) + if (__p && !__traits_type::eq(__c, char_type())) { // Try first for acceptable digit; record it if found. - __xtrc[__pos++] = _S_atoms[__p - __watoms]; + __xtrc += _S_atoms_in[__p - __watoms]; + ++__pos; ++__sep_pos; __c = *(++__beg); } - else if (__c == __sep && __check_grouping) + else if (__traits_type::eq(__c, __sep) && __check_grouping) { // NB: Thousands separator at the beginning of a string // is a no-no, as is two consecutive thousands separators. @@ -316,23 +363,17 @@ namespace std // match, then get very very upset, and set failbit. if (__check_grouping && __found_grouping.size()) { - // Add the ending grouping + // Add the ending grouping. __found_grouping += static_cast(__sep_pos); - if (!__verify_grouping(__grouping, __found_grouping)) - { - __err |= ios_base::failbit; - __xtrc[__pos] = '\0'; - if (__beg == __end) - __err |= ios_base::eofbit; - return; - } + __err |= ios_base::failbit; } - // Finish up - __xtrc[__pos] = char_type(); + // Finish up. + __xtrc += char(); if (__beg == __end) __err |= ios_base::eofbit; + return __beg; } #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS @@ -343,47 +384,45 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, bool& __v) const { - // Parse bool values as long + // Parse bool values as unsigned long if (!(__io.flags() & ios_base::boolalpha)) { // NB: We can't just call do_get(long) here, as it might // refer to a derived class. - - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32] = {'\0'}; + string __xtrc; int __base; - _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long __l = strtol(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __l <= 1 - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __l; - else + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + + unsigned long __ul; + __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); + if (!(__err & ios_base::failbit) && __ul <= 1) + __v = __ul; + else __err |= ios_base::failbit; } // Parse bool values as alphanumeric else { - locale __loc = __io.getloc(); - const numpunct& __np = use_facet >(__loc); - const char_type* __true = __np.truename().c_str(); - const char_type* __false = __np.falsename().c_str(); + typedef char_traits<_CharT> __traits_type; + typedef basic_string<_CharT> __string_type; - const size_t __truen = __np.truename().size() - 1; - const size_t __falsen = __np.falsename().size() - 1; + locale __loc = __io.getloc(); + const numpunct<_CharT>& __np = use_facet >(__loc); + const __string_type __true = __np.truename(); + const __string_type __false = __np.falsename(); + const char_type* __trues = __true.c_str(); + const char_type* __falses = __false.c_str(); + const size_t __truen = __true.size() - 1; + const size_t __falsen = __false.size() - 1; for (size_t __n = 0; __beg != __end; ++__n) { char_type __c = *__beg++; - bool __testf = __n <= __falsen ? __c == __false[__n] : false; - bool __testt = __n <= __truen ? __c == __true[__n] : false; + bool __testf = __n <= __falsen + ? __traits_type::eq(__c, __falses[__n]) : false; + bool __testt = __n <= __truen + ? __traits_type::eq(__c, __trues[__n]) : false; if (!(__testf || __testt)) { __err |= ios_base::failbit; @@ -413,22 +452,10 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, long& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long __l = strtol(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __l; - else - __err |= ios_base::failbit; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); return __beg; } @@ -438,23 +465,16 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, unsigned short& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - unsigned long __ul = strtoul(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0 - && __ul <= USHRT_MAX) - __v = static_cast(__ul); - else - __err |= ios_base::failbit; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + unsigned long __ul; + __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); + if (!(__err & ios_base::failbit) + && __ul <= numeric_limits::max()) + __v = static_cast(__ul); + else + __err |= ios_base::failbit; return __beg; } @@ -464,23 +484,16 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, unsigned int& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - unsigned long __ul = strtoul(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0 - && __ul <= UINT_MAX) - __v = static_cast(__ul); - else - __err |= ios_base::failbit; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + unsigned long __ul; + __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); + if (!(__err & ios_base::failbit) + && __ul <= numeric_limits::max()) + __v = static_cast(__ul); + else + __err |= ios_base::failbit; return __beg; } @@ -490,22 +503,10 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, unsigned long& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32] = {'\0'}; + string __xtrc; int __base; - _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - unsigned long __ul = strtoul(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ul; - else - __err |= ios_base::failbit; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); return __beg; } @@ -516,22 +517,10 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, long long& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long long __ll = strtoll(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ll; - else - __err |= ios_base::failbit; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); return __beg; } @@ -541,22 +530,10 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, unsigned long long& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - unsigned long long __ull = strtoull(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ull; - else - __err |= ios_base::failbit; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); return __beg; } #endif @@ -567,25 +544,10 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, float& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 256 for - // floating-point types. - char __xtrc[32]= {'\0'}; - _M_extract_float(__beg, __end, __io, __err, __xtrc); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; -#ifdef _GLIBCPP_USE_C99 - float __f = strtof(__xtrc, &__sanity); -#else - float __f = static_cast(strtod(__xtrc, &__sanity)); -#endif - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __f; - else - __err |= ios_base::failbit; + string __xtrc; + __xtrc.reserve(32); + __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); return __beg; } @@ -595,21 +557,10 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, double& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 256 for - // floating-point types. - char __xtrc[32]= {'\0'}; - _M_extract_float(__beg, __end, __io, __err, __xtrc); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - double __d = strtod(__xtrc, &__sanity); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __d; - else - __err |= ios_base::failbit; + string __xtrc; + __xtrc.reserve(32); + __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); return __beg; } @@ -619,43 +570,10 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, long double& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 256 for - // floating-point types. - char __xtrc[32]= {'\0'}; - _M_extract_float(__beg, __end, __io, __err, __xtrc); - -#if defined(_GLIBCPP_USE_C99) && !defined(__hpux) - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long double __ld = strtold(__xtrc, &__sanity); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ld; -#else - // Stage 2: determine a conversion specifier. - ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; - const char* __conv; - if (__basefield == ios_base::oct) - __conv = "%Lo"; - else if (__basefield == ios_base::hex) - __conv = "%LX"; - else if (__basefield == 0) - __conv = "%Li"; - else - __conv = "%Lf"; - - // Stage 3: store results. - typedef typename char_traits<_CharT>::int_type int_type; - long double __ld; - int __p = sscanf(__xtrc, __conv, &__ld); - if (!(__err & ios_base::failbit) && __p - && static_cast(__p) != char_traits<_CharT>::eof()) - __v = __ld; -#endif - else - __err |= ios_base::failbit; + string __xtrc; + __xtrc.reserve(32); + __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); return __beg; } @@ -672,38 +590,265 @@ namespace std | ios_base::uppercase | ios_base::internal); __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - void* __vp = reinterpret_cast(strtoul(__xtrc, &__sanity, __base)); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __vp; - else - __err |= ios_base::failbit; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); // Reset from hex formatted input __io.flags(__fmt); + + unsigned long __ul; + __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); + if (!(__err & ios_base::failbit)) + __v = reinterpret_cast(__ul); + else + __err |= ios_base::failbit; return __beg; } + // For use by integer and floating-point types after they have been + // converted into a char_type string. + template + 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(__w); + } + + // Forwarding functions to peel signed from unsigned integer types. + template + inline int + __int_to_char(_CharT* __out, const int __size, long __v, + const _CharT* __lit, ios_base::fmtflags __flags) + { + unsigned long __ul = static_cast(__v); + bool __neg = false; + if (__v < 0) + { + __ul = -__ul; + __neg = true; + } + return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); + } + + template + 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 + 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(__v); + bool __neg = false; + if (__v < 0) + { + __ull = -__ull; + __neg = true; + } + return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); + } + + template + 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 + 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 + 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; + } - // The following code uses sprintf() to convert floating point - // values for insertion into a stream. An optimization would be to - // replace sprintf() with code that works directly on a wide buffer - // and then use __pad to do the padding. It would be good - // to replace sprintf() anyway to avoid accidental buffer overruns - // and to gain back the efficiency that C++ provides by knowing up - // front the type of the values to insert. This implementation - // follows the C++ standard fairly directly as outlined in 22.2.2.2 - // [lib.locale.num.put] + template + template + _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(__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 + 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 template _OutIter @@ -711,168 +856,110 @@ namespace std _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, _ValueT __v) const { - const int __max_digits = numeric_limits<_ValueT>::digits10; + // 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(); - // Protect against sprintf() buffer overflows. if (__prec > static_cast(__max_digits)) __prec = static_cast(__max_digits); + else if (__prec < static_cast(0)) + __prec = static_cast(6); + + 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) + int __cs_size = __max_digits * 3; + char* __cs = static_cast(__builtin_alloca(__cs_size)); + + _S_format_float(__io, __fbuf, __mod); + __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(__builtin_alloca(__cs_size)); + __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; - // XXX Why + 4? Why * 4? What's going on? Who's on first? + + // 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 + // the other hand, for non-fixed outputs __max_digits*3 chars + // are largely sufficient. const int __cs_size = __fixed ? __max_exp + __max_digits + 4 - : __max_digits * 4; + : __max_digits * 3; char* __cs = static_cast(__builtin_alloca(__cs_size)); - int __len; - // [22.2.2.2.2] Stage 1, numeric conversion to character. - if (_S_format_float(__io, __fbuf, __mod, __prec)) - __len = sprintf(__cs, __fbuf, __prec, __v); - else - __len = sprintf(__cs, __fbuf, __v); - return _M_widen_float(__s, __io, __fill, __cs, __len); - } - - template - template - _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. - // Leave room for "+/-," "0x," and commas. This size is - // arbitrary, but should work. - char __cs[64]; - // Long enough for the max format spec. - char __fbuf[16]; - _S_format_int(__io, __fbuf, __mod, __modl); - int __len = sprintf(__cs, __fbuf, __v); - return _M_widen_int(__s, __io, __fill, __cs, __len); - } + _S_format_float(__io, __fbuf, __mod); + __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); +#endif - template - _OutIter - num_put<_CharT, _OutIter>:: - _M_widen_float(_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 >(__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 >(__loc); - if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.'))) - __ws[__p - __ws] = __np.decimal_point(); + if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) + __ws[__p - __ws] = __dec; -#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) - { - char_traits<_CharT>::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 - _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 >(__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 >(__loc); - const string __grouping = __np.grouping(); - ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; - bool __dec = __basefield != ios_base::oct - && __basefield != ios_base::hex; - if (__grouping.size() && __dec) + _CharT* __ws2; + if (__lc._M_use_grouping) { - _CharT* __p; - __p = __add_grouping(__ws2, __np.thousands_sep(), __grouping.c_str(), - __grouping.c_str() + __grouping.size(), - __ws, __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 - _OutIter - num_put<_CharT, _OutIter>:: - _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, - int __len) const - { - // [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(__len)) { - __pad(__io, __fill, __ws2, __ws, __w, __len, true); - __len = static_cast(__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 _OutIter @@ -883,25 +970,32 @@ namespace std if ((__flags & ios_base::boolalpha) == 0) { unsigned long __uv = __v; - _M_convert_int(__s, __io, __fill, 'u', char_type(), __uv); + __s = _M_convert_int(__s, __io, __fill, __uv); } else { locale __loc = __io.getloc(); const numpunct<_CharT>& __np = use_facet >(__loc); - const char_type* __ws; - int __len; + typedef basic_string<_CharT> __string_type; + __string_type __name; if (__v) - { - __ws = __np.truename().c_str(); - __len = __np.truename().size(); - } + __name = __np.truename(); else - { - __ws = __np.falsename().c_str(); - __len = __np.falsename().size(); - } - _M_insert(__s, __io, __fill, __ws, __len); + __name = __np.falsename(); + + const _CharT* __cs = __name.c_str(); + int __len = __name.size(); + _CharT* __cs3; + streamsize __w = __io.width(); + if (__w > static_cast(__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; } @@ -910,35 +1004,35 @@ 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_type(), __v); } + { return _M_convert_int(__s, __io, __fill, __v); } template _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_type(), __v); } + { return _M_convert_int(__s, __io, __fill, __v); } #ifdef _GLIBCPP_USE_LONG_LONG template _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 _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 _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const - { return _M_convert_float(__s, __io, __fill, char_type(), __v); } + { return _M_convert_float(__s, __io, __fill, char(), __v); } template _OutIter @@ -959,8 +1053,8 @@ namespace std __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); try { - _M_convert_int(__s, __io, __fill, 'u', char_type(), - reinterpret_cast(__v)); + __s = _M_convert_int(__s, __io, __fill, + reinterpret_cast(__v)); __io.flags(__flags); } catch (...) @@ -979,30 +1073,15 @@ namespace std ios_base::iostate& __err, long double& __units) const { string_type __str; - this->do_get(__beg, __end, __intl, __io, __err, __str); + __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); const int __n = numeric_limits::digits10; - char* __cs = static_cast(__builtin_alloca(sizeof(char) * __n)); + char* __cs = static_cast(__builtin_alloca(__n)); const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet >(__loc); const _CharT* __wcs = __str.c_str(); __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs); - -#if defined(_GLIBCPP_USE_C99) && !defined(__hpux) - char* __sanity; - errno = 0; - long double __ld = strtold(__cs, &__sanity); - if (!(__err & ios_base::failbit) - && __sanity != __cs && *__sanity == '\0' && errno == 0) - __units = __ld; -#else - typedef typename char_traits<_CharT>::int_type int_type; - long double __ld; - int __p = sscanf(__cs, "%Lf", &__ld); - if (!(__err & ios_base::failbit) - && __p && static_cast(__p) != char_traits<_CharT>::eof()) - __units = __ld; -#endif + __convert_to_v(__cs, __units, __err, _S_c_locale); return __beg; } @@ -1048,6 +1127,9 @@ namespace std // Flag marking when a decimal point is found. bool __testdecfound = false; + // The tentative returned string is stored here. + string_type __temp_units; + char_type __c = *__beg; char_type __eof = static_cast(char_traits::eof()); for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) @@ -1056,20 +1138,29 @@ namespace std switch (__which) { case money_base::symbol: - if (__io.flags() & ios_base::showbase) + if (__io.flags() & ios_base::showbase + || __i < 2 || __sign.size() > 1 + || ((static_cast(__p.field[3]) != money_base::none) + && __i == 2)) { - // Symbol is required. + // According to 22.2.6.1.2.2, symbol is required + // if (__io.flags() & ios_base::showbase), + // otherwise is optional and consumed only if + // other characters are needed to complete the + // format. const string_type __symbol = __intl ? __mpt.curr_symbol() : __mpf.curr_symbol(); size_type __len = __symbol.size(); - size_type __i = 0; + size_type __j = 0; while (__beg != __end - && __i < __len && __symbol[__i] == __c) + && __j < __len && __symbol[__j] == __c) { __c = *(++__beg); - ++__i; + ++__j; } - if (__i != __len) + // When (__io.flags() & ios_base::showbase) + // symbol is required. + if (__j != __len && (__io.flags() & ios_base::showbase)) __testvalid = false; } break; @@ -1132,7 +1223,7 @@ namespace std } else { - __units += __c; + __temp_units += __c; ++__sep_pos; } __c = *(++__beg); @@ -1163,11 +1254,11 @@ namespace std } // Strip leading zeros. - while (__units[0] == __ctype.widen('0')) - __units.erase(__units.begin()); + while (__temp_units[0] == __ctype.widen('0')) + __temp_units.erase(__temp_units.begin()); - if (__sign == __neg_sign) - __units.insert(__units.begin(), __ctype.widen('-')); + if (__sign.size() && __sign == __neg_sign) + __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); // Test for grouping fidelity. if (__grouping.size() && __grouping_tmp.size()) @@ -1181,8 +1272,12 @@ namespace std __err |= ios_base::eofbit; // Iff valid sequence is not recognized. - if (!__testvalid || !__units.size()) + if (!__testvalid || !__temp_units.size()) __err |= ios_base::failbit; + else + // Use the "swap trick" to copy __temp_units into __units. + __temp_units.swap(__units); + return __beg; } @@ -1193,11 +1288,30 @@ namespace std long double __units) const { const locale __loc = __io.getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - const int __n = numeric_limits::digits10; - char* __cs = static_cast(__builtin_alloca(sizeof(char) * __n)); - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); - int __len = sprintf(__cs, "%.01Lf", __units); + const ctype<_CharT>& __ctype = use_facet >(__loc); +#ifdef _GLIBCPP_USE_C99 + // First try a buffer perhaps big enough. + int __cs_size = 64; + char* __cs = static_cast(__builtin_alloca(__cs_size)); + int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, + _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(__builtin_alloca(__cs_size)); + __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, + _S_c_locale); + } +#else + // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point, + // decimal digit, '\0'. + const int __cs_size = numeric_limits::max_exponent10 + 5; + char* __cs = static_cast(__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)); __ctype.widen(__cs, __cs + __len, __ws); string_type __digits(__ws); return this->do_put(__s, __intl, __io, __fill, __digits); @@ -1289,8 +1403,9 @@ namespace std : __mpf.thousands_sep(); const char* __gbeg = __grouping.c_str(); const char* __gend = __gbeg + __grouping.size(); - const int __n = numeric_limits::digits10 * 2; - _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); + const int __n = (__end - __beg) * 2; + _CharT* __ws2 = + 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); @@ -1332,7 +1447,7 @@ namespace std if (__testipad) __res += string_type(__width - __len, __fill); else - __res += __ctype.widen(' '); + __res += __ctype.widen(__fill); break; case money_base::none: if (__testipad) @@ -1359,8 +1474,7 @@ namespace std } // Write resulting, fully-formatted string to output iterator. - for (size_type __j = 0; __j < __len; ++__j) - __s = __res[__j]; + __s = __write(__s, __res.c_str(), __len); } __io.width(0); return __s; @@ -1460,13 +1574,13 @@ namespace std break; case 'I': // Hour [01, 12]. [tm_hour] - _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, + _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, __ctype, __err); break; case 'm': // Month [01, 12]. [tm_mon] - _M_extract_num(__beg, __end, __mem, 1, 12, 2, - __ctype, __err); + _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, + __err); if (!__err) __tm->tm_mon = __mem - 1; break; @@ -1615,8 +1729,9 @@ namespace std const _CharT** __names, size_t __indexlen, ios_base::iostate& __err) const { - typedef char_traits __traits_type; - int* __matches = static_cast(__builtin_alloca(sizeof(int) * __indexlen)); + typedef char_traits<_CharT> __traits_type; + int* __matches = static_cast(__builtin_alloca(sizeof(int) + * __indexlen)); size_t __nmatches = 0; size_t __pos = 0; bool __testvalid = true; @@ -1628,7 +1743,7 @@ namespace std if (__c == __names[__i1][0]) __matches[__nmatches++] = __i1; - while(__nmatches > 1) + while (__nmatches > 1) { // Find smallest matching string. size_t __minlen = 10; @@ -1710,7 +1825,7 @@ namespace std do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, tm* __tm) const { - typedef char_traits __traits_type; + typedef char_traits<_CharT> __traits_type; locale __loc = __io.getloc(); __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); const char_type* __days[7]; @@ -1753,7 +1868,7 @@ namespace std do_get_monthname(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, tm* __tm) const { - typedef char_traits __traits_type; + typedef char_traits<_CharT> __traits_type; locale __loc = __io.getloc(); __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); const char_type* __months[12]; @@ -1811,9 +1926,13 @@ namespace std } if (__i == 2 || __i == 4) { - int __year = atoi(__digits.c_str()); - __year = __i == 2 ? __year : __year - 1900; - __tm->tm_year = __year; + long __l; + __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); + if (!(__err & ios_base::failbit) && __l <= INT_MAX) + { + __l = __i == 2 ? __l : __l - 1900; + __tm->tm_year = static_cast(__l); + } } else __err |= ios_base::failbit; @@ -1849,10 +1968,13 @@ namespace std } else __format = __c; - this->do_put(__s, __io, char_type(), __tm, __format, __mod); + __s = this->do_put(__s, __io, _CharT(), __tm, __format, __mod); } else - __s = __c; + { + *__s = __c; + ++__s; + } } return __s; } @@ -1870,7 +1992,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(__builtin_alloca(__maxlen)); + char_type* __res = static_cast(__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 @@ -1891,26 +2013,23 @@ namespace std __fmt[3] = char_type(); } - __tp._M_put_helper(__res, __maxlen, __fmt, __tm); + __tp._M_put(__res, __maxlen, __fmt, __tm); // Write resulting, fully-formatted string to output iterator. - size_t __len = char_traits::length(__res); - for (size_t __i = 0; __i < __len; ++__i) - __s = __res[__i]; - return __s; + return __write(__s, __res, char_traits::length(__res)); } // Generic version does nothing. template int - collate<_CharT>::_M_compare_helper(const _CharT*, const _CharT*) const + collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const { return 0; } // Generic version does nothing. template size_t - collate<_CharT>::_M_transform_helper(_CharT*, const _CharT*, size_t) const + collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const { return 0; } template @@ -1921,24 +2040,25 @@ namespace std { const string_type __one(__lo1, __hi1); const string_type __two(__lo2, __hi2); - return _M_compare_helper(__one.c_str(), __two.c_str()); + return _M_compare(__one.c_str(), __two.c_str()); } template - collate<_CharT>::string_type + typename collate<_CharT>::string_type collate<_CharT>:: do_transform(const _CharT* __lo, const _CharT* __hi) const { - size_t __len = __hi - __lo; - _CharT* __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); - size_t __res = _M_transform_helper(__c, __lo, __len); + 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) { - // Try to increment size of translated string. - size_t __len2 = __len * 2; - _CharT* __c2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len2)); - __res = _M_transform_helper(__c2, __lo, __len); - // XXX Throw exception if still indeterminate? + __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * (__res + 1))); + _M_transform(__c, __lo, __res + 1); } return string_type(__c); } @@ -1951,7 +2071,7 @@ namespace std unsigned long __val = 0; for (; __lo < __hi; ++__lo) __val = *__lo + ((__val << 7) | - (__val >> (numeric_limits::digits - 1))); + (__val >> (numeric_limits::digits - 7))); return static_cast(__val); } @@ -1963,22 +2083,23 @@ namespace std // internal-adjusted objects are padded according to the rules below // concerning 0[xX] and +-, otherwise, exactly as right-adjusted // ones are. + + // NB: Of the two parameters, _CharT can be deduced from the + // function arguments. The other (_Traits) has to be explicitly specified. template - void - __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds, - const streamsize __newlen, const streamsize __oldlen, - const bool __num) + void + __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, + _CharT* __news, const _CharT* __olds, + const streamsize __newlen, + const streamsize __oldlen, const bool __num) { - typedef _CharT char_type; - typedef _Traits traits_type; - typedef typename traits_type::int_type int_type; - - int_type __plen = static_cast(__newlen - __oldlen); - char_type* __pads = static_cast(__builtin_alloca(sizeof(char_type) * __plen)); - traits_type::assign(__pads, __plen, __fill); + size_t __plen = static_cast(__newlen - __oldlen); + _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __plen)); + _Traits::assign(__pads, __plen, __fill); - char_type* __beg; - char_type* __end; + _CharT* __beg; + _CharT* __end; size_t __mod = 0; size_t __beglen; //either __plen or __oldlen ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; @@ -1986,7 +2107,7 @@ namespace std if (__adjust == ios_base::left) { // Padding last. - __beg = const_cast(__olds); + __beg = const_cast<_CharT*>(__olds); __beglen = __oldlen; __end = __pads; } @@ -1997,12 +2118,14 @@ namespace std // Who came up with these rules, anyway? Jeeze. locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet >(__loc); - const char_type __minus = __ctype.widen('-'); - const char_type __plus = __ctype.widen('+'); - bool __testsign = __olds[0] == __minus || __olds[0] == __plus; - bool __testhex = __ctype.widen('0') == __olds[0] - && (__ctype.widen('x') == __olds[1] - || __ctype.widen('X') == __olds[1]); + const _CharT __minus = __ctype.widen('-'); + const _CharT __plus = __ctype.widen('+'); + bool __testsign = _Traits::eq(__olds[0], __minus) + || _Traits::eq(__olds[0], __plus); + + bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) + && (_Traits::eq(__ctype.widen('x'), __olds[1]) + || _Traits::eq(__ctype.widen('X'), __olds[1])); if (__testhex) { __news[0] = __olds[0]; @@ -2011,23 +2134,23 @@ namespace std __news += 2; __beg = __pads; __beglen = __plen; - __end = const_cast(__olds + __mod); + __end = const_cast<_CharT*>(__olds + __mod); } else if (__testsign) { - __news[0] = __olds[0] == __plus ? __plus : __minus; + _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; ++__mod; ++__news; __beg = __pads; __beglen = __plen; - __end = const_cast(__olds + __mod); + __end = const_cast<_CharT*>(__olds + __mod); } else { // Padding first. __beg = __pads; __beglen = __plen; - __end = const_cast(__olds); + __end = const_cast<_CharT*>(__olds); } } else @@ -2035,33 +2158,13 @@ namespace std // Padding first. __beg = __pads; __beglen = __plen; - __end = const_cast(__olds); + __end = const_cast<_CharT*>(__olds); } - traits_type::copy(__news, __beg, __beglen); - traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod); + _Traits::copy(__news, __beg, __beglen); + _Traits::copy(__news + __beglen, __end, + __newlen - __beglen - __mod); } - // NB: Can't have default argument on non-member template, and - // num_put doesn't have a _Traits template parameter, so this - // forwarding template adds in the default template argument. - template - void - __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds, - const streamsize __newlen, const streamsize __oldlen, - const bool __num) - { - return __pad<_CharT, char_traits<_CharT> >(__io, __fill, __news, __olds, - __newlen, __oldlen, __num); - } - - // 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 bool __verify_grouping(const basic_string<_CharT>& __grouping, @@ -2086,11 +2189,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 _CharT* __add_grouping(_CharT* __s, _CharT __sep, @@ -2110,6 +2208,290 @@ namespace std while (__first != __last); return __s; } + + // Generic definition, locale cache initialization. + template + void + __locale_cache<_CharT>::_M_init(const locale& __loc) + { + if (__builtin_expect(has_facet >(__loc), true)) + { + const numpunct<_CharT>& __np = use_facet >(__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 >(__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); + } + } + + // 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; + extern template class moneypunct; + extern template class moneypunct_byname; + extern template class moneypunct_byname; + extern template class money_get; + extern template class money_put; + extern template class numpunct; + extern template class numpunct_byname; + extern template class num_get; + extern template class num_put; + extern template class __timepunct; + extern template class time_put; + extern template class time_put_byname; + extern template class time_get; + extern template class time_get_byname; + extern template class messages; + extern template class messages_byname; + extern template class ctype_byname; + extern template class codecvt_byname; + extern template class collate; + extern template class collate_byname; + + extern template + const codecvt& + use_facet >(const locale&); + + extern template + const collate& + use_facet >(const locale&); + + extern template + const numpunct& + use_facet >(const locale&); + + extern template + const num_put& + use_facet >(const locale&); + + extern template + const num_get& + use_facet >(const locale&); + + extern template + const moneypunct& + use_facet >(const locale&); + + extern template + const moneypunct& + use_facet >(const locale&); + + extern template + const money_put& + use_facet >(const locale&); + + extern template + const money_get& + use_facet >(const locale&); + + extern template + const __timepunct& + use_facet<__timepunct >(const locale&); + + extern template + const time_put& + use_facet >(const locale&); + + extern template + const time_get& + use_facet >(const locale&); + + extern template + const messages& + use_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet<__timepunct >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + +#ifdef _GLIBCPP_USE_WCHAR_T + extern template class moneypunct; + extern template class moneypunct; + extern template class moneypunct_byname; + extern template class moneypunct_byname; + extern template class money_get; + extern template class money_put; + extern template class numpunct; + extern template class numpunct_byname; + extern template class num_get; + extern template class num_put; + extern template class __timepunct; + extern template class time_put; + extern template class time_put_byname; + extern template class time_get; + extern template class time_get_byname; + extern template class messages; + extern template class messages_byname; + extern template class ctype_byname; + extern template class codecvt_byname; + extern template class collate; + extern template class collate_byname; + + extern template + const codecvt& + use_facet >(locale const&); + + extern template + const collate& + use_facet >(const locale&); + + extern template + const numpunct& + use_facet >(const locale&); + + extern template + const num_put& + use_facet >(const locale&); + + extern template + const num_get& + use_facet >(const locale&); + + extern template + const moneypunct& + use_facet >(const locale&); + + extern template + const moneypunct& + use_facet >(const locale&); + + extern template + const money_put& + use_facet >(const locale&); + + extern template + const money_get& + use_facet >(const locale&); + + extern template + const __timepunct& + use_facet<__timepunct >(const locale&); + + extern template + const time_put& + use_facet >(const locale&); + + extern template + const time_get& + use_facet >(const locale&); + + extern template + const messages& + use_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet<__timepunct >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); +#endif +#endif } // namespace std #endif