Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 131 additions & 65 deletions CppConsoleTable.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
========================= Cpp Console Table
| Cpp | Console | Table | version 1.0.0
========================= https://github.com/Oradle/CppConsoleTable
========================= Cpp Console Table
| Cpp | Console | Table | version 1.2.0
========================= https://github.com/Oradle/CppConsoleTable

Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2017 Oradle
Expand Down Expand Up @@ -35,13 +35,19 @@ SOFTWARE.
#include <iomanip>
#include <algorithm>
#include <vector>
#include <type_traits>

namespace samilton {
// force declaration
class ConsoleTable;
class ConsoleRow;

class ConsoleString {
public:
ConsoleString(ConsoleRow *parent) {
_parent = parent;
}

ConsoleString &operator=(const std::string &val) {
_str = val;
return *this;
Expand All @@ -52,22 +58,8 @@ namespace samilton {
return *this;
}

ConsoleString &operator=(const long &val) {
_str = std::to_string(val);
return *this;
}

ConsoleString &operator=(const int &val) {
_str = std::to_string(val);
return *this;
}

ConsoleString &operator=(const double &val) {
_str = std::to_string(val);
return *this;
}

ConsoleString &operator=(const float &val) {
template<class T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
ConsoleString &operator=(const T &val) {
_str = std::to_string(val);
return *this;
}
Expand All @@ -83,29 +75,28 @@ namespace samilton {
private:
friend std::ostream &operator<<(std::ostream &stream, ConsoleTable &table);

ConsoleRow *_parent;
std::string _str;
};

class ConsoleRow {
public:
ConsoleRow(ConsoleTable *parent) {
_parent = parent;
}

~ConsoleRow() {
for (auto &element : _rowData) {
delete element.second;
}
_rowData.clear();
}

ConsoleString &operator[](const size_t &column) {
try {
return *_rowData.at(column);
}
catch (...) {
_rowData[column] = new ConsoleString;
return *_rowData[column];
}
}
ConsoleString &operator[](const size_t column);
private:
friend std::ostream &operator<<(std::ostream &stream, ConsoleTable &table);

ConsoleTable *_parent;
std::map<size_t, ConsoleString*> _rowData;
};

Expand All @@ -126,34 +117,92 @@ namespace samilton {

ConsoleTable() {
_alignment = Alignment::left;
_leftIndent = 0;
_rightIndent = 0;
_leftIndent = _rightIndent = _rowSize = _columnSize = 0;
}

ConsoleTable(const Alignment &alignment) {
_alignment = alignment;
_leftIndent = 0;
_rightIndent = 0;
_leftIndent = _rightIndent = _rowSize = _columnSize = 0;
}

ConsoleTable(const size_t &leftIndent, const size_t &rightIndent, const Alignment &alignment = Alignment::left) {
_leftIndent = leftIndent;
_rightIndent = rightIndent;
_alignment = alignment;
_rowSize = _columnSize = 0;
}

~ConsoleTable() {
clear();
}

template<class T,
class = typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<std::string, T>::value ||
std::is_same<char*, T>::value>::type>
void addRow(const std::vector<T> &row) {
const size_t tmp = _rowSize;
for (size_t i = 0; i < row.size(); i++) {
(*this)[tmp][i] = row[i];
}
}

template<class T,
class = typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<std::string, T>::value>::type>
void addRow(const T *row, const size_t &size) {
const size_t tmp = _rowSize;
for (size_t i = 0; i < size; i++) {
(*this)[tmp][i] = row[i];
}
}

template<class T,
class = typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<std::string, T>::value ||
std::is_same<char*, T>::value>::type>
void addColumn(const std::vector<T> &column) {
const size_t tmp = _columnSize;
for (size_t i = 0; i < column.size(); i++) {
(*this)[i][tmp] = column[i];
}
}

template<class T,
class = typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<std::string, T>::value>::type>
void addColumn(const T *column, const size_t &size) {
const size_t tmp = _columnSize;
for (size_t i = 0; i < size; i++) {
(*this)[i][tmp] = column[i];
}
}

template<class T,
class = typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<std::string, T>::value ||
std::is_same<char*, T>::value>::type>
void assign(const std::vector<std::vector<T>> &table) {
clear();
for (size_t i = 0; i < table.size(); i++)
for (size_t j = 0; j < table[i].size(); j++)
(*this)[i][j] = table[i][j];
}

void clear() {
for (auto &element : _tableData) {
delete element.second;
}

_tableData.clear();
_columnSize = _rowSize = 0;
}

void setAlignment(const Alignment &alignment) {
_alignment = alignment;
}

void setIndent(const size_t &leftIndent, const size_t &rightIndent)
{
void setIndent(const size_t &leftIndent, const size_t &rightIndent) {
_leftIndent = leftIndent;
_rightIndent = rightIndent;
}
Expand All @@ -162,18 +211,21 @@ namespace samilton {
_chars = chars;
}

ConsoleRow &operator[](const size_t &row) {
try {
return *_tableData.at(row);
}
catch (...) {
_tableData[row] = new ConsoleRow;
return *_tableData[row];
}
template<class T,
class = typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<std::string, T>::value ||
std::is_same<char*, T>::value>::type>
ConsoleTable &operator=(const std::vector<std::vector<T>> &table) {
assign(table);
return *this;
}

ConsoleRow &operator[](const size_t row);

friend std::ostream &operator<<(std::ostream &stream, ConsoleTable &table);
private:
friend ConsoleString &ConsoleRow::operator[](const size_t column);

void _fillStreamByChar(std::ostream &stream, const char &fillChar, const size_t &lenght) {
if (lenght > 0)
stream << std::setfill(fillChar) << std::setw(lenght);
Expand All @@ -188,29 +240,43 @@ namespace samilton {
std::map<size_t, ConsoleRow*> _tableData;
Alignment _alignment;
size_t _leftIndent, _rightIndent;
size_t _rowSize, _columnSize;
};

inline ConsoleRow &ConsoleTable::operator[](const size_t row){
try {
return *_tableData.at(row);
}
catch (...) {
_rowSize = std::max(_rowSize, row + 1);

_tableData[row] = new ConsoleRow(this);
return *_tableData[row];
}
}

inline ConsoleString &ConsoleRow::operator[](const size_t column) {
try {
return *_rowData.at(column);
}
catch (...) {
_parent->_columnSize = std::max(_parent->_columnSize, column + 1);

_rowData[column] = new ConsoleString(this);
return *_rowData[column];
}
}

inline std::ostream &operator<<(std::ostream &stream, ConsoleTable &table) {
// Return if table is empty
if (table._tableData.size() == 0)
return stream;

// Calculation row and column
size_t row = 0;
size_t column = 0;
for (auto &i : table._tableData) {
row = std::max(row, i.first);
for (auto &j : i.second->_rowData)
column = std::max(column, j.first);
}
row++;
column++;


// Calculation width of every column
std::vector<size_t> columnWidth;
for (size_t i = 0; i < column; i++) {
for (size_t i = 0; i < table._columnSize; i++) {
size_t tmp = 1;
for (size_t j = 0; j < row; j++) {
for (size_t j = 0; j < table._rowSize; j++) {
if (table._tableData[j] != nullptr && table._tableData[j]->_rowData[i] != nullptr) {
tmp = std::max(tmp, table._tableData[j]->_rowData[i]->_str.size());
}
Expand All @@ -222,16 +288,16 @@ namespace samilton {
stream << std::right << table._chars.topLeft;
table._fillStreamByChar(stream, table._chars.topDownSimple, columnWidth[0] + 1 + table._leftIndent + table._rightIndent);

if (column != 1) {
for (size_t i = 1; i < column; i++) {
if (table._columnSize != 1) {
for (size_t i = 1; i < table._columnSize; i++) {
stream << table._chars.topSeparation << std::setw(columnWidth[i] + 1 + table._leftIndent + table._rightIndent);
}
}
stream << table._chars.topRight << std::endl;

// Elements and middle borders
for (size_t i = 0; i < row; i++) {
for (size_t j = 0; j < column; j++) {
for (size_t i = 0; i < table._rowSize; i++) {
for (size_t j = 0; j < table._columnSize; j++) {
if (table._tableData[i] != nullptr && table._tableData[i]->_rowData[j] != nullptr) {
if (table._alignment == ConsoleTable::Alignment::centre) {
const size_t tmp = columnWidth[j] - table._tableData[i]->_rowData[j]->_str.size();
Expand Down Expand Up @@ -279,12 +345,12 @@ namespace samilton {
stream << std::right << table._chars.leftRightSimple << std::endl;

// Down border
if (i == row - 1) {
if (i == table._rowSize - 1) {
stream << table._chars.downLeft;
table._fillStreamByChar(stream, table._chars.topDownSimple, columnWidth[0] + 1 + table._leftIndent + table._rightIndent);

if (column != 1) {
for (size_t j = 1; j < column; j++) {
if (table._columnSize != 1) {
for (size_t j = 1; j < table._columnSize; j++) {
stream << table._chars.downSeparation << std::setw(columnWidth[j] + 1 + table._leftIndent + table._rightIndent);
}
}
Expand All @@ -294,8 +360,8 @@ namespace samilton {
stream << table._chars.leftSeparation;
table._fillStreamByChar(stream, table._chars.topDownSimple, columnWidth[0] + 1 + table._leftIndent + table._rightIndent);

if (column != 1) {
for (size_t j = 1; j < column; j++) {
if (table._columnSize != 1) {
for (size_t j = 1; j < table._columnSize; j++) {
stream << table._chars.centreSeparation << std::setw(columnWidth[j] + 1 + table._leftIndent + table._rightIndent);
}
}
Expand Down