Utils: Add senf::format::eng format manipulation members
g0dil [Wed, 30 Sep 2009 20:24:08 +0000 (20:24 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1469 270642c3-0616-0410-b53a-bc976706d245

senf/Utils/Format.cc
senf/Utils/Format.cci
senf/Utils/Format.hh
senf/Utils/Format.test.cc
senf/Utils/Statistics.cc
senf/Utils/Statistics.cci

index 3373bb8..78d3e8d 100644 (file)
@@ -50,20 +50,29 @@ prefix_ std::ostream & senf::format::operator<<(std::ostream & os, eng const & v
     boost::io::ios_base_all_saver ibas (os);
     boost::io::ios_fill_saver ifs (os);
 
+    os.setf(v_.flags_, v_.mask_);
+    if (v_.havePrecision_)
+        os.precision(v_.precision_);
+    if (v_.haveWidth_)
+        os.width(v_.width_);
+    if (v_.haveFill_)
+        os.fill(v_.fill_);
+
     unsigned prec (os.precision());
     if (prec < 4) 
         prec = 4;
     unsigned w (os.width());
     char fill (os.fill());
     unsigned minw (prec+2+((os.flags() & std::ios_base::showbase) ? 1 : 4));
-    std::ios_base::fmtflags align (os.flags() & std::ios_base::adjustfield);
-    if (! std::isnan(v_.d))
+    std::ios_base::fmtflags flags (os.flags());
+    std::ios_base::fmtflags align (flags & std::ios_base::adjustfield);
+    if (! std::isnan(v_.d_))
         minw += prec+3;
     
-    double ref (std::fabs(v_.v));
-    double v (v_.v);
-    double d (0.0);
-    if (! std::isnan(v_.d)) d = std::fabs(v_.d);
+    float ref (std::fabs(v_.v_));
+    float v (v_.v_);
+    float d (0.0);
+    if (! std::isnan(v_.d_)) d = std::fabs(v_.d_);
     int scale (0);
 
     if (d > ref) ref = d;
@@ -82,9 +91,8 @@ prefix_ std::ostream & senf::format::operator<<(std::ostream & os, eng const & v
 
     os << std::dec << std::setprecision(prec-3) << std::fixed;
     if (w > 0) {
-        if ((align == 0 || align == std::ios_base::right || align == std::ios_base::internal) 
-            && w > minw)
-            os << std::setw(prec+2+w-minw);
+        if ((align == 0 || align == std::ios_base::right || align == std::ios_base::internal))
+            os << std::setw(prec+2+(w>minw ? w-minw : 0));
         else 
             os << std::right << std::setfill(' ') << std::setw(prec+2);
     }
@@ -93,19 +101,19 @@ prefix_ std::ostream & senf::format::operator<<(std::ostream & os, eng const & v
     os << v;
 
     os << std::setfill('0') << std::noshowpos;
-    if (! std::isnan(v_.d)) {
+    if (! std::isnan(v_.d_)) {
         os << "+-";
         if (w > 0)
             os << std::setw(prec+1);
         os << d;
     }
 
-    if ((os.flags() & std::ios_base::showbase) && unsigned(std::abs(scale/3)) <= SIScales) {
+    if ((flags & std::ios_base::showbase) && unsigned(std::abs(scale/3)) <= SIScales) {
         if (w > 0 || scale != 0)
             os << SIPrefix[scale/3+SIScales];
     }
-    else if ((os.flags() & std::ios_base::showpoint) || scale != 0)
-        os << ((os.flags() & std::ios_base::uppercase)?'E':'e') 
+    else if ((flags & std::ios_base::showpoint) || scale != 0)
+        os << ((flags & std::ios_base::uppercase)?'E':'e') 
            << std::showpos << std::internal << std::setw(3) << scale;
     else if (w > 0)
         os << "    ";
index ed1ad85..7871b7d 100644 (file)
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
 
-prefix_ senf::format::eng::eng(double v_, double d_)
-    : v (v_), d (d_)
+prefix_ senf::format::eng::eng(float v, float d)
+    : v_ (v), d_ (d), haveWidth_ (false), width_ (0), havePrecision_ (false), precision_ (0),
+      haveFill_ (false), fill_ (' '), mask_ (), flags_ ()
 {}
 
+prefix_ senf::format::eng const & senf::format::eng::setw(unsigned w)
+    const
+{
+    haveWidth_ = true;
+    width_ = w;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::setprecision(unsigned p)
+    const
+{
+    havePrecision_ = true;
+    precision_ = p;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::setfill(char c)
+    const
+{
+    haveFill_ = true;
+    fill_ = c;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::showbase()
+    const
+{
+    mask_ |= std::ios_base::showbase;
+    flags_ |= std::ios_base::showbase;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::noshowbase()
+    const
+{
+    mask_ |= std::ios_base::showbase;
+    flags_ &= ~std::ios_base::showbase;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::showpos()
+    const
+{
+    mask_ |= std::ios_base::showpos;
+    flags_ |= std::ios_base::showpos;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::noshowpos()
+    const
+{
+    mask_ |= std::ios_base::showpos;
+    flags_ &= ~std::ios_base::showpos;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::showpoint()
+    const
+{
+    mask_ |= std::ios_base::showpoint;
+    flags_ |= std::ios_base::showpoint;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::noshowpoint()
+    const
+{
+    mask_ |= std::ios_base::showpoint;
+    flags_ &= ~std::ios_base::showpoint;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::uppercase()
+    const
+{
+    mask_ |= std::ios_base::uppercase;
+    flags_ |= std::ios_base::uppercase;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::nouppercase()
+    const
+{
+    mask_ |= std::ios_base::uppercase;
+    flags_ &= ~std::ios_base::uppercase;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::left()
+    const
+{
+    mask_ |= std::ios_base::adjustfield;
+    flags_ &= ~std::ios_base::adjustfield;
+    flags_ |= std::ios_base::left;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::internal()
+    const
+{
+    mask_ |= std::ios_base::adjustfield;
+    flags_ &= ~std::ios_base::adjustfield;
+    flags_ |= std::ios_base::internal;
+    return *this;
+}
+
+prefix_ senf::format::eng const & senf::format::eng::right()
+    const
+{
+    mask_ |= std::ios_base::adjustfield;
+    flags_ &= ~std::ios_base::adjustfield;
+    flags_ |= std::ios_base::right;
+    return *this;
+}
+
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
index beb5008..7e0b364 100644 (file)
@@ -59,47 +59,60 @@ namespace format {
         </pre>
 
         senf::format::eng supports several formating options:
-        \par \c std::setw()
+        \par \c std::\c setw
             If the width is set >0, the output will be padded internally. If the width is set to
             more than the minimal required output width including internal padding, the output is
             padded on the left or right depending on the streams \c ajustfield setting (changed
             with \c std::left, \c std:;right or \c std::interal). If the \c adjustfield is set to \c
             internal, padding is added between the sign and the number.
 
-        \par \c std::\c setprecision()
+        \par \c std::\c setprecision
             The default stream precision is 6. This will schow values with 6 significant digits. The
             count includes the number of digits in front of the decimal point.
 
-        \par \c std::\c showbase
+        \par \c std::\c showbase, \c std::\c noshowbase
             If the \c showbase flag is set, Instead of writing out the scale exponent in numeric
             form, output the corresponding SI prefix.
 
-        \par \c std::\c showpos
+        \par \c std::\c showpos, \c std::\c noshowpos
             If the \c showpos flag is set, positive values will have a '+' sign.
 
-        \par \c std::\c showpoint
+        \par \c std::\c showpoint, \c std::\c noshowpoint
             If the \c showpoint flag is set, the exponent will be output even if it is 0. Otherwise,
             if \c width is set, the exponent will be replaced with 4 blanks.
         
-        \par \c std::\c uppercase
+        \par \c std::\c uppercase, \c std::\c nouppercase
             If the \c uppercase flag is set, the exponent letter will be an uppercase 'E' instead of
             'e'. SI prefixes are \e not uppercased, since some SI prefixes differ only in case.
 
-        \par \c std::\c setfill()
+        \par \c std::\c setfill
             The fill character is honored for the outside padding but \e not for the internal
             padding.
 
+        \par \c std::\c left, \c std::\c internal, \c std::\c right
+            The alignment flags specify the external padding but do not affect the internal
+            padding.
+
+        All these flags may optionally be set by calling members of the senf::format::eng() return
+        value with the same name.
+
         Examples:
         \code
-            os << senf::format::eng(1.23);
-              -> "1.230"
-            os << std::setw(1) << senf::format::eng(1.23);
-              -> "   1.230    "
-            os << std::setw(25) << std::setprecision(5) << std::showpos << std::uppercase 
-               << std::internal << senf::format::eng(12345,67);
-              -> "+       12.35+-000.07E+03"
-            os << std::showbase << senf::format::eng(12345,67);
-              -> "12.345+-0.067k"
+        os << senf::format::eng(1.23);
+          -> "1.230"
+
+        os << std::setw(1) << senf::format::eng(1.23);
+          -> "   1.230    "
+
+        os << std::setw(25) << std::setprecision(5) << std::showpos << std::uppercase 
+           << std::internal << senf::format::eng(12345,67);
+          -> "+       12.35+-000.07E+03"
+
+        os << std::showbase << senf::format::eng(12345,67);
+          -> "12.345+-0.067k"
+
+        senf::str(senf::format::eng(12.345,67).setw().setprecision(5).showpoint().uppercase())
+          -> "  12.35+-67.00E+00"
         \endcode
         
         \param[in] v value
@@ -107,16 +120,46 @@ namespace format {
 
         \ingroup senf_utils_format
      */
-    streamable_type eng(double v, double d=NAN);
+    streamable_type eng(float v, float d=NAN);
 
 #else
 
-    struct eng
+    class eng
     {
-        eng(double v_, double d_ = std::numeric_limits<double>::quiet_NaN());
+    public:
+        eng(float v, float d = std::numeric_limits<float>::quiet_NaN());
+
+        eng const & setw(unsigned w = 1) const;
+        eng const & setprecision(unsigned p) const;
+        eng const & setfill(char c) const;
+
+        eng const & showbase() const;
+        eng const & noshowbase() const;
+        eng const & showpos() const;
+        eng const & noshowpos() const;
+        eng const & showpoint() const;
+        eng const & noshowpoint() const;
+        eng const & uppercase() const;
+        eng const & nouppercase() const;
+        eng const & left() const;
+        eng const & internal() const;
+        eng const & right() const;
+
+    private:
+        float v_;
+        float d_;
+        
+        mutable bool haveWidth_;
+        mutable unsigned width_;
+        mutable bool havePrecision_;
+        mutable unsigned precision_;
+        mutable bool haveFill_;
+        mutable char fill_;
+        mutable std::ios_base::fmtflags mask_;
+        mutable std::ios_base::fmtflags flags_;
+
+        friend std::ostream & operator<<(std::ostream & os, eng const & v);
 
-        double v;
-        double d;
     };
 
     std::ostream & operator<<(std::ostream & os, eng const & v);
index 996fe38..ef1a2a2 100644 (file)
@@ -31,6 +31,7 @@
 #include <iomanip>
 #include "Format.hh"
 #include <boost/cstdint.hpp>
+#include "String.hh"
 
 #include <senf/Utils/auto_unit_test.hh>
 #include <boost/test/test_tools.hpp>
@@ -112,6 +113,23 @@ BOOST_AUTO_UNIT_TEST(formatEng)
         ss << std::showbase << senf::format::eng(12345,67);
         BOOST_CHECK_EQUAL( ss.str(), "12.345+-0.067k" );
     }
+
+    // class member formatting
+    BOOST_CHECK_EQUAL( senf::str(senf::format::eng(12345, 67)
+                                 .setw()
+                                 .setprecision(5)
+                                 .setfill('0')
+                                 .showbase()
+                                 .showpos()
+                                 .internal()),
+                       "+012.35+-000.07k" );
+
+    BOOST_CHECK_EQUAL( senf::str(senf::format::eng(12.345, 67)
+                                 .setw()
+                                 .setprecision(5)
+                                 .showpoint()
+                                 .uppercase()),
+                       "  12.35+-067.00E+00" );
 }
 
 BOOST_AUTO_UNIT_TEST(dumpint)
index 730898d..a22a57e 100644 (file)
@@ -86,22 +86,20 @@ senf::StatisticsBase::output(unsigned n)
 prefix_ void senf::StatisticsBase::consoleList(unsigned level, std::ostream & os)
     const
 {
-    os << boost::format("%s%-5d%|15t|  %12s  %19.5g  %12s\n") 
-        % std::string(2*level,' ') 
-        % rank() 
-        % boost::io::group(std::setw(1),senf::format::eng(min()))
-        % boost::io::group(std::setw(1),senf::format::eng(avg(),dev()))
-        % boost::io::group(std::setw(1),senf::format::eng(max()));
+    namespace fmt = senf::format;
+
+    os << boost::format("%s%-5d%|15t|  %12.5g  %19.5g  %12.5g\n") 
+        % std::string(2*level,' ') % rank() 
+        % fmt::eng(min()).setw() % fmt::eng(avg(),dev()).setw() % fmt::eng(max()).setw();
     {
         OutputMap::const_iterator i (outputs_.begin());
         OutputMap::const_iterator i_end (outputs_.end());
         for (; i != i_end; ++i)
-            os << boost::format("            %3d  %12s  %19.5g  %12s\n")
+            os << boost::format("            %3d  %12.5g  %19.5g  %12.5g\n")
                 % i->second.n 
-                % boost::io::group(std::setw(1),senf::format::eng(i->second.min/i->second.n))
-                % boost::io::group(std::setw(1),senf::format::eng(i->second.avg/i->second.n,
-                                                                  i->second.dev/i->second.n))
-                % boost::io::group(std::setw(1),senf::format::eng(i->second.max/i->second.n));
+                % fmt::eng(i->second.min).setw() 
+                % fmt::eng(i->second.avg, i->second.dev).setw() 
+                % fmt::eng(i->second.max).setw();
     }
     {
         Children::const_iterator i (children_.begin());
@@ -130,7 +128,11 @@ prefix_ void senf::StatisticsBase::generateOutput()
             i->second.max += j->max;
             i->second.dev += j->dev;
         }
-        i->second.signal(i->second.min/n, i->second.avg/n, i->second.max/n, i->second.dev/n);
+        i->second.min /= n;
+        i->second.avg /= n;
+        i->second.max /= n;
+        i->second.dev /= n;
+        i->second.signal(i->second.min, i->second.avg, i->second.max, i->second.dev);
     }
 }
 
@@ -208,7 +210,7 @@ prefix_ senf::Statistics::Statistics()
 
 prefix_ void senf::Statistics::consoleList(std::ostream & os)
 {
-    os << "RANK        WIN           MIN                  AVG           MAX\n";
+    os << "RANK        WIN       MIN          AVG                   MAX\n";
     StatisticsBase::consoleList(0, os);
 }
 
index d58a9bd..0ed4fbd 100644 (file)
@@ -92,7 +92,7 @@ prefix_ void senf::StatisticsBase::OutputEntry::consoleList(std::ostream & os)
 // senf::StatisticsBase
 
 prefix_ senf::StatisticsBase::StatisticsBase()
-    : min_ (0.0f), avg_ (0.0f), max_ (0.0f), maxQueueLen_ (0u)
+    : min_ (0.0f), avg_ (0.0f), max_ (0.0f), dev_ (0.0f), maxQueueLen_ (0u)
 {}
 
 prefix_ senf::StatisticsBase::~StatisticsBase()