[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