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.
@@ -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)
@@ -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
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.
@@ -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 *);
+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 *)
@@ -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 *);
+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 *);
 
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);
-            } else if (style->cell_format == CF_STRING) {
+            } else {
                 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);
-                    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);
                 }
-            } else {
-                NOT_REACHED();
             }
         } else {
             cell->text = xstrdup("");
@@ -272,6 +274,34 @@ table_print_table__(const struct table *table, const struct table_style *style)
     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)
 {
@@ -469,6 +499,8 @@ table_parse_format(struct table_style *style, const char *format)
 {
     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")) {
@@ -487,6 +519,8 @@ table_parse_cell_format(struct table_style *style, const char *format)
 {
     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 {
@@ -503,6 +537,10 @@ table_print(const struct table *table, const struct table_style *style)
         table_print_table__(table, style);
         break;
 
+    case TF_LIST:
+        table_print_list__(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. */
+    TF_LIST,                    /* One cell per line, one row per paragraph. */
     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. */
+    CF_BARE,                    /* String format without most punctuation. */
     CF_JSON                     /* JSON. */
 };
 
@@ -80,13 +82,15 @@ struct table_style {
 
 #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},   \
-        {"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':                                   \
@@ -103,6 +107,12 @@ struct table_style {
                                                     \
         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);
index 8be272a..41e039c 100644 (file)
@@ -3,8 +3,10 @@
 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"
@@ -37,6 +39,11 @@ types of \fIformat\fR are available:
 .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
@@ -56,3 +63,5 @@ per line, with indentation.
 .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:
 .
+.ds TD (default)
 .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},
-        TABLE_LONG_OPTIONS
+        TABLE_LONG_OPTIONS,
         STREAM_SSL_LONG_OPTIONS
 #endif
         {0, 0, 0, 0},