C
This commit is contained in:
parent
444b61e119
commit
033506e7a9
458
src/fort.c
458
src/fort.c
@ -49,6 +49,9 @@ typedef int fort_status_t;
|
|||||||
#define IS_SUCCESS(arg) ((arg) == F_SUCCESS)
|
#define IS_SUCCESS(arg) ((arg) == F_SUCCESS)
|
||||||
#define IS_ERROR(arg) (!IS_SUCCESS(arg))
|
#define IS_ERROR(arg) (!IS_SUCCESS(arg))
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* UTILITIES
|
||||||
|
* ***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -68,6 +71,33 @@ static void destroy_string_buffer(string_buffer_t *buffer);
|
|||||||
static fort_status_t realloc_string_buffer_without_copy(string_buffer_t *buffer);
|
static fort_status_t realloc_string_buffer_without_copy(string_buffer_t *buffer);
|
||||||
static fort_status_t fill_buffer_from_string(string_buffer_t *buffer, const char *str);
|
static fort_status_t fill_buffer_from_string(string_buffer_t *buffer, const char *str);
|
||||||
|
|
||||||
|
static size_t buffer_text_height(string_buffer_t *buffer)
|
||||||
|
{
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t buffer_text_width(string_buffer_t *buffer)
|
||||||
|
{
|
||||||
|
if (buffer == NULL || buffer->str == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return strlen(buffer->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int buffer_printf(string_buffer_t *buffer, size_t row, char *buf, size_t buf_len)
|
||||||
|
{
|
||||||
|
if (buffer == NULL || buffer->str == NULL
|
||||||
|
|| row >= buffer_text_height(buffer) || buf_len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return snprintf(buf, buf_len, "%*s", (int)(buf_len - 1), buffer->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* VECTOR
|
* VECTOR
|
||||||
* ***************************************************************************/
|
* ***************************************************************************/
|
||||||
@ -102,7 +132,7 @@ struct cell_options
|
|||||||
};
|
};
|
||||||
typedef struct cell_options cell_options_t;
|
typedef struct cell_options cell_options_t;
|
||||||
|
|
||||||
void init_cell_options(cell_options_t *options)
|
static void init_cell_options(cell_options_t *options)
|
||||||
{
|
{
|
||||||
assert(options);
|
assert(options);
|
||||||
options->padding_top = 1;
|
options->padding_top = 1;
|
||||||
@ -119,7 +149,7 @@ struct fort_cell
|
|||||||
cell_options_t options;
|
cell_options_t options;
|
||||||
};
|
};
|
||||||
|
|
||||||
fort_cell_t * create_cell()
|
static fort_cell_t * create_cell()
|
||||||
{
|
{
|
||||||
fort_cell_t *cell = F_CALLOC(sizeof(fort_cell_t), 1);
|
fort_cell_t *cell = F_CALLOC(sizeof(fort_cell_t), 1);
|
||||||
if (cell == NULL)
|
if (cell == NULL)
|
||||||
@ -133,7 +163,7 @@ fort_cell_t * create_cell()
|
|||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_cell(fort_cell_t *cell)
|
static void destroy_cell(fort_cell_t *cell)
|
||||||
{
|
{
|
||||||
if (cell == NULL)
|
if (cell == NULL)
|
||||||
return;
|
return;
|
||||||
@ -141,22 +171,22 @@ void destroy_cell(fort_cell_t *cell)
|
|||||||
F_FREE(cell);
|
F_FREE(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hint_width_cell(fort_cell_t *cell)
|
static int hint_width_cell(const fort_cell_t *cell)
|
||||||
{
|
{
|
||||||
assert(cell);
|
assert(cell);
|
||||||
int result = cell->options.padding_left + cell->options.padding_right;
|
int result = cell->options.padding_left + cell->options.padding_right;
|
||||||
if (cell->str_buffer && cell->str_buffer->str) {
|
if (cell->str_buffer && cell->str_buffer->str) {
|
||||||
result += strlen(cell->str_buffer->str);
|
result += buffer_text_width(cell->str_buffer);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hint_height_cell(fort_cell_t *cell)
|
static int hint_height_cell(const fort_cell_t *cell)
|
||||||
{
|
{
|
||||||
assert(cell);
|
assert(cell);
|
||||||
int result = cell->options.padding_top + cell->options.padding_bottom;
|
int result = cell->options.padding_top + cell->options.padding_bottom;
|
||||||
if (cell->str_buffer && cell->str_buffer->str) {
|
if (cell->str_buffer && cell->str_buffer->str) {
|
||||||
result += 1;
|
result += buffer_text_height(cell->str_buffer);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -166,7 +196,7 @@ int hint_height_cell(fort_cell_t *cell)
|
|||||||
* Returns number of lines in cell. If cell is empty or
|
* Returns number of lines in cell. If cell is empty or
|
||||||
* contains empty string, then 0 is returned.
|
* contains empty string, then 0 is returned.
|
||||||
*/
|
*/
|
||||||
int lines_number_cell(fort_cell_t *cell)
|
static int lines_number_cell(fort_cell_t *cell)
|
||||||
{
|
{
|
||||||
assert(cell);
|
assert(cell);
|
||||||
if (cell->str_buffer == NULL || cell->str_buffer->str == NULL || cell->str_buffer->str[0] == '\0') {
|
if (cell->str_buffer == NULL || cell->str_buffer->str == NULL || cell->str_buffer->str[0] == '\0') {
|
||||||
@ -182,6 +212,38 @@ int lines_number_cell(fort_cell_t *cell)
|
|||||||
return result + 1;
|
return result + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cell_printf(fort_cell_t *cell, size_t row, char *buf, size_t buf_len)
|
||||||
|
{
|
||||||
|
if (cell == NULL || buf_len == 0 || row >= hint_height_cell(cell)
|
||||||
|
|| (buf_len <= hint_width_cell(cell))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (row < cell->options.padding_top
|
||||||
|
|| row >= (cell->options.padding_top + buffer_text_height(cell->str_buffer))) {
|
||||||
|
for (int i = 0; i < (buf_len - 1); ++i) {
|
||||||
|
snprintf(buf, buf_len, "%c", ' ');
|
||||||
|
}
|
||||||
|
return buf_len - 1;
|
||||||
|
} else {
|
||||||
|
int written = 0;
|
||||||
|
int left = cell->options.padding_left;
|
||||||
|
|
||||||
|
for (int i = 0; i < left; ++i) {
|
||||||
|
written += snprintf(buf + written, buf_len - written, "%c", ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
written += buffer_printf(cell->str_buffer, row - cell->options.padding_top, buf + written, buf_len - written);
|
||||||
|
while (written < (buf_len - 1)) {
|
||||||
|
written += snprintf(buf + written, buf_len - written, "%c", ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* ROW
|
* ROW
|
||||||
* ***************************************************************************/
|
* ***************************************************************************/
|
||||||
@ -226,7 +288,7 @@ static void destroy_row(fort_row_t *row)
|
|||||||
static fort_row_t * create_row_from_string(const char *str);
|
static fort_row_t * create_row_from_string(const char *str);
|
||||||
static fort_row_t* create_row_from_fmt_string(const char* FORT_RESTRICT fmt, va_list *va_args);
|
static fort_row_t* create_row_from_fmt_string(const char* FORT_RESTRICT fmt, va_list *va_args);
|
||||||
|
|
||||||
int columns_in_row(const fort_row_t *row)
|
static int columns_in_row(const fort_row_t *row)
|
||||||
{
|
{
|
||||||
if (row == NULL || row->cells == NULL)
|
if (row == NULL || row->cells == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@ -234,21 +296,59 @@ int columns_in_row(const fort_row_t *row)
|
|||||||
return vector_size(row->cells);
|
return vector_size(row->cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fort_cell_t *get_cell(fort_row_t *row, size_t col)
|
||||||
|
{
|
||||||
|
if (row == NULL || row->cells == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (col < columns_in_row(row)) {
|
||||||
|
return vector_at(row->cells, col);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const fort_cell_t *get_cell_c(const fort_row_t *row, size_t col)
|
||||||
|
{
|
||||||
|
return get_cell((fort_row_t *)row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* TABLE
|
* TABLE
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
struct fort_table;
|
||||||
|
typedef struct fort_table fort_table_t;
|
||||||
struct fort_table
|
struct fort_table
|
||||||
{
|
{
|
||||||
fort_row_t *header;
|
|
||||||
vector_t *rows;
|
vector_t *rows;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static fort_status_t get_table_sizes(const FTABLE *table, size_t *rows, size_t *cols);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static fort_row_t *get_row(fort_table_t *table, size_t row)
|
||||||
|
{
|
||||||
|
if (table == NULL || table->rows == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t rows = vector_size(table->rows);
|
||||||
|
if (row < rows) {
|
||||||
|
return vector_at(table->rows, row);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const fort_row_t *get_row_c(const fort_table_t *table, size_t row)
|
||||||
|
{
|
||||||
|
return get_row((fort_table_t *)table, row);
|
||||||
|
}
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* LIBFORT helpers
|
* LIBFORT helpers
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
char *fort_strdup(const char* str)
|
static char *fort_strdup(const char* str)
|
||||||
{
|
{
|
||||||
if (str == NULL)
|
if (str == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -262,7 +362,7 @@ char *fort_strdup(const char* str)
|
|||||||
return str_copy;
|
return str_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t number_of_columns_in_format_string(const char *fmt)
|
static size_t number_of_columns_in_format_string(const char *fmt)
|
||||||
{
|
{
|
||||||
int separator_counter = 0;
|
int separator_counter = 0;
|
||||||
const char *pos = fmt;
|
const char *pos = fmt;
|
||||||
@ -301,7 +401,6 @@ void ft_destroy_table(FTABLE *FORT_RESTRICT table)
|
|||||||
if (table == NULL)
|
if (table == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
destroy_row(table->header);
|
|
||||||
if (table->rows) {
|
if (table->rows) {
|
||||||
size_t row_n = vector_size(table->rows);
|
size_t row_n = vector_size(table->rows);
|
||||||
for (size_t i = 0; i < row_n; ++i) {
|
for (size_t i = 0; i < row_n; ++i) {
|
||||||
@ -312,221 +411,15 @@ void ft_destroy_table(FTABLE *FORT_RESTRICT table)
|
|||||||
F_FREE(table);
|
F_FREE(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void forward_va_list(const char *fmt FORT_UNUSED, va_list *va)
|
|
||||||
//{
|
|
||||||
// /* todo - do normal implementation */
|
|
||||||
// va_arg(*va, int);
|
|
||||||
// va_arg(*va, int);
|
|
||||||
|
|
||||||
// while (*fmt) {
|
|
||||||
// if (*fmt != '%') {
|
|
||||||
// ++fmt;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// char argument_type[2] = { '\0', '\0'};
|
|
||||||
|
|
||||||
// check_format:
|
|
||||||
// ++fmt;
|
|
||||||
// /* todo: do normal checking for order of symbols. Don't think symbol checking can be in independent order. */
|
|
||||||
// switch(*fmt) {
|
|
||||||
// case '\0':
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// /* flags */
|
|
||||||
// case '-':
|
|
||||||
// case '+':
|
|
||||||
// case ' ':
|
|
||||||
// case '#':
|
|
||||||
// case '0':
|
|
||||||
// case '1':
|
|
||||||
// case '2':
|
|
||||||
// case '3':
|
|
||||||
// case '4':
|
|
||||||
// case '5':
|
|
||||||
// case '6':
|
|
||||||
// case '7':
|
|
||||||
// case '8':
|
|
||||||
// case '9':
|
|
||||||
// case '.':
|
|
||||||
// goto check_format;
|
|
||||||
|
|
||||||
|
|
||||||
// /* length modifiers */
|
|
||||||
// case 'h':
|
|
||||||
// case 'l':
|
|
||||||
// if (argument_type[0] == '\0')
|
|
||||||
// argument_type[0] = *fmt;
|
|
||||||
// else
|
|
||||||
// argument_type[1] = *fmt;
|
|
||||||
// goto check_format;
|
|
||||||
// case 'j':
|
|
||||||
// case 'z':
|
|
||||||
// case 't':
|
|
||||||
// case 'L':
|
|
||||||
// argument_type[1] = *fmt;
|
|
||||||
// goto check_format;
|
|
||||||
|
|
||||||
// /* specifiers */
|
|
||||||
// case 'c':
|
|
||||||
// if (argument_type[0] == 'l' && argument_type[0] == '\0')
|
|
||||||
// va_arg(*va, wint_t);
|
|
||||||
// else
|
|
||||||
// va_arg(*va, int);
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// /* specifiers */
|
|
||||||
// case 's':
|
|
||||||
// if (argument_type[0] == 'l' && argument_type[0] == '\0')
|
|
||||||
// va_arg(*va, wint_t);
|
|
||||||
// else
|
|
||||||
// va_arg(*va, int);
|
|
||||||
// break;
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//int ft_hdr_printf(FTABLE *FORT_RESTRICT table, const char* FORT_RESTRICT fmt, ...)
|
|
||||||
//{
|
|
||||||
// int DUMMY_BUFFER_SZ = 1024;
|
|
||||||
// char dummy_buffer[DUMMY_BUFFER_SZ];
|
|
||||||
|
|
||||||
// char *fmt_copy = F_STRDUP(fmt);
|
|
||||||
// if (fmt_copy == NULL)
|
|
||||||
// return 0;
|
|
||||||
|
|
||||||
// va_list va;
|
|
||||||
// va_start(va, fmt);
|
|
||||||
|
|
||||||
// char *pos = fmt_copy;
|
|
||||||
// char *base_pos = fmt_copy;
|
|
||||||
// while (*pos) {
|
|
||||||
// pos = strchr(pos, FORT_COL_SEPARATOR);
|
|
||||||
// if (pos != NULL) {
|
|
||||||
// /* todo: do normal escape checking */
|
|
||||||
// if (pos > base_pos && (*(pos - 1) == '\\')) { /* column separator is escaped */
|
|
||||||
// ++pos;
|
|
||||||
// continue;
|
|
||||||
// } else { /* column separator is found and it is not escaped */
|
|
||||||
// *(pos) = '\0';
|
|
||||||
// ++pos;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// while (1) {
|
|
||||||
// va_list va_arg;
|
|
||||||
// va_copy(va_arg, va);
|
|
||||||
// int n = vsnprintf(dummy_buffer, DUMMY_BUFFER_SZ, base_pos, va_arg);
|
|
||||||
|
|
||||||
// /* successful write */
|
|
||||||
// if (n < DUMMY_BUFFER_SZ) {
|
|
||||||
// forward_va_list(base_pos, &va);
|
|
||||||
// fprintf(stderr, "%s\n", dummy_buffer);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (pos == NULL)
|
|
||||||
// break;
|
|
||||||
// base_pos = pos;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//// va_list va;
|
|
||||||
//// int written_cols = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//// written_cols = vfprintf(stderr, fmt, va);
|
int ft_row_printf_impl(FTABLE *FORT_RESTRICT table, size_t row, const char* FORT_RESTRICT fmt, va_list *va)
|
||||||
|
|
||||||
//// va_end(va);
|
|
||||||
//// va_start(va, fmt);
|
|
||||||
//// written_cols |= vfprintf(stderr, fmt, va);
|
|
||||||
|
|
||||||
|
|
||||||
//// va_end(va);
|
|
||||||
|
|
||||||
// F_FREE(fmt_copy);
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//int ft_hdr_printf(FTABLE *FORT_RESTRICT table, const char* FORT_RESTRICT fmt, ...)
|
|
||||||
//{
|
|
||||||
// string_buffer_t *buffer = create_string_buffer(1024);
|
|
||||||
// if (buffer == NULL)
|
|
||||||
// return -1;
|
|
||||||
|
|
||||||
// int cols_origin = number_of_columns_in_format_string(fmt);
|
|
||||||
|
|
||||||
// while (1) {
|
|
||||||
// va_list va;
|
|
||||||
// va_start(va, fmt);
|
|
||||||
// int virtual_sz = vsnprintf(buffer->str, buffer->str_sz, fmt, va);
|
|
||||||
// va_end(va);
|
|
||||||
// /* If error encountered */
|
|
||||||
// if (virtual_sz == -1)
|
|
||||||
// goto clear;
|
|
||||||
|
|
||||||
// /* Successful write */
|
|
||||||
// if (virtual_sz < buffer->str_sz)
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// /* Otherwise buffer was too small, so incr. buffer size ant try again. */
|
|
||||||
// if (!IS_SUCCESS(realloc_string_buffer_without_copy(buffer)))
|
|
||||||
// goto clear;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// int cols = number_of_columns_in_format_string(buffer->str);
|
|
||||||
// if (cols == cols_origin) {
|
|
||||||
|
|
||||||
// fort_row_t *row = create_row_from_string(buffer->str);
|
|
||||||
// if (row == NULL) {
|
|
||||||
// goto clear;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// table->header = row;
|
|
||||||
// return vector_size(row->cells);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
//clear:
|
|
||||||
// destroy_string_buffer(buffer);
|
|
||||||
// return -1;
|
|
||||||
//}
|
|
||||||
|
|
||||||
int ft_hdr_printf(FTABLE *FORT_RESTRICT table, const char* FORT_RESTRICT fmt, ...)
|
|
||||||
{
|
{
|
||||||
if (table == NULL)
|
if (table == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
va_list va;
|
fort_row_t *new_row = create_row_from_fmt_string(fmt, va);
|
||||||
va_start(va, fmt);
|
|
||||||
fort_row_t *row = create_row_from_fmt_string(fmt, &va);
|
|
||||||
va_end(va);
|
|
||||||
|
|
||||||
if (row == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (table->header) {
|
|
||||||
destroy_row(table->header);
|
|
||||||
}
|
|
||||||
table->header = row;
|
|
||||||
return vector_size(row->cells);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ft_row_printf(FTABLE *FORT_RESTRICT table, size_t row, const char* FORT_RESTRICT fmt, ...)
|
|
||||||
{
|
|
||||||
if (table == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
|
||||||
fort_row_t *new_row = create_row_from_fmt_string(fmt, &va);
|
|
||||||
va_end(va);
|
|
||||||
|
|
||||||
if (new_row == NULL) {
|
if (new_row == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -560,6 +453,24 @@ clear:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ft_hdr_printf(FTABLE *FORT_RESTRICT table, const char* FORT_RESTRICT fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
int result = ft_row_printf_impl(table, 0, fmt, &va);
|
||||||
|
va_end(va);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft_row_printf(FTABLE *FORT_RESTRICT table, size_t row, const char* FORT_RESTRICT fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
int result = ft_row_printf_impl(table, row, fmt, &va);
|
||||||
|
va_end(va);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -766,7 +677,7 @@ static void *vector_at(vector_t *vector, size_t index)
|
|||||||
|
|
||||||
|
|
||||||
#define FOR_EACH_(type, item, vector, index_name) \
|
#define FOR_EACH_(type, item, vector, index_name) \
|
||||||
for (size_t index_name = 0; (item = *(type*)vector_at(vector, index_name)), (index_name < vector_size(vector)); ++index_name)
|
for (size_t index_name = 0; (index_name < vector_size(vector)) ? ((item = *(type*)vector_at(vector, index_name)), 1) : 0; ++index_name)
|
||||||
|
|
||||||
#define FOR_EACH(type, item, vector) \
|
#define FOR_EACH(type, item, vector) \
|
||||||
FOR_EACH_(type, item, vector, UNIQUE_NAME(i))
|
FOR_EACH_(type, item, vector, UNIQUE_NAME(i))
|
||||||
@ -894,7 +805,7 @@ static int print_row(char *buffer, const fort_row_t *row)
|
|||||||
/*
|
/*
|
||||||
* Returns number of cells (rows * cols)
|
* Returns number of cells (rows * cols)
|
||||||
*/
|
*/
|
||||||
static void table_body_sizes(const FTABLE *table, size_t *rows, size_t *cols)
|
static fort_status_t get_table_sizes(const FTABLE *table, size_t *rows, size_t *cols)
|
||||||
{
|
{
|
||||||
*rows = 0;
|
*rows = 0;
|
||||||
*cols = 0;
|
*cols = 0;
|
||||||
@ -906,26 +817,82 @@ static void table_body_sizes(const FTABLE *table, size_t *rows, size_t *cols)
|
|||||||
*cols = cols_in_row;
|
*cols = cols_in_row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return F_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fort_status_t table_rows_and_cols_geometry(const FTABLE *table,
|
||||||
|
size_t **col_width_arr_p, size_t *col_width_arr_sz,
|
||||||
|
size_t **row_height_arr_p, size_t *row_height_arr_sz)
|
||||||
|
{
|
||||||
|
if (table == NULL) {
|
||||||
|
return F_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cols = 0;
|
||||||
|
size_t rows = 0;
|
||||||
|
int status = get_table_sizes(table, &rows, &cols);
|
||||||
|
if (IS_ERROR(status))
|
||||||
|
return status;
|
||||||
|
|
||||||
|
size_t *col_width_arr = F_CALLOC(sizeof(size_t), cols);
|
||||||
|
size_t *row_height_arr = F_CALLOC(sizeof(size_t), rows);
|
||||||
|
if (col_width_arr == NULL || row_height_arr == NULL) {
|
||||||
|
F_FREE(col_width_arr);
|
||||||
|
F_FREE(row_height_arr);
|
||||||
|
return F_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t col = 0; col < cols; ++col) {
|
||||||
|
col_width_arr[col] = 0;
|
||||||
|
for (size_t row = 0; row < rows; ++row) {
|
||||||
|
const fort_row_t *row_p = get_row_c(table, row);
|
||||||
|
const fort_cell_t *cell = get_cell_c(row_p, col);
|
||||||
|
if (cell) {
|
||||||
|
col_width_arr[col] = MAX(col_width_arr[col], hint_width_cell(cell));
|
||||||
|
row_height_arr[row] = MAX(row_height_arr[row], hint_height_cell(cell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*col_width_arr_p = col_width_arr;
|
||||||
|
*col_width_arr_sz = cols;
|
||||||
|
*row_height_arr_p = row_height_arr;
|
||||||
|
*row_height_arr_sz = rows;
|
||||||
|
return F_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns geometry in characters
|
* Returns geometry in characters
|
||||||
*/
|
*/
|
||||||
static void table_geometry(const FTABLE *table, size_t *height, size_t *width)
|
static fort_status_t table_geometry(const FTABLE *table, size_t *height, size_t *width)
|
||||||
{
|
{
|
||||||
|
if (table == NULL)
|
||||||
|
return F_ERROR;
|
||||||
|
|
||||||
*height = 0;
|
*height = 0;
|
||||||
*width = 0;
|
*width = 0;
|
||||||
if (table) {
|
|
||||||
size_t cols = 0;
|
size_t cols = 0;
|
||||||
size_t rows = 0;
|
size_t rows = 0;
|
||||||
table_body_sizes(table, &rows, &cols);
|
size_t *col_width_arr = NULL;
|
||||||
if (table->header) {
|
size_t *row_height_arr = NULL;
|
||||||
cols = MAX(cols, columns_in_row(table->header));
|
|
||||||
++rows;
|
int status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows);
|
||||||
|
if (IS_ERROR(status))
|
||||||
|
return status;
|
||||||
|
|
||||||
|
*width = 1 + (cols == 0 ? 1 : cols) + 1; // for boundaries (that take 1 symbol) + newline
|
||||||
|
for (size_t i = 0; i < cols; ++i) {
|
||||||
|
*width += col_width_arr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*height = 1 + (rows == 0 ? 1 : rows); // for boundaries (that take 1 symbol)
|
||||||
|
for (size_t i = 0; i < rows; ++i) {
|
||||||
|
*height += row_height_arr[i];
|
||||||
}
|
}
|
||||||
|
F_FREE(col_width_arr);
|
||||||
|
F_FREE(row_height_arr);
|
||||||
|
return F_SUCCESS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ft_to_string(const FTABLE *FORT_RESTRICT table)
|
char* ft_to_string(const FTABLE *FORT_RESTRICT table)
|
||||||
@ -933,12 +900,7 @@ char* ft_to_string(const FTABLE *FORT_RESTRICT table)
|
|||||||
assert(table);
|
assert(table);
|
||||||
char *dummy = F_MALLOC(2056);
|
char *dummy = F_MALLOC(2056);
|
||||||
|
|
||||||
fort_row_t *header = table->header;
|
int dev = 0;
|
||||||
int dev = print_row(dummy, header);
|
|
||||||
|
|
||||||
sprintf(dummy + dev , "\n");
|
|
||||||
dev += 1;
|
|
||||||
|
|
||||||
size_t rows = vector_size(table->rows);
|
size_t rows = vector_size(table->rows);
|
||||||
for (size_t i = 0; i < rows; ++i) {
|
for (size_t i = 0; i < rows; ++i) {
|
||||||
fort_row_t *row = *(fort_row_t**)vector_at(table->rows, i);
|
fort_row_t *row = *(fort_row_t**)vector_at(table->rows, i);
|
||||||
@ -951,6 +913,32 @@ char* ft_to_string(const FTABLE *FORT_RESTRICT table)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//char* ft_to_string(const FTABLE *FORT_RESTRICT table)
|
||||||
|
//{
|
||||||
|
// assert(table);
|
||||||
|
|
||||||
|
// size_t height = 0;
|
||||||
|
// size_t width = 0;
|
||||||
|
// int status = table_geometry(table, &height, &width);
|
||||||
|
// if (IS_ERROR(status)) {
|
||||||
|
// return NULL;
|
||||||
|
// }
|
||||||
|
// fprintf(stderr, "width = %d ; height = %d\n", (int)width, (int)height);
|
||||||
|
// size_t sz = height * width + 10;
|
||||||
|
// char *dummy = F_MALLOC(sz);
|
||||||
|
|
||||||
|
// int dev = 0;
|
||||||
|
// size_t rows = vector_size(table->rows);
|
||||||
|
// for (size_t i = 0; i < rows; ++i) {
|
||||||
|
// fort_row_t *row = *(fort_row_t**)vector_at(table->rows, i);
|
||||||
|
// dev += print_row(dummy + dev, row);
|
||||||
|
// sprintf(dummy + dev , "\n");
|
||||||
|
// dev += 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return dummy;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
11
src/fort_impl.h
Normal file
11
src/fort_impl.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef FORT_IMPL_H
|
||||||
|
#define FORT_IMPL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "fort.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FORT_IMPL_H
|
@ -4,6 +4,7 @@
|
|||||||
int main(void) {
|
int main(void) {
|
||||||
const struct CMUnitTest tests[] = {
|
const struct CMUnitTest tests[] = {
|
||||||
cmocka_unit_test(test_vector_basic),
|
cmocka_unit_test(test_vector_basic),
|
||||||
|
cmocka_unit_test(test_table_geometry),
|
||||||
cmocka_unit_test(test_table_basic)
|
cmocka_unit_test(test_table_basic)
|
||||||
};
|
};
|
||||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
@ -3,6 +3,25 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "fort.c"
|
||||||
|
|
||||||
|
void test_table_geometry(void **state)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
FTABLE *table = ft_create_table();
|
||||||
|
|
||||||
|
int n = ft_hdr_printf(table, "%c", 'c');
|
||||||
|
assert_true( n == 1 );
|
||||||
|
|
||||||
|
size_t height = 0;
|
||||||
|
size_t width = 0;
|
||||||
|
int status = table_geometry(table, &height, &width);
|
||||||
|
assert_true( IS_SUCCESS(status) );
|
||||||
|
|
||||||
|
|
||||||
|
ft_destroy_table(table);
|
||||||
|
}
|
||||||
|
|
||||||
void test_table_basic(void **state)
|
void test_table_basic(void **state)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
@ -11,17 +30,23 @@ void test_table_basic(void **state)
|
|||||||
int n = ft_hdr_printf(table, "%d , %c|| %s|%f", 3, 'c', "234", 3.14);
|
int n = ft_hdr_printf(table, "%d , %c|| %s|%f", 3, 'c', "234", 3.14);
|
||||||
assert_true( n == 4 );
|
assert_true( n == 4 );
|
||||||
|
|
||||||
n = ft_row_printf(table, 0, "%d , %c|| %s|%f", 3, 'c', "234", 3.14);
|
|
||||||
assert_true( n == 4 );
|
|
||||||
n = ft_row_printf(table, 1, "%d , %c|| %s|%f", 3, 'c', "234", 3.14);
|
n = ft_row_printf(table, 1, "%d , %c|| %s|%f", 3, 'c', "234", 3.14);
|
||||||
assert_true( n == 4 );
|
assert_true( n == 4 );
|
||||||
|
n = ft_row_printf(table, 2, "%d , %c|| %s|%f", 3, 'c', "234", 3.14);
|
||||||
|
assert_true( n == 4 );
|
||||||
|
n = ft_row_printf(table, 4, "%d , %c|| %s|%f", 3, 'c', "234", 3.14);
|
||||||
|
assert_true( n == 4 );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *table_str = ft_to_string(table);
|
char *table_str = ft_to_string(table);
|
||||||
const char *table_str_etalon =
|
const char *table_str_etalon =
|
||||||
"| 3 , c| | 234| 3.140000\n"
|
"| 3 , c| | 234| 3.140000\n"
|
||||||
"| 3 , c| | 234| 3.140000\n"
|
"| 3 , c| | 234| 3.140000\n"
|
||||||
|
"| 3 , c| | 234| 3.140000\n"
|
||||||
|
"\n"
|
||||||
"| 3 , c| | 234| 3.140000\n";
|
"| 3 , c| | 234| 3.140000\n";
|
||||||
|
fprintf(stderr, "%s", table_str);
|
||||||
|
|
||||||
assert_true( strcmp(table_str, table_str_etalon) == 0);
|
assert_true( strcmp(table_str, table_str_etalon) == 0);
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
|
|
||||||
void test_vector_basic(void **state);
|
void test_vector_basic(void **state);
|
||||||
|
|
||||||
|
void test_table_geometry(void **state);
|
||||||
void test_table_basic(void **state);
|
void test_table_basic(void **state);
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user