This is the mail archive of the libstdc++@sourceware.cygnus.com 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]

stream inserter implementation for double/long double


Here's my implementation of num_put::do_put() for double and long
double. I'll post my test cases shortly.

Index: locale_facets.tcc
===================================================================
RCS file: /cvs/libstdc++/libstdc++/bits/locale_facets.tcc,v
retrieving revision 1.16
diff -u -r1.16 locale_facets.tcc
--- locale_facets.tcc	1999/11/12 08:06:48	1.16
+++ locale_facets.tcc	1999/11/12 21:39:41
@@ -1023,22 +1023,119 @@
       return _S_format_long(__s, __io, __fill, false, __v);
     }
 
+  // The following code uses sprintf() to convert floating point values
for
+  // insertion into a stream. The current implementation replicates the
+  // code in _S_pad_numeric() (in _S_output_float()) in order to
prevent having to
+  // create a "wide" buffer in addition to the "narrow" buffer passed
to 
+  // sprintf(). An optimization would be to replace sprintf() with
+  // code that works directly on a wide buffer and then use
+  // _S_pad_numeric() to do the padding. It would be good to replace
+  // sprintf() anyway to avoid accidental buffer overruns and to gain
+  // back the efficiency that C++ provides by knowing up front the type
+  // of the values to insert. This implementation follows the
+  // C++ standard fairly directly as outlined in 22.2.2.2
[lib.locale.num.put]
+  bool
+    _S_build_float_format(ios_base& __io,char* __fptr,char
__modifier,streamsize __prec)
+    {
+      bool __incl_prec = false;
+      ios_base::fmtflags __flags = __io.flags();
+      *__fptr++ = '%';
+      if ( __flags & ios_base::showpos )  /* [22.2.2.2.2] Table 60 */
+	*__fptr++ = '+';
+      if ( __flags & ios_base::showpoint )
+	*__fptr++ = '#';
+      if ( __flags & ios_base::fixed || __prec > 0 ) /* as per
[22.2.2.2.2.11] */
+	{
+	  *__fptr++ = '.';
+	  *__fptr++ = '*';
+	  __incl_prec = true;
+	}
+      if ( __modifier )
+	*__fptr++ = __modifier;
+      ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
+      if ( __fltfield == ios_base::fixed )  /* [22.2.2.2.2] Table 58 */
+	*__fptr++ = 'f';
+      else if ( __fltfield == ios_base::scientific )
+	*__fptr++ = (__flags & ios_base::uppercase) ? 'E' : 'e';
+      else
+	*__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g';
+      *__fptr = '\0';
+      return __incl_prec;
+    }
+
+  template<typename _CharT,typename _OutIter>
+    _OutIter 
+    _S_output_float(_OutIter __s,ios_base& __io,_CharT __fill,const
char* __sptr,size_t __slen)
+    {
+      size_t __padding = __io.width() > streamsize(__slen) ?
+	__io.width()-__slen : 0;
+      locale __loc = __io.getloc();
+      ctype<_CharT> const& __ct = use_facet<ctype<_CharT> >(__loc);
+      ios_base::fmtflags __adjfield = __io.flags() &
ios_base::adjustfield;
+      const char* const __eptr = __sptr+__slen;
+      if ( __adjfield == ios_base::internal )  /* [22.2.2.2.2.19] Table
61 */
+	{
+	  if ( __sptr<__eptr && (*__sptr == '+' || *__sptr == '-') )
+	    __s = __ct.widen(*__sptr),++__s,++__sptr; /* [22.2.2.2.2.14];
widen() */
+	  __s = _S_fill(__s,__fill,__padding),__padding=0;
+	}
+      else if ( __adjfield != ios_base::left )
+	__s = _S_fill(__s,__fill,__padding),__padding=0;
+      char __decimal_point = *(localeconv()->decimal_point);  // the
"C" locale decimal character
+      for ( ; __sptr != __eptr ; ++__s,++__sptr )
+	{
+	  if ( *__sptr == __decimal_point ) /* [22.2.2.2.2.17]; decimal point
conversion */
+	    {
+	      const _Format_cache<_CharT>* __fmt =
_Format_cache<_CharT>::_S_get(__io);
+	      __s = __fmt->_M_decimal_point;
+	    }
+	  else
+	    __s = __ct.widen(*__sptr); /* [22.2.2.2.2.14]; widen() */
+	}
+      if ( __padding )
+	  _S_fill(__s,__fill,__padding); /* [22.2.2.2.2.19] Table 61 */
+      __io.width(0);
+      return __s;
+    }
+
   template <typename _CharT, typename _OutIter>
     _OutIter 
     num_put<_CharT, _OutIter>::
-    do_put(iter_type __s, ios_base& /*__io*/, char_type /*__fill*/,
-           double /*__v*/) const
+    do_put(iter_type __s, ios_base& __io, char_type __fill,
+           double __v) const
     {
-      return __s;  // XXX not done
+      const streamsize __max_prec = numeric_limits<double>::digits10;
+      streamsize __prec = __io.precision();
+      if ( __prec > __max_prec ) /* protect against sprintf() buffer
overflows */
+	__prec = __max_prec;
+      char __sbuf[__max_prec*2]; /* the *2 provides for signs, exp,
'E', and pad */
+      size_t __slen;
+      char __fbuf[16];  /* long enough for the max format spec */
+      if ( _S_build_float_format(__io,__fbuf,0,__prec) )
+	__slen = sprintf(__sbuf,__fbuf,__prec,__v);
+      else
+	__slen = sprintf(__sbuf,__fbuf,__v);
+      return _S_output_float(__s,__io,__fill,__sbuf,__slen);/*
[22.2.2.2.2] Stages 2-4 */
     }
 
   template <typename _CharT, typename _OutIter>
     _OutIter 
     num_put<_CharT, _OutIter>::
-    do_put(iter_type __s, ios_base& /*__io*/, char_type /*__fill*/,
-	   long double /*__v*/) const
+    do_put(iter_type __s, ios_base& __io, char_type __fill,
+	   long double __v) const
     {
-      return __s;  // XXX not done
+      const streamsize __max_prec = numeric_limits<long
double>::digits10;
+      streamsize __prec = __io.precision();
+      if ( __prec > __max_prec ) /* protect against sprintf() buffer
overflows */
+	__prec = __max_prec;
+      char __sbuf[__max_prec*2]; /* the *2 provides for signs, exp,
'E', and pad */
+      size_t __slen;
+      char __fbuf[16];  /* long enough for the max format spec */
+      if ( _S_build_float_format(__io,__fbuf,'L',__prec) ) /* 'L' as
per [22.2.2.2.2] Table 59 */
+	__slen = sprintf(__sbuf,__fbuf,__prec,__v);
+      else
+	__slen = sprintf(__sbuf,__fbuf,__v);
+      return _S_output_float(__s,__io,__fill,__sbuf,__slen);/*
[22.2.2.2.2] Stages 2-4 */
     }
 
   template <typename _CharT, typename _OutIter>
===================================================================

Best Regards,
Kevin Ediger
-- 
LI-COR, Inc.
Voice: 402.467.3576 ext 3695, Fax: 402.467.0872
mailto:kediger@licor.com
http://www.licor.com

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