table: Add new "bare" output formatting options.
authorBen Pfaff <blp@nicira.com>
Wed, 2 Feb 2011 19:24:35 +0000 (11:24 -0800)
committerBen Pfaff <blp@nicira.com>
Wed, 9 Feb 2011 00:10:05 +0000 (16:10 -0800)
--format=list corresponds to the output format that "ovs-vsctl list" has
always used.

--bare is easier for scripts to parse.

lib/ovsdb-data.c
lib/ovsdb-data.h
lib/table.c
lib/table.h
lib/table.man
ovsdb/ovsdb-client.1.in
ovsdb/ovsdb-client.c

index 20d333e..5b91ea0 100644 (file)
@@ -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");
  * you may not use this file except in compliance with the License.
  *
  * Licensed under the Apache License, Version 2.0 (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 *
 check_string_constraints(const char *s,
                          const struct ovsdb_string_constraints *c)
 static struct ovsdb_error *
 check_string_constraints(const char *s,
                          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
  * 'sh'.  Destroys 'sh'. */
 void
 /* Initializes 'datum' as a string-to-string map whose contents are taken from
  * 'sh'.  Destroys 'sh'. */
 void
index f7e98a8..ced3033 100644 (file)
@@ -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");
  * you may not use this file except in compliance with the License.
  *
  * Licensed under the Apache License, Version 2.0 (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;
 void ovsdb_atom_to_string(const union ovsdb_atom *, enum ovsdb_atomic_type,
                           struct ds *);
     WARN_UNUSED_RESULT;
 void ovsdb_atom_to_string(const union ovsdb_atom *, enum ovsdb_atomic_type,
                           struct ds *);
+void ovsdb_atom_to_bare(const union ovsdb_atom *, enum ovsdb_atomic_type,
+                        struct ds *);
 
 struct ovsdb_error *ovsdb_atom_check_constraints(
     const union ovsdb_atom *, const struct ovsdb_base_type *)
 
 struct ovsdb_error *ovsdb_atom_check_constraints(
     const union ovsdb_atom *, const struct ovsdb_base_type *)
@@ -167,6 +169,8 @@ char *ovsdb_datum_from_string(struct ovsdb_datum *,
     WARN_UNUSED_RESULT;
 void ovsdb_datum_to_string(const struct ovsdb_datum *,
                            const struct ovsdb_type *, struct ds *);
     WARN_UNUSED_RESULT;
 void ovsdb_datum_to_string(const struct ovsdb_datum *,
                            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 *);
 
index d150b29..86366d0 100644 (file)
@@ -36,7 +36,7 @@ cell_to_text(struct cell *cell, const struct table_style *style)
         if (cell->json) {
             if (style->cell_format == CF_JSON || !cell->type) {
                 cell->text = json_to_string(cell->json, JSSF_SORT);
         if (cell->json) {
             if (style->cell_format == CF_JSON || !cell->type) {
                 cell->text = json_to_string(cell->json, JSSF_SORT);
-            } else if (style->cell_format == CF_STRING) {
+            } else {
                 struct ovsdb_datum datum;
                 struct ovsdb_error *error;
                 struct ds s;
                 struct ovsdb_datum datum;
                 struct ovsdb_error *error;
                 struct ds s;
@@ -45,14 +45,16 @@ cell_to_text(struct cell *cell, const struct table_style *style)
                                               NULL);
                 if (!error) {
                     ds_init(&s);
                                               NULL);
                 if (!error) {
                     ds_init(&s);
-                    ovsdb_datum_to_string(&datum, cell->type, &s);
+                    if (style->cell_format == CF_STRING) {
+                        ovsdb_datum_to_string(&datum, cell->type, &s);
+                    } else {
+                        ovsdb_datum_to_bare(&datum, cell->type, &s);
+                    }
                     ovsdb_datum_destroy(&datum, cell->type);
                     cell->text = ds_steal_cstr(&s);
                 } else {
                     cell->text = json_to_string(cell->json, JSSF_SORT);
                 }
                     ovsdb_datum_destroy(&datum, cell->type);
                     cell->text = ds_steal_cstr(&s);
                 } else {
                     cell->text = json_to_string(cell->json, JSSF_SORT);
                 }
-            } else {
-                NOT_REACHED();
             }
         } else {
             cell->text = xstrdup("");
             }
         } else {
             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
 table_escape_html_text__(const char *s, size_t n)
 {
 static void
 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")) {
         style->format = TF_TABLE;
 {
     if (!strcmp(format, "table")) {
         style->format = TF_TABLE;
+    } else if (!strcmp(format, "list")) {
+        style->format = TF_LIST;
     } else if (!strcmp(format, "html")) {
         style->format = TF_HTML;
     } else if (!strcmp(format, "csv")) {
     } else if (!strcmp(format, "html")) {
         style->format = TF_HTML;
     } else if (!strcmp(format, "csv")) {
@@ -487,6 +519,8 @@ table_parse_cell_format(struct table_style *style, const char *format)
 {
     if (!strcmp(format, "string")) {
         style->cell_format = CF_STRING;
 {
     if (!strcmp(format, "string")) {
         style->cell_format = CF_STRING;
+    } else if (!strcmp(format, "bare")) {
+        style->cell_format = CF_BARE;
     } else if (!strcmp(format, "json")) {
         style->cell_format = CF_JSON;
     } else {
     } else if (!strcmp(format, "json")) {
         style->cell_format = CF_JSON;
     } else {
@@ -503,6 +537,10 @@ table_print(const struct table *table, const struct table_style *style)
         table_print_table__(table, style);
         break;
 
         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_HTML:
         table_print_html__(table, style);
         break;
index c24bca2..e35fefa 100644 (file)
@@ -59,6 +59,7 @@ struct cell *table_add_cell(struct table *);
 
 enum table_format {
     TF_TABLE,                   /* 2-d table. */
 
 enum table_format {
     TF_TABLE,                   /* 2-d table. */
+    TF_LIST,                    /* One cell per line, one row per paragraph. */
     TF_HTML,                    /* HTML table. */
     TF_CSV,                     /* Comma-separated lines. */
     TF_JSON                     /* JSON. */
     TF_HTML,                    /* HTML table. */
     TF_CSV,                     /* Comma-separated lines. */
     TF_JSON                     /* JSON. */
@@ -66,6 +67,7 @@ enum table_format {
 
 enum cell_format {
     CF_STRING,                  /* String format. */
 
 enum cell_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                      \
     OPT_NO_HEADINGS,                            \
 
 #define TABLE_OPTION_ENUMS                      \
     OPT_NO_HEADINGS,                            \
-    OPT_PRETTY
+    OPT_PRETTY,                                 \
+    OPT_BARE
 
 #define TABLE_LONG_OPTIONS                                  \
         {"format", required_argument, 0, 'f'},              \
         {"data", required_argument, 0, 'd'},                \
         {"no-headings", no_argument, 0, OPT_NO_HEADINGS},   \
 
 #define TABLE_LONG_OPTIONS                                  \
         {"format", required_argument, 0, 'f'},              \
         {"data", required_argument, 0, 'd'},                \
         {"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)                \
         case 'f':                                   \
 
 #define TABLE_OPTION_HANDLERS(STYLE)                \
         case 'f':                                   \
@@ -103,6 +107,12 @@ struct table_style {
                                                     \
         case OPT_PRETTY:                            \
             (STYLE)->json_flags |= JSSF_PRETTY;     \
                                                     \
         case OPT_PRETTY:                            \
             (STYLE)->json_flags |= JSSF_PRETTY;     \
+            break;                                  \
+                                                    \
+        case OPT_BARE:                              \
+            (STYLE)->format = TF_LIST;              \
+            (STYLE)->cell_format = CF_BARE;         \
+            (STYLE)->headings = false;              \
             break;
 
 void table_parse_format(struct table_style *, const char *format);
             break;
 
 void table_parse_format(struct table_style *, const char *format);
index 8be272a..41e039c 100644 (file)
@@ -3,8 +3,10 @@
 Sets the type of table formatting.  The following types of
 \fIformat\fR are available:
 .RS
 Sets the type of table formatting.  The following types of
 \fIformat\fR are available:
 .RS
-.IP "\fBtable\fR (default)"
-Text-based tables with aligned columns.
+.IP "\fBtable\fR"
+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"
 HTML tables.
 .IP "\fBcvs\fR"
 .IP "\fBhtml\fR"
 HTML tables.
 .IP "\fBcvs\fR"
@@ -37,6 +39,11 @@ types of \fIformat\fR are available:
 .RS
 .IP "\fBstring\fR (default)"
 The simple format described in \fBovs\-vsctl\fR(8).
 .RS
 .IP "\fBstring\fR (default)"
 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"
 JSON.
 .RE
 .IP "\fBjson\fR"
 JSON.
 .RE
@@ -56,3 +63,5 @@ per line, with indentation.
 .IP
 This option does not affect JSON in tables, which is always printed
 compactly.
 .IP
 This option does not affect JSON in tables, which is always printed
 compactly.
+.IP "\fB\-\-bare\fR"
+Equivalent to \fB\-\-format=list \-\-data=bare \-\-no\-headings\fR.
index 2b1281d..fe7b7fa 100644 (file)
@@ -127,6 +127,7 @@ contents of \fItable\fR.
 Much of the output from \fBovsdb\-client\fR is in the form of tables.
 The following options controlling output formatting:
 .
 Much of the output from \fBovsdb\-client\fR is in the form of tables.
 The following options controlling output formatting:
 .
+.ds TD (default)
 .so lib/table.man
 .
 .SS "Daemon Options"
 .so lib/table.man
 .
 .SS "Daemon Options"
index 6402e90..a66b013 100644 (file)
@@ -80,7 +80,7 @@ parse_options(int argc, char *argv[])
         DAEMON_LONG_OPTIONS,
 #ifdef HAVE_OPENSSL
         {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
         DAEMON_LONG_OPTIONS,
 #ifdef HAVE_OPENSSL
         {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
-        TABLE_LONG_OPTIONS
+        TABLE_LONG_OPTIONS,
         STREAM_SSL_LONG_OPTIONS
 #endif
         {0, 0, 0, 0},
         STREAM_SSL_LONG_OPTIONS
 #endif
         {0, 0, 0, 0},