1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef PSURFACE_INDENT_HH
4 #define PSURFACE_INDENT_HH
5 
6 #include <ostream>
7 #include <string>
8 
9 namespace psurface {
10   /** @addtogroup Common
11    *
12    * @{
13    */
14   /**
15    * @file
16    * @brief  Utility class for handling nested indentation in output.
17    * @author Jö Fahlke
18    */
19   //! Utility class for handling nested indentation in output.
20   /**
21    * An indentation object hast a string basic_indent and an indentation
22    * level.  When it is put into a std::ostream using << it will print its
23    * basic_indent as many times as its indentation level.  By default the
24    * basic_indent will be two spaces and the indentation level will be 0.
25    *
26    * An Indent object may also have a reference to a parent Indent object.  If
27    * it has, that object it put into the stream with the << operator before
28    * the indentation of this object is put into the stream.  This effectively
29    * chains Indent objects together.
30    *
31    * You can use the ++ operator to raise and the -- operator to lower the
32    * indentation by one level.
33    *
34    * You can use the + operator with a numeric second argument morelevel to
35    * create a copy of the Indent object with the indentation level increased
36    * morelevel times.  This is mainly useful to pass indent+1 to a function,
37    * where indent is an indentation object.
38    *
39    * You can use the + operator with a string second argument newindent to
40    * create a new Indent object with this object as parent, a basic_indent of
41    * newindent, and an indentation level of one.  This is mainly useful to
42    * pass indent+"> " to a function, where "> " is a possibly different
43    * indentation string then the one used by indent indentation object.
44    *
45    * \note The idea is for functions receive indentation objects as call by
46    *       value parameters.  This way, the indentation object of the caller
47    *       will not be modified by the function and the function can simply
48    *       return at anytime without having to clean up.
49    */
50   class Indent
51   {
52     const Indent* parent;
53     std::string basic_indent;
54     unsigned level;
55 
56   public:
57     //! setup without parent
58     /**
59      * \note Initial indentation level is 0 by default for this constructor.
60      */
Indent(const std::string & basic_indent_="  ",unsigned level_=0)61     inline Indent(const std::string& basic_indent_ = "  ", unsigned level_ = 0)
62       : parent(0), basic_indent(basic_indent_), level(level_)
63     { }
64 
65     //! setup without parent and basic_indentation of two spaces
Indent(unsigned level_)66     inline Indent(unsigned level_)
67       : parent(0), basic_indent("  "), level(level_)
68     { }
69 
70     //! setup with parent
71     /**
72      * \note Initial indentation level is 1 by default for this constructor.
73      */
Indent(const Indent * parent_,const std::string & basic_indent_="  ",unsigned level_=1)74     inline Indent(const Indent* parent_,
75                   const std::string& basic_indent_ = "  ", unsigned level_ = 1)
76       : parent(parent_), basic_indent(basic_indent_), level(level_)
77     { }
78 
79     //! setup with parent
Indent(const Indent * parent_,unsigned level_)80     inline Indent(const Indent* parent_, unsigned level_)
81       : parent(parent_), basic_indent("  "), level(level_)
82     { }
83 
84     //! create new indentation object with this one as parent
operator +(const std::string & newindent) const85     inline Indent operator+(const std::string& newindent) const {
86       return Indent(this, newindent);
87     }
88     //! create a copy of this indetation object with raised level
operator +(unsigned morelevel) const89     inline Indent operator+(unsigned morelevel) const {
90       return Indent(parent, basic_indent, level+morelevel);
91     }
92     //! raise indentation level
operator ++()93     inline Indent& operator++() { ++level; return *this; }
94     //! lower indentation level
operator --()95     inline Indent& operator--() { --level; return *this; }
96 
97     //! write indentation to a stream
98     friend inline std::ostream& operator<<(std::ostream& s,
99                                            const Indent& indent);
100   };
101 
102   //! write indentation to a stream
operator <<(std::ostream & s,const Indent & indent)103   inline std::ostream& operator<<(std::ostream& s, const Indent& indent) {
104     if(indent.parent)
105       s << *indent.parent;
106     for(unsigned i = 0; i < indent.level; ++i)
107       s << indent.basic_indent;
108     return s;
109   }
110 
111   /** }@ group Common */
112 
113 } // namespace Dune
114 
115 #endif // DUNE_COMMON_INDENT_HH
116