From b94932c063f642abe06e8f3fb72e3abe4416371f Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 3 May 2019 14:53:23 +0200 Subject: libsmartcols: (groups) print group childrent after regualr tree Signed-off-by: Karel Zak --- libsmartcols/src/grouping.c | 28 ++++++++++++++++- libsmartcols/src/print.c | 70 ++++++++++++++++++++++++++----------------- libsmartcols/src/smartcolsP.h | 2 ++ 3 files changed, 72 insertions(+), 28 deletions(-) (limited to 'libsmartcols') diff --git a/libsmartcols/src/grouping.c b/libsmartcols/src/grouping.c index b767405aa..c8515cc92 100644 --- a/libsmartcols/src/grouping.c +++ b/libsmartcols/src/grouping.c @@ -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 diff --git a/libsmartcols/src/print.c b/libsmartcols/src/print.c index 2a43e2243..526b0b763 100644 --- a/libsmartcols/src/print.c +++ b/libsmartcols/src/print.c @@ -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; } diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h index bbc8a98a1..c063db212 100644 --- a/libsmartcols/src/smartcolsP.h +++ b/libsmartcols/src/smartcolsP.h @@ -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 -- cgit v1.2.3-55-g7522