diff --git a/libsmartcols/docs/libsmartcols-sections.txt b/libsmartcols/docs/libsmartcols-sections.txt index 6289e3a2f..4ac129141 100644 --- a/libsmartcols/docs/libsmartcols-sections.txt +++ b/libsmartcols/docs/libsmartcols-sections.txt @@ -143,6 +143,7 @@ scols_unref_table table_print scols_print_table scols_print_table_to_string +scols_table_print_range
diff --git a/libsmartcols/samples/tree.c b/libsmartcols/samples/tree.c index 52be7fbd5..d2afc4717 100644 --- a/libsmartcols/samples/tree.c +++ b/libsmartcols/samples/tree.c @@ -142,13 +142,15 @@ static void add_lines(struct libscols_table *tb, const char *dirname) static void __attribute__((__noreturn__)) usage(FILE *out) { fprintf(out, " %s [options] [ ...]\n\n", program_invocation_short_name); - fputs(" -c, --csv display a csv-like output\n", out); - fputs(" -i, --ascii use ascii characters only\n", out); - fputs(" -l, --list use list format output\n", out); - fputs(" -n, --noheadings don't print headings\n", out); - fputs(" -p, --pairs use key=\"value\" output format\n", out); - fputs(" -J, --json use JSON output format\n", out); - fputs(" -r, --raw use raw output format\n", out); + fputs(" -c, --csv display a csv-like output\n", out); + fputs(" -i, --ascii use ascii characters only\n", out); + fputs(" -l, --list use list format output\n", out); + fputs(" -n, --noheadings don't print headings\n", out); + fputs(" -p, --pairs use key=\"value\" output format\n", out); + fputs(" -J, --json use JSON output format\n", out); + fputs(" -r, --raw use raw output format\n", out); + fputs(" -S, --range-start first line to print\n", out); + fputs(" -E, --range-end last line to print\n", out); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } @@ -156,7 +158,8 @@ static void __attribute__((__noreturn__)) usage(FILE *out) int main(int argc, char *argv[]) { struct libscols_table *tb; - int c, notree = 0; + int c, notree = 0, nstart = -1, nend = -1; + static const struct option longopts[] = { { "ascii", 0, 0, 'i' }, @@ -166,7 +169,8 @@ int main(int argc, char *argv[]) { "pairs", 0, 0, 'p' }, { "json", 0, 0, 'J' }, { "raw", 0, 0, 'r' }, - + { "range-start",1, 0, 'S' }, + { "range-end", 1, 0, 'E' }, { NULL, 0, 0, 0 }, }; @@ -178,7 +182,7 @@ int main(int argc, char *argv[]) if (!tb) err(EXIT_FAILURE, "faild to create output table"); - while((c = getopt_long(argc, argv, "ciJlnpr", longopts, NULL)) != -1) { + while((c = getopt_long(argc, argv, "ciJlnprS:E:", longopts, NULL)) != -1) { switch(c) { case 'c': scols_table_set_column_separator(tb, ","); @@ -206,6 +210,12 @@ int main(int argc, char *argv[]) scols_table_enable_raw(tb, 1); notree = 1; break; + case 'S': + nstart = strtos32_or_err(optarg, "failed to parse range start") - 1; + break; + case 'E': + nend = strtos32_or_err(optarg, "failed to parse range end") - 1; + break; default: usage(stderr); } @@ -219,8 +229,21 @@ int main(int argc, char *argv[]) else while (optind < argc) add_lines(tb, argv[optind++]); - scols_print_table(tb); - scols_unref_table(tb); + if (nstart >= 0 || nend >= 0) { + /* print subset */ + struct libscols_line *start = NULL, *end = NULL; + if (nstart >= 0) + start = scols_table_get_line(tb, nstart); + if (nend >= 0) + end = scols_table_get_line(tb, nend); + + if (start || end) + scols_table_print_range(tb, start, end); + } else + /* print all table */ + scols_print_table(tb); + + scols_unref_table(tb); return EXIT_SUCCESS; } diff --git a/libsmartcols/src/libsmartcols.h.in b/libsmartcols/src/libsmartcols.h.in index 213d50af2..5f87d965f 100644 --- a/libsmartcols/src/libsmartcols.h.in +++ b/libsmartcols/src/libsmartcols.h.in @@ -246,6 +246,10 @@ extern int scols_sort_table(struct libscols_table *tb, struct libscols_column *c extern int scols_print_table(struct libscols_table *tb); extern int scols_print_table_to_string(struct libscols_table *tb, char **data); +extern int scols_table_print_range( struct libscols_table *tb, + struct libscols_line *start, + struct libscols_line *end); + #ifdef __cplusplus } #endif diff --git a/libsmartcols/src/libsmartcols.sym b/libsmartcols/src/libsmartcols.sym index 1a5505c47..250c06d6d 100644 --- a/libsmartcols/src/libsmartcols.sym +++ b/libsmartcols/src/libsmartcols.sym @@ -132,4 +132,5 @@ global: scols_table_get_title; scols_cell_get_flags; scols_cell_set_flags; + scols_table_print_range; } SMARTCOLS_2.27; diff --git a/libsmartcols/src/table.c b/libsmartcols/src/table.c index f91526bbd..fdbc7cd3f 100644 --- a/libsmartcols/src/table.c +++ b/libsmartcols/src/table.c @@ -572,13 +572,7 @@ err: * @tb: table * @n: column number (0..N) * - * This is a shortcut for - * - * ln = scols_new_line(); - * scols_line_set_....(cl, ...); - * scols_table_add_line(tb, ln); - * - * Returns: a newly allocate line + * Returns: a line or NULL */ struct libscols_line *scols_table_get_line(struct libscols_table *tb, size_t n) diff --git a/libsmartcols/src/table_print.c b/libsmartcols/src/table_print.c index 06fcabe9f..d8965726e 100644 --- a/libsmartcols/src/table_print.c +++ b/libsmartcols/src/table_print.c @@ -801,24 +801,39 @@ static int print_header(struct libscols_table *tb, struct libscols_buffer *buf) return rc; } -static int print_table(struct libscols_table *tb, struct libscols_buffer *buf) +static int print_range( struct libscols_table *tb, + struct libscols_buffer *buf, + struct libscols_iter *itr, + struct libscols_line *end) { int rc = 0; struct libscols_line *ln; - struct libscols_iter itr; assert(tb); - scols_reset_iter(&itr, SCOLS_ITER_FORWARD); - while (rc == 0 && scols_table_next_line(tb, &itr, &ln) == 0) { + while (rc == 0 && scols_table_next_line(tb, itr, &ln) == 0) { + fput_line_open(tb); rc = print_line(tb, ln, buf); - fput_line_close(tb, scols_iter_is_last(&itr)); + fput_line_close(tb, scols_iter_is_last(itr)); + + if (end && ln == end) + break; } return rc; + } +static int print_table(struct libscols_table *tb, struct libscols_buffer *buf) +{ + struct libscols_iter itr; + + scols_reset_iter(&itr, SCOLS_ITER_FORWARD); + return print_range(tb, buf, &itr, NULL); +} + + static int print_tree_line(struct libscols_table *tb, struct libscols_line *ln, struct libscols_buffer *buf, @@ -1202,33 +1217,14 @@ static size_t strlen_line(struct libscols_line *ln) return sz; } - - -/** - * scols_print_table: - * @tb: table - * - * Prints the table to the output stream. - * - * Returns: 0, a negative value in case of an error. - */ -int scols_print_table(struct libscols_table *tb) +static int initialize_printting(struct libscols_table *tb, struct libscols_buffer **buf) { - int rc = 0; size_t bufsz, extra_bufsz = 0; struct libscols_line *ln; struct libscols_iter itr; - struct libscols_buffer *buf; + int rc; - if (!tb) - return -EINVAL; - - DBG(TAB, ul_debugobj(tb, "printing")); - - if (list_empty(&tb->tb_lines)) { - DBG(TAB, ul_debugobj(tb, "ignore -- epmty table")); - return 0; - } + DBG(TAB, ul_debugobj(tb, "initialize printting")); if (!tb->symbols) scols_table_set_symbols(tb, NULL); /* use default */ @@ -1262,7 +1258,9 @@ int scols_print_table(struct libscols_table *tb) case SCOLS_FMT_EXPORT: { struct libscols_column *cl; + scols_reset_iter(&itr, SCOLS_ITER_FORWARD); + while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) { if (scols_column_is_hidden(cl)) continue; @@ -1275,7 +1273,6 @@ int scols_print_table(struct libscols_table *tb) break; } - /* * Enlarge buffer if necessary, the buffer should be large enough to * store line data and tree ascii art (or another decoration). @@ -1287,16 +1284,87 @@ int scols_print_table(struct libscols_table *tb) bufsz = sz; } - buf = new_buffer(bufsz + 1); /* data + space for \0 */ - if (!buf) + *buf = new_buffer(bufsz + 1); /* data + space for \0 */ + if (!*buf) return -ENOMEM; if (tb->format == SCOLS_FMT_HUMAN) { - rc = recount_widths(tb, buf); + rc = recount_widths(tb, *buf); if (rc != 0) - goto done; + goto err; } + return 0; +err: + free_buffer(*buf); + return rc; +} + +/** + * scola_table_print_range: + * @tb: table + * @start: first printed line or NULL to print from the beggin of the table + * @end: last printed line or NULL to print all from start. + * + * Returns: 0, a negative value in case of an error. + */ +int scols_table_print_range( struct libscols_table *tb, + struct libscols_line *start, + struct libscols_line *end) +{ + struct libscols_buffer *buf; + struct libscols_iter itr; + int rc; + + if (scols_table_is_tree(tb)) + return -EINVAL; + + DBG(TAB, ul_debugobj(tb, "printing range")); + + rc = initialize_printting(tb, &buf); + if (rc) + return rc; + + if (start) { + itr.direction = SCOLS_ITER_FORWARD; + itr.head = &tb->tb_lines; + itr.p = &start->ln_lines; + } else + scols_reset_iter(&itr, SCOLS_ITER_FORWARD); + + rc = print_range(tb, buf, &itr, end); + + free_buffer(buf); + return 0; +} + +/** + * scols_print_table: + * @tb: table + * + * Prints the table to the output stream. + * + * Returns: 0, a negative value in case of an error. + */ +int scols_print_table(struct libscols_table *tb) +{ + int rc = 0; + struct libscols_buffer *buf; + + if (!tb) + return -EINVAL; + + DBG(TAB, ul_debugobj(tb, "printing")); + + if (list_empty(&tb->tb_lines)) { + DBG(TAB, ul_debugobj(tb, "ignore -- epmty table")); + return 0; + } + + rc = initialize_printting(tb, &buf); + if (rc) + return rc; + fput_table_open(tb); if (tb->format == SCOLS_FMT_HUMAN)