This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Slightly improved fix for libstdc++/4402


Hi again.

Considering again my patch http://gcc.gnu.org/ml/libstdc++/2001-11/msg00095.html I see now
that a much better tuning exists for the threshold value in the final if switch. A number
explicitly greater than __max_prec * 2 makes clear in the code that non-std::fixed outputs
are *always* dealt with using the automatic fast buffer: I propose __max_prec * 4 in the
following updated patch.

In short, non-std::fixed outputs are guaranteed to be processed only two-comparisons
slower than today; std::fixed outputs are dealt with with the fast automatic array most of
the cases, with the dynamically allocated array only in the most "silly" situations, i.e.
when they are very big (abs > 1e32) and are able to seg-fault in the current library;
*any* number will be safely processed :-)

Cheers,
Paolo.


*** locale_facets.tcc.orig Sat Nov 10 19:29:38 2001
--- locale_facets.tcc Mon Nov 12 22:34:30 2001
*************** namespace std
*** 872,891 ****
      {
        const streamsize __max_prec = numeric_limits<double>::digits10 + 3;
        streamsize __prec = __io.precision();
-       // Protect against sprintf() buffer overflows.
        if (__prec > __max_prec)
          __prec = __max_prec;
-       // The *2 provides for signs, exp, 'E', and pad.
-       char __sbuf[__max_prec * 2];
        size_t __slen;
        // Long enough for the max format spec.
        char __fbuf[16];
!       if (__build_float_format(__io, __fbuf, 0, __prec))
!         __slen = sprintf(__sbuf, __fbuf, __prec, __v);
        else
!         __slen = sprintf(__sbuf, __fbuf, __v);
!       // [22.2.2.2.2] Stages 2-4.
!       return __output_float(__s, __io, __fill, __sbuf, __slen);
      }

    template<typename _CharT, typename _OutIter>
--- 872,917 ----
      {
        const streamsize __max_prec = numeric_limits<double>::digits10 + 3;
        streamsize __prec = __io.precision();
        if (__prec > __max_prec)
          __prec = __max_prec;
        size_t __slen;
        // Long enough for the max format spec.
        char __fbuf[16];
!       // Upper bounding __slen
!       size_t __max_slen;
!       if (__io.flags() & ios_base::fixed)
!         // Small and big std::fixed numbers
!         if (__v > -1e32 && __v < 1e32)
!           __max_slen = 32 + __max_prec + 3;
!         else
!           __max_slen = numeric_limits<double>::max_exponent10 + __max_prec + 3;
        else
!         // The *2 provides for signs, exp, 'E'.
!         __max_slen = __max_prec * 2;
!       bool __ff = __build_float_format(__io, __fbuf, 0, __prec);
!       // Deal with both "short" and "long" numbers
!       if (__max_slen <= __max_prec * 4)
!         {
!           char __sbuf[__max_prec * 4];
!           if (__ff)
!             __slen = sprintf(__sbuf, __fbuf, __prec, __v);
!           else
!             __slen = sprintf(__sbuf, __fbuf, __v);
!           // [22.2.2.2.2] Stages 2-4.
!           return __output_float(__s, __io, __fill, __sbuf, __slen);
!         }
!       else
!         {
!           char* __sbuf = new char[__max_slen];
!           if (__ff)
!             __slen = sprintf(__sbuf, __fbuf, __prec, __v);
!           else
!             __slen = sprintf(__sbuf, __fbuf, __v);
!           // [22.2.2.2.2] Stages 2-4.
!           _OutIter __ri = __output_float(__s, __io, __fill, __sbuf, __slen);
!           delete[] __sbuf;
!           return __ri;
!         }
      }

    template<typename _CharT, typename _OutIter>
*************** namespace std
*** 896,916 ****
      {
        const streamsize __max_prec = numeric_limits<long double>::digits10 + 3;
        streamsize __prec = __io.precision();
-       // Protect against sprintf() buffer overflows.
        if (__prec > __max_prec)
          __prec = __max_prec;
-       // The *2 provides for signs, exp, 'E', and pad.
-       char __sbuf[__max_prec * 2];
        size_t __slen;
        // Long enough for the max format spec.
        char __fbuf[16];
        // 'L' as per [22.2.2.2.2] Table 59
!       if (__build_float_format(__io, __fbuf, 'L', __prec))
!         __slen = sprintf(__sbuf, __fbuf, __prec, __v);
        else
!         __slen = sprintf(__sbuf, __fbuf, __v);
!       // [22.2.2.2.2] Stages 2-4
!       return __output_float(__s, __io, __fill, __sbuf, __slen);
      }

    template<typename _CharT, typename _OutIter>
--- 922,968 ----
      {
        const streamsize __max_prec = numeric_limits<long double>::digits10 + 3;
        streamsize __prec = __io.precision();
        if (__prec > __max_prec)
          __prec = __max_prec;
        size_t __slen;
        // Long enough for the max format spec.
        char __fbuf[16];
+       // Upper bounding __slen
+       size_t __max_slen;
+       if (__io.flags() & ios_base::fixed)
+         // Small and big std::fixed numbers
+         if (__v > -1e32 && __v < 1e32)
+           __max_slen = 32 + __max_prec + 3;
+         else
+           __max_slen = numeric_limits<long double>::max_exponent10 + __max_prec + 3;
+       else
+         // The *2 provides for signs, exp, 'E'.
+         __max_slen = __max_prec * 2;
        // 'L' as per [22.2.2.2.2] Table 59
!       bool __ff = __build_float_format(__io, __fbuf, 'L', __prec);
!       // Deal with "short" and "long" numbers
!       if (__max_slen <= __max_prec * 4)
!         {
!           char __sbuf[__max_prec * 4];
!           if (__ff)
!             __slen = sprintf(__sbuf, __fbuf, __prec, __v);
!           else
!             __slen = sprintf(__sbuf, __fbuf, __v);
!           // [22.2.2.2.2] Stages 2-4.
!           return __output_float(__s, __io, __fill, __sbuf, __slen);
!         }
        else
!         {
!           char* __sbuf = new char[__max_slen];
!           if (__ff)
!             __slen = sprintf(__sbuf, __fbuf, __prec, __v);
!           else
!             __slen = sprintf(__sbuf, __fbuf, __v);
!           // [22.2.2.2.2] Stages 2-4.
!           _OutIter __ri = __output_float(__s, __io, __fill, __sbuf, __slen);
!           delete[] __sbuf;
!           return __ri;
!         }
      }

    template<typename _CharT, typename _OutIter>




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]