From c57e73eac9334d5196599511939e2b57e588ff54 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 18 Oct 2023 10:20:12 +0200 Subject: [PATCH] libsmartcols: add scols_cell_refer_memory() * allow to use non-string data * use memcpy() rather than strdup() for data Signed-off-by: Karel Zak --- libsmartcols/src/cell.c | 67 ++++++++++++++++++++++++++---- libsmartcols/src/libsmartcols.h.in | 5 +++ libsmartcols/src/libsmartcols.sym | 2 + libsmartcols/src/print.c | 12 ++++-- libsmartcols/src/smartcolsP.h | 1 + 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/libsmartcols/src/cell.c b/libsmartcols/src/cell.c index f1d488fe87..f2bac54350 100644 --- a/libsmartcols/src/cell.c +++ b/libsmartcols/src/cell.c @@ -56,27 +56,31 @@ int scols_reset_cell(struct libscols_cell *ce) * @ce: a pointer to a struct libscols_cell instance * @data: data (used for scols_print_table()) * - * Stores a copy of the @str in @ce, the old data are deallocated by free(). + * Stores a copy of the @data in @ce, the old data are deallocated by free(). * * Returns: 0, a negative value in case of an error. */ int scols_cell_set_data(struct libscols_cell *ce, const char *data) { + int rc; + if (!ce) return -EINVAL; - return strdup_to_struct_member(ce, data, data); + rc = strdup_to_struct_member(ce, data, data); + ce->datasiz = ce->data ? strlen(ce->data) + 1: 0; + return rc; } /** * scols_cell_refer_data: * @ce: a pointer to a struct libscols_cell instance - * @data: data (used for scols_print_table()) + * @data: string (used for scols_print_table()) * - * Adds a reference to @str to @ce. The pointer is deallocated by - * scols_reset_cell() or scols_unref_line(). This function is mostly designed - * for situations when the data for the cell are already composed in allocated - * memory (e.g. asprintf()) to avoid extra unnecessary strdup(). + * Adds a reference to @data to @ce. The pointer is deallocated by + * scols_reset_cell() or scols_unref_line() by free(). This function is mostly + * designed for situations when the data for the cell are already composed in + * allocated memory (e.g. asprintf()) to avoid extra unnecessary strdup(). * * Returns: 0, a negative value in case of an error. */ @@ -86,9 +90,46 @@ int scols_cell_refer_data(struct libscols_cell *ce, char *data) return -EINVAL; free(ce->data); ce->data = data; + ce->datasiz = ce->data ? strlen(ce->data) + 1: 0; + return 0; +} + +/** + * scols_cell_refer_memory: + * @ce: a pointer to a struct libscols_cell instance + * @data: data + * @datasiz: size of the data + * + * Same like scols_cell_refer_data, but @data does not have to be zero terminated. + * The pointer is deallocated by scols_reset_cell() or scols_unref_line() by free(). + * + * The column (for the cell) has to define wrap function which converts the + * data to zero terminated string, otherwise library will work with the data as + * with string! + * + * Returns: 0, a negative value in case of an error. + */ +int scols_cell_refer_memory(struct libscols_cell *ce, char *data, size_t datasiz) +{ + if (!ce) + return -EINVAL; + free(ce->data); + ce->data = data; + ce->datasiz = datasiz; return 0; } +/** + * scols_cell_get_datasiz: + * @ce: a pointer to a struct libscols_cell instance + * + * Returns: the current set data size. + */ +size_t scols_cell_get_datasiz(struct libscols_cell *ce) +{ + return ce ? ce->datasiz : 0; +} + /** * scols_cell_get_data: * @ce: a pointer to a struct libscols_cell instance @@ -251,7 +292,7 @@ int scols_cell_get_alignment(const struct libscols_cell *ce) * @dest: a pointer to a struct libscols_cell instance * @src: a pointer to an immutable struct libscols_cell instance * - * Copy the contents of @src into @dest. + * Copy the contents (data, usewrdata, colors) of @src into @dest. * * Returns: 0, a negative value in case of an error. */ @@ -259,11 +300,19 @@ int scols_cell_copy_content(struct libscols_cell *dest, const struct libscols_cell *src) { int rc; + char *data = NULL; if (!dest || !src) return -EINVAL; - rc = scols_cell_set_data(dest, scols_cell_get_data(src)); + if (src->datasiz) { + data = malloc(src->datasiz); + if (!data) + return -ENOMEM; + memcpy(data, src->data, src->datasiz); + } + + rc = scols_cell_refer_memory(dest, data, src->datasiz); if (!rc) rc = scols_cell_set_color(dest, scols_cell_get_color(src)); if (!rc) diff --git a/libsmartcols/src/libsmartcols.h.in b/libsmartcols/src/libsmartcols.h.in index ab54c0efe5..a0b5255cab 100644 --- a/libsmartcols/src/libsmartcols.h.in +++ b/libsmartcols/src/libsmartcols.h.in @@ -146,7 +146,11 @@ extern int scols_cell_copy_content(struct libscols_cell *dest, const struct libscols_cell *src); extern int scols_cell_set_data(struct libscols_cell *ce, const char *data); extern int scols_cell_refer_data(struct libscols_cell *ce, char *data); +extern int scols_cell_refer_memory(struct libscols_cell *ce, char *data, size_t datasiz); + extern const char *scols_cell_get_data(const struct libscols_cell *ce); +extern size_t scols_cell_get_datasiz(struct libscols_cell *ce); + extern int scols_cell_set_color(struct libscols_cell *ce, const char *color); extern const char *scols_cell_get_color(const struct libscols_cell *ce); @@ -159,6 +163,7 @@ extern int scols_cell_set_userdata(struct libscols_cell *ce, void *data); extern int scols_cmpstr_cells(struct libscols_cell *a, struct libscols_cell *b, void *data); + /* column.c */ extern int scols_column_is_tree(const struct libscols_column *cl); extern int scols_column_is_trunc(const struct libscols_column *cl); diff --git a/libsmartcols/src/libsmartcols.sym b/libsmartcols/src/libsmartcols.sym index 4fa6df6040..909139884e 100644 --- a/libsmartcols/src/libsmartcols.sym +++ b/libsmartcols/src/libsmartcols.sym @@ -217,4 +217,6 @@ SMARTCOLS_2.39 { SMARTCOLS_2.40 { scols_table_get_cursor; + scols_cell_refer_memory; + scols_cell_get_datasiz; } SMARTCOLS_2.39; diff --git a/libsmartcols/src/print.c b/libsmartcols/src/print.c index 6f2cb5abc4..20f86f44e9 100644 --- a/libsmartcols/src/print.c +++ b/libsmartcols/src/print.c @@ -656,6 +656,7 @@ int __cursor_to_buffer(struct libscols_table *tb, int cal) { const char *data = NULL; + size_t datasiz = 0; struct libscols_cell *ce; struct libscols_line *ln; struct libscols_column *cl; @@ -681,9 +682,13 @@ int __cursor_to_buffer(struct libscols_table *tb, if (rc < 0) return rc; data = x; + if (data && *data) + datasiz = strlen(data); rc = 0; - } else + } else { data = scols_cell_get_data(ce); + datasiz = scols_cell_get_datasiz(ce); + } } if (!scols_column_is_tree(cl)) @@ -710,8 +715,9 @@ int __cursor_to_buffer(struct libscols_table *tb, if (!rc && (ln->parent || cl->is_groups) && !scols_table_is_json(tb)) ul_buffer_save_pointer(buf, SCOLS_BUFPTR_TREEEND); notree: - if (!rc && data) - rc = ul_buffer_append_string(buf, data); + if (!rc && data && datasiz) + rc = ul_buffer_append_data(buf, data, datasiz); + return rc; } diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h index 3abe8803a0..1ffdf23f60 100644 --- a/libsmartcols/src/smartcolsP.h +++ b/libsmartcols/src/smartcolsP.h @@ -80,6 +80,7 @@ struct libscols_symbols { */ struct libscols_cell { char *data; + size_t datasiz; char *color; void *userdata; int flags; -- 2.47.3