aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2025-01-15 03:04:23 +0100
committerFederico Angelilli <code@fedang.net>2025-01-15 03:04:23 +0100
commit752fae256623eb55f257ffd88c14b91f605770d3 (patch)
treeefdf08031fbed270023e436e65d47496bf30d041
parent97e75f4ed2d6a3d9ad8f87547e14f36cbdf72826 (diff)
Add any_json write api
-rw-r--r--any_json.h158
-rw-r--r--test/json.c139
2 files changed, 297 insertions, 0 deletions
diff --git a/any_json.h b/any_json.h
new file mode 100644
index 0000000..021a997
--- /dev/null
+++ b/any_json.h
@@ -0,0 +1,158 @@
+#ifndef ANY_JSON_INCLUDE
+#define ANY_JSON_INCLUDE
+
+#include <stdbool.h>
+
+typedef int (*any_json_write_fputs_t)(const char *string, void *stream);
+
+typedef struct {
+ void *stream;
+ any_json_write_fputs_t fputs;
+ int indent;
+ bool first;
+ bool pretty;
+} any_json_write_t;
+
+void any_json_write_init(any_json_write_t *json, void *stream,
+ any_json_write_fputs_t fputs, bool pretty);
+
+bool any_json_write_open_object(any_json_write_t *json);
+
+bool any_json_write_close_object(any_json_write_t *json);
+
+bool any_json_write_open_array(any_json_write_t *json);
+
+bool any_json_write_close_array(any_json_write_t *json);
+
+bool any_json_write_member(any_json_write_t *json, const char *key);
+
+bool any_json_write_string(any_json_write_t *json, const char *string);
+
+bool any_json_write_number(any_json_write_t *json, double value);
+
+bool any_json_write_bool(any_json_write_t *json, bool value);
+
+bool any_json_write_null(any_json_write_t *json);
+
+#endif
+
+#ifdef ANY_JSON_IMPLEMENT
+
+#include <string.h>
+
+#ifndef ANY_JSON_INDENT
+#define ANY_JSON_INDENT 4
+#endif
+
+static void any_json_write_indent(any_json_write_t *json, bool newline)
+{
+ if (json->pretty) {
+ if (newline)
+ json->fputs("\n", json->stream);
+
+ for (int i = 0; i < json->indent; i++)
+ json->fputs(" ", json->stream);
+ }
+}
+
+void any_json_write_init(any_json_write_t *json, void *stream,
+ any_json_write_fputs_t fputs, bool pretty)
+{
+ memset(json, 0, sizeof(any_json_write_t));
+ json->stream = stream;
+ json->fputs = fputs;
+ json->pretty = pretty;
+}
+
+bool any_json_write_open_object(any_json_write_t *json)
+{
+ json->indent += ANY_JSON_INDENT;
+ json->first = true;
+ json->fputs("{", json->stream);
+}
+
+bool any_json_write_close_object(any_json_write_t *json)
+{
+ json->indent -= ANY_JSON_INDENT;
+ json->first = false;
+ any_json_write_indent(json, true);
+ json->fputs("}", json->stream);
+}
+
+bool any_json_write_open_array(any_json_write_t *json)
+{
+ json->indent += ANY_JSON_INDENT;
+ json->first = true;
+ json->fputs("[", json->stream);
+}
+
+bool any_json_write_close_array(any_json_write_t *json)
+{
+ json->indent -= ANY_JSON_INDENT;
+ json->first = false;
+ any_json_write_indent(json, true);
+ json->fputs("]", json->stream);
+}
+
+bool any_json_write_member(any_json_write_t *json, const char *key)
+{
+ if (!json->first)
+ json->fputs(",", json->stream);
+
+ any_json_write_indent(json, true);
+ json->first = false;
+
+ if (key != NULL) {
+ any_json_write_string(json, key);
+ json->fputs(json->pretty ? ": " : ":", json->stream);
+ }
+}
+
+bool any_json_write_string(any_json_write_t *json, const char *string)
+{
+ json->fputs("\"", json->stream);
+ json->fputs(string, json->stream);
+ json->fputs("\"", json->stream);
+}
+
+bool any_json_write_number(any_json_write_t *json, double value)
+{
+ char buffer[1080] = { 0 };
+ snprintf(buffer, sizeof(buffer), "%lf", value);
+ json->fputs(buffer, json->stream);
+}
+
+bool any_json_write_bool(any_json_write_t *json, bool value)
+{
+ json->fputs(value ? "true" : "false", json->stream);
+}
+
+bool any_json_write_null(any_json_write_t *json)
+{
+ json->fputs("null", json->stream);
+}
+
+#endif
+
+// MIT License
+//
+// Copyright (c) 2025 Federico Angelilli
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
diff --git a/test/json.c b/test/json.c
new file mode 100644
index 0000000..635f474
--- /dev/null
+++ b/test/json.c
@@ -0,0 +1,139 @@
+#include <string.h>
+#include <stdio.h>
+
+#define ANY_JSON_IMPLEMENT
+#include "any_json.h"
+
+// TODO
+void test_read()
+{
+ const char *src =
+ "{\n"
+ "\t\"hello\": 1,\n"
+ "\t\"key2\": true,\n"
+ "\t\"_aaa__\": { },\n"
+ "\t\"dict\": [1, 2, { \"key\": \"value\" }],\n"
+ "\t\"varx\": 1.1\n"
+ "}\n";
+
+ //any_json_reader_t json;
+ //any_json_reader_init(&json, src, strlen(src));
+
+ //while ((key = any_json_reader_key(&json)) != NULL) {
+ // switch (any_json_reader_type(&json)) {
+ // case ANY_JSON_STRING:
+ // break;
+
+ // case ANY_JSON_NUMBER:
+ // break;
+
+ // case ANY_JSON_BOOL:
+ // break;
+
+ // case ANY_JSON_NULL:
+ // break;
+ // }
+ //}
+
+ //if (any_json_next_object(&json)) {
+ // char *key;
+ // while ((key = any_json_next_key(&json)) != NULL) {
+ // printf("KEY: %s\n", key);
+
+ // any_json_
+ // }
+ // any_json_end(&json);
+ //}
+}
+
+void test_write(bool pretty)
+{
+ any_json_write_t json;
+ any_json_write_init(&json, stdout, (any_json_write_fputs_t)fputs, pretty);
+
+ any_json_write_open_object(&json);
+
+ const char *props[][2] = {
+ { "name", "test" },
+ { "scope", "local" },
+ { "project", "any_json" },
+ { "author", "me" },
+ { 0 },
+ };
+
+ for (int i = 0; props[i][0] != NULL; i++) {
+ any_json_write_member(&json, props[i][0]);
+ any_json_write_string(&json, props[i][1]);
+ }
+
+ any_json_write_member(&json, "list");
+ any_json_write_open_array(&json);
+ {
+ any_json_write_member(&json, NULL);
+ any_json_write_number(&json, 1111111);
+
+ any_json_write_member(&json, NULL);
+ any_json_write_number(&json, 49e32);
+
+ any_json_write_member(&json, NULL);
+ any_json_write_number(&json, 99.99);
+
+ any_json_write_member(&json, NULL);
+ any_json_write_open_array(&json);
+ {
+ any_json_write_member(&json, NULL);
+ any_json_write_string(&json, "nested");
+
+ any_json_write_member(&json, NULL);
+ any_json_write_string(&json, "array");
+ }
+ any_json_write_close_array(&json);
+ }
+ any_json_write_close_array(&json);
+
+ any_json_write_member(&json, "sub");
+ any_json_write_open_object(&json);
+ {
+ any_json_write_member(&json, "data");
+ any_json_write_open_object(&json);
+ {
+ any_json_write_member(&json, "handle");
+ any_json_write_null(&json);
+
+ any_json_write_member(&json, "version");
+ any_json_write_number(&json, 1.1);
+ }
+ any_json_write_close_object(&json);
+
+ any_json_write_member(&json, "pack");
+ any_json_write_open_array(&json);
+ {
+ any_json_write_member(&json, NULL);
+ any_json_write_string(&json, "bin");
+
+ any_json_write_member(&json, NULL);
+ any_json_write_string(&json, "lib");
+
+ any_json_write_member(&json, NULL);
+ any_json_write_bool(&json, true);
+ }
+ any_json_write_close_array(&json);
+ }
+ any_json_write_close_object(&json);
+
+ any_json_write_close_object(&json);
+
+ puts("\n");
+}
+
+int main()
+{
+ printf("JSON WRITE TEST\n");
+ test_write(false);
+
+ printf("JSON PRETTY WRITE TEST\n");
+ test_write(true);
+
+ return 0;
+}
+