+++ /dev/null
-#include "carefulputc.h"
-#include "smartcolsP.h"
-
-void fput_indent(struct libscols_table *tb)
-{
- int i;
-
- for (i = 0; i <= tb->indent; i++)
- fputs(" ", tb->out);
-}
-
-void fput_table_open(struct libscols_table *tb)
-{
- tb->indent = 0;
-
- if (scols_table_is_json(tb)) {
- fputc('{', tb->out);
- fputs(linesep(tb), tb->out);
-
- fput_indent(tb);
- fputs_quoted(tb->name, tb->out);
- fputs(": [", tb->out);
- fputs(linesep(tb), tb->out);
-
- tb->indent++;
- tb->indent_last_sep = 1;
- }
-}
-
-void fput_table_close(struct libscols_table *tb)
-{
- tb->indent--;
-
- if (scols_table_is_json(tb)) {
- fput_indent(tb);
- fputc(']', tb->out);
- tb->indent--;
- fputs(linesep(tb), tb->out);
- fputc('}', tb->out);
- tb->indent_last_sep = 1;
- }
-}
-
-void fput_children_open(struct libscols_table *tb)
-{
- if (scols_table_is_json(tb)) {
- fputc(',', tb->out);
- fputs(linesep(tb), tb->out);
- fput_indent(tb);
- fputs("\"children\": [", tb->out);
- }
- /* between parent and child is separator */
- fputs(linesep(tb), tb->out);
- tb->indent_last_sep = 1;
- tb->indent++;
- tb->termlines_used++;
-}
-
-void fput_children_close(struct libscols_table *tb)
-{
- tb->indent--;
-
- if (scols_table_is_json(tb)) {
- fput_indent(tb);
- fputc(']', tb->out);
- fputs(linesep(tb), tb->out);
- tb->indent_last_sep = 1;
- }
-}
-
-void fput_line_open(struct libscols_table *tb)
-{
- if (scols_table_is_json(tb)) {
- fput_indent(tb);
- fputc('{', tb->out);
- tb->indent_last_sep = 0;
- }
- tb->indent++;
-}
-
-void fput_line_close(struct libscols_table *tb, int last, int last_in_table)
-{
- tb->indent--;
- if (scols_table_is_json(tb)) {
- if (tb->indent_last_sep)
- fput_indent(tb);
- fputs(last ? "}" : "},", tb->out);
- if (!tb->no_linesep)
- fputs(linesep(tb), tb->out);
-
- } else if (tb->no_linesep == 0 && last_in_table == 0) {
- fputs(linesep(tb), tb->out);
- tb->termlines_used++;
- }
-
- tb->indent_last_sep = 1;
-}
if (list_empty(&tb->tb_lines)) {
DBG(TAB, ul_debugobj(tb, "ignore -- no lines"));
if (scols_table_is_json(tb)) {
- fput_table_open(tb);
- fput_table_close(tb);
+ ul_jsonwrt_init(&tb->json, tb->out, 0);
+ ul_jsonwrt_root_open(&tb->json);
+ ul_jsonwrt_array_open(&tb->json, tb->name);
+ ul_jsonwrt_array_close(&tb->json, 1);
+ ul_jsonwrt_root_close(&tb->json);
} else if (is_empty)
*is_empty = 1;
return 0;
if (rc)
return rc;
- fput_table_open(tb);
+ if (scols_table_is_json(tb)) {
+ ul_jsonwrt_root_open(&tb->json);
+ ul_jsonwrt_array_open(&tb->json, tb->name);
+ }
if (tb->format == SCOLS_FMT_HUMAN)
__scols_print_title(tb);
else
rc = __scols_print_table(tb, buf);
- fput_table_close(tb);
+ if (scols_table_is_json(tb)) {
+ ul_jsonwrt_array_close(&tb->json, 1);
+ ul_jsonwrt_root_close(&tb->json);
+ }
done:
__scols_cleanup_printing(tb, buf);
return rc;
int empty = 0;
int rc = do_print_table(tb, &empty);
- if (rc == 0 && !empty)
+ if (rc == 0 && !empty && !scols_table_is_json(tb))
fputc('\n', tb->out);
return rc;
}
size_t len = 0, i, width, bytes;
const char *color = NULL;
char *data, *nextchunk;
+ const char *name = NULL;
int is_last;
assert(tb);
if (!data)
data = "";
+ if (tb->format != SCOLS_FMT_HUMAN)
+ name = scols_cell_get_data(&cl->header);
+
is_last = is_last_column(cl);
+ if (is_last && scols_table_is_json(tb) &&
+ scols_table_is_tree(tb) && has_children(ln))
+ /* "children": [] is the real last value */
+ is_last = 0;
+
switch (tb->format) {
case SCOLS_FMT_RAW:
fputs_nonblank(data, tb->out);
return 0;
case SCOLS_FMT_EXPORT:
- fprintf(tb->out, "%s=", scols_cell_get_data(&cl->header));
+ fprintf(tb->out, "%s=", name);
fputs_quoted(data, tb->out);
if (!is_last)
fputs(colsep(tb), tb->out);
return 0;
case SCOLS_FMT_JSON:
- fputs_quoted_json_lower(scols_cell_get_data(&cl->header), tb->out);
- fputs(":", tb->out);
switch (cl->json_type) {
- case SCOLS_JSON_STRING:
- if (!*data)
- fputs("null", tb->out);
- else
- fputs_quoted_json(data, tb->out);
- break;
- case SCOLS_JSON_NUMBER:
- if (!*data)
- fputs("null", tb->out);
- else
- fputs(data, tb->out);
- break;
- case SCOLS_JSON_BOOLEAN:
- fputs(!*data ? "false" :
- *data == '0' ? "false" :
- *data == 'N' || *data == 'n' ? "false" : "true",
- tb->out);
- break;
+ case SCOLS_JSON_STRING:
+ ul_jsonwrt_value_s(&tb->json, name, data, is_last);
+ break;
+ case SCOLS_JSON_NUMBER:
+ ul_jsonwrt_value_raw(&tb->json, name, data, is_last);
+ break;
+ case SCOLS_JSON_BOOLEAN:
+ ul_jsonwrt_value_boolean(&tb->json, name,
+ !*data ? 0 :
+ *data == '0' ? 0 :
+ *data == 'N' || *data == 'n' ? 0 : 1,
+ is_last);
+ break;
}
- if (!is_last)
- fputs(", ", tb->out);
return 0;
case SCOLS_FMT_HUMAN:
int last = scols_iter_is_last(itr);
- fput_line_open(tb);
+ if (scols_table_is_json(tb))
+ ul_jsonwrt_object_open(&tb->json, NULL);
+
rc = print_line(tb, ln, buf);
- fput_line_close(tb, last, last);
+
+ if (scols_table_is_json(tb))
+ ul_jsonwrt_object_close(&tb->json, last);
+ else if (last == 0 && tb->no_linesep == 0) {
+ fputs(linesep(tb), tb->out);
+ tb->termlines_used++;
+ }
if (end && ln == end)
break;
DBG(LINE, ul_debugobj(ln, " printing tree line"));
- fput_line_open(tb);
+ if (scols_table_is_json(tb))
+ ul_jsonwrt_object_open(&tb->json, NULL);
+
rc = print_line(tb, ln, buf);
if (rc)
return rc;
- if (has_children(ln))
- fput_children_open(tb);
-
- else {
- int last_in_tree = scols_walk_is_last(tb, ln);
+ if (has_children(ln)) {
+ if (scols_table_is_json(tb))
+ ul_jsonwrt_array_open(&tb->json, "children");
+ else {
+ /* between parent and child is separator */
+ fputs(linesep(tb), tb->out);
+ tb->termlines_used++;
+ }
+ } else {
int last;
/* terminate all open last children for JSON */
last = (is_child(ln) && is_last_child(ln)) ||
(is_tree_root(ln) && is_last_tree_root(tb, ln));
- fput_line_close(tb, last, last_in_tree);
+ ul_jsonwrt_object_close(&tb->json, last);
if (last && is_child(ln))
- fput_children_close(tb);
-
- last_in_tree = 0;
+ ul_jsonwrt_array_close(&tb->json, last);
ln = ln->parent;
} while(ln && last);
- } else {
- /* standard output */
- last = (is_child(ln) && is_last_child(ln)) ||
- (is_group_child(ln) && is_last_group_child(ln));
+ } else if (tb->no_linesep == 0) {
+ int last_in_tree = scols_walk_is_last(tb, ln);
- fput_line_close(tb, last, last_in_tree);
+ if (last_in_tree == 0) {
+ /* standard output */
+ fputs(linesep(tb), tb->out);
+ tb->termlines_used++;
+ }
}
}
extra_bufsz += tb->ncols; /* separator between columns */
break;
case SCOLS_FMT_JSON:
- if (tb->format == SCOLS_FMT_JSON)
- extra_bufsz += tb->nlines * 3; /* indentation */
+ ul_jsonwrt_init(&tb->json, tb->out, 0);
+ extra_bufsz += tb->nlines * 3; /* indentation */
/* fallthrough */
case SCOLS_FMT_EXPORT:
{
#include "list.h"
#include "strutils.h"
#include "color-names.h"
+#include "jsonwrt.h"
#include "debug.h"
#include "libsmartcols.h"
struct libscols_symbols *symbols;
struct libscols_cell title; /* optional table title (for humans) */
- int indent; /* indentation counter */
- int indent_last_sep;/* last printed has been line separator */
+ struct ul_jsonwrt json; /* JSON formatting */
+
int format; /* SCOLS_FMT_* */
size_t termlines_used; /* printed line counter */
struct libscols_iter *itr,
struct libscols_line *end);
-/*
- * fput.c
- */
-extern void fput_indent(struct libscols_table *tb);
-extern void fput_table_open(struct libscols_table *tb);
-extern void fput_table_close(struct libscols_table *tb);
-extern void fput_children_open(struct libscols_table *tb);
-extern void fput_children_close(struct libscols_table *tb);
-extern void fput_line_open(struct libscols_table *tb);
-extern void fput_line_close(struct libscols_table *tb, int last, int last_in_table);
-
static inline int is_tree_root(struct libscols_line *ln)
{
return ln && !ln->parent && !ln->parent_group;