[A] Added adding_strategy
property to the tables
This commit is contained in:
parent
7d313ee078
commit
27e1102878
@ -3,6 +3,8 @@
|
|||||||
### API
|
### API
|
||||||
|
|
||||||
- Add functions to check if table is empty to the API.
|
- Add functions to check if table is empty to the API.
|
||||||
|
- `ft_ln` returns status of operation.
|
||||||
|
- Add new table property `adding_strategy` (2 strategies available - replace(default) and insert).
|
||||||
|
|
||||||
## v0.3.2
|
## v0.3.2
|
||||||
|
|
||||||
|
323
lib/fort.c
323
lib/fort.c
@ -311,6 +311,12 @@ size_t vector_capacity(const f_vector_t *);
|
|||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
int vector_push(f_vector_t *, const void *item);
|
int vector_push(f_vector_t *, const void *item);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
int vector_insert(f_vector_t *, const void *item, size_t pos);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_vector_t *vector_split(f_vector_t *, size_t pos);
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
const void *vector_at_c(const f_vector_t *vector, size_t index);
|
const void *vector_at_c(const f_vector_t *vector, size_t index);
|
||||||
|
|
||||||
@ -320,12 +326,15 @@ void *vector_at(f_vector_t *, size_t index);
|
|||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_status vector_swap(f_vector_t *cur_vec, f_vector_t *mv_vec, size_t pos);
|
f_status vector_swap(f_vector_t *cur_vec, f_vector_t *mv_vec, size_t pos);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
void vector_clear(f_vector_t *);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
int vector_erase(f_vector_t *, size_t index);
|
||||||
|
|
||||||
#ifdef FT_TEST_BUILD
|
#ifdef FT_TEST_BUILD
|
||||||
f_vector_t *copy_vector(f_vector_t *);
|
f_vector_t *copy_vector(f_vector_t *);
|
||||||
size_t vector_index_of(const f_vector_t *, const void *item);
|
size_t vector_index_of(const f_vector_t *, const void *item);
|
||||||
int vector_erase(f_vector_t *, size_t index);
|
|
||||||
void vector_clear(f_vector_t *);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* VECTOR_H */
|
#endif /* VECTOR_H */
|
||||||
@ -2020,6 +2029,7 @@ struct fort_entire_table_properties {
|
|||||||
unsigned int top_margin;
|
unsigned int top_margin;
|
||||||
unsigned int right_margin;
|
unsigned int right_margin;
|
||||||
unsigned int bottom_margin;
|
unsigned int bottom_margin;
|
||||||
|
enum ft_adding_strategy add_strategy;
|
||||||
};
|
};
|
||||||
typedef struct fort_entire_table_properties fort_entire_table_properties_t;
|
typedef struct fort_entire_table_properties fort_entire_table_properties_t;
|
||||||
extern fort_entire_table_properties_t g_entire_table_properties;
|
extern fort_entire_table_properties_t g_entire_table_properties;
|
||||||
@ -2134,6 +2144,9 @@ void destroy_row(f_row_t *row);
|
|||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_row_t *copy_row(f_row_t *row);
|
f_row_t *copy_row(f_row_t *row);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_row_t *split_row(f_row_t *row, size_t pos);
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_row_t *create_row_from_string(const char *str);
|
f_row_t *create_row_from_string(const char *str);
|
||||||
|
|
||||||
@ -2152,9 +2165,15 @@ const f_cell_t *get_cell_c(const f_row_t *row, size_t col);
|
|||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_cell_t *get_cell_and_create_if_not_exists(f_row_t *row, size_t col);
|
f_cell_t *get_cell_and_create_if_not_exists(f_row_t *row, size_t col);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_cell_t *create_cell_in_position(f_row_t *row, size_t col);
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos);
|
f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_status insert_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos);
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
size_t group_cell_number(const f_row_t *row, size_t master_cell_col);
|
size_t group_cell_number(const f_row_t *row, size_t master_cell_col);
|
||||||
|
|
||||||
@ -2611,7 +2630,14 @@ ft_table_t *ft_create_table(void)
|
|||||||
F_FREE(result);
|
F_FREE(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
result->properties = NULL;
|
|
||||||
|
result->properties = create_table_properties();
|
||||||
|
if (result->properties == NULL) {
|
||||||
|
destroy_vector(result->separators);
|
||||||
|
destroy_vector(result->rows);
|
||||||
|
F_FREE(result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
result->conv_buffer = NULL;
|
result->conv_buffer = NULL;
|
||||||
result->cur_row = 0;
|
result->cur_row = 0;
|
||||||
result->cur_col = 0;
|
result->cur_col = 0;
|
||||||
@ -2677,7 +2703,12 @@ ft_table_t *ft_copy_table(ft_table_t *table)
|
|||||||
vector_push(result->separators, &new_sep);
|
vector_push(result->separators, &new_sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* note: by default new table has allocated default properties, so we
|
||||||
|
* have to destroy them first.
|
||||||
|
*/
|
||||||
|
if (result->properties) {
|
||||||
|
destroy_table_properties(result->properties);
|
||||||
|
}
|
||||||
result->properties = copy_table_properties(table->properties);
|
result->properties = copy_table_properties(table->properties);
|
||||||
if (result->properties == NULL) {
|
if (result->properties == NULL) {
|
||||||
ft_destroy_table(result);
|
ft_destroy_table(result);
|
||||||
@ -2691,12 +2722,57 @@ ft_table_t *ft_copy_table(ft_table_t *table)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int split_cur_row(ft_table_t *table, f_row_t **tail_of_cur_row)
|
||||||
|
{
|
||||||
|
if (table->cur_row >= vector_size(table->rows)) {
|
||||||
|
tail_of_cur_row = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ft_ln(ft_table_t *table)
|
f_row_t *row = *(f_row_t **)vector_at(table->rows, table->cur_row);
|
||||||
|
if (table->cur_col >= columns_in_row(row)) {
|
||||||
|
tail_of_cur_row = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_row_t *tail = split_row(row, table->cur_col);
|
||||||
|
if (!tail) {
|
||||||
|
tail_of_cur_row = NULL;
|
||||||
|
return FT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*tail_of_cur_row = tail;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft_ln(ft_table_t *table)
|
||||||
{
|
{
|
||||||
assert(table);
|
assert(table);
|
||||||
|
fort_entire_table_properties_t *table_props = &table->properties->entire_table_properties;
|
||||||
|
switch (table_props->add_strategy) {
|
||||||
|
case FT_STRATEGY_INSERT: {
|
||||||
|
f_row_t *new_row = NULL;
|
||||||
|
if (FT_IS_ERROR(split_cur_row(table, &new_row))) {
|
||||||
|
return FT_ERROR;
|
||||||
|
}
|
||||||
|
if (new_row) {
|
||||||
|
if (FT_IS_ERROR(vector_insert(table->rows, &new_row, table->cur_row + 1))) {
|
||||||
|
destroy_row(new_row);
|
||||||
|
return FT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FT_STRATEGY_REPLACE:
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0 && "Unexpected situation inside libfort");
|
||||||
|
break;
|
||||||
|
}
|
||||||
table->cur_col = 0;
|
table->cur_col = 0;
|
||||||
table->cur_row++;
|
table->cur_row++;
|
||||||
|
return FT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ft_cur_row(const ft_table_t *table)
|
size_t ft_cur_row(const ft_table_t *table)
|
||||||
@ -2760,7 +2836,23 @@ static int ft_row_printf_impl_(ft_table_t *table, size_t row, const struct f_str
|
|||||||
|
|
||||||
new_cols = columns_in_row(new_row);
|
new_cols = columns_in_row(new_row);
|
||||||
cur_row_p = (f_row_t **)vector_at(table->rows, row);
|
cur_row_p = (f_row_t **)vector_at(table->rows, row);
|
||||||
swap_row(*cur_row_p, new_row, table->cur_col);
|
|
||||||
|
fort_entire_table_properties_t *table_props = &table->properties->entire_table_properties;
|
||||||
|
switch (table_props->add_strategy) {
|
||||||
|
case FT_STRATEGY_INSERT: {
|
||||||
|
if (FT_IS_ERROR(insert_row(*cur_row_p, new_row, table->cur_col)))
|
||||||
|
goto clear;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FT_STRATEGY_REPLACE: {
|
||||||
|
if (FT_IS_ERROR(swap_row(*cur_row_p, new_row, table->cur_col)))
|
||||||
|
goto clear;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(0 && "Unexpected situation inside libfort");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
table->cur_col += new_cols;
|
table->cur_col += new_cols;
|
||||||
destroy_row(new_row);
|
destroy_row(new_row);
|
||||||
@ -4920,6 +5012,7 @@ fort_entire_table_properties_t g_entire_table_properties = {
|
|||||||
0, /* top_margin */
|
0, /* top_margin */
|
||||||
0, /* right_margin */
|
0, /* right_margin */
|
||||||
0, /* bottom_margin */
|
0, /* bottom_margin */
|
||||||
|
FT_STRATEGY_REPLACE, /* add_strategy */
|
||||||
};
|
};
|
||||||
|
|
||||||
static f_status set_entire_table_property_internal(fort_entire_table_properties_t *properties, uint32_t property, int value)
|
static f_status set_entire_table_property_internal(fort_entire_table_properties_t *properties, uint32_t property, int value)
|
||||||
@ -4934,6 +5027,8 @@ static f_status set_entire_table_property_internal(fort_entire_table_properties_
|
|||||||
properties->right_margin = value;
|
properties->right_margin = value;
|
||||||
} else if (PROP_IS_SET(property, FT_TPROP_BOTTOM_MARGIN)) {
|
} else if (PROP_IS_SET(property, FT_TPROP_BOTTOM_MARGIN)) {
|
||||||
properties->bottom_margin = value;
|
properties->bottom_margin = value;
|
||||||
|
} else if (PROP_IS_SET(property, FT_TPROP_ADDING_STRATEGY)) {
|
||||||
|
properties->add_strategy = (enum ft_adding_strategy)value;
|
||||||
} else {
|
} else {
|
||||||
return FT_EINVAL;
|
return FT_EINVAL;
|
||||||
}
|
}
|
||||||
@ -4989,7 +5084,8 @@ f_table_properties_t g_table_properties = {
|
|||||||
0, /* left_margin */
|
0, /* left_margin */
|
||||||
0, /* top_margin */
|
0, /* top_margin */
|
||||||
0, /* right_margin */
|
0, /* right_margin */
|
||||||
0 /* bottom_margin */
|
0, /* bottom_margin */
|
||||||
|
FT_STRATEGY_REPLACE, /* add_strategy */
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5084,21 +5180,41 @@ struct f_row {
|
|||||||
f_vector_t *cells;
|
f_vector_t *cells;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static
|
||||||
FT_INTERNAL
|
f_row_t *create_row_impl(f_vector_t *cells)
|
||||||
f_row_t *create_row(void)
|
|
||||||
{
|
{
|
||||||
f_row_t *row = (f_row_t *)F_CALLOC(1, sizeof(f_row_t));
|
f_row_t *row = (f_row_t *)F_CALLOC(1, sizeof(f_row_t));
|
||||||
if (row == NULL)
|
if (row == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
row->cells = create_vector(sizeof(f_cell_t *), DEFAULT_VECTOR_CAPACITY);
|
if (cells) {
|
||||||
if (row->cells == NULL) {
|
row->cells = cells;
|
||||||
F_FREE(row);
|
} else {
|
||||||
return NULL;
|
row->cells = create_vector(sizeof(f_cell_t *), DEFAULT_VECTOR_CAPACITY);
|
||||||
|
if (row->cells == NULL) {
|
||||||
|
F_FREE(row);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_row_t *create_row(void)
|
||||||
|
{
|
||||||
|
return create_row_impl(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void destroy_each_cell(f_vector_t *cells)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
size_t cells_n = vector_size(cells);
|
||||||
|
for (i = 0; i < cells_n; ++i) {
|
||||||
|
f_cell_t *cell = *(f_cell_t **)vector_at(cells, i);
|
||||||
|
destroy_cell(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
void destroy_row(f_row_t *row)
|
void destroy_row(f_row_t *row)
|
||||||
{
|
{
|
||||||
@ -5106,12 +5222,7 @@ void destroy_row(f_row_t *row)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (row->cells) {
|
if (row->cells) {
|
||||||
size_t i = 0;
|
destroy_each_cell(row->cells);
|
||||||
size_t cells_n = vector_size(row->cells);
|
|
||||||
for (i = 0; i < cells_n; ++i) {
|
|
||||||
f_cell_t *cell = *(f_cell_t **)vector_at(row->cells, i);
|
|
||||||
destroy_cell(cell);
|
|
||||||
}
|
|
||||||
destroy_vector(row->cells);
|
destroy_vector(row->cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5141,6 +5252,23 @@ f_row_t *copy_row(f_row_t *row)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_row_t *split_row(f_row_t *row, size_t pos)
|
||||||
|
{
|
||||||
|
assert(row);
|
||||||
|
|
||||||
|
f_vector_t *cells = vector_split(row->cells, pos);
|
||||||
|
if (!cells)
|
||||||
|
return NULL;
|
||||||
|
f_row_t *tail = create_row_impl(cells);
|
||||||
|
if (!tail) {
|
||||||
|
destroy_each_cell(cells);
|
||||||
|
destroy_vector(cells);
|
||||||
|
}
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
size_t columns_in_row(const f_row_t *row)
|
size_t columns_in_row(const f_row_t *row)
|
||||||
{
|
{
|
||||||
@ -5202,6 +5330,23 @@ f_cell_t *get_cell_and_create_if_not_exists(f_row_t *row, size_t col)
|
|||||||
return get_cell_impl(row, col, CREATE_ON_NULL);
|
return get_cell_impl(row, col, CREATE_ON_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_cell_t *create_cell_in_position(f_row_t *row, size_t col)
|
||||||
|
{
|
||||||
|
if (row == NULL || row->cells == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_cell_t *new_cell = create_cell();
|
||||||
|
if (new_cell == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (FT_IS_ERROR(vector_insert(row->cells, &new_cell, col))) {
|
||||||
|
destroy_cell(new_cell);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return *(f_cell_t **)vector_at(row->cells, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos)
|
f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos)
|
||||||
@ -5220,6 +5365,37 @@ f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos)
|
|||||||
return vector_swap(cur_row->cells, ins_row->cells, pos);
|
return vector_swap(cur_row->cells, ins_row->cells, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ownership of cells of `ins_row` is passed to `cur_row`. */
|
||||||
|
FT_INTERNAL
|
||||||
|
f_status insert_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos)
|
||||||
|
{
|
||||||
|
assert(cur_row);
|
||||||
|
assert(ins_row);
|
||||||
|
|
||||||
|
while (vector_size(cur_row->cells) < pos) {
|
||||||
|
f_cell_t *new_cell = create_cell();
|
||||||
|
if (!new_cell)
|
||||||
|
return FT_ERROR;
|
||||||
|
vector_push(cur_row->cells, &new_cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t sz = vector_size(ins_row->cells);
|
||||||
|
size_t i = 0;
|
||||||
|
for (i = 0; i < sz; ++i) {
|
||||||
|
f_cell_t *cell = *(f_cell_t **)vector_at(ins_row->cells, i);
|
||||||
|
if (FT_IS_ERROR(vector_insert(cur_row->cells, &cell, pos + i))) {
|
||||||
|
/* clean up what we have inserted */
|
||||||
|
while (i--) {
|
||||||
|
vector_erase(cur_row->cells, pos);
|
||||||
|
}
|
||||||
|
return FT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Clear cells so that it will be safe to destroy this row */
|
||||||
|
vector_clear(ins_row->cells);
|
||||||
|
return FT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
size_t group_cell_number(const f_row_t *row, size_t master_cell_col)
|
size_t group_cell_number(const f_row_t *row, size_t master_cell_col)
|
||||||
@ -6672,7 +6848,6 @@ f_row_t *get_row_and_create_if_not_exists(ft_table_t *table, size_t row)
|
|||||||
return get_row_impl(table, row, CREATE_ON_NULL);
|
return get_row_impl(table, row, CREATE_ON_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_string_buffer_t *get_cur_str_buffer_and_create_if_not_exists(ft_table_t *table)
|
f_string_buffer_t *get_cur_str_buffer_and_create_if_not_exists(ft_table_t *table)
|
||||||
{
|
{
|
||||||
@ -6681,7 +6856,21 @@ f_string_buffer_t *get_cur_str_buffer_and_create_if_not_exists(ft_table_t *table
|
|||||||
f_row_t *row = get_row_and_create_if_not_exists(table, table->cur_row);
|
f_row_t *row = get_row_and_create_if_not_exists(table, table->cur_row);
|
||||||
if (row == NULL)
|
if (row == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
f_cell_t *cell = get_cell_and_create_if_not_exists(row, table->cur_col);
|
|
||||||
|
f_cell_t *cell = NULL;
|
||||||
|
fort_entire_table_properties_t *table_props = &table->properties->entire_table_properties;
|
||||||
|
switch (table_props->add_strategy) {
|
||||||
|
case FT_STRATEGY_INSERT:
|
||||||
|
cell = create_cell_in_position(row, table->cur_col);
|
||||||
|
break;
|
||||||
|
case FT_STRATEGY_REPLACE:
|
||||||
|
cell = get_cell_and_create_if_not_exists(row, table->cur_col);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0 && "Unexpected situation inside libfort");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (cell == NULL)
|
if (cell == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -6983,6 +7172,56 @@ int vector_push(f_vector_t *vector, const void *item)
|
|||||||
return FT_SUCCESS;
|
return FT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
int vector_insert(f_vector_t *vector, const void *item, size_t pos)
|
||||||
|
{
|
||||||
|
assert(vector);
|
||||||
|
assert(item);
|
||||||
|
size_t needed_capacity = MAX(pos + 1, vector->m_size + 1);
|
||||||
|
if (vector->m_capacity < needed_capacity) {
|
||||||
|
if (vector_reallocate_(vector, needed_capacity) == -1)
|
||||||
|
return FT_ERROR;
|
||||||
|
vector->m_capacity = needed_capacity;
|
||||||
|
}
|
||||||
|
size_t offset = pos * vector->m_item_size;
|
||||||
|
if (pos >= vector->m_size) {
|
||||||
|
/* Data in the middle are not initialized */
|
||||||
|
memcpy((char *)vector->m_data + offset, item, vector->m_item_size);
|
||||||
|
vector->m_size = pos + 1;
|
||||||
|
return FT_SUCCESS;
|
||||||
|
} else {
|
||||||
|
/* Shift following data by one position */
|
||||||
|
memmove((char *)vector->m_data + offset + vector->m_item_size,
|
||||||
|
(char *)vector->m_data + offset,
|
||||||
|
vector->m_item_size * (vector->m_size - pos));
|
||||||
|
memcpy((char *)vector->m_data + offset, item, vector->m_item_size);
|
||||||
|
++(vector->m_size);
|
||||||
|
return FT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_vector_t *vector_split(f_vector_t *vector, size_t pos)
|
||||||
|
{
|
||||||
|
size_t trailing_sz = vector->m_size > pos ? vector->m_size - pos : 0;
|
||||||
|
f_vector_t *new_vector = create_vector(vector->m_item_size, trailing_sz);
|
||||||
|
if (!new_vector)
|
||||||
|
return new_vector;
|
||||||
|
if (new_vector->m_capacity < trailing_sz) {
|
||||||
|
destroy_vector(new_vector);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trailing_sz == 0)
|
||||||
|
return new_vector;
|
||||||
|
|
||||||
|
size_t offset = vector->m_item_size * pos;
|
||||||
|
memcpy(new_vector->m_data, (char *)vector->m_data + offset,
|
||||||
|
trailing_sz * vector->m_item_size);
|
||||||
|
new_vector->m_size = trailing_sz;
|
||||||
|
vector->m_size = pos;
|
||||||
|
return new_vector;
|
||||||
|
}
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
const void *vector_at_c(const f_vector_t *vector, size_t index)
|
const void *vector_at_c(const f_vector_t *vector, size_t index)
|
||||||
@ -7058,6 +7297,26 @@ f_status vector_swap(f_vector_t *cur_vec, f_vector_t *mv_vec, size_t pos)
|
|||||||
return FT_SUCCESS;
|
return FT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
void vector_clear(f_vector_t *vector)
|
||||||
|
{
|
||||||
|
vector->m_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
int vector_erase(f_vector_t *vector, size_t index)
|
||||||
|
{
|
||||||
|
assert(vector);
|
||||||
|
|
||||||
|
if (vector->m_size == 0 || index >= vector->m_size)
|
||||||
|
return FT_ERROR;
|
||||||
|
|
||||||
|
memmove((char *)vector->m_data + vector->m_item_size * index,
|
||||||
|
(char *)vector->m_data + vector->m_item_size * (index + 1),
|
||||||
|
(vector->m_size - 1 - index) * vector->m_item_size);
|
||||||
|
vector->m_size--;
|
||||||
|
return FT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FT_TEST_BUILD
|
#ifdef FT_TEST_BUILD
|
||||||
|
|
||||||
@ -7091,26 +7350,6 @@ size_t vector_index_of(const f_vector_t *vector, const void *item)
|
|||||||
return INVALID_VEC_INDEX;
|
return INVALID_VEC_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int vector_erase(f_vector_t *vector, size_t index)
|
|
||||||
{
|
|
||||||
assert(vector);
|
|
||||||
|
|
||||||
if (vector->m_size == 0 || index >= vector->m_size)
|
|
||||||
return FT_ERROR;
|
|
||||||
|
|
||||||
memmove((char *)vector->m_data + vector->m_item_size * index,
|
|
||||||
(char *)vector->m_data + vector->m_item_size * (index + 1),
|
|
||||||
(vector->m_size - 1 - index) * vector->m_item_size);
|
|
||||||
vector->m_size--;
|
|
||||||
return FT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void vector_clear(f_vector_t *vector)
|
|
||||||
{
|
|
||||||
vector->m_size = 0;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
|
27
lib/fort.h
27
lib/fort.h
@ -275,8 +275,14 @@ ft_table_t *ft_copy_table(ft_table_t *table);
|
|||||||
*
|
*
|
||||||
* @param table
|
* @param table
|
||||||
* Pointer to formatted table.
|
* Pointer to formatted table.
|
||||||
|
* @return
|
||||||
|
* - 0: Success; data were written
|
||||||
|
* - (<0): In case of error.
|
||||||
|
* @note
|
||||||
|
* This function can fail only in case FT_STRATEGY_INSERT adding strategy
|
||||||
|
* was set for the table.
|
||||||
*/
|
*/
|
||||||
void ft_ln(ft_table_t *table);
|
int ft_ln(ft_table_t *table);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get row number of the current cell.
|
* Get row number of the current cell.
|
||||||
@ -812,12 +818,23 @@ int ft_set_cell_prop(ft_table_t *table, size_t row, size_t col, uint32_t propert
|
|||||||
* @name Table properties identifiers.
|
* @name Table properties identifiers.
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define FT_TPROP_LEFT_MARGIN (0x01U << 0)
|
#define FT_TPROP_LEFT_MARGIN (0x01U << 0)
|
||||||
#define FT_TPROP_TOP_MARGIN (0x01U << 1)
|
#define FT_TPROP_TOP_MARGIN (0x01U << 1)
|
||||||
#define FT_TPROP_RIGHT_MARGIN (0x01U << 2)
|
#define FT_TPROP_RIGHT_MARGIN (0x01U << 2)
|
||||||
#define FT_TPROP_BOTTOM_MARGIN (0x01U << 3)
|
#define FT_TPROP_BOTTOM_MARGIN (0x01U << 3)
|
||||||
|
#define FT_TPROP_ADDING_STRATEGY (0x01U << 4)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding strategy.
|
||||||
|
*
|
||||||
|
* Determines what happens with old content if current cell is not empty after
|
||||||
|
* adding data to it. Default strategy is FT_STRATEGY_REPLACE.
|
||||||
|
*/
|
||||||
|
enum ft_adding_strategy {
|
||||||
|
FT_STRATEGY_REPLACE = 0, /**< Replace old content. */
|
||||||
|
FT_STRATEGY_INSERT /**< Insert new conten. Old content is shifted. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
27
lib/fort.hpp
27
lib/fort.hpp
@ -60,6 +60,17 @@ enum class row_type {
|
|||||||
header = FT_ROW_HEADER
|
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.
|
* Colors.
|
||||||
*/
|
*/
|
||||||
@ -893,6 +904,22 @@ public:
|
|||||||
{
|
{
|
||||||
return FT_IS_SUCCESS(ft_set_tbl_prop(table_, FT_TPROP_BOTTOM_MARGIN, 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:
|
private:
|
||||||
ft_table_t *table_;
|
ft_table_t *table_;
|
||||||
mutable std::stringstream stream_;
|
mutable std::stringstream stream_;
|
||||||
|
27
src/fort.h
27
src/fort.h
@ -275,8 +275,14 @@ ft_table_t *ft_copy_table(ft_table_t *table);
|
|||||||
*
|
*
|
||||||
* @param table
|
* @param table
|
||||||
* Pointer to formatted table.
|
* Pointer to formatted table.
|
||||||
|
* @return
|
||||||
|
* - 0: Success; data were written
|
||||||
|
* - (<0): In case of error.
|
||||||
|
* @note
|
||||||
|
* This function can fail only in case FT_STRATEGY_INSERT adding strategy
|
||||||
|
* was set for the table.
|
||||||
*/
|
*/
|
||||||
void ft_ln(ft_table_t *table);
|
int ft_ln(ft_table_t *table);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get row number of the current cell.
|
* Get row number of the current cell.
|
||||||
@ -812,12 +818,23 @@ int ft_set_cell_prop(ft_table_t *table, size_t row, size_t col, uint32_t propert
|
|||||||
* @name Table properties identifiers.
|
* @name Table properties identifiers.
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define FT_TPROP_LEFT_MARGIN (0x01U << 0)
|
#define FT_TPROP_LEFT_MARGIN (0x01U << 0)
|
||||||
#define FT_TPROP_TOP_MARGIN (0x01U << 1)
|
#define FT_TPROP_TOP_MARGIN (0x01U << 1)
|
||||||
#define FT_TPROP_RIGHT_MARGIN (0x01U << 2)
|
#define FT_TPROP_RIGHT_MARGIN (0x01U << 2)
|
||||||
#define FT_TPROP_BOTTOM_MARGIN (0x01U << 3)
|
#define FT_TPROP_BOTTOM_MARGIN (0x01U << 3)
|
||||||
|
#define FT_TPROP_ADDING_STRATEGY (0x01U << 4)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding strategy.
|
||||||
|
*
|
||||||
|
* Determines what happens with old content if current cell is not empty after
|
||||||
|
* adding data to it. Default strategy is FT_STRATEGY_REPLACE.
|
||||||
|
*/
|
||||||
|
enum ft_adding_strategy {
|
||||||
|
FT_STRATEGY_REPLACE = 0, /**< Replace old content. */
|
||||||
|
FT_STRATEGY_INSERT /**< Insert new conten. Old content is shifted. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
27
src/fort.hpp
27
src/fort.hpp
@ -60,6 +60,17 @@ enum class row_type {
|
|||||||
header = FT_ROW_HEADER
|
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.
|
* Colors.
|
||||||
*/
|
*/
|
||||||
@ -893,6 +904,22 @@ public:
|
|||||||
{
|
{
|
||||||
return FT_IS_SUCCESS(ft_set_tbl_prop(table_, FT_TPROP_BOTTOM_MARGIN, 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:
|
private:
|
||||||
ft_table_t *table_;
|
ft_table_t *table_;
|
||||||
mutable std::stringstream stream_;
|
mutable std::stringstream stream_;
|
||||||
|
@ -57,7 +57,14 @@ ft_table_t *ft_create_table(void)
|
|||||||
F_FREE(result);
|
F_FREE(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
result->properties = NULL;
|
|
||||||
|
result->properties = create_table_properties();
|
||||||
|
if (result->properties == NULL) {
|
||||||
|
destroy_vector(result->separators);
|
||||||
|
destroy_vector(result->rows);
|
||||||
|
F_FREE(result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
result->conv_buffer = NULL;
|
result->conv_buffer = NULL;
|
||||||
result->cur_row = 0;
|
result->cur_row = 0;
|
||||||
result->cur_col = 0;
|
result->cur_col = 0;
|
||||||
@ -123,7 +130,12 @@ ft_table_t *ft_copy_table(ft_table_t *table)
|
|||||||
vector_push(result->separators, &new_sep);
|
vector_push(result->separators, &new_sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* note: by default new table has allocated default properties, so we
|
||||||
|
* have to destroy them first.
|
||||||
|
*/
|
||||||
|
if (result->properties) {
|
||||||
|
destroy_table_properties(result->properties);
|
||||||
|
}
|
||||||
result->properties = copy_table_properties(table->properties);
|
result->properties = copy_table_properties(table->properties);
|
||||||
if (result->properties == NULL) {
|
if (result->properties == NULL) {
|
||||||
ft_destroy_table(result);
|
ft_destroy_table(result);
|
||||||
@ -137,12 +149,57 @@ ft_table_t *ft_copy_table(ft_table_t *table)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int split_cur_row(ft_table_t *table, f_row_t **tail_of_cur_row)
|
||||||
|
{
|
||||||
|
if (table->cur_row >= vector_size(table->rows)) {
|
||||||
|
tail_of_cur_row = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ft_ln(ft_table_t *table)
|
f_row_t *row = *(f_row_t **)vector_at(table->rows, table->cur_row);
|
||||||
|
if (table->cur_col >= columns_in_row(row)) {
|
||||||
|
tail_of_cur_row = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_row_t *tail = split_row(row, table->cur_col);
|
||||||
|
if (!tail) {
|
||||||
|
tail_of_cur_row = NULL;
|
||||||
|
return FT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*tail_of_cur_row = tail;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft_ln(ft_table_t *table)
|
||||||
{
|
{
|
||||||
assert(table);
|
assert(table);
|
||||||
|
fort_entire_table_properties_t *table_props = &table->properties->entire_table_properties;
|
||||||
|
switch (table_props->add_strategy) {
|
||||||
|
case FT_STRATEGY_INSERT: {
|
||||||
|
f_row_t *new_row = NULL;
|
||||||
|
if (FT_IS_ERROR(split_cur_row(table, &new_row))) {
|
||||||
|
return FT_ERROR;
|
||||||
|
}
|
||||||
|
if (new_row) {
|
||||||
|
if (FT_IS_ERROR(vector_insert(table->rows, &new_row, table->cur_row + 1))) {
|
||||||
|
destroy_row(new_row);
|
||||||
|
return FT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FT_STRATEGY_REPLACE:
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0 && "Unexpected situation inside libfort");
|
||||||
|
break;
|
||||||
|
}
|
||||||
table->cur_col = 0;
|
table->cur_col = 0;
|
||||||
table->cur_row++;
|
table->cur_row++;
|
||||||
|
return FT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ft_cur_row(const ft_table_t *table)
|
size_t ft_cur_row(const ft_table_t *table)
|
||||||
@ -206,7 +263,23 @@ static int ft_row_printf_impl_(ft_table_t *table, size_t row, const struct f_str
|
|||||||
|
|
||||||
new_cols = columns_in_row(new_row);
|
new_cols = columns_in_row(new_row);
|
||||||
cur_row_p = (f_row_t **)vector_at(table->rows, row);
|
cur_row_p = (f_row_t **)vector_at(table->rows, row);
|
||||||
swap_row(*cur_row_p, new_row, table->cur_col);
|
|
||||||
|
fort_entire_table_properties_t *table_props = &table->properties->entire_table_properties;
|
||||||
|
switch (table_props->add_strategy) {
|
||||||
|
case FT_STRATEGY_INSERT: {
|
||||||
|
if (FT_IS_ERROR(insert_row(*cur_row_p, new_row, table->cur_col)))
|
||||||
|
goto clear;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FT_STRATEGY_REPLACE: {
|
||||||
|
if (FT_IS_ERROR(swap_row(*cur_row_p, new_row, table->cur_col)))
|
||||||
|
goto clear;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(0 && "Unexpected situation inside libfort");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
table->cur_col += new_cols;
|
table->cur_col += new_cols;
|
||||||
destroy_row(new_row);
|
destroy_row(new_row);
|
||||||
|
@ -874,6 +874,7 @@ fort_entire_table_properties_t g_entire_table_properties = {
|
|||||||
0, /* top_margin */
|
0, /* top_margin */
|
||||||
0, /* right_margin */
|
0, /* right_margin */
|
||||||
0, /* bottom_margin */
|
0, /* bottom_margin */
|
||||||
|
FT_STRATEGY_REPLACE, /* add_strategy */
|
||||||
};
|
};
|
||||||
|
|
||||||
static f_status set_entire_table_property_internal(fort_entire_table_properties_t *properties, uint32_t property, int value)
|
static f_status set_entire_table_property_internal(fort_entire_table_properties_t *properties, uint32_t property, int value)
|
||||||
@ -888,6 +889,8 @@ static f_status set_entire_table_property_internal(fort_entire_table_properties_
|
|||||||
properties->right_margin = value;
|
properties->right_margin = value;
|
||||||
} else if (PROP_IS_SET(property, FT_TPROP_BOTTOM_MARGIN)) {
|
} else if (PROP_IS_SET(property, FT_TPROP_BOTTOM_MARGIN)) {
|
||||||
properties->bottom_margin = value;
|
properties->bottom_margin = value;
|
||||||
|
} else if (PROP_IS_SET(property, FT_TPROP_ADDING_STRATEGY)) {
|
||||||
|
properties->add_strategy = (enum ft_adding_strategy)value;
|
||||||
} else {
|
} else {
|
||||||
return FT_EINVAL;
|
return FT_EINVAL;
|
||||||
}
|
}
|
||||||
@ -943,7 +946,8 @@ f_table_properties_t g_table_properties = {
|
|||||||
0, /* left_margin */
|
0, /* left_margin */
|
||||||
0, /* top_margin */
|
0, /* top_margin */
|
||||||
0, /* right_margin */
|
0, /* right_margin */
|
||||||
0 /* bottom_margin */
|
0, /* bottom_margin */
|
||||||
|
FT_STRATEGY_REPLACE, /* add_strategy */
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -177,6 +177,7 @@ struct fort_entire_table_properties {
|
|||||||
unsigned int top_margin;
|
unsigned int top_margin;
|
||||||
unsigned int right_margin;
|
unsigned int right_margin;
|
||||||
unsigned int bottom_margin;
|
unsigned int bottom_margin;
|
||||||
|
enum ft_adding_strategy add_strategy;
|
||||||
};
|
};
|
||||||
typedef struct fort_entire_table_properties fort_entire_table_properties_t;
|
typedef struct fort_entire_table_properties fort_entire_table_properties_t;
|
||||||
extern fort_entire_table_properties_t g_entire_table_properties;
|
extern fort_entire_table_properties_t g_entire_table_properties;
|
||||||
|
106
src/row.c
106
src/row.c
@ -10,21 +10,41 @@ struct f_row {
|
|||||||
f_vector_t *cells;
|
f_vector_t *cells;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static
|
||||||
FT_INTERNAL
|
f_row_t *create_row_impl(f_vector_t *cells)
|
||||||
f_row_t *create_row(void)
|
|
||||||
{
|
{
|
||||||
f_row_t *row = (f_row_t *)F_CALLOC(1, sizeof(f_row_t));
|
f_row_t *row = (f_row_t *)F_CALLOC(1, sizeof(f_row_t));
|
||||||
if (row == NULL)
|
if (row == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
row->cells = create_vector(sizeof(f_cell_t *), DEFAULT_VECTOR_CAPACITY);
|
if (cells) {
|
||||||
if (row->cells == NULL) {
|
row->cells = cells;
|
||||||
F_FREE(row);
|
} else {
|
||||||
return NULL;
|
row->cells = create_vector(sizeof(f_cell_t *), DEFAULT_VECTOR_CAPACITY);
|
||||||
|
if (row->cells == NULL) {
|
||||||
|
F_FREE(row);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_row_t *create_row(void)
|
||||||
|
{
|
||||||
|
return create_row_impl(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void destroy_each_cell(f_vector_t *cells)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
size_t cells_n = vector_size(cells);
|
||||||
|
for (i = 0; i < cells_n; ++i) {
|
||||||
|
f_cell_t *cell = *(f_cell_t **)vector_at(cells, i);
|
||||||
|
destroy_cell(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
void destroy_row(f_row_t *row)
|
void destroy_row(f_row_t *row)
|
||||||
{
|
{
|
||||||
@ -32,12 +52,7 @@ void destroy_row(f_row_t *row)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (row->cells) {
|
if (row->cells) {
|
||||||
size_t i = 0;
|
destroy_each_cell(row->cells);
|
||||||
size_t cells_n = vector_size(row->cells);
|
|
||||||
for (i = 0; i < cells_n; ++i) {
|
|
||||||
f_cell_t *cell = *(f_cell_t **)vector_at(row->cells, i);
|
|
||||||
destroy_cell(cell);
|
|
||||||
}
|
|
||||||
destroy_vector(row->cells);
|
destroy_vector(row->cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +82,23 @@ f_row_t *copy_row(f_row_t *row)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_row_t *split_row(f_row_t *row, size_t pos)
|
||||||
|
{
|
||||||
|
assert(row);
|
||||||
|
|
||||||
|
f_vector_t *cells = vector_split(row->cells, pos);
|
||||||
|
if (!cells)
|
||||||
|
return NULL;
|
||||||
|
f_row_t *tail = create_row_impl(cells);
|
||||||
|
if (!tail) {
|
||||||
|
destroy_each_cell(cells);
|
||||||
|
destroy_vector(cells);
|
||||||
|
}
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
size_t columns_in_row(const f_row_t *row)
|
size_t columns_in_row(const f_row_t *row)
|
||||||
{
|
{
|
||||||
@ -128,6 +160,23 @@ f_cell_t *get_cell_and_create_if_not_exists(f_row_t *row, size_t col)
|
|||||||
return get_cell_impl(row, col, CREATE_ON_NULL);
|
return get_cell_impl(row, col, CREATE_ON_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_cell_t *create_cell_in_position(f_row_t *row, size_t col)
|
||||||
|
{
|
||||||
|
if (row == NULL || row->cells == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_cell_t *new_cell = create_cell();
|
||||||
|
if (new_cell == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (FT_IS_ERROR(vector_insert(row->cells, &new_cell, col))) {
|
||||||
|
destroy_cell(new_cell);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return *(f_cell_t **)vector_at(row->cells, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos)
|
f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos)
|
||||||
@ -146,6 +195,37 @@ f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos)
|
|||||||
return vector_swap(cur_row->cells, ins_row->cells, pos);
|
return vector_swap(cur_row->cells, ins_row->cells, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ownership of cells of `ins_row` is passed to `cur_row`. */
|
||||||
|
FT_INTERNAL
|
||||||
|
f_status insert_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos)
|
||||||
|
{
|
||||||
|
assert(cur_row);
|
||||||
|
assert(ins_row);
|
||||||
|
|
||||||
|
while (vector_size(cur_row->cells) < pos) {
|
||||||
|
f_cell_t *new_cell = create_cell();
|
||||||
|
if (!new_cell)
|
||||||
|
return FT_ERROR;
|
||||||
|
vector_push(cur_row->cells, &new_cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t sz = vector_size(ins_row->cells);
|
||||||
|
size_t i = 0;
|
||||||
|
for (i = 0; i < sz; ++i) {
|
||||||
|
f_cell_t *cell = *(f_cell_t **)vector_at(ins_row->cells, i);
|
||||||
|
if (FT_IS_ERROR(vector_insert(cur_row->cells, &cell, pos + i))) {
|
||||||
|
/* clean up what we have inserted */
|
||||||
|
while (i--) {
|
||||||
|
vector_erase(cur_row->cells, pos);
|
||||||
|
}
|
||||||
|
return FT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Clear cells so that it will be safe to destroy this row */
|
||||||
|
vector_clear(ins_row->cells);
|
||||||
|
return FT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
size_t group_cell_number(const f_row_t *row, size_t master_cell_col)
|
size_t group_cell_number(const f_row_t *row, size_t master_cell_col)
|
||||||
|
@ -18,6 +18,9 @@ void destroy_row(f_row_t *row);
|
|||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_row_t *copy_row(f_row_t *row);
|
f_row_t *copy_row(f_row_t *row);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_row_t *split_row(f_row_t *row, size_t pos);
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_row_t *create_row_from_string(const char *str);
|
f_row_t *create_row_from_string(const char *str);
|
||||||
|
|
||||||
@ -36,9 +39,15 @@ const f_cell_t *get_cell_c(const f_row_t *row, size_t col);
|
|||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_cell_t *get_cell_and_create_if_not_exists(f_row_t *row, size_t col);
|
f_cell_t *get_cell_and_create_if_not_exists(f_row_t *row, size_t col);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_cell_t *create_cell_in_position(f_row_t *row, size_t col);
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos);
|
f_status swap_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_status insert_row(f_row_t *cur_row, f_row_t *ins_row, size_t pos);
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
size_t group_cell_number(const f_row_t *row, size_t master_cell_col);
|
size_t group_cell_number(const f_row_t *row, size_t master_cell_col);
|
||||||
|
|
||||||
|
17
src/table.c
17
src/table.c
@ -81,7 +81,6 @@ f_row_t *get_row_and_create_if_not_exists(ft_table_t *table, size_t row)
|
|||||||
return get_row_impl(table, row, CREATE_ON_NULL);
|
return get_row_impl(table, row, CREATE_ON_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_string_buffer_t *get_cur_str_buffer_and_create_if_not_exists(ft_table_t *table)
|
f_string_buffer_t *get_cur_str_buffer_and_create_if_not_exists(ft_table_t *table)
|
||||||
{
|
{
|
||||||
@ -90,7 +89,21 @@ f_string_buffer_t *get_cur_str_buffer_and_create_if_not_exists(ft_table_t *table
|
|||||||
f_row_t *row = get_row_and_create_if_not_exists(table, table->cur_row);
|
f_row_t *row = get_row_and_create_if_not_exists(table, table->cur_row);
|
||||||
if (row == NULL)
|
if (row == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
f_cell_t *cell = get_cell_and_create_if_not_exists(row, table->cur_col);
|
|
||||||
|
f_cell_t *cell = NULL;
|
||||||
|
fort_entire_table_properties_t *table_props = &table->properties->entire_table_properties;
|
||||||
|
switch (table_props->add_strategy) {
|
||||||
|
case FT_STRATEGY_INSERT:
|
||||||
|
cell = create_cell_in_position(row, table->cur_col);
|
||||||
|
break;
|
||||||
|
case FT_STRATEGY_REPLACE:
|
||||||
|
cell = get_cell_and_create_if_not_exists(row, table->cur_col);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0 && "Unexpected situation inside libfort");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (cell == NULL)
|
if (cell == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
90
src/vector.c
90
src/vector.c
@ -91,6 +91,56 @@ int vector_push(f_vector_t *vector, const void *item)
|
|||||||
return FT_SUCCESS;
|
return FT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
int vector_insert(f_vector_t *vector, const void *item, size_t pos)
|
||||||
|
{
|
||||||
|
assert(vector);
|
||||||
|
assert(item);
|
||||||
|
size_t needed_capacity = MAX(pos + 1, vector->m_size + 1);
|
||||||
|
if (vector->m_capacity < needed_capacity) {
|
||||||
|
if (vector_reallocate_(vector, needed_capacity) == -1)
|
||||||
|
return FT_ERROR;
|
||||||
|
vector->m_capacity = needed_capacity;
|
||||||
|
}
|
||||||
|
size_t offset = pos * vector->m_item_size;
|
||||||
|
if (pos >= vector->m_size) {
|
||||||
|
/* Data in the middle are not initialized */
|
||||||
|
memcpy((char *)vector->m_data + offset, item, vector->m_item_size);
|
||||||
|
vector->m_size = pos + 1;
|
||||||
|
return FT_SUCCESS;
|
||||||
|
} else {
|
||||||
|
/* Shift following data by one position */
|
||||||
|
memmove((char *)vector->m_data + offset + vector->m_item_size,
|
||||||
|
(char *)vector->m_data + offset,
|
||||||
|
vector->m_item_size * (vector->m_size - pos));
|
||||||
|
memcpy((char *)vector->m_data + offset, item, vector->m_item_size);
|
||||||
|
++(vector->m_size);
|
||||||
|
return FT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_vector_t *vector_split(f_vector_t *vector, size_t pos)
|
||||||
|
{
|
||||||
|
size_t trailing_sz = vector->m_size > pos ? vector->m_size - pos : 0;
|
||||||
|
f_vector_t *new_vector = create_vector(vector->m_item_size, trailing_sz);
|
||||||
|
if (!new_vector)
|
||||||
|
return new_vector;
|
||||||
|
if (new_vector->m_capacity < trailing_sz) {
|
||||||
|
destroy_vector(new_vector);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trailing_sz == 0)
|
||||||
|
return new_vector;
|
||||||
|
|
||||||
|
size_t offset = vector->m_item_size * pos;
|
||||||
|
memcpy(new_vector->m_data, (char *)vector->m_data + offset,
|
||||||
|
trailing_sz * vector->m_item_size);
|
||||||
|
new_vector->m_size = trailing_sz;
|
||||||
|
vector->m_size = pos;
|
||||||
|
return new_vector;
|
||||||
|
}
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
const void *vector_at_c(const f_vector_t *vector, size_t index)
|
const void *vector_at_c(const f_vector_t *vector, size_t index)
|
||||||
@ -166,6 +216,26 @@ f_status vector_swap(f_vector_t *cur_vec, f_vector_t *mv_vec, size_t pos)
|
|||||||
return FT_SUCCESS;
|
return FT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
void vector_clear(f_vector_t *vector)
|
||||||
|
{
|
||||||
|
vector->m_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
int vector_erase(f_vector_t *vector, size_t index)
|
||||||
|
{
|
||||||
|
assert(vector);
|
||||||
|
|
||||||
|
if (vector->m_size == 0 || index >= vector->m_size)
|
||||||
|
return FT_ERROR;
|
||||||
|
|
||||||
|
memmove((char *)vector->m_data + vector->m_item_size * index,
|
||||||
|
(char *)vector->m_data + vector->m_item_size * (index + 1),
|
||||||
|
(vector->m_size - 1 - index) * vector->m_item_size);
|
||||||
|
vector->m_size--;
|
||||||
|
return FT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FT_TEST_BUILD
|
#ifdef FT_TEST_BUILD
|
||||||
|
|
||||||
@ -199,24 +269,4 @@ size_t vector_index_of(const f_vector_t *vector, const void *item)
|
|||||||
return INVALID_VEC_INDEX;
|
return INVALID_VEC_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int vector_erase(f_vector_t *vector, size_t index)
|
|
||||||
{
|
|
||||||
assert(vector);
|
|
||||||
|
|
||||||
if (vector->m_size == 0 || index >= vector->m_size)
|
|
||||||
return FT_ERROR;
|
|
||||||
|
|
||||||
memmove((char *)vector->m_data + vector->m_item_size * index,
|
|
||||||
(char *)vector->m_data + vector->m_item_size * (index + 1),
|
|
||||||
(vector->m_size - 1 - index) * vector->m_item_size);
|
|
||||||
vector->m_size--;
|
|
||||||
return FT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void vector_clear(f_vector_t *vector)
|
|
||||||
{
|
|
||||||
vector->m_size = 0;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
13
src/vector.h
13
src/vector.h
@ -21,6 +21,12 @@ size_t vector_capacity(const f_vector_t *);
|
|||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
int vector_push(f_vector_t *, const void *item);
|
int vector_push(f_vector_t *, const void *item);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
int vector_insert(f_vector_t *, const void *item, size_t pos);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
f_vector_t *vector_split(f_vector_t *, size_t pos);
|
||||||
|
|
||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
const void *vector_at_c(const f_vector_t *vector, size_t index);
|
const void *vector_at_c(const f_vector_t *vector, size_t index);
|
||||||
|
|
||||||
@ -30,12 +36,15 @@ void *vector_at(f_vector_t *, size_t index);
|
|||||||
FT_INTERNAL
|
FT_INTERNAL
|
||||||
f_status vector_swap(f_vector_t *cur_vec, f_vector_t *mv_vec, size_t pos);
|
f_status vector_swap(f_vector_t *cur_vec, f_vector_t *mv_vec, size_t pos);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
void vector_clear(f_vector_t *);
|
||||||
|
|
||||||
|
FT_INTERNAL
|
||||||
|
int vector_erase(f_vector_t *, size_t index);
|
||||||
|
|
||||||
#ifdef FT_TEST_BUILD
|
#ifdef FT_TEST_BUILD
|
||||||
f_vector_t *copy_vector(f_vector_t *);
|
f_vector_t *copy_vector(f_vector_t *);
|
||||||
size_t vector_index_of(const f_vector_t *, const void *item);
|
size_t vector_index_of(const f_vector_t *, const void *item);
|
||||||
int vector_erase(f_vector_t *, size_t index);
|
|
||||||
void vector_clear(f_vector_t *);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* VECTOR_H */
|
#endif /* VECTOR_H */
|
||||||
|
@ -1608,8 +1608,95 @@ void test_table_write(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SCENARIO("Test write and printf functions simultaneously") {
|
||||||
|
table = ft_create_table();
|
||||||
|
assert_true(table != NULL);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_write(table, "0", "1")));
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_printf(table, "2|3")));
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_write(table, "5", "6")));
|
||||||
|
|
||||||
|
const char *table_str = ft_to_string(table);
|
||||||
|
assert_true(table_str != NULL);
|
||||||
|
const char *table_str_etalon =
|
||||||
|
"+---+---+---+---+---+---+\n"
|
||||||
|
"| 0 | 1 | 2 | 3 | 5 | 6 |\n"
|
||||||
|
"+---+---+---+---+---+---+\n";
|
||||||
|
assert_str_equal(table_str, table_str_etalon);
|
||||||
|
|
||||||
|
ft_destroy_table(table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_table_insert_strategy(void)
|
||||||
|
{
|
||||||
|
SCENARIO("Test ft_ln") {
|
||||||
|
ft_table_t *table = ft_create_table();
|
||||||
|
assert_true(table != NULL);
|
||||||
|
ft_set_tbl_prop(table, FT_TPROP_ADDING_STRATEGY, FT_STRATEGY_INSERT);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_write_ln(table, "0", "1", "2")));
|
||||||
|
ft_set_cur_cell(table, 0, 2);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_ln(table)));
|
||||||
|
ft_set_cur_cell(table, 1, 1);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_write(table, "3")));
|
||||||
|
|
||||||
|
const char *table_str = ft_to_string(table);
|
||||||
|
assert_true(table_str != NULL);
|
||||||
|
const char *table_str_etalon =
|
||||||
|
"+---+---+\n"
|
||||||
|
"| 0 | 1 |\n"
|
||||||
|
"| 2 | 3 |\n"
|
||||||
|
"+---+---+\n";
|
||||||
|
assert_str_equal(table_str, table_str_etalon);
|
||||||
|
|
||||||
|
ft_destroy_table(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("Test write functions") {
|
||||||
|
ft_table_t *table = ft_create_table();
|
||||||
|
assert_true(table != NULL);
|
||||||
|
ft_set_tbl_prop(table, FT_TPROP_ADDING_STRATEGY, FT_STRATEGY_INSERT);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_write_ln(table, "0", "1", "2", "4", "5")));
|
||||||
|
ft_set_cur_cell(table, 0, 2);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_ln(table)));
|
||||||
|
ft_set_cur_cell(table, 1, 1);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_write_ln(table, "3")));
|
||||||
|
|
||||||
|
const char *table_str = ft_to_string(table);
|
||||||
|
assert_true(table_str != NULL);
|
||||||
|
const char *table_str_etalon =
|
||||||
|
"+---+---+\n"
|
||||||
|
"| 0 | 1 |\n"
|
||||||
|
"| 2 | 3 |\n"
|
||||||
|
"| 4 | 5 |\n"
|
||||||
|
"+---+---+\n";
|
||||||
|
assert_str_equal(table_str, table_str_etalon);
|
||||||
|
|
||||||
|
ft_destroy_table(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("Test printf functions") {
|
||||||
|
ft_table_t *table = ft_create_table();
|
||||||
|
assert_true(table != NULL);
|
||||||
|
ft_set_tbl_prop(table, FT_TPROP_ADDING_STRATEGY, FT_STRATEGY_INSERT);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_write_ln(table, "0", "1", "2", "5", "6")));
|
||||||
|
ft_set_cur_cell(table, 0, 2);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_ln(table)));
|
||||||
|
ft_set_cur_cell(table, 1, 1);
|
||||||
|
assert_true(FT_IS_SUCCESS(ft_printf_ln(table, "3|4")));
|
||||||
|
|
||||||
|
const char *table_str = ft_to_string(table);
|
||||||
|
assert_true(table_str != NULL);
|
||||||
|
const char *table_str_etalon =
|
||||||
|
"+---+---+---+\n"
|
||||||
|
"| 0 | 1 | |\n"
|
||||||
|
"| 2 | 3 | 4 |\n"
|
||||||
|
"| 5 | 6 | |\n"
|
||||||
|
"+---+---+---+\n";
|
||||||
|
assert_str_equal(table_str, table_str_etalon);
|
||||||
|
|
||||||
|
ft_destroy_table(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void test_table_copy(void)
|
void test_table_copy(void)
|
||||||
{
|
{
|
||||||
|
@ -300,6 +300,52 @@ void test_cpp_table_write(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_cpp_table_insert(void)
|
||||||
|
{
|
||||||
|
SCENARIO("Test insert into beginning") {
|
||||||
|
fort::char_table table;
|
||||||
|
table.set_adding_strategy(fort::add_strategy::insert);
|
||||||
|
table.set_border_style(FT_BOLD_STYLE);
|
||||||
|
table << "val1" << "val2" << fort::endr
|
||||||
|
<< "val3" << "val4" << fort::endr;
|
||||||
|
|
||||||
|
table.set_cur_cell(0, 0);
|
||||||
|
table << fort::header
|
||||||
|
<< "hdr1" << "hdr2" << fort::endr;
|
||||||
|
|
||||||
|
std::string table_str = table.to_string();
|
||||||
|
std::string table_str_etalon =
|
||||||
|
"┏━━━━━━┳━━━━━━┓\n"
|
||||||
|
"┃ hdr1 ┃ hdr2 ┃\n"
|
||||||
|
"┣━━━━━━╋━━━━━━┫\n"
|
||||||
|
"┃ val1 ┃ val2 ┃\n"
|
||||||
|
"┃ val3 ┃ val4 ┃\n"
|
||||||
|
"┗━━━━━━┻━━━━━━┛\n";
|
||||||
|
assert_string_equal(table_str, table_str_etalon);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("Test insert into the middle") {
|
||||||
|
fort::char_table table;
|
||||||
|
table.set_adding_strategy(fort::add_strategy::insert);
|
||||||
|
table.set_border_style(FT_BOLD_STYLE);
|
||||||
|
table << fort::header << "hdr1" << "hdr2" << fort::endr
|
||||||
|
<< "val1" << "val4" << fort::endr;
|
||||||
|
|
||||||
|
table.set_cur_cell(1, 1);
|
||||||
|
table << "val2" << fort::endr << "val3";
|
||||||
|
|
||||||
|
std::string table_str = table.to_string();
|
||||||
|
std::string table_str_etalon =
|
||||||
|
"┏━━━━━━┳━━━━━━┓\n"
|
||||||
|
"┃ hdr1 ┃ hdr2 ┃\n"
|
||||||
|
"┣━━━━━━╋━━━━━━┫\n"
|
||||||
|
"┃ val1 ┃ val2 ┃\n"
|
||||||
|
"┃ val3 ┃ val4 ┃\n"
|
||||||
|
"┗━━━━━━┻━━━━━━┛\n";
|
||||||
|
assert_string_equal(table_str, table_str_etalon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void test_cpp_table_changing_cell(void)
|
void test_cpp_table_changing_cell(void)
|
||||||
{
|
{
|
||||||
WHEN("All columns are equal and not empty") {
|
WHEN("All columns are equal and not empty") {
|
||||||
|
@ -16,6 +16,7 @@ void test_table_changing_cell(void);
|
|||||||
void test_wcs_table_boundaries(void);
|
void test_wcs_table_boundaries(void);
|
||||||
#endif
|
#endif
|
||||||
void test_table_write(void);
|
void test_table_write(void);
|
||||||
|
void test_table_insert_strategy(void);
|
||||||
void test_table_border_style(void);
|
void test_table_border_style(void);
|
||||||
void test_table_builtin_border_styles(void);
|
void test_table_builtin_border_styles(void);
|
||||||
void test_table_cell_properties(void);
|
void test_table_cell_properties(void);
|
||||||
@ -49,6 +50,7 @@ struct test_case bb_test_suite [] = {
|
|||||||
{"test_utf8_table", test_utf8_table},
|
{"test_utf8_table", test_utf8_table},
|
||||||
#endif
|
#endif
|
||||||
{"test_table_write", test_table_write},
|
{"test_table_write", test_table_write},
|
||||||
|
{"test_table_insert_strategy", test_table_insert_strategy},
|
||||||
{"test_table_changing_cell", test_table_changing_cell},
|
{"test_table_changing_cell", test_table_changing_cell},
|
||||||
{"test_table_border_style", test_table_border_style},
|
{"test_table_border_style", test_table_border_style},
|
||||||
{"test_table_builtin_border_styles", test_table_builtin_border_styles},
|
{"test_table_builtin_border_styles", test_table_builtin_border_styles},
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
/* Test cases */
|
/* Test cases */
|
||||||
void test_cpp_table_basic(void);
|
void test_cpp_table_basic(void);
|
||||||
void test_cpp_table_write(void);
|
void test_cpp_table_write(void);
|
||||||
|
void test_cpp_table_insert(void);
|
||||||
void test_cpp_table_changing_cell(void);
|
void test_cpp_table_changing_cell(void);
|
||||||
void test_cpp_table_tbl_properties(void);
|
void test_cpp_table_tbl_properties(void);
|
||||||
void test_cpp_table_cell_properties(void);
|
void test_cpp_table_cell_properties(void);
|
||||||
@ -15,6 +16,7 @@ void test_cpp_bug_fixes(void);
|
|||||||
struct test_case bb_test_suite [] = {
|
struct test_case bb_test_suite [] = {
|
||||||
{"test_cpp_table_basic", test_cpp_table_basic},
|
{"test_cpp_table_basic", test_cpp_table_basic},
|
||||||
{"test_cpp_table_write", test_cpp_table_write},
|
{"test_cpp_table_write", test_cpp_table_write},
|
||||||
|
{"test_cpp_table_insert", test_cpp_table_insert},
|
||||||
{"test_cpp_table_changing_cell", test_cpp_table_changing_cell},
|
{"test_cpp_table_changing_cell", test_cpp_table_changing_cell},
|
||||||
{"test_cpp_table_tbl_properties", test_cpp_table_tbl_properties},
|
{"test_cpp_table_tbl_properties", test_cpp_table_tbl_properties},
|
||||||
{"test_cpp_table_cell_properties", test_cpp_table_cell_properties},
|
{"test_cpp_table_cell_properties", test_cpp_table_cell_properties},
|
||||||
|
@ -87,6 +87,30 @@ void test_vector_basic(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WHEN("Testing insert method vector") {
|
||||||
|
vector_clear(vector);
|
||||||
|
|
||||||
|
size_t capacity = 10 * init_capacity;
|
||||||
|
for (i = 0; i < capacity; ++i) {
|
||||||
|
item_t item = (item_t)i;
|
||||||
|
vector_insert(vector, &item, 0);
|
||||||
|
}
|
||||||
|
assert_true(vector_size(vector) == capacity);
|
||||||
|
for (i = 0; i < capacity; ++i) {
|
||||||
|
assert_true(*(item_t *)vector_at(vector, i) == (item_t)(capacity - i) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
item_t item_666 = 666;
|
||||||
|
vector_insert(vector, &item_666, 5 * capacity - 1);
|
||||||
|
assert_true(vector_size(vector) == 5 * capacity);
|
||||||
|
assert_true(*(item_t *)vector_at(vector, 5 * capacity - 1) == item_666);
|
||||||
|
|
||||||
|
item_t item_777 = 777;
|
||||||
|
vector_insert(vector, &item_777, 10);
|
||||||
|
assert_true(vector_size(vector) == 5 * capacity + 1);
|
||||||
|
assert_true(*(item_t *)vector_at(vector, 10) == item_777);
|
||||||
|
}
|
||||||
|
|
||||||
WHEN("Moving from another vector") {
|
WHEN("Moving from another vector") {
|
||||||
vector_clear(vector);
|
vector_clear(vector);
|
||||||
for (i = 0; i < 10; ++i) {
|
for (i = 0; i < 10; ++i) {
|
||||||
|
Loading…
Reference in New Issue
Block a user