#include <limits> // For numeric_limits
#include <typeinfo> // For bad_cast.
#include <bits/streambuf_iterator.h>
+#include <ext/type_traits.h>
_GLIBCXX_BEGIN_NAMESPACE(std)
_GLIBCXX_END_LDBL_NAMESPACE
- template<typename _ValueT>
- struct __to_unsigned_type
- { typedef _ValueT __type; };
-
- template<>
- struct __to_unsigned_type<long>
- { typedef unsigned long __type; };
-
-#ifdef _GLIBCXX_USE_LONG_LONG
- template<>
- struct __to_unsigned_type<long long>
- { typedef unsigned long long __type; };
-#endif
-
_GLIBCXX_BEGIN_LDBL_NAMESPACE
template<typename _CharT, typename _InIter>
ios_base::iostate& __err, _ValueT& __v) const
{
typedef char_traits<_CharT> __traits_type;
- typedef typename __to_unsigned_type<_ValueT>::__type __unsigned_type;
+ using __gnu_cxx::__add_unsigned;
+ typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
typedef __numpunct_cache<_CharT> __cache_type;
__use_cache<__cache_type> __uc;
const locale& __loc = __io._M_getloc();
_GLIBCXX_END_LDBL_NAMESPACE
- // Forwarding functions to peel signed from unsigned integer types and
- // either cast or compute the absolute value for the former, depending
- // on __basefield.
- template<typename _CharT>
- inline int
- __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
- ios_base::fmtflags __flags)
- {
- unsigned long __ul = __v;
- const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
- if (__builtin_expect(__basefield != ios_base::oct
- && __basefield != ios_base::hex, true))
- __ul = __v < 0 ? -__v : __ul;
- return __int_to_char(__bufend, __ul, __lit, __flags, false);
- }
-
- template<typename _CharT>
- inline int
- __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
- ios_base::fmtflags __flags)
- { return __int_to_char(__bufend, __v, __lit, __flags, false); }
-
-#ifdef _GLIBCXX_USE_LONG_LONG
- template<typename _CharT>
- inline int
- __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
- ios_base::fmtflags __flags)
- {
- unsigned long long __ull = __v;
- const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
- if (__builtin_expect(__basefield != ios_base::oct
- && __basefield != ios_base::hex, true))
- __ull = __v < 0 ? -__v : __ull;
- return __int_to_char(__bufend, __ull, __lit, __flags, false);
- }
-
- template<typename _CharT>
- inline int
- __int_to_char(_CharT* __bufend, unsigned long long __v,
- const _CharT* __lit, ios_base::fmtflags __flags)
- { return __int_to_char(__bufend, __v, __lit, __flags, false); }
-#endif
-
- // N.B. The last argument is currently unused (see libstdc++/20914).
template<typename _CharT, typename _ValueT>
int
__int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
- ios_base::fmtflags __flags, bool)
+ ios_base::fmtflags __flags, bool __dec)
{
- const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
_CharT* __buf = __bufend;
-
- if (__builtin_expect(__basefield != ios_base::oct
- && __basefield != ios_base::hex, true))
+ if (__builtin_expect(__dec, true))
{
// Decimal.
do
}
while (__v != 0);
}
- else if (__basefield == ios_base::oct)
+ else if ((__flags & ios_base::basefield) == ios_base::oct)
{
// Octal.
do
_M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
_ValueT __v) const
{
- typedef __numpunct_cache<_CharT> __cache_type;
+ using __gnu_cxx::__add_unsigned;
+ typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
+ typedef __numpunct_cache<_CharT> __cache_type;
__use_cache<__cache_type> __uc;
const locale& __loc = __io._M_getloc();
const __cache_type* __lc = __uc(__loc);
// [22.2.2.2.2] Stage 1, numeric conversion to character.
// Result is returned right-justified in the buffer.
- int __len = __int_to_char(__cs + __ilen, __v, __lit, __flags);
+ const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
+ const bool __dec = (__basefield != ios_base::oct
+ && __basefield != ios_base::hex);
+ const __unsigned_type __u = (__v > 0 || !__dec) ? __v : -__v;
+ int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec);
__cs += __ilen - __len;
// Add grouping, if necessary.
}
// Complete Stage 1, prepend numeric base or sign.
- const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
- if (__builtin_expect(__basefield != ios_base::oct
- && __basefield != ios_base::hex, true))
+ if (__builtin_expect(__dec, true))
{
// Decimal.
if (__v > 0)
__len = __newlen;
}
- // The following code uses snprintf (or sprintf(), when
+ // The following code uses vsnprintf (or vsprintf(), when
// _GLIBCXX_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
const __cache_type* __lc = __uc(__loc);
// Use default precision if out of range.
- streamsize __prec = __io.precision();
- if (__prec < static_cast<streamsize>(0))
- __prec = static_cast<streamsize>(6);
+ const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision();
const int __max_digits = numeric_limits<_ValueT>::digits10;
int __len;
// Long enough for the max format spec.
char __fbuf[16];
+ __num_base::_S_format_float(__io, __fbuf, __mod);
#ifdef _GLIBCXX_USE_C99
// First try a buffer perhaps big enough (most probably sufficient
// for non-ios_base::fixed outputs)
int __cs_size = __max_digits * 3;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-
- __num_base::_S_format_float(__io, __fbuf, __mod);
- __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
- _S_get_c_locale(), __prec);
+ __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+ __fbuf, __prec, __v);
// 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 = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
- _S_get_c_locale(), __prec);
+ __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+ __fbuf, __prec, __v);
}
#else
// Consider the possibility of long ios_base::fixed outputs
const int __cs_size = __fixed ? __max_exp + __prec + 4
: __max_digits * 2 + __prec;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-
- __num_base::_S_format_float(__io, __fbuf, __mod);
- __len = std::__convert_from_v(__cs, 0, __fbuf, __v,
- _S_get_c_locale(), __prec);
+ __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf,
+ __prec, __v);
#endif
// [22.2.2.2.2] Stage 2, convert to char_type, using correct
__ctype.widen(__cs, __cs + __len, __ws);
// Replace decimal point.
- const _CharT __cdec = __ctype.widen('.');
- const _CharT __dec = __lc->_M_decimal_point;
- const _CharT* __p = char_traits<_CharT>::find(__ws, __len, __cdec);
+ _CharT* __wp = 0;
+ const char* __p = char_traits<char>::find(__cs, __len, '.');
if (__p)
- __ws[__p - __ws] = __dec;
+ {
+ __wp = __ws + (__p - __cs);
+ *__wp = __lc->_M_decimal_point;
+ }
// Add grouping, if necessary.
// N.B. Make sure to not group things like 2e20, i.e., no decimal
// point, scientific notation.
if (__lc->_M_use_grouping
- && (__p || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
- && __cs[1] >= '0' && __cs[2] >= '0')))
+ && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
+ && __cs[1] >= '0' && __cs[2] >= '0')))
{
// Grouping can add (almost) as many separators as the
// number of digits, but no more.
}
_M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
- __lc->_M_thousands_sep, __p, __ws2 + __off,
+ __lc->_M_thousands_sep, __wp, __ws2 + __off,
__ws + __off, __len);
__len += __off;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 328. Bad sprintf format modifier in money_put<>::do_put()
- int __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
- _S_get_c_locale(), 0);
+ int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+ "%.*Lf", 0, __units);
// 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 = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
- _S_get_c_locale(), 0);
+ __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+ "%.*Lf", 0, __units);
}
#else
// max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
- int __len = std::__convert_from_v(__cs, 0, "%.*Lf", __units,
- _S_get_c_locale(), 0);
+ int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
+ 0, __units);
#endif
_CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __cs_size));
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
const size_t __len = char_traits<_CharT>::length(__format);
- for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
+ ios_base::iostate __tmperr = ios_base::goodbit;
+ for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
{
if (__ctype.narrow(__format[__i], 0) == '%')
{
const char_type* __days1[7];
__tp._M_days_abbreviated(__days1);
__beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
- 7, __io, __err);
+ 7, __io, __tmperr);
break;
case 'A':
// Weekday name [tm_wday].
const char_type* __days2[7];
__tp._M_days(__days2);
__beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
- 7, __io, __err);
+ 7, __io, __tmperr);
break;
case 'h':
case 'b':
const char_type* __months1[12];
__tp._M_months_abbreviated(__months1);
__beg = _M_extract_name(__beg, __end, __tm->tm_mon,
- __months1, 12, __io, __err);
+ __months1, 12, __io, __tmperr);
break;
case 'B':
// Month name [tm_mon].
const char_type* __months2[12];
__tp._M_months(__months2);
__beg = _M_extract_name(__beg, __end, __tm->tm_mon,
- __months2, 12, __io, __err);
+ __months2, 12, __io, __tmperr);
break;
case 'c':
// Default time and date representation.
const char_type* __dt[2];
__tp._M_date_time_formats(__dt);
- __beg = _M_extract_via_format(__beg, __end, __io, __err,
+ __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
__tm, __dt[0]);
break;
case 'd':
// Day [01, 31]. [tm_mday]
__beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
- __io, __err);
+ __io, __tmperr);
break;
case 'e':
// Day [1, 31], with single digits preceded by
// space. [tm_mday]
if (__ctype.is(ctype_base::space, *__beg))
__beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
- 1, __io, __err);
+ 1, __io, __tmperr);
else
__beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
- 2, __io, __err);
+ 2, __io, __tmperr);
break;
case 'D':
// Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
__cs = "%m/%d/%y";
__ctype.widen(__cs, __cs + 9, __wcs);
- __beg = _M_extract_via_format(__beg, __end, __io, __err,
+ __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
__tm, __wcs);
break;
case 'H':
// Hour [00, 23]. [tm_hour]
__beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
- __io, __err);
+ __io, __tmperr);
break;
case 'I':
// Hour [01, 12]. [tm_hour]
__beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
- __io, __err);
+ __io, __tmperr);
break;
case 'm':
// Month [01, 12]. [tm_mon]
__beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
- __io, __err);
- if (!__err)
+ __io, __tmperr);
+ if (!__tmperr)
__tm->tm_mon = __mem - 1;
break;
case 'M':
// Minute [00, 59]. [tm_min]
__beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
- __io, __err);
+ __io, __tmperr);
break;
case 'n':
if (__ctype.narrow(*__beg, 0) == '\n')
++__beg;
else
- __err |= ios_base::failbit;
+ __tmperr |= ios_base::failbit;
break;
case 'R':
// Equivalent to (%H:%M).
__cs = "%H:%M";
__ctype.widen(__cs, __cs + 6, __wcs);
- __beg = _M_extract_via_format(__beg, __end, __io, __err,
+ __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
__tm, __wcs);
break;
case 'S':
#else
__beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
#endif
- __io, __err);
+ __io, __tmperr);
break;
case 't':
if (__ctype.narrow(*__beg, 0) == '\t')
++__beg;
else
- __err |= ios_base::failbit;
+ __tmperr |= ios_base::failbit;
break;
case 'T':
// Equivalent to (%H:%M:%S).
__cs = "%H:%M:%S";
__ctype.widen(__cs, __cs + 9, __wcs);
- __beg = _M_extract_via_format(__beg, __end, __io, __err,
+ __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
__tm, __wcs);
break;
case 'x':
// Locale's date.
const char_type* __dates[2];
__tp._M_date_formats(__dates);
- __beg = _M_extract_via_format(__beg, __end, __io, __err,
+ __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
__tm, __dates[0]);
break;
case 'X':
// Locale's time.
const char_type* __times[2];
__tp._M_time_formats(__times);
- __beg = _M_extract_via_format(__beg, __end, __io, __err,
+ __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
__tm, __times[0]);
break;
case 'y':
case 'C': // C99
// Two digit year. [tm_year]
__beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
- __io, __err);
+ __io, __tmperr);
break;
case 'Y':
// Year [1900). [tm_year]
__beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
- __io, __err);
- if (!__err)
+ __io, __tmperr);
+ if (!__tmperr)
__tm->tm_year = __mem - 1900;
break;
case 'Z':
int __tmp;
__beg = _M_extract_name(__beg, __end, __tmp,
__timepunct_cache<_CharT>::_S_timezones,
- 14, __io, __err);
+ 14, __io, __tmperr);
// GMT requires special effort.
- if (__beg != __end && !__err && __tmp == 0
+ if (__beg != __end && !__tmperr && __tmp == 0
&& (*__beg == __ctype.widen('-')
|| *__beg == __ctype.widen('+')))
{
__beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
- __io, __err);
+ __io, __tmperr);
__beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
- __io, __err);
+ __io, __tmperr);
}
}
else
- __err |= ios_base::failbit;
+ __tmperr |= ios_base::failbit;
break;
default:
// Not recognized.
- __err |= ios_base::failbit;
+ __tmperr |= ios_base::failbit;
}
}
else
if (__format[__i] == *__beg)
++__beg;
else
- __err |= ios_base::failbit;
+ __tmperr |= ios_base::failbit;
}
}
+
+ if (__tmperr)
+ __err |= ios_base::failbit;
+
return __beg;
}
__member = __value;
else
__err |= ios_base::failbit;
+
return __beg;
}
__testvalid = false;
if (!__testvalid)
__err |= ios_base::failbit;
+
return __beg;
}
const char_type* __days[7];
__tp._M_days_abbreviated(__days);
int __tmpwday;
- __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err);
+ ios_base::iostate __tmperr = ios_base::goodbit;
+ __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
+ __io, __tmperr);
// Check to see if non-abbreviated name exists, and extract.
// NB: Assumes both _M_days and _M_days_abbreviated organized in
// __days array with the same index points to a day, and that
// day's abbreviated form.
// NB: Also assumes that an abbreviated name is a subset of the name.
- if (!__err && __beg != __end)
+ if (!__tmperr && __beg != __end)
{
size_t __pos = __traits_type::length(__days[__tmpwday]);
__tp._M_days(__days);
&& __name[__pos] == *__beg)
++__beg, ++__pos;
if (__len != __pos)
- __err |= ios_base::failbit;
+ __tmperr |= ios_base::failbit;
}
}
- if (!__err)
+ if (!__tmperr)
__tm->tm_wday = __tmpwday;
-
+ else
+ __err |= ios_base::failbit;
+
if (__beg == __end)
__err |= ios_base::eofbit;
return __beg;
const char_type* __months[12];
__tp._M_months_abbreviated(__months);
int __tmpmon;
+ ios_base::iostate __tmperr = ios_base::goodbit;
__beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12,
- __io, __err);
+ __io, __tmperr);
// Check to see if non-abbreviated name exists, and extract.
// NB: Assumes both _M_months and _M_months_abbreviated organized in
// __months array with the same index points to a month, and that
// month's abbreviated form.
// NB: Also assumes that an abbreviated name is a subset of the name.
- if (!__err && __beg != __end)
+ if (!__tmperr && __beg != __end)
{
size_t __pos = __traits_type::length(__months[__tmpmon]);
__tp._M_months(__months);
&& __name[__pos] == *__beg)
++__beg, ++__pos;
if (__len != __pos)
- __err |= ios_base::failbit;
+ __tmperr |= ios_base::failbit;
}
}
- if (!__err)
+ if (!__tmperr)
__tm->tm_mon = __tmpmon;
+ else
+ __err |= ios_base::failbit;
if (__beg == __end)
__err |= ios_base::eofbit;
__tm->tm_year = __i == 2 ? __value : __value - 1900;
else
__err |= ios_base::failbit;
+
if (__beg == __end)
__err |= ios_base::eofbit;
return __beg;
collate<_CharT>::
do_transform(const _CharT* __lo, const _CharT* __hi) const
{
+ string_type __ret;
+
// strxfrm assumes zero-terminated strings so we make a copy
- string_type __str(__lo, __hi);
+ const string_type __str(__lo, __hi);
const _CharT* __p = __str.c_str();
const _CharT* __pend = __str.data() + __str.length();
size_t __len = (__hi - __lo) * 2;
- string_type __ret;
+ _CharT* __c = new _CharT[__len];
- // strxfrm stops when it sees a nul character so we break
- // the string into zero-terminated substrings and pass those
- // to strxfrm.
- for (;;)
+ try
{
- // 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)
+ // strxfrm stops when it sees a nul character so we break
+ // the string into zero-terminated substrings and pass those
+ // to strxfrm.
+ for (;;)
{
- __len = __res + 1;
- __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
- * __len));
- __res = _M_transform(__c, __p, __len);
- }
+ // First try a buffer perhaps big enough.
+ 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;
+ delete [] __c, __c = 0;
+ __c = new _CharT[__len];
+ __res = _M_transform(__c, __p, __len);
+ }
- __ret.append(__c, __res);
- __p += char_traits<_CharT>::length(__p);
- if (__p == __pend)
- return __ret;
+ __ret.append(__c, __res);
+ __p += char_traits<_CharT>::length(__p);
+ if (__p == __pend)
+ break;
- __p++;
- __ret.push_back(_CharT());
+ __p++;
+ __ret.push_back(_CharT());
+ }
}
+ catch(...)
+ {
+ delete [] __c;
+ __throw_exception_again;
+ }
+
+ delete [] __c;
+
+ return __ret;
}
template<typename _CharT>