]> mj.ucw.cz Git - libucw.git/commitdiff
JSON: Rudimentary formatting
authorMartin Mares <mj@ucw.cz>
Wed, 8 Jul 2015 14:43:57 +0000 (16:43 +0200)
committerMartin Mares <mj@ucw.cz>
Wed, 8 Jul 2015 14:43:57 +0000 (16:43 +0200)
ucw-json/Makefile
ucw-json/format.c [new file with mode: 0644]
ucw-json/json.c
ucw-json/json.h
ucw-json/parse.c

index 0e5bd98b856400703501a9350a263f286f37fbd5..7c54ffb79381f02adecd26c088d646b0eaa4d0e0 100644 (file)
@@ -4,7 +4,7 @@
 DIRS+=ucw-json
 PROGS+=$(o)/ucw-json/json-test
 
-LIBJSON_MODS=json parse
+LIBJSON_MODS=json parse format
 LIBJSON_MOD_PATHS=$(addprefix $(o)/ucw-json/,$(LIBJSON_MODS))
 LIBJSON_INCLUDES=json.h
 LIBJSON_DEPS=$(LIBUCW)
diff --git a/ucw-json/format.c b/ucw-json/format.c
new file mode 100644 (file)
index 0000000..2c17ca5
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *     UCW JSON Library -- Formatter
+ *
+ *     (c) 2015 Martin Mares <mj@ucw.cz>
+ *
+ *     This software may be freely distributed and used according to the terms
+ *     of the GNU Lesser General Public License.
+ */
+
+#include <ucw/lib.h>
+#include <ucw/fastbuf.h>
+#include <ucw/gary.h>
+#include <ucw/ff-unicode.h>
+#include <ucw/unicode.h>
+#include <ucw-json/json.h>
+
+#include <stdio.h>
+
+void json_set_output(struct json_context *js, struct fastbuf *fb)
+{
+  js->out_fb = fb;
+}
+
+static void write_string(struct fastbuf *fb, const char *p)
+{
+  bputc(fb, '"');
+  for (;;)
+    {
+      uint u;
+      p = utf8_32_get(p, &u);
+      if (!u)
+       break;
+      if (u == '"' || u == '\\')
+       {
+         bputc(fb, '\\');
+         bputc(fb, u);
+       }
+      else if (u < 0x20)
+       {
+         // We avoid "\f" nor "\b" and use "\uXXXX" instead
+         switch (u)
+           {
+           case 0x09: bputs(fb, "\\t"); break;
+           case 0x0a: bputs(fb, "\\n"); break;
+           case 0x0d: bputs(fb, "\\r"); break;
+           default:
+             bprintf(fb, "\\u%04x", u);
+           }
+       }
+      else
+       bputc(fb, u);
+    }
+  bputc(fb, '"');
+}
+
+void json_write_value(struct json_context *js, struct json_node *n)
+{
+  struct fastbuf *fb = js->out_fb;
+
+  switch (n->type)
+    {
+    case JSON_NULL:
+      bputs(fb, "null");
+      break;
+    case JSON_BOOLEAN:
+      bputs(fb, (n->boolean ? "true" : "false"));
+      break;
+    case JSON_NUMBER:
+      // FIXME: Formatting of floats
+      bprintf(fb, "%f", n->number);
+      break;
+    case JSON_STRING:
+      write_string(fb, n->string);
+      break;
+    case JSON_ARRAY:
+      {
+       // FIXME: Indent
+       bputs(fb, "[ ");
+       for (size_t i=0; i < GARY_SIZE(n->elements); i++)
+         {
+           if (i)
+             bputs(fb, ", ");
+           json_write_value(js, n->elements[i]);
+         }
+       bputc(fb, ']');
+       break;
+      }
+    case JSON_OBJECT:
+      {
+       bputs(fb, "{ ");
+       // FIXME: Indent
+       for (size_t i=0; i < GARY_SIZE(n->pairs); i++)
+         {
+           if (i)
+             bputs(fb, ", ");
+           struct json_pair *p = &n->pairs[i];
+           write_string(fb, p->key);
+           bputs(fb, ": ");
+           json_write_value(js, p->value);
+         }
+       bputc(fb, '}');
+       break;
+      }
+    default:
+      ASSERT(0);
+    }
+}
+
+void json_write(struct json_context *js, struct fastbuf *fb, struct json_node *n)
+{
+  json_set_output(js, fb);
+  json_write_value(js, n);
+  bputc(fb, '\n');
+}
index 35ee49f9b462b8139f5cf98c316ac6395ca221d8..6b53d2fb2f757879468788f6c60cf1cb0eeb1102 100644 (file)
@@ -7,8 +7,6 @@
  *     of the GNU Lesser General Public License.
  */
 
-#undef LOCAL_DEBUG
-
 #include <ucw/lib.h>
 #include <ucw/gary.h>
 #include <ucw/mempool.h>
index 5340a30e1ea57f15f4048b4f6ef94e08efc81c5f..ac5570d9cc7b9e59b3675a2c18fdf97529943789 100644 (file)
@@ -34,6 +34,8 @@ struct json_context {
   struct json_node *next_token;
   struct json_node *trivial_token;
   int next_char;
+
+  struct fastbuf *out_fb;
 };
 
 struct json_context *json_new(void);
@@ -120,8 +122,12 @@ void json_set_input(struct json_context *js, struct fastbuf *in);
 struct json_node *json_peek_token(struct json_context *js);
 struct json_node *json_next_token(struct json_context *js);
 
-struct json_node *json_next_object(struct json_context *js);
+struct json_node *json_next_value(struct json_context *js);
 
 struct json_node *json_parse(struct json_context *js, struct fastbuf *fb);
 
+void json_set_output(struct json_context *js, struct fastbuf *fb);
+void json_write_value(struct json_context *js, struct json_node *n);
+void json_write(struct json_context *js, struct fastbuf *fb, struct json_node *n);
+
 #endif
index 181c6afb5bcdff274600080d6233bb358df4ca24..a4de28defa522f6ead699ee133ba38ab0e2908f2 100644 (file)
@@ -7,11 +7,10 @@
  *     of the GNU Lesser General Public License.
  */
 
-#undef LOCAL_DEBUG
-
 #include <ucw/lib.h>
-#include <ucw/trans.h>
+#include <ucw/fastbuf.h>
 #include <ucw/ff-unicode.h>
+#include <ucw/trans.h>
 #include <ucw/unicode.h>
 #include <ucw-json/json.h>
 
@@ -332,7 +331,7 @@ struct json_node *json_next_token(struct json_context *js)
   return t;
 }
 
-struct json_node *json_next_object(struct json_context *js)
+struct json_node *json_next_value(struct json_context *js)
 {
   struct json_node *t = json_next_token(js);
 
@@ -356,7 +355,7 @@ struct json_node *json_next_object(struct json_context *js)
          json_next_token(js);
        else for (;;)
          {
-           struct json_node *v = json_next_object(js);
+           struct json_node *v = json_next_value(js);
            if (!v)
              json_parse_error(js, "Unterminated array");
            json_array_append(a, v);
@@ -378,7 +377,7 @@ struct json_node *json_next_object(struct json_context *js)
          json_next_token(js);
        else for (;;)
          {
-           struct json_node *k = json_next_object(js);
+           struct json_node *k = json_next_value(js);
            if (!k)
              json_parse_error(js, "Unterminated object");
            if (k->type != JSON_STRING)
@@ -388,7 +387,7 @@ struct json_node *json_next_object(struct json_context *js)
            if (t->type != JSON_NAME_SEP)
              json_parse_error(js, "Colon expected");
 
-           struct json_node *v = json_next_object(js);
+           struct json_node *v = json_next_value(js);
            if (!v)
              json_parse_error(js, "Unterminated object");
            if (json_object_get(o, k->string))          // FIXME: Optimize
@@ -422,7 +421,7 @@ struct json_node *json_parse(struct json_context *js, struct fastbuf *fb)
 {
   json_set_input(js, fb);
 
-  struct json_node *n = json_next_object(js);
+  struct json_node *n = json_next_value(js);
   if (!n)
     json_parse_error(js, "Empty input");