[libcxx-commits] [libcxx] b889cbf - [libc++] Refactor num_put::do_put to reduce duplication
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Nov 1 07:05:25 PDT 2021
Author: Louis Dionne
Date: 2021-11-01T10:05:10-04:00
New Revision: b889cbf36635a302f5b77560f1769178f196c2c7
URL: https://github.com/llvm/llvm-project/commit/b889cbf36635a302f5b77560f1769178f196c2c7
DIFF: https://github.com/llvm/llvm-project/commit/b889cbf36635a302f5b77560f1769178f196c2c7.diff
LOG: [libc++] Refactor num_put::do_put to reduce duplication
I was going to make a change in that area of the code and I noticed that
we basically duplicated the same code 5 times to handle integral types
and floating point types. This commit simply pulls the duplication into
a function.
Differential Revision: https://reviews.llvm.org/D112830
Added:
Modified:
libcxx/include/locale
Removed:
################################################################################
diff --git a/libcxx/include/locale b/libcxx/include/locale
index c20e15f3e750b..7f5063a07650c 100644
--- a/libcxx/include/locale
+++ b/libcxx/include/locale
@@ -1360,6 +1360,18 @@ protected:
long double __v) const;
virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
const void* __v) const;
+
+ template <class _Integral>
+ _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 <class _Float>
+ _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 <class _CharT, class _OutputIterator>
@@ -1456,19 +1468,22 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
}
template <class _CharT, class _OutputIterator>
+template <class _Integral>
+_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<unsigned long>::digits / 3) // 1 char per 3 bits
- + ((numeric_limits<unsigned long>::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 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
}
+template <class _CharT, class _OutputIterator>
+_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 <class _CharT, class _OutputIterator>
_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<unsigned long long>::digits / 3) // 1 char per 3 bits
- + ((numeric_limits<unsigned long long>::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 <class _CharT, class _OutputIterator>
@@ -1518,27 +1520,7 @@ _OutputIterator
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<unsigned long>::digits / 3) // 1 char per 3 bits
- + ((numeric_limits<unsigned long>::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 <class _CharT, class _OutputIterator>
@@ -1546,37 +1528,19 @@ _OutputIterator
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<unsigned long long>::digits / 3) // 1 char per 3 bits
- + ((numeric_limits<unsigned long long>::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 <class _CharT, class _OutputIterator>
+template <class _Float>
+_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 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
return __s;
}
+template <class _CharT, class _OutputIterator>
+_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 <class _CharT, class _OutputIterator>
_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<char, void(*)(void*)> __nbh(nullptr, free);
- if (__nc > static_cast<int>(__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<char_type, void(*)(void*)> __obh(0, free);
- if (__nb != __nar)
- {
- __ob = (char_type*)malloc(2*static_cast<size_t>(__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 <class _CharT, class _OutputIterator>
More information about the libcxx-commits
mailing list