1
0
Files
YYCCommonplace/src/yycc/carton/tabulate.hpp

199 lines
6.1 KiB
C++

#pragma once
#include "../macro/class_copy_move.hpp"
#include <initializer_list>
#include <string>
#include <string_view>
#include <vector>
#include <iostream>
namespace yycc::carton::tabulate {
/**
* @private
* @brief Assistant class recording column width.
*/
class TabulateWidth {
public:
/**
* @brief Create width recorder with given column count.
* @param[in] n Column count.
*/
TabulateWidth(size_t n);
~TabulateWidth();
YYCC_DEFAULT_COPY_MOVE(TabulateWidth)
public:
/**
* @brief Get column count.
* @return Column count.
*/
size_t get_column_count() const;
/**
* @brief Get column width of given index.
* @param[in] column_index Column index for fetching width.
* @return Column width of given index.
*/
size_t get_column_width(size_t column_index) const;
/**
* @brief Update column width of given index with given value.
* @details The width of column will be updated to the maximum between given value and old value.
* @param[in] column_index Column index for updating width.
* @param[in] new_size New width value.
*/
void update_column_width(size_t column_index, size_t new_size);
/**
* @brief Clear all width data
* @details All width data will be reset to zero.
*/
void clear();
private:
std::vector<size_t> widths;
};
/**
* @private
* @brief Assistant class holding table cell data.
* @details
* This class holds the data of table cell.
* Also make a cache for the width this cell's text occupied in console,
* to avoid duplicated calculation for occupied width.
*/
class TabulateCell {
public:
/**
* @brief Build cell with given text.
* @param[in] text Data of cell.
*/
TabulateCell(const std::u8string_view& text);
~TabulateCell();
YYCC_DEFAULT_COPY_MOVE(TabulateCell)
public:
/**
* @brief Get the text of cell.
* @return The text of cell.
*/
const std::u8string& get_text() const;
/**
* @brief Get width this cell's text occupied in console.
* @return The width this cell occupied.
*/
size_t get_text_width() const;
private:
/// @brief The data of cell.
std::u8string text;
/// @brief The width cache of this data occupied in console.
size_t text_width;
};
/**
* @private
* @brief The type representing one row of data in table.
*/
using Row = std::vector<TabulateCell>;
/**
* @private
* @brief The type representing row collection in table.
*/
using Rows = std::vector<Row>;
/**
* @brief Main class of Tabulate
*/
class Tabulate {
public:
/**
* @brief Create Tabulate class with given column count.
* @details
* In default, the separator bar of table is 3 dash.
* Header and separator bar are also shown in default.
* @param[in] n Column count of table.
*/
Tabulate(size_t n);
~Tabulate();
YYCC_DELETE_COPY_MOVE(Tabulate)
public:
/**
* @brief Print table into given stream.
* @details In default, stream is \c stdout.
* @param[in] dst The stream printed into.
*/
void print(std::ostream& dst = std::cout) const;
/**
* @brief Get the column count of table.
* @return Column count of table.
*/
size_t get_column_count() const;
/**
* @brief Change whether show table header when printing.
* @param[in] show_header True for showing, otherwise false.
*/
void show_header(bool show_header);
/**
* @brief Change whether show separator bar when printing.
* @param[in] show_bar True for showing, otherwise false.
*/
void show_bar(bool show_bar);
/**
* @brief Modify the prefix string of table.
* @details
* The prefix string of table is the string
* which will be printed before each lines of output.
* It is usually used for indent.
* @param[in] prefix The prefix string.
*/
void set_prefix(const std::u8string_view& prefix);
/**
* @brief Modify the header of table.
* @param[in] hdr An initializer list holding header texts one by one.
* @exception std::invalid_argument The size of given header is mismatch with column count.
*/
void set_header(std::initializer_list<std::u8string_view> hdr);
/**
* @brief Modify separator bar string of table.
* @param[in] bar New separator bar string.
*/
void set_bar(const std::u8string_view& bar);
/**
* @brief Add one data row into table.
* @param[in] row An initializer list holding row texts one by one.
* @exception std::invalid_argument The size of given header is mismatch with column count.
*/
void add_row(std::initializer_list<std::u8string_view> row);
/**
* @brief Clear all data rows of table.
* @details Table header and separator bar will not be changed.
*/
void clear();
private:
/// @brief The column count of table.
size_t n;
/// @brief Whether showing table header.
bool header_display;
/// @brief Whether showing table separator bar between header and data.
bool bar_display;
/// @brief The prefix string presented in each lines of output table.
std::u8string prefix_string;
/// @brief Width recorder for header.
TabulateWidth header_widths;
/// @brief Width recorder for data.
TabulateWidth rows_widths;
/// @brief The header of table.
Row header;
/// @brief The separator bar of table.
TabulateCell bar;
/// @brief The data of table.
Rows rows;
};
}