From: Karel Zak Date: Wed, 19 Mar 2014 15:29:39 +0000 (+0100) Subject: libsmartcols: add table struct, cleanup refcounting X-Git-Tag: v2.25-rc1~382 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c638c57ac3af8b819ef7b71804d585c3e9cf549c;p=thirdparty%2Futil-linux.git libsmartcols: add table struct, cleanup refcounting Signed-off-by: Karel Zak --- diff --git a/libsmartcols/src/cell.c b/libsmartcols/src/cell.c index 31934ab644..5e3ea6081b 100644 --- a/libsmartcols/src/cell.c +++ b/libsmartcols/src/cell.c @@ -26,12 +26,14 @@ int scols_reset_cell(struct libscols_cell *ce) if (!ce) return -EINVAL; - free(ce->data); + if (!ce->is_ref) + free(ce->data); free(ce->color); memset(ce, 0, sizeof(*ce)); return 0; } +/* stores copy of the @str to cell */ int scols_cell_set_data(struct libscols_cell *ce, const char *str) { char *p = NULL; @@ -45,8 +47,26 @@ int scols_cell_set_data(struct libscols_cell *ce, const char *str) if (!p) return -ENOMEM; } - free(ce->data); + if (!ce->is_ref) + free(ce->data); ce->data = p; + ce->is_ref = 0; + return 0; +} + +/* add reference to @str to cell */ +int scols_cell_refer_data(struct libscols_cell *ce, char *str) +{ + char *p = NULL; + + assert(ce); + + if (!ce) + return -EINVAL; + if (!ce->is_ref) + free(ce->data); + ce->data = p; + ce->is_ref = 1; return 0; } diff --git a/libsmartcols/src/line.c b/libsmartcols/src/line.c index 589d5a2f65..80a1beabbe 100644 --- a/libsmartcols/src/line.c +++ b/libsmartcols/src/line.c @@ -14,6 +14,12 @@ #include "smartcolsP.h" +/* + * Note that the line is allocated without cells, the cells will be allocated + * later when you add the line to the table. If you want to use the line + * without table then you have to explicitly allocate the cells by + * scols_line_alloc_cells(). + */ struct libscols_line *scols_new_line(void) { struct libscols_line *ln; @@ -21,7 +27,6 @@ struct libscols_line *scols_new_line(void) ln = calloc(1, sizeof(*ln)); if (!ln) return NULL; - ln->refcount = 1; INIT_LIST_HEAD(&ln->ln_lines); INIT_LIST_HEAD(&ln->ln_children); @@ -37,20 +42,63 @@ void scols_ref_line(struct libscols_line *ln) void scols_unref_line(struct libscols_line *ln) { - if (ln && --ln->refcount <= 0) { - size_t i; + if (ln && --ln->refcount <= 0) { list_del(&ln->ln_lines); list_del(&ln->ln_children); - for (i = 0; i <= ln->ncells; i++) - scols_reset_cell(ln->cells[i]); - free(ln->data); + scols_line_free_cells(ln); free(ln->color); free(ln); + return; } } +void scols_line_free_cells(struct libscols_line *ln) +{ + size_t i; + + if (!ln || !ln->cells) + return; + + for (i = 0; i < ln->ncells; i++) + scols_reset_cell(&ln->cells[i]); + + free(ln->cells); + ln->ncells = 0; + ln->cells = NULL; +} + + +int scols_line_alloc_cells(struct libscols_line *ln, size_t n) +{ + struct libscols_cell *ce; + + assert(ln); + + if (!ln) + return -EINVAL; + if (ln->ncells == n) + return 0; + + if (!n) { + scols_line_free_cells(ln); + return 0; + } + + ce = realloc(ln->cells, n * sizeof(struct libscols_cell)); + if (!ce) + return -errno; + + if (n > ln->ncells) + memset(ce + ln->ncells, 0, + (n - ln->ncells) * sizeof(struct libscols_cell)); + + ln->cells = ce; + ln->ncells = n; + return 0; +} + int scols_line_set_userdata(struct libscols_line *ln, void *data) { assert(ln); @@ -66,12 +114,41 @@ void *scols_line_get_userdata(struct libscols_line *ln) return ln ? ln->userdata : NULL; } -int scols_line_set_parent(struct libscols_line *ln, struct libscols_line *parent) +int scols_line_remove_child(struct libscols_line *ln, struct libscols_line *child) { assert(ln); - if (!ln) + assert(child); + + if (!ln || !child) + return -EINVAL; + list_del_init(&child->ln_children); + scols_unref_line(child); + + child->parent = NULL; + scols_unref_line(ln); + return 0; +} + +int scols_line_add_child(struct libscols_line *ln, struct libscols_line *child) +{ + assert(ln); + assert(child); + + if (!ln || !child) return -EINVAL; - ln->parent = parent; + + /* unref old<->parent */ + if (child->parent) + scols_line_remove_child(child->parent, child); + + /* new reference from parent to child */ + list_add_tail(&child->ln_children, &ln->ln_branch); + scols_ref_line(child); + + /* new reference from child to parent */ + child->parent = ln; + scols_ref_line(ln); + return 0; } @@ -108,12 +185,6 @@ const char *scols_line_get_color(struct libscols_line *ln) return ln ? ln->color : NULL; } -size_t scols_line_get_datasize(struct libscols_line *ln) -{ - assert(ln); - return ln ? ln->data_sz : 0; -} - size_t scols_line_get_ncells(struct libscols_line *ln) { assert(ln); @@ -127,12 +198,33 @@ struct libscols_cell *scols_line_get_cell(struct libscols_line *ln, if (!ln || n >= ln->ncells) return NULL; - return ln->cells[n]; + return &ln->cells[n]; +} + +/* just shortcut */ +int scols_line_set_data(struct libscols_line *ln, size_t n, const char *data) +{ + struct libscols_cell *ce = scols_line_get_cell(ln, n); + + if (!ce) + return -EINVAL; + return scols_cell_set_data(ce, data); +} + +/* just shortcut */ +int scols_line_refer_data(struct libscols_line *ln, size_t n, char *data) +{ + struct libscols_cell *ce = scols_line_get_cell(ln, n); + + if (!ce) + return -EINVAL; + return scols_cell_refer_data(ce, data); } struct libscols_line *scols_copy_line(struct libscols_line *ln) { struct libscols_line *ret; + size_t i; assert (ln); if (!ln) @@ -143,22 +235,16 @@ struct libscols_line *scols_copy_line(struct libscols_line *ln) return NULL; if (scols_line_set_color(ret, ln->color)) goto err; + if (scols_line_alloc_cells(ret, ln->ncells)) + goto err; + ret->userdata = ln->userdata; - ret->parent = ln->parent; - ret->data_sz = ln->data_sz; ret->ncells = ln->ncells; + ret->seqnum = ln->seqnum; - if (ln->ncells) { - size_t i; - - ret->cells = calloc(ln->ncells, sizeof(struct libscols_cell)); - if (!ret->cells) + for (i = 0; i < ret->ncells; ++i) { + if (scols_cell_copy_content(&ret->cells[i], &ln->cells[i])) goto err; - - for (i = 0; i < ret->ncells; ++i) { - if (scols_cell_copy_content(ret->cells[i], ln->cells[i])) - goto err; - } } return ret; diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h index f697cc8b9d..1bba01730b 100644 --- a/libsmartcols/src/smartcolsP.h +++ b/libsmartcols/src/smartcolsP.h @@ -24,6 +24,7 @@ # define assert(x) #endif + /* * Generic iterator */ @@ -37,9 +38,10 @@ struct libscols_iter { * Tree symbols */ struct libscols_symbols { - char *branch; - char *vert; - char *right; + int refcount; + char *branch; + char *vert; + char *right; }; /* @@ -48,6 +50,8 @@ struct libscols_symbols { struct libscols_cell { char *data; char *color; + + unsigned int is_ref; /* data is reference to foreign pointer */ }; @@ -77,11 +81,12 @@ struct libscols_column { */ struct libscols_line { int refcount; + size_t seqnum; + void *userdata; - size_t data_sz; /* strlen of all data */ char *color; /* default line color */ - struct libscols_cell **cells; /* array with data */ + struct libscols_cell *cells; /* array with data */ size_t ncells; /* number of cells */ struct list_head ln_lines; /* table lines */ @@ -91,4 +96,38 @@ struct libscols_line { struct libscols_line *parent; }; +/* + * The table + */ +struct libscols_table { + int refcount; + size_t ncols; /* number of columns */ + size_t nlines; /* number of lines */ + size_t termwidth; /* terminal width */ + int is_term; /* is a tty? */ + int flags; + int first_run; + + struct list_head tb_columns; + struct list_head tb_lines; + struct libscols_symbols *symbols; +}; + +#define IS_ITER_FORWARD(_i) ((_i)->direction == SCOLS_ITER_FORWARD) +#define IS_ITER_BACKWARD(_i) ((_i)->direction == SCOLS_ITER_BACKWARD) + +#define SCOLS_ITER_INIT(itr, list) \ + do { \ + (itr)->p = IS_ITER_FORWARD(itr) ? \ + (list)->next : (list)->prev; \ + (itr)->head = (list); \ + } while(0) + +#define SCOLS_ITER_ITERATE(itr, res, restype, member) \ + do { \ + res = list_entry((itr)->p, restype, member); \ + (itr)->p = IS_ITER_FORWARD(itr) ? \ + (itr)->p->next : (itr)->p->prev; \ + } while(0) + #endif /* _LIBSMARTCOLS_PRIVATE_H */ diff --git a/libsmartcols/src/symbols.c b/libsmartcols/src/symbols.c index 344ddcf53a..7f5f56f7a9 100644 --- a/libsmartcols/src/symbols.c +++ b/libsmartcols/src/symbols.c @@ -7,9 +7,32 @@ struct libscols_symbols *scols_new_symbols(void) { - return calloc(1, sizeof(struct libscols_symbols)); + struct libscols_symbols *sy = calloc(1, sizeof(struct libscols_symbols)); + + if (!sy) + return NULL; + sy->refcount = 1; + return sy; } + +void scols_ref_symbols(struct libscols_symbols *sy) +{ + if (sy) + sy->refcount++; +} + +void scols_unref_symbols(struct libscols_symbols *sy) +{ + if (sy && --sy->refcount <= 0) { + free(sy->branch); + free(sy->vert); + free(sy->right); + free(sy); + } +} + + int scols_symbols_set_branch(struct libscols_symbols *sb, const char *str) { char *p = NULL; @@ -86,18 +109,9 @@ struct libscols_symbols *scols_copy_symbols(const struct libscols_symbols *sb) if (!rc) return ret; - scols_free_symbols(ret); + scols_unref_symbols(ret); return NULL; } -void scols_free_symbols(struct libscols_symbols *sb) -{ - if (!sb) - return; - free(sb->branch); - free(sb->vert); - free(sb->right); - free(sb); -}