(root)/
util-linux-2.39/
libsmartcols/
src/
walk.c
       1  #include "smartcolsP.h"
       2  
       3  static int walk_line(struct libscols_table *tb,
       4  		     struct libscols_line *ln,
       5  		     struct libscols_column *cl,
       6  		     int (*callback)(struct libscols_table *,
       7  			            struct libscols_line *,
       8  				    struct libscols_column *,
       9  				    void *),
      10  		    void *data)
      11  {
      12  	int rc = 0;
      13  
      14  /*	DBG(LINE, ul_debugobj(ln, " wall line")); */
      15  
      16  	/* we list group children in __scols_print_tree() after tree root node */
      17  	if (is_group_member(ln) && is_last_group_member(ln) && has_group_children(ln))
      18  		tb->ngrpchlds_pending++;
      19  
      20  	if (has_groups(tb))
      21  		rc = scols_groups_update_grpset(tb, ln);
      22  	if (rc == 0)
      23  		rc = callback(tb, ln, cl, data);
      24  
      25  	/* children */
      26  	if (rc == 0 && has_children(ln)) {
      27  		struct list_head *p;
      28  
      29  /*		DBG(LINE, ul_debugobj(ln, " children walk"));*/
      30  
      31  		list_for_each(p, &ln->ln_branch) {
      32  			struct libscols_line *chld = list_entry(p,
      33  					struct libscols_line, ln_children);
      34  
      35  			rc = walk_line(tb, chld, cl, callback, data);
      36  			if (rc)
      37  				break;
      38  		}
      39  	}
      40  
      41  /*	DBG(LINE, ul_debugobj(ln, "<- walk line done [rc=%d]", rc)); */
      42  	return rc;
      43  }
      44  
      45  /* last line in the tree? */
      46  int scols_walk_is_last(struct libscols_table *tb, struct libscols_line *ln)
      47  {
      48  	if (tb->walk_last_done == 0)
      49  		return 0;
      50  	if (tb->ngrpchlds_pending > 0)
      51  		return 0;
      52  	if (has_children(ln))
      53  		return 0;
      54  	if (is_tree_root(ln) && !is_last_tree_root(tb, ln))
      55  		return 0;
      56  	if (is_group_member(ln) && (!is_last_group_member(ln) || has_group_children(ln)))
      57  		return 0;
      58  	if (is_child(ln)) {
      59  		struct libscols_line *parent = ln->parent;
      60  
      61  		if (!is_last_child(ln))
      62  			return 0;
      63  		while (parent) {
      64  			if (is_child(parent) && !is_last_child(parent))
      65  				return 0;
      66  			if (!parent->parent)
      67  				break;
      68  			parent = parent->parent;
      69  		}
      70  		if (is_tree_root(parent) && !is_last_tree_root(tb, parent))
      71  			return 0;
      72  	}
      73  	if (is_group_child(ln) && !is_last_group_child(ln))
      74  		return 0;
      75  
      76  	DBG(LINE, ul_debugobj(ln, "last in table"));
      77  	return 1;
      78  }
      79  
      80  int scols_walk_tree(struct libscols_table *tb,
      81  		    struct libscols_column *cl,
      82  		    int (*callback)(struct libscols_table *,
      83  			            struct libscols_line *,
      84  				    struct libscols_column *,
      85  				    void *),
      86  		    void *data)
      87  {
      88  	int rc = 0;
      89  	struct libscols_line *ln;
      90  	struct libscols_iter itr;
      91  
      92  	assert(tb);
      93  /*	DBG(TAB, ul_debugobj(tb, ">> walk start"));*/
      94  
      95  	/* init */
      96  	tb->ngrpchlds_pending = 0;
      97  	tb->walk_last_tree_root = NULL;
      98  	tb->walk_last_done = 0;
      99  
     100  	if (has_groups(tb))
     101  		scols_groups_reset_state(tb);
     102  
     103  	/* set pointer to last tree root */
     104  	scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
     105  	while (scols_table_next_line(tb, &itr, &ln) == 0) {
     106  		if (!tb->walk_last_tree_root)
     107  			tb->walk_last_tree_root = ln;
     108  		if (is_child(ln) || is_group_child(ln))
     109  			continue;
     110  		tb->walk_last_tree_root = ln;
     111  	}
     112  
     113  	/* walk */
     114  	scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
     115  	while (rc == 0 && scols_table_next_line(tb, &itr, &ln) == 0) {
     116  		if (ln->parent || ln->parent_group)
     117  			continue;
     118  
     119  		if (tb->walk_last_tree_root == ln)
     120  			tb->walk_last_done = 1;
     121  		rc = walk_line(tb, ln, cl, callback, data);
     122  
     123  		/* walk group's children */
     124  		while (rc == 0 && tb->ngrpchlds_pending) {
     125  			struct libscols_group *gr = scols_grpset_get_printable_children(tb);
     126  			struct list_head *p;
     127  
     128  			DBG(LINE, ul_debugobj(ln, " walk group children [pending=%zu]", tb->ngrpchlds_pending));
     129  			if (!gr) {
     130  				DBG(LINE, ul_debugobj(ln, " *** ngrpchlds_pending counter invalid"));
     131  				tb->ngrpchlds_pending = 0;
     132  				break;
     133  			}
     134  
     135  			tb->ngrpchlds_pending--;
     136  
     137  			list_for_each(p, &gr->gr_children) {
     138  				struct libscols_line *chld =
     139  					list_entry(p, struct libscols_line, ln_children);
     140  
     141  				rc = walk_line(tb, chld, cl, callback, data);
     142  				if (rc)
     143  					break;
     144  			}
     145  		}
     146  	}
     147  
     148  	tb->ngrpchlds_pending = 0;
     149  	tb->walk_last_done = 0;
     150  /*	DBG(TAB, ul_debugobj(tb, "<< walk end [rc=%d]", rc));*/
     151  	return rc;
     152  }