OSDN Git Service

2001-12-05 Benjamin Kosnik <bkoz@redhat.com>
authorbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Dec 2001 22:07:36 +0000 (22:07 +0000)
committerbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Dec 2001 22:07:36 +0000 (22:07 +0000)
DR/282
* include/bits/locale_facets.tcc (num_put::_M_widen_float): Add
grouping to floating point types.
* testsuite/27_io/ostream_inserter_arith.cc (test02): Add test.

2001-12-04  Paolo Carlini <pcarlini@unitus.it>

        libstdc++/4402
        * testsuite/27_io/ostream_inserter_arith.cc (test02): add testcase
from the PR.
        * include/bits/locale_facets.tcc (num_put::_M_convert_float):
        Deal properly with long ios_base::fixed floats.
        (num_put::_M_widen_float): use
__len in __builtin_alloca call.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@47696 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/locale_facets.tcc
libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc

index 84f842f..08d0eb8 100644 (file)
@@ -1,3 +1,20 @@
+2001-12-05  Benjamin Kosnik  <bkoz@redhat.com>
+
+       DR/282
+       * include/bits/locale_facets.tcc (num_put::_M_widen_float): Add
+       grouping to floating point types.
+       * testsuite/27_io/ostream_inserter_arith.cc (test02): Add test.
+       
+2001-12-04  Paolo Carlini <pcarlini@unitus.it>
+
+        libstdc++/4402
+        * testsuite/27_io/ostream_inserter_arith.cc (test02): add testcase
+       from the PR.
+        * include/bits/locale_facets.tcc (num_put::_M_convert_float):
+        Deal properly with long ios_base::fixed floats.
+        (num_put::_M_widen_float): use
+       __len in __builtin_alloca call.
+
 2001-12-04  Benjamin Kosnik  <bkoz@redhat.com>
 
        * src/Makefile.am (sources): Add ext-inst.cc.
index 835a0ae..95cbee5 100644 (file)
@@ -711,15 +711,23 @@ namespace std
       _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
                       _ValueT __v) const
       {
-       const streamsize __max_prec = numeric_limits<_ValueT>::digits10;
+       const int __max_digits = numeric_limits<_ValueT>::digits10;
        streamsize __prec = __io.precision();
        // Protect against sprintf() buffer overflows.
-       if (__prec > __max_prec)
-         __prec = __max_prec;
+       if (__prec > static_cast<streamsize>(__max_digits))
+         __prec = static_cast<streamsize>(__max_digits);
 
        // Long enough for the max format spec.
        char __fbuf[16];
-       char __cs[64];
+
+       // Consider the possibility of long ios_base::fixed outputs
+       const bool __fixed = __io.flags() & ios_base::fixed;
+       const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
+       // XXX Why + 4? Why * 4? What's going on? Who's on first?
+       const int __cs_size = __fixed ? __max_exp + __max_digits + 4 
+                                     : __max_digits * 4;
+       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+
        int __len;
        // [22.2.2.2.2] Stage 1, numeric conversion to character.
        if (_S_format_float(__io, __fbuf, __mod, __prec))
@@ -757,14 +765,47 @@ namespace std
       // numpunct.decimal_point() values for '.' and adding grouping.
       const locale __loc = __io.getloc();
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
+      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
+                                                          * __len));
+      // Grouping can add (almost) as many separators as the number of
+      // digits, but no more.
+      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
+                                                           * __len * 2));
       __ctype.widen(__cs, __cs + __len, __ws);
       
-      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
       // Replace decimal point.
       const _CharT* __p;
+      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
       if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.')))
        __ws[__p - __ws] = __np.decimal_point();
+
+#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
+//282. What types does numpunct grouping refer to?
+      // Add grouping, if necessary. 
+      const string __grouping = __np.grouping();
+      ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
+      if (__grouping.size())
+       {
+         _CharT* __p2;
+         int __declen = __p ? __p - __ws : __len;
+         __p2 = __add_grouping(__ws2, __np.thousands_sep(), 
+                               __grouping.c_str(),
+                               __grouping.c_str() + __grouping.size(),
+                               __ws, __ws + __declen);
+         int __newlen = __p2 - __ws2;
+       
+         // Tack on decimal part.
+         if (__p)
+           {
+             char_traits<_CharT>::copy(__p2, __p, __len - __declen);
+             __newlen += __len - __declen;
+           }    
+
+         // Switch strings, establish correct new length.
+         __ws = __ws2;
+         __len = __newlen;
+       }
+#endif
       return _M_insert(__s, __io, __fill, __ws, __len);
     }
 
@@ -778,13 +819,17 @@ namespace std
       // numpunct.decimal_point() values for '.' and adding grouping.
       const locale __loc = __io.getloc();
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
-      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
+      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
+                                                          * __len));
+      // Grouping can add (almost) as many separators as the number of
+      // digits, but no more.
+      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
+                                                           * __len * 2));
       __ctype.widen(__cs, __cs + __len, __ws);
 
       // Add grouping, if necessary.
       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
-      string __grouping = __np.grouping();
+      const string __grouping = __np.grouping();
       ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
       bool __dec = __basefield != ios_base::oct 
                   && __basefield != ios_base::hex;
@@ -810,8 +855,9 @@ namespace std
              int __len) const
     {
       // [22.2.2.2.2] Stage 3.
-      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
       streamsize __w = __io.width();
+      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
+                                                           * __w));
       if (__w > static_cast<streamsize>(__len))
        {
          __pad(__io, __fill, __ws2, __ws, __w, __len, true);
index 2e57922..580730b 100644 (file)
@@ -272,6 +272,29 @@ test02()
 #endif
   VERIFY(os && os.str() == largebuf);
 
+  // Make sure we can output a long float in fixed format
+  // without seg-faulting (libstdc++/4402)
+  double val2 = 3.5e230;
+
+  ostringstream os2;
+  os2.precision(3);
+  os2.setf(ios::fixed);
+  os2 << val2;
+
+  sprintf(largebuf, "%.*f", 3, val2);
+#ifdef TEST_NUMPUT_VERBOSE
+  cout << "expect: " << largebuf << endl;
+  cout << "result: " << os2.str() << endl;
+#endif
+  VERIFY(os2 && os2.str() == largebuf);
+
+  // Check it can be done in a locale with grouping on.
+  locale loc2("de_DE");
+  os2.imbue(loc2);
+  os2 << fixed << setprecision(3) << val2 << endl;
+  os2 << endl;
+  os2 << fixed << setprecision(1) << val2 << endl;
+
   return 0;
 }