Utils: Formating helpers (senf::format::eng, senf::format::dumpint)
g0dil [Wed, 30 Sep 2009 15:04:57 +0000 (15:04 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1468 270642c3-0616-0410-b53a-bc976706d245

14 files changed:
senf/Packets/DefaultBundle/EthernetPacket.cc
senf/Packets/DumpFormat.cc
senf/Packets/DumpFormat.hh
senf/Packets/DumpFormat.test.cc
senf/Packets/PacketRegistry.ct
senf/Utils/Format.cc [new file with mode: 0644]
senf/Utils/Format.cci [copied from senf/Packets/DumpFormat.ih with 72% similarity]
senf/Utils/Format.cti [moved from senf/Packets/DumpFormat.ct with 69% similarity]
senf/Utils/Format.hh [new file with mode: 0644]
senf/Utils/Format.ih [moved from senf/Packets/DumpFormat.ih with 83% similarity]
senf/Utils/Format.test.cc [new file with mode: 0644]
senf/Utils/Mainpage.dox
senf/Utils/Statistics.cc
senf/Utils/Statistics.test.cc

index 30e8e8d..04a87af 100644 (file)
@@ -30,6 +30,7 @@
 #include "LlcSnapPacket.hh"
 #include <iomanip>
 #include <boost/io/ios_state.hpp>
+#include <senf/Utils/Format.hh>
 
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
@@ -53,7 +54,7 @@ prefix_ void senf::EthernetPacketType::dump(packet p, std::ostream & os)
     os <<     ": \n"
        << senf::fieldName("destination")               << p->destination() << "\n"
        << senf::fieldName("source")                    << p->source() << "\n"
-       << senf::fieldName("type/length")               << senf::prettyNumber(p->type_length().value()) << "\n";
+       << senf::fieldName("type/length")               << senf::format::dumpint(p->type_length().value()) << "\n";
 }
 
 prefix_ senf::PacketInterpreterBase::factory_t senf::EthernetPacketType::nextPacketType(packet p)
index 2c99df2..de102c7 100644 (file)
@@ -24,7 +24,7 @@
     \brief DumpFormat non-inline non-template implementation */
 
 #include "Packets.hh"
-#include "DumpFormat.ih"
+//#include "DumpFormat.ih"
 
 // Custom includes
 #include <iostream>
@@ -46,36 +46,6 @@ prefix_ std::string senf::fieldName(std::string const & s)
     return t;
 }
 
-prefix_ std::string senf::detail::prettySignedNumber(long long v, unsigned bits)
-{
-    if (v<0) return prettyUnsignedNumber(-v,bits,-1);
-    else     return prettyUnsignedNumber(v,bits,+1);
-}
-
-prefix_ std::string senf::detail::prettyUnsignedNumber(unsigned long long v, unsigned bits,
-                                                       int sign)
-{
-    int bytes ((bits+7)/8);
-    int digs (int(2.4*bytes)+1);
-    std::stringstream ss;
-    ss << (sign ? (sign<0 ? "-" : " ") : "") 
-       << "0x" << std::setw(2*bytes) << std::setfill('0') << std::hex 
-       << 1u*v
-       << " (" << std::setw(digs+(sign ? 1 : 0)) << std::setfill(' ') << std::dec;
-    if (sign)
-        ss << sign*static_cast<long long>(v);
-    else
-        ss << 1u*v;
-    ss << ") (";
-    for (int i (bytes-1); i>=0; --i) {
-        char c ((v>>(8*i))&0xff);
-        ss << ((c>=32 && c<=127) ? c : '.');
-    }
-    ss << ')';
-    return ss.str();
-}
-
-
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "DumpFormat.mpp"
index 0d1cea2..cb3e09d 100644 (file)
@@ -42,13 +42,6 @@ namespace senf {
 
     std::string fieldName(std::string const & s);
     
-    template <class T> 
-    std::string prettyNumber(T const & v, 
-                             typename boost::enable_if<boost::is_signed<T> >::type * = 0);
-
-    template <class T> 
-    std::string prettyNumber(T const & v, 
-                             typename boost::enable_if<boost::is_unsigned<T> >::type * = 0);
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
@@ -56,7 +49,7 @@ namespace senf {
 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_DumpFormat_i_)
 #define HH_SENF_Packets_DumpFormat_i_
 //#include "DumpFormat.cci"
-#include "DumpFormat.ct"
+//#include "DumpFormat.ct"
 //#include "DumpFormat.cti"
 #endif
 
index 37ab50f..87463fc 100644 (file)
@@ -40,10 +40,6 @@ BOOST_AUTO_UNIT_TEST(dumpFormat)
     BOOST_CHECK_EQUAL( senf::fieldName("test"), "  test                    : " );
     BOOST_CHECK_EQUAL( senf::fieldName("xxxxxxxxxxxxxxxxxxxxxxx"), "  xxxxxxxxxxxxxxxxxxxxxxx : " );
     BOOST_CHECK_EQUAL( senf::fieldName("xxxxxxxxxxxxxxxxxxxxxxxx"), "  xxxxxxxxxxxxxxxxxxxxxxxx : " );
-
-    BOOST_CHECK_EQUAL( senf::prettyNumber<boost::int16_t>(-1), "-0x0001 (    -1) (..)" );
-    BOOST_CHECK_EQUAL( senf::prettyNumber<boost::int16_t>(1), " 0x0001 (     1) (..)" );
-    BOOST_CHECK_EQUAL( senf::prettyNumber<boost::uint16_t>(1), "0x0001 (    1) (..)" );
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index cda493b..b4babcc 100644 (file)
@@ -31,6 +31,7 @@
 #include <iomanip>
 #include <cmath>
 #include <senf/Utils/TypeInfo.hh>
+#include <senf/Utils/Format.hh>
 
 #define prefix_
 ///////////////////////////////ct.p////////////////////////////////////////
@@ -169,7 +170,7 @@ prefix_ void senf::detail::DumpKey<KeyType,is_integral>::dump(KeyType const & v,
 template <class KeyType>
 prefix_ void senf::detail::DumpKey<KeyType, true>::dump(KeyType const & v, std::ostream & os)
 {
-    os << "  " << senf::prettyNumber(v);
+    os << "  " << senf::format::dumpint(v);
 }
 
 ///////////////////////////////ct.e////////////////////////////////////////
diff --git a/senf/Utils/Format.cc b/senf/Utils/Format.cc
new file mode 100644 (file)
index 0000000..3373bb8
--- /dev/null
@@ -0,0 +1,161 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Format non-inline non-template implementation */
+
+#include "Format.hh"
+#include "Format.ih"
+
+// Custom includes
+#include <cmath>
+#include <boost/io/ios_state.hpp>
+#include <iomanip>
+#include <sstream>
+
+//#include "Format.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+
+    char const SIPrefix[] = { 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm', 
+                              ' ', 
+                              'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
+    unsigned const SIScales = 8;
+
+}
+
+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);
+
+    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))
+        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);
+    int scale (0);
+
+    if (d > ref) ref = d;
+    while (ref >= 1000.0) {
+        ref /= 1000.0;
+        v /= 1000.0;
+        d /= 1000.0;
+        scale += 3;
+    }
+    while (ref > 0 && ref < 1) {
+        ref *= 1000.0;
+        v *= 1000.0;
+        d *= 1000.0;
+        scale -= 3;
+    }
+
+    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);
+        else 
+            os << std::right << std::setfill(' ') << std::setw(prec+2);
+    }
+    else
+        os << std::right;
+    os << v;
+
+    os << std::setfill('0') << std::noshowpos;
+    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 (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') 
+           << std::showpos << std::internal << std::setw(3) << scale;
+    else if (w > 0)
+        os << "    ";
+    if (w > minw && align == std::ios_base::left)
+        os << std::setfill(fill) << std::setw(w-minw) << "";
+
+    return os;
+}
+
+prefix_ std::string senf::format::detail::dumpintSigned(long long v, unsigned bits)
+{
+    if (v<0) return dumpintUnsigned(-v,bits,-1);
+    else     return dumpintUnsigned(v,bits,+1);
+}
+
+prefix_ std::string senf::format::detail::dumpintUnsigned(unsigned long long v, unsigned bits,
+                                                          int sign)
+{
+    int bytes ((bits+7)/8);
+    int digs (int(2.4*bytes)+1);
+    std::stringstream ss;
+    ss << (sign ? (sign<0 ? "-" : " ") : "") 
+       << "0x" << std::setw(2*bytes) << std::setfill('0') << std::hex 
+       << 1u*v
+       << " (" << std::setw(digs+(sign ? 1 : 0)) << std::setfill(' ') << std::dec;
+    if (sign)
+        ss << sign*static_cast<long long>(v);
+    else
+        ss << 1u*v;
+    ss << ") (";
+    for (int i (bytes-1); i>=0; --i) {
+        char c ((v>>(8*i))&0xff);
+        ss << ((c>=32 && c<=127) ? c : '.');
+    }
+    ss << ')';
+    return ss.str();
+}
+
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Format.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
similarity index 72%
copy from senf/Packets/DumpFormat.ih
copy to senf/Utils/Format.cci
index 302cb8d..ed1ad85 100644 (file)
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief DumpFormat internal header */
+    \brief Format inline non-template implementation */
 
-#ifndef IH_SENF_senf_Packets_DumpFormat_
-#define IH_SENF_senf_Packets_DumpFormat_ 1
+#include "Format.ih"
 
 // Custom includes
 
-///////////////////////////////ih.p////////////////////////////////////////
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
 
-namespace senf {
-namespace detail {
+prefix_ senf::format::eng::eng(double v_, double d_)
+    : v (v_), d (d_)
+{}
 
-    std::string prettySignedNumber(long long v, unsigned bits);
-    std::string prettyUnsignedNumber(unsigned long long v, unsigned bits, int sign=0);
-
-}}
-
-///////////////////////////////ih.e////////////////////////////////////////
-#endif
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
 
 \f
 // Local Variables:
similarity index 69%
rename from senf/Packets/DumpFormat.ct
rename to senf/Utils/Format.cti
index 93650c5..41b8ab4 100644 (file)
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief DumpFormat non-inline template implementation  */
+    \brief Format inline template implementation */
 
-#include "DumpFormat.ih"
+#include "Format.ih"
 
 // Custom includes
-#include <sstream>
 
-#define prefix_
-///////////////////////////////ct.p////////////////////////////////////////
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
 
 template <class T>
 prefix_ std::string 
-senf::prettyNumber(T const & v, typename boost::enable_if<boost::is_signed<T> >::type *)
+senf::format::dumpint(T const & v, typename boost::enable_if<boost::is_signed<T> >::type *)
 { 
-   return detail::prettySignedNumber(v, std::numeric_limits<T>::digits);
+   return detail::dumpintSigned(v, std::numeric_limits<T>::digits);
 }
 
 template <class T>
 prefix_ std::string
-senf::prettyNumber(T const & v, typename boost::enable_if<boost::is_unsigned<T> >::type *)
+senf::format::dumpint(T const & v, typename boost::enable_if<boost::is_unsigned<T> >::type *)
 {
-   return detail::prettyUnsignedNumber(v, std::numeric_limits<T>::digits); 
+   return detail::dumpintUnsigned(v, std::numeric_limits<T>::digits); 
 }
 
-///////////////////////////////ct.e////////////////////////////////////////
+///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
 \f
diff --git a/senf/Utils/Format.hh b/senf/Utils/Format.hh
new file mode 100644 (file)
index 0000000..beb5008
--- /dev/null
@@ -0,0 +1,173 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Format public header */
+
+#ifndef HH_SENF_senf_Utils_Format_
+#define HH_SENF_senf_Utils_Format_ 1
+
+// Custom includes
+#include <limits>
+#include <iostream>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_signed.hpp>
+#include <boost/type_traits/is_unsigned.hpp>
+
+//#include "Format.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace format {
+
+    /** \defgroup senf_utils_format Formating
+     */
+
+#ifdef DOXYGEN
+
+    /** \brief Format value in engineering representation
+
+        The engineering representation is an exponential representation. Exponents however are
+        always multiples of 3:
+        <pre>
+        123.45   -> 123.450e+00
+        123.45e2 ->  12.345e+03
+        </pre>
+
+        Additionally, an optional delta value may be displayed:
+        <pre>
+        123.45+-1.34e+03
+        </pre>
+
+        senf::format::eng supports several formating options:
+        \par \c std::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()
+            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
+            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
+            If the \c showpos flag is set, positive values will have a '+' sign.
+
+        \par \c std::\c showpoint
+            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
+            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()
+            The fill character is honored for the outside padding but \e not for the internal
+            padding.
+
+        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"
+        \endcode
+        
+        \param[in] v value
+        \param[in] d optional delta
+
+        \ingroup senf_utils_format
+     */
+    streamable_type eng(double v, double d=NAN);
+
+#else
+
+    struct eng
+    {
+        eng(double v_, double d_ = std::numeric_limits<double>::quiet_NaN());
+
+        double v;
+        double d;
+    };
+
+    std::ostream & operator<<(std::ostream & os, eng const & v);
+
+#endif
+
+#ifdef DOXYGEN
+
+    /** \brief Dump integer value with internal representation
+
+        senf::format::dumpint() will output a signed or unsigned numeric argument in the following
+        representations:
+        \li hexadecimal notation
+        \li decimal notation
+        \li byte values interpreted as ASCII characters (in network byte order)
+
+        All fields will be padded depending on the size of the type to a byte boundary (e.g. a 32bit
+        integer type will be padded to 8 hex-digits, 10 decimal digits and 4 ASCII characters)
+
+        \ingroup senf_utils_format
+     */
+    template <class T>
+    streamable_type dumpint(T const & v);
+
+#else 
+
+    template <class T> 
+    std::string dumpint(T const & v, 
+                        typename boost::enable_if<boost::is_signed<T> >::type * = 0);
+
+    template <class T> 
+    std::string dumpint(T const & v, 
+                        typename boost::enable_if<boost::is_unsigned<T> >::type * = 0);
+
+#endif
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "Format.cci"
+//#include "Format.ct"
+#include "Format.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
similarity index 83%
rename from senf/Packets/DumpFormat.ih
rename to senf/Utils/Format.ih
index 302cb8d..0a4a709 100644 (file)
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief DumpFormat internal header */
+    \brief Format internal header */
 
-#ifndef IH_SENF_senf_Packets_DumpFormat_
-#define IH_SENF_senf_Packets_DumpFormat_ 1
+#ifndef IH_SENF_senf_Utils_Format_
+#define IH_SENF_senf_Utils_Format_ 1
 
 // Custom includes
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
 namespace senf {
+namespace format {
 namespace detail {
 
-    std::string prettySignedNumber(long long v, unsigned bits);
-    std::string prettyUnsignedNumber(unsigned long long v, unsigned bits, int sign=0);
+    std::string dumpintSigned(long long v, unsigned bits);
+    std::string dumpintUnsigned(unsigned long long v, unsigned bits, int sign=0);
 
-}}
+}}}
 
 ///////////////////////////////ih.e////////////////////////////////////////
 #endif
diff --git a/senf/Utils/Format.test.cc b/senf/Utils/Format.test.cc
new file mode 100644 (file)
index 0000000..996fe38
--- /dev/null
@@ -0,0 +1,146 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Format.test unit tests */
+
+//#include "Format.test.hh"
+//#include "Format.test.ih"
+
+// Custom includes
+#include <sstream>
+#include <iomanip>
+#include "Format.hh"
+#include <boost/cstdint.hpp>
+
+#include <senf/Utils/auto_unit_test.hh>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+BOOST_AUTO_UNIT_TEST(formatEng)
+{
+    std::stringstream ss;
+
+#   define CheckFormat(v,s)                                             \
+        {                                                               \
+            ss.str("");                                                 \
+            ss << senf::format::eng v;                                  \
+            BOOST_CHECK_EQUAL( ss.str(), s );                           \
+        }
+
+    ss << std::setw(21);
+
+    CheckFormat( (0.0),                      "            0.000    " );
+    CheckFormat( (-1.4431288e5, 2.26338e4),  "-144.313+-022.634e+03" );
+    CheckFormat( (1.4444e-13, 2.111111e-16), " 144.440+-000.211e-15" );
+    CheckFormat( (1.345e-3, 3.456),          "   0.001+-003.456    " );
+
+    ss << std::setprecision(4) << std::uppercase << std::showpoint;
+
+    CheckFormat( (0.0),                      "              0.0E+00" );
+    CheckFormat( (-1.4431288e5, 2.26338e4),  "    -144.3+-022.6E+03" );
+    CheckFormat( (1.4444e-13, 2.111111e-16), "     144.4+-000.2E-15" );
+    CheckFormat( (1.345e-3, 3.456),          "       0.0+-003.5E+00" );
+
+    ss << std::showbase << std::internal << std::showpos << std::setfill('0');
+
+    CheckFormat( (0.0),                      "+00000000000000000.0 " );
+    CheckFormat( (-1.4431288e5, 2.26338e4),  "-0000000144.3+-022.6k" );
+    CheckFormat( (1.4444e-13, 2.111111e-16), "+0000000144.4+-000.2f" );
+    CheckFormat( (1.345e-3, 3.456),          "+0000000000.0+-003.5 " );
+
+    ss << std::left << std::noshowpos << std::setfill('*');
+
+    CheckFormat( (0.0),                      "   0.0 **************" );
+    CheckFormat( (-1.4431288e5, 2.26338e4),  "-144.3+-022.6k*******" );
+    CheckFormat( (1.4444e-13, 2.111111e-16), " 144.4+-000.2f*******" );
+    CheckFormat( (1.345e-3, 3.456),          "   0.0+-003.5 *******" );
+
+    ss << std::setw(0);
+
+    CheckFormat( (0.0),                      "0.0" );
+    CheckFormat( (-1.4431288e5, 2.26338e4),  "-144.3+-22.6k" );
+    CheckFormat( (1.4444e-13, 2.111111e-16), "144.4+-0.2f" );
+    CheckFormat( (1.345e-3, 3.456),          "0.0+-3.5" );
+
+#   undef CheckFormat
+    
+    // From documentation
+    
+    {
+        std::stringstream ss;
+        ss << senf::format::eng(1.23);
+        BOOST_CHECK_EQUAL(ss.str(), "1.230");
+    }
+
+    {
+        std::stringstream ss;
+        ss << std::setw(1) << senf::format::eng(1.23);
+        BOOST_CHECK_EQUAL( ss.str(), "   1.230    " );
+    }
+
+    {
+        std::stringstream ss;
+        ss << std::setw(25) << std::setprecision(5) << std::showpos << std::uppercase 
+           << std::internal << senf::format::eng(12345,67);
+        BOOST_CHECK_EQUAL( ss.str(), "+       12.35+-000.07E+03" );
+    }
+
+    {
+        std::stringstream ss;
+        ss << std::showbase << senf::format::eng(12345,67);
+        BOOST_CHECK_EQUAL( ss.str(), "12.345+-0.067k" );
+    }
+}
+
+BOOST_AUTO_UNIT_TEST(dumpint)
+{
+    std::stringstream ss;
+    
+#   define CheckFormat(v,s)                                             \
+        {                                                               \
+            ss.str("");                                                 \
+            ss << senf::format::dumpint(v);                             \
+            BOOST_CHECK_EQUAL( ss.str(), s );                           \
+        }
+
+    CheckFormat( boost::int8_t(32), " 0x20 (  32) ( )" );
+    CheckFormat( boost::uint16_t(1234), "0x04d2 ( 1234) (..)" );
+
+#   undef CheckFormat
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index 6e2c7f8..ff7e569 100644 (file)
@@ -114,6 +114,9 @@ namespace senf {
     by the GNU libc</td></tr>
 
     <tr><td>signalName()</td><td>convert signal number to string representation</td></tr>
+
+    <tr><td>\ref senf_utils_format</td><td>\c iostream formating helpers for extended
+    formats</td></tr>
     </table>
 
 
index 7506e07..730898d 100644 (file)
@@ -30,6 +30,7 @@
 #include <cmath>
 #include <sstream>
 #include <senf/Utils/Console/Console.hh>
+#include <senf/Utils/Format.hh>
 #include "StatisticsTargets.hh"
 
 //#include "Statistics.mpp"
@@ -82,63 +83,25 @@ senf::StatisticsBase::output(unsigned n)
     return OutputProxy<StatisticsBase>(this, &(i->second));
 }
 
-//
-// generate an engineering style notation 
-//
-std::string format_eng( float f)
-{
-    char buf[16];
-    if (f > 0) {
-        int n = 0;
-        while( f >= 1000.0f) {
-                f /= 1000.0f;
-                n+=3;
-        }
-
-        if( n >=3)
-            sprintf( buf, " %3.2fe%+03d", f, n);
-        else
-            sprintf( buf, "      %3.2f", f);
-    }
-    else if (f < 0) {
-        int n = 0;
-        while( f <= -1000.0f) {
-                f *= 1000.0f;
-                n+=3;
-        }
-        if( n >=3)
-            sprintf( buf, " %3.2fe%+03d", f, n);
-        else
-            sprintf( buf, "      %3.2f", f);
-    }
-    else{
-        sprintf( buf, "        0.00");
-    }
-
-    return buf;
-}
-
-
 prefix_ void senf::StatisticsBase::consoleList(unsigned level, std::ostream & os)
     const
 {
-    os << boost::format("%s%-5d%|15t|  %12s  %12s   %12s  %12s\n") 
+    os << boost::format("%s%-5d%|15t|  %12s  %19.5g  %12s\n") 
         % std::string(2*level,' ') 
         % rank() 
-        % format_eng(min()) 
-        % format_eng(avg()) 
-        % format_eng(dev())
-        % format_eng(max());
+        % 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()));
     {
         OutputMap::const_iterator i (outputs_.begin());
         OutputMap::const_iterator i_end (outputs_.end());
         for (; i != i_end; ++i)
-            os << boost::format("            %3d  %12s  %12s   %12s  %12s\n")
+            os << boost::format("            %3d  %12s  %19.5g  %12s\n")
                 % i->second.n 
-                % format_eng(i->second.min/i->second.n) 
-                % format_eng(i->second.avg/i->second.n)
-                % format_eng(i->second.dev/i->second.n)
-                % format_eng(i->second.max/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));
     }
     {
         Children::const_iterator i (children_.begin());
@@ -245,7 +208,7 @@ prefix_ senf::Statistics::Statistics()
 
 prefix_ void senf::Statistics::consoleList(std::ostream & os)
 {
-    os << "RANK        WIN           MIN           AVG            DEV           MAX\n";
+    os << "RANK        WIN           MIN                  AVG           MAX\n";
     StatisticsBase::consoleList(0, os);
 }
 
index fb10b1f..bd89f74 100644 (file)
@@ -50,7 +50,6 @@ namespace {
             { return arg.rank(); }
     };
 
-
     struct splitFloats
     {
         typedef boost::char_separator<char> Separator;
@@ -72,8 +71,10 @@ namespace {
         typedef TransformIterator const_iterator;
         
         splitFloats(std::string const & s) : s_ (s), sep_ (" \n"), tok_ (s_, sep_) {}
-        TransformIterator begin() const { return TransformIterator(FilterIterator(tok_.begin())); }
-        TransformIterator end() const { return TransformIterator(FilterIterator(tok_.end())); }
+        TransformIterator begin() const 
+            { return TransformIterator(FilterIterator(tok_.begin(), tok_.end())); }
+        TransformIterator end() const 
+            { return TransformIterator(FilterIterator(tok_.end(), tok_.end())); }
 
         std::string s_;
         Separator sep_;