]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libsmartcols: add table struct, cleanup refcounting
authorKarel Zak <kzak@redhat.com>
Wed, 19 Mar 2014 15:29:39 +0000 (16:29 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 3 Apr 2014 10:29:16 +0000 (12:29 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
libsmartcols/src/cell.c
libsmartcols/src/line.c
libsmartcols/src/smartcolsP.h
libsmartcols/src/symbols.c

index 31934ab644cbd694d6c924722f23451b42cf8fe7..5e3ea6081bc37b66f191836d3b77e0be15e7ef1a 100644 (file)
@@ -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;
 }
 
index 589d5a2f6538e7bd2331aeed574d9d0252d8126f..80a1beabbed9bcebbfb9321c15b4e1fd95b6a102 100644 (file)
 
 #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;
index f697cc8b9d5c55a85334becd4d3d4cc35836192f..1bba01730ba101b1f2333b33c811a236eb64af80 100644 (file)
@@ -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 */
index 344ddcf53aeff1c88e8d8ee3006a8821a5e55da5..7f5f56f7a97f4544e732cfeadfc675046512d221 100644 (file)
@@ -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);
-}