/* {{copyright}} */ /* {{version}} */ /* {{license}} */ #pragma once #include #include namespace sdi_toolBox::console { //-------------------------------------------------------------- class ConsoleTable { public: using Row = std::vector; using ColumnWidths = std::vector; public: ConsoleTable() = default; // Constructor virtual ~ConsoleTable() = default; // Destructor ConsoleTable(const ConsoleTable &other) = delete; // Copy constructor ConsoleTable(ConsoleTable &&other) noexcept = delete; // Move constructor ConsoleTable &operator=(const ConsoleTable &other) = delete; // Copy assignment ConsoleTable &operator=(ConsoleTable &&other) noexcept = delete; // Move assignment void setHeaders(const Row &headers); // Set table headers void addRow(const Row &row); // Add a row to the table [[nodiscard]] std::string render() const; // Render the table as a string protected: Row m_headers; // Table headers std::vector m_rows; // Table rows size_t m_padding = 2; // Padding between columns private: [[nodiscard]] ColumnWidths calculateColumnWidths() const; // Calculate column widths [[nodiscard]] static std::string drawSeparator(const ColumnWidths &columnWidths); // Draw a separator line (+---+---+---+) [[nodiscard]] static std::string drawRow(const Row &row, // Draw a single row const ColumnWidths &columnWidths); }; //-------------------------------------------------------------- /* Set table headers */ inline void ConsoleTable::setHeaders(const Row &headers) { m_headers = headers; } //-------------------------------------------------------------- /* Add a row to the table */ inline void ConsoleTable::addRow(const Row &row) { m_rows.push_back(row); } //-------------------------------------------------------------- /* Render the table as a string */ inline std::string ConsoleTable::render() const { // Calculate column widths const auto columnWidths = calculateColumnWidths(); // Initialize the output string std::string output; // Draw the top separator output += drawSeparator(columnWidths); // Draw the headers output += drawRow(m_headers, columnWidths); // Draw the separator between headers and data output += drawSeparator(columnWidths); // Draw the data rows for (const auto &row : m_rows) { output += drawRow(row, columnWidths); } // Draw the bottom separator output += drawSeparator(columnWidths); return output; } //-------------------------------------------------------------- /* Calculate column widths */ inline ConsoleTable::ColumnWidths ConsoleTable::calculateColumnWidths() const { // Determine the number of columns (based on headers or first row) const auto numColumns = m_headers.empty() ? (m_rows.empty() ? 0 : m_rows[0].size()) : m_headers.size(); // Initialize column widths ColumnWidths widths(numColumns, 0); // Calculate widths based on headers for (size_t i = 0; i < m_headers.size() && i < numColumns; ++i) { widths[i] = std::max(widths[i], m_headers[i].length() + m_padding); } // Calculate widths based on rows for (const auto &row : m_rows) { for (size_t i = 0; i < row.size() && i < numColumns; ++i) { widths[i] = std::max(widths[i], row[i].length() + m_padding); } } return widths; } //-------------------------------------------------------------- /* Draw a separator line (+---+---+---+) */ inline std::string ConsoleTable::drawSeparator(const ColumnWidths &columnWidths) { std::string output; output += "+"; for (const auto &width : columnWidths) { output += std::string(width, '-') + "+"; } output += "\n"; return output; } //-------------------------------------------------------------- /* Draw a single row */ inline std::string ConsoleTable::drawRow(const Row &row, const ColumnWidths &columnWidths) { std::string output; output += "|"; for (size_t i = 0; i < columnWidths.size(); ++i) { const auto cellContent = (i < row.size()) ? row[i] : ""; output += " " + cellContent; // Add padding spaces const size_t paddingSpaces = columnWidths[i] - cellContent.length() - 1; output += std::string(paddingSpaces, ' '); output += "|"; } output += "\n"; return output; } //-------------------------------------------------------------- } // namespace sdi_toolBox::console