1237 lines
32 KiB
C++
1237 lines
32 KiB
C++
/*
|
|
libfort
|
|
|
|
MIT License
|
|
|
|
Copyright (c) 2017 - 2020 Seleznev Anton
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
/**
|
|
* @file fort.hpp
|
|
* @brief Main header file describing libfort C++ API .
|
|
*
|
|
* This files contains C++ wrappers around libfort API that can
|
|
* be used in C++ code.
|
|
*/
|
|
#ifndef LIBFORT_HPP
|
|
#define LIBFORT_HPP
|
|
|
|
#include <string>
|
|
#include <stdexcept>
|
|
#include <sstream>
|
|
|
|
#include "fort.h"
|
|
|
|
namespace fort
|
|
{
|
|
|
|
/**
|
|
* Alignment of cell content.
|
|
*/
|
|
enum class text_align {
|
|
left = FT_ALIGNED_LEFT,
|
|
center = FT_ALIGNED_CENTER,
|
|
right = FT_ALIGNED_RIGHT
|
|
};
|
|
|
|
/**
|
|
* Type of table row. Determines appearance of row.
|
|
*/
|
|
enum class row_type {
|
|
common = FT_ROW_COMMON,
|
|
header = FT_ROW_HEADER
|
|
};
|
|
|
|
/**
|
|
* Adding strategy.
|
|
*
|
|
* Determines what happens with old content if current cell is not empty after
|
|
* adding data to it. Default strategy is 'replace'.
|
|
*/
|
|
enum class add_strategy {
|
|
replace = FT_STRATEGY_REPLACE,
|
|
insert = FT_STRATEGY_INSERT
|
|
};
|
|
|
|
/**
|
|
* Colors.
|
|
*/
|
|
enum class color {
|
|
default_color = FT_COLOR_DEFAULT,
|
|
black = FT_COLOR_BLACK,
|
|
red = FT_COLOR_RED,
|
|
green = FT_COLOR_GREEN,
|
|
yellow = FT_COLOR_YELLOW,
|
|
blue = FT_COLOR_BLUE,
|
|
magenta = FT_COLOR_MAGENTA,
|
|
cyan = FT_COLOR_CYAN,
|
|
light_gray = FT_COLOR_LIGHT_GRAY,
|
|
dark_gray = FT_COLOR_DARK_GRAY,
|
|
light_red = FT_COLOR_LIGHT_RED,
|
|
light_green = FT_COLOR_LIGHT_GREEN,
|
|
light_yellow = FT_COLOR_LIGHT_YELLOW,
|
|
light_blue = FT_COLOR_LIGHT_BLUE,
|
|
light_magenta = FT_COLOR_LIGHT_MAGENTA,
|
|
light_cyan = FT_COLOR_LIGHT_CYAN,
|
|
light_whyte = FT_COLOR_LIGHT_WHYTE
|
|
};
|
|
|
|
/**
|
|
* Text styles.
|
|
*/
|
|
enum class text_style {
|
|
default_style = FT_TSTYLE_DEFAULT,
|
|
bold = FT_TSTYLE_BOLD,
|
|
dim = FT_TSTYLE_DIM,
|
|
italic = FT_TSTYLE_ITALIC,
|
|
underlined = FT_TSTYLE_UNDERLINED,
|
|
blink = FT_TSTYLE_BLINK,
|
|
inverted = FT_TSTYLE_INVERTED,
|
|
hidden = FT_TSTYLE_HIDDEN
|
|
};
|
|
|
|
|
|
enum class table_type {
|
|
character,
|
|
#ifdef FT_HAVE_UTF8
|
|
utf8
|
|
#endif /* FT_HAVE_UTF8 */
|
|
};
|
|
|
|
/**
|
|
* Table manipulator.
|
|
*
|
|
* Table manipulators can be used to change current cell and change appearance
|
|
* of cells.
|
|
*/
|
|
class table_manipulator
|
|
{
|
|
public:
|
|
explicit table_manipulator(int i)
|
|
: value(i)
|
|
{
|
|
}
|
|
template <table_type TT>
|
|
friend class table;
|
|
private:
|
|
int value;
|
|
};
|
|
|
|
/**
|
|
* Table manipulator to set current row as a header.
|
|
*/
|
|
const table_manipulator header(0);
|
|
|
|
/**
|
|
* Table manipulator to move current cell to the first cell of the next row.
|
|
*/
|
|
const table_manipulator endr(1);
|
|
|
|
/**
|
|
* Table manipulator to add separator to the table.
|
|
*/
|
|
const table_manipulator separator(2);
|
|
|
|
/**
|
|
* Property owner.
|
|
*
|
|
* property_owner is a base class for all objects (table, row, column, cell) for
|
|
* which user can specify properties.
|
|
*/
|
|
template <typename table>
|
|
class property_owner
|
|
{
|
|
public:
|
|
|
|
property_owner(std::size_t row_idx, std::size_t coll_idx, table *tbl, bool def = false)
|
|
: ps_row_idx_(row_idx), ps_coll_idx_(coll_idx),
|
|
ps_table_(tbl), set_default_properties_(def) {}
|
|
|
|
/**
|
|
* Set min width for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Value of the min width.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error
|
|
*/
|
|
bool set_cell_min_width(unsigned value)
|
|
{
|
|
return set_property(FT_CPROP_MIN_WIDTH, value);
|
|
}
|
|
|
|
/**
|
|
* Set text alignment for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Value of the text alignment.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error
|
|
*/
|
|
bool set_cell_text_align(fort::text_align value)
|
|
{
|
|
return set_property(FT_CPROP_TEXT_ALIGN, static_cast<int>(value));
|
|
}
|
|
|
|
/**
|
|
* Set top padding for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Value of the top padding.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_top_padding(unsigned value)
|
|
{
|
|
return set_property(FT_CPROP_TOP_PADDING, value);
|
|
}
|
|
|
|
/**
|
|
* Set bottom padding for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Value of the bottom padding.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_bottom_padding(unsigned value)
|
|
{
|
|
return set_property(FT_CPROP_BOTTOM_PADDING, value);
|
|
}
|
|
|
|
/**
|
|
* Set left padding for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Value of the left padding.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_left_padding(unsigned value)
|
|
{
|
|
return set_property(FT_CPROP_LEFT_PADDING, value);
|
|
}
|
|
|
|
/**
|
|
* Set right padding for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Value of the left padding.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_right_padding(unsigned value)
|
|
{
|
|
return set_property(FT_CPROP_RIGHT_PADDING, value);
|
|
}
|
|
|
|
/**
|
|
* Set row type for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Value of the row type.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_row_type(fort::row_type value)
|
|
{
|
|
return set_property(FT_CPROP_ROW_TYPE, static_cast<int>(value));
|
|
}
|
|
|
|
/**
|
|
* Set empty string height for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Value of the empty string height.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_empty_str_height(unsigned value)
|
|
{
|
|
return set_property(FT_CPROP_EMPTY_STR_HEIGHT, value);
|
|
}
|
|
|
|
/**
|
|
* Set content foreground color for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Color.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_content_fg_color(fort::color value)
|
|
{
|
|
return set_property(FT_CPROP_CONT_FG_COLOR, static_cast<int>(value));
|
|
}
|
|
|
|
/**
|
|
* Set cell background color for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Color.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_bg_color(fort::color value)
|
|
{
|
|
return set_property(FT_CPROP_CELL_BG_COLOR, static_cast<int>(value));
|
|
}
|
|
|
|
/**
|
|
* Set content background color for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Color.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_content_bg_color(fort::color value)
|
|
{
|
|
return set_property(FT_CPROP_CONT_BG_COLOR, static_cast<int>(value));
|
|
}
|
|
|
|
/**
|
|
* Set cell text style for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Text style.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_text_style(fort::text_style value)
|
|
{
|
|
return set_property(FT_CPROP_CELL_TEXT_STYLE, static_cast<int>(value));
|
|
}
|
|
|
|
/**
|
|
* Set content text style for the specified cell of the table.
|
|
*
|
|
* @param value
|
|
* Text style.
|
|
* @return
|
|
* - true: Success; cell property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_content_text_style(fort::text_style value)
|
|
{
|
|
return set_property(FT_CPROP_CONT_TEXT_STYLE, static_cast<int>(value));
|
|
}
|
|
|
|
protected:
|
|
std::size_t ps_row_idx_;
|
|
std::size_t ps_coll_idx_;
|
|
table *ps_table_;
|
|
bool set_default_properties_;
|
|
|
|
bool set_property(uint32_t property, int value)
|
|
{
|
|
int status;
|
|
if (set_default_properties_) {
|
|
status = ft_set_default_cell_prop(property, value);
|
|
} else {
|
|
status = ft_set_cell_prop(ps_table_->table_, ps_row_idx_, ps_coll_idx_, property, value);
|
|
}
|
|
return FT_IS_SUCCESS(status);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Formatted table.
|
|
*
|
|
* Table template class is a C++ wrapper around struct {@link ft_table}.
|
|
* Template parameter is {@link table_type}. Useful instantiations of table
|
|
* template class are {@link char_table} and {@link utf8_table}.
|
|
*/
|
|
template <table_type TT = table_type::character>
|
|
class table: public property_owner<table<TT>>
|
|
{
|
|
/**
|
|
* Utility types.
|
|
*/
|
|
using table_t = table<TT>;
|
|
using property_owner_t = property_owner<table_t>;
|
|
|
|
public:
|
|
|
|
/**
|
|
* Default constructor.
|
|
*/
|
|
table()
|
|
: property_owner_t(FT_ANY_ROW, FT_ANY_COLUMN, this),
|
|
table_(ft_create_table())
|
|
{
|
|
if (table_ == NULL)
|
|
throw std::bad_alloc();
|
|
}
|
|
|
|
/**
|
|
* Destructor.
|
|
*/
|
|
~table()
|
|
{
|
|
ft_destroy_table(table_);
|
|
}
|
|
|
|
/**
|
|
* Copy contstructor.
|
|
*/
|
|
table(const table &tbl)
|
|
: property_owner_t(FT_ANY_ROW, FT_ANY_COLUMN, this), table_(NULL)
|
|
{
|
|
if (tbl.table_) {
|
|
ft_table_t *table_copy = ft_copy_table(tbl.table_);
|
|
if (table_copy == NULL)
|
|
throw std::runtime_error("Error during table copy");
|
|
|
|
stream_.str(std::string());
|
|
if (tbl.stream_.tellp() >= 0) {
|
|
stream_ << tbl.stream_.str();
|
|
}
|
|
table_ = table_copy;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Move contstructor.
|
|
*/
|
|
table(table &&tbl)
|
|
: property_owner_t(FT_ANY_ROW, FT_ANY_COLUMN, this), table_(tbl.table_)
|
|
{
|
|
if (tbl.stream_.tellp() >= 0) {
|
|
stream_ << tbl.stream_.str();
|
|
tbl.stream_.str(std::string());
|
|
}
|
|
tbl.table_ = 0;
|
|
}
|
|
|
|
/**
|
|
* Copy assignment operator.
|
|
*/
|
|
table &operator=(const table &tbl)
|
|
{
|
|
if (&tbl == this)
|
|
return *this;
|
|
|
|
if (tbl.table_) {
|
|
ft_table_t *table_copy = ft_copy_table(tbl.table_);
|
|
if (table_copy == NULL)
|
|
throw std::runtime_error("Error during table copy");
|
|
|
|
stream_.str(std::string());
|
|
if (tbl.stream_.tellp() >= 0) {
|
|
stream_ << tbl.stream_.str();
|
|
}
|
|
ft_destroy_table(table_);
|
|
table_ = table_copy;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Move assignment operator.
|
|
*/
|
|
table &operator=(table &&tbl)
|
|
{
|
|
if (&tbl == this)
|
|
return *this;
|
|
|
|
if (tbl.table_) {
|
|
stream_.str(std::string());
|
|
if (tbl.stream_.tellp() >= 0) {
|
|
stream_ << tbl.stream_.str();
|
|
tbl.stream_.str(std::string());
|
|
}
|
|
ft_destroy_table(table_);
|
|
table_ = tbl.table_;
|
|
tbl.table_ = NULL;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Convert table to string representation.
|
|
*
|
|
* @return
|
|
* - String representation of formatted table, on success.
|
|
* - In case of error std::runtime_error is thrown.
|
|
*/
|
|
std::string to_string() const
|
|
{
|
|
const char *str = c_str();
|
|
if (str == NULL)
|
|
throw std::runtime_error("Error during table to string conversion");
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* Convert table to string representation.
|
|
*
|
|
* Table object has ownership of the returned pointer. So there is no need to
|
|
* free it. To take ownership user should explicitly copy the returned
|
|
* string with strdup or similar functions.
|
|
*
|
|
* Returned pointer may be later invalidated by:
|
|
* - Calling destroying the table;
|
|
* - Other invocations of c_str or to_string.
|
|
*
|
|
* @return
|
|
* - The pointer to the string representation of formatted table, on success.
|
|
* - NULL on error.
|
|
*/
|
|
const char *c_str() const
|
|
{
|
|
#ifdef FT_HAVE_UTF8
|
|
return (TT == table_type::character)
|
|
? ft_to_string(table_)
|
|
: (const char *)ft_to_u8string(table_);
|
|
#else
|
|
return ft_to_string(table_);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Write provided object to the table.
|
|
*
|
|
* To convert object to the string representation conversion for
|
|
* std::ostream is used.
|
|
*
|
|
* @param arg
|
|
* Obect that would be inserted in the current cell.
|
|
* @return
|
|
* - Reference to the current table.
|
|
*/
|
|
template <typename T>
|
|
table &operator<<(const T &arg)
|
|
{
|
|
stream_ << arg;
|
|
if (stream_.tellp() >= 0) {
|
|
#ifdef FT_HAVE_UTF8
|
|
if (TT == table_type::character) {
|
|
ft_nwrite(table_, 1, stream_.str().c_str());
|
|
} else {
|
|
ft_u8nwrite(table_, 1, (const void *)stream_.str().c_str());
|
|
}
|
|
#else
|
|
ft_nwrite(table_, 1, stream_.str().c_str());
|
|
#endif
|
|
|
|
stream_.str(std::string());
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
table &operator<<(const table_manipulator &arg)
|
|
{
|
|
if (arg.value == header.value)
|
|
ft_set_cell_prop(table_, FT_CUR_ROW, FT_ANY_ROW, FT_CPROP_ROW_TYPE, FT_ROW_HEADER);
|
|
else if (arg.value == endr.value)
|
|
ft_ln(table_);
|
|
else if (arg.value == separator.value)
|
|
ft_add_separator(table_);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Write string to the the table.
|
|
*
|
|
* Write specified string to the current cell.
|
|
*
|
|
* @param str
|
|
* String to write.
|
|
* @return
|
|
* - 0: Success; data were written
|
|
* - (<0): In case of error
|
|
*/
|
|
bool write(const char *str)
|
|
{
|
|
#ifdef FT_HAVE_UTF8
|
|
if (TT == table_type::character) {
|
|
return FT_IS_SUCCESS(ft_write(table_, str));
|
|
} else {
|
|
return FT_IS_SUCCESS(ft_u8write(table_, (const void *)str));
|
|
}
|
|
#else
|
|
return FT_IS_SUCCESS(ft_write(table_, str));
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Write string to the the table and go to the next line.
|
|
*
|
|
* Write specified string to the current cell and move current position to
|
|
* the first cell of the next line(row).
|
|
*
|
|
* @param str
|
|
* String to write.
|
|
* @return
|
|
* - 0: Success; data were written
|
|
* - (<0): In case of error
|
|
*/
|
|
bool write_ln(const char *str)
|
|
{
|
|
#ifdef FT_HAVE_UTF8
|
|
if (TT == table_type::character) {
|
|
return FT_IS_SUCCESS(ft_write_ln(table_, str));
|
|
} else {
|
|
return FT_IS_SUCCESS(ft_u8write_ln(table_, str));
|
|
}
|
|
#else
|
|
return FT_IS_SUCCESS(ft_write_ln(table_, str));
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Write string to the the table.
|
|
*
|
|
* Write specified string to the current cell.
|
|
*
|
|
* @param str
|
|
* String to write.
|
|
* @return
|
|
* - 0: Success; data were written
|
|
* - (<0): In case of error
|
|
*/
|
|
bool write(const std::string &str)
|
|
{
|
|
return write(str.c_str());
|
|
}
|
|
|
|
/**
|
|
* Write string to the the table and go to the next line.
|
|
*
|
|
* Write specified string to the current cell and move current position to
|
|
* the first cell of the next line(row).
|
|
*
|
|
* @param str
|
|
* String to write.
|
|
* @return
|
|
* - 0: Success; data were written
|
|
* - (<0): In case of error
|
|
*/
|
|
bool write_ln(const std::string &str)
|
|
{
|
|
return write_ln(str.c_str());
|
|
}
|
|
|
|
#ifdef __cpp_variadic_templates
|
|
/**
|
|
* Write strings to the table.
|
|
*
|
|
* Write specified strings to the same number of consecutive cells in the
|
|
* current row.
|
|
*
|
|
* @param str
|
|
* String to write.
|
|
* @param strings
|
|
* Strings to write.
|
|
* @return
|
|
* - 0: Success; data were written
|
|
* - (<0): In case of error
|
|
*/
|
|
template <typename T, typename ...Ts>
|
|
bool write(const T &str, const Ts &...strings)
|
|
{
|
|
return write(str) && write(strings...);
|
|
}
|
|
|
|
/**
|
|
* Write strings to the table and go to the next line.
|
|
*
|
|
* Write specified strings to the same number of consecutive cells in the
|
|
* current row and move current position to the first cell of the next
|
|
* line(row).
|
|
*
|
|
* @param str
|
|
* String to write.
|
|
* @param strings
|
|
* Strings to write.
|
|
* @return
|
|
* - 0: Success; data were written
|
|
* - (<0): In case of error
|
|
*/
|
|
template <typename T, typename ...Ts>
|
|
bool write_ln(const T &str, const Ts &...strings)
|
|
{
|
|
return write(str) && write_ln(strings...);
|
|
}
|
|
#else /* __cpp_variadic_templates */
|
|
|
|
template <typename T_0, typename T_1>
|
|
bool write(const T_0 &arg_0, const T_1 &arg_1)
|
|
{
|
|
return write(arg_0) && write(arg_1);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2>
|
|
bool write(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2)
|
|
{
|
|
return write(arg_0) && write(arg_1, arg_2);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3>
|
|
bool write(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3)
|
|
{
|
|
return write(arg_0) && write(arg_1, arg_2, arg_3);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3, typename T_4>
|
|
bool write(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3, const T_4 &arg_4)
|
|
{
|
|
return write(arg_0) && write(arg_1, arg_2, arg_3, arg_4);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3, typename T_4, typename T_5>
|
|
bool write(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3, const T_4 &arg_4, const T_5 &arg_5)
|
|
{
|
|
return write(arg_0) && write(arg_1, arg_2, arg_3, arg_4, arg_5);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3, typename T_4, typename T_5, typename T_6>
|
|
bool write(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3, const T_4 &arg_4, const T_5 &arg_5, const T_6 &arg_6)
|
|
{
|
|
return write(arg_0) && write(arg_1, arg_2, arg_3, arg_4, arg_5, arg_6);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3, typename T_4, typename T_5, typename T_6, typename T_7>
|
|
bool write(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3, const T_4 &arg_4, const T_5 &arg_5, const T_6 &arg_6, const T_7 &arg_7)
|
|
{
|
|
return write(arg_0) && write(arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7);
|
|
}
|
|
|
|
|
|
template <typename T_0, typename T_1>
|
|
bool write_ln(const T_0 &arg_0, const T_1 &arg_1)
|
|
{
|
|
return write(arg_0) && write_ln(arg_1);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2>
|
|
bool write_ln(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2)
|
|
{
|
|
return write(arg_0) && write_ln(arg_1, arg_2);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3>
|
|
bool write_ln(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3)
|
|
{
|
|
return write(arg_0) && write_ln(arg_1, arg_2, arg_3);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3, typename T_4>
|
|
bool write_ln(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3, const T_4 &arg_4)
|
|
{
|
|
return write(arg_0) && write_ln(arg_1, arg_2, arg_3, arg_4);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3, typename T_4, typename T_5>
|
|
bool write_ln(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3, const T_4 &arg_4, const T_5 &arg_5)
|
|
{
|
|
return write(arg_0) && write_ln(arg_1, arg_2, arg_3, arg_4, arg_5);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3, typename T_4, typename T_5, typename T_6>
|
|
bool write_ln(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3, const T_4 &arg_4, const T_5 &arg_5, const T_6 &arg_6)
|
|
{
|
|
return write(arg_0) && write_ln(arg_1, arg_2, arg_3, arg_4, arg_5, arg_6);
|
|
}
|
|
|
|
template <typename T_0, typename T_1, typename T_2, typename T_3, typename T_4, typename T_5, typename T_6, typename T_7>
|
|
bool write_ln(const T_0 &arg_0, const T_1 &arg_1, const T_2 &arg_2, const T_3 &arg_3, const T_4 &arg_4, const T_5 &arg_5, const T_6 &arg_6, const T_7 &arg_7)
|
|
{
|
|
return write(arg_0) && write_ln(arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7);
|
|
}
|
|
|
|
#endif /* __cpp_variadic_templates */
|
|
|
|
/**
|
|
* Write elements from range to the table.
|
|
*
|
|
* Write objects from range to consecutive cells in the current row.
|
|
*
|
|
* @param first, last
|
|
* Range of elements.
|
|
* @return
|
|
* - 0: Success; data were written
|
|
* - (<0): In case of error
|
|
*/
|
|
template <typename InputIt>
|
|
bool range_write(InputIt first, InputIt last)
|
|
{
|
|
while (first != last) {
|
|
*this << *first;
|
|
++first;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Write elements from range to the table and go to the next line.
|
|
*
|
|
* Write objects from range to consecutive cells in the current row and
|
|
* move current position to the first cell of the next line(row).
|
|
*
|
|
* @param first, last
|
|
* Range of elements.
|
|
* @return
|
|
* - 0: Success; data were written
|
|
* - (<0): In case of error
|
|
*/
|
|
template <typename InputIt>
|
|
bool range_write_ln(InputIt first, InputIt last)
|
|
{
|
|
while (first != last) {
|
|
*this << *first;
|
|
++first;
|
|
}
|
|
ft_ln(table_);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Set border style for the table.
|
|
*
|
|
* @param style
|
|
* Pointer to border style.
|
|
* @return
|
|
* - True: Success; table border style was changed.
|
|
* - False: Error
|
|
*/
|
|
bool set_border_style(const struct ft_border_style *style)
|
|
{
|
|
return FT_IS_SUCCESS(ft_set_border_style(table_, style));
|
|
}
|
|
|
|
/**
|
|
* Set current cell position.
|
|
*
|
|
* Current cell - cell that will be edited with all modifiing functions.
|
|
*
|
|
* @param row_i
|
|
* New row number for the current cell.
|
|
* @param col_i
|
|
* New row number for the current cell.
|
|
*/
|
|
void set_cur_cell(size_t row_i, size_t col_i)
|
|
{
|
|
ft_set_cur_cell(table_, row_i, col_i);
|
|
}
|
|
|
|
|
|
/**
|
|
* Set table left margin.
|
|
*
|
|
* @param value
|
|
* Left margin.
|
|
* @return
|
|
* - true: Success; table property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_left_margin(unsigned value)
|
|
{
|
|
return FT_IS_SUCCESS(ft_set_tbl_prop(table_, FT_TPROP_LEFT_MARGIN, value));
|
|
}
|
|
|
|
/**
|
|
* Set table top margin.
|
|
*
|
|
* @param value
|
|
* Top margin.
|
|
* @return
|
|
* - true: Success; table property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_top_margin(unsigned value)
|
|
{
|
|
return FT_IS_SUCCESS(ft_set_tbl_prop(table_, FT_TPROP_TOP_MARGIN, value));
|
|
}
|
|
|
|
/**
|
|
* Set table right margin.
|
|
*
|
|
* @param value
|
|
* Right margin.
|
|
* @return
|
|
* - true: Success; table property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_right_margin(unsigned value)
|
|
{
|
|
return FT_IS_SUCCESS(ft_set_tbl_prop(table_, FT_TPROP_RIGHT_MARGIN, value));
|
|
}
|
|
|
|
/**
|
|
* Set table bottom margin.
|
|
*
|
|
* @param value
|
|
* Bottom margin.
|
|
* @return
|
|
* - true: Success; table property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_bottom_margin(unsigned value)
|
|
{
|
|
return FT_IS_SUCCESS(ft_set_tbl_prop(table_, FT_TPROP_BOTTOM_MARGIN, value));
|
|
}
|
|
|
|
/**
|
|
* Set table adding strategy.
|
|
*
|
|
* @param value
|
|
* Adding strategy.
|
|
* @return
|
|
* - true: Success; table property was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_adding_strategy(fort::add_strategy value)
|
|
{
|
|
return FT_IS_SUCCESS(ft_set_tbl_prop(table_,
|
|
FT_TPROP_ADDING_STRATEGY,
|
|
static_cast<int>(value)));
|
|
}
|
|
private:
|
|
ft_table_t *table_;
|
|
mutable std::stringstream stream_;
|
|
friend class property_owner<table>;
|
|
|
|
|
|
public:
|
|
|
|
/* Iterators */
|
|
/* todo: implement chains like table[0][0] = table [0][1] = "somethings" */
|
|
|
|
/**
|
|
* Table cell.
|
|
*/
|
|
class table_cell: public property_owner_t
|
|
{
|
|
using property_owner_t::ps_coll_idx_;
|
|
using property_owner_t::ps_row_idx_;
|
|
using property_owner_t::ps_table_;
|
|
using property_owner_t::set_default_properties_;
|
|
public:
|
|
table_cell(std::size_t row_idx, std::size_t coll_idx, table &tbl)
|
|
: property_owner_t(row_idx, coll_idx, &tbl) {}
|
|
|
|
table_cell &operator=(const char *str)
|
|
{
|
|
ft_set_cur_cell(ps_table_->table_, ps_row_idx_, ps_coll_idx_);
|
|
ps_table_->write(str);
|
|
return *this;
|
|
}
|
|
|
|
table_cell &operator=(const std::string &str)
|
|
{
|
|
return operator=(str.c_str());
|
|
}
|
|
|
|
/**
|
|
* Set column span for the specified cell of the table.
|
|
*
|
|
* @param hor_span
|
|
* Column span.
|
|
* @return
|
|
* - true: Success; cell span was changed.
|
|
* - false: In case of error.
|
|
*/
|
|
bool set_cell_span(size_t hor_span)
|
|
{
|
|
if (set_default_properties_)
|
|
return false;
|
|
|
|
return FT_IS_SUCCESS(ft_set_cell_span(ps_table_->table_, ps_row_idx_, ps_coll_idx_, hor_span));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Table row.
|
|
*/
|
|
class table_row: public property_owner_t
|
|
{
|
|
using property_owner_t::ps_row_idx_;
|
|
using property_owner_t::ps_table_;
|
|
public:
|
|
table_row(std::size_t row_idx, table &tbl)
|
|
: property_owner_t(row_idx, FT_ANY_COLUMN, &tbl) {}
|
|
|
|
class table_cell
|
|
operator[](std::size_t coll_idx)
|
|
{
|
|
return table_cell(ps_row_idx_, coll_idx, *ps_table_);
|
|
}
|
|
|
|
void erase()
|
|
{
|
|
if (FT_IS_ERROR(ft_erase_range(ps_table_->table_,
|
|
property_owner_t::ps_row_idx_, 0,
|
|
property_owner_t::ps_row_idx_, FT_MAX_COL_INDEX))) {
|
|
throw std::runtime_error("Failed to erase row");
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Table column.
|
|
*/
|
|
class table_column: public property_owner_t
|
|
{
|
|
using property_owner_t::ps_coll_idx_;
|
|
using property_owner_t::ps_table_;
|
|
public:
|
|
table_column(std::size_t col_idx, table &tbl)
|
|
: property_owner_t(FT_ANY_ROW, col_idx, &tbl) {}
|
|
|
|
void erase()
|
|
{
|
|
if (FT_IS_ERROR(ft_erase_range(ps_table_->table_,
|
|
0, ps_coll_idx_,
|
|
FT_MAX_ROW_INDEX, ps_coll_idx_))) {
|
|
throw std::runtime_error("Failed to erase column");
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Range of cells.
|
|
*
|
|
* @note: at the moment function of propery owener will work only on the
|
|
* top left cell.
|
|
* @todo: Implement their work on the whole range.
|
|
*/
|
|
class cell_range: public property_owner_t
|
|
{
|
|
using property_owner_t::ps_coll_idx_;
|
|
using property_owner_t::ps_row_idx_;
|
|
using property_owner_t::ps_table_;
|
|
public:
|
|
cell_range(size_t top_left_row, size_t top_left_col,
|
|
size_t bottom_right_row, size_t bottom_right_col,
|
|
table &tbl)
|
|
: property_owner_t(top_left_row, top_left_col, &tbl),
|
|
bottom_right_row_(bottom_right_row),
|
|
bottom_right_col_(bottom_right_col)
|
|
{}
|
|
|
|
void erase()
|
|
{
|
|
if (FT_IS_ERROR(ft_erase_range(ps_table_->table_,
|
|
ps_row_idx_, ps_coll_idx_,
|
|
bottom_right_row_, bottom_right_col_))) {
|
|
throw std::runtime_error("Failed to erase column");
|
|
}
|
|
}
|
|
|
|
private:
|
|
std::size_t bottom_right_row_;
|
|
std::size_t bottom_right_col_;
|
|
};
|
|
|
|
|
|
class default_properties: public property_owner_t
|
|
{
|
|
public:
|
|
default_properties(table *tbl)
|
|
: property_owner_t(FT_ANY_ROW, FT_ANY_COLUMN, tbl, true) {}
|
|
};
|
|
|
|
class table_row
|
|
operator[](std::size_t row_idx)
|
|
{
|
|
return table_row(row_idx, *this);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get cell.
|
|
*
|
|
* @param row_idx
|
|
* Row index.
|
|
* @param col_idx
|
|
* Column index.
|
|
* @return
|
|
* table_cell object.
|
|
*/
|
|
class table_cell
|
|
cell(std::size_t row_idx, std::size_t col_idx)
|
|
{
|
|
return (*this)[row_idx][col_idx];
|
|
}
|
|
|
|
/**
|
|
* Get column number of the current cell.
|
|
*
|
|
* @return
|
|
* Column number of the current cell.
|
|
*/
|
|
size_t
|
|
cur_col() const noexcept
|
|
{
|
|
return ft_cur_col(table_);
|
|
}
|
|
|
|
/**
|
|
* Get row number of the current cell.
|
|
*
|
|
* @return
|
|
* Row number of the current cell.
|
|
*/
|
|
size_t
|
|
cur_row() const noexcept
|
|
{
|
|
return ft_cur_row(table_);
|
|
}
|
|
|
|
/**
|
|
* Check if table is empty.
|
|
*
|
|
* @return
|
|
* true - table is empty
|
|
* false - some data has been inserted
|
|
*/
|
|
bool
|
|
is_empty() const noexcept
|
|
{
|
|
return ft_is_empty(table_);
|
|
}
|
|
|
|
/**
|
|
* Get number of rows in the table.
|
|
*
|
|
* @return
|
|
* Number of rows in the table.
|
|
*/
|
|
std::size_t
|
|
row_count() const noexcept
|
|
{
|
|
return ft_row_count(table_);
|
|
}
|
|
|
|
/**
|
|
* Get current cell.
|
|
*
|
|
* @return
|
|
* Current cell.
|
|
*/
|
|
class table_cell
|
|
cur_cell()
|
|
{
|
|
return cell(cur_row(), cur_col());
|
|
}
|
|
|
|
/**
|
|
* Get row.
|
|
*
|
|
* @param row_idx
|
|
* Row index.
|
|
* @return
|
|
* table_row object.
|
|
*/
|
|
class table_row
|
|
row(std::size_t row_idx)
|
|
{
|
|
return table_row(row_idx, *this);
|
|
}
|
|
|
|
/**
|
|
* Get column.
|
|
*
|
|
* @param col_idx
|
|
* Column index.
|
|
* @return
|
|
* table_column object.
|
|
*/
|
|
class table_column
|
|
column(std::size_t col_idx)
|
|
{
|
|
return table_column(col_idx, *this);
|
|
}
|
|
|
|
/**
|
|
* Get range of cells.
|
|
*
|
|
* @param col_idx
|
|
* Column index.
|
|
* @return
|
|
* table_column object.
|
|
*/
|
|
class cell_range
|
|
range(std::size_t top_left_row, std::size_t top_left_col,
|
|
std::size_t bottom_right_row, std::size_t bottom_right_col)
|
|
{
|
|
return cell_range(top_left_row, top_left_col,
|
|
bottom_right_row, bottom_right_col,
|
|
*this);
|
|
}
|
|
|
|
static class default_properties
|
|
default_props()
|
|
{
|
|
return default_properties(NULL);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Formatted table containing common char content.
|
|
*
|
|
* Content of the table is treated as a string where each byte represesents a
|
|
* character. Should work for ascii characters. In case of usage of different
|
|
* international symbols it is recommended to use {@link utf8_table}.
|
|
*/
|
|
using char_table = table<table_type::character>;
|
|
|
|
#ifdef FT_HAVE_UTF8
|
|
/**
|
|
* Formatted table containing utf-8 content.
|
|
*/
|
|
using utf8_table = table<table_type::utf8>;
|
|
#endif
|
|
|
|
/**
|
|
* Set default border style for all new formatted tables.
|
|
*
|
|
* @param style
|
|
* Pointer to border style.
|
|
* @return
|
|
* - True: Success; table border style was changed.
|
|
* - False: Error
|
|
*/
|
|
inline bool set_default_border_style(struct ft_border_style *style)
|
|
{
|
|
return FT_IS_SUCCESS(ft_set_default_border_style(style));
|
|
}
|
|
|
|
|
|
} // namespace fort
|
|
|
|
#endif // LIBFORT_HPP
|