forked from banga/Library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
indentable.h
127 lines (110 loc) · 2.45 KB
/
indentable.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
* Indentable.h
*
* Wrapper for ostream objects to indent/dedent lines automatically, especially
* useful for debugging recursive functions.
*
* usage:
*
* Indentable i(cout, 4, 2);
* function Recursive(...) {
* ScopedIndent scoped(i);
* i << "..." << endl;
* ...
* Recursive(...)
* }
*
*/
#ifndef __SHREY_LIB_INDENTABLE_H__
#define __SHREY_LIB_INDENTABLE_H__
#include <algorithm>
#include <iostream>
#include <string>
namespace lib {
using std::cout;
using std::endl;
using std::max;
using std::ostream;
using std::string;
class Indentable {
public:
explicit Indentable(ostream& out, int indent_size = 0, int indent_increment = 2)
: out_(out),
indent_size_(indent_size),
indent_increment_(indent_increment),
indent_pending_(true),
endl_addr_(&endl) { }
void Indent() {
indent_size_ += indent_increment_;
}
void Dedent() {
indent_size_ = max(indent_size_ - indent_increment_, 0);
}
template <typename T>
Indentable& operator << (const T& t) {
indent_if_pending();
out_ << t;
return *this;
}
Indentable& operator << (char c) {
indent_if_pending();
if (c == '\n') set_indent_pending();
out_ << c;
return *this;
}
Indentable& operator << (const char* str) {
while(*str) {
indent_if_pending();
out_ << *str;
if(*str++ == '\n') set_indent_pending();
}
return *this;
}
Indentable& operator << (const string& str) {
for(size_t i = 0; i < str.length(); ++i) {
indent_if_pending();
out_ << str[i];
if (str[i] == '\n') set_indent_pending();
}
return *this;
}
Indentable& operator << (ostream& (*pf) (ostream&)) {
indent_if_pending();
if (pf == endl_addr_) set_indent_pending();
out_ << pf;
return *this;
}
private:
ostream& out_;
int indent_size_, indent_increment_;
bool indent_pending_;
ostream& (*endl_addr_) (ostream&);
void set_indent_pending() { indent_pending_ = true; }
void indent() {
out_ << string(indent_size_, ' ');
}
void indent_if_pending() {
if (indent_pending_) {
indent();
indent_pending_ = false;
}
}
};
/*
* Helper class to match indent/dedent with a block or function scope
*/
class ScopedIndent {
public:
ScopedIndent(Indentable& indentable)
: indentable_(indentable) {
indentable_.Indent();
}
~ScopedIndent() {
indentable_.Dedent();
}
private:
Indentable& indentable_;
};
Indentable icout(cout);
} // namespace lib
#endif