Utils: Formating helpers (senf::format::eng, senf::format::dumpint)
[senf.git] / senf / Utils / Format.cc
1 // $Id$
2 //
3 // Copyright (C) 2009 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Format non-inline non-template implementation */
25
26 #include "Format.hh"
27 #include "Format.ih"
28
29 // Custom includes
30 #include <cmath>
31 #include <boost/io/ios_state.hpp>
32 #include <iomanip>
33 #include <sstream>
34
35 //#include "Format.mpp"
36 #define prefix_
37 ///////////////////////////////cc.p////////////////////////////////////////
38
39 namespace {
40
41     char const SIPrefix[] = { 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm', 
42                               ' ', 
43                               'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
44     unsigned const SIScales = 8;
45
46 }
47
48 prefix_ std::ostream & senf::format::operator<<(std::ostream & os, eng const & v_)
49 {
50     boost::io::ios_base_all_saver ibas (os);
51     boost::io::ios_fill_saver ifs (os);
52
53     unsigned prec (os.precision());
54     if (prec < 4) 
55         prec = 4;
56     unsigned w (os.width());
57     char fill (os.fill());
58     unsigned minw (prec+2+((os.flags() & std::ios_base::showbase) ? 1 : 4));
59     std::ios_base::fmtflags align (os.flags() & std::ios_base::adjustfield);
60     if (! std::isnan(v_.d))
61         minw += prec+3;
62     
63     double ref (std::fabs(v_.v));
64     double v (v_.v);
65     double d (0.0);
66     if (! std::isnan(v_.d)) d = std::fabs(v_.d);
67     int scale (0);
68
69     if (d > ref) ref = d;
70     while (ref >= 1000.0) {
71         ref /= 1000.0;
72         v /= 1000.0;
73         d /= 1000.0;
74         scale += 3;
75     }
76     while (ref > 0 && ref < 1) {
77         ref *= 1000.0;
78         v *= 1000.0;
79         d *= 1000.0;
80         scale -= 3;
81     }
82
83     os << std::dec << std::setprecision(prec-3) << std::fixed;
84     if (w > 0) {
85         if ((align == 0 || align == std::ios_base::right || align == std::ios_base::internal) 
86             && w > minw)
87             os << std::setw(prec+2+w-minw);
88         else 
89             os << std::right << std::setfill(' ') << std::setw(prec+2);
90     }
91     else
92         os << std::right;
93     os << v;
94
95     os << std::setfill('0') << std::noshowpos;
96     if (! std::isnan(v_.d)) {
97         os << "+-";
98         if (w > 0)
99             os << std::setw(prec+1);
100         os << d;
101     }
102
103     if ((os.flags() & std::ios_base::showbase) && unsigned(std::abs(scale/3)) <= SIScales) {
104         if (w > 0 || scale != 0)
105             os << SIPrefix[scale/3+SIScales];
106     }
107     else if ((os.flags() & std::ios_base::showpoint) || scale != 0)
108         os << ((os.flags() & std::ios_base::uppercase)?'E':'e') 
109            << std::showpos << std::internal << std::setw(3) << scale;
110     else if (w > 0)
111         os << "    ";
112     if (w > minw && align == std::ios_base::left)
113         os << std::setfill(fill) << std::setw(w-minw) << "";
114
115     return os;
116 }
117
118 prefix_ std::string senf::format::detail::dumpintSigned(long long v, unsigned bits)
119 {
120     if (v<0) return dumpintUnsigned(-v,bits,-1);
121     else     return dumpintUnsigned(v,bits,+1);
122 }
123
124 prefix_ std::string senf::format::detail::dumpintUnsigned(unsigned long long v, unsigned bits,
125                                                           int sign)
126 {
127     int bytes ((bits+7)/8);
128     int digs (int(2.4*bytes)+1);
129     std::stringstream ss;
130     ss << (sign ? (sign<0 ? "-" : " ") : "") 
131        << "0x" << std::setw(2*bytes) << std::setfill('0') << std::hex 
132        << 1u*v
133        << " (" << std::setw(digs+(sign ? 1 : 0)) << std::setfill(' ') << std::dec;
134     if (sign)
135         ss << sign*static_cast<long long>(v);
136     else
137         ss << 1u*v;
138     ss << ") (";
139     for (int i (bytes-1); i>=0; --i) {
140         char c ((v>>(8*i))&0xff);
141         ss << ((c>=32 && c<=127) ? c : '.');
142     }
143     ss << ')';
144     return ss.str();
145 }
146
147
148 ///////////////////////////////cc.e////////////////////////////////////////
149 #undef prefix_
150 //#include "Format.mpp"
151
152 \f
153 // Local Variables:
154 // mode: c++
155 // fill-column: 100
156 // comment-column: 40
157 // c-file-style: "senf"
158 // indent-tabs-mode: nil
159 // ispell-local-dictionary: "american"
160 // compile-command: "scons -u test"
161 // End: