mirror of
https://github.com/openvswitch/ovs
synced 2025-09-03 15:55:19 +00:00
table: Add new "bare" output formatting options.
--format=list corresponds to the output format that "ovs-vsctl list" has always used. --bare is easier for scripts to parse.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2009, 2010 Nicira Networks
|
/* Copyright (c) 2009, 2010, 2011 Nicira Networks
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -625,6 +625,20 @@ ovsdb_atom_to_string(const union ovsdb_atom *atom, enum ovsdb_atomic_type type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Appends 'atom' (which has the given 'type') to 'out', in a bare string
|
||||||
|
* format that cannot be parsed uniformly back into a datum but is easier for
|
||||||
|
* shell scripts, etc., to deal with. */
|
||||||
|
void
|
||||||
|
ovsdb_atom_to_bare(const union ovsdb_atom *atom, enum ovsdb_atomic_type type,
|
||||||
|
struct ds *out)
|
||||||
|
{
|
||||||
|
if (type == OVSDB_TYPE_STRING) {
|
||||||
|
ds_put_cstr(out, atom->string);
|
||||||
|
} else {
|
||||||
|
ovsdb_atom_to_string(atom, type, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct ovsdb_error *
|
static struct ovsdb_error *
|
||||||
check_string_constraints(const char *s,
|
check_string_constraints(const char *s,
|
||||||
const struct ovsdb_string_constraints *c)
|
const struct ovsdb_string_constraints *c)
|
||||||
@@ -1445,6 +1459,29 @@ ovsdb_datum_to_string(const struct ovsdb_datum *datum,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Appends to 'out' the 'datum' (with the given 'type') in a bare string format
|
||||||
|
* that cannot be parsed uniformly back into a datum but is easier for shell
|
||||||
|
* scripts, etc., to deal with. */
|
||||||
|
void
|
||||||
|
ovsdb_datum_to_bare(const struct ovsdb_datum *datum,
|
||||||
|
const struct ovsdb_type *type, struct ds *out)
|
||||||
|
{
|
||||||
|
bool is_map = ovsdb_type_is_map(type);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < datum->n; i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
ds_put_cstr(out, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
ovsdb_atom_to_bare(&datum->keys[i], type->key.type, out);
|
||||||
|
if (is_map) {
|
||||||
|
ds_put_char(out, '=');
|
||||||
|
ovsdb_atom_to_bare(&datum->values[i], type->value.type, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Initializes 'datum' as a string-to-string map whose contents are taken from
|
/* Initializes 'datum' as a string-to-string map whose contents are taken from
|
||||||
* 'sh'. Destroys 'sh'. */
|
* 'sh'. Destroys 'sh'. */
|
||||||
void
|
void
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2009, 2010 Nicira Networks
|
/* Copyright (c) 2009, 2010, 2011 Nicira Networks
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -94,6 +94,8 @@ char *ovsdb_atom_from_string(union ovsdb_atom *,
|
|||||||
WARN_UNUSED_RESULT;
|
WARN_UNUSED_RESULT;
|
||||||
void ovsdb_atom_to_string(const union ovsdb_atom *, enum ovsdb_atomic_type,
|
void ovsdb_atom_to_string(const union ovsdb_atom *, enum ovsdb_atomic_type,
|
||||||
struct ds *);
|
struct ds *);
|
||||||
|
void ovsdb_atom_to_bare(const union ovsdb_atom *, enum ovsdb_atomic_type,
|
||||||
|
struct ds *);
|
||||||
|
|
||||||
struct ovsdb_error *ovsdb_atom_check_constraints(
|
struct ovsdb_error *ovsdb_atom_check_constraints(
|
||||||
const union ovsdb_atom *, const struct ovsdb_base_type *)
|
const union ovsdb_atom *, const struct ovsdb_base_type *)
|
||||||
@@ -167,6 +169,8 @@ char *ovsdb_datum_from_string(struct ovsdb_datum *,
|
|||||||
WARN_UNUSED_RESULT;
|
WARN_UNUSED_RESULT;
|
||||||
void ovsdb_datum_to_string(const struct ovsdb_datum *,
|
void ovsdb_datum_to_string(const struct ovsdb_datum *,
|
||||||
const struct ovsdb_type *, struct ds *);
|
const struct ovsdb_type *, struct ds *);
|
||||||
|
void ovsdb_datum_to_bare(const struct ovsdb_datum *,
|
||||||
|
const struct ovsdb_type *, struct ds *);
|
||||||
|
|
||||||
void ovsdb_datum_from_shash(struct ovsdb_datum *, struct shash *);
|
void ovsdb_datum_from_shash(struct ovsdb_datum *, struct shash *);
|
||||||
|
|
||||||
|
44
lib/table.c
44
lib/table.c
@@ -36,7 +36,7 @@ cell_to_text(struct cell *cell, const struct table_style *style)
|
|||||||
if (cell->json) {
|
if (cell->json) {
|
||||||
if (style->cell_format == CF_JSON || !cell->type) {
|
if (style->cell_format == CF_JSON || !cell->type) {
|
||||||
cell->text = json_to_string(cell->json, JSSF_SORT);
|
cell->text = json_to_string(cell->json, JSSF_SORT);
|
||||||
} else if (style->cell_format == CF_STRING) {
|
} else {
|
||||||
struct ovsdb_datum datum;
|
struct ovsdb_datum datum;
|
||||||
struct ovsdb_error *error;
|
struct ovsdb_error *error;
|
||||||
struct ds s;
|
struct ds s;
|
||||||
@@ -45,14 +45,16 @@ cell_to_text(struct cell *cell, const struct table_style *style)
|
|||||||
NULL);
|
NULL);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
ds_init(&s);
|
ds_init(&s);
|
||||||
|
if (style->cell_format == CF_STRING) {
|
||||||
ovsdb_datum_to_string(&datum, cell->type, &s);
|
ovsdb_datum_to_string(&datum, cell->type, &s);
|
||||||
|
} else {
|
||||||
|
ovsdb_datum_to_bare(&datum, cell->type, &s);
|
||||||
|
}
|
||||||
ovsdb_datum_destroy(&datum, cell->type);
|
ovsdb_datum_destroy(&datum, cell->type);
|
||||||
cell->text = ds_steal_cstr(&s);
|
cell->text = ds_steal_cstr(&s);
|
||||||
} else {
|
} else {
|
||||||
cell->text = json_to_string(cell->json, JSSF_SORT);
|
cell->text = json_to_string(cell->json, JSSF_SORT);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cell->text = xstrdup("");
|
cell->text = xstrdup("");
|
||||||
@@ -272,6 +274,34 @@ table_print_table__(const struct table *table, const struct table_style *style)
|
|||||||
free(widths);
|
free(widths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
table_print_list__(const struct table *table, const struct table_style *style)
|
||||||
|
{
|
||||||
|
static int n = 0;
|
||||||
|
size_t x, y;
|
||||||
|
|
||||||
|
if (n++ > 0) {
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table->caption) {
|
||||||
|
puts(table->caption);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (y = 0; y < table->n_rows; y++) {
|
||||||
|
if (y > 0) {
|
||||||
|
putchar('\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);
|
||||||
|
}
|
||||||
|
puts(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
table_escape_html_text__(const char *s, size_t n)
|
table_escape_html_text__(const char *s, size_t n)
|
||||||
{
|
{
|
||||||
@@ -469,6 +499,8 @@ table_parse_format(struct table_style *style, const char *format)
|
|||||||
{
|
{
|
||||||
if (!strcmp(format, "table")) {
|
if (!strcmp(format, "table")) {
|
||||||
style->format = TF_TABLE;
|
style->format = TF_TABLE;
|
||||||
|
} else if (!strcmp(format, "list")) {
|
||||||
|
style->format = TF_LIST;
|
||||||
} else if (!strcmp(format, "html")) {
|
} else if (!strcmp(format, "html")) {
|
||||||
style->format = TF_HTML;
|
style->format = TF_HTML;
|
||||||
} else if (!strcmp(format, "csv")) {
|
} else if (!strcmp(format, "csv")) {
|
||||||
@@ -487,6 +519,8 @@ table_parse_cell_format(struct table_style *style, const char *format)
|
|||||||
{
|
{
|
||||||
if (!strcmp(format, "string")) {
|
if (!strcmp(format, "string")) {
|
||||||
style->cell_format = CF_STRING;
|
style->cell_format = CF_STRING;
|
||||||
|
} else if (!strcmp(format, "bare")) {
|
||||||
|
style->cell_format = CF_BARE;
|
||||||
} else if (!strcmp(format, "json")) {
|
} else if (!strcmp(format, "json")) {
|
||||||
style->cell_format = CF_JSON;
|
style->cell_format = CF_JSON;
|
||||||
} else {
|
} else {
|
||||||
@@ -503,6 +537,10 @@ table_print(const struct table *table, const struct table_style *style)
|
|||||||
table_print_table__(table, style);
|
table_print_table__(table, style);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TF_LIST:
|
||||||
|
table_print_list__(table, style);
|
||||||
|
break;
|
||||||
|
|
||||||
case TF_HTML:
|
case TF_HTML:
|
||||||
table_print_html__(table, style);
|
table_print_html__(table, style);
|
||||||
break;
|
break;
|
||||||
|
14
lib/table.h
14
lib/table.h
@@ -59,6 +59,7 @@ struct cell *table_add_cell(struct table *);
|
|||||||
|
|
||||||
enum table_format {
|
enum table_format {
|
||||||
TF_TABLE, /* 2-d table. */
|
TF_TABLE, /* 2-d table. */
|
||||||
|
TF_LIST, /* One cell per line, one row per paragraph. */
|
||||||
TF_HTML, /* HTML table. */
|
TF_HTML, /* HTML table. */
|
||||||
TF_CSV, /* Comma-separated lines. */
|
TF_CSV, /* Comma-separated lines. */
|
||||||
TF_JSON /* JSON. */
|
TF_JSON /* JSON. */
|
||||||
@@ -66,6 +67,7 @@ enum table_format {
|
|||||||
|
|
||||||
enum cell_format {
|
enum cell_format {
|
||||||
CF_STRING, /* String format. */
|
CF_STRING, /* String format. */
|
||||||
|
CF_BARE, /* String format without most punctuation. */
|
||||||
CF_JSON /* JSON. */
|
CF_JSON /* JSON. */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,13 +82,15 @@ struct table_style {
|
|||||||
|
|
||||||
#define TABLE_OPTION_ENUMS \
|
#define TABLE_OPTION_ENUMS \
|
||||||
OPT_NO_HEADINGS, \
|
OPT_NO_HEADINGS, \
|
||||||
OPT_PRETTY
|
OPT_PRETTY, \
|
||||||
|
OPT_BARE
|
||||||
|
|
||||||
#define TABLE_LONG_OPTIONS \
|
#define TABLE_LONG_OPTIONS \
|
||||||
{"format", required_argument, 0, 'f'}, \
|
{"format", required_argument, 0, 'f'}, \
|
||||||
{"data", required_argument, 0, 'd'}, \
|
{"data", required_argument, 0, 'd'}, \
|
||||||
{"no-headings", no_argument, 0, OPT_NO_HEADINGS}, \
|
{"no-headings", no_argument, 0, OPT_NO_HEADINGS}, \
|
||||||
{"pretty", no_argument, 0, OPT_PRETTY},
|
{"pretty", no_argument, 0, OPT_PRETTY}, \
|
||||||
|
{"bare", no_argument, 0, OPT_BARE}
|
||||||
|
|
||||||
#define TABLE_OPTION_HANDLERS(STYLE) \
|
#define TABLE_OPTION_HANDLERS(STYLE) \
|
||||||
case 'f': \
|
case 'f': \
|
||||||
@@ -103,6 +107,12 @@ struct table_style {
|
|||||||
\
|
\
|
||||||
case OPT_PRETTY: \
|
case OPT_PRETTY: \
|
||||||
(STYLE)->json_flags |= JSSF_PRETTY; \
|
(STYLE)->json_flags |= JSSF_PRETTY; \
|
||||||
|
break; \
|
||||||
|
\
|
||||||
|
case OPT_BARE: \
|
||||||
|
(STYLE)->format = TF_LIST; \
|
||||||
|
(STYLE)->cell_format = CF_BARE; \
|
||||||
|
(STYLE)->headings = false; \
|
||||||
break;
|
break;
|
||||||
|
|
||||||
void table_parse_format(struct table_style *, const char *format);
|
void table_parse_format(struct table_style *, const char *format);
|
||||||
|
@@ -3,8 +3,10 @@
|
|||||||
Sets the type of table formatting. The following types of
|
Sets the type of table formatting. The following types of
|
||||||
\fIformat\fR are available:
|
\fIformat\fR are available:
|
||||||
.RS
|
.RS
|
||||||
.IP "\fBtable\fR (default)"
|
.IP "\fBtable\fR"
|
||||||
Text-based tables with aligned columns.
|
2-D text tables with aligned columns.
|
||||||
|
.IP "\fBlist\fR"
|
||||||
|
A list with one column per line and rows separated by a blank line.
|
||||||
.IP "\fBhtml\fR"
|
.IP "\fBhtml\fR"
|
||||||
HTML tables.
|
HTML tables.
|
||||||
.IP "\fBcvs\fR"
|
.IP "\fBcvs\fR"
|
||||||
@@ -37,6 +39,11 @@ types of \fIformat\fR are available:
|
|||||||
.RS
|
.RS
|
||||||
.IP "\fBstring\fR (default)"
|
.IP "\fBstring\fR (default)"
|
||||||
The simple format described in \fBovs\-vsctl\fR(8).
|
The simple format described in \fBovs\-vsctl\fR(8).
|
||||||
|
.IP "\fBbare\fR"
|
||||||
|
The simple format with punctuation stripped off: \fB[]\fR and \fB{}\fR
|
||||||
|
are omitted around sets, maps, and empty columns, items within sets
|
||||||
|
and maps are space-separated, and strings are never quoted. This
|
||||||
|
format may be easier for scripts to parse.
|
||||||
.IP "\fBjson\fR"
|
.IP "\fBjson\fR"
|
||||||
JSON.
|
JSON.
|
||||||
.RE
|
.RE
|
||||||
@@ -56,3 +63,5 @@ per line, with indentation.
|
|||||||
.IP
|
.IP
|
||||||
This option does not affect JSON in tables, which is always printed
|
This option does not affect JSON in tables, which is always printed
|
||||||
compactly.
|
compactly.
|
||||||
|
.IP "\fB\-\-bare\fR"
|
||||||
|
Equivalent to \fB\-\-format=list \-\-data=bare \-\-no\-headings\fR.
|
||||||
|
@@ -127,6 +127,7 @@ contents of \fItable\fR.
|
|||||||
Much of the output from \fBovsdb\-client\fR is in the form of tables.
|
Much of the output from \fBovsdb\-client\fR is in the form of tables.
|
||||||
The following options controlling output formatting:
|
The following options controlling output formatting:
|
||||||
.
|
.
|
||||||
|
.ds TD (default)
|
||||||
.so lib/table.man
|
.so lib/table.man
|
||||||
.
|
.
|
||||||
.SS "Daemon Options"
|
.SS "Daemon Options"
|
||||||
|
@@ -80,7 +80,7 @@ parse_options(int argc, char *argv[])
|
|||||||
DAEMON_LONG_OPTIONS,
|
DAEMON_LONG_OPTIONS,
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
{"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
|
{"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
|
||||||
TABLE_LONG_OPTIONS
|
TABLE_LONG_OPTIONS,
|
||||||
STREAM_SSL_LONG_OPTIONS
|
STREAM_SSL_LONG_OPTIONS
|
||||||
#endif
|
#endif
|
||||||
{0, 0, 0, 0},
|
{0, 0, 0, 0},
|
||||||
|
Reference in New Issue
Block a user