11/*
2- ========================= Cpp Console Table
3- | Cpp | Console | Table | version 1.0 .0
4- ========================= https://github.com/Oradle/CppConsoleTable
2+ ========================= Cpp Console Table
3+ | Cpp | Console | Table | version 1.2 .0
4+ ========================= https://github.com/Oradle/CppConsoleTable
55
66Licensed under the MIT License <http://opensource.org/licenses/MIT>.
77Copyright (c) 2017 Oradle
@@ -35,13 +35,19 @@ SOFTWARE.
3535#include < iomanip>
3636#include < algorithm>
3737#include < vector>
38+ #include < type_traits>
3839
3940namespace samilton {
4041 // force declaration
4142 class ConsoleTable ;
43+ class ConsoleRow ;
4244
4345 class ConsoleString {
4446 public:
47+ ConsoleString (ConsoleRow *parent) {
48+ _parent = parent;
49+ }
50+
4551 ConsoleString &operator =(const std::string &val) {
4652 _str = val;
4753 return *this ;
@@ -52,22 +58,8 @@ namespace samilton {
5258 return *this ;
5359 }
5460
55- ConsoleString &operator =(const long &val) {
56- _str = std::to_string (val);
57- return *this ;
58- }
59-
60- ConsoleString &operator =(const int &val) {
61- _str = std::to_string (val);
62- return *this ;
63- }
64-
65- ConsoleString &operator =(const double &val) {
66- _str = std::to_string (val);
67- return *this ;
68- }
69-
70- ConsoleString &operator =(const float &val) {
61+ template <class T , class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
62+ ConsoleString &operator =(const T &val) {
7163 _str = std::to_string (val);
7264 return *this ;
7365 }
@@ -83,29 +75,28 @@ namespace samilton {
8375 private:
8476 friend std::ostream &operator <<(std::ostream &stream, ConsoleTable &table);
8577
78+ ConsoleRow *_parent;
8679 std::string _str;
8780 };
8881
8982 class ConsoleRow {
9083 public:
84+ ConsoleRow (ConsoleTable *parent) {
85+ _parent = parent;
86+ }
87+
9188 ~ConsoleRow () {
9289 for (auto &element : _rowData) {
9390 delete element.second ;
9491 }
92+ _rowData.clear ();
9593 }
9694
97- ConsoleString &operator [](const size_t &column) {
98- try {
99- return *_rowData.at (column);
100- }
101- catch (...) {
102- _rowData[column] = new ConsoleString;
103- return *_rowData[column];
104- }
105- }
95+ ConsoleString &operator [](const size_t column);
10696 private:
10797 friend std::ostream &operator <<(std::ostream &stream, ConsoleTable &table);
10898
99+ ConsoleTable *_parent;
109100 std::map<size_t , ConsoleString*> _rowData;
110101 };
111102
@@ -126,34 +117,92 @@ namespace samilton {
126117
127118 ConsoleTable () {
128119 _alignment = Alignment::left;
129- _leftIndent = 0 ;
130- _rightIndent = 0 ;
120+ _leftIndent = _rightIndent = _rowSize = _columnSize = 0 ;
131121 }
132122
133123 ConsoleTable (const Alignment &alignment) {
134124 _alignment = alignment;
135- _leftIndent = 0 ;
136- _rightIndent = 0 ;
125+ _leftIndent = _rightIndent = _rowSize = _columnSize = 0 ;
137126 }
138127
139128 ConsoleTable (const size_t &leftIndent, const size_t &rightIndent, const Alignment &alignment = Alignment::left) {
140129 _leftIndent = leftIndent;
141130 _rightIndent = rightIndent;
142131 _alignment = alignment;
132+ _rowSize = _columnSize = 0 ;
143133 }
144134
145135 ~ConsoleTable () {
136+ clear ();
137+ }
138+
139+ template <class T ,
140+ class = typename std::enable_if<std::is_arithmetic<T>::value ||
141+ std::is_same<std::string, T>::value ||
142+ std::is_same<char *, T>::value>::type>
143+ void addRow (const std::vector<T> &row) {
144+ const size_t tmp = _rowSize;
145+ for (size_t i = 0 ; i < row.size (); i++) {
146+ (*this )[tmp][i] = row[i];
147+ }
148+ }
149+
150+ template <class T ,
151+ class = typename std::enable_if<std::is_arithmetic<T>::value ||
152+ std::is_same<std::string, T>::value>::type>
153+ void addRow (const T *row, const size_t &size) {
154+ const size_t tmp = _rowSize;
155+ for (size_t i = 0 ; i < size; i++) {
156+ (*this )[tmp][i] = row[i];
157+ }
158+ }
159+
160+ template <class T ,
161+ class = typename std::enable_if<std::is_arithmetic<T>::value ||
162+ std::is_same<std::string, T>::value ||
163+ std::is_same<char *, T>::value>::type>
164+ void addColumn (const std::vector<T> &column) {
165+ const size_t tmp = _columnSize;
166+ for (size_t i = 0 ; i < column.size (); i++) {
167+ (*this )[i][tmp] = column[i];
168+ }
169+ }
170+
171+ template <class T ,
172+ class = typename std::enable_if<std::is_arithmetic<T>::value ||
173+ std::is_same<std::string, T>::value>::type>
174+ void addColumn (const T *column, const size_t &size) {
175+ const size_t tmp = _columnSize;
176+ for (size_t i = 0 ; i < size; i++) {
177+ (*this )[i][tmp] = column[i];
178+ }
179+ }
180+
181+ template <class T ,
182+ class = typename std::enable_if<std::is_arithmetic<T>::value ||
183+ std::is_same<std::string, T>::value ||
184+ std::is_same<char *, T>::value>::type>
185+ void assign (const std::vector<std::vector<T>> &table) {
186+ clear ();
187+ for (size_t i = 0 ; i < table.size (); i++)
188+ for (size_t j = 0 ; j < table[i].size (); j++)
189+ (*this )[i][j] = table[i][j];
190+ }
191+
192+ void clear () {
146193 for (auto &element : _tableData) {
147194 delete element.second ;
148195 }
196+
197+ _tableData.clear ();
198+ _columnSize = _rowSize = 0 ;
149199 }
150200
151201 void setAlignment (const Alignment &alignment) {
152202 _alignment = alignment;
153203 }
154204
155- void setIndent (const size_t &leftIndent, const size_t &rightIndent)
156- {
205+ void setIndent (const size_t &leftIndent, const size_t &rightIndent) {
157206 _leftIndent = leftIndent;
158207 _rightIndent = rightIndent;
159208 }
@@ -162,18 +211,21 @@ namespace samilton {
162211 _chars = chars;
163212 }
164213
165- ConsoleRow &operator [](const size_t &row) {
166- try {
167- return *_tableData.at (row);
168- }
169- catch (...) {
170- _tableData[row] = new ConsoleRow;
171- return *_tableData[row];
172- }
214+ template <class T ,
215+ class = typename std::enable_if<std::is_arithmetic<T>::value ||
216+ std::is_same<std::string, T>::value ||
217+ std::is_same<char *, T>::value>::type>
218+ ConsoleTable &operator =(const std::vector<std::vector<T>> &table) {
219+ assign (table);
220+ return *this ;
173221 }
174222
223+ ConsoleRow &operator [](const size_t row);
224+
175225 friend std::ostream &operator <<(std::ostream &stream, ConsoleTable &table);
176226 private:
227+ friend ConsoleString &ConsoleRow::operator [](const size_t column);
228+
177229 void _fillStreamByChar (std::ostream &stream, const char &fillChar, const size_t &lenght) {
178230 if (lenght > 0 )
179231 stream << std::setfill (fillChar) << std::setw (lenght);
@@ -188,29 +240,43 @@ namespace samilton {
188240 std::map<size_t , ConsoleRow*> _tableData;
189241 Alignment _alignment;
190242 size_t _leftIndent, _rightIndent;
243+ size_t _rowSize, _columnSize;
191244 };
192245
246+ inline ConsoleRow &ConsoleTable::operator [](const size_t row){
247+ try {
248+ return *_tableData.at (row);
249+ }
250+ catch (...) {
251+ _rowSize = std::max (_rowSize, row + 1 );
252+
253+ _tableData[row] = new ConsoleRow (this );
254+ return *_tableData[row];
255+ }
256+ }
257+
258+ inline ConsoleString &ConsoleRow::operator [](const size_t column) {
259+ try {
260+ return *_rowData.at (column);
261+ }
262+ catch (...) {
263+ _parent->_columnSize = std::max (_parent->_columnSize , column + 1 );
264+
265+ _rowData[column] = new ConsoleString (this );
266+ return *_rowData[column];
267+ }
268+ }
269+
193270 inline std::ostream &operator <<(std::ostream &stream, ConsoleTable &table) {
194271 // Return if table is empty
195272 if (table._tableData .size () == 0 )
196273 return stream;
197-
198- // Calculation row and column
199- size_t row = 0 ;
200- size_t column = 0 ;
201- for (auto &i : table._tableData ) {
202- row = std::max (row, i.first );
203- for (auto &j : i.second ->_rowData )
204- column = std::max (column, j.first );
205- }
206- row++;
207- column++;
208-
274+
209275 // Calculation width of every column
210276 std::vector<size_t > columnWidth;
211- for (size_t i = 0 ; i < column ; i++) {
277+ for (size_t i = 0 ; i < table. _columnSize ; i++) {
212278 size_t tmp = 1 ;
213- for (size_t j = 0 ; j < row ; j++) {
279+ for (size_t j = 0 ; j < table. _rowSize ; j++) {
214280 if (table._tableData [j] != nullptr && table._tableData [j]->_rowData [i] != nullptr ) {
215281 tmp = std::max (tmp, table._tableData [j]->_rowData [i]->_str .size ());
216282 }
@@ -222,16 +288,16 @@ namespace samilton {
222288 stream << std::right << table._chars .topLeft ;
223289 table._fillStreamByChar (stream, table._chars .topDownSimple , columnWidth[0 ] + 1 + table._leftIndent + table._rightIndent );
224290
225- if (column != 1 ) {
226- for (size_t i = 1 ; i < column ; i++) {
291+ if (table. _columnSize != 1 ) {
292+ for (size_t i = 1 ; i < table. _columnSize ; i++) {
227293 stream << table._chars .topSeparation << std::setw (columnWidth[i] + 1 + table._leftIndent + table._rightIndent );
228294 }
229295 }
230296 stream << table._chars .topRight << std::endl;
231297
232298 // Elements and middle borders
233- for (size_t i = 0 ; i < row ; i++) {
234- for (size_t j = 0 ; j < column ; j++) {
299+ for (size_t i = 0 ; i < table. _rowSize ; i++) {
300+ for (size_t j = 0 ; j < table. _columnSize ; j++) {
235301 if (table._tableData [i] != nullptr && table._tableData [i]->_rowData [j] != nullptr ) {
236302 if (table._alignment == ConsoleTable::Alignment::centre) {
237303 const size_t tmp = columnWidth[j] - table._tableData [i]->_rowData [j]->_str .size ();
@@ -279,12 +345,12 @@ namespace samilton {
279345 stream << std::right << table._chars .leftRightSimple << std::endl;
280346
281347 // Down border
282- if (i == row - 1 ) {
348+ if (i == table. _rowSize - 1 ) {
283349 stream << table._chars .downLeft ;
284350 table._fillStreamByChar (stream, table._chars .topDownSimple , columnWidth[0 ] + 1 + table._leftIndent + table._rightIndent );
285351
286- if (column != 1 ) {
287- for (size_t j = 1 ; j < column ; j++) {
352+ if (table. _columnSize != 1 ) {
353+ for (size_t j = 1 ; j < table. _columnSize ; j++) {
288354 stream << table._chars .downSeparation << std::setw (columnWidth[j] + 1 + table._leftIndent + table._rightIndent );
289355 }
290356 }
@@ -294,8 +360,8 @@ namespace samilton {
294360 stream << table._chars .leftSeparation ;
295361 table._fillStreamByChar (stream, table._chars .topDownSimple , columnWidth[0 ] + 1 + table._leftIndent + table._rightIndent );
296362
297- if (column != 1 ) {
298- for (size_t j = 1 ; j < column ; j++) {
363+ if (table. _columnSize != 1 ) {
364+ for (size_t j = 1 ; j < table. _columnSize ; j++) {
299365 stream << table._chars .centreSeparation << std::setw (columnWidth[j] + 1 + table._leftIndent + table._rightIndent );
300366 }
301367 }
0 commit comments