]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/jsonwrt: add new functions to write in JSON
authorKarel Zak <kzak@redhat.com>
Thu, 12 Nov 2020 10:19:13 +0000 (11:19 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 12 Nov 2020 10:19:13 +0000 (11:19 +0100)
We need JSON formatting stuff also outside libsmartcols.

Signed-off-by: Karel Zak <kzak@redhat.com>
include/Makemodule.am
include/jsonwrt.h [new file with mode: 0644]
lib/Makemodule.am
lib/jsonwrt.c [new file with mode: 0644]

index 8d40fa48201a1cad6f598716c1441140a22e62a5..ed03ace7b7c34bafc149c1b021a02b1dc5f60e6c 100644 (file)
@@ -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 (file)
index 0000000..04ef49e
--- /dev/null
@@ -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 */
index e2e3e4f7c6d76eb3eac4cfb6a6f00c028c467ab8..bf389db0e2f81d2fc0dccadc59c548b1ba4f13f7 100644 (file)
@@ -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 (file)
index 0000000..6d559dd
--- /dev/null
@@ -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 <kzak@redhat.com>
+ */
+#include <stdio.h>
+#include <inttypes.h>
+
+#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);
+}
+