From 37bcd05602760c0bd0d063c43e346f4343834c6b Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 12 Nov 2020 11:19:13 +0100 Subject: [PATCH] lib/jsonwrt: add new functions to write in JSON We need JSON formatting stuff also outside libsmartcols. Signed-off-by: Karel Zak --- include/Makemodule.am | 1 + include/jsonwrt.h | 44 +++++++++++++++ lib/Makemodule.am | 1 + lib/jsonwrt.c | 128 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 174 insertions(+) create mode 100644 include/jsonwrt.h create mode 100644 lib/jsonwrt.c diff --git a/include/Makemodule.am b/include/Makemodule.am index 8d40fa482..ed03ace7b 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -26,6 +26,7 @@ dist_noinst_HEADERS += \ include/idcache.h \ include/ismounted.h \ include/iso9660.h \ + include/jsonwrt.h \ include/pwdutils.h \ include/linux_version.h \ include/list.h \ diff --git a/include/jsonwrt.h b/include/jsonwrt.h new file mode 100644 index 000000000..04ef49e6f --- /dev/null +++ b/include/jsonwrt.h @@ -0,0 +1,44 @@ +#ifndef UTIL_LINUX_JSONWRT_H +#define UTIL_LINUX_JSONWRT_H + +enum { + UL_JSON_OBJECT, + UL_JSON_ARRAY, + UL_JSON_VALUE +}; + +struct ul_jsonwrt { + FILE *out; + int indent; + + unsigned int postponed_break :1; +}; + +void ul_jsonwrt_init(struct ul_jsonwrt *fmt, FILE *out, int indent); +void ul_jsonwrt_indent(struct ul_jsonwrt *fmt); +void ul_jsonwrt_open(struct ul_jsonwrt *fmt, const char *name, int type); +void ul_jsonwrt_close(struct ul_jsonwrt *fmt, int type, int islast); + +#define ul_jsonwrt_root_open(_f) ul_jsonwrt_open(_f, NULL, UL_JSON_OBJECT) +#define ul_jsonwrt_root_close(_f) ul_jsonwrt_close(_f, UL_JSON_OBJECT, 1) + +#define ul_jsonwrt_array_open(_f, _n) ul_jsonwrt_open(_f, _n, UL_JSON_ARRAY) +#define ul_jsonwrt_array_close(_f, _l) ul_jsonwrt_close(_f, UL_JSON_ARRAY, _l) + +#define ul_jsonwrt_object_open(_f, _n) ul_jsonwrt_open(_f, _n, UL_JSON_OBJECT) +#define ul_jsonwrt_object_close(_f, _l) ul_jsonwrt_close(_f, UL_JSON_OBJECT, _l) + +#define ul_jsonwrt_value_open(_f, _n) ul_jsonwrt_open(_f, _n, UL_JSON_VALUE) +#define ul_jsonwrt_value_close(_f, _l) ul_jsonwrt_close(_f, UL_JSON_VALUE, _l) + + +void ul_jsonwrt_value_raw(struct ul_jsonwrt *fmt, + const char *name, const char *data, int islast); +void ul_jsonwrt_value_s(struct ul_jsonwrt *fmt, + const char *name, const char *data, int islast); +void ul_jsonwrt_value_u64(struct ul_jsonwrt *fmt, + const char *name, uint64_t data, int islast); +void ul_jsonwrt_value_boolean(struct ul_jsonwrt *fmt, + const char *name, int data, int islast); + +#endif /* UTIL_LINUX_JSONWRT_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index e2e3e4f7c..bf389db0e 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -22,6 +22,7 @@ libcommon_la_SOURCES = \ lib/encode.c \ lib/fileutils.c \ lib/color-names.c \ + lib/jsonwrt.c \ lib/mangle.c \ lib/match.c \ lib/mbsalign.c \ diff --git a/lib/jsonwrt.c b/lib/jsonwrt.c new file mode 100644 index 000000000..6d559dd71 --- /dev/null +++ b/lib/jsonwrt.c @@ -0,0 +1,128 @@ +/* + * JSON output formatting functions. + * + * No copyright is claimed. This code is in the public domain; do with + * it what you wish. + * + * Written by Karel Zak + */ +#include +#include + +#include "c.h" +#include "carefulputc.h" +#include "jsonwrt.h" + + +void ul_jsonwrt_init(struct ul_jsonwrt *fmt, FILE *out, int indent) +{ + fmt->out = out; + fmt->indent = indent; +} + +void ul_jsonwrt_indent(struct ul_jsonwrt *fmt) +{ + int i; + + for (i = 0; i < fmt->indent; i++) + fputs(" ", fmt->out); +} + +void ul_jsonwrt_open(struct ul_jsonwrt *fmt, const char *name, int type) +{ + if (fmt->postponed_break && !name) + ; + else { + ul_jsonwrt_indent(fmt); + if (name) + fputs_quoted(name, fmt->out); + } + + switch (type) { + case UL_JSON_OBJECT: + fputs(name ? ": {\n" : "{\n", fmt->out); + fmt->indent++; + break; + case UL_JSON_ARRAY: + fputs(name ? ": [\n" : "{\n", fmt->out); + fmt->indent++; + break; + case UL_JSON_VALUE: + fputs(name ? ": " : " ", fmt->out); + break; + } + fmt->postponed_break = 0; +} + +void ul_jsonwrt_close(struct ul_jsonwrt *fmt, int type, int islast) +{ + if (fmt->indent == 0) { + fputs("}\n", fmt->out); + fmt->indent--; + return; + } + assert(fmt->indent > 0); + + switch (type) { + case UL_JSON_OBJECT: + fmt->indent--; + ul_jsonwrt_indent(fmt); + fputs(islast ? "}" : "},", fmt->out); + break; + case UL_JSON_ARRAY: + fmt->indent--; + ul_jsonwrt_indent(fmt); + fputs(islast ? "]" : "],", fmt->out); + break; + case UL_JSON_VALUE: + if (!islast) + fputc(',', fmt->out); + break; + } + + if (!islast && (type == UL_JSON_OBJECT || type == UL_JSON_ARRAY)) + fmt->postponed_break = 1; + else { + fputc('\n', fmt->out); + fmt->postponed_break = 0; + } +} + +void ul_jsonwrt_value_raw(struct ul_jsonwrt *fmt, + const char *name, const char *data, int islast) +{ + ul_jsonwrt_value_open(fmt, name); + if (data && *data) + fputs(data, fmt->out); + else + fputs("null", fmt->out); + ul_jsonwrt_value_close(fmt, islast); +} + +void ul_jsonwrt_value_s(struct ul_jsonwrt *fmt, + const char *name, const char *data, int islast) +{ + ul_jsonwrt_value_open(fmt, name); + if (data && *data) + fputs_quoted(data, fmt->out); + else + fputs("null", fmt->out); + ul_jsonwrt_value_close(fmt, islast); +} + +void ul_jsonwrt_value_u64(struct ul_jsonwrt *fmt, + const char *name, uint64_t data, int islast) +{ + ul_jsonwrt_value_open(fmt, name); + fprintf(fmt->out, "%"PRIu64, data); + ul_jsonwrt_value_close(fmt, islast); +} + +void ul_jsonwrt_value_boolean(struct ul_jsonwrt *fmt, + const char *name, int data, int islast) +{ + ul_jsonwrt_value_open(fmt, name); + fputs(data ? "true" : "false", fmt->out); + ul_jsonwrt_value_close(fmt, islast); +} +