From 3bb882be440ad37036382854f7b16047b1d52f16 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 25 Oct 2018 16:26:30 +0200 Subject: libsmartcols: split print.c into print.c, put.c and print-api.c Signed-off-by: Karel Zak --- libsmartcols/src/Makemodule.am | 2 + libsmartcols/src/fput.c | 97 +++++++++++++ libsmartcols/src/print-api.c | 208 ++++++++++++++++++++++++++ libsmartcols/src/print.c | 322 ++--------------------------------------- libsmartcols/src/smartcolsP.h | 22 +++ 5 files changed, 339 insertions(+), 312 deletions(-) create mode 100644 libsmartcols/src/fput.c create mode 100644 libsmartcols/src/print-api.c (limited to 'libsmartcols') diff --git a/libsmartcols/src/Makemodule.am b/libsmartcols/src/Makemodule.am index 3d18180f4..6dc4dd881 100644 --- a/libsmartcols/src/Makemodule.am +++ b/libsmartcols/src/Makemodule.am @@ -16,6 +16,8 @@ libsmartcols_la_SOURCES= \ libsmartcols/src/line.c \ libsmartcols/src/table.c \ libsmartcols/src/print.c \ + libsmartcols/src/fput.c \ + libsmartcols/src/print-api.c \ libsmartcols/src/version.c \ libsmartcols/src/buffer.c \ libsmartcols/src/calculate.c \ diff --git a/libsmartcols/src/fput.c b/libsmartcols/src/fput.c new file mode 100644 index 000000000..b00c3d8b8 --- /dev/null +++ b/libsmartcols/src/fput.c @@ -0,0 +1,97 @@ +#include "carefulputc.h" +#include "smartcolsP.h" + +void fput_indent(struct libscols_table *tb) +{ + int i; + + for (i = 0; i <= tb->indent; i++) + fputs(" ", tb->out); +} + +void fput_table_open(struct libscols_table *tb) +{ + tb->indent = 0; + + if (scols_table_is_json(tb)) { + fputc('{', tb->out); + fputs(linesep(tb), tb->out); + + fput_indent(tb); + fputs_quoted(tb->name, tb->out); + fputs(": [", tb->out); + fputs(linesep(tb), tb->out); + + tb->indent++; + tb->indent_last_sep = 1; + } +} + +void fput_table_close(struct libscols_table *tb) +{ + tb->indent--; + + if (scols_table_is_json(tb)) { + fput_indent(tb); + fputc(']', tb->out); + tb->indent--; + fputs(linesep(tb), tb->out); + fputc('}', tb->out); + tb->indent_last_sep = 1; + } +} + +void fput_children_open(struct libscols_table *tb) +{ + if (scols_table_is_json(tb)) { + fputc(',', tb->out); + fputs(linesep(tb), tb->out); + fput_indent(tb); + fputs("\"children\": [", tb->out); + } + /* between parent and child is separator */ + fputs(linesep(tb), tb->out); + tb->indent_last_sep = 1; + tb->indent++; + tb->termlines_used++; +} + +void fput_children_close(struct libscols_table *tb) +{ + tb->indent--; + + if (scols_table_is_json(tb)) { + fput_indent(tb); + fputc(']', tb->out); + fputs(linesep(tb), tb->out); + tb->indent_last_sep = 1; + } +} + +void fput_line_open(struct libscols_table *tb) +{ + if (scols_table_is_json(tb)) { + fput_indent(tb); + fputc('{', tb->out); + tb->indent_last_sep = 0; + } + tb->indent++; +} + +void fput_line_close(struct libscols_table *tb, int last, int last_in_table) +{ + tb->indent--; + if (scols_table_is_json(tb)) { + if (tb->indent_last_sep) + fput_indent(tb); + fputs(last ? "}" : "},", tb->out); + if (!tb->no_linesep) + fputs(linesep(tb), tb->out); + + } else if (tb->no_linesep == 0 && last_in_table == 0) { + fputs(linesep(tb), tb->out); + tb->termlines_used++; + } + + tb->indent_last_sep = 1; +} diff --git a/libsmartcols/src/print-api.c b/libsmartcols/src/print-api.c new file mode 100644 index 000000000..48b954baf --- /dev/null +++ b/libsmartcols/src/print-api.c @@ -0,0 +1,208 @@ +#include "smartcolsP.h" + +/** + * scola_table_print_range: + * @tb: table + * @start: first printed line or NULL to print from the begin of the table + * @end: last printed line or NULL to print all from start. + * + * If the start is the first line in the table than prints table header too. + * The header is printed only once. This does not work for trees. + * + * 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 = NULL; + struct libscols_iter itr; + int rc; + + if (scols_table_is_tree(tb)) + return -EINVAL; + + DBG(TAB, ul_debugobj(tb, "printing range from API")); + + rc = __scols_initialize_printing(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); + + if (!start || itr.p == tb->tb_lines.next) { + rc = __scols_print_header(tb, buf); + if (rc) + goto done; + } + + rc = __scols_print_range(tb, buf, &itr, end); +done: + __scols_cleanup_printing(tb, buf); + return rc; +} + +/** + * scols_table_print_range_to_string: + * @tb: table + * @start: first printed line or NULL to print from the beginning of the table + * @end: last printed line or NULL to print all from start. + * @data: pointer to the beginning of a memory area to print to + * + * The same as scols_table_print_range(), but prints to @data instead of + * stream. + * + * Returns: 0, a negative value in case of an error. + */ +#ifdef HAVE_OPEN_MEMSTREAM +int scols_table_print_range_to_string( struct libscols_table *tb, + struct libscols_line *start, + struct libscols_line *end, + char **data) +{ + FILE *stream, *old_stream; + size_t sz; + int rc; + + if (!tb) + return -EINVAL; + + DBG(TAB, ul_debugobj(tb, "printing range to string")); + + /* create a stream for output */ + stream = open_memstream(data, &sz); + if (!stream) + return -ENOMEM; + + old_stream = scols_table_get_stream(tb); + scols_table_set_stream(tb, stream); + rc = scols_table_print_range(tb, start, end); + fclose(stream); + scols_table_set_stream(tb, old_stream); + + return rc; +} +#else +int scols_table_print_range_to_string( + struct libscols_table *tb __attribute__((__unused__)), + struct libscols_line *start __attribute__((__unused__)), + struct libscols_line *end __attribute__((__unused__)), + char **data __attribute__((__unused__))) +{ + return -ENOSYS; +} +#endif + +static int do_print_table(struct libscols_table *tb, int *is_empty) +{ + int rc = 0; + struct libscols_buffer *buf = NULL; + + if (!tb) + return -EINVAL; + + DBG(TAB, ul_debugobj(tb, "printing")); + if (is_empty) + *is_empty = 0; + + if (list_empty(&tb->tb_columns)) { + DBG(TAB, ul_debugobj(tb, "error -- no columns")); + return -EINVAL; + } + if (list_empty(&tb->tb_lines)) { + DBG(TAB, ul_debugobj(tb, "ignore -- no lines")); + if (is_empty) + *is_empty = 1; + return 0; + } + + tb->header_printed = 0; + rc = __scols_initialize_printing(tb, &buf); + if (rc) + return rc; + + fput_table_open(tb); + + if (tb->format == SCOLS_FMT_HUMAN) + __scols_print_title(tb); + + rc = __scols_print_header(tb, buf); + if (rc) + goto done; + + if (scols_table_is_tree(tb)) + rc = __scols_print_tree(tb, buf); + else + rc = __scols_print_table(tb, buf); + + fput_table_close(tb); +done: + __scols_cleanup_printing(tb, buf); + return rc; +} + +/** + * scols_print_table: + * @tb: table + * + * Prints the table to the output stream and terminate by \n. + * + * Returns: 0, a negative value in case of an error. + */ +int scols_print_table(struct libscols_table *tb) +{ + int empty = 0; + int rc = do_print_table(tb, &empty); + + if (rc == 0 && !empty) + fputc('\n', tb->out); + return rc; +} + +/** + * scols_print_table_to_string: + * @tb: table + * @data: pointer to the beginning of a memory area to print to + * + * Prints the table to @data. + * + * Returns: 0, a negative value in case of an error. + */ +#ifdef HAVE_OPEN_MEMSTREAM +int scols_print_table_to_string(struct libscols_table *tb, char **data) +{ + FILE *stream, *old_stream; + size_t sz; + int rc; + + if (!tb) + return -EINVAL; + + DBG(TAB, ul_debugobj(tb, "printing to string")); + + /* create a stream for output */ + stream = open_memstream(data, &sz); + if (!stream) + return -ENOMEM; + + old_stream = scols_table_get_stream(tb); + scols_table_set_stream(tb, stream); + rc = do_print_table(tb, NULL); + fclose(stream); + scols_table_set_stream(tb, old_stream); + + return rc; +} +#else +int scols_print_table_to_string( + struct libscols_table *tb __attribute__((__unused__)), + char **data __attribute__((__unused__))) +{ + return -ENOSYS; +} +#endif diff --git a/libsmartcols/src/print.c b/libsmartcols/src/print.c index 7e56f466e..dc6637cea 100644 --- a/libsmartcols/src/print.c +++ b/libsmartcols/src/print.c @@ -476,101 +476,6 @@ int __cell_to_buffer(struct libscols_table *tb, return rc; } -static void fput_indent(struct libscols_table *tb) -{ - int i; - - for (i = 0; i <= tb->indent; i++) - fputs(" ", tb->out); -} - -static void fput_table_open(struct libscols_table *tb) -{ - tb->indent = 0; - - if (scols_table_is_json(tb)) { - fputc('{', tb->out); - fputs(linesep(tb), tb->out); - - fput_indent(tb); - fputs_quoted(tb->name, tb->out); - fputs(": [", tb->out); - fputs(linesep(tb), tb->out); - - tb->indent++; - tb->indent_last_sep = 1; - } -} - -static void fput_table_close(struct libscols_table *tb) -{ - tb->indent--; - - if (scols_table_is_json(tb)) { - fput_indent(tb); - fputc(']', tb->out); - tb->indent--; - fputs(linesep(tb), tb->out); - fputc('}', tb->out); - tb->indent_last_sep = 1; - } -} - -static void fput_children_open(struct libscols_table *tb) -{ - if (scols_table_is_json(tb)) { - fputc(',', tb->out); - fputs(linesep(tb), tb->out); - fput_indent(tb); - fputs("\"children\": [", tb->out); - } - /* between parent and child is separator */ - fputs(linesep(tb), tb->out); - tb->indent_last_sep = 1; - tb->indent++; - tb->termlines_used++; -} - -static void fput_children_close(struct libscols_table *tb) -{ - tb->indent--; - - if (scols_table_is_json(tb)) { - fput_indent(tb); - fputc(']', tb->out); - fputs(linesep(tb), tb->out); - tb->indent_last_sep = 1; - } -} - -static void fput_line_open(struct libscols_table *tb) -{ - if (scols_table_is_json(tb)) { - fput_indent(tb); - fputc('{', tb->out); - tb->indent_last_sep = 0; - } - tb->indent++; -} - -static void fput_line_close(struct libscols_table *tb, int last, int last_in_table) -{ - tb->indent--; - if (scols_table_is_json(tb)) { - if (tb->indent_last_sep) - fput_indent(tb); - fputs(last ? "}" : "},", tb->out); - if (!tb->no_linesep) - fputs(linesep(tb), tb->out); - - } else if (tb->no_linesep == 0 && last_in_table == 0) { - fputs(linesep(tb), tb->out); - tb->termlines_used++; - } - - tb->indent_last_sep = 1; -} - /* * Prints data. Data can be printed in more formats (raw, NAME=xxx pairs), and * control and non-printable characters can be encoded in the \x?? encoding. @@ -622,7 +527,7 @@ static int print_line(struct libscols_table *tb, return 0; } -static int print_title(struct libscols_table *tb) +int __scols_print_title(struct libscols_table *tb) { int rc, color = 0; mbs_align_t align; @@ -724,7 +629,7 @@ done: return rc; } -static int print_header(struct libscols_table *tb, struct libscols_buffer *buf) +int __scols_print_header(struct libscols_table *tb, struct libscols_buffer *buf) { int rc = 0; struct libscols_column *cl; @@ -765,7 +670,7 @@ static int print_header(struct libscols_table *tb, struct libscols_buffer *buf) } -static int print_range( struct libscols_table *tb, +int __scols_print_range(struct libscols_table *tb, struct libscols_buffer *buf, struct libscols_iter *itr, struct libscols_line *end) @@ -788,19 +693,19 @@ static int print_range( struct libscols_table *tb, break; if (!last && want_repeat_header(tb)) - print_header(tb, buf); + __scols_print_header(tb, buf); } return rc; } -static int print_table(struct libscols_table *tb, struct libscols_buffer *buf) +int __scols_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); + return __scols_print_range(tb, buf, &itr, NULL); } @@ -844,7 +749,7 @@ done: return rc; } -static int print_tree(struct libscols_table *tb, struct libscols_buffer *buf) +int __scols_print_tree(struct libscols_table *tb, struct libscols_buffer *buf) { int rc = 0; struct libscols_line *ln, *last = NULL; @@ -886,7 +791,7 @@ static size_t strlen_line(struct libscols_line *ln) return sz; } -static void cleanup_printing(struct libscols_table *tb, struct libscols_buffer *buf) +void __scols_cleanup_printing(struct libscols_table *tb, struct libscols_buffer *buf) { if (!tb) return; @@ -899,7 +804,7 @@ static void cleanup_printing(struct libscols_table *tb, struct libscols_buffer * } } -static int initialize_printing(struct libscols_table *tb, struct libscols_buffer **buf) +int __scols_initialize_printing(struct libscols_table *tb, struct libscols_buffer **buf) { size_t bufsz, extra_bufsz = 0; struct libscols_line *ln; @@ -996,214 +901,7 @@ static int initialize_printing(struct libscols_table *tb, struct libscols_buffer return 0; err: - cleanup_printing(tb, *buf); + __scols_cleanup_printing(tb, *buf); return rc; } -/** - * scola_table_print_range: - * @tb: table - * @start: first printed line or NULL to print from the begin of the table - * @end: last printed line or NULL to print all from start. - * - * If the start is the first line in the table than prints table header too. - * The header is printed only once. This does not work for trees. - * - * 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 = NULL; - struct libscols_iter itr; - int rc; - - if (scols_table_is_tree(tb)) - return -EINVAL; - - DBG(TAB, ul_debugobj(tb, "printing range from API")); - - rc = initialize_printing(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); - - if (!start || itr.p == tb->tb_lines.next) { - rc = print_header(tb, buf); - if (rc) - goto done; - } - - rc = print_range(tb, buf, &itr, end); -done: - cleanup_printing(tb, buf); - return rc; -} - -/** - * scols_table_print_range_to_string: - * @tb: table - * @start: first printed line or NULL to print from the beginning of the table - * @end: last printed line or NULL to print all from start. - * @data: pointer to the beginning of a memory area to print to - * - * The same as scols_table_print_range(), but prints to @data instead of - * stream. - * - * Returns: 0, a negative value in case of an error. - */ -#ifdef HAVE_OPEN_MEMSTREAM -int scols_table_print_range_to_string( struct libscols_table *tb, - struct libscols_line *start, - struct libscols_line *end, - char **data) -{ - FILE *stream, *old_stream; - size_t sz; - int rc; - - if (!tb) - return -EINVAL; - - DBG(TAB, ul_debugobj(tb, "printing range to string")); - - /* create a stream for output */ - stream = open_memstream(data, &sz); - if (!stream) - return -ENOMEM; - - old_stream = scols_table_get_stream(tb); - scols_table_set_stream(tb, stream); - rc = scols_table_print_range(tb, start, end); - fclose(stream); - scols_table_set_stream(tb, old_stream); - - return rc; -} -#else -int scols_table_print_range_to_string( - struct libscols_table *tb __attribute__((__unused__)), - struct libscols_line *start __attribute__((__unused__)), - struct libscols_line *end __attribute__((__unused__)), - char **data __attribute__((__unused__))) -{ - return -ENOSYS; -} -#endif - -static int __scols_print_table(struct libscols_table *tb, int *is_empty) -{ - int rc = 0; - struct libscols_buffer *buf = NULL; - - if (!tb) - return -EINVAL; - - DBG(TAB, ul_debugobj(tb, "printing")); - if (is_empty) - *is_empty = 0; - - if (list_empty(&tb->tb_columns)) { - DBG(TAB, ul_debugobj(tb, "error -- no columns")); - return -EINVAL; - } - if (list_empty(&tb->tb_lines)) { - DBG(TAB, ul_debugobj(tb, "ignore -- no lines")); - if (is_empty) - *is_empty = 1; - return 0; - } - - tb->header_printed = 0; - rc = initialize_printing(tb, &buf); - if (rc) - return rc; - - fput_table_open(tb); - - if (tb->format == SCOLS_FMT_HUMAN) - print_title(tb); - - rc = print_header(tb, buf); - if (rc) - goto done; - - if (scols_table_is_tree(tb)) - rc = print_tree(tb, buf); - else - rc = print_table(tb, buf); - - fput_table_close(tb); -done: - cleanup_printing(tb, buf); - return rc; -} - -/** - * scols_print_table: - * @tb: table - * - * Prints the table to the output stream and terminate by \n. - * - * Returns: 0, a negative value in case of an error. - */ -int scols_print_table(struct libscols_table *tb) -{ - int empty = 0; - int rc = __scols_print_table(tb, &empty); - - if (rc == 0 && !empty) - fputc('\n', tb->out); - return rc; -} - -/** - * scols_print_table_to_string: - * @tb: table - * @data: pointer to the beginning of a memory area to print to - * - * Prints the table to @data. - * - * Returns: 0, a negative value in case of an error. - */ -#ifdef HAVE_OPEN_MEMSTREAM -int scols_print_table_to_string(struct libscols_table *tb, char **data) -{ - FILE *stream, *old_stream; - size_t sz; - int rc; - - if (!tb) - return -EINVAL; - - DBG(TAB, ul_debugobj(tb, "printing to string")); - - /* create a stream for output */ - stream = open_memstream(data, &sz); - if (!stream) - return -ENOMEM; - - old_stream = scols_table_get_stream(tb); - scols_table_set_stream(tb, stream); - rc = __scols_print_table(tb, NULL); - fclose(stream); - scols_table_set_stream(tb, old_stream); - - return rc; -} -#else -int scols_print_table_to_string( - struct libscols_table *tb __attribute__((__unused__)), - char **data __attribute__((__unused__))) -{ - return -ENOSYS; -} -#endif - diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h index 94a2bc242..84f9b5be5 100644 --- a/libsmartcols/src/smartcolsP.h +++ b/libsmartcols/src/smartcolsP.h @@ -250,6 +250,28 @@ extern int __cell_to_buffer(struct libscols_table *tb, struct libscols_column *cl, struct libscols_buffer *buf); +void __scols_cleanup_printing(struct libscols_table *tb, struct libscols_buffer *buf); +int __scols_initialize_printing(struct libscols_table *tb, struct libscols_buffer **buf); +int __scols_print_tree(struct libscols_table *tb, struct libscols_buffer *buf); +int __scols_print_table(struct libscols_table *tb, struct libscols_buffer *buf); +int __scols_print_header(struct libscols_table *tb, struct libscols_buffer *buf); +int __scols_print_title(struct libscols_table *tb); +int __scols_print_range(struct libscols_table *tb, + struct libscols_buffer *buf, + struct libscols_iter *itr, + struct libscols_line *end); + +/* + * fput.c + */ +extern void fput_indent(struct libscols_table *tb); +extern void fput_table_open(struct libscols_table *tb); +extern void fput_table_close(struct libscols_table *tb); +extern void fput_children_open(struct libscols_table *tb); +extern void fput_children_close(struct libscols_table *tb); +extern void fput_line_open(struct libscols_table *tb); +extern void fput_line_close(struct libscols_table *tb, int last, int last_in_table); + static inline int is_last_child(struct libscols_line *ln) { if (!ln || !ln->parent) -- cgit v1.2.3-55-g7522