From ac54041501ce1ed3b224411342a881b0effb7210 Mon Sep 17 00:00:00 2001 From: seleznevae Date: Sun, 6 May 2018 16:36:53 +0300 Subject: [PATCH] [C] Changed names of the files --- CMakeLists.txt | 14 +- amalgamate.py | 2 +- include/fort.c | 1984 ++++++++++++++--------------- src/cell.h | 2 +- src/fort.c | 983 -------------- src/fort_impl.c | 1191 +++++++++++++---- src/fort_utils.c | 270 ++++ src/{fort_impl.h => fort_utils.h} | 0 src/options.c | 2 +- src/options.h | 2 +- src/row.h | 2 +- src/string_buffer.h | 2 +- src/table.h | 2 +- src/vector.h | 2 +- 14 files changed, 2229 insertions(+), 2229 deletions(-) delete mode 100644 src/fort.c create mode 100644 src/fort_utils.c rename src/{fort_impl.h => fort_utils.h} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 966a773..7035351 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,15 +63,15 @@ FILE(GLOB_RECURSE FortHeaders "include/*.h" "include/*.hpp" "tests/*.h" "src/*.h add_custom_target(headers SOURCES ${FortHeaders}) -set(FORT_SOURCES - src/fort.c +set(FORT_DEV_SOURCES + src/fort_impl.c src/vector.c src/string_buffer.c src/options.c src/cell.c src/row.c src/table.c - src/fort_impl.c + src/fort_utils.c src/wcwidth.c) @@ -81,13 +81,13 @@ set(EXAMPLE_SOURCES example/main.c) add_executable(${PROJECT_NAME}_example ${EXAMPLE_SOURCES} - ${FORT_SOURCES}) + ${FORT_DEV_SOURCES}) set(EXAMPLE_CPP_SOURCES example/main.cpp) add_executable(${PROJECT_NAME}_example_cpp ${EXAMPLE_CPP_SOURCES} - ${FORT_SOURCES}) + ${FORT_DEV_SOURCES}) set(TEST_SOURCES_DEV tests/main_test.c @@ -100,7 +100,7 @@ set(TEST_SOURCES_DEV tests/bb_tests/test_memory_errors.c tests/test_utils.c) add_executable(${PROJECT_NAME}_test_dev - ${FORT_SOURCES} + ${FORT_DEV_SOURCES} ${TEST_SOURCES_DEV}) target_compile_definitions(${PROJECT_NAME}_test_dev @@ -119,7 +119,7 @@ add_executable(${PROJECT_NAME}_test if(FORT_CXX_BUILD) - SET_SOURCE_FILES_PROPERTIES( ${FORT_SOURCES} PROPERTIES LANGUAGE CXX) + SET_SOURCE_FILES_PROPERTIES( ${FORT_DEV_SOURCES} PROPERTIES LANGUAGE CXX) SET_SOURCE_FILES_PROPERTIES( ${EXAMPLE_SOURCES} PROPERTIES LANGUAGE CXX) SET_SOURCE_FILES_PROPERTIES( ${TEST_SOURCES} PROPERTIES LANGUAGE CXX) endif(FORT_CXX_BUILD) diff --git a/amalgamate.py b/amalgamate.py index 46f24a2..4641b7a 100644 --- a/amalgamate.py +++ b/amalgamate.py @@ -63,7 +63,7 @@ def main(): # config["header_files"] = filter(is_c_header_file, all_files) config["header_files"] = [ - "fort_impl.h", + "fort_utils.h", "vector.h", "wcwidth.h", "string_buffer.h", diff --git a/include/fort.c b/include/fort.c index a149ea5..f0f34dd 100644 --- a/include/fort.c +++ b/include/fort.c @@ -3,7 +3,7 @@ /******************************************************** - Begin of file "fort_impl.h" + Begin of file "fort_utils.h" ********************************************************/ #ifndef FORT_IMPL_H @@ -157,7 +157,7 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str); #endif /* FORT_IMPL_H */ /******************************************************** - End of file "fort_impl.h" + End of file "fort_utils.h" ********************************************************/ @@ -168,7 +168,7 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str); #ifndef VECTOR_H #define VECTOR_H -/* #include "fort_impl.h" */ /* Commented by amalgamation script */ +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ /***************************************************************************** @@ -234,7 +234,7 @@ int mk_wcswidth(const wchar_t *pwcs, size_t n); #ifndef STRING_BUFFER_H #define STRING_BUFFER_H -/* #include "fort_impl.h" */ /* Commented by amalgamation script */ +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ /***************************************************************************** @@ -290,7 +290,7 @@ int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, siz #ifndef OPTIONS_H #define OPTIONS_H -/* #include "fort_impl.h" */ /* Commented by amalgamation script */ +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ #include #include @@ -463,7 +463,7 @@ void destroy_table_options(fort_table_options_t* options); #ifndef CELL_H #define CELL_H -/* #include "fort_impl.h" */ /* Commented by amalgamation script */ +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ @@ -512,7 +512,7 @@ string_buffer_t* cell_get_string_buffer(fort_cell_t *cell); #ifndef ROW_H #define ROW_H -/* #include "fort_impl.h" */ /* Commented by amalgamation script */ +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ #include "fort.h" #include /* #include "options.h" */ /* Commented by amalgamation script */ @@ -585,7 +585,7 @@ int wsnprintf_row(const fort_row_t *row, wchar_t *buffer, size_t buf_sz, size_t #ifndef TABLE_H #define TABLE_H -/* #include "fort_impl.h" */ /* Commented by amalgamation script */ +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ struct ft_table; typedef struct ft_table ft_table_t; @@ -645,7 +645,7 @@ fort_status_t table_geometry(const ft_table_t *table, size_t *height, size_t *wi #include /* #include "options.h" */ /* Commented by amalgamation script */ -/* #include "fort_impl.h" */ /* Commented by amalgamation script */ +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ /* #include "vector.h" */ /* Commented by amalgamation script */ /***************************************************************************** @@ -1523,987 +1523,6 @@ fort_status_t table_geometry(const ft_table_t *table, size_t *height, size_t *wi Begin of file "fort_impl.c" ********************************************************/ -/* #include "fort_impl.h" */ /* Commented by amalgamation script */ -#ifdef FT_HAVE_WCHAR -#include -#endif - - - -/***************************************************************************** - * LIBFORT helpers - *****************************************************************************/ - -#ifndef FT_MICROSOFT_COMPILER -void *(*fort_malloc)(size_t size) = &malloc; -void (*fort_free)(void *ptr) = &free; -void *(*fort_calloc)(size_t nmemb, size_t size) = &calloc; -void *(*fort_realloc)(void *ptr, size_t size) = &realloc; -#else -static void *local_malloc(size_t size) -{ - return malloc(size); -} - -static void local_free(void *ptr) -{ - free(ptr); -} - -static void *local_calloc(size_t nmemb, size_t size) -{ - return calloc(nmemb, size); -} - -static void *local_realloc(void *ptr, size_t size) -{ - return realloc(ptr, size); -} - -void *(*fort_malloc)(size_t size) = &local_malloc; -void (*fort_free)(void *ptr) = &local_free; -void *(*fort_calloc)(size_t nmemb, size_t size) = &local_calloc; -void *(*fort_realloc)(void *ptr, size_t size) = &local_realloc; -#endif - -static void *custom_fort_calloc(size_t nmemb, size_t size) -{ - size_t total_size = nmemb * size; - void *result = F_MALLOC(total_size); - if (result != NULL) - memset(result, 0, total_size); - return result; -} - -static void *custom_fort_realloc(void *ptr, size_t size) -{ - if (ptr == NULL) - return F_MALLOC(size); - if (size == 0) { - F_FREE(ptr); - return NULL; - } - - void *new_chunk = F_MALLOC(size); - if (new_chunk == NULL) - return NULL; - - /* - * In theory we should copy MIN(size, size allocated for ptr) bytes, - * but this is rather dummy implementation so we don't care about it - */ - memcpy(new_chunk, ptr, size); - F_FREE(ptr); - return new_chunk; -} - -void set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)) -{ - assert((f_malloc == NULL && f_free == NULL) /* Use std functions */ - || (f_malloc != NULL && f_free != NULL) /* Use custom functions */); - - if (f_malloc == NULL && f_free == NULL) { -#ifndef FT_MICROSOFT_COMPILER - fort_malloc = &malloc; - fort_free = &free; - fort_calloc = &calloc; - fort_realloc = &realloc; -#else - fort_malloc = &local_malloc; - fort_free = &local_free; - fort_calloc = &local_calloc; - fort_realloc = &local_realloc; -#endif - } else { - fort_malloc = f_malloc; - fort_free = f_free; - fort_calloc = &custom_fort_calloc; - fort_realloc = &custom_fort_realloc; - } - -} - - -char *fort_strdup(const char *str) -{ - if (str == NULL) - return NULL; - - size_t sz = strlen(str); - char *str_copy = (char *)F_MALLOC((sz + 1) * sizeof(char)); - if (str_copy == NULL) - return NULL; - - strcpy(str_copy, str); - return str_copy; -} - -wchar_t *fort_wcsdup(const wchar_t *str) -{ - if (str == NULL) - return NULL; - - size_t sz = wcslen(str); - wchar_t *str_copy = (wchar_t *)F_MALLOC((sz + 1) * sizeof(wchar_t)); - if (str_copy == NULL) - return NULL; - - wcscpy(str_copy, str); - return str_copy; -} - -size_t number_of_columns_in_format_string(const char *fmt) -{ - int separator_counter = 0; - const char *pos = fmt; - while (1) { - pos = strchr(pos, FORT_COL_SEPARATOR); - if (pos == NULL) - break; - - separator_counter++; - ++pos; - } - return separator_counter + 1; -} - -size_t number_of_columns_in_format_wstring(const wchar_t *fmt) -{ - int separator_counter = 0; - const wchar_t *pos = fmt; - while (1) { - pos = wcschr(pos, FORT_COL_SEPARATOR); - if (pos == NULL) - break; - - separator_counter++; - ++pos; - } - return separator_counter + 1; -} - - -//int snprint_n_chars(char *buf, size_t length, size_t n, char ch) -//{ -// if (length <= n) -// return -1; - -// if (n == 0) -// return 0; - -// /* To ensure valid return value it is safely not print such big strings */ -// if (n > INT_MAX) -// return -1; - -// int status = snprintf(buf, length, "%0*d", (int)n, 0); -// if (status < 0) -// return status; - -// size_t i = 0; -// for (i = 0; i < n; ++i) { -// *buf = ch; -// buf++; -// } -// return (int)n; -//} - -int snprint_n_strings(char *buf, size_t length, size_t n, const char *str) -{ - size_t str_len = strlen(str); - if (length <= n * str_len) - return -1; - - if (n == 0) - return 0; - - /* To ensure valid return value it is safely not print such big strings */ - if (n * str_len > INT_MAX) - return -1; - - int status = snprintf(buf, length, "%0*d", (int)(n * str_len), 0); - if (status < 0) - return status; - - size_t i = 0; - for (i = 0; i < n; ++i) { - const char *str_p = str; - while (*str_p) - *(buf++) = *(str_p++); - } - return (int)(n * str_len); -} - - -//int wsnprint_n_chars(wchar_t *buf, size_t length, size_t n, wchar_t ch) -//{ -// if (length <= n) -// return -1; - -// if (n == 0) -// return 0; - -// /* To ensure valid return value it is safely not print such big strings */ -// if (n > INT_MAX) -// return -1; - -// int status = swprintf(buf, length, L"%0*d", (int)n, 0); -// if (status < 0) -// return status; - -// size_t i = 0; -// for (i = 0; i < n; ++i) { -// *buf = ch; -// buf++; -// } -// return (int)n; -//} - -int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str) -{ - size_t str_len = strlen(str); - - /* This function doesn't work properly with multibyte characters - * so it is better return an error in this case - */ - if (str_len > 1) - return -1; - - if (length <= n * str_len) - return -1; - - if (n == 0) - return 0; - - - - /* To ensure valid return value it is safely not print such big strings */ - if (n * str_len > INT_MAX) - return -1; - - int status = swprintf(buf, length, L"%0*d", (int)(n * str_len), 0); - if (status < 0) - return status; - - size_t i = 0; - for (i = 0; i < n; ++i) { - const char *str_p = str; - while (*str_p) - *(buf++) = (wchar_t) * (str_p++); - } - return (int)(n * str_len); -} - - -/******************************************************** - End of file "fort_impl.c" - ********************************************************/ - - -/******************************************************** - Begin of file "vector.c" - ********************************************************/ - -/* #include "vector.h" */ /* Commented by amalgamation script */ -#include -#include - -/***************************************************************************** - * VECTOR IMPLEMENTATIONS - * ***************************************************************************/ - -struct vector { - size_t m_size; - void *m_data; - size_t m_capacity; - size_t m_item_size; -}; - -static int vector_reallocate_(vector_t *vector, size_t new_capacity) -{ - assert(vector); - assert(new_capacity > vector->m_capacity); - - size_t new_size = new_capacity * vector->m_item_size; - vector->m_data = F_REALLOC(vector->m_data, new_size); - if (vector->m_data == NULL) - return -1; - return 0; -} - -/* ------------ Constructors & Destructors ----------------------------- */ - -vector_t *create_vector(size_t item_size, size_t capacity) -{ - vector_t *vector = (vector_t *)F_MALLOC(sizeof(vector_t)); - if (vector == NULL) { - SYS_LOG_ERROR("Failed to allocate memory for asock vector"); - return NULL; - } - - size_t init_size = MAX(item_size * capacity, 1); - vector->m_data = F_MALLOC(init_size); - if (vector->m_data == NULL) { - SYS_LOG_ERROR("Failed to allocate memory for asock vector inern. buffer"); - F_FREE(vector); - return NULL; - } - - vector->m_size = 0; - vector->m_capacity = capacity; - vector->m_item_size = item_size; - - return vector; -} - - -void destroy_vector(vector_t *vector) -{ - assert(vector); - F_FREE(vector->m_data); - F_FREE(vector); -} - -vector_t *copy_vector(vector_t *v) -{ - if (v == NULL) - return NULL; - - vector_t *new_vector = create_vector(v->m_item_size, v->m_capacity); - if (new_vector == NULL) - return NULL; - - memcpy(new_vector->m_data, v->m_data, v->m_item_size * v->m_size); - new_vector->m_size = v->m_size ; - new_vector->m_item_size = v->m_item_size ; - return new_vector; -} - - - -/* ----------- Nonmodifying functions --------------------------------- */ - -size_t vector_size(const vector_t *vector) -{ - assert(vector); - return vector->m_size; -} - - -size_t vector_capacity(const vector_t *vector) -{ - assert(vector); - return vector->m_capacity; -} - -size_t vector_index_of(const vector_t *vector, const void *item) -{ - assert(vector); - assert(item); - - size_t i = 0; - for (i = 0; i < vector->m_size; ++i) { - void *data_pos = (char *)vector->m_data + i * vector->m_item_size; - if (memcmp(data_pos, item, vector->m_item_size) == 0) { - return i; - } - } - return INVALID_VEC_INDEX; -} - - -/* ----------- Modifying functions ------------------------------------- */ - -int vector_push(vector_t *vector, const void *item) -{ - assert(vector); - assert(item); - - if (vector->m_size == vector->m_capacity) { - if (vector_reallocate_(vector, vector->m_capacity * 2) == -1) - return FT_ERROR; - vector->m_capacity = vector->m_capacity * 2; - } - - ptrdiff_t deviation = vector->m_size * vector->m_item_size; - memcpy((char *)vector->m_data + deviation, item, vector->m_item_size); - - ++(vector->m_size); - - return FT_SUCCESS; -} - - -int vector_erase(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(vector_t *vector) -{ - vector->m_size = 0; -} - -const void *vector_at_c(const vector_t *vector, size_t index) -{ - if (index >= vector->m_size) - return NULL; - - return (char *)vector->m_data + index * vector->m_item_size; -} - - -void *vector_at(vector_t *vector, size_t index) -{ - if (index >= vector->m_size) - return NULL; - - return (char *)vector->m_data + index * vector->m_item_size; -} - -fort_status_t vector_swap(vector_t *cur_vec, vector_t *mv_vec, size_t pos) -{ - assert(cur_vec); - assert(mv_vec); - assert(cur_vec != mv_vec); - assert(cur_vec->m_item_size == mv_vec->m_item_size); - - size_t cur_sz = vector_size(cur_vec); - size_t mv_sz = vector_size(mv_vec); - if (mv_sz == 0) { - return FT_SUCCESS; - } - - size_t min_targ_size = pos + mv_sz; - if (cur_sz < min_targ_size) { - if (vector_reallocate_(cur_vec, min_targ_size) == -1) - return FT_ERROR; - cur_vec->m_capacity = min_targ_size; - } - - ptrdiff_t deviation = pos * cur_vec->m_item_size; - void *tmp = NULL; - size_t new_mv_sz = 0; - if (cur_sz > pos) { - new_mv_sz = MIN(cur_sz - pos, mv_sz); - tmp = F_MALLOC(cur_vec->m_item_size * new_mv_sz); - if (tmp == NULL) { - return FT_MEMORY_ERROR; - } - } - - memcpy(tmp, - (char *)cur_vec->m_data + deviation, - cur_vec->m_item_size * (cur_sz - pos)); - memcpy((char *)cur_vec->m_data + deviation, - mv_vec->m_data, - cur_vec->m_item_size * mv_sz); - memcpy(mv_vec->m_data, - tmp, - cur_vec->m_item_size * new_mv_sz); - - mv_vec->m_size = new_mv_sz; - F_FREE(tmp); - return FT_SUCCESS; -} - - - - -/******************************************************** - End of file "vector.c" - ********************************************************/ - - -/******************************************************** - Begin of file "string_buffer.c" - ********************************************************/ - -/* #include "string_buffer.h" */ /* Commented by amalgamation script */ -/* #include "options.h" */ /* Commented by amalgamation script */ -/* #include "wcwidth.h" */ /* Commented by amalgamation script */ -#include -#include -#include -/***************************************************************************** - * STRING BUFFER - * ***************************************************************************/ - - -static ptrdiff_t str_iter_width(const char *beg, const char *end) -{ - assert(end >= beg); - return (end - beg); -} - -static ptrdiff_t wcs_iter_width(const wchar_t *beg, const wchar_t *end) -{ - assert(end >= beg); - return mk_wcswidth(beg, (end - beg)); -} - - -static size_t buf_str_len(const string_buffer_t *buf) -{ - assert(buf); - if (buf->type == CharBuf) { - return strlen(buf->str.cstr); - } else { - return wcslen(buf->str.wstr); - } -} - -size_t strchr_count(const char *str, char ch) -{ - if (str == NULL) - return 0; - - size_t count = 0; - str = strchr(str, ch); - while (str) { - count++; - str++; - str = strchr(str, ch); - } - return count; -} - -size_t wstrchr_count(const wchar_t *str, wchar_t ch) -{ - if (str == NULL) - return 0; - - size_t count = 0; - str = wcschr(str, ch); - while (str) { - count++; - str++; - str = wcschr(str, ch); - } - return count; -} - -const char *str_n_substring_beg(const char *str, char ch_separator, size_t n) -{ - if (str == NULL) - return NULL; - - if (n == 0) - return str; - - str = strchr(str, ch_separator); - --n; - while (n > 0) { - if (str == NULL) - return NULL; - --n; - str++; - str = strchr(str, ch_separator); - } - return str ? (str + 1) : NULL; -} - -const wchar_t *wstr_n_substring_beg(const wchar_t *str, wchar_t ch_separator, size_t n) -{ - if (str == NULL) - return NULL; - - if (n == 0) - return str; - - str = wcschr(str, ch_separator); - --n; - while (n > 0) { - if (str == NULL) - return NULL; - --n; - str++; - str = wcschr(str, ch_separator); - } - return str ? (str + 1) : NULL; -} - -void str_n_substring(const char *str, char ch_separator, size_t n, const char **begin, const char **end) -{ - const char *beg = str_n_substring_beg(str, ch_separator, n); - if (beg == NULL) { - *begin = NULL; - *end = NULL; - return; - } - - const char *en = strchr(beg, ch_separator); - if (en == NULL) { - en = str + strlen(str); - } - - *begin = beg; - *end = en; - return; -} - -void wstr_n_substring(const wchar_t *str, wchar_t ch_separator, size_t n, const wchar_t **begin, const wchar_t **end) -{ - const wchar_t *beg = wstr_n_substring_beg(str, ch_separator, n); - if (beg == NULL) { - *begin = NULL; - *end = NULL; - return; - } - - const wchar_t *en = wcschr(beg, ch_separator); - if (en == NULL) { - en = str + wcslen(str); - } - - *begin = beg; - *end = en; - return; -} - - -string_buffer_t *create_string_buffer(size_t number_of_chars, enum str_buf_type type) -{ - size_t sz = (number_of_chars) * (type == CharBuf ? sizeof(char) : sizeof(wchar_t)); - string_buffer_t *result = (string_buffer_t *)F_MALLOC(sizeof(string_buffer_t)); - if (result == NULL) - return NULL; - result->str.data = F_MALLOC(sz); - if (result->str.data == NULL) { - F_FREE(result); - return NULL; - } - result->data_sz = sz; - result->type = type; - - if (sz && type == CharBuf) { - result->str.cstr[0] = '\0'; - } else if (sz && type == WCharBuf) { - result->str.wstr[0] = L'\0'; - } - - return result; -} - -void destroy_string_buffer(string_buffer_t *buffer) -{ - if (buffer == NULL) - return; - F_FREE(buffer->str.data); - buffer->str.data = NULL; - F_FREE(buffer); -} - -fort_status_t realloc_string_buffer_without_copy(string_buffer_t *buffer) -{ - assert(buffer); - char *new_str = (char *)F_MALLOC(buffer->data_sz * 2); - if (new_str == NULL) { - return FT_MEMORY_ERROR; - } - F_FREE(buffer->str.data); - buffer->str.data = new_str; - buffer->data_sz *= 2; - return FT_SUCCESS; -} - -fort_status_t fill_buffer_from_string(string_buffer_t *buffer, const char *str) -{ - assert(buffer); - assert(str); - - size_t sz = strlen(str); - char *copy = F_STRDUP(str); - if (copy == NULL) - return FT_MEMORY_ERROR; - - while (sz >= string_buffer_capacity(buffer)) { - int status = realloc_string_buffer_without_copy(buffer); - if (!FT_IS_SUCCESS(status)) { - return status; - } - } - F_FREE(buffer->str.data); - buffer->str.cstr = copy; - buffer->type = CharBuf; - - return FT_SUCCESS; -} - -fort_status_t fill_buffer_from_wstring(string_buffer_t *buffer, const wchar_t *str) -{ - assert(buffer); - assert(str); - - size_t sz = wcslen(str); - wchar_t *copy = F_WCSDUP(str); - if (copy == NULL) - return FT_MEMORY_ERROR; - - while (sz >= string_buffer_capacity(buffer)) { - int status = realloc_string_buffer_without_copy(buffer); - if (!FT_IS_SUCCESS(status)) { - return status; - } - } - F_FREE(buffer->str.data); - buffer->str.wstr = copy; - buffer->type = WCharBuf; - - return FT_SUCCESS; -} - - - -size_t buffer_text_height(string_buffer_t *buffer) -{ - if (buffer == NULL || buffer->str.data == NULL || buf_str_len(buffer) == 0) { - return 0; - } - if (buffer->type == CharBuf) - return 1 + strchr_count(buffer->str.cstr, '\n'); - else - return 1 + wstrchr_count(buffer->str.wstr, L'\n'); -} - -size_t buffer_text_width(string_buffer_t *buffer) -{ - size_t max_length = 0; - int n = 0; - if (buffer->type == CharBuf) { - while (1) { - const char *beg = NULL; - const char *end = NULL; - str_n_substring(buffer->str.cstr, '\n', n, &beg, &end); - if (beg == NULL || end == NULL) - return max_length; - - max_length = MAX(max_length, (size_t)(end - beg)); - ++n; - } - } else { - while (1) { - const wchar_t *beg = NULL; - const wchar_t *end = NULL; - wstr_n_substring(buffer->str.wstr, L'\n', n, &beg, &end); - if (beg == NULL || end == NULL) - return max_length; - - int line_width = mk_wcswidth(beg, end - beg); - if (line_width < 0) /* For safety */ - line_width = 0; - max_length = MAX(max_length, (size_t)line_width); - - ++n; - } - } -} - - - -int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t buf_len, const context_t *context) -{ -#define CHAR_TYPE char -#define NULL_CHAR '\0' -#define NEWLINE_CHAR '\n' -#define SPACE_CHAR " " -#define SNPRINTF_FMT_STR "%*s" -#define SNPRINTF snprintf -#define BUFFER_STR str.cstr -//#define SNPRINT_N_CHARS snprint_n_chars -#define SNPRINT_N_STRINGS snprint_n_strings -#define STR_N_SUBSTRING str_n_substring -#define STR_ITER_WIDTH str_iter_width - - if (buffer == NULL || buffer->str.data == NULL - || buffer_row >= buffer_text_height(buffer) || buf_len == 0) { - return -1; - } - - size_t content_width = buffer_text_width(buffer); - if ((buf_len - 1) < content_width) - return -1; - - size_t left = 0; - size_t right = 0; - - switch (get_cell_opt_value_hierarcial(context->table_options, context->row, context->column, FT_COPT_TEXT_ALIGN)) { - case FT_ALIGNED_LEFT: - left = 0; - right = (buf_len - 1) - content_width; - break; - case FT_ALIGNED_CENTER: - left = ((buf_len - 1) - content_width) / 2; - right = ((buf_len - 1) - content_width) - left; - break; - case FT_ALIGNED_RIGHT: - left = (buf_len - 1) - content_width; - right = 0; - break; - default: - assert(0); - break; - } - - int written = 0; - int tmp = 0; - const CHAR_TYPE *beg = NULL; - const CHAR_TYPE *end = NULL; - CHAR_TYPE old_value; - - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, left, SPACE_CHAR)); - - STR_N_SUBSTRING(buffer->BUFFER_STR, NEWLINE_CHAR, buffer_row, &beg, &end); - if (beg == NULL || end == NULL) - return -1; - old_value = *end; - *(CHAR_TYPE *)end = NULL_CHAR; - - ptrdiff_t str_it_width = STR_ITER_WIDTH(beg, end); - if (str_it_width < 0 || content_width < (size_t)str_it_width) - return - 1; - - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); - *(CHAR_TYPE *)end = old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, right, SPACE_CHAR)); - return written; - -clear: - return -1; - -#undef CHAR_TYPE -#undef NULL_CHAR -#undef NEWLINE_CHAR -#undef SPACE_CHAR -#undef SNPRINTF_FMT_STR -#undef SNPRINTF -#undef BUFFER_STR -//#undef SNPRINT_N_CHARS -#undef SNPRINT_N_STRINGS -#undef STR_N_SUBSTRING -#undef STR_ITER_WIDTH -} - - -int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t buf_len, const context_t *context) -{ -#define CHAR_TYPE wchar_t -#define NULL_CHAR L'\0' -#define NEWLINE_CHAR L'\n' -#define SPACE_CHAR " " -#define SNPRINTF_FMT_STR L"%*ls" -#define SNPRINTF swprintf -#define BUFFER_STR str.wstr -//#define SNPRINT_N_CHARS wsnprint_n_chars -#define SNPRINT_N_STRINGS wsnprint_n_string -#define STR_N_SUBSTRING wstr_n_substring -#define STR_ITER_WIDTH wcs_iter_width - - if (buffer == NULL || buffer->str.data == NULL - || buffer_row >= buffer_text_height(buffer) || buf_len == 0) { - return -1; - } - - size_t content_width = buffer_text_width(buffer); - if ((buf_len - 1) < content_width) - return -1; - - size_t left = 0; - size_t right = 0; - - switch (get_cell_opt_value_hierarcial(context->table_options, context->row, context->column, FT_COPT_TEXT_ALIGN)) { - case FT_ALIGNED_LEFT: - left = 0; - right = (buf_len - 1) - content_width; - break; - case FT_ALIGNED_CENTER: - left = ((buf_len - 1) - content_width) / 2; - right = ((buf_len - 1) - content_width) - left; - break; - case FT_ALIGNED_RIGHT: - left = (buf_len - 1) - content_width; - right = 0; - break; - default: - assert(0); - break; - } - - int written = 0; - int tmp = 0; - const CHAR_TYPE *beg = NULL; - const CHAR_TYPE *end = NULL; - CHAR_TYPE old_value; - - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, left, SPACE_CHAR)); - - STR_N_SUBSTRING(buffer->BUFFER_STR, NEWLINE_CHAR, buffer_row, &beg, &end); - if (beg == NULL || end == NULL) - return -1; - old_value = *end; - *(CHAR_TYPE *)end = NULL_CHAR; - - ptrdiff_t str_it_width = STR_ITER_WIDTH(beg, end); - if (str_it_width < 0 || content_width < (size_t)str_it_width) - return - 1; - - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); - *(CHAR_TYPE *)end = old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, right, SPACE_CHAR)); - return written; - -clear: - return -1; - -#undef CHAR_TYPE -#undef NULL_CHAR -#undef NEWLINE_CHAR -#undef SPACE_CHAR -#undef SNPRINTF_FMT_STR -#undef SNPRINTF -#undef BUFFER_STR -//#undef SNPRINT_N_CHARS -#undef SNPRINT_N_STRINGS -#undef STR_N_SUBSTRING -#undef STR_ITER_WIDTH -} - -size_t string_buffer_capacity(const string_buffer_t *buffer) -{ - assert(buffer); - if (buffer->type == CharBuf) - return buffer->data_sz; - else - return buffer->data_sz / sizeof(wchar_t); -} - -void *buffer_get_data(string_buffer_t *buffer) -{ - assert(buffer); - return buffer->str.data; -} - - -/******************************************************** - End of file "string_buffer.c" - ********************************************************/ - - -/******************************************************** - Begin of file "fort.c" - ********************************************************/ - /* libfort @@ -2540,7 +1559,7 @@ SOFTWARE. #include /* #include "vector.h" */ /* Commented by amalgamation script */ -/* #include "fort_impl.h" */ /* Commented by amalgamation script */ +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ /* #include "string_buffer.h" */ /* Commented by amalgamation script */ /* #include "table.h" */ /* Commented by amalgamation script */ /* #include "row.h" */ /* Commented by amalgamation script */ @@ -3489,7 +2508,988 @@ int ft_set_cell_span(ft_table_t *table, size_t row, size_t col, size_t hor_span) } /******************************************************** - End of file "fort.c" + End of file "fort_impl.c" + ********************************************************/ + + +/******************************************************** + Begin of file "vector.c" + ********************************************************/ + +/* #include "vector.h" */ /* Commented by amalgamation script */ +#include +#include + +/***************************************************************************** + * VECTOR IMPLEMENTATIONS + * ***************************************************************************/ + +struct vector { + size_t m_size; + void *m_data; + size_t m_capacity; + size_t m_item_size; +}; + +static int vector_reallocate_(vector_t *vector, size_t new_capacity) +{ + assert(vector); + assert(new_capacity > vector->m_capacity); + + size_t new_size = new_capacity * vector->m_item_size; + vector->m_data = F_REALLOC(vector->m_data, new_size); + if (vector->m_data == NULL) + return -1; + return 0; +} + +/* ------------ Constructors & Destructors ----------------------------- */ + +vector_t *create_vector(size_t item_size, size_t capacity) +{ + vector_t *vector = (vector_t *)F_MALLOC(sizeof(vector_t)); + if (vector == NULL) { + SYS_LOG_ERROR("Failed to allocate memory for asock vector"); + return NULL; + } + + size_t init_size = MAX(item_size * capacity, 1); + vector->m_data = F_MALLOC(init_size); + if (vector->m_data == NULL) { + SYS_LOG_ERROR("Failed to allocate memory for asock vector inern. buffer"); + F_FREE(vector); + return NULL; + } + + vector->m_size = 0; + vector->m_capacity = capacity; + vector->m_item_size = item_size; + + return vector; +} + + +void destroy_vector(vector_t *vector) +{ + assert(vector); + F_FREE(vector->m_data); + F_FREE(vector); +} + +vector_t *copy_vector(vector_t *v) +{ + if (v == NULL) + return NULL; + + vector_t *new_vector = create_vector(v->m_item_size, v->m_capacity); + if (new_vector == NULL) + return NULL; + + memcpy(new_vector->m_data, v->m_data, v->m_item_size * v->m_size); + new_vector->m_size = v->m_size ; + new_vector->m_item_size = v->m_item_size ; + return new_vector; +} + + + +/* ----------- Nonmodifying functions --------------------------------- */ + +size_t vector_size(const vector_t *vector) +{ + assert(vector); + return vector->m_size; +} + + +size_t vector_capacity(const vector_t *vector) +{ + assert(vector); + return vector->m_capacity; +} + +size_t vector_index_of(const vector_t *vector, const void *item) +{ + assert(vector); + assert(item); + + size_t i = 0; + for (i = 0; i < vector->m_size; ++i) { + void *data_pos = (char *)vector->m_data + i * vector->m_item_size; + if (memcmp(data_pos, item, vector->m_item_size) == 0) { + return i; + } + } + return INVALID_VEC_INDEX; +} + + +/* ----------- Modifying functions ------------------------------------- */ + +int vector_push(vector_t *vector, const void *item) +{ + assert(vector); + assert(item); + + if (vector->m_size == vector->m_capacity) { + if (vector_reallocate_(vector, vector->m_capacity * 2) == -1) + return FT_ERROR; + vector->m_capacity = vector->m_capacity * 2; + } + + ptrdiff_t deviation = vector->m_size * vector->m_item_size; + memcpy((char *)vector->m_data + deviation, item, vector->m_item_size); + + ++(vector->m_size); + + return FT_SUCCESS; +} + + +int vector_erase(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(vector_t *vector) +{ + vector->m_size = 0; +} + +const void *vector_at_c(const vector_t *vector, size_t index) +{ + if (index >= vector->m_size) + return NULL; + + return (char *)vector->m_data + index * vector->m_item_size; +} + + +void *vector_at(vector_t *vector, size_t index) +{ + if (index >= vector->m_size) + return NULL; + + return (char *)vector->m_data + index * vector->m_item_size; +} + +fort_status_t vector_swap(vector_t *cur_vec, vector_t *mv_vec, size_t pos) +{ + assert(cur_vec); + assert(mv_vec); + assert(cur_vec != mv_vec); + assert(cur_vec->m_item_size == mv_vec->m_item_size); + + size_t cur_sz = vector_size(cur_vec); + size_t mv_sz = vector_size(mv_vec); + if (mv_sz == 0) { + return FT_SUCCESS; + } + + size_t min_targ_size = pos + mv_sz; + if (cur_sz < min_targ_size) { + if (vector_reallocate_(cur_vec, min_targ_size) == -1) + return FT_ERROR; + cur_vec->m_capacity = min_targ_size; + } + + ptrdiff_t deviation = pos * cur_vec->m_item_size; + void *tmp = NULL; + size_t new_mv_sz = 0; + if (cur_sz > pos) { + new_mv_sz = MIN(cur_sz - pos, mv_sz); + tmp = F_MALLOC(cur_vec->m_item_size * new_mv_sz); + if (tmp == NULL) { + return FT_MEMORY_ERROR; + } + } + + memcpy(tmp, + (char *)cur_vec->m_data + deviation, + cur_vec->m_item_size * (cur_sz - pos)); + memcpy((char *)cur_vec->m_data + deviation, + mv_vec->m_data, + cur_vec->m_item_size * mv_sz); + memcpy(mv_vec->m_data, + tmp, + cur_vec->m_item_size * new_mv_sz); + + mv_vec->m_size = new_mv_sz; + F_FREE(tmp); + return FT_SUCCESS; +} + + + + +/******************************************************** + End of file "vector.c" + ********************************************************/ + + +/******************************************************** + Begin of file "string_buffer.c" + ********************************************************/ + +/* #include "string_buffer.h" */ /* Commented by amalgamation script */ +/* #include "options.h" */ /* Commented by amalgamation script */ +/* #include "wcwidth.h" */ /* Commented by amalgamation script */ +#include +#include +#include +/***************************************************************************** + * STRING BUFFER + * ***************************************************************************/ + + +static ptrdiff_t str_iter_width(const char *beg, const char *end) +{ + assert(end >= beg); + return (end - beg); +} + +static ptrdiff_t wcs_iter_width(const wchar_t *beg, const wchar_t *end) +{ + assert(end >= beg); + return mk_wcswidth(beg, (end - beg)); +} + + +static size_t buf_str_len(const string_buffer_t *buf) +{ + assert(buf); + if (buf->type == CharBuf) { + return strlen(buf->str.cstr); + } else { + return wcslen(buf->str.wstr); + } +} + +size_t strchr_count(const char *str, char ch) +{ + if (str == NULL) + return 0; + + size_t count = 0; + str = strchr(str, ch); + while (str) { + count++; + str++; + str = strchr(str, ch); + } + return count; +} + +size_t wstrchr_count(const wchar_t *str, wchar_t ch) +{ + if (str == NULL) + return 0; + + size_t count = 0; + str = wcschr(str, ch); + while (str) { + count++; + str++; + str = wcschr(str, ch); + } + return count; +} + +const char *str_n_substring_beg(const char *str, char ch_separator, size_t n) +{ + if (str == NULL) + return NULL; + + if (n == 0) + return str; + + str = strchr(str, ch_separator); + --n; + while (n > 0) { + if (str == NULL) + return NULL; + --n; + str++; + str = strchr(str, ch_separator); + } + return str ? (str + 1) : NULL; +} + +const wchar_t *wstr_n_substring_beg(const wchar_t *str, wchar_t ch_separator, size_t n) +{ + if (str == NULL) + return NULL; + + if (n == 0) + return str; + + str = wcschr(str, ch_separator); + --n; + while (n > 0) { + if (str == NULL) + return NULL; + --n; + str++; + str = wcschr(str, ch_separator); + } + return str ? (str + 1) : NULL; +} + +void str_n_substring(const char *str, char ch_separator, size_t n, const char **begin, const char **end) +{ + const char *beg = str_n_substring_beg(str, ch_separator, n); + if (beg == NULL) { + *begin = NULL; + *end = NULL; + return; + } + + const char *en = strchr(beg, ch_separator); + if (en == NULL) { + en = str + strlen(str); + } + + *begin = beg; + *end = en; + return; +} + +void wstr_n_substring(const wchar_t *str, wchar_t ch_separator, size_t n, const wchar_t **begin, const wchar_t **end) +{ + const wchar_t *beg = wstr_n_substring_beg(str, ch_separator, n); + if (beg == NULL) { + *begin = NULL; + *end = NULL; + return; + } + + const wchar_t *en = wcschr(beg, ch_separator); + if (en == NULL) { + en = str + wcslen(str); + } + + *begin = beg; + *end = en; + return; +} + + +string_buffer_t *create_string_buffer(size_t number_of_chars, enum str_buf_type type) +{ + size_t sz = (number_of_chars) * (type == CharBuf ? sizeof(char) : sizeof(wchar_t)); + string_buffer_t *result = (string_buffer_t *)F_MALLOC(sizeof(string_buffer_t)); + if (result == NULL) + return NULL; + result->str.data = F_MALLOC(sz); + if (result->str.data == NULL) { + F_FREE(result); + return NULL; + } + result->data_sz = sz; + result->type = type; + + if (sz && type == CharBuf) { + result->str.cstr[0] = '\0'; + } else if (sz && type == WCharBuf) { + result->str.wstr[0] = L'\0'; + } + + return result; +} + +void destroy_string_buffer(string_buffer_t *buffer) +{ + if (buffer == NULL) + return; + F_FREE(buffer->str.data); + buffer->str.data = NULL; + F_FREE(buffer); +} + +fort_status_t realloc_string_buffer_without_copy(string_buffer_t *buffer) +{ + assert(buffer); + char *new_str = (char *)F_MALLOC(buffer->data_sz * 2); + if (new_str == NULL) { + return FT_MEMORY_ERROR; + } + F_FREE(buffer->str.data); + buffer->str.data = new_str; + buffer->data_sz *= 2; + return FT_SUCCESS; +} + +fort_status_t fill_buffer_from_string(string_buffer_t *buffer, const char *str) +{ + assert(buffer); + assert(str); + + size_t sz = strlen(str); + char *copy = F_STRDUP(str); + if (copy == NULL) + return FT_MEMORY_ERROR; + + while (sz >= string_buffer_capacity(buffer)) { + int status = realloc_string_buffer_without_copy(buffer); + if (!FT_IS_SUCCESS(status)) { + return status; + } + } + F_FREE(buffer->str.data); + buffer->str.cstr = copy; + buffer->type = CharBuf; + + return FT_SUCCESS; +} + +fort_status_t fill_buffer_from_wstring(string_buffer_t *buffer, const wchar_t *str) +{ + assert(buffer); + assert(str); + + size_t sz = wcslen(str); + wchar_t *copy = F_WCSDUP(str); + if (copy == NULL) + return FT_MEMORY_ERROR; + + while (sz >= string_buffer_capacity(buffer)) { + int status = realloc_string_buffer_without_copy(buffer); + if (!FT_IS_SUCCESS(status)) { + return status; + } + } + F_FREE(buffer->str.data); + buffer->str.wstr = copy; + buffer->type = WCharBuf; + + return FT_SUCCESS; +} + + + +size_t buffer_text_height(string_buffer_t *buffer) +{ + if (buffer == NULL || buffer->str.data == NULL || buf_str_len(buffer) == 0) { + return 0; + } + if (buffer->type == CharBuf) + return 1 + strchr_count(buffer->str.cstr, '\n'); + else + return 1 + wstrchr_count(buffer->str.wstr, L'\n'); +} + +size_t buffer_text_width(string_buffer_t *buffer) +{ + size_t max_length = 0; + int n = 0; + if (buffer->type == CharBuf) { + while (1) { + const char *beg = NULL; + const char *end = NULL; + str_n_substring(buffer->str.cstr, '\n', n, &beg, &end); + if (beg == NULL || end == NULL) + return max_length; + + max_length = MAX(max_length, (size_t)(end - beg)); + ++n; + } + } else { + while (1) { + const wchar_t *beg = NULL; + const wchar_t *end = NULL; + wstr_n_substring(buffer->str.wstr, L'\n', n, &beg, &end); + if (beg == NULL || end == NULL) + return max_length; + + int line_width = mk_wcswidth(beg, end - beg); + if (line_width < 0) /* For safety */ + line_width = 0; + max_length = MAX(max_length, (size_t)line_width); + + ++n; + } + } +} + + + +int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t buf_len, const context_t *context) +{ +#define CHAR_TYPE char +#define NULL_CHAR '\0' +#define NEWLINE_CHAR '\n' +#define SPACE_CHAR " " +#define SNPRINTF_FMT_STR "%*s" +#define SNPRINTF snprintf +#define BUFFER_STR str.cstr +//#define SNPRINT_N_CHARS snprint_n_chars +#define SNPRINT_N_STRINGS snprint_n_strings +#define STR_N_SUBSTRING str_n_substring +#define STR_ITER_WIDTH str_iter_width + + if (buffer == NULL || buffer->str.data == NULL + || buffer_row >= buffer_text_height(buffer) || buf_len == 0) { + return -1; + } + + size_t content_width = buffer_text_width(buffer); + if ((buf_len - 1) < content_width) + return -1; + + size_t left = 0; + size_t right = 0; + + switch (get_cell_opt_value_hierarcial(context->table_options, context->row, context->column, FT_COPT_TEXT_ALIGN)) { + case FT_ALIGNED_LEFT: + left = 0; + right = (buf_len - 1) - content_width; + break; + case FT_ALIGNED_CENTER: + left = ((buf_len - 1) - content_width) / 2; + right = ((buf_len - 1) - content_width) - left; + break; + case FT_ALIGNED_RIGHT: + left = (buf_len - 1) - content_width; + right = 0; + break; + default: + assert(0); + break; + } + + int written = 0; + int tmp = 0; + const CHAR_TYPE *beg = NULL; + const CHAR_TYPE *end = NULL; + CHAR_TYPE old_value; + + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, left, SPACE_CHAR)); + + STR_N_SUBSTRING(buffer->BUFFER_STR, NEWLINE_CHAR, buffer_row, &beg, &end); + if (beg == NULL || end == NULL) + return -1; + old_value = *end; + *(CHAR_TYPE *)end = NULL_CHAR; + + ptrdiff_t str_it_width = STR_ITER_WIDTH(beg, end); + if (str_it_width < 0 || content_width < (size_t)str_it_width) + return - 1; + + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + *(CHAR_TYPE *)end = old_value; + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, right, SPACE_CHAR)); + return written; + +clear: + return -1; + +#undef CHAR_TYPE +#undef NULL_CHAR +#undef NEWLINE_CHAR +#undef SPACE_CHAR +#undef SNPRINTF_FMT_STR +#undef SNPRINTF +#undef BUFFER_STR +//#undef SNPRINT_N_CHARS +#undef SNPRINT_N_STRINGS +#undef STR_N_SUBSTRING +#undef STR_ITER_WIDTH +} + + +int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t buf_len, const context_t *context) +{ +#define CHAR_TYPE wchar_t +#define NULL_CHAR L'\0' +#define NEWLINE_CHAR L'\n' +#define SPACE_CHAR " " +#define SNPRINTF_FMT_STR L"%*ls" +#define SNPRINTF swprintf +#define BUFFER_STR str.wstr +//#define SNPRINT_N_CHARS wsnprint_n_chars +#define SNPRINT_N_STRINGS wsnprint_n_string +#define STR_N_SUBSTRING wstr_n_substring +#define STR_ITER_WIDTH wcs_iter_width + + if (buffer == NULL || buffer->str.data == NULL + || buffer_row >= buffer_text_height(buffer) || buf_len == 0) { + return -1; + } + + size_t content_width = buffer_text_width(buffer); + if ((buf_len - 1) < content_width) + return -1; + + size_t left = 0; + size_t right = 0; + + switch (get_cell_opt_value_hierarcial(context->table_options, context->row, context->column, FT_COPT_TEXT_ALIGN)) { + case FT_ALIGNED_LEFT: + left = 0; + right = (buf_len - 1) - content_width; + break; + case FT_ALIGNED_CENTER: + left = ((buf_len - 1) - content_width) / 2; + right = ((buf_len - 1) - content_width) - left; + break; + case FT_ALIGNED_RIGHT: + left = (buf_len - 1) - content_width; + right = 0; + break; + default: + assert(0); + break; + } + + int written = 0; + int tmp = 0; + const CHAR_TYPE *beg = NULL; + const CHAR_TYPE *end = NULL; + CHAR_TYPE old_value; + + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, left, SPACE_CHAR)); + + STR_N_SUBSTRING(buffer->BUFFER_STR, NEWLINE_CHAR, buffer_row, &beg, &end); + if (beg == NULL || end == NULL) + return -1; + old_value = *end; + *(CHAR_TYPE *)end = NULL_CHAR; + + ptrdiff_t str_it_width = STR_ITER_WIDTH(beg, end); + if (str_it_width < 0 || content_width < (size_t)str_it_width) + return - 1; + + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + *(CHAR_TYPE *)end = old_value; + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, right, SPACE_CHAR)); + return written; + +clear: + return -1; + +#undef CHAR_TYPE +#undef NULL_CHAR +#undef NEWLINE_CHAR +#undef SPACE_CHAR +#undef SNPRINTF_FMT_STR +#undef SNPRINTF +#undef BUFFER_STR +//#undef SNPRINT_N_CHARS +#undef SNPRINT_N_STRINGS +#undef STR_N_SUBSTRING +#undef STR_ITER_WIDTH +} + +size_t string_buffer_capacity(const string_buffer_t *buffer) +{ + assert(buffer); + if (buffer->type == CharBuf) + return buffer->data_sz; + else + return buffer->data_sz / sizeof(wchar_t); +} + +void *buffer_get_data(string_buffer_t *buffer) +{ + assert(buffer); + return buffer->str.data; +} + + +/******************************************************** + End of file "string_buffer.c" + ********************************************************/ + + +/******************************************************** + Begin of file "fort_utils.c" + ********************************************************/ + +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ +#ifdef FT_HAVE_WCHAR +#include +#endif + + + +/***************************************************************************** + * LIBFORT helpers + *****************************************************************************/ + +#ifndef FT_MICROSOFT_COMPILER +void *(*fort_malloc)(size_t size) = &malloc; +void (*fort_free)(void *ptr) = &free; +void *(*fort_calloc)(size_t nmemb, size_t size) = &calloc; +void *(*fort_realloc)(void *ptr, size_t size) = &realloc; +#else +static void *local_malloc(size_t size) +{ + return malloc(size); +} + +static void local_free(void *ptr) +{ + free(ptr); +} + +static void *local_calloc(size_t nmemb, size_t size) +{ + return calloc(nmemb, size); +} + +static void *local_realloc(void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +void *(*fort_malloc)(size_t size) = &local_malloc; +void (*fort_free)(void *ptr) = &local_free; +void *(*fort_calloc)(size_t nmemb, size_t size) = &local_calloc; +void *(*fort_realloc)(void *ptr, size_t size) = &local_realloc; +#endif + +static void *custom_fort_calloc(size_t nmemb, size_t size) +{ + size_t total_size = nmemb * size; + void *result = F_MALLOC(total_size); + if (result != NULL) + memset(result, 0, total_size); + return result; +} + +static void *custom_fort_realloc(void *ptr, size_t size) +{ + if (ptr == NULL) + return F_MALLOC(size); + if (size == 0) { + F_FREE(ptr); + return NULL; + } + + void *new_chunk = F_MALLOC(size); + if (new_chunk == NULL) + return NULL; + + /* + * In theory we should copy MIN(size, size allocated for ptr) bytes, + * but this is rather dummy implementation so we don't care about it + */ + memcpy(new_chunk, ptr, size); + F_FREE(ptr); + return new_chunk; +} + +void set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)) +{ + assert((f_malloc == NULL && f_free == NULL) /* Use std functions */ + || (f_malloc != NULL && f_free != NULL) /* Use custom functions */); + + if (f_malloc == NULL && f_free == NULL) { +#ifndef FT_MICROSOFT_COMPILER + fort_malloc = &malloc; + fort_free = &free; + fort_calloc = &calloc; + fort_realloc = &realloc; +#else + fort_malloc = &local_malloc; + fort_free = &local_free; + fort_calloc = &local_calloc; + fort_realloc = &local_realloc; +#endif + } else { + fort_malloc = f_malloc; + fort_free = f_free; + fort_calloc = &custom_fort_calloc; + fort_realloc = &custom_fort_realloc; + } + +} + + +char *fort_strdup(const char *str) +{ + if (str == NULL) + return NULL; + + size_t sz = strlen(str); + char *str_copy = (char *)F_MALLOC((sz + 1) * sizeof(char)); + if (str_copy == NULL) + return NULL; + + strcpy(str_copy, str); + return str_copy; +} + +wchar_t *fort_wcsdup(const wchar_t *str) +{ + if (str == NULL) + return NULL; + + size_t sz = wcslen(str); + wchar_t *str_copy = (wchar_t *)F_MALLOC((sz + 1) * sizeof(wchar_t)); + if (str_copy == NULL) + return NULL; + + wcscpy(str_copy, str); + return str_copy; +} + +size_t number_of_columns_in_format_string(const char *fmt) +{ + int separator_counter = 0; + const char *pos = fmt; + while (1) { + pos = strchr(pos, FORT_COL_SEPARATOR); + if (pos == NULL) + break; + + separator_counter++; + ++pos; + } + return separator_counter + 1; +} + +size_t number_of_columns_in_format_wstring(const wchar_t *fmt) +{ + int separator_counter = 0; + const wchar_t *pos = fmt; + while (1) { + pos = wcschr(pos, FORT_COL_SEPARATOR); + if (pos == NULL) + break; + + separator_counter++; + ++pos; + } + return separator_counter + 1; +} + + +//int snprint_n_chars(char *buf, size_t length, size_t n, char ch) +//{ +// if (length <= n) +// return -1; + +// if (n == 0) +// return 0; + +// /* To ensure valid return value it is safely not print such big strings */ +// if (n > INT_MAX) +// return -1; + +// int status = snprintf(buf, length, "%0*d", (int)n, 0); +// if (status < 0) +// return status; + +// size_t i = 0; +// for (i = 0; i < n; ++i) { +// *buf = ch; +// buf++; +// } +// return (int)n; +//} + +int snprint_n_strings(char *buf, size_t length, size_t n, const char *str) +{ + size_t str_len = strlen(str); + if (length <= n * str_len) + return -1; + + if (n == 0) + return 0; + + /* To ensure valid return value it is safely not print such big strings */ + if (n * str_len > INT_MAX) + return -1; + + int status = snprintf(buf, length, "%0*d", (int)(n * str_len), 0); + if (status < 0) + return status; + + size_t i = 0; + for (i = 0; i < n; ++i) { + const char *str_p = str; + while (*str_p) + *(buf++) = *(str_p++); + } + return (int)(n * str_len); +} + + +//int wsnprint_n_chars(wchar_t *buf, size_t length, size_t n, wchar_t ch) +//{ +// if (length <= n) +// return -1; + +// if (n == 0) +// return 0; + +// /* To ensure valid return value it is safely not print such big strings */ +// if (n > INT_MAX) +// return -1; + +// int status = swprintf(buf, length, L"%0*d", (int)n, 0); +// if (status < 0) +// return status; + +// size_t i = 0; +// for (i = 0; i < n; ++i) { +// *buf = ch; +// buf++; +// } +// return (int)n; +//} + +int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str) +{ + size_t str_len = strlen(str); + + /* This function doesn't work properly with multibyte characters + * so it is better return an error in this case + */ + if (str_len > 1) + return -1; + + if (length <= n * str_len) + return -1; + + if (n == 0) + return 0; + + + + /* To ensure valid return value it is safely not print such big strings */ + if (n * str_len > INT_MAX) + return -1; + + int status = swprintf(buf, length, L"%0*d", (int)(n * str_len), 0); + if (status < 0) + return status; + + size_t i = 0; + for (i = 0; i < n; ++i) { + const char *str_p = str; + while (*str_p) + *(buf++) = (wchar_t) * (str_p++); + } + return (int)(n * str_len); +} + + +/******************************************************** + End of file "fort_utils.c" ********************************************************/ diff --git a/src/cell.h b/src/cell.h index 42216f6..7934571 100644 --- a/src/cell.h +++ b/src/cell.h @@ -1,7 +1,7 @@ #ifndef CELL_H #define CELL_H -#include "fort_impl.h" +#include "fort_utils.h" diff --git a/src/fort.c b/src/fort.c deleted file mode 100644 index c90424f..0000000 --- a/src/fort.c +++ /dev/null @@ -1,983 +0,0 @@ -/* -libfort - -MIT License - -Copyright (c) 2017 - 2018 Seleznev Anton - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include -#include -#include -#include "fort.h" -#include -#include -#include -#include - -#include "vector.h" -#include "fort_impl.h" -#include "string_buffer.h" -#include "table.h" -#include "row.h" -#include "options.h" - - - - -/***************************************************************************** - * LIBFORT - * ***************************************************************************/ - -ft_table_t *ft_create_table(void) -{ - ft_table_t *result = (ft_table_t *)F_CALLOC(1, sizeof(ft_table_t)); - if (result == NULL) - return NULL; - - result->rows = create_vector(sizeof(fort_row_t *), DEFAULT_VECTOR_CAPACITY); - if (result->rows == NULL) { - 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; - result->cur_col = 0; - return result; -} - - -void ft_destroy_table(ft_table_t *table) -{ - size_t i = 0; - - if (table == NULL) - return; - - if (table->rows) { - size_t row_n = vector_size(table->rows); - for (i = 0; i < row_n; ++i) { - destroy_row(*(fort_row_t **)vector_at(table->rows, i)); - } - destroy_vector(table->rows); - } - if (table->separators) { - size_t row_n = vector_size(table->separators); - for (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); -} - -void ft_ln(ft_table_t *table) -{ - assert(table); - table->cur_col = 0; - table->cur_row++; -} - -size_t ft_cur_row(ft_table_t *table) -{ - assert(table); - return table->cur_row; -} - -size_t ft_cur_col(ft_table_t *table) -{ - assert(table); - return table->cur_col; -} - -void ft_set_cur_cell(ft_table_t *table, size_t row, size_t col) -{ - assert(table); - table->cur_row = row; - table->cur_col = col; -} - - -static int ft_row_printf_impl(ft_table_t *table, size_t row, const char *fmt, va_list *va) -{ -#define CREATE_ROW_FROM_FMT_STRING create_row_from_fmt_string - size_t i = 0; - size_t new_cols = 0; - - if (table == NULL) - return -1; - - fort_row_t *new_row = CREATE_ROW_FROM_FMT_STRING(fmt, va); - - if (new_row == NULL) { - return -1; - } - - fort_row_t **cur_row_p = NULL; - size_t sz = vector_size(table->rows); - if (row >= sz) { - size_t push_n = row - sz + 1; - for (i = 0; i < push_n; ++i) { - fort_row_t *padding_row = create_row(); - if (padding_row == NULL) - goto clear; - - if (FT_IS_ERROR(vector_push(table->rows, &padding_row))) { - destroy_row(padding_row); - goto clear; - } - } - } - /* todo: clearing pushed items in case of error ?? */ - - new_cols = columns_in_row(new_row); - cur_row_p = (fort_row_t **)vector_at(table->rows, row); - swap_row(*cur_row_p, new_row, table->cur_col); - - table->cur_col += new_cols; - destroy_row(new_row); - return new_cols; - -clear: - destroy_row(new_row); - return -1; -#undef CREATE_ROW_FROM_FMT_STRING -} - -#ifdef FT_HAVE_WCHAR -static int ft_row_wprintf_impl(ft_table_t *table, size_t row, const wchar_t *fmt, va_list *va) -{ -#define CREATE_ROW_FROM_FMT_STRING create_row_from_fmt_wstring - size_t i = 0; - size_t new_cols = 0; - - if (table == NULL) - return -1; - - fort_row_t *new_row = CREATE_ROW_FROM_FMT_STRING(fmt, va); - - if (new_row == NULL) { - return -1; - } - - fort_row_t **cur_row_p = NULL; - size_t sz = vector_size(table->rows); - if (row >= sz) { - size_t push_n = row - sz + 1; - for (i = 0; i < push_n; ++i) { - fort_row_t *padding_row = create_row(); - if (padding_row == NULL) - goto clear; - - if (FT_IS_ERROR(vector_push(table->rows, &padding_row))) { - destroy_row(padding_row); - goto clear; - } - } - } - /* todo: clearing pushed items in case of error ?? */ - - new_cols = columns_in_row(new_row); - cur_row_p = (fort_row_t **)vector_at(table->rows, row); - swap_row(*cur_row_p, new_row, table->cur_col); - - table->cur_col += new_cols; - destroy_row(new_row); - return new_cols; - -clear: - destroy_row(new_row); - return -1; -#undef CREATE_ROW_FROM_FMT_STRING -} -#endif - -#if defined(FT_CLANG_COMPILER) || defined(FT_GCC_COMPILER) -#define FT_PRINTF ft_printf -#define FT_PRINTF_LN ft_printf_ln -#else -#define FT_PRINTF ft_printf_impl -#define FT_PRINTF_LN ft_printf_ln_impl -#endif - - - -int FT_PRINTF(ft_table_t *table, const char *fmt, ...) -{ - assert(table); - va_list va; - va_start(va, fmt); - int result = ft_row_printf_impl(table, table->cur_row, fmt, &va); - va_end(va); - return result; -} - -int FT_PRINTF_LN(ft_table_t *table, const char *fmt, ...) -{ - assert(table); - va_list va; - va_start(va, fmt); - int result = ft_row_printf_impl(table, table->cur_row, fmt, &va); - if (result >= 0) { - ft_ln(table); - } - va_end(va); - return result; -} - -#undef FT_PRINTF -#undef FT_PRINTF_LN -#undef FT_HDR_PRINTF -#undef FT_HDR_PRINTF_LN - -#ifdef FT_HAVE_WCHAR -int ft_wprintf(ft_table_t *table, const wchar_t *fmt, ...) -{ - assert(table); - va_list va; - va_start(va, fmt); - int result = ft_row_wprintf_impl(table, table->cur_row, fmt, &va); - va_end(va); - return result; -} - -int ft_wprintf_ln(ft_table_t *table, const wchar_t *fmt, ...) -{ - assert(table); - va_list va; - va_start(va, fmt); - int result = ft_row_wprintf_impl(table, table->cur_row, fmt, &va); - if (result >= 0) { - ft_ln(table); - } - va_end(va); - return result; -} - -#endif - - -static int ft_write_impl(ft_table_t *table, const char *cell_content) -{ - assert(table); - string_buffer_t *str_buffer = get_cur_str_buffer_and_create_if_not_exists(table); - if (str_buffer == NULL) - return FT_ERROR; - - int status = fill_buffer_from_string(str_buffer, cell_content); - if (FT_IS_SUCCESS(status)) { - table->cur_col++; - } - return status; -} - - -#ifdef FT_HAVE_WCHAR - -static int ft_wwrite_impl(ft_table_t *table, const wchar_t *cell_content) -{ - assert(table); - string_buffer_t *str_buffer = get_cur_str_buffer_and_create_if_not_exists(table); - if (str_buffer == NULL) - return FT_ERROR; - - int status = fill_buffer_from_wstring(str_buffer, cell_content); - if (FT_IS_SUCCESS(status)) { - table->cur_col++; - } - return status; -} - -#endif - - -int ft_nwrite(ft_table_t *table, size_t count, const char *cell_content, ...) -{ - size_t i = 0; - assert(table); - int status = ft_write_impl(table, cell_content); - if (FT_IS_ERROR(status)) - return status; - - va_list va; - va_start(va, cell_content); - --count; - for (i = 0; i < count; ++i) { - const char *cell = va_arg(va, const char *); - status = ft_write_impl(table, cell); - if (FT_IS_ERROR(status)) - return status; - } - va_end(va); - return status; -} - -int ft_nwrite_ln(ft_table_t *table, size_t count, const char *cell_content, ...) -{ - size_t i = 0; - assert(table); - int status = ft_write_impl(table, cell_content); - if (FT_IS_ERROR(status)) - return status; - - va_list va; - va_start(va, cell_content); - --count; - for (i = 0; i < count; ++i) { - const char *cell = va_arg(va, const char *); - status = ft_write_impl(table, cell); - if (FT_IS_ERROR(status)) { - va_end(va); - return status; - } - } - va_end(va); - - ft_ln(table); - return status; -} - -#ifdef FT_HAVE_WCHAR - -int ft_nwwrite(ft_table_t *table, size_t n, const wchar_t *cell_content, ...) -{ - size_t i = 0; - assert(table); - int status = ft_wwrite_impl(table, cell_content); - if (FT_IS_ERROR(status)) - return status; - - va_list va; - va_start(va, cell_content); - --n; - for (i = 0; i < n; ++i) { - const wchar_t *cell = va_arg(va, const wchar_t *); - status = ft_wwrite_impl(table, cell); - if (FT_IS_ERROR(status)) - return status; - } - va_end(va); - return status; -} - -int ft_nwwrite_ln(ft_table_t *table, size_t n, const wchar_t *cell_content, ...) -{ - size_t i = 0; - assert(table); - int status = ft_wwrite_impl(table, cell_content); - if (FT_IS_ERROR(status)) - return status; - - va_list va; - va_start(va, cell_content); - --n; - for (i = 0; i < n; ++i) { - const wchar_t *cell = va_arg(va, const wchar_t *); - status = ft_wwrite_impl(table, cell); - if (FT_IS_ERROR(status)) { - va_end(va); - return status; - } - } - va_end(va); - - ft_ln(table); - return status; -} -#endif - - -int ft_row_write(ft_table_t *table, size_t cols, const char *cells[]) -{ - size_t i = 0; - assert(table); - for (i = 0; i < cols; ++i) { - int status = ft_write_impl(table, cells[i]); - if (FT_IS_ERROR(status)) { - /* todo: maybe current pos in case of error should be equal to the one before function call? */ - return status; - } - } - return FT_SUCCESS; -} - -int ft_row_write_ln(ft_table_t *table, size_t cols, const char *cells[]) -{ - assert(table); - int status = ft_row_write(table, cols, cells); - if (FT_IS_SUCCESS(status)) { - ft_ln(table); - } - return status; -} - -#ifdef FT_HAVE_WCHAR -int ft_row_wwrite(ft_table_t *table, size_t cols, const wchar_t *cells[]) -{ - size_t i = 0; - assert(table); - for (i = 0; i < cols; ++i) { - int status = ft_wwrite_impl(table, cells[i]); - if (FT_IS_ERROR(status)) { - /* todo: maybe current pos in case of error should be equal to the one before function call? */ - return status; - } - } - return FT_SUCCESS; -} - -int ft_row_wwrite_ln(ft_table_t *table, size_t cols, const wchar_t *cells[]) -{ - assert(table); - int status = ft_row_wwrite(table, cols, cells); - if (FT_IS_SUCCESS(status)) { - ft_ln(table); - } - return status; -} -#endif - - - -int ft_table_write(ft_table_t *table, size_t rows, size_t cols, const char *table_cells[]) -{ - size_t i = 0; - assert(table); - for (i = 0; i < rows; ++i) { - int status = ft_row_write(table, cols, (const char **)&table_cells[i * cols]); - if (FT_IS_ERROR(status)) { - /* todo: maybe current pos in case of error should be equal to the one before function call? */ - return status; - } - if (i != rows - 1) - ft_ln(table); - } - return FT_SUCCESS; -} - -int ft_table_write_ln(ft_table_t *table, size_t rows, size_t cols, const char *table_cells[]) -{ - assert(table); - int status = ft_table_write(table, rows, cols, table_cells); - if (FT_IS_SUCCESS(status)) { - ft_ln(table); - } - return status; -} - - -#ifdef FT_HAVE_WCHAR -int ft_table_wwrite(ft_table_t *table, size_t rows, size_t cols, const wchar_t *table_cells[]) -{ - size_t i = 0; - assert(table); - for (i = 0; i < rows; ++i) { - int status = ft_row_wwrite(table, cols, (const wchar_t **)&table_cells[i * cols]); - if (FT_IS_ERROR(status)) { - /* todo: maybe current pos in case of error should be equal to the one before function call? */ - return status; - } - if (i != rows - 1) - ft_ln(table); - } - return FT_SUCCESS; -} - -int ft_table_wwrite_ln(ft_table_t *table, size_t rows, size_t cols, const wchar_t *table_cells[]) -{ - assert(table); - int status = ft_table_wwrite(table, rows, cols, table_cells); - if (FT_IS_SUCCESS(status)) { - ft_ln(table); - } - return status; -} -#endif - - - - - - -/***************************************************************************** - * TABLE - * ***************************************************************************/ - - - -const char *ft_to_string(const ft_table_t *table) -{ - typedef char char_type; - const char_type *empty_string = ""; - const enum str_buf_type buf_type = CharBuf; - const char *space_char = " "; - const char *new_line_char = "\n"; -#define cur_F_STRDUP F_STRDUP - int (*snprintf_row_)(const fort_row_t *, char *, size_t, size_t *, size_t, size_t, const context_t *) = snprintf_row; - int (*print_row_separator_)(char *, size_t, - const size_t *, size_t, - const fort_row_t *, const fort_row_t *, - enum HorSeparatorPos, const separator_t *, - const context_t *) = print_row_separator; -// int (*snprint_n_chars_)(char *, size_t, size_t, char) = snprint_n_chars; - int (*snprint_n_strings_)(char *, size_t, size_t, const char *) = snprint_n_strings; - assert(table); - - /* Determing size of table string representation */ - size_t height = 0; - size_t width = 0; - int status = table_geometry(table, &height, &width); - if (FT_IS_ERROR(status)) { - return NULL; - } - size_t sz = height * width + 1; - - /* Allocate string buffer for string representation */ - if (table->conv_buffer == NULL) { - ((ft_table_t *)table)->conv_buffer = create_string_buffer(sz, buf_type); - if (table->conv_buffer == NULL) - return NULL; - } - while (string_buffer_capacity(table->conv_buffer) < sz) { - if (FT_IS_ERROR(realloc_string_buffer_without_copy(table->conv_buffer))) { - return NULL; - } - } - char_type *buffer = (char_type *)buffer_get_data(table->conv_buffer); - - - size_t cols = 0; - size_t rows = 0; - size_t *col_width_arr = NULL; - size_t *row_height_arr = NULL; - status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); - if (FT_IS_ERROR(status)) - return NULL; - - if (rows == 0) - return cur_F_STRDUP(empty_string); - - int written = 0; - int tmp = 0; - size_t i = 0; - context_t context; - context.table_options = (table->options ? table->options : &g_table_options); - fort_row_t *prev_row = NULL; - fort_row_t *cur_row = NULL; - separator_t *cur_sep = NULL; - size_t sep_size = vector_size(table->separators); - - /* Print top margin */ - for (i = 0; i < context.table_options->entire_table_options.top_margin; ++i) { - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char)); - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char)); - } - - 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; - context.row = i; - CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, separatorPos, cur_sep, &context)); - CHCK_RSLT_ADD_TO_WRITTEN(snprintf_row_(cur_row, buffer + written, sz - written, col_width_arr, cols, row_height_arr[i], &context)); - prev_row = cur_row; - } - cur_row = NULL; - cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL; - CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, BottomSeparator, cur_sep, &context)); - - /* Print bottom margin */ - for (i = 0; i < context.table_options->entire_table_options.bottom_margin; ++i) { - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char)); - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char)); - } - - - F_FREE(col_width_arr); - F_FREE(row_height_arr); - return buffer; - -clear: - F_FREE(col_width_arr); - F_FREE(row_height_arr); -// F_FREE(buffer); - return NULL; -#undef cur_F_STRDUP -} - - -#ifdef FT_HAVE_WCHAR - -const wchar_t *ft_to_wstring(const ft_table_t *table) -{ - typedef wchar_t char_type; - const char_type *empty_string = L""; - const enum str_buf_type buf_type = WCharBuf; - const char *space_char = " "; - const char *new_line_char = "\n"; -#define cur_F_STRDUP F_WCSDUP - int (*snprintf_row_)(const fort_row_t *, wchar_t *, size_t, size_t *, size_t, size_t, const context_t *) = wsnprintf_row; - int (*print_row_separator_)(wchar_t *, size_t, - const size_t *, size_t, - const fort_row_t *, const fort_row_t *, - enum HorSeparatorPos, const separator_t *, - const context_t *) = wprint_row_separator; -// int (*snprint_n_chars_)(wchar_t *, size_t, size_t, wchar_t) = wsnprint_n_chars; - int (*snprint_n_strings_)(wchar_t *, size_t, size_t, const char *) = wsnprint_n_string; - - - assert(table); - - /* Determing size of table string representation */ - size_t height = 0; - size_t width = 0; - int status = table_geometry(table, &height, &width); - if (FT_IS_ERROR(status)) { - return NULL; - } - size_t sz = height * width + 1; - - /* Allocate string buffer for string representation */ - if (table->conv_buffer == NULL) { - ((ft_table_t *)table)->conv_buffer = create_string_buffer(sz, buf_type); - if (table->conv_buffer == NULL) - return NULL; - } - while (string_buffer_capacity(table->conv_buffer) < sz) { - if (FT_IS_ERROR(realloc_string_buffer_without_copy(table->conv_buffer))) { - return NULL; - } - } - char_type *buffer = (char_type *)buffer_get_data(table->conv_buffer); - - - size_t cols = 0; - size_t rows = 0; - size_t *col_width_arr = NULL; - size_t *row_height_arr = NULL; - status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); - - if (rows == 0) - return cur_F_STRDUP(empty_string); - - if (FT_IS_ERROR(status)) - return NULL; - - int written = 0; - int tmp = 0; - size_t i = 0; - context_t context; - context.table_options = (table->options ? table->options : &g_table_options); - fort_row_t *prev_row = NULL; - fort_row_t *cur_row = NULL; - separator_t *cur_sep = NULL; - size_t sep_size = vector_size(table->separators); - - /* Print top margin */ - for (i = 0; i < context.table_options->entire_table_options.top_margin; ++i) { - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char)); - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char)); - } - - 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; - context.row = i; - CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, separatorPos, cur_sep, &context)); - CHCK_RSLT_ADD_TO_WRITTEN(snprintf_row_(cur_row, buffer + written, sz - written, col_width_arr, cols, row_height_arr[i], &context)); - prev_row = cur_row; - } - cur_row = NULL; - cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL; - CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, BottomSeparator, cur_sep, &context)); - - /* Print bottom margin */ - for (i = 0; i < context.table_options->entire_table_options.bottom_margin; ++i) { - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char)); - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char)); - } - - F_FREE(col_width_arr); - F_FREE(row_height_arr); - return buffer; - -clear: - F_FREE(col_width_arr); - F_FREE(row_height_arr); -// F_FREE(buffer); - return NULL; -#undef cur_F_STRDUP -} - -#endif - - -/* - * TMP - */ -//static int dummy_function(void) -//#if defined(FT_CLANG_COMPILER) || defined(FT_GCC_COMPILER) -//__attribute__ ((unused)) -//#endif -//; - -//static int dummy_function(void) -//{ -// if (0) { -// vector_t *v = create_vector(1, DEFAULT_VECTOR_CAPACITY); -// vector_clear(v); -// vector_erase(v, 0); -// vector_index_of(v, NULL); -// vector_capacity(v); -// } -// return 0; -//} - - - - -int ft_add_separator(ft_table_t *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 FT_MEMORY_ERROR; - int status = vector_push(table->separators, &sep_p); - if (FT_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 FT_ERROR; - return FT_SUCCESS; -} - - - - -/* ******************************************************************************* */ - - -struct ft_border_style *FT_BASIC_STYLE = (struct ft_border_style *) &FORT_BASIC_STYLE; -struct ft_border_style *FT_SIMPLE_STYLE = (struct ft_border_style *) &FORT_SIMPLE_STYLE; -struct ft_border_style *FT_PLAIN_STYLE = (struct ft_border_style *) &FORT_PLAIN_STYLE; -struct ft_border_style *FT_DOT_STYLE = (struct ft_border_style *) &FORT_DOT_STYLE; -struct ft_border_style *FT_EMPTY_STYLE = (struct ft_border_style *) &FORT_EMPTY_STYLE; -struct ft_border_style *FT_SOLID_STYLE = (struct ft_border_style *) &FORT_SOLID_STYLE; -struct ft_border_style *FT_SOLID_ROUND_STYLE = (struct ft_border_style *) &FORT_SOLID_ROUND_STYLE; -struct ft_border_style *FT_DOUBLE_STYLE = (struct ft_border_style *) &FORT_DOUBLE_STYLE; -struct ft_border_style *FT_DOUBLE2_STYLE = (struct ft_border_style *) &FORT_DOUBLE2_STYLE; -struct ft_border_style *FT_BOLD_STYLE = (struct ft_border_style *) &FORT_BOLD_STYLE; -struct ft_border_style *FT_BOLD2_STYLE = (struct ft_border_style *) &FORT_BOLD2_STYLE; -struct ft_border_style *FT_FRAME_STYLE = (struct ft_border_style *) &FORT_FRAME_STYLE; - - - -static void set_border_options_for_options(fort_table_options_t *options, struct ft_border_style *style) -{ - if ((struct fort_border_style *)style == &FORT_BASIC_STYLE - || (struct fort_border_style *)style == &FORT_SIMPLE_STYLE - || (struct fort_border_style *)style == &FORT_DOT_STYLE - || (struct fort_border_style *)style == &FORT_PLAIN_STYLE - || (struct fort_border_style *)style == &FORT_EMPTY_STYLE - || (struct fort_border_style *)style == &FORT_SOLID_STYLE - || (struct fort_border_style *)style == &FORT_SOLID_ROUND_STYLE - || (struct fort_border_style *)style == &FORT_DOUBLE_STYLE - || (struct fort_border_style *)style == &FORT_DOUBLE2_STYLE - || (struct fort_border_style *)style == &FORT_BOLD_STYLE - || (struct fort_border_style *)style == &FORT_BOLD2_STYLE - || (struct fort_border_style *)style == &FORT_FRAME_STYLE) { - memcpy(&(options->border_style), (struct fort_border_style *)style, sizeof(struct fort_border_style)); - return; - } - - struct ft_border_chars *border_chs = &(style->border_chs); - struct ft_border_chars *header_border_chs = &(style->header_border_chs); - -#define BOR_CHARS options->border_style.border_chars -#define H_BOR_CHARS options->border_style.header_border_chars -#define SEP_CHARS options->border_style.separator_chars - - /* - BOR_CHARS[TL_bip] = BOR_CHARS[TT_bip] = BOR_CHARS[TV_bip] = BOR_CHARS[TR_bip] = border_chs->top_border_ch; - BOR_CHARS[LH_bip] = BOR_CHARS[IH_bip] = BOR_CHARS[II_bip] = BOR_CHARS[RH_bip] = border_chs->separator_ch; - BOR_CHARS[BL_bip] = BOR_CHARS[BB_bip] = BOR_CHARS[BV_bip] = BOR_CHARS[BR_bip] = border_chs->bottom_border_ch; - BOR_CHARS[LL_bip] = BOR_CHARS[IV_bip] = BOR_CHARS[RR_bip] = border_chs->side_border_ch; - - H_BOR_CHARS[TL_bip] = H_BOR_CHARS[TT_bip] = H_BOR_CHARS[TV_bip] = H_BOR_CHARS[TR_bip] = header_border_chs->top_border_ch; - H_BOR_CHARS[LH_bip] = H_BOR_CHARS[IH_bip] = H_BOR_CHARS[II_bip] = H_BOR_CHARS[RH_bip] = header_border_chs->separator_ch; - H_BOR_CHARS[BL_bip] = H_BOR_CHARS[BB_bip] = H_BOR_CHARS[BV_bip] = H_BOR_CHARS[BR_bip] = header_border_chs->bottom_border_ch; - H_BOR_CHARS[LL_bip] = H_BOR_CHARS[IV_bip] = H_BOR_CHARS[RR_bip] = header_border_chs->side_border_ch; - */ - - BOR_CHARS[TT_bip] = border_chs->top_border_ch; - BOR_CHARS[IH_bip] = border_chs->separator_ch; - BOR_CHARS[BB_bip] = border_chs->bottom_border_ch; - BOR_CHARS[LL_bip] = BOR_CHARS[IV_bip] = BOR_CHARS[RR_bip] = border_chs->side_border_ch; - - BOR_CHARS[TL_bip] = BOR_CHARS[TV_bip] = BOR_CHARS[TR_bip] = border_chs->out_intersect_ch; - BOR_CHARS[LH_bip] = BOR_CHARS[RH_bip] = border_chs->out_intersect_ch; - BOR_CHARS[BL_bip] = BOR_CHARS[BV_bip] = BOR_CHARS[BR_bip] = border_chs->out_intersect_ch; - BOR_CHARS[II_bip] = border_chs->in_intersect_ch; - -// if (border_chs->separator_ch == '\0' && border_chs->in_intersect_ch == '\0') { -// BOR_CHARS[LH_bip] = BOR_CHARS[RH_bip] = '\0'; -// } - if (strlen(border_chs->separator_ch) == 0 && strlen(border_chs->in_intersect_ch) == 0) { - BOR_CHARS[LH_bip] = BOR_CHARS[RH_bip] = "\0"; - } - - - H_BOR_CHARS[TT_bip] = header_border_chs->top_border_ch; - H_BOR_CHARS[IH_bip] = header_border_chs->separator_ch; - H_BOR_CHARS[BB_bip] = header_border_chs->bottom_border_ch; - H_BOR_CHARS[LL_bip] = H_BOR_CHARS[IV_bip] = H_BOR_CHARS[RR_bip] = header_border_chs->side_border_ch; - - H_BOR_CHARS[TL_bip] = H_BOR_CHARS[TV_bip] = H_BOR_CHARS[TR_bip] = header_border_chs->out_intersect_ch; - H_BOR_CHARS[LH_bip] = H_BOR_CHARS[RH_bip] = header_border_chs->out_intersect_ch; - H_BOR_CHARS[BL_bip] = H_BOR_CHARS[BV_bip] = H_BOR_CHARS[BR_bip] = header_border_chs->out_intersect_ch; - H_BOR_CHARS[II_bip] = header_border_chs->in_intersect_ch; - -// if (header_border_chs->separator_ch == '\0' && header_border_chs->in_intersect_ch == '\0') { -// H_BOR_CHARS[LH_bip] = H_BOR_CHARS[RH_bip] = '\0'; -// } - if (strlen(header_border_chs->separator_ch) == 0 && strlen(header_border_chs->in_intersect_ch) == 0) { - BOR_CHARS[LH_bip] = BOR_CHARS[RH_bip] = "\0"; - } - - SEP_CHARS[LH_sip] = SEP_CHARS[RH_sip] = SEP_CHARS[II_sip] = header_border_chs->out_intersect_ch; - SEP_CHARS[IH_sip] = style->hor_separator_char; - - -#undef BOR_CHARS -#undef H_BOR_CHARS -#undef SEP_CHARS -} - - -int ft_set_default_border_style(struct ft_border_style *style) -{ - set_border_options_for_options(&g_table_options, style); - return FT_SUCCESS; -} - -int ft_set_border_style(ft_table_t *table, struct ft_border_style *style) -{ - assert(table); - if (table->options == NULL) { - table->options = create_table_options(); - if (table->options == NULL) - return FT_MEMORY_ERROR; - } - set_border_options_for_options(table->options, style); - return FT_SUCCESS; -} - - - -int ft_set_cell_option(ft_table_t *table, size_t row, size_t col, uint32_t option, int value) -{ - assert(table); - - if (table->options == NULL) { - table->options = create_table_options(); - if (table->options == NULL) - return FT_MEMORY_ERROR; - } - if (table->options->cell_options == NULL) { - table->options->cell_options = create_cell_opt_container(); - if (table->options->cell_options == NULL) { - return FT_ERROR; - } - } - - if (row == FT_CUR_ROW) - row = table->cur_row; - if (row == FT_CUR_COLUMN) - col = table->cur_col; - - return set_cell_option(table->options->cell_options, row, col, option, value); -} - -int ft_set_default_cell_option(uint32_t option, int value) -{ - return set_default_cell_option(option, value); -} - - -int ft_set_default_tbl_option(uint32_t option, int value) -{ - return set_default_entire_table_option(option, value); -} - -int ft_set_tbl_option(ft_table_t *table, uint32_t option, int value) -{ - assert(table); - - if (table->options == NULL) { - table->options = create_table_options(); - if (table->options == NULL) - return FT_MEMORY_ERROR; - } - return set_entire_table_option(table->options, option, value); -} - -void ft_set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)) -{ - set_memory_funcs(f_malloc, f_free); -} - -int ft_set_cell_span(ft_table_t *table, size_t row, size_t col, size_t hor_span) -{ - assert(table); - if (hor_span < 2) - return FT_EINVAL; - - if (row == FT_CUR_ROW) - row = table->cur_row; - if (row == FT_CUR_COLUMN) - col = table->cur_col; - - fort_row_t *row_p = get_row_and_create_if_not_exists(table, row); - if (row_p == NULL) - return FT_ERROR; - - return row_set_cell_span(row_p, col, hor_span); -} diff --git a/src/fort_impl.c b/src/fort_impl.c index 83646e6..ddebd43 100644 --- a/src/fort_impl.c +++ b/src/fort_impl.c @@ -1,270 +1,983 @@ -#include "fort_impl.h" -#ifdef FT_HAVE_WCHAR +/* +libfort + +MIT License + +Copyright (c) 2017 - 2018 Seleznev Anton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include +#include +#include +#include "fort.h" +#include +#include #include -#endif +#include + +#include "vector.h" +#include "fort_utils.h" +#include "string_buffer.h" +#include "table.h" +#include "row.h" +#include "options.h" + /***************************************************************************** - * LIBFORT helpers - *****************************************************************************/ + * LIBFORT + * ***************************************************************************/ -#ifndef FT_MICROSOFT_COMPILER -void *(*fort_malloc)(size_t size) = &malloc; -void (*fort_free)(void *ptr) = &free; -void *(*fort_calloc)(size_t nmemb, size_t size) = &calloc; -void *(*fort_realloc)(void *ptr, size_t size) = &realloc; -#else -static void *local_malloc(size_t size) +ft_table_t *ft_create_table(void) { - return malloc(size); -} + ft_table_t *result = (ft_table_t *)F_CALLOC(1, sizeof(ft_table_t)); + if (result == NULL) + return NULL; -static void local_free(void *ptr) -{ - free(ptr); -} - -static void *local_calloc(size_t nmemb, size_t size) -{ - return calloc(nmemb, size); -} - -static void *local_realloc(void *ptr, size_t size) -{ - return realloc(ptr, size); -} - -void *(*fort_malloc)(size_t size) = &local_malloc; -void (*fort_free)(void *ptr) = &local_free; -void *(*fort_calloc)(size_t nmemb, size_t size) = &local_calloc; -void *(*fort_realloc)(void *ptr, size_t size) = &local_realloc; -#endif - -static void *custom_fort_calloc(size_t nmemb, size_t size) -{ - size_t total_size = nmemb * size; - void *result = F_MALLOC(total_size); - if (result != NULL) - memset(result, 0, total_size); + result->rows = create_vector(sizeof(fort_row_t *), DEFAULT_VECTOR_CAPACITY); + if (result->rows == NULL) { + 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; + result->cur_col = 0; return result; } -static void *custom_fort_realloc(void *ptr, size_t size) + +void ft_destroy_table(ft_table_t *table) { - if (ptr == NULL) - return F_MALLOC(size); - if (size == 0) { - F_FREE(ptr); - return NULL; + size_t i = 0; + + if (table == NULL) + return; + + if (table->rows) { + size_t row_n = vector_size(table->rows); + for (i = 0; i < row_n; ++i) { + destroy_row(*(fort_row_t **)vector_at(table->rows, i)); + } + destroy_vector(table->rows); + } + if (table->separators) { + size_t row_n = vector_size(table->separators); + for (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); +} + +void ft_ln(ft_table_t *table) +{ + assert(table); + table->cur_col = 0; + table->cur_row++; +} + +size_t ft_cur_row(ft_table_t *table) +{ + assert(table); + return table->cur_row; +} + +size_t ft_cur_col(ft_table_t *table) +{ + assert(table); + return table->cur_col; +} + +void ft_set_cur_cell(ft_table_t *table, size_t row, size_t col) +{ + assert(table); + table->cur_row = row; + table->cur_col = col; +} + + +static int ft_row_printf_impl(ft_table_t *table, size_t row, const char *fmt, va_list *va) +{ +#define CREATE_ROW_FROM_FMT_STRING create_row_from_fmt_string + size_t i = 0; + size_t new_cols = 0; + + if (table == NULL) + return -1; + + fort_row_t *new_row = CREATE_ROW_FROM_FMT_STRING(fmt, va); + + if (new_row == NULL) { + return -1; } - void *new_chunk = F_MALLOC(size); - if (new_chunk == NULL) + fort_row_t **cur_row_p = NULL; + size_t sz = vector_size(table->rows); + if (row >= sz) { + size_t push_n = row - sz + 1; + for (i = 0; i < push_n; ++i) { + fort_row_t *padding_row = create_row(); + if (padding_row == NULL) + goto clear; + + if (FT_IS_ERROR(vector_push(table->rows, &padding_row))) { + destroy_row(padding_row); + goto clear; + } + } + } + /* todo: clearing pushed items in case of error ?? */ + + new_cols = columns_in_row(new_row); + cur_row_p = (fort_row_t **)vector_at(table->rows, row); + swap_row(*cur_row_p, new_row, table->cur_col); + + table->cur_col += new_cols; + destroy_row(new_row); + return new_cols; + +clear: + destroy_row(new_row); + return -1; +#undef CREATE_ROW_FROM_FMT_STRING +} + +#ifdef FT_HAVE_WCHAR +static int ft_row_wprintf_impl(ft_table_t *table, size_t row, const wchar_t *fmt, va_list *va) +{ +#define CREATE_ROW_FROM_FMT_STRING create_row_from_fmt_wstring + size_t i = 0; + size_t new_cols = 0; + + if (table == NULL) + return -1; + + fort_row_t *new_row = CREATE_ROW_FROM_FMT_STRING(fmt, va); + + if (new_row == NULL) { + return -1; + } + + fort_row_t **cur_row_p = NULL; + size_t sz = vector_size(table->rows); + if (row >= sz) { + size_t push_n = row - sz + 1; + for (i = 0; i < push_n; ++i) { + fort_row_t *padding_row = create_row(); + if (padding_row == NULL) + goto clear; + + if (FT_IS_ERROR(vector_push(table->rows, &padding_row))) { + destroy_row(padding_row); + goto clear; + } + } + } + /* todo: clearing pushed items in case of error ?? */ + + new_cols = columns_in_row(new_row); + cur_row_p = (fort_row_t **)vector_at(table->rows, row); + swap_row(*cur_row_p, new_row, table->cur_col); + + table->cur_col += new_cols; + destroy_row(new_row); + return new_cols; + +clear: + destroy_row(new_row); + return -1; +#undef CREATE_ROW_FROM_FMT_STRING +} +#endif + +#if defined(FT_CLANG_COMPILER) || defined(FT_GCC_COMPILER) +#define FT_PRINTF ft_printf +#define FT_PRINTF_LN ft_printf_ln +#else +#define FT_PRINTF ft_printf_impl +#define FT_PRINTF_LN ft_printf_ln_impl +#endif + + + +int FT_PRINTF(ft_table_t *table, const char *fmt, ...) +{ + assert(table); + va_list va; + va_start(va, fmt); + int result = ft_row_printf_impl(table, table->cur_row, fmt, &va); + va_end(va); + return result; +} + +int FT_PRINTF_LN(ft_table_t *table, const char *fmt, ...) +{ + assert(table); + va_list va; + va_start(va, fmt); + int result = ft_row_printf_impl(table, table->cur_row, fmt, &va); + if (result >= 0) { + ft_ln(table); + } + va_end(va); + return result; +} + +#undef FT_PRINTF +#undef FT_PRINTF_LN +#undef FT_HDR_PRINTF +#undef FT_HDR_PRINTF_LN + +#ifdef FT_HAVE_WCHAR +int ft_wprintf(ft_table_t *table, const wchar_t *fmt, ...) +{ + assert(table); + va_list va; + va_start(va, fmt); + int result = ft_row_wprintf_impl(table, table->cur_row, fmt, &va); + va_end(va); + return result; +} + +int ft_wprintf_ln(ft_table_t *table, const wchar_t *fmt, ...) +{ + assert(table); + va_list va; + va_start(va, fmt); + int result = ft_row_wprintf_impl(table, table->cur_row, fmt, &va); + if (result >= 0) { + ft_ln(table); + } + va_end(va); + return result; +} + +#endif + + +static int ft_write_impl(ft_table_t *table, const char *cell_content) +{ + assert(table); + string_buffer_t *str_buffer = get_cur_str_buffer_and_create_if_not_exists(table); + if (str_buffer == NULL) + return FT_ERROR; + + int status = fill_buffer_from_string(str_buffer, cell_content); + if (FT_IS_SUCCESS(status)) { + table->cur_col++; + } + return status; +} + + +#ifdef FT_HAVE_WCHAR + +static int ft_wwrite_impl(ft_table_t *table, const wchar_t *cell_content) +{ + assert(table); + string_buffer_t *str_buffer = get_cur_str_buffer_and_create_if_not_exists(table); + if (str_buffer == NULL) + return FT_ERROR; + + int status = fill_buffer_from_wstring(str_buffer, cell_content); + if (FT_IS_SUCCESS(status)) { + table->cur_col++; + } + return status; +} + +#endif + + +int ft_nwrite(ft_table_t *table, size_t count, const char *cell_content, ...) +{ + size_t i = 0; + assert(table); + int status = ft_write_impl(table, cell_content); + if (FT_IS_ERROR(status)) + return status; + + va_list va; + va_start(va, cell_content); + --count; + for (i = 0; i < count; ++i) { + const char *cell = va_arg(va, const char *); + status = ft_write_impl(table, cell); + if (FT_IS_ERROR(status)) + return status; + } + va_end(va); + return status; +} + +int ft_nwrite_ln(ft_table_t *table, size_t count, const char *cell_content, ...) +{ + size_t i = 0; + assert(table); + int status = ft_write_impl(table, cell_content); + if (FT_IS_ERROR(status)) + return status; + + va_list va; + va_start(va, cell_content); + --count; + for (i = 0; i < count; ++i) { + const char *cell = va_arg(va, const char *); + status = ft_write_impl(table, cell); + if (FT_IS_ERROR(status)) { + va_end(va); + return status; + } + } + va_end(va); + + ft_ln(table); + return status; +} + +#ifdef FT_HAVE_WCHAR + +int ft_nwwrite(ft_table_t *table, size_t n, const wchar_t *cell_content, ...) +{ + size_t i = 0; + assert(table); + int status = ft_wwrite_impl(table, cell_content); + if (FT_IS_ERROR(status)) + return status; + + va_list va; + va_start(va, cell_content); + --n; + for (i = 0; i < n; ++i) { + const wchar_t *cell = va_arg(va, const wchar_t *); + status = ft_wwrite_impl(table, cell); + if (FT_IS_ERROR(status)) + return status; + } + va_end(va); + return status; +} + +int ft_nwwrite_ln(ft_table_t *table, size_t n, const wchar_t *cell_content, ...) +{ + size_t i = 0; + assert(table); + int status = ft_wwrite_impl(table, cell_content); + if (FT_IS_ERROR(status)) + return status; + + va_list va; + va_start(va, cell_content); + --n; + for (i = 0; i < n; ++i) { + const wchar_t *cell = va_arg(va, const wchar_t *); + status = ft_wwrite_impl(table, cell); + if (FT_IS_ERROR(status)) { + va_end(va); + return status; + } + } + va_end(va); + + ft_ln(table); + return status; +} +#endif + + +int ft_row_write(ft_table_t *table, size_t cols, const char *cells[]) +{ + size_t i = 0; + assert(table); + for (i = 0; i < cols; ++i) { + int status = ft_write_impl(table, cells[i]); + if (FT_IS_ERROR(status)) { + /* todo: maybe current pos in case of error should be equal to the one before function call? */ + return status; + } + } + return FT_SUCCESS; +} + +int ft_row_write_ln(ft_table_t *table, size_t cols, const char *cells[]) +{ + assert(table); + int status = ft_row_write(table, cols, cells); + if (FT_IS_SUCCESS(status)) { + ft_ln(table); + } + return status; +} + +#ifdef FT_HAVE_WCHAR +int ft_row_wwrite(ft_table_t *table, size_t cols, const wchar_t *cells[]) +{ + size_t i = 0; + assert(table); + for (i = 0; i < cols; ++i) { + int status = ft_wwrite_impl(table, cells[i]); + if (FT_IS_ERROR(status)) { + /* todo: maybe current pos in case of error should be equal to the one before function call? */ + return status; + } + } + return FT_SUCCESS; +} + +int ft_row_wwrite_ln(ft_table_t *table, size_t cols, const wchar_t *cells[]) +{ + assert(table); + int status = ft_row_wwrite(table, cols, cells); + if (FT_IS_SUCCESS(status)) { + ft_ln(table); + } + return status; +} +#endif + + + +int ft_table_write(ft_table_t *table, size_t rows, size_t cols, const char *table_cells[]) +{ + size_t i = 0; + assert(table); + for (i = 0; i < rows; ++i) { + int status = ft_row_write(table, cols, (const char **)&table_cells[i * cols]); + if (FT_IS_ERROR(status)) { + /* todo: maybe current pos in case of error should be equal to the one before function call? */ + return status; + } + if (i != rows - 1) + ft_ln(table); + } + return FT_SUCCESS; +} + +int ft_table_write_ln(ft_table_t *table, size_t rows, size_t cols, const char *table_cells[]) +{ + assert(table); + int status = ft_table_write(table, rows, cols, table_cells); + if (FT_IS_SUCCESS(status)) { + ft_ln(table); + } + return status; +} + + +#ifdef FT_HAVE_WCHAR +int ft_table_wwrite(ft_table_t *table, size_t rows, size_t cols, const wchar_t *table_cells[]) +{ + size_t i = 0; + assert(table); + for (i = 0; i < rows; ++i) { + int status = ft_row_wwrite(table, cols, (const wchar_t **)&table_cells[i * cols]); + if (FT_IS_ERROR(status)) { + /* todo: maybe current pos in case of error should be equal to the one before function call? */ + return status; + } + if (i != rows - 1) + ft_ln(table); + } + return FT_SUCCESS; +} + +int ft_table_wwrite_ln(ft_table_t *table, size_t rows, size_t cols, const wchar_t *table_cells[]) +{ + assert(table); + int status = ft_table_wwrite(table, rows, cols, table_cells); + if (FT_IS_SUCCESS(status)) { + ft_ln(table); + } + return status; +} +#endif + + + + + + +/***************************************************************************** + * TABLE + * ***************************************************************************/ + + + +const char *ft_to_string(const ft_table_t *table) +{ + typedef char char_type; + const char_type *empty_string = ""; + const enum str_buf_type buf_type = CharBuf; + const char *space_char = " "; + const char *new_line_char = "\n"; +#define cur_F_STRDUP F_STRDUP + int (*snprintf_row_)(const fort_row_t *, char *, size_t, size_t *, size_t, size_t, const context_t *) = snprintf_row; + int (*print_row_separator_)(char *, size_t, + const size_t *, size_t, + const fort_row_t *, const fort_row_t *, + enum HorSeparatorPos, const separator_t *, + const context_t *) = print_row_separator; +// int (*snprint_n_chars_)(char *, size_t, size_t, char) = snprint_n_chars; + int (*snprint_n_strings_)(char *, size_t, size_t, const char *) = snprint_n_strings; + assert(table); + + /* Determing size of table string representation */ + size_t height = 0; + size_t width = 0; + int status = table_geometry(table, &height, &width); + if (FT_IS_ERROR(status)) { return NULL; + } + size_t sz = height * width + 1; + + /* Allocate string buffer for string representation */ + if (table->conv_buffer == NULL) { + ((ft_table_t *)table)->conv_buffer = create_string_buffer(sz, buf_type); + if (table->conv_buffer == NULL) + return NULL; + } + while (string_buffer_capacity(table->conv_buffer) < sz) { + if (FT_IS_ERROR(realloc_string_buffer_without_copy(table->conv_buffer))) { + return NULL; + } + } + char_type *buffer = (char_type *)buffer_get_data(table->conv_buffer); + + + size_t cols = 0; + size_t rows = 0; + size_t *col_width_arr = NULL; + size_t *row_height_arr = NULL; + status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); + if (FT_IS_ERROR(status)) + return NULL; + + if (rows == 0) + return cur_F_STRDUP(empty_string); + + int written = 0; + int tmp = 0; + size_t i = 0; + context_t context; + context.table_options = (table->options ? table->options : &g_table_options); + fort_row_t *prev_row = NULL; + fort_row_t *cur_row = NULL; + separator_t *cur_sep = NULL; + size_t sep_size = vector_size(table->separators); + + /* Print top margin */ + for (i = 0; i < context.table_options->entire_table_options.top_margin; ++i) { + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char)); + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char)); + } + + 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; + context.row = i; + CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, separatorPos, cur_sep, &context)); + CHCK_RSLT_ADD_TO_WRITTEN(snprintf_row_(cur_row, buffer + written, sz - written, col_width_arr, cols, row_height_arr[i], &context)); + prev_row = cur_row; + } + cur_row = NULL; + cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL; + CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, BottomSeparator, cur_sep, &context)); + + /* Print bottom margin */ + for (i = 0; i < context.table_options->entire_table_options.bottom_margin; ++i) { + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char)); + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char)); + } + + + F_FREE(col_width_arr); + F_FREE(row_height_arr); + return buffer; + +clear: + F_FREE(col_width_arr); + F_FREE(row_height_arr); +// F_FREE(buffer); + return NULL; +#undef cur_F_STRDUP +} + + +#ifdef FT_HAVE_WCHAR + +const wchar_t *ft_to_wstring(const ft_table_t *table) +{ + typedef wchar_t char_type; + const char_type *empty_string = L""; + const enum str_buf_type buf_type = WCharBuf; + const char *space_char = " "; + const char *new_line_char = "\n"; +#define cur_F_STRDUP F_WCSDUP + int (*snprintf_row_)(const fort_row_t *, wchar_t *, size_t, size_t *, size_t, size_t, const context_t *) = wsnprintf_row; + int (*print_row_separator_)(wchar_t *, size_t, + const size_t *, size_t, + const fort_row_t *, const fort_row_t *, + enum HorSeparatorPos, const separator_t *, + const context_t *) = wprint_row_separator; +// int (*snprint_n_chars_)(wchar_t *, size_t, size_t, wchar_t) = wsnprint_n_chars; + int (*snprint_n_strings_)(wchar_t *, size_t, size_t, const char *) = wsnprint_n_string; + + + assert(table); + + /* Determing size of table string representation */ + size_t height = 0; + size_t width = 0; + int status = table_geometry(table, &height, &width); + if (FT_IS_ERROR(status)) { + return NULL; + } + size_t sz = height * width + 1; + + /* Allocate string buffer for string representation */ + if (table->conv_buffer == NULL) { + ((ft_table_t *)table)->conv_buffer = create_string_buffer(sz, buf_type); + if (table->conv_buffer == NULL) + return NULL; + } + while (string_buffer_capacity(table->conv_buffer) < sz) { + if (FT_IS_ERROR(realloc_string_buffer_without_copy(table->conv_buffer))) { + return NULL; + } + } + char_type *buffer = (char_type *)buffer_get_data(table->conv_buffer); + + + size_t cols = 0; + size_t rows = 0; + size_t *col_width_arr = NULL; + size_t *row_height_arr = NULL; + status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); + + if (rows == 0) + return cur_F_STRDUP(empty_string); + + if (FT_IS_ERROR(status)) + return NULL; + + int written = 0; + int tmp = 0; + size_t i = 0; + context_t context; + context.table_options = (table->options ? table->options : &g_table_options); + fort_row_t *prev_row = NULL; + fort_row_t *cur_row = NULL; + separator_t *cur_sep = NULL; + size_t sep_size = vector_size(table->separators); + + /* Print top margin */ + for (i = 0; i < context.table_options->entire_table_options.top_margin; ++i) { + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char)); + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char)); + } + + 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; + context.row = i; + CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, separatorPos, cur_sep, &context)); + CHCK_RSLT_ADD_TO_WRITTEN(snprintf_row_(cur_row, buffer + written, sz - written, col_width_arr, cols, row_height_arr[i], &context)); + prev_row = cur_row; + } + cur_row = NULL; + cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL; + CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, BottomSeparator, cur_sep, &context)); + + /* Print bottom margin */ + for (i = 0; i < context.table_options->entire_table_options.bottom_margin; ++i) { + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char)); + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char)); + } + + F_FREE(col_width_arr); + F_FREE(row_height_arr); + return buffer; + +clear: + F_FREE(col_width_arr); + F_FREE(row_height_arr); +// F_FREE(buffer); + return NULL; +#undef cur_F_STRDUP +} + +#endif + + +/* + * TMP + */ +//static int dummy_function(void) +//#if defined(FT_CLANG_COMPILER) || defined(FT_GCC_COMPILER) +//__attribute__ ((unused)) +//#endif +//; + +//static int dummy_function(void) +//{ +// if (0) { +// vector_t *v = create_vector(1, DEFAULT_VECTOR_CAPACITY); +// vector_clear(v); +// vector_erase(v, 0); +// vector_index_of(v, NULL); +// vector_capacity(v); +// } +// return 0; +//} + + + + +int ft_add_separator(ft_table_t *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 FT_MEMORY_ERROR; + int status = vector_push(table->separators, &sep_p); + if (FT_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 FT_ERROR; + return FT_SUCCESS; +} + + + + +/* ******************************************************************************* */ + + +struct ft_border_style *FT_BASIC_STYLE = (struct ft_border_style *) &FORT_BASIC_STYLE; +struct ft_border_style *FT_SIMPLE_STYLE = (struct ft_border_style *) &FORT_SIMPLE_STYLE; +struct ft_border_style *FT_PLAIN_STYLE = (struct ft_border_style *) &FORT_PLAIN_STYLE; +struct ft_border_style *FT_DOT_STYLE = (struct ft_border_style *) &FORT_DOT_STYLE; +struct ft_border_style *FT_EMPTY_STYLE = (struct ft_border_style *) &FORT_EMPTY_STYLE; +struct ft_border_style *FT_SOLID_STYLE = (struct ft_border_style *) &FORT_SOLID_STYLE; +struct ft_border_style *FT_SOLID_ROUND_STYLE = (struct ft_border_style *) &FORT_SOLID_ROUND_STYLE; +struct ft_border_style *FT_DOUBLE_STYLE = (struct ft_border_style *) &FORT_DOUBLE_STYLE; +struct ft_border_style *FT_DOUBLE2_STYLE = (struct ft_border_style *) &FORT_DOUBLE2_STYLE; +struct ft_border_style *FT_BOLD_STYLE = (struct ft_border_style *) &FORT_BOLD_STYLE; +struct ft_border_style *FT_BOLD2_STYLE = (struct ft_border_style *) &FORT_BOLD2_STYLE; +struct ft_border_style *FT_FRAME_STYLE = (struct ft_border_style *) &FORT_FRAME_STYLE; + + + +static void set_border_options_for_options(fort_table_options_t *options, struct ft_border_style *style) +{ + if ((struct fort_border_style *)style == &FORT_BASIC_STYLE + || (struct fort_border_style *)style == &FORT_SIMPLE_STYLE + || (struct fort_border_style *)style == &FORT_DOT_STYLE + || (struct fort_border_style *)style == &FORT_PLAIN_STYLE + || (struct fort_border_style *)style == &FORT_EMPTY_STYLE + || (struct fort_border_style *)style == &FORT_SOLID_STYLE + || (struct fort_border_style *)style == &FORT_SOLID_ROUND_STYLE + || (struct fort_border_style *)style == &FORT_DOUBLE_STYLE + || (struct fort_border_style *)style == &FORT_DOUBLE2_STYLE + || (struct fort_border_style *)style == &FORT_BOLD_STYLE + || (struct fort_border_style *)style == &FORT_BOLD2_STYLE + || (struct fort_border_style *)style == &FORT_FRAME_STYLE) { + memcpy(&(options->border_style), (struct fort_border_style *)style, sizeof(struct fort_border_style)); + return; + } + + struct ft_border_chars *border_chs = &(style->border_chs); + struct ft_border_chars *header_border_chs = &(style->header_border_chs); + +#define BOR_CHARS options->border_style.border_chars +#define H_BOR_CHARS options->border_style.header_border_chars +#define SEP_CHARS options->border_style.separator_chars /* - * In theory we should copy MIN(size, size allocated for ptr) bytes, - * but this is rather dummy implementation so we don't care about it - */ - memcpy(new_chunk, ptr, size); - F_FREE(ptr); - return new_chunk; -} + BOR_CHARS[TL_bip] = BOR_CHARS[TT_bip] = BOR_CHARS[TV_bip] = BOR_CHARS[TR_bip] = border_chs->top_border_ch; + BOR_CHARS[LH_bip] = BOR_CHARS[IH_bip] = BOR_CHARS[II_bip] = BOR_CHARS[RH_bip] = border_chs->separator_ch; + BOR_CHARS[BL_bip] = BOR_CHARS[BB_bip] = BOR_CHARS[BV_bip] = BOR_CHARS[BR_bip] = border_chs->bottom_border_ch; + BOR_CHARS[LL_bip] = BOR_CHARS[IV_bip] = BOR_CHARS[RR_bip] = border_chs->side_border_ch; -void set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)) -{ - assert((f_malloc == NULL && f_free == NULL) /* Use std functions */ - || (f_malloc != NULL && f_free != NULL) /* Use custom functions */); + H_BOR_CHARS[TL_bip] = H_BOR_CHARS[TT_bip] = H_BOR_CHARS[TV_bip] = H_BOR_CHARS[TR_bip] = header_border_chs->top_border_ch; + H_BOR_CHARS[LH_bip] = H_BOR_CHARS[IH_bip] = H_BOR_CHARS[II_bip] = H_BOR_CHARS[RH_bip] = header_border_chs->separator_ch; + H_BOR_CHARS[BL_bip] = H_BOR_CHARS[BB_bip] = H_BOR_CHARS[BV_bip] = H_BOR_CHARS[BR_bip] = header_border_chs->bottom_border_ch; + H_BOR_CHARS[LL_bip] = H_BOR_CHARS[IV_bip] = H_BOR_CHARS[RR_bip] = header_border_chs->side_border_ch; + */ - if (f_malloc == NULL && f_free == NULL) { -#ifndef FT_MICROSOFT_COMPILER - fort_malloc = &malloc; - fort_free = &free; - fort_calloc = &calloc; - fort_realloc = &realloc; -#else - fort_malloc = &local_malloc; - fort_free = &local_free; - fort_calloc = &local_calloc; - fort_realloc = &local_realloc; -#endif - } else { - fort_malloc = f_malloc; - fort_free = f_free; - fort_calloc = &custom_fort_calloc; - fort_realloc = &custom_fort_realloc; - } + BOR_CHARS[TT_bip] = border_chs->top_border_ch; + BOR_CHARS[IH_bip] = border_chs->separator_ch; + BOR_CHARS[BB_bip] = border_chs->bottom_border_ch; + BOR_CHARS[LL_bip] = BOR_CHARS[IV_bip] = BOR_CHARS[RR_bip] = border_chs->side_border_ch; -} + BOR_CHARS[TL_bip] = BOR_CHARS[TV_bip] = BOR_CHARS[TR_bip] = border_chs->out_intersect_ch; + BOR_CHARS[LH_bip] = BOR_CHARS[RH_bip] = border_chs->out_intersect_ch; + BOR_CHARS[BL_bip] = BOR_CHARS[BV_bip] = BOR_CHARS[BR_bip] = border_chs->out_intersect_ch; + BOR_CHARS[II_bip] = border_chs->in_intersect_ch; - -char *fort_strdup(const char *str) -{ - if (str == NULL) - return NULL; - - size_t sz = strlen(str); - char *str_copy = (char *)F_MALLOC((sz + 1) * sizeof(char)); - if (str_copy == NULL) - return NULL; - - strcpy(str_copy, str); - return str_copy; -} - -wchar_t *fort_wcsdup(const wchar_t *str) -{ - if (str == NULL) - return NULL; - - size_t sz = wcslen(str); - wchar_t *str_copy = (wchar_t *)F_MALLOC((sz + 1) * sizeof(wchar_t)); - if (str_copy == NULL) - return NULL; - - wcscpy(str_copy, str); - return str_copy; -} - -size_t number_of_columns_in_format_string(const char *fmt) -{ - int separator_counter = 0; - const char *pos = fmt; - while (1) { - pos = strchr(pos, FORT_COL_SEPARATOR); - if (pos == NULL) - break; - - separator_counter++; - ++pos; - } - return separator_counter + 1; -} - -size_t number_of_columns_in_format_wstring(const wchar_t *fmt) -{ - int separator_counter = 0; - const wchar_t *pos = fmt; - while (1) { - pos = wcschr(pos, FORT_COL_SEPARATOR); - if (pos == NULL) - break; - - separator_counter++; - ++pos; - } - return separator_counter + 1; -} - - -//int snprint_n_chars(char *buf, size_t length, size_t n, char ch) -//{ -// if (length <= n) -// return -1; - -// if (n == 0) -// return 0; - -// /* To ensure valid return value it is safely not print such big strings */ -// if (n > INT_MAX) -// return -1; - -// int status = snprintf(buf, length, "%0*d", (int)n, 0); -// if (status < 0) -// return status; - -// size_t i = 0; -// for (i = 0; i < n; ++i) { -// *buf = ch; -// buf++; +// if (border_chs->separator_ch == '\0' && border_chs->in_intersect_ch == '\0') { +// BOR_CHARS[LH_bip] = BOR_CHARS[RH_bip] = '\0'; // } -// return (int)n; -//} - -int snprint_n_strings(char *buf, size_t length, size_t n, const char *str) -{ - size_t str_len = strlen(str); - if (length <= n * str_len) - return -1; - - if (n == 0) - return 0; - - /* To ensure valid return value it is safely not print such big strings */ - if (n * str_len > INT_MAX) - return -1; - - int status = snprintf(buf, length, "%0*d", (int)(n * str_len), 0); - if (status < 0) - return status; - - size_t i = 0; - for (i = 0; i < n; ++i) { - const char *str_p = str; - while (*str_p) - *(buf++) = *(str_p++); + if (strlen(border_chs->separator_ch) == 0 && strlen(border_chs->in_intersect_ch) == 0) { + BOR_CHARS[LH_bip] = BOR_CHARS[RH_bip] = "\0"; } - return (int)(n * str_len); -} -//int wsnprint_n_chars(wchar_t *buf, size_t length, size_t n, wchar_t ch) -//{ -// if (length <= n) -// return -1; + H_BOR_CHARS[TT_bip] = header_border_chs->top_border_ch; + H_BOR_CHARS[IH_bip] = header_border_chs->separator_ch; + H_BOR_CHARS[BB_bip] = header_border_chs->bottom_border_ch; + H_BOR_CHARS[LL_bip] = H_BOR_CHARS[IV_bip] = H_BOR_CHARS[RR_bip] = header_border_chs->side_border_ch; -// if (n == 0) -// return 0; + H_BOR_CHARS[TL_bip] = H_BOR_CHARS[TV_bip] = H_BOR_CHARS[TR_bip] = header_border_chs->out_intersect_ch; + H_BOR_CHARS[LH_bip] = H_BOR_CHARS[RH_bip] = header_border_chs->out_intersect_ch; + H_BOR_CHARS[BL_bip] = H_BOR_CHARS[BV_bip] = H_BOR_CHARS[BR_bip] = header_border_chs->out_intersect_ch; + H_BOR_CHARS[II_bip] = header_border_chs->in_intersect_ch; -// /* To ensure valid return value it is safely not print such big strings */ -// if (n > INT_MAX) -// return -1; - -// int status = swprintf(buf, length, L"%0*d", (int)n, 0); -// if (status < 0) -// return status; - -// size_t i = 0; -// for (i = 0; i < n; ++i) { -// *buf = ch; -// buf++; +// if (header_border_chs->separator_ch == '\0' && header_border_chs->in_intersect_ch == '\0') { +// H_BOR_CHARS[LH_bip] = H_BOR_CHARS[RH_bip] = '\0'; // } -// return (int)n; -//} - -int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str) -{ - size_t str_len = strlen(str); - - /* This function doesn't work properly with multibyte characters - * so it is better return an error in this case - */ - if (str_len > 1) - return -1; - - if (length <= n * str_len) - return -1; - - if (n == 0) - return 0; - - - - /* To ensure valid return value it is safely not print such big strings */ - if (n * str_len > INT_MAX) - return -1; - - int status = swprintf(buf, length, L"%0*d", (int)(n * str_len), 0); - if (status < 0) - return status; - - size_t i = 0; - for (i = 0; i < n; ++i) { - const char *str_p = str; - while (*str_p) - *(buf++) = (wchar_t) * (str_p++); + if (strlen(header_border_chs->separator_ch) == 0 && strlen(header_border_chs->in_intersect_ch) == 0) { + BOR_CHARS[LH_bip] = BOR_CHARS[RH_bip] = "\0"; } - return (int)(n * str_len); + + SEP_CHARS[LH_sip] = SEP_CHARS[RH_sip] = SEP_CHARS[II_sip] = header_border_chs->out_intersect_ch; + SEP_CHARS[IH_sip] = style->hor_separator_char; + + +#undef BOR_CHARS +#undef H_BOR_CHARS +#undef SEP_CHARS } + +int ft_set_default_border_style(struct ft_border_style *style) +{ + set_border_options_for_options(&g_table_options, style); + return FT_SUCCESS; +} + +int ft_set_border_style(ft_table_t *table, struct ft_border_style *style) +{ + assert(table); + if (table->options == NULL) { + table->options = create_table_options(); + if (table->options == NULL) + return FT_MEMORY_ERROR; + } + set_border_options_for_options(table->options, style); + return FT_SUCCESS; +} + + + +int ft_set_cell_option(ft_table_t *table, size_t row, size_t col, uint32_t option, int value) +{ + assert(table); + + if (table->options == NULL) { + table->options = create_table_options(); + if (table->options == NULL) + return FT_MEMORY_ERROR; + } + if (table->options->cell_options == NULL) { + table->options->cell_options = create_cell_opt_container(); + if (table->options->cell_options == NULL) { + return FT_ERROR; + } + } + + if (row == FT_CUR_ROW) + row = table->cur_row; + if (row == FT_CUR_COLUMN) + col = table->cur_col; + + return set_cell_option(table->options->cell_options, row, col, option, value); +} + +int ft_set_default_cell_option(uint32_t option, int value) +{ + return set_default_cell_option(option, value); +} + + +int ft_set_default_tbl_option(uint32_t option, int value) +{ + return set_default_entire_table_option(option, value); +} + +int ft_set_tbl_option(ft_table_t *table, uint32_t option, int value) +{ + assert(table); + + if (table->options == NULL) { + table->options = create_table_options(); + if (table->options == NULL) + return FT_MEMORY_ERROR; + } + return set_entire_table_option(table->options, option, value); +} + +void ft_set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)) +{ + set_memory_funcs(f_malloc, f_free); +} + +int ft_set_cell_span(ft_table_t *table, size_t row, size_t col, size_t hor_span) +{ + assert(table); + if (hor_span < 2) + return FT_EINVAL; + + if (row == FT_CUR_ROW) + row = table->cur_row; + if (row == FT_CUR_COLUMN) + col = table->cur_col; + + fort_row_t *row_p = get_row_and_create_if_not_exists(table, row); + if (row_p == NULL) + return FT_ERROR; + + return row_set_cell_span(row_p, col, hor_span); +} diff --git a/src/fort_utils.c b/src/fort_utils.c new file mode 100644 index 0000000..1a8cfea --- /dev/null +++ b/src/fort_utils.c @@ -0,0 +1,270 @@ +#include "fort_utils.h" +#ifdef FT_HAVE_WCHAR +#include +#endif + + + +/***************************************************************************** + * LIBFORT helpers + *****************************************************************************/ + +#ifndef FT_MICROSOFT_COMPILER +void *(*fort_malloc)(size_t size) = &malloc; +void (*fort_free)(void *ptr) = &free; +void *(*fort_calloc)(size_t nmemb, size_t size) = &calloc; +void *(*fort_realloc)(void *ptr, size_t size) = &realloc; +#else +static void *local_malloc(size_t size) +{ + return malloc(size); +} + +static void local_free(void *ptr) +{ + free(ptr); +} + +static void *local_calloc(size_t nmemb, size_t size) +{ + return calloc(nmemb, size); +} + +static void *local_realloc(void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +void *(*fort_malloc)(size_t size) = &local_malloc; +void (*fort_free)(void *ptr) = &local_free; +void *(*fort_calloc)(size_t nmemb, size_t size) = &local_calloc; +void *(*fort_realloc)(void *ptr, size_t size) = &local_realloc; +#endif + +static void *custom_fort_calloc(size_t nmemb, size_t size) +{ + size_t total_size = nmemb * size; + void *result = F_MALLOC(total_size); + if (result != NULL) + memset(result, 0, total_size); + return result; +} + +static void *custom_fort_realloc(void *ptr, size_t size) +{ + if (ptr == NULL) + return F_MALLOC(size); + if (size == 0) { + F_FREE(ptr); + return NULL; + } + + void *new_chunk = F_MALLOC(size); + if (new_chunk == NULL) + return NULL; + + /* + * In theory we should copy MIN(size, size allocated for ptr) bytes, + * but this is rather dummy implementation so we don't care about it + */ + memcpy(new_chunk, ptr, size); + F_FREE(ptr); + return new_chunk; +} + +void set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)) +{ + assert((f_malloc == NULL && f_free == NULL) /* Use std functions */ + || (f_malloc != NULL && f_free != NULL) /* Use custom functions */); + + if (f_malloc == NULL && f_free == NULL) { +#ifndef FT_MICROSOFT_COMPILER + fort_malloc = &malloc; + fort_free = &free; + fort_calloc = &calloc; + fort_realloc = &realloc; +#else + fort_malloc = &local_malloc; + fort_free = &local_free; + fort_calloc = &local_calloc; + fort_realloc = &local_realloc; +#endif + } else { + fort_malloc = f_malloc; + fort_free = f_free; + fort_calloc = &custom_fort_calloc; + fort_realloc = &custom_fort_realloc; + } + +} + + +char *fort_strdup(const char *str) +{ + if (str == NULL) + return NULL; + + size_t sz = strlen(str); + char *str_copy = (char *)F_MALLOC((sz + 1) * sizeof(char)); + if (str_copy == NULL) + return NULL; + + strcpy(str_copy, str); + return str_copy; +} + +wchar_t *fort_wcsdup(const wchar_t *str) +{ + if (str == NULL) + return NULL; + + size_t sz = wcslen(str); + wchar_t *str_copy = (wchar_t *)F_MALLOC((sz + 1) * sizeof(wchar_t)); + if (str_copy == NULL) + return NULL; + + wcscpy(str_copy, str); + return str_copy; +} + +size_t number_of_columns_in_format_string(const char *fmt) +{ + int separator_counter = 0; + const char *pos = fmt; + while (1) { + pos = strchr(pos, FORT_COL_SEPARATOR); + if (pos == NULL) + break; + + separator_counter++; + ++pos; + } + return separator_counter + 1; +} + +size_t number_of_columns_in_format_wstring(const wchar_t *fmt) +{ + int separator_counter = 0; + const wchar_t *pos = fmt; + while (1) { + pos = wcschr(pos, FORT_COL_SEPARATOR); + if (pos == NULL) + break; + + separator_counter++; + ++pos; + } + return separator_counter + 1; +} + + +//int snprint_n_chars(char *buf, size_t length, size_t n, char ch) +//{ +// if (length <= n) +// return -1; + +// if (n == 0) +// return 0; + +// /* To ensure valid return value it is safely not print such big strings */ +// if (n > INT_MAX) +// return -1; + +// int status = snprintf(buf, length, "%0*d", (int)n, 0); +// if (status < 0) +// return status; + +// size_t i = 0; +// for (i = 0; i < n; ++i) { +// *buf = ch; +// buf++; +// } +// return (int)n; +//} + +int snprint_n_strings(char *buf, size_t length, size_t n, const char *str) +{ + size_t str_len = strlen(str); + if (length <= n * str_len) + return -1; + + if (n == 0) + return 0; + + /* To ensure valid return value it is safely not print such big strings */ + if (n * str_len > INT_MAX) + return -1; + + int status = snprintf(buf, length, "%0*d", (int)(n * str_len), 0); + if (status < 0) + return status; + + size_t i = 0; + for (i = 0; i < n; ++i) { + const char *str_p = str; + while (*str_p) + *(buf++) = *(str_p++); + } + return (int)(n * str_len); +} + + +//int wsnprint_n_chars(wchar_t *buf, size_t length, size_t n, wchar_t ch) +//{ +// if (length <= n) +// return -1; + +// if (n == 0) +// return 0; + +// /* To ensure valid return value it is safely not print such big strings */ +// if (n > INT_MAX) +// return -1; + +// int status = swprintf(buf, length, L"%0*d", (int)n, 0); +// if (status < 0) +// return status; + +// size_t i = 0; +// for (i = 0; i < n; ++i) { +// *buf = ch; +// buf++; +// } +// return (int)n; +//} + +int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str) +{ + size_t str_len = strlen(str); + + /* This function doesn't work properly with multibyte characters + * so it is better return an error in this case + */ + if (str_len > 1) + return -1; + + if (length <= n * str_len) + return -1; + + if (n == 0) + return 0; + + + + /* To ensure valid return value it is safely not print such big strings */ + if (n * str_len > INT_MAX) + return -1; + + int status = swprintf(buf, length, L"%0*d", (int)(n * str_len), 0); + if (status < 0) + return status; + + size_t i = 0; + for (i = 0; i < n; ++i) { + const char *str_p = str; + while (*str_p) + *(buf++) = (wchar_t) * (str_p++); + } + return (int)(n * str_len); +} + diff --git a/src/fort_impl.h b/src/fort_utils.h similarity index 100% rename from src/fort_impl.h rename to src/fort_utils.h diff --git a/src/options.c b/src/options.c index 7c47f52..7083a51 100644 --- a/src/options.c +++ b/src/options.c @@ -1,6 +1,6 @@ #include #include "options.h" -#include "fort_impl.h" +#include "fort_utils.h" #include "vector.h" /***************************************************************************** diff --git a/src/options.h b/src/options.h index 5d7a95a..d92d4c4 100644 --- a/src/options.h +++ b/src/options.h @@ -1,7 +1,7 @@ #ifndef OPTIONS_H #define OPTIONS_H -#include "fort_impl.h" +#include "fort_utils.h" #include #include diff --git a/src/row.h b/src/row.h index 239d469..23980fc 100644 --- a/src/row.h +++ b/src/row.h @@ -1,7 +1,7 @@ #ifndef ROW_H #define ROW_H -#include "fort_impl.h" +#include "fort_utils.h" #include "fort.h" #include #include "options.h" diff --git a/src/string_buffer.h b/src/string_buffer.h index e451188..9c0a97f 100644 --- a/src/string_buffer.h +++ b/src/string_buffer.h @@ -1,7 +1,7 @@ #ifndef STRING_BUFFER_H #define STRING_BUFFER_H -#include "fort_impl.h" +#include "fort_utils.h" /***************************************************************************** diff --git a/src/table.h b/src/table.h index 528536f..d085c90 100644 --- a/src/table.h +++ b/src/table.h @@ -1,7 +1,7 @@ #ifndef TABLE_H #define TABLE_H -#include "fort_impl.h" +#include "fort_utils.h" struct ft_table; typedef struct ft_table ft_table_t; diff --git a/src/vector.h b/src/vector.h index 7e768a1..ba1e5d1 100644 --- a/src/vector.h +++ b/src/vector.h @@ -1,7 +1,7 @@ #ifndef VECTOR_H #define VECTOR_H -#include "fort_impl.h" +#include "fort_utils.h" /*****************************************************************************