diff --git a/libcxx/include/locale b/libcxx/include/locale --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -1360,6 +1360,18 @@ long double __v) const; virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const; + + template + _LIBCPP_HIDE_FROM_ABI inline + _OutputIterator __do_put_integral(iter_type __s, ios_base& __iob, + char_type __fl, _Integral __v, + char const* __len) const; + + template + _LIBCPP_HIDE_FROM_ABI inline + _OutputIterator __do_put_floating_point(iter_type __s, ios_base& __iob, + char_type __fl, _Float __v, + char const* __len) const; }; template @@ -1456,19 +1468,22 @@ } template +template +_LIBCPP_HIDE_FROM_ABI inline _OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, - char_type __fl, long __v) const +num_put<_CharT, _OutputIterator>::__do_put_integral(iter_type __s, ios_base& __iob, + char_type __fl, _Integral __v, + char const* __len) const { // Stage 1 - Get number in narrow char char __fmt[6] = {'%', 0}; - const char* __len = "l"; - this->__format_int(__fmt+1, __len, true, __iob.flags()); + this->__format_int(__fmt+1, __len, is_signed<_Integral>::value, __iob.flags()); // Worst case is octal, with showbase enabled. Note that octal is always // printed as an unsigned value. + using _Unsigned = typename make_unsigned<_Integral>::type; _LIBCPP_CONSTEXPR const unsigned __nbuf - = (numeric_limits::digits / 3) // 1 char per 3 bits - + ((numeric_limits::digits % 3) != 0) // round up + = (numeric_limits<_Unsigned>::digits / 3) // 1 char per 3 bits + + ((numeric_limits<_Unsigned>::digits % 3) != 0) // round up + 2; // base prefix + terminating null character char __nar[__nbuf]; int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); @@ -1484,33 +1499,20 @@ return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); } +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, + char_type __fl, long __v) const +{ + return this->__do_put_integral(__s, __iob, __fl, __v, "l"); +} + template _OutputIterator num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { - // Stage 1 - Get number in narrow char - char __fmt[8] = {'%', 0}; - const char* __len = "ll"; - this->__format_int(__fmt+1, __len, true, __iob.flags()); - // Worst case is octal, with showbase enabled. Note that octal is always - // printed as an unsigned value. - _LIBCPP_CONSTEXPR const unsigned __nbuf - = (numeric_limits::digits / 3) // 1 char per 3 bits - + ((numeric_limits::digits % 3) != 0) // round up - + 2; // base prefix + terminating null character - char __nar[__nbuf]; - int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); - char* __ne = __nar + __nc; - char* __np = this->__identify_padding(__nar, __ne, __iob); - // Stage 2 - Widen __nar while adding thousands separators - char_type __o[2*(__nbuf-1) - 1]; - char_type* __op; // pad here - char_type* __oe; // end of output - this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc()); - // [__o, __oe) contains thousands_sep'd wide number - // Stage 3 & 4 - return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); + return this->__do_put_integral(__s, __iob, __fl, __v, "ll"); } template @@ -1518,27 +1520,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { - // Stage 1 - Get number in narrow char - char __fmt[6] = {'%', 0}; - const char* __len = "l"; - this->__format_int(__fmt+1, __len, false, __iob.flags()); - // Worst case is octal, with showbase enabled. - _LIBCPP_CONSTEXPR const unsigned __nbuf - = (numeric_limits::digits / 3) // 1 char per 3 bits - + ((numeric_limits::digits % 3) != 0) // round up - + 2; // base prefix + terminating null character - char __nar[__nbuf]; - int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); - char* __ne = __nar + __nc; - char* __np = this->__identify_padding(__nar, __ne, __iob); - // Stage 2 - Widen __nar while adding thousands separators - char_type __o[2*(__nbuf-1) - 1]; - char_type* __op; // pad here - char_type* __oe; // end of output - this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc()); - // [__o, __oe) contains thousands_sep'd wide number - // Stage 3 & 4 - return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); + return this->__do_put_integral(__s, __iob, __fl, __v, "l"); } template @@ -1546,37 +1528,19 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { - // Stage 1 - Get number in narrow char - char __fmt[8] = {'%', 0}; - const char* __len = "ll"; - this->__format_int(__fmt+1, __len, false, __iob.flags()); - // Worst case is octal, with showbase enabled. - _LIBCPP_CONSTEXPR const unsigned __nbuf - = (numeric_limits::digits / 3) // 1 char per 3 bits - + ((numeric_limits::digits % 3) != 0) // round up - + 2; // base prefix + terminating null character - char __nar[__nbuf]; - int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); - char* __ne = __nar + __nc; - char* __np = this->__identify_padding(__nar, __ne, __iob); - // Stage 2 - Widen __nar while adding thousands separators - char_type __o[2*(__nbuf-1) - 1]; - char_type* __op; // pad here - char_type* __oe; // end of output - this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc()); - // [__o, __oe) contains thousands_sep'd wide number - // Stage 3 & 4 - return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); + return this->__do_put_integral(__s, __iob, __fl, __v, "ll"); } template +template +_LIBCPP_HIDE_FROM_ABI inline _OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, - char_type __fl, double __v) const +num_put<_CharT, _OutputIterator>::__do_put_floating_point(iter_type __s, ios_base& __iob, + char_type __fl, _Float __v, + char const* __len) const { // Stage 1 - Get number in narrow char char __fmt[8] = {'%', 0}; - const char* __len = ""; bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags()); const unsigned __nbuf = 30; char __nar[__nbuf]; @@ -1620,55 +1584,20 @@ return __s; } +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, + char_type __fl, double __v) const +{ + return this->__do_put_floating_point(__s, __iob, __fl, __v, ""); +} + template _OutputIterator num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { - // Stage 1 - Get number in narrow char - char __fmt[8] = {'%', 0}; - const char* __len = "L"; - bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags()); - const unsigned __nbuf = 30; - char __nar[__nbuf]; - char* __nb = __nar; - int __nc; - if (__specify_precision) - __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, - (int)__iob.precision(), __v); - else - __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v); - unique_ptr __nbh(nullptr, free); - if (__nc > static_cast(__nbuf-1)) - { - if (__specify_precision) - __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); - else - __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v); - if (__nc == -1) - __throw_bad_alloc(); - __nbh.reset(__nb); - } - char* __ne = __nb + __nc; - char* __np = this->__identify_padding(__nb, __ne, __iob); - // Stage 2 - Widen __nar while adding thousands separators - char_type __o[2*(__nbuf-1) - 1]; - char_type* __ob = __o; - unique_ptr __obh(0, free); - if (__nb != __nar) - { - __ob = (char_type*)malloc(2*static_cast(__nc)*sizeof(char_type)); - if (__ob == 0) - __throw_bad_alloc(); - __obh.reset(__ob); - } - char_type* __op; // pad here - char_type* __oe; // end of output - this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc()); - // [__o, __oe) contains thousands_sep'd wide number - // Stage 3 & 4 - __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl); - return __s; + return this->__do_put_floating_point(__s, __iob, __fl, __v, "L"); } template