From: g0dil Date: Wed, 30 Sep 2009 15:04:57 +0000 (+0000) Subject: Utils: Formating helpers (senf::format::eng, senf::format::dumpint) X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=af697a0c8591b38f7ee7dbc3d1d0293f4ff72d37;p=senf.git Utils: Formating helpers (senf::format::eng, senf::format::dumpint) git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1468 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/senf/Packets/DefaultBundle/EthernetPacket.cc b/senf/Packets/DefaultBundle/EthernetPacket.cc index 30e8e8d..04a87af 100644 --- a/senf/Packets/DefaultBundle/EthernetPacket.cc +++ b/senf/Packets/DefaultBundle/EthernetPacket.cc @@ -30,6 +30,7 @@ #include "LlcSnapPacket.hh" #include #include +#include #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) diff --git a/senf/Packets/DumpFormat.cc b/senf/Packets/DumpFormat.cc index 2c99df2..de102c7 100644 --- a/senf/Packets/DumpFormat.cc +++ b/senf/Packets/DumpFormat.cc @@ -24,7 +24,7 @@ \brief DumpFormat non-inline non-template implementation */ #include "Packets.hh" -#include "DumpFormat.ih" +//#include "DumpFormat.ih" // Custom includes #include @@ -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(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" diff --git a/senf/Packets/DumpFormat.hh b/senf/Packets/DumpFormat.hh index 0d1cea2..cb3e09d 100644 --- a/senf/Packets/DumpFormat.hh +++ b/senf/Packets/DumpFormat.hh @@ -42,13 +42,6 @@ namespace senf { std::string fieldName(std::string const & s); - template - std::string prettyNumber(T const & v, - typename boost::enable_if >::type * = 0); - - template - std::string prettyNumber(T const & v, - typename boost::enable_if >::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 diff --git a/senf/Packets/DumpFormat.test.cc b/senf/Packets/DumpFormat.test.cc index 37ab50f..87463fc 100644 --- a/senf/Packets/DumpFormat.test.cc +++ b/senf/Packets/DumpFormat.test.cc @@ -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(-1), "-0x0001 ( -1) (..)" ); - BOOST_CHECK_EQUAL( senf::prettyNumber(1), " 0x0001 ( 1) (..)" ); - BOOST_CHECK_EQUAL( senf::prettyNumber(1), "0x0001 ( 1) (..)" ); } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/senf/Packets/PacketRegistry.ct b/senf/Packets/PacketRegistry.ct index cda493b..b4babcc 100644 --- a/senf/Packets/PacketRegistry.ct +++ b/senf/Packets/PacketRegistry.ct @@ -31,6 +31,7 @@ #include #include #include +#include #define prefix_ ///////////////////////////////ct.p//////////////////////////////////////// @@ -169,7 +170,7 @@ prefix_ void senf::detail::DumpKey::dump(KeyType const & v, template prefix_ void senf::detail::DumpKey::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 index 0000000..3373bb8 --- /dev/null +++ b/senf/Utils/Format.cc @@ -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 +// +// 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 +#include +#include +#include + +//#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(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" + + +// 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: diff --git a/senf/Packets/DumpFormat.ih b/senf/Utils/Format.cci similarity index 72% copy from senf/Packets/DumpFormat.ih copy to senf/Utils/Format.cci index 302cb8d..ed1ad85 100644 --- a/senf/Packets/DumpFormat.ih +++ b/senf/Utils/Format.cci @@ -21,25 +21,21 @@ // 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_ // Local Variables: diff --git a/senf/Packets/DumpFormat.ct b/senf/Utils/Format.cti similarity index 69% rename from senf/Packets/DumpFormat.ct rename to senf/Utils/Format.cti index 93650c5..41b8ab4 100644 --- a/senf/Packets/DumpFormat.ct +++ b/senf/Utils/Format.cti @@ -21,31 +21,30 @@ // 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 -#define prefix_ -///////////////////////////////ct.p//////////////////////////////////////// +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// template prefix_ std::string -senf::prettyNumber(T const & v, typename boost::enable_if >::type *) +senf::format::dumpint(T const & v, typename boost::enable_if >::type *) { - return detail::prettySignedNumber(v, std::numeric_limits::digits); + return detail::dumpintSigned(v, std::numeric_limits::digits); } template prefix_ std::string -senf::prettyNumber(T const & v, typename boost::enable_if >::type *) +senf::format::dumpint(T const & v, typename boost::enable_if >::type *) { - return detail::prettyUnsignedNumber(v, std::numeric_limits::digits); + return detail::dumpintUnsigned(v, std::numeric_limits::digits); } -///////////////////////////////ct.e//////////////////////////////////////// +///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/senf/Utils/Format.hh b/senf/Utils/Format.hh new file mode 100644 index 0000000..beb5008 --- /dev/null +++ b/senf/Utils/Format.hh @@ -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 +// +// 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 +#include +#include +#include +#include + +//#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: +
+        123.45   -> 123.450e+00
+        123.45e2 ->  12.345e+03
+        
+ + Additionally, an optional delta value may be displayed: +
+        123.45+-1.34e+03
+        
+ + 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::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 + streamable_type dumpint(T const & v); + +#else + + template + std::string dumpint(T const & v, + typename boost::enable_if >::type * = 0); + + template + std::string dumpint(T const & v, + typename boost::enable_if >::type * = 0); + +#endif + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "Format.cci" +//#include "Format.ct" +#include "Format.cti" +#endif + + +// 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: diff --git a/senf/Packets/DumpFormat.ih b/senf/Utils/Format.ih similarity index 83% rename from senf/Packets/DumpFormat.ih rename to senf/Utils/Format.ih index 302cb8d..0a4a709 100644 --- a/senf/Packets/DumpFormat.ih +++ b/senf/Utils/Format.ih @@ -21,22 +21,23 @@ // 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 index 0000000..996fe38 --- /dev/null +++ b/senf/Utils/Format.test.cc @@ -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 +// +// 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 +#include +#include "Format.hh" +#include + +#include +#include + +#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_ + + +// 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: diff --git a/senf/Utils/Mainpage.dox b/senf/Utils/Mainpage.dox index 6e2c7f8..ff7e569 100644 --- a/senf/Utils/Mainpage.dox +++ b/senf/Utils/Mainpage.dox @@ -114,6 +114,9 @@ namespace senf { by the GNU libc signalName()convert signal number to string representation + + \ref senf_utils_format\c iostream formating helpers for extended + formats diff --git a/senf/Utils/Statistics.cc b/senf/Utils/Statistics.cc index 7506e07..730898d 100644 --- a/senf/Utils/Statistics.cc +++ b/senf/Utils/Statistics.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include "StatisticsTargets.hh" //#include "Statistics.mpp" @@ -82,63 +83,25 @@ senf::StatisticsBase::output(unsigned n) return OutputProxy(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); } diff --git a/senf/Utils/Statistics.test.cc b/senf/Utils/Statistics.test.cc index fb10b1f..bd89f74 100644 --- a/senf/Utils/Statistics.test.cc +++ b/senf/Utils/Statistics.test.cc @@ -50,7 +50,6 @@ namespace { { return arg.rank(); } }; - struct splitFloats { typedef boost::char_separator 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_;