[A] Added hor separator

This commit is contained in:
seleznevae 2018-02-04 16:21:04 +03:00
parent 4d4635162b
commit 1741a8a169
9 changed files with 158 additions and 28 deletions

View File

@ -227,6 +227,7 @@ FORT_EXTERN int ft_table_write_ln(FTABLE *FORT_RESTRICT table, size_t rows, size
FORT_EXTERN int ft_add_separator(FTABLE *FORT_RESTRICT table);

View File

@ -58,6 +58,12 @@ FTABLE * ft_create_table(void)
F_FREE(result);
return NULL;
}
result->separators = create_vector(sizeof(separator_t*), DEFAULT_VECTOR_CAPACITY);
if (result->separators == NULL) {
destroy_vector(result->rows);
F_FREE(result);
return NULL;
}
result->options = NULL;
result->conv_buffer = NULL;
result->cur_row = 0;
@ -78,6 +84,13 @@ void ft_destroy_table(FTABLE *FORT_RESTRICT table)
}
destroy_vector(table->rows);
}
if (table->separators) {
size_t row_n = vector_size(table->separators);
for (size_t i = 0; i < row_n; ++i) {
destroy_separator(*(separator_t **)vector_at(table->separators, i));
}
destroy_vector(table->separators);
}
destroy_table_options(table->options);
destroy_string_buffer(table->conv_buffer);
F_FREE(table);
@ -509,15 +522,20 @@ const char* ft_to_string(const FTABLE *FORT_RESTRICT table)
context_t *context = (table->options ? table->options : &g_table_options);
fort_row_t *prev_row = NULL;
fort_row_t *cur_row = NULL;
for (size_t i = 0; i < rows; ++i) {
separator_t *cur_sep = NULL;
size_t sep_size = vector_size(table->separators);
size_t i = 0;
for (i = 0; i < rows; ++i) {
cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL;
cur_row = *(fort_row_t**)vector_at(table->rows, i);
enum HorSeparatorPos separatorPos = (i == 0) ? TopSeparator : InsideSeparator;
CHECK_RESULT_AND_MOVE_DEV(print_row_separator(buffer + dev, sz - dev, col_width_arr, cols, prev_row, cur_row, separatorPos, context));
CHECK_RESULT_AND_MOVE_DEV(print_row_separator(buffer + dev, sz - dev, col_width_arr, cols, prev_row, cur_row, separatorPos, cur_sep, context));
CHECK_RESULT_AND_MOVE_DEV(snprintf_row(cur_row, buffer + dev, sz - dev, col_width_arr, cols, row_height_arr[i], context));
prev_row = cur_row;
}
cur_row = NULL;
CHECK_RESULT_AND_MOVE_DEV(print_row_separator(buffer + dev, sz - dev, col_width_arr, cols, prev_row, cur_row, BottomSeparator, context));
cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL;
CHECK_RESULT_AND_MOVE_DEV(print_row_separator(buffer + dev, sz - dev, col_width_arr, cols, prev_row, cur_row, BottomSeparator, cur_sep, context));
F_FREE(col_width_arr);
@ -555,3 +573,28 @@ static int dummy_function()
int ft_add_separator(FTABLE *table)
{
assert(table);
assert(table->separators);
while(vector_size(table->separators) <= table->cur_row) {
separator_t *sep_p = create_separator(F_FALSE);
if (sep_p == NULL)
return F_MEMORY_ERROR;
int status = vector_push(table->separators, &sep_p);
if (IS_ERROR(status))
return status;
}
separator_t **sep_p = (separator_t **)vector_at(table->separators, table->cur_row);
if (*sep_p == NULL)
*sep_p = create_separator(F_TRUE);
else
(*sep_p)->enabled = F_TRUE;
if (*sep_p == NULL)
return F_ERROR;
return F_SUCCESS;
}

View File

@ -79,7 +79,10 @@ struct fort_row;
struct vector;
struct fort_cell;
struct string_buffer;
struct separator
{
int enabled;
};
typedef struct fort_table_options fort_table_options_t;
typedef fort_table_options_t context_t;
@ -89,7 +92,7 @@ typedef struct fort_cell fort_cell_t;
typedef struct string_buffer string_buffer_t;
typedef struct fort_row fort_row_t;
typedef struct fort_table FTABLE;
typedef struct separator separator_t;

View File

@ -77,6 +77,11 @@ fort_table_options_t g_table_options = {
'+', '-', '+', '+'
},
/* separator_chars */
{
'+', '=', '+', '+',
},
NULL, /* col_options */
};

View File

@ -75,6 +75,16 @@ enum BorderItemPos
};
enum SeparatorItemPos
{
LH_sip = 0,
IH_sip = 1,
II_sip = 2,
RH_sip = 3,
SepratorItemPosSize
};
struct fort_table_options
{
@ -86,6 +96,7 @@ struct fort_table_options
char border_chars[BorderItemPosSize];
char header_border_chars[BorderItemPosSize];
char separator_chars[SepratorItemPosSize];
vector_t *col_options;
};

View File

@ -110,7 +110,8 @@ fort_cell_t *get_cell_and_create_if_not_exists(fort_row_t *row, size_t col)
int print_row_separator(char *buffer, size_t buffer_sz,
const size_t *col_width_arr, size_t cols,
const fort_row_t *upper_row, const fort_row_t *lower_row,
enum HorSeparatorPos separatorPos, const context_t *context)
enum HorSeparatorPos separatorPos,
const separator_t *sep, const context_t *context)
{
#define CHECK_RESULT_AND_MOVE_DEV(statement) \
k = statement; \
@ -152,27 +153,34 @@ int print_row_separator(char *buffer, size_t buffer_sz,
border_chars = &context->border_chars;
}
switch (separatorPos) {
case TopSeparator:
L = &(*border_chars)[TL_bip];
I = &(*border_chars)[TT_bip];
IV = &(*border_chars)[TV_bip];
R = &(*border_chars)[TR_bip];
break;
case InsideSeparator:
L = &(*border_chars)[LH_bip];
I = &(*border_chars)[IH_bip];
IV = &(*border_chars)[II_bip];
R = &(*border_chars)[RH_bip];
break;
case BottomSeparator:
L = &(*border_chars)[BL_bip];
I = &(*border_chars)[BB_bip];
IV = &(*border_chars)[BV_bip];
R = &(*border_chars)[BR_bip];
break;
default:
break;
if (sep && sep->enabled) {
L = &(context->separator_chars[LH_sip]);
I = &(context->separator_chars[IH_sip]);
IV = &(context->separator_chars[II_sip]);
R = &(context->separator_chars[RH_sip]);
} else {
switch (separatorPos) {
case TopSeparator:
L = &(*border_chars)[TL_bip];
I = &(*border_chars)[TT_bip];
IV = &(*border_chars)[TV_bip];
R = &(*border_chars)[TR_bip];
break;
case InsideSeparator:
L = &(*border_chars)[LH_bip];
I = &(*border_chars)[IH_bip];
IV = &(*border_chars)[II_bip];
R = &(*border_chars)[RH_bip];
break;
case BottomSeparator:
L = &(*border_chars)[BL_bip];
I = &(*border_chars)[BB_bip];
IV = &(*border_chars)[BV_bip];
R = &(*border_chars)[BR_bip];
break;
default:
break;
}
}
/* If all chars are not printable, skip line separator */

View File

@ -33,7 +33,8 @@ fort_cell_t *get_cell_and_create_if_not_exists(fort_row_t *row, size_t col);
int print_row_separator(char *buffer, size_t buffer_sz,
const size_t *col_width_arr, size_t cols,
const fort_row_t *upper_row, const fort_row_t *lower_row,
enum HorSeparatorPos separatorPos, const context_t *context);
enum HorSeparatorPos separatorPos, const separator_t *sep,
const context_t *context);

View File

@ -3,6 +3,7 @@
#include "fort_impl.h"
#include "fort.h"
struct fort_table;
typedef struct fort_table fort_table_t;
struct fort_table
@ -12,8 +13,26 @@ struct fort_table
string_buffer_t *conv_buffer;
size_t cur_row;
size_t cur_col;
vector_t *separators;
};
static inline
separator_t *create_separator(int enabled)
{
separator_t *res = F_CALLOC(1, sizeof(separator_t));
if (res == NULL)
return NULL;
res->enabled = enabled;
return res;
}
static inline
void destroy_separator(separator_t *sep)
{
F_FREE(sep);
}
fort_status_t get_table_sizes(const FTABLE *table, size_t *rows, size_t *cols);
fort_row_t *get_row_implementation(fort_table_t *table, size_t row, enum PolicyOnNull policy);

View File

@ -33,6 +33,11 @@ fort_table_options_t test_table_opts = {
'+', '-', '+', '+'
},
/* separator_chars */
{
'+', '=', '+', '+',
},
NULL, /* col_options */
};
@ -347,6 +352,40 @@ void test_table_options(void **state)
ft_destroy_table(table);
}
WHEN("Separator testing") {
table = create_test_int_table(0);
ft_add_separator(table);
int n = ft_hdr_printf_ln(table, "%d|%d|%d|%d", 3, 4, 55, 67);
assert_true( n == 4 );
const char *table_str = ft_to_string(table);
assert_true( table_str != NULL );
const char *table_str_etalon =
"+---+---+----+----+\n"
"| | | | |\n"
"| 3 | 4 | 55 | 67 |\n"
"| | | | |\n"
"+---+---+----+----+\n"
"| | | | |\n"
"| 3 | 4 | 55 | 67 |\n"
"| | | | |\n"
"+---+---+----+----+\n"
"| | | | |\n"
"| 3 | 4 | 55 | 67 |\n"
"| | | | |\n"
"+===+===+====+====+\n"
"| | | | |\n"
"| 3 | 4 | 55 | 67 |\n"
"| | | | |\n"
"+---+---+----+----+\n";
// fprintf(stderr, "content:\n%s", table_str);
assert_true( strcmp(table_str, table_str_etalon) == 0);
ft_destroy_table(table);
}
WHEN("Top and bottom padding = 0") {
fort_table_options_t table_options;
memcpy(&table_options, &test_table_opts, sizeof(fort_table_options_t));