-static struct ovsdb_schema *
-fetch_schema(const char *server, const char *database)
-{
- struct ovsdb_schema *schema;
- struct jsonrpc *rpc;
-
- rpc = open_jsonrpc(server);
- schema = fetch_schema_from_rpc(rpc, database);
- jsonrpc_close(rpc);
-
- return schema;
-}
-\f
-struct column {
- char *heading;
-};
-
-struct cell {
- /* Literal text. */
- char *text;
-
- /* JSON. */
- struct json *json;
- const struct ovsdb_type *type;
-};
-
-static const char *
-cell_to_text(const struct cell *cell_)
-{
- struct cell *cell = (struct cell *) cell_;
- if (!cell->text) {
- if (cell->json) {
- if (data_format == DF_JSON || !cell->type) {
- cell->text = json_to_string(cell->json, JSSF_SORT);
- } else if (data_format == DF_STRING) {
- struct ovsdb_datum datum;
- struct ovsdb_error *error;
- struct ds s;
-
- error = ovsdb_datum_from_json(&datum, cell->type, cell->json,
- NULL);
- if (!error) {
- ds_init(&s);
- ovsdb_datum_to_string(&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("");
- }
- }
-
- return cell->text;
-}
-
-static void
-cell_destroy(struct cell *cell)
-{
- free(cell->text);
- json_destroy(cell->json);
-}
-
-struct table {
- struct cell *cells;
- struct column *columns;
- size_t n_columns, allocated_columns;
- size_t n_rows, allocated_rows;
- size_t current_column;
- char *caption;
-};
-
-static void
-table_init(struct table *table)
-{
- memset(table, 0, sizeof *table);
-}
-
-static void
-table_destroy(struct table *table)
-{
- size_t i;
-
- for (i = 0; i < table->n_columns; i++) {
- free(table->columns[i].heading);
- }
- free(table->columns);
-
- for (i = 0; i < table->n_columns * table->n_rows; i++) {
- cell_destroy(&table->cells[i]);
- }
- free(table->cells);
-
- free(table->caption);
-}
-
-static void
-table_set_caption(struct table *table, char *caption)
-{
- free(table->caption);
- table->caption = caption;
-}
-
-static void
-table_add_column(struct table *table, const char *heading, ...)
- PRINTF_FORMAT(2, 3);
-
-static void
-table_add_column(struct table *table, const char *heading, ...)
-{
- struct column *column;
- va_list args;
-
- assert(!table->n_rows);
- if (table->n_columns >= table->allocated_columns) {
- table->columns = x2nrealloc(table->columns, &table->allocated_columns,
- sizeof *table->columns);
- }
- column = &table->columns[table->n_columns++];
-
- va_start(args, heading);
- column->heading = xvasprintf(heading, args);
- va_end(args);
-}
-
-static struct cell *
-table_cell__(const struct table *table, size_t row, size_t column)
-{
- return &table->cells[column + row * table->n_columns];
-}
-
-static void
-table_add_row(struct table *table)
-{
- size_t x, y;
-
- if (table->n_rows >= table->allocated_rows) {
- table->cells = x2nrealloc(table->cells, &table->allocated_rows,
- table->n_columns * sizeof *table->cells);
- }
-
- y = table->n_rows++;
- table->current_column = 0;
- for (x = 0; x < table->n_columns; x++) {
- struct cell *cell = table_cell__(table, y, x);
- memset(cell, 0, sizeof *cell);
- }
-}
-
-static struct cell *
-table_add_cell(struct table *table)
-{
- size_t x, y;
-
- assert(table->n_rows > 0);
- assert(table->current_column < table->n_columns);
-
- x = table->current_column++;
- y = table->n_rows - 1;
-
- return table_cell__(table, y, x);
-}
-
-static void
-table_print_table_line__(struct ds *line)
-{
- puts(ds_cstr(line));
- ds_clear(line);
-}
-
-static void
-table_print_table__(const struct table *table)
-{
- static int n = 0;
- struct ds line = DS_EMPTY_INITIALIZER;
- int *widths;
- size_t x, y;
-
- if (n++ > 0) {
- putchar('\n');
- }
-
- if (table->caption) {
- puts(table->caption);
- }
-
- widths = xmalloc(table->n_columns * sizeof *widths);
- for (x = 0; x < table->n_columns; x++) {
- const struct column *column = &table->columns[x];
-
- widths[x] = strlen(column->heading);
- for (y = 0; y < table->n_rows; y++) {
- const char *text = cell_to_text(table_cell__(table, y, x));
- size_t length = strlen(text);
-
- if (length > widths[x])
- widths[x] = length;
- }
- }
-
- if (output_headings) {
- for (x = 0; x < table->n_columns; x++) {
- const struct column *column = &table->columns[x];
- if (x) {
- ds_put_char(&line, ' ');
- }
- ds_put_format(&line, "%-*s", widths[x], column->heading);
- }
- table_print_table_line__(&line);
-
- for (x = 0; x < table->n_columns; x++) {
- if (x) {
- ds_put_char(&line, ' ');
- }
- ds_put_char_multiple(&line, '-', widths[x]);
- }
- table_print_table_line__(&line);
- }
-
- 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));
- if (x) {
- ds_put_char(&line, ' ');
- }
- ds_put_format(&line, "%-*s", widths[x], text);
- }
- table_print_table_line__(&line);
- }
-
- ds_destroy(&line);
- free(widths);
-}
-