switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Format.hh
index beb5008..aebcf23 100644 (file)
@@ -1,24 +1,29 @@
 // $Id$
 //
-// Copyright (C) 2009 
+// 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.
+// The contents of this file are subject to the Fraunhofer FOKUS Public License
+// Version 1.0 (the "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at 
+// http://senf.berlios.de/license.html
 //
-// 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.
+// The Fraunhofer FOKUS Public License Version 1.0 is based on, 
+// but modifies the Mozilla Public License Version 1.1.
+// See the full license text for the amendments.
 //
-// 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.
+// Software distributed under the License is distributed on an "AS IS" basis, 
+// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
+// for the specific language governing rights and limitations under the License.
+//
+// The Original Code is Fraunhofer FOKUS code.
+//
+// The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
+// (registered association), Hansastraße 27 c, 80686 Munich, Germany.
+// All Rights Reserved.
+//
+// Contributor(s):
+//   Stefan Bund <g0dil@berlios.de>
 
 /** \file
     \brief Format public header */
@@ -34,7 +39,7 @@
 #include <boost/type_traits/is_unsigned.hpp>
 
 //#include "Format.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace senf {
 namespace format {
@@ -59,64 +64,107 @@ namespace format {
         </pre>
 
         senf::format::eng supports several formating options:
-        \par \c std::setw()
+        \par \c std::\c 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()
+        \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
+        \par \c std::\c showbase, \c std::\c noshowbase
             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
+        \par \c std::\c showpos, \c std::\c noshowpos
             If the \c showpos flag is set, positive values will have a '+' sign.
 
-        \par \c std::\c showpoint
+        \par \c std::\c showpoint, \c std::\c noshowpoint
             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
+
+        \par \c std::\c uppercase, \c std::\c nouppercase
             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()
+        \par \c std::\c setfill
             The fill character is honored for the outside padding but \e not for the internal
             padding.
 
+        \par \c std::\c left, \c std::\c internal, \c std::\c right
+            The alignment flags specify the external padding but do not affect the internal
+            padding.
+
+        All these flags may optionally be set by calling members of the senf::format::eng() return
+        value with the same name.
+
         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"
+        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"
+
+        senf::str(senf::format::eng(12.345,67).setw().setprecision(5).showpoint().uppercase())
+          -> "  12.35+-67.00E+00"
         \endcode
-        
+
         \param[in] v value
         \param[in] d optional delta
 
         \ingroup senf_utils_format
      */
-    streamable_type eng(double v, double d=NAN);
+    streamable_type eng(float v, float d=NAN);
 
 #else
 
-    struct eng
+    class eng
     {
-        eng(double v_, double d_ = std::numeric_limits<double>::quiet_NaN());
+    public:
+        eng(float v, float d = std::numeric_limits<float>::quiet_NaN());
+
+        eng const & setw(unsigned w = 1) const;
+        eng const & setprecision(unsigned p) const;
+        eng const & setfill(char c) const;
+
+        eng const & showbase() const;
+        eng const & noshowbase() const;
+        eng const & showpos() const;
+        eng const & noshowpos() const;
+        eng const & showpoint() const;
+        eng const & noshowpoint() const;
+        eng const & uppercase() const;
+        eng const & nouppercase() const;
+        eng const & left() const;
+        eng const & internal() const;
+        eng const & right() const;
+
+    private:
+        float v_;
+        float d_;
+
+        mutable bool haveWidth_;
+        mutable unsigned width_;
+        mutable bool havePrecision_;
+        mutable unsigned precision_;
+        mutable bool haveFill_;
+        mutable char fill_;
+        mutable std::ios_base::fmtflags mask_;
+        mutable std::ios_base::fmtflags flags_;
+
+        friend std::ostream & operator<<(std::ostream & os, eng const & v);
 
-        double v;
-        double d;
     };
 
     std::ostream & operator<<(std::ostream & os, eng const & v);
@@ -141,21 +189,80 @@ namespace format {
     template <class T>
     streamable_type dumpint(T const & v);
 
-#else 
+#else
 
-    template <class T> 
-    std::string dumpint(T const & v, 
+    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, 
+    template <class T>
+    std::string dumpint(T const & v,
                         typename boost::enable_if<boost::is_unsigned<T> >::type * = 0);
 
+    template <class T>
+    std::string dumpint(T const & v,
+                        typename boost::enable_if<boost::is_signed<typename T::value_type> >::type * = 0);
+
+    template <class T>
+    std::string dumpint(T const & v,
+                        typename boost::enable_if<boost::is_unsigned<typename T::value_type> >::type * = 0);
+
 #endif
 
+    /** \brief Helper class to easily achieve indent levels
+
+        This class helps to achieve indent levels across function calls. Every instance
+        increases the static indent level. On destruction the level is decreased to the level
+        before the instance.
+        The following example illustrates the use of this class:
+        \code
+            void f1() {
+                senf::format::IndentHelper indent;
+                std::cout << indent << "f1\n";
+            }
+            void f2() {
+                senf::format::IndentHelper indent;
+                std::cout << indent << "f2 begin\n";
+                f1();
+                std::cout << indent << "f2 end\n";
+            }
+            f2()
+        \endcode
+        Output:
+        <pre>
+            f2 begin
+              f1
+            f2 end
+        </pre>
+        Here <tt>f1()</tt> and <tt>f2()</tt> don't need to know to current indent level,
+        they just increase the level by instantiating IndentHelper.
+
+        \ingroup senf_utils_format
+     */
+    class IndentHelper
+    {
+        static unsigned int static_level;
+        unsigned int instance_level;
+    public:
+
+        IndentHelper();                 ///< Construct new IndentHelper instance
+                                        /**< The static indent level is increased by one. */
+        ~IndentHelper();                ///< Destruct IndentHelper instance
+                                        /**< The static indent level will be decreased to the
+                                             level before the instance. */
+        void increase();                ///< Increase the indent level
+                                        /**< The indent level of the instance is increases by one. */
+        unsigned int level() const;     ///< return the current indent level
+    };
+
+    /** \brief Output indent to given ostream
+        \related IndentHelper
+     */
+    std::ostream & operator<<(std::ostream & os, IndentHelper const & indent);
+
 }}
 
-///////////////////////////////hh.e////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 #include "Format.cci"
 //#include "Format.ct"
 #include "Format.cti"