-
Notifications
You must be signed in to change notification settings - Fork 5
/
ConsoleTable.cpp
161 lines (127 loc) · 4.28 KB
/
ConsoleTable.cpp
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "ConsoleTable.h"
ConsoleTable::ConsoleTable(std::initializer_list<std::string> headers) : headers{headers} {
for (const auto &column : headers) {
widths.push_back(column.length());
}
}
void ConsoleTable::setPadding(unsigned int n) {
padding = n;
}
void ConsoleTable::setStyle(unsigned int n) {
switch (n) {
case 0 :
style = BasicStyle;
break;
case 1 :
style = LineStyle;
break;
case 2 :
style = DoubleLineStyle;
break;
case 3 :
style = InvisibleStyle;
break;
default :
style = BasicStyle;
break;
}
}
bool ConsoleTable::addRow(std::initializer_list<std::string> row) {
if (row.size() > widths.size()) {
throw std::invalid_argument{"Appended row size must be same as header size"};
}
auto r = std::vector<std::string>{row};
rows.push_back(r);
for (unsigned int i = 0; i < r.size(); ++i) {
widths[i] = std::max(r[i].size(), widths[i]);
}
return true;
}
bool ConsoleTable::removeRow(unsigned int index) {
if (index > rows.size())
return false;
rows.erase(rows.begin() + index);
return true;
}
ConsoleTable &ConsoleTable::operator+=(std::initializer_list<std::string> row) {
if (row.size() > widths.size()) {
throw std::invalid_argument{"Appended row size must be same as header size"};
}
addRow(row);
return *this;
}
ConsoleTable &ConsoleTable::operator-=(const uint32_t rowIndex) {
if (rows.size() < rowIndex)
throw std::out_of_range{"Row index out of range."};
removeRow(rowIndex);
return *this;
}
std::string ConsoleTable::getLine(RowType rowType) const {
std::stringstream line;
line << rowType.left;
for (unsigned int i = 0; i < widths.size(); ++i) {
for (unsigned int j = 0; j < (widths[i] + padding + padding); ++j) {
line << style.horizontal;
}
line << (i == widths.size() - 1 ? rowType.right : rowType.intersect);
}
return line.str() + "\n";
}
std::string ConsoleTable::getHeaders(Headers headers) const {
std::stringstream line;
line << style.vertical;
for (unsigned int i = 0; i < headers.size(); ++i) {
std::string text = headers[i];
line << SPACE_CHARACTER * padding + text + SPACE_CHARACTER * (widths[i] - text.length()) + SPACE_CHARACTER * padding;
line << style.vertical;
}
line << "\n";
return line.str();
}
std::string ConsoleTable::getRows(Rows rows) const {
std::stringstream line;
for (auto &row : rows) {
line << style.vertical;
for (unsigned int j = 0; j < row.size(); ++j) {
std::string text = row[j];
line << SPACE_CHARACTER * padding + text + SPACE_CHARACTER * (widths[j] - text.length()) + SPACE_CHARACTER * padding;
line << style.vertical;
}
line << "\n";
}
return line.str();
}
std::ostream &operator<<(std::ostream &out, const ConsoleTable &consoleTable) {
out << consoleTable.getLine(consoleTable.style.top);
out << consoleTable.getHeaders(consoleTable.headers);
out << consoleTable.getLine(consoleTable.style.middle);
out << consoleTable.getRows(consoleTable.rows);
out << consoleTable.getLine(consoleTable.style.bottom);
return out;
}
bool ConsoleTable::sort(bool ascending) {
if (ascending)
std::sort(rows.begin(), rows.end(), std::less<std::vector<std::string>>());
else
std::sort(rows.begin(), rows.end(), std::greater<std::vector<std::string>>());
return true;
}
void ConsoleTable::updateRow(unsigned int row, unsigned int header, std::string data) {
if (row > rows.size() - 1)
throw std::out_of_range{"Row index out of range."};
if (header > headers.size() - 1)
throw std::out_of_range{"Header index out of range."};
rows[row][header] = data;
}
void ConsoleTable::updateHeader(unsigned int header, std::string text) {
if (header > headers.size())
throw std::out_of_range{"Header index out of range."};
headers[header] = text;
}
std::string operator*(const std::string &other, int repeats) {
std::string ret;
ret.reserve(other.size() * repeats);
for (; repeats; --repeats)
ret.append(other);
return ret;
}