From 1741a8a169e2aa38a33a15f543d4c4d0cc4a4fc8 Mon Sep 17 00:00:00 2001 From: seleznevae Date: Sun, 4 Feb 2018 16:21:04 +0300 Subject: [PATCH] [A] Added hor separator --- include/fort.h | 1 + src/fort.c | 49 ++++++++++++++++++++++++++++++++++++++++--- src/fort_impl.h | 7 +++++-- src/options.c | 5 +++++ src/options.h | 11 ++++++++++ src/row.c | 52 ++++++++++++++++++++++++++-------------------- src/row.h | 3 ++- src/table.h | 19 +++++++++++++++++ tests/test_table.c | 39 ++++++++++++++++++++++++++++++++++ 9 files changed, 158 insertions(+), 28 deletions(-) diff --git a/include/fort.h b/include/fort.h index ba31b97..76304e5 100644 --- a/include/fort.h +++ b/include/fort.h @@ -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); diff --git a/src/fort.c b/src/fort.c index 5a61209..e8434d3 100644 --- a/src/fort.c +++ b/src/fort.c @@ -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; +} diff --git a/src/fort_impl.h b/src/fort_impl.h index cceaac3..41fbc09 100644 --- a/src/fort_impl.h +++ b/src/fort_impl.h @@ -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; diff --git a/src/options.c b/src/options.c index 7c5d5ca..ea1c8ec 100644 --- a/src/options.c +++ b/src/options.c @@ -77,6 +77,11 @@ fort_table_options_t g_table_options = { '+', '-', '+', '+' }, + /* separator_chars */ + { + '+', '=', '+', '+', + }, + NULL, /* col_options */ }; diff --git a/src/options.h b/src/options.h index b0e6e3c..973f2bc 100644 --- a/src/options.h +++ b/src/options.h @@ -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; }; diff --git a/src/row.c b/src/row.c index ca1ffe9..dd19fd5 100644 --- a/src/row.c +++ b/src/row.c @@ -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 */ diff --git a/src/row.h b/src/row.h index a35a0d6..a7762b7 100644 --- a/src/row.h +++ b/src/row.h @@ -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); diff --git a/src/table.h b/src/table.h index 1af922a..d1ff568 100644 --- a/src/table.h +++ b/src/table.h @@ -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); diff --git a/tests/test_table.c b/tests/test_table.c index 5df42bb..31746a2 100644 --- a/tests/test_table.c +++ b/tests/test_table.c @@ -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));