UL_JSON_VALUE
};
+typedef enum {
+ UL_JSON_PRETTY,
+ UL_JSON_COMPACT,
+ UL_JSON_LINE,
+} ul_json_format_t;
+
struct ul_jsonwrt {
FILE *out;
int indent;
unsigned int after_close :1;
+ ul_json_format_t json_format;
};
-void ul_jsonwrt_init(struct ul_jsonwrt *fmt, FILE *out, int indent);
+void ul_jsonwrt_init(struct ul_jsonwrt *fmt, FILE *out, int indent, ul_json_format_t json_format);
int ul_jsonwrt_is_ready(struct ul_jsonwrt *fmt);
void ul_jsonwrt_indent(struct ul_jsonwrt *fmt);
void ul_jsonwrt_open(struct ul_jsonwrt *fmt, const char *name, int type);
#define fputs_quoted_json_upper(_d, _o) fputs_quoted_case_json(_d, _o, 1, 0)
#define fputs_quoted_json_lower(_d, _o) fputs_quoted_case_json(_d, _o, -1, 0)
-void ul_jsonwrt_init(struct ul_jsonwrt *fmt, FILE *out, int indent)
+void ul_jsonwrt_init(struct ul_jsonwrt *fmt, FILE *out, int indent, ul_json_format_t json_format)
{
fmt->out = out;
fmt->indent = indent;
+ fmt->json_format = json_format;
fmt->after_close = 0;
}
static void print_name(struct ul_jsonwrt *fmt, const char *name)
{
- if (name) {
- if (fmt->after_close)
- fputs(",\n", fmt->out);
- ul_jsonwrt_indent(fmt);
- fputs_quoted_json_lower(name, fmt->out);
- } else {
- if (fmt->after_close)
- fputs(",", fmt->out);
+ if (fmt->after_close) {
+ if (fmt->json_format == UL_JSON_LINE)
+ fputs(fmt->indent == 0 ? "\n" : ",", fmt->out);
else
- ul_jsonwrt_indent(fmt);
+ fputs(name ? ",\n" : ",", fmt->out);
}
+ if (fmt->json_format != UL_JSON_LINE && (name || !fmt->after_close))
+ ul_jsonwrt_indent(fmt);
+ if (name)
+ fputs_quoted_json_lower(name, fmt->out);
}
void ul_jsonwrt_open(struct ul_jsonwrt *fmt, const char *name, int type)
{
+ const char *s = "";
+
print_name(fmt, name);
switch (type) {
case UL_JSON_OBJECT:
- fputs(name ? ": {\n" : "{\n", fmt->out);
+ s = fmt->json_format == UL_JSON_LINE ? (name ? ":{" : "{") : (name ? ": {\n" : "{\n");
fmt->indent++;
break;
case UL_JSON_ARRAY:
- fputs(name ? ": [\n" : "[\n", fmt->out);
+ s = fmt->json_format == UL_JSON_LINE ? (name ? ":[" : "[") : (name ? ": [\n" : "[\n");
fmt->indent++;
break;
case UL_JSON_VALUE:
- fputs(name ? ": " : " ", fmt->out);
+ s = fmt->json_format == UL_JSON_LINE ? (name ? ":" : "") : (name ? ": " : " ");
break;
}
+ fputs(s, fmt->out);
fmt->after_close = 0;
}
void ul_jsonwrt_empty(struct ul_jsonwrt *fmt, const char *name, int type)
{
+ const char *s = "";
+
print_name(fmt, name);
switch (type) {
case UL_JSON_OBJECT:
- fputs(name ? ": {}" : "{}", fmt->out);
+ s = fmt->json_format == UL_JSON_LINE ? (name ? ":{}" : "{}") : (name ? ": {}" : "{}");
break;
case UL_JSON_ARRAY:
- fputs(name ? ": []" : "[]", fmt->out);
+ s = fmt->json_format == UL_JSON_LINE ? (name ? ":[]" : "[]") : (name ? ": []" : "[]");
break;
case UL_JSON_VALUE:
- fputs(name ? ": null" : "null", fmt->out);
+ s = fmt->json_format == UL_JSON_LINE ? (name ? ":null" : "null") : (name ? ": null" : "null");
break;
}
-
+ fputs(s, fmt->out);
fmt->after_close = 1;
}
void ul_jsonwrt_close(struct ul_jsonwrt *fmt, int type)
{
+ char endchr;
+
assert(fmt->indent > 0);
switch (type) {
case UL_JSON_OBJECT:
fmt->indent--;
- fputc('\n', fmt->out);
- ul_jsonwrt_indent(fmt);
- fputs("}", fmt->out);
- if (fmt->indent == 0)
- fputs("\n", fmt->out);
+ endchr = '}';
break;
case UL_JSON_ARRAY:
fmt->indent--;
- fputc('\n', fmt->out);
- ul_jsonwrt_indent(fmt);
- fputs("]", fmt->out);
+ endchr = ']';
break;
case UL_JSON_VALUE:
- break;
+ fmt->after_close = 1;
+ return;
+ default:
+ fmt->after_close = 1;
+ return;
}
+ if (fmt->json_format != UL_JSON_LINE) {
+ fputc('\n', fmt->out);
+ ul_jsonwrt_indent(fmt);
+ }
+ fputc(endchr, fmt->out);
+ if (fmt->json_format != UL_JSON_LINE && type == UL_JSON_OBJECT && fmt->indent == 0)
+ fputc('\n', fmt->out);
fmt->after_close = 1;
}
DBG(SCRIPT, ul_debugobj(dp, "writing json dump to file"));
- ul_jsonwrt_init(&json, f, 0);
+ ul_jsonwrt_init(&json, f, 0, UL_JSON_PRETTY);
ul_jsonwrt_root_open(&json);
ul_jsonwrt_object_open(&json, "partitiontable");
if (!fltr || !out)
return -EINVAL;
- ul_jsonwrt_init(&json, out, 0);
+ ul_jsonwrt_init(&json, out, 0, UL_JSON_PRETTY);
ul_jsonwrt_root_open(&json);
filter_dump_node(&json, fltr->root);
if (list_empty(&tb->tb_lines)) {
DBG(TAB, ul_debugobj(tb, "ignore -- no lines"));
if (scols_table_is_json(tb)) {
- ul_jsonwrt_init(&tb->json, tb->out, 0);
- ul_jsonwrt_root_open(&tb->json);
- ul_jsonwrt_array_open(&tb->json, tb->name ? tb->name : "");
- ul_jsonwrt_array_close(&tb->json);
- ul_jsonwrt_root_close(&tb->json);
+ ul_jsonwrt_init(&tb->json, tb->out, 0, tb->json_format);
+ if (tb->json_format != UL_JSON_LINE) {
+ ul_jsonwrt_root_open(&tb->json);
+ ul_jsonwrt_array_open(&tb->json, tb->name ? tb->name : "");
+ ul_jsonwrt_array_close(&tb->json);
+ ul_jsonwrt_root_close(&tb->json);
+ }
} else if (is_empty)
*is_empty = 1;
return 0;
if (rc)
return rc;
- if (scols_table_is_json(tb)) {
+ if (scols_table_is_json(tb) && tb->json_format != UL_JSON_LINE) {
ul_jsonwrt_root_open(&tb->json);
ul_jsonwrt_array_open(&tb->json, tb->name ? tb->name : "");
}
rc = __scols_print_table(tb, &buf);
if (scols_table_is_json(tb)) {
- ul_jsonwrt_array_close(&tb->json);
- ul_jsonwrt_root_close(&tb->json);
+ if (tb->json_format != UL_JSON_LINE) {
+ ul_jsonwrt_array_close(&tb->json);
+ ul_jsonwrt_root_close(&tb->json);
+ } else {
+ fputc('\n', tb->out); /* trailing newline after last object */
+ }
}
done:
__scols_cleanup_printing(tb, &buf);
extra_bufsz += tb->ncols; /* separator between columns */
break;
case SCOLS_FMT_JSON:
- ul_jsonwrt_init(&tb->json, tb->out, 0);
+ ul_jsonwrt_init(&tb->json, tb->out, 0, tb->json_format);
extra_bufsz += tb->nlines * 3; /* indentation */
FALLTHROUGH;
case SCOLS_FMT_EXPORT:
struct libscols_line *cur_line; /* currently used line */
struct libscols_column *cur_column; /* currently used column */
+ ul_json_format_t json_format; /* JSON output format */
+
/* flags */
bool ascii , /* don't use unicode */
colors_wanted , /* enable colors */
tb->padding_debug = 1;
}
+static ul_json_format_t get_json_format(void)
+{
+ const char *str;
+
+ str = getenv("LIBSMARTCOLS_JSON");
+ if (!str)
+ return UL_JSON_PRETTY;
+ else if (strcmp(str, "compact") == 0)
+ return UL_JSON_COMPACT;
+ else if (strcmp(str, "lines") == 0)
+ return UL_JSON_LINE;
+
+ /* default to pretty */
+ return UL_JSON_PRETTY;
+}
+
/**
* scols_new_table:
*
DBG(TAB, ul_debugobj(tb, "alloc"));
ON_DBG(INIT, check_padding_debug(tb));
+ tb->json_format = get_json_format();
return tb;
}
if (ctl->json) {
if (!ul_jsonwrt_is_ready(&ctl->jfmt)) {
- ul_jsonwrt_init(&ctl->jfmt, stdout, 0);
+ ul_jsonwrt_init(&ctl->jfmt, stdout, 0, UL_JSON_PRETTY);
ul_jsonwrt_root_open(&ctl->jfmt);
ul_jsonwrt_array_open(&ctl->jfmt, "dmesg");
}