]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libsmartcols: (groups) print group childrent after regualr tree
authorKarel Zak <kzak@redhat.com>
Fri, 3 May 2019 12:53:23 +0000 (14:53 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 3 May 2019 12:53:23 +0000 (14:53 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
libsmartcols/src/grouping.c
libsmartcols/src/print.c
libsmartcols/src/smartcolsP.h

index b767405aad9184cf5d37b986b07c3511582c745d..c8515cc92ec35bd4644a96c21107333c8fbee5c0 100644 (file)
@@ -468,7 +468,8 @@ int scols_groups_calculate_grpset(struct libscols_table *tb)
        }
 
        scols_groups_reset_state(tb);
-       DBG(TAB, ul_debugobj(tb, "<- done grpset calculate [top-level]"));
+       DBG(TAB, ul_debugobj(tb, "<- done grpset calculate [top-level, rc=%d, size=%zu]",
+                               rc, tb->grpset_size));
        return rc;
 }
 
@@ -489,6 +490,7 @@ void scols_groups_reset_state(struct libscols_table *tb)
                DBG(TAB, ul_debugobj(tb, " zeroize grpset"));
                memset(tb->grpset, 0, tb->grpset_size * sizeof(struct libscols_group *));
        }
+       tb->ngrpchlds_pending = 0;
 }
 
 static void add_member(struct libscols_group *gr, struct libscols_line *ln)
@@ -504,6 +506,30 @@ static void add_member(struct libscols_group *gr, struct libscols_line *ln)
        scols_ref_line(ln);
 }
 
+/*
+ * Returns first group which is ready to print group children.
+ *
+ * This function scans grpset[] in backward order and returns first group
+ * with SCOLS_GSTATE_CONT_CHILDREN or SCOLS_GSTATE_LAST_MEMBER state.
+ */
+struct libscols_group *scols_grpset_get_printable_children(struct libscols_table *tb)
+{
+       size_t i;
+
+       for (i = tb->grpset_size; i > 0; i -= SCOLS_GRPSET_CHUNKSIZ) {
+               struct libscols_group *gr = tb->grpset[i-1];
+
+               if (gr == NULL)
+                       continue;
+               if (gr->state == SCOLS_GSTATE_CONT_CHILDREN ||
+                   gr->state == SCOLS_GSTATE_LAST_MEMBER)
+                       return gr;
+       }
+
+       return NULL;
+}
+
+
 /**
  * scols_table_group_lines:
  * @tb: a pointer to a struct libscols_table instance
index 2a43e22432c8a42b1dbe578249123a00d4e313c9..526b0b76336aaf2f86cb33b18fb09a9bb7de3646 100644 (file)
@@ -839,49 +839,33 @@ static int print_tree_line(struct libscols_table *tb,
                goto done;
 
        children = has_children(ln);
-       gr_children = is_last_group_member(ln) && has_group_children(ln);
 
-       if (children || gr_children)
-               fput_children_open(tb);
+       /* we print group children in __scols_print_tree() after tree is printed */
+       gr_children = is_last_group_member(ln) && has_group_children(ln);
+       if (gr_children) {
+               last_in_table = 0;
+               tb->ngrpchlds_pending++;
+       }
 
-       /* print children */
        if (children) {
                struct list_head *p;
 
                DBG(LINE, ul_debugobj(ln, " printing children"));
 
+               fput_children_open(tb);
                list_for_each(p, &ln->ln_branch) {
                        struct libscols_line *chld =
                                        list_entry(p, struct libscols_line, ln_children);
-                       int last_child = !gr_children && p->next == &ln->ln_branch;
-
-                       rc = print_tree_line(tb, chld, buf, last_child, last_in_table && last_child);
-                       if (rc)
-                               goto done;
-               }
-       }
-
-       /* print group's children */
-       if (gr_children) {
-               struct list_head *p;
-
-               DBG(LINE, ul_debugobj(ln, " printing group children"));
-
-               list_for_each(p, &ln->group->gr_children) {
-                       struct libscols_line *chld =
-                                       list_entry(p, struct libscols_line, ln_children);
-                       int last_child = p->next == &ln->group->gr_children;
+                       int last_child = p->next == &ln->ln_branch;
 
                        rc = print_tree_line(tb, chld, buf, last_child, last_in_table && last_child);
                        if (rc)
                                goto done;
                }
-       }
-
-       if (children || gr_children)
                fput_children_close(tb);
+       }
 
-       if ((!children && !gr_children) || scols_table_is_json(tb))
+       if (!children || scols_table_is_json(tb))
                fput_line_close(tb, last, last_in_table);
 done:
        DBG(LINE, ul_debugobj(ln, "<- print tree line [rc=%d]", rc));
@@ -912,8 +896,40 @@ int __scols_print_tree(struct libscols_table *tb, struct libscols_buffer *buf)
                if (ln->parent || ln->parent_group)
                        continue;
                rc = print_tree_line(tb, ln, buf, ln == last, ln == last);
-       }
+               if (rc)
+                       break;
+
+               DBG(LINE, ul_debugobj(ln, " pending groups: %zu", tb->ngrpchlds_pending));
+
+               /* print group's children */
+               while (tb->ngrpchlds_pending) {
+                       struct libscols_group *gr = scols_grpset_get_printable_children(tb);
+                       struct list_head *p;
+
+                       DBG(LINE, ul_debugobj(ln, " printing group children [pending=%zu]", tb->ngrpchlds_pending));
+                       if (!gr) {
+                               DBG(LINE, ul_debugobj(ln, " *** ngrpchlds_pending counter invalid"));
+                               tb->ngrpchlds_pending = 0;
+                               break;
+                       }
 
+                       DBG(LINE, ul_debugobj(ln, " printing group children"));
+                       tb->ngrpchlds_pending--;
+                       list_for_each(p, &gr->gr_children) {
+                               struct libscols_line *chld =
+                                       list_entry(p, struct libscols_line, ln_children);
+                               int last_child = p->next == &gr->gr_children;
+
+                               rc = print_tree_line(tb, chld, buf, last_child,
+                                                       last_child
+                                                       && ln == last
+                                                       && tb->ngrpchlds_pending == 0);
+                               if (rc)
+                                       goto done;
+                       }
+               }
+       }
+done:
        return rc;
 }
 
index bbc8a98a149d32288bbad724b50a99d29cae180a..c063db212c5bf28324bd5304245b0c2a8a484644 100644 (file)
@@ -214,6 +214,7 @@ struct libscols_table {
        struct list_head        tb_groups;      /* all defined groups */
        struct libscols_group   **grpset;
        size_t                  grpset_size;
+       size_t                  ngrpchlds_pending;      /* groups with not yet printed children */
 
        struct libscols_symbols *symbols;
        struct libscols_cell    title;          /* optional table title (for humans) */
@@ -311,6 +312,7 @@ void scols_groups_fix_members_order(struct libscols_table *tb);
 int scols_groups_calculate_grpset(struct libscols_table *tb);
 int scols_groups_update_grpset(struct libscols_table *tb, struct libscols_line *ln);
 void scols_groups_reset_state(struct libscols_table *tb);
+struct libscols_group *scols_grpset_get_printable_children(struct libscols_table *tb);
 
 /*
  * calculate.c