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
128
|
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
* \class vespalib::Printable
* \ingroup util
*
* \brief Utility class for printing of class instances.
*
* By implementing this class, you can implement only the print function to get:
* - A toString() implementation.
* - An operator<< implementation.
* - Indentation support to simplify printing objects recursively.
*
* A verbose flag is also given. Non-verbose mode is used by default, but for
* debugging use it may be helpful to look at more detailed state of objects.
*
* \class vespalib::AsciiPrintable
* \ingroup util
*
* \brief Similar utility as Printable, but for vespalib string/stream.
*
* Sadly, std::string may have performance issues in some contexts, as it does
* some synchronization to allow sharing content, and requires heap allocation.
* std::ostream also have issues causing it to require some synchronization.
*
* The AsciiPrintable class implements similar functionality as Printable,
* using the vespalib classes on top of the STL functionality. Using this class
* instead, toString() and operator<< can be more efficient, while it is still
* backward compatible with STL variants.
*/
#pragma once
#include <vespa/vespalib/stllike/string.h>
#include <vector>
namespace vespalib {
class asciistream;
class Printable {
public:
virtual ~Printable() {}
/**
* Print instance textual to the given stream.
*
* This function is expected to NOT add a newline after the last line
* printed.
*
* You should be properly indented before calling this function. The indent
* variable tells you what you need to add after each newline to get
* indented as far as your first line was. Thus, single line output don't
* need to worry about indentation.
*
* A typical multiline print would thus be something like this:
* <pre>
* out << "MyClass() {\n"
* << "\n" << indent << " some info"
* << "\n" << indent << "}";
* </pre>
*
* By not adding whitespace in either end of the output, we give maximum
* freedom for nesting output. For instance, if I wanted to create output of
* class OtherClass that inherited MyClass and I wanted it to contain all
* the information I could write OtherClass output like this:
* <pre>
* out << "OtherClass() : ";
* MyClass::print(out, verbose, indent + " ");
* out << "\n" << indent << {\n"
* << "\n" << indent << " some more info"
* << "\n" << indent << "}";
* </pre>
*
* @param out The stream to print itself to.
* @param verbose Whether to print detailed information or not. For instance
* a list might print it's size and properties if not verbose
* and print each singel element too if verbose. Default for
* toString() and output operators is false.
* @param indent This indentation should be printed AFTER each newline
* printed. (Not before output in first line)
*/
virtual void print(std::ostream& out,
bool verbose = false,
const std::string& indent = "") const = 0;
/** Utility functions to get print() output as a string. */
std::string toString(bool verbose = false,
const std::string& indent = "") const;
};
class AsciiPrintable : public Printable {
public:
virtual ~AsciiPrintable() {}
enum PrintMode {
NORMAL,
VERBOSE
};
class PrintProperties {
PrintMode _mode;
vespalib::string _indent;
public:
PrintProperties(PrintMode mode = NORMAL, stringref indent_ = "")
: _mode(mode), _indent(indent_) {}
PrintProperties indentedCopy() const
{ return PrintProperties(_mode, _indent + " "); }
bool verbose() const { return (_mode == VERBOSE); }
const vespalib::string& indent() const { return _indent; }
vespalib::string indent(uint32_t extraLevels) const;
};
void print(std::ostream& out, bool verbose, const std::string& indent) const override;
virtual void print(vespalib::asciistream&, const PrintProperties& = PrintProperties()) const = 0;
vespalib::string toString(const PrintProperties& = PrintProperties()) const;
};
std::ostream& operator<<(std::ostream& out, const Printable& p);
vespalib::asciistream& operator<<(vespalib::asciistream& out, const AsciiPrintable& p);
template<typename T>
void print(const std::vector<T> & v, vespalib::asciistream& out, const AsciiPrintable::PrintProperties& p);
} // vespalib
|