switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Format.cc
1 // $Id$
2 //
3 // Copyright (C) 2009
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief Format non-inline non-template implementation */
30
31 #include "Format.hh"
32 #include "Format.ih"
33
34 // Custom includes
35 #include <cmath>
36 #include <boost/io/ios_state.hpp>
37 #include <iomanip>
38 #include <sstream>
39
40 //#include "Format.mpp"
41 #define prefix_
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
43
44 namespace {
45
46     char const SIPrefix[] = { 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm',
47                               ' ',
48                               'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
49     unsigned const SIScales = 8;
50
51 }
52
53 prefix_ std::ostream & senf::format::operator<<(std::ostream & os, eng const & v_)
54 {
55     boost::io::ios_base_all_saver ibas (os);
56     boost::io::ios_fill_saver ifs (os);
57
58     os.setf(v_.flags_, v_.mask_);
59     if (v_.havePrecision_)
60         os.precision(v_.precision_);
61     if (v_.haveWidth_)
62         os.width(v_.width_);
63     if (v_.haveFill_)
64         os.fill(v_.fill_);
65
66     unsigned prec (os.precision());
67     if (prec < 4)
68         prec = 4;
69     unsigned w (os.width());
70     char fill (os.fill());
71     unsigned minw (prec+2+((os.flags() & std::ios_base::showbase) ? 1 : 4));
72     std::ios_base::fmtflags flags (os.flags());
73     std::ios_base::fmtflags align (flags & std::ios_base::adjustfield);
74     if (! std::isnan(v_.d_))
75         minw += prec+3;
76
77     float ref (std::fabs(v_.v_));
78     float v (v_.v_);
79     float d (0.0);
80     if (! std::isnan(v_.d_)) d = std::fabs(v_.d_);
81     int scale (0);
82
83     if (d > ref) ref = d;
84     while (ref >= 1000.0) {
85         ref /= 1000.0;
86         v /= 1000.0;
87         d /= 1000.0;
88         scale += 3;
89     }
90     while (ref > 0 && ref < 1) {
91         ref *= 1000.0;
92         v *= 1000.0;
93         d *= 1000.0;
94         scale -= 3;
95     }
96
97     os << std::dec << std::setprecision(prec-3) << std::fixed;
98     if (w > 0) {
99         if ((align == 0 || align == std::ios_base::right || align == std::ios_base::internal))
100             os << std::setw(prec+2+(w>minw ? w-minw : 0));
101         else
102             os << std::right << std::setfill(' ') << std::setw(prec+2);
103     }
104     else
105         os << std::right;
106     os << v;
107
108     os << std::setfill('0') << std::noshowpos;
109     if (! std::isnan(v_.d_)) {
110         os << "+-";
111         if (w > 0)
112             os << std::setw(prec+1);
113         os << d;
114     }
115
116     if ((flags & std::ios_base::showbase) && unsigned(std::abs(scale/3)) <= SIScales) {
117         if (w > 0 || scale != 0)
118             os << SIPrefix[scale/3+SIScales];
119     }
120     else if ((flags & std::ios_base::showpoint) || scale != 0)
121         os << ((flags & std::ios_base::uppercase)?'E':'e')
122            << std::showpos << std::internal << std::setw(3) << scale;
123     else if (w > 0)
124         os << "    ";
125     if (w > minw && align == std::ios_base::left)
126         os << std::setfill(fill) << std::setw(w-minw) << "";
127
128     return os;
129 }
130
131 prefix_ std::string senf::format::detail::dumpintSigned(long long v, unsigned bits)
132 {
133     if (v<0) return dumpintUnsigned(-v,bits,-1);
134     else     return dumpintUnsigned(v,bits,+1);
135 }
136
137 prefix_ std::string senf::format::detail::dumpintUnsigned(unsigned long long v, unsigned bits,
138                                                           int sign)
139 {
140     int bytes ((bits+7)/8);
141     int digs (int(2.4*bytes)+1);
142     std::stringstream ss;
143     ss << (sign ? (sign<0 ? "-" : " ") : "")
144        << "0x" << std::setw(2*bytes) << std::setfill('0') << std::hex
145        << 1u*v
146        << " (" << std::setw(digs+(sign ? 1 : 0)) << std::setfill(' ') << std::dec;
147     if (sign)
148         ss << sign*static_cast<long long>(v);
149     else
150         ss << 1u*v;
151     ss << ") (";
152     for (int i (bytes-1); i>=0; --i) {
153         char c ((v>>(8*i))&0xff);
154         ss << ((c>=32 && c<=126) ? c : '.');
155     }
156     ss << ')';
157     return ss.str();
158 }
159
160 unsigned int senf::format::IndentHelper::static_level = 0;
161
162
163 //-/////////////////////////////////////////////////////////////////////////////////////////////////
164 #undef prefix_
165 //#include "Format.mpp"
166
167 \f
168 // Local Variables:
169 // mode: c++
170 // fill-column: 100
171 // comment-column: 40
172 // c-file-style: "senf"
173 // indent-tabs-mode: nil
174 // ispell-local-dictionary: "american"
175 // compile-command: "scons -u test"
176 // End: