2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 14:25:26 +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
table_print_table_line__(struct ds *line)
table_finish_line(struct ds *s)
{
while (ds_last(line) == ' ') {
line->length--;
while (ds_last(s) == ' ') {
s->length--;
}
puts(ds_cstr(line));
ds_clear(line);
ds_put_char(s, '\n');
}
static char *
@@ -228,31 +227,31 @@ table_format_timestamp__(void)
}
static void
table_print_timestamp__(const struct table *table)
table_print_timestamp__(const struct table *table, struct ds *s)
{
if (table->timestamp) {
char *s = table_format_timestamp__();
puts(s);
free(s);
char *timestamp = table_format_timestamp__();
ds_put_format(s, "%s\n", timestamp);
free(timestamp);
}
}
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;
struct ds line = DS_EMPTY_INITIALIZER;
int *widths;
size_t x, y;
if (n++ > 0) {
putchar('\n');
ds_put_char(s, '\n');
}
table_print_timestamp__(table);
table_print_timestamp__(table, s);
if (table->caption) {
puts(table->caption);
ds_put_format(s, "%s\n", table->caption);
}
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++) {
const struct column *column = &table->columns[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++) {
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 (x = 0; x < table->n_columns; x++) {
const char *text = cell_to_text(table_cell__(table, y, x), style);
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);
}
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;
size_t x, y;
if (n++ > 0) {
putchar('\n');
ds_put_char(s, '\n');
}
table_print_timestamp__(table);
table_print_timestamp__(table, s);
if (table->caption) {
puts(table->caption);
ds_put_format(s, "%s\n", table->caption);
}
for (y = 0; y < table->n_rows; y++) {
if (y > 0) {
putchar('\n');
ds_put_char(s, '\n');
}
for (x = 0; x < table->n_columns; x++) {
const char *text = cell_to_text(table_cell__(table, y, x), style);
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
table_escape_html_text__(const char *s, size_t n)
table_escape_html_text__(const char *content, size_t n, struct ds *s)
{
size_t i;
if (!strpbrk(content, "&<>\"")) {
ds_put_cstr(s, content);
} else {
size_t i;
for (i = 0; i < n; i++) {
char c = s[i];
for (i = 0; i < n; i++) {
char c = content[i];
switch (c) {
case '&':
fputs("&amp;", stdout);
break;
case '<':
fputs("&lt;", stdout);
break;
case '>':
fputs("&gt;", stdout);
break;
case '"':
fputs("&quot;", stdout);
break;
default:
putchar(c);
break;
switch (c) {
case '&':
ds_put_cstr(s, "&amp;");
break;
case '<':
ds_put_cstr(s, "&lt;");
break;
case '>':
ds_put_cstr(s, "&gt;");
break;
case '"':
ds_put_cstr(s, "&quot;");
break;
default:
ds_put_char(s, c);
break;
}
}
}
}
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;
printf(" <%s>", element);
ds_put_format(s, " <%s>", element);
for (p = content; *p; ) {
struct uuid uuid;
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;
} else {
table_escape_html_text__(p, 1);
table_escape_html_text__(p, 1, s);
p++;
}
}
printf("</%s>\n", element);
ds_put_format(s, "</%s>\n", element);
}
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;
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) {
table_print_html_cell__("caption", table->caption);
table_print_html_cell__("caption", table->caption, s);
}
if (style->headings) {
fputs(" <tr>\n", stdout);
ds_put_cstr(s, " <tr>\n");
for (x = 0; x < table->n_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++) {
fputs(" <tr>\n", stdout);
ds_put_cstr(s, " <tr>\n");
for (x = 0; x < table->n_columns; x++) {
const char *content;
content = cell_to_text(table_cell__(table, y, x), style);
if (!strcmp(table->columns[x].heading, "_uuid")) {
fputs(" <td><a name=\"", stdout);
table_escape_html_text__(content, strlen(content));
fputs("\">", stdout);
table_escape_html_text__(content, 8);
fputs("</a></td>\n", stdout);
ds_put_cstr(s, " <td><a name=\"");
table_escape_html_text__(content, strlen(content), s);
ds_put_cstr(s, "\">");
table_escape_html_text__(content, 8, s);
ds_put_cstr(s, "</a></td>\n");
} 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
table_print_csv_cell__(const char *content)
table_print_csv_cell__(const char *content, struct ds *s)
{
const char *p;
if (!strpbrk(content, "\n\",")) {
fputs(content, stdout);
ds_put_cstr(s, content);
} else {
putchar('"');
ds_put_char(s, '"');
for (p = content; *p != '\0'; p++) {
switch (*p) {
case '"':
fputs("\"\"", stdout);
ds_put_cstr(s, "\"\"");
break;
default:
putchar(*p);
ds_put_char(s, *p);
break;
}
}
putchar('"');
ds_put_char(s, '"');
}
}
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;
size_t x, y;
if (n++ > 0) {
putchar('\n');
ds_put_char(s, '\n');
}
table_print_timestamp__(table);
table_print_timestamp__(table, s);
if (table->caption) {
puts(table->caption);
ds_put_format(s, "%s\n", table->caption);
}
if (style->headings) {
for (x = 0; x < table->n_columns; x++) {
const struct column *column = &table->columns[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 (x = 0; x < table->n_columns; x++) {
if (x) {
putchar(',');
ds_put_char(s, ',');
}
table_print_csv_cell__(cell_to_text(table_cell__(table, y, x),
style));
style), s);
}
putchar('\n');
ds_put_char(s, '\n');
}
}
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;
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);
}
if (table->timestamp) {
char *s = table_format_timestamp__();
json_object_put_string(json, "time", s);
free(s);
json_object_put_nocopy(
json, "time",
json_string_create_nocopy(table_format_timestamp__()));
}
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);
char *s = json_to_string(json, style->json_flags);
json_to_ds(json, style->json_flags, s);
json_destroy(json);
puts(s);
free(s);
}
/* 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'. */
void
table_print(const struct table *table, const struct table_style *style)
{
switch (style->format) {
case TF_TABLE:
table_print_table__(table, style);
break;
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;
}
struct ds s = DS_EMPTY_INITIALIZER;
table_format(table, style, &s);
fputs(ds_cstr(&s), stdout);
ds_destroy(&s);
}
void

View File

@@ -21,6 +21,7 @@
#include <stddef.h>
#include "compiler.h"
struct ds;
struct table_style;
/* 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_print(const struct table *, const struct table_style *);
void table_format(const struct table *, const struct table_style *,
struct ds *);
void table_usage(void);
#endif /* table.h */