2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-04 00:05:15 +00:00

table: New function table_format() for formatting a table as a string.

This will be useful for daemonized ovn-nbctl.

Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jakub Sitnicki <jkbs@redhat.com>
This commit is contained in:
Ben Pfaff
2018-07-09 16:34:00 -07:00
parent 6f231f7c3a
commit cb139fa8b3
2 changed files with 133 additions and 116 deletions

View File

@@ -212,13 +212,12 @@ table_add_cell(struct table *table)
} }
static void static void
table_print_table_line__(struct ds *line) table_finish_line(struct ds *s)
{ {
while (ds_last(line) == ' ') { while (ds_last(s) == ' ') {
line->length--; s->length--;
} }
puts(ds_cstr(line)); ds_put_char(s, '\n');
ds_clear(line);
} }
static char * static char *
@@ -228,31 +227,31 @@ table_format_timestamp__(void)
} }
static void static void
table_print_timestamp__(const struct table *table) table_print_timestamp__(const struct table *table, struct ds *s)
{ {
if (table->timestamp) { if (table->timestamp) {
char *s = table_format_timestamp__(); char *timestamp = table_format_timestamp__();
puts(s); ds_put_format(s, "%s\n", timestamp);
free(s); free(timestamp);
} }
} }
static void static void
table_print_table__(const struct table *table, const struct table_style *style) table_print_table__(const struct table *table, const struct table_style *style,
struct ds *s)
{ {
static int n = 0; static int n = 0;
struct ds line = DS_EMPTY_INITIALIZER;
int *widths; int *widths;
size_t x, y; size_t x, y;
if (n++ > 0) { if (n++ > 0) {
putchar('\n'); ds_put_char(s, '\n');
} }
table_print_timestamp__(table); table_print_timestamp__(table, s);
if (table->caption) { if (table->caption) {
puts(table->caption); ds_put_format(s, "%s\n", table->caption);
} }
widths = xzalloc(table->n_columns * sizeof *widths); widths = xzalloc(table->n_columns * sizeof *widths);
@@ -286,222 +285,229 @@ table_print_table__(const struct table *table, const struct table_style *style)
for (x = 0; x < table->n_columns; x++) { for (x = 0; x < table->n_columns; x++) {
const struct column *column = &table->columns[x]; const struct column *column = &table->columns[x];
if (x) { if (x) {
ds_put_char(&line, ' '); ds_put_char(s, ' ');
} }
ds_put_format(&line, "%-*s", widths[x], column->heading); ds_put_format(s, "%-*s", widths[x], column->heading);
} }
table_print_table_line__(&line); table_finish_line(s);
for (x = 0; x < table->n_columns; x++) { for (x = 0; x < table->n_columns; x++) {
if (x) { if (x) {
ds_put_char(&line, ' '); ds_put_char(s, ' ');
} }
ds_put_char_multiple(&line, '-', widths[x]); ds_put_char_multiple(s, '-', widths[x]);
} }
table_print_table_line__(&line); table_finish_line(s);
} }
for (y = 0; y < table->n_rows; y++) { for (y = 0; y < table->n_rows; y++) {
for (x = 0; x < table->n_columns; x++) { for (x = 0; x < table->n_columns; x++) {
const char *text = cell_to_text(table_cell__(table, y, x), style); const char *text = cell_to_text(table_cell__(table, y, x), style);
if (x) { if (x) {
ds_put_char(&line, ' '); ds_put_char(s, ' ');
} }
ds_put_format(&line, "%-*.*s", widths[x], widths[x], text); ds_put_format(s, "%-*.*s", widths[x], widths[x], text);
} }
table_print_table_line__(&line); table_finish_line(s);
} }
ds_destroy(&line);
free(widths); free(widths);
} }
static void static void
table_print_list__(const struct table *table, const struct table_style *style) table_print_list__(const struct table *table, const struct table_style *style,
struct ds *s)
{ {
static int n = 0; static int n = 0;
size_t x, y; size_t x, y;
if (n++ > 0) { if (n++ > 0) {
putchar('\n'); ds_put_char(s, '\n');
} }
table_print_timestamp__(table); table_print_timestamp__(table, s);
if (table->caption) { if (table->caption) {
puts(table->caption); ds_put_format(s, "%s\n", table->caption);
} }
for (y = 0; y < table->n_rows; y++) { for (y = 0; y < table->n_rows; y++) {
if (y > 0) { if (y > 0) {
putchar('\n'); ds_put_char(s, '\n');
} }
for (x = 0; x < table->n_columns; x++) { for (x = 0; x < table->n_columns; x++) {
const char *text = cell_to_text(table_cell__(table, y, x), style); const char *text = cell_to_text(table_cell__(table, y, x), style);
if (style->headings) { if (style->headings) {
printf("%-20s: ", table->columns[x].heading); ds_put_format(s, "%-20s: ", table->columns[x].heading);
} }
puts(text); ds_put_format(s, "%s\n", text);
} }
} }
} }
static void static void
table_escape_html_text__(const char *s, size_t n) table_escape_html_text__(const char *content, size_t n, struct ds *s)
{ {
if (!strpbrk(content, "&<>\"")) {
ds_put_cstr(s, content);
} else {
size_t i; size_t i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
char c = s[i]; char c = content[i];
switch (c) { switch (c) {
case '&': case '&':
fputs("&amp;", stdout); ds_put_cstr(s, "&amp;");
break; break;
case '<': case '<':
fputs("&lt;", stdout); ds_put_cstr(s, "&lt;");
break; break;
case '>': case '>':
fputs("&gt;", stdout); ds_put_cstr(s, "&gt;");
break; break;
case '"': case '"':
fputs("&quot;", stdout); ds_put_cstr(s, "&quot;");
break; break;
default: default:
putchar(c); ds_put_char(s, c);
break; break;
} }
} }
}
} }
static void static void
table_print_html_cell__(const char *element, const char *content) table_print_html_cell__(const char *element, const char *content, struct ds *s)
{ {
const char *p; const char *p;
printf(" <%s>", element); ds_put_format(s, " <%s>", element);
for (p = content; *p; ) { for (p = content; *p; ) {
struct uuid uuid; struct uuid uuid;
if (uuid_from_string_prefix(&uuid, p)) { if (uuid_from_string_prefix(&uuid, p)) {
printf("<a href=\"#%.*s\">%.*s</a>", UUID_LEN, p, 8, p); ds_put_format(s, "<a href=\"#%.*s\">%.*s</a>", UUID_LEN, p, 8, p);
p += UUID_LEN; p += UUID_LEN;
} else { } else {
table_escape_html_text__(p, 1); table_escape_html_text__(p, 1, s);
p++; p++;
} }
} }
printf("</%s>\n", element); ds_put_format(s, "</%s>\n", element);
} }
static void static void
table_print_html__(const struct table *table, const struct table_style *style) table_print_html__(const struct table *table, const struct table_style *style,
struct ds *s)
{ {
size_t x, y; size_t x, y;
table_print_timestamp__(table); table_print_timestamp__(table, s);
fputs("<table border=1>\n", stdout); ds_put_cstr(s, "<table border=1>\n");
if (table->caption) { if (table->caption) {
table_print_html_cell__("caption", table->caption); table_print_html_cell__("caption", table->caption, s);
} }
if (style->headings) { if (style->headings) {
fputs(" <tr>\n", stdout); ds_put_cstr(s, " <tr>\n");
for (x = 0; x < table->n_columns; x++) { for (x = 0; x < table->n_columns; x++) {
const struct column *column = &table->columns[x]; const struct column *column = &table->columns[x];
table_print_html_cell__("th", column->heading); table_print_html_cell__("th", column->heading, s);
} }
fputs(" </tr>\n", stdout); ds_put_cstr(s, " </tr>\n");
} }
for (y = 0; y < table->n_rows; y++) { for (y = 0; y < table->n_rows; y++) {
fputs(" <tr>\n", stdout); ds_put_cstr(s, " <tr>\n");
for (x = 0; x < table->n_columns; x++) { for (x = 0; x < table->n_columns; x++) {
const char *content; const char *content;
content = cell_to_text(table_cell__(table, y, x), style); content = cell_to_text(table_cell__(table, y, x), style);
if (!strcmp(table->columns[x].heading, "_uuid")) { if (!strcmp(table->columns[x].heading, "_uuid")) {
fputs(" <td><a name=\"", stdout); ds_put_cstr(s, " <td><a name=\"");
table_escape_html_text__(content, strlen(content)); table_escape_html_text__(content, strlen(content), s);
fputs("\">", stdout); ds_put_cstr(s, "\">");
table_escape_html_text__(content, 8); table_escape_html_text__(content, 8, s);
fputs("</a></td>\n", stdout); ds_put_cstr(s, "</a></td>\n");
} else { } else {
table_print_html_cell__("td", content); table_print_html_cell__("td", content, s);
} }
} }
fputs(" </tr>\n", stdout); ds_put_cstr(s, " </tr>\n");
} }
fputs("</table>\n", stdout); ds_put_cstr(s, "</table>\n");
} }
static void static void
table_print_csv_cell__(const char *content) table_print_csv_cell__(const char *content, struct ds *s)
{ {
const char *p; const char *p;
if (!strpbrk(content, "\n\",")) { if (!strpbrk(content, "\n\",")) {
fputs(content, stdout); ds_put_cstr(s, content);
} else { } else {
putchar('"'); ds_put_char(s, '"');
for (p = content; *p != '\0'; p++) { for (p = content; *p != '\0'; p++) {
switch (*p) { switch (*p) {
case '"': case '"':
fputs("\"\"", stdout); ds_put_cstr(s, "\"\"");
break; break;
default: default:
putchar(*p); ds_put_char(s, *p);
break; break;
} }
} }
putchar('"'); ds_put_char(s, '"');
} }
} }
static void static void
table_print_csv__(const struct table *table, const struct table_style *style) table_print_csv__(const struct table *table, const struct table_style *style,
struct ds *s)
{ {
static int n = 0; static int n = 0;
size_t x, y; size_t x, y;
if (n++ > 0) { if (n++ > 0) {
putchar('\n'); ds_put_char(s, '\n');
} }
table_print_timestamp__(table); table_print_timestamp__(table, s);
if (table->caption) { if (table->caption) {
puts(table->caption); ds_put_format(s, "%s\n", table->caption);
} }
if (style->headings) { if (style->headings) {
for (x = 0; x < table->n_columns; x++) { for (x = 0; x < table->n_columns; x++) {
const struct column *column = &table->columns[x]; const struct column *column = &table->columns[x];
if (x) { if (x) {
putchar(','); ds_put_char(s, ',');
} }
table_print_csv_cell__(column->heading); table_print_csv_cell__(column->heading, s);
} }
putchar('\n'); ds_put_char(s, '\n');
} }
for (y = 0; y < table->n_rows; y++) { for (y = 0; y < table->n_rows; y++) {
for (x = 0; x < table->n_columns; x++) { for (x = 0; x < table->n_columns; x++) {
if (x) { if (x) {
putchar(','); ds_put_char(s, ',');
} }
table_print_csv_cell__(cell_to_text(table_cell__(table, y, x), table_print_csv_cell__(cell_to_text(table_cell__(table, y, x),
style)); style), s);
} }
putchar('\n'); ds_put_char(s, '\n');
} }
} }
static void static void
table_print_json__(const struct table *table, const struct table_style *style) table_print_json__(const struct table *table, const struct table_style *style,
struct ds *s)
{ {
struct json *json, *headings, *data; struct json *json, *headings, *data;
size_t x, y; size_t x, y;
@@ -511,9 +517,9 @@ table_print_json__(const struct table *table, const struct table_style *style)
json_object_put_string(json, "caption", table->caption); json_object_put_string(json, "caption", table->caption);
} }
if (table->timestamp) { if (table->timestamp) {
char *s = table_format_timestamp__(); json_object_put_nocopy(
json_object_put_string(json, "time", s); json, "time",
free(s); json_string_create_nocopy(table_format_timestamp__()));
} }
headings = json_array_create_empty(); headings = json_array_create_empty();
@@ -540,10 +546,8 @@ table_print_json__(const struct table *table, const struct table_style *style)
} }
json_object_put(json, "data", data); json_object_put(json, "data", data);
char *s = json_to_string(json, style->json_flags); json_to_ds(json, style->json_flags, s);
json_destroy(json); json_destroy(json);
puts(s);
free(s);
} }
/* Parses 'format' as the argument to a --format command line option, updating /* Parses 'format' as the argument to a --format command line option, updating
@@ -582,31 +586,41 @@ table_parse_cell_format(struct table_style *style, const char *format)
} }
} }
void
table_format(const struct table *table, const struct table_style *style,
struct ds *s)
{
switch (style->format) {
case TF_TABLE:
table_print_table__(table, style, s);
break;
case TF_LIST:
table_print_list__(table, style, s);
break;
case TF_HTML:
table_print_html__(table, style, s);
break;
case TF_CSV:
table_print_csv__(table, style, s);
break;
case TF_JSON:
table_print_json__(table, style, s);
break;
}
}
/* Outputs 'table' on stdout in the specified 'style'. */ /* Outputs 'table' on stdout in the specified 'style'. */
void void
table_print(const struct table *table, const struct table_style *style) table_print(const struct table *table, const struct table_style *style)
{ {
switch (style->format) { struct ds s = DS_EMPTY_INITIALIZER;
case TF_TABLE: table_format(table, style, &s);
table_print_table__(table, style); fputs(ds_cstr(&s), stdout);
break; ds_destroy(&s);
case TF_LIST:
table_print_list__(table, style);
break;
case TF_HTML:
table_print_html__(table, style);
break;
case TF_CSV:
table_print_csv__(table, style);
break;
case TF_JSON:
table_print_json__(table, style);
break;
}
} }
void void

View File

@@ -21,6 +21,7 @@
#include <stddef.h> #include <stddef.h>
#include "compiler.h" #include "compiler.h"
struct ds;
struct table_style; struct table_style;
/* Manipulating tables and their rows and columns. */ /* Manipulating tables and their rows and columns. */
@@ -128,6 +129,8 @@ void table_parse_format(struct table_style *, const char *format);
void table_parse_cell_format(struct table_style *, const char *format); void table_parse_cell_format(struct table_style *, const char *format);
void table_print(const struct table *, const struct table_style *); void table_print(const struct table *, const struct table_style *);
void table_format(const struct table *, const struct table_style *,
struct ds *);
void table_usage(void); void table_usage(void);
#endif /* table.h */ #endif /* table.h */