switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Format.hh
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 public header */
30
31 #ifndef HH_SENF_senf_Utils_Format_
32 #define HH_SENF_senf_Utils_Format_ 1
33
34 // Custom includes
35 #include <limits>
36 #include <iostream>
37 #include <boost/utility/enable_if.hpp>
38 #include <boost/type_traits/is_signed.hpp>
39 #include <boost/type_traits/is_unsigned.hpp>
40
41 //#include "Format.mpp"
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
43
44 namespace senf {
45 namespace format {
46
47     /** \defgroup senf_utils_format Formating
48      */
49
50 #ifdef DOXYGEN
51
52     /** \brief Format value in engineering representation
53
54         The engineering representation is an exponential representation. Exponents however are
55         always multiples of 3:
56         <pre>
57         123.45   -> 123.450e+00
58         123.45e2 ->  12.345e+03
59         </pre>
60
61         Additionally, an optional delta value may be displayed:
62         <pre>
63         123.45+-1.34e+03
64         </pre>
65
66         senf::format::eng supports several formating options:
67         \par \c std::\c setw
68             If the width is set >0, the output will be padded internally. If the width is set to
69             more than the minimal required output width including internal padding, the output is
70             padded on the left or right depending on the streams \c ajustfield setting (changed
71             with \c std::left, \c std:;right or \c std::interal). If the \c adjustfield is set to \c
72             internal, padding is added between the sign and the number.
73
74         \par \c std::\c setprecision
75             The default stream precision is 6. This will schow values with 6 significant digits. The
76             count includes the number of digits in front of the decimal point.
77
78         \par \c std::\c showbase, \c std::\c noshowbase
79             If the \c showbase flag is set, Instead of writing out the scale exponent in numeric
80             form, output the corresponding SI prefix.
81
82         \par \c std::\c showpos, \c std::\c noshowpos
83             If the \c showpos flag is set, positive values will have a '+' sign.
84
85         \par \c std::\c showpoint, \c std::\c noshowpoint
86             If the \c showpoint flag is set, the exponent will be output even if it is 0. Otherwise,
87             if \c width is set, the exponent will be replaced with 4 blanks.
88
89         \par \c std::\c uppercase, \c std::\c nouppercase
90             If the \c uppercase flag is set, the exponent letter will be an uppercase 'E' instead of
91             'e'. SI prefixes are \e not uppercased, since some SI prefixes differ only in case.
92
93         \par \c std::\c setfill
94             The fill character is honored for the outside padding but \e not for the internal
95             padding.
96
97         \par \c std::\c left, \c std::\c internal, \c std::\c right
98             The alignment flags specify the external padding but do not affect the internal
99             padding.
100
101         All these flags may optionally be set by calling members of the senf::format::eng() return
102         value with the same name.
103
104         Examples:
105         \code
106         os << senf::format::eng(1.23);
107           -> "1.230"
108
109         os << std::setw(1) << senf::format::eng(1.23);
110           -> "   1.230    "
111
112         os << std::setw(25) << std::setprecision(5) << std::showpos << std::uppercase
113            << std::internal << senf::format::eng(12345,67);
114           -> "+       12.35+-000.07E+03"
115
116         os << std::showbase << senf::format::eng(12345,67);
117           -> "12.345+-0.067k"
118
119         senf::str(senf::format::eng(12.345,67).setw().setprecision(5).showpoint().uppercase())
120           -> "  12.35+-67.00E+00"
121         \endcode
122
123         \param[in] v value
124         \param[in] d optional delta
125
126         \ingroup senf_utils_format
127      */
128     streamable_type eng(float v, float d=NAN);
129
130 #else
131
132     class eng
133     {
134     public:
135         eng(float v, float d = std::numeric_limits<float>::quiet_NaN());
136
137         eng const & setw(unsigned w = 1) const;
138         eng const & setprecision(unsigned p) const;
139         eng const & setfill(char c) const;
140
141         eng const & showbase() const;
142         eng const & noshowbase() const;
143         eng const & showpos() const;
144         eng const & noshowpos() const;
145         eng const & showpoint() const;
146         eng const & noshowpoint() const;
147         eng const & uppercase() const;
148         eng const & nouppercase() const;
149         eng const & left() const;
150         eng const & internal() const;
151         eng const & right() const;
152
153     private:
154         float v_;
155         float d_;
156
157         mutable bool haveWidth_;
158         mutable unsigned width_;
159         mutable bool havePrecision_;
160         mutable unsigned precision_;
161         mutable bool haveFill_;
162         mutable char fill_;
163         mutable std::ios_base::fmtflags mask_;
164         mutable std::ios_base::fmtflags flags_;
165
166         friend std::ostream & operator<<(std::ostream & os, eng const & v);
167
168     };
169
170     std::ostream & operator<<(std::ostream & os, eng const & v);
171
172 #endif
173
174 #ifdef DOXYGEN
175
176     /** \brief Dump integer value with internal representation
177
178         senf::format::dumpint() will output a signed or unsigned numeric argument in the following
179         representations:
180         \li hexadecimal notation
181         \li decimal notation
182         \li byte values interpreted as ASCII characters (in network byte order)
183
184         All fields will be padded depending on the size of the type to a byte boundary (e.g. a 32bit
185         integer type will be padded to 8 hex-digits, 10 decimal digits and 4 ASCII characters)
186
187         \ingroup senf_utils_format
188      */
189     template <class T>
190     streamable_type dumpint(T const & v);
191
192 #else
193
194     template <class T>
195     std::string dumpint(T const & v,
196                         typename boost::enable_if<boost::is_signed<T> >::type * = 0);
197
198     template <class T>
199     std::string dumpint(T const & v,
200                         typename boost::enable_if<boost::is_unsigned<T> >::type * = 0);
201
202     template <class T>
203     std::string dumpint(T const & v,
204                         typename boost::enable_if<boost::is_signed<typename T::value_type> >::type * = 0);
205
206     template <class T>
207     std::string dumpint(T const & v,
208                         typename boost::enable_if<boost::is_unsigned<typename T::value_type> >::type * = 0);
209
210 #endif
211
212     /** \brief Helper class to easily achieve indent levels
213
214         This class helps to achieve indent levels across function calls. Every instance
215         increases the static indent level. On destruction the level is decreased to the level
216         before the instance.
217         The following example illustrates the use of this class:
218         \code
219             void f1() {
220                 senf::format::IndentHelper indent;
221                 std::cout << indent << "f1\n";
222             }
223             void f2() {
224                 senf::format::IndentHelper indent;
225                 std::cout << indent << "f2 begin\n";
226                 f1();
227                 std::cout << indent << "f2 end\n";
228             }
229             f2()
230         \endcode
231         Output:
232         <pre>
233             f2 begin
234               f1
235             f2 end
236         </pre>
237         Here <tt>f1()</tt> and <tt>f2()</tt> don't need to know to current indent level,
238         they just increase the level by instantiating IndentHelper.
239
240         \ingroup senf_utils_format
241      */
242     class IndentHelper
243     {
244         static unsigned int static_level;
245         unsigned int instance_level;
246     public:
247
248         IndentHelper();                 ///< Construct new IndentHelper instance
249                                         /**< The static indent level is increased by one. */
250         ~IndentHelper();                ///< Destruct IndentHelper instance
251                                         /**< The static indent level will be decreased to the
252                                              level before the instance. */
253         void increase();                ///< Increase the indent level
254                                         /**< The indent level of the instance is increases by one. */
255         unsigned int level() const;     ///< return the current indent level
256     };
257
258     /** \brief Output indent to given ostream
259         \related IndentHelper
260      */
261     std::ostream & operator<<(std::ostream & os, IndentHelper const & indent);
262
263 }}
264
265 //-/////////////////////////////////////////////////////////////////////////////////////////////////
266 #include "Format.cci"
267 //#include "Format.ct"
268 #include "Format.cti"
269 #endif
270
271 \f
272 // Local Variables:
273 // mode: c++
274 // fill-column: 100
275 // comment-column: 40
276 // c-file-style: "senf"
277 // indent-tabs-mode: nil
278 // ispell-local-dictionary: "american"
279 // compile-command: "scons -u test"
280 // End: