| 57 | namespace tabulate { |
| 58 | |
| 59 | class Table { |
| 60 | public: |
| 61 | Table() : table_(TableInternal::create()) {} |
| 62 | |
| 63 | using Row_t = std::vector<variant<std::string, const char *, string_view, Table>>; |
| 64 | |
| 65 | Table &add_row(const Row_t &cells) { |
| 66 | |
| 67 | if (rows_ == 0) { |
| 68 | // This is the first row added |
| 69 | // cells.size() is the number of columns |
| 70 | cols_ = cells.size(); |
| 71 | } |
| 72 | |
| 73 | std::vector<std::string> cell_strings; |
| 74 | if (cells.size() < cols_) { |
| 75 | cell_strings.resize(cols_); |
| 76 | std::fill(cell_strings.begin(), cell_strings.end(), ""); |
| 77 | } else { |
| 78 | cell_strings.resize(cells.size()); |
| 79 | std::fill(cell_strings.begin(), cell_strings.end(), ""); |
| 80 | } |
| 81 | |
| 82 | for (size_t i = 0; i < cells.size(); ++i) { |
| 83 | auto cell = cells[i]; |
| 84 | if (holds_alternative<std::string>(cell)) { |
| 85 | cell_strings[i] = *get_if<std::string>(&cell); |
| 86 | } else if (holds_alternative<const char *>(cell)) { |
| 87 | cell_strings[i] = *get_if<const char *>(&cell); |
| 88 | } else if (holds_alternative<string_view>(cell)) { |
| 89 | cell_strings[i] = std::string{*get_if<string_view>(&cell)}; |
| 90 | } else { |
| 91 | auto table = *get_if<Table>(&cell); |
| 92 | std::stringstream stream; |
| 93 | table.print(stream); |
| 94 | cell_strings[i] = stream.str(); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | table_->add_row(cell_strings); |
| 99 | rows_ += 1; |
| 100 | return *this; |
| 101 | } |
| 102 | |
| 103 | Row &operator[](size_t index) { return row(index); } |
| 104 | |
| 105 | Row &row(size_t index) { return (*table_)[index]; } |
| 106 | |
| 107 | Column column(size_t index) { return table_->column(index); } |
| 108 | |
| 109 | Format &format() { return table_->format(); } |
| 110 | |
| 111 | void print(std::ostream &stream) { table_->print(stream); } |
| 112 | |
| 113 | std::string str() { |
| 114 | std::stringstream stream; |
| 115 | print(stream); |
| 116 | return stream.str(); |