static struct libscols_line *get_line_with_id(struct libscols_table *tb, int col_id, const char *id) { struct libscols_line *ln; struct libscols_iter *itr = scols_new_iter(SCOLS_ITER_FORWARD); while (scols_table_next_line(tb, itr, &ln) == 0) { struct libscols_cell *ce = scols_line_get_cell(ln, col_id); const char *data = ce ? scols_cell_get_data(ce) : NULL; if (data && strcmp(data, id) == 0) break; } scols_free_iter(itr); return ln; }
static void compose_tree(struct libscols_table *tb, int parent_col, int id_col) { struct libscols_line *ln; struct libscols_iter *itr = scols_new_iter(SCOLS_ITER_FORWARD); while (scols_table_next_line(tb, itr, &ln) == 0) { struct libscols_line *parent = NULL; struct libscols_cell *ce = scols_line_get_cell(ln, parent_col); const char *data = ce ? scols_cell_get_data(ce) : NULL; if (data) parent = get_line_with_id(tb, id_col, data); if (parent) scols_line_add_child(parent, ln); } scols_free_iter(itr); }
/* It would be possible to use fdisk_table_to_string(), but we want some * extension to the output format, so let's do it without libfdisk */ static char *table_to_string(struct cfdisk *cf, struct fdisk_table *tb) { const struct fdisk_column *col; struct fdisk_partition *pa; struct fdisk_label *lb; struct fdisk_iter *itr = NULL; struct libscols_table *table = NULL; struct libscols_iter *s_itr = NULL; char *res = NULL; size_t i; int tree = 0; struct libscols_line *ln, *ln_cont = NULL; DBG(FRONTEND, ul_debug("table: convert to string")); assert(cf); assert(cf->cxt); assert(cf->cols); assert(tb); lb = fdisk_context_get_label(cf->cxt, NULL); assert(lb); itr = fdisk_new_iter(FDISK_ITER_FORWARD); if (!itr) goto done; /* get container (e.g. extended partition) */ while (fdisk_table_next_partition(tb, itr, &pa) == 0) { if (fdisk_partition_is_nested(pa)) { DBG(FRONTEND, ul_debug("table: nested detected, using tree")); tree = SCOLS_FL_TREE; break; } } table = scols_new_table(); if (!table) goto done; scols_table_enable_maxout(table, 1); /* headers */ for (i = 0; i < cf->ncols; i++) { col = fdisk_label_get_column(lb, cf->cols[i]); if (col) { int fl = col->scols_flags; if (tree && col->id == FDISK_COL_DEVICE) fl |= SCOLS_FL_TREE; if (!scols_table_new_column(table, col->name, col->width, fl)) goto done; } } /* data */ fdisk_reset_iter(itr, FDISK_ITER_FORWARD); while (fdisk_table_next_partition(tb, itr, &pa) == 0) { struct libscols_line *parent = fdisk_partition_is_nested(pa) ? ln_cont : NULL; ln = scols_table_new_line(table, parent); if (!ln) goto done; for (i = 0; i < cf->ncols; i++) { char *cdata = NULL; col = fdisk_label_get_column(lb, cf->cols[i]); if (!col) continue; if (fdisk_partition_to_string(pa, cf->cxt, col->id, &cdata)) continue; scols_line_refer_data(ln, i, cdata); } if (tree && fdisk_partition_is_container(pa)) ln_cont = ln; scols_line_set_userdata(ln, (void *) pa); fdisk_ref_partition(pa); } if (scols_table_is_empty(table)) goto done; scols_table_reduce_termwidth(table, ARROW_CURSOR_WIDTH); scols_print_table_to_string(table, &res); /* scols_* code might reorder lines, let's reorder @tb according to the * final output (it's no problem because partitions are addressed by * parno stored within struct fdisk_partition) */ /* remove all */ fdisk_reset_iter(itr, FDISK_ITER_FORWARD); while (fdisk_table_next_partition(tb, itr, &pa) == 0) fdisk_table_remove_partition(tb, pa); s_itr = scols_new_iter(SCOLS_ITER_FORWARD); if (!s_itr) goto done; /* add all in the right order (don't forget the output is tree) */ while (scols_table_next_line(table, s_itr, &ln) == 0) { if (scols_line_get_parent(ln)) continue; if (partition_from_scols(tb, ln)) break; } done: scols_unref_table(table); scols_free_iter(s_itr); fdisk_free_iter(itr); return res; }
/* * This function counts column width. * * For the SCOLS_FL_NOEXTREMES columns it is possible to call this function * two times. The first pass counts the width and average width. If the column * contains fields that are too large (a width greater than 2 * average) then * the column is marked as "extreme". In the second pass all extreme fields * are ignored and the column width is counted from non-extreme fields only. */ static int count_column_width(struct libscols_table *tb, struct libscols_column *cl, struct libscols_buffer *buf) { int rc = 0, no_header = 0; assert(tb); assert(cl); cl->width = 0; if (!cl->width_min) { if (cl->width_hint < 1 && scols_table_is_maxout(tb) && tb->is_term) { cl->width_min = (size_t) (cl->width_hint * tb->termwidth); if (cl->width_min && !is_last_column(cl)) cl->width_min--; } if (scols_cell_get_data(&cl->header)) { size_t len = mbs_safe_width(scols_cell_get_data(&cl->header)); cl->width_min = max(cl->width_min, len); } else no_header = 1; if (!cl->width_min) cl->width_min = 1; } if (scols_table_is_tree(tb)) { /* Count width for tree */ rc = scols_walk_tree(tb, cl, walk_count_cell_width, (void *) buf); if (rc) goto done; } else { /* Count width for list */ struct libscols_iter itr; struct libscols_line *ln; scols_reset_iter(&itr, SCOLS_ITER_FORWARD); while (scols_table_next_line(tb, &itr, &ln) == 0) { rc = count_cell_width(tb, ln, cl, buf); if (rc) goto done; } } if (scols_column_is_tree(cl) && has_groups(tb)) { /* We don't fill buffer with groups tree ascii art during width * calcualtion. The print function only enlarge grpset[] and we * calculate final width from grpset_size. */ size_t gprwidth = tb->grpset_size + 1; cl->width_treeart += gprwidth; cl->width_max += gprwidth; cl->width += gprwidth; if (cl->extreme_count) cl->extreme_sum += gprwidth; } if (cl->extreme_count && cl->width_avg == 0) { cl->width_avg = cl->extreme_sum / cl->extreme_count; if (cl->width_avg && cl->width_max > cl->width_avg * 2) cl->is_extreme = 1; } /* enlarge to minimal width */ if (cl->width < cl->width_min && !scols_column_is_strict_width(cl)) cl->width = cl->width_min; /* use absolute size for large columns */ else if (cl->width_hint >= 1 && cl->width < (size_t) cl->width_hint && cl->width_min < (size_t) cl->width_hint) cl->width = (size_t) cl->width_hint; /* Column without header and data, set minimal size to zero (default is 1) */ if (cl->width_max == 0 && no_header && cl->width_min == 1 && cl->width <= 1) cl->width = cl->width_min = 0; done: ON_DBG(COL, dbg_column(tb, cl)); return rc; }