forked from chipsalliance/verible
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdisplay_utils.h
147 lines (127 loc) · 5.45 KB
/
display_utils.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef VERIBLE_COMMON_STRINGS_DISPLAY_UTILS_H_
#define VERIBLE_COMMON_STRINGS_DISPLAY_UTILS_H_
#include <iosfwd>
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
namespace verible {
// Stream printable object that limits the length of text printed.
// Applications: debugging potentially long strings, where only the head and
// tail are sufficient to comprehend the text being referenced.
//
// usage: stream << AutoTruncate{text, limit};
//
// example output (limit: 9): "abc...xyz"
struct AutoTruncate {
const absl::string_view text;
// Maximum number of characters to show, including "..."
const int max_chars;
};
std::ostream& operator<<(std::ostream&, const AutoTruncate& trunc);
// To help visualize strings with non-alphanumeric characters, this stream
// adapter prints special characters escaped using C escape sequences, without
// modifying or copying the original string.
//
// usage: stream << EscapeString(text);
struct EscapeString {
const absl::string_view text; // original text to be printed
explicit EscapeString(absl::string_view text) : text(text) {}
};
std::ostream& operator<<(std::ostream&, const EscapeString& vis);
// To help visualize strings that consist of whitespace, this stream adapter
// prints spaces, tabs, and newlines with alternate text, without modifying or
// copying the original string.
//
// usage: stream << VisualizeWhitespace(text_with_lots_of_spaces);
struct VisualizeWhitespace {
const absl::string_view text; // original text to be printed
const char space_alt; // spaces replacement
const absl::string_view newline_alt; // newline replacement
const absl::string_view tab_alt; // tab replacement
// constructor needed for C++11
explicit VisualizeWhitespace(absl::string_view text, char space_alt = '.',
absl::string_view newline_alt = "\\\n",
absl::string_view tab_alt = "#")
: text(text),
space_alt(space_alt),
newline_alt(newline_alt),
tab_alt(tab_alt) {}
};
std::ostream& operator<<(std::ostream&, const VisualizeWhitespace& vis);
// TODO(fangism): once C++17 becomes the minimum standard for building
// push the following block into an internal namespace, and use auto
// return types instead of directly naming these types.
// namespace internal {
// Helper struct for bundling parameters to absl::StrJoin.
// This is useful for contructing printer adapters for types that
// are typedefs/aliases of standard containers, and not their own class.
// For example, not every std::vector<int> wants to be formatted the same way.
// Be careful not to define std::ostream& operator<< for such types, as you
// accidentally create conflicting definitions, and violate ODR.
template <class T>
struct SequenceStreamFormatter {
const T& sequence; // binds to object that is to be printed
absl::string_view separator;
absl::string_view prefix;
absl::string_view suffix;
// TODO(fangism): pass in custom formatter object, and be able to nest
// multiple levels of formatters.
};
// Redirects stream printing to abs::StrJoin wrapped in a single object.
template <class T>
std::ostream& operator<<(std::ostream& stream,
const SequenceStreamFormatter<T>& t) {
return stream << t.prefix
<< absl::StrJoin(t.sequence.begin(), t.sequence.end(),
t.separator, absl::StreamFormatter())
<< t.suffix;
}
// } // namespace internal
// SequenceFormatter helps create custom formatters (pretty-printers) for
// standard container types, when providing a plain std::ostream& operator<<
// overload would be ill-advised.
// This is the next best alternative, even if it requires the caller to wrap
// plain container objects.
//
// Example usage (define the following for your specific container type):
// Suppose MySequenceType is a typedef to a container like std::list<int>.
// Define a forwarding function:
//
// [pre C++17]
// SequenceStreamFormatter<MySequenceType> MySequenceFormatter(
// const MySequenceType& t) {
// return verible::SequenceFormatter(t, " | ", "< ", " >");
// }
//
// [C++17 and higher, supporting auto return type]:
// auto MySequenceFormatter(const MySequenceType& t) {
// return verible::SequenceFormatter(t, " | ", "< ", " >");
// }
//
// and call it:
// stream << MySequenceFormatter(sequence_obj) << ...;
//
// to consistently produce text like:
// "< 1 | 2 | 3 | ... >"
//
template <class T>
SequenceStreamFormatter<T> SequenceFormatter(const T& t,
absl::string_view sep = ", ",
absl::string_view prefix = "",
absl::string_view suffix = "") {
return SequenceStreamFormatter<T>{t, sep, prefix, suffix};
}
} // namespace verible
#endif // VERIBLE_COMMON_STRINGS_DISPLAY_UTILS_H_