marc8 + ISO2709 checks for leader 9 YAZ-800
[yaz-moved-to-github.git] / src / json.c
index a2d4f1d..a214eac 100644 (file)
@@ -1,12 +1,14 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2009 Index Data
+ * Copyright (C) Index Data
  * See the file LICENSE for details.
  */
-
 /**
  * \file json.c
  * \brief JSON encoding/decoding
  */
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 #include <yaz/json.h>
 
@@ -34,7 +36,7 @@ struct json_parser_s {
 json_parser_t json_parser_create(void)
 {
     json_parser_t p = (json_parser_t) xmalloc(sizeof(*p));
-    
+
     p->buf = 0;
     p->cp = 0;
     p->err_msg = 0;
@@ -134,7 +136,7 @@ static int json_one_char(const char **p, char *out)
         case 'b':
             *out = '\b'; break;
         case 'f':
-            *out = '\b'; break;
+            *out = '\f'; break;
         case 'n':
             *out = '\n'; break;
         case 'r':
@@ -196,7 +198,7 @@ static struct json_node *json_parse_string(json_parser_t p)
     }
     n = json_new_node(p, json_node_string);
     dst = n->u.string = (char *) xmalloc(l + 1);
-    
+
     cp = p->cp;
     while (*cp && *cp != '"')
     {
@@ -300,7 +302,7 @@ static struct json_node *json_parse_elements(json_parser_t p)
         }
         m2 = json_new_node(p, json_node_list);
         m2->u.link[0] = n2;
-        
+
         m1->u.link[1] = m2;
         m1 = m2;
     }
@@ -375,7 +377,7 @@ static struct json_node *json_parse_members(json_parser_t p)
         }
         m2 = json_new_node(p, json_node_list);
         m2->u.link[0] = n2;
-        
+
         m1->u.link[1] = m2;
         m1 = m2;
     }
@@ -420,7 +422,7 @@ struct json_node *json_parser_parse(json_parser_t p, const char *json_str)
     p->buf = json_str;
     p->cp = p->buf;
 
-    n = json_parse_object(p);
+    n = json_parse_value(p);
     if (!n)
         return 0;
     c = look_ch(p);
@@ -433,7 +435,8 @@ struct json_node *json_parser_parse(json_parser_t p, const char *json_str)
     return n;
 }
 
-struct json_node *json_parse(const char *json_str, const char **errmsg)
+struct json_node *json_parse2(const char *json_str, const char **errmsg,
+                              size_t *pos)
 {
     json_parser_t p = json_parser_create();
     struct json_node *n = 0;
@@ -447,43 +450,92 @@ struct json_node *json_parse(const char *json_str, const char **errmsg)
         n = json_parser_parse(p, json_str);
         if (!n && errmsg)
             *errmsg = json_parser_get_errmsg(p);
+        if (pos)
+            *pos = json_parser_get_position(p);
         json_parser_destroy(p);
     }
     return n;
 }
 
-void json_write_wrbuf(struct json_node *node, WRBUF result)
+struct json_node *json_parse(const char *json_str, const char **errmsg)
+{
+    return json_parse2(json_str, errmsg, 0);
+}
+
+static void json_indent(WRBUF result, int indent)
+{
+    size_t l = wrbuf_len(result);
+    if (l == 0 || wrbuf_buf(result)[l-1] == '\n')
+    {
+        int i;
+        for (i = 0; i < indent; i++)
+            wrbuf_putc(result, ' ');
+    }
+}
+
+static void json_write_wrbuf_r(struct json_node *node, WRBUF result, int indent)
 {
+    int sub_indent = -1;
+    if (indent >= 0)
+        sub_indent = indent + 1;
     switch (node->type)
     {
     case json_node_object:
+        json_indent(result, indent);
         wrbuf_puts(result, "{");
+        if (indent >= 0)
+        {
+            wrbuf_puts(result, "\n");
+            json_indent(result, sub_indent);
+        }
         if (node->u.link[0])
-            json_write_wrbuf(node->u.link[0], result);
+            json_write_wrbuf_r(node->u.link[0], result, sub_indent);
+        if (indent >= 0)
+        {
+            wrbuf_puts(result, "\n");
+            json_indent(result, indent);
+        }
         wrbuf_puts(result, "}");
         break;
     case json_node_array:
+        json_indent(result, indent);
         wrbuf_puts(result, "[");
+        if (indent >= 0)
+        {
+            wrbuf_puts(result, "\n");
+            json_indent(result, sub_indent);
+        }
         if (node->u.link[0])
-            json_write_wrbuf(node->u.link[0], result);
+        {
+            json_write_wrbuf_r(node->u.link[0], result, sub_indent);
+        }
+        if (indent >= 0)
+        {
+            wrbuf_puts(result, "\n");
+            json_indent(result, indent);
+        }
         wrbuf_puts(result, "]");
         break;
     case json_node_list:
-        json_write_wrbuf(node->u.link[0], result);
+        json_write_wrbuf_r(node->u.link[0], result, indent);
         if (node->u.link[1])
         {
             wrbuf_puts(result, ",");
-            json_write_wrbuf(node->u.link[1], result);
+            if (indent >= 0)
+                wrbuf_puts(result, " ");
+            json_write_wrbuf_r(node->u.link[1], result, indent);
         }
         break;
     case json_node_pair:
-        json_write_wrbuf(node->u.link[0], result);
+        json_write_wrbuf_r(node->u.link[0], result, indent);
         wrbuf_puts(result, ":");
-        json_write_wrbuf(node->u.link[1], result);
+        if (indent >= 0)
+            wrbuf_puts(result, " ");
+        json_write_wrbuf_r(node->u.link[1], result, indent);
         break;
     case json_node_string:
         wrbuf_puts(result, "\"");
-        wrbuf_puts(result, node->u.string);
+        wrbuf_json_puts(result, node->u.string);
         wrbuf_puts(result, "\"");
         break;
     case json_node_number:
@@ -501,6 +553,16 @@ void json_write_wrbuf(struct json_node *node, WRBUF result)
     }
 }
 
+void json_write_wrbuf_pretty(struct json_node *node, WRBUF result)
+{
+    json_write_wrbuf_r(node, result, 1);
+}
+
+void json_write_wrbuf(struct json_node *node, WRBUF result)
+{
+    json_write_wrbuf_r(node, result, -1);
+}
+
 static struct json_node **json_get_objectp(struct json_node *n,
                                            const char *name)
 {
@@ -521,7 +583,7 @@ static struct json_node **json_get_objectp(struct json_node *n,
 struct json_node *json_get_object(struct json_node *n, const char *name)
 {
     struct json_node **np = json_get_objectp(n, name);
-    
+
     if (np)
         return *np;
     return 0;
@@ -530,7 +592,7 @@ struct json_node *json_get_object(struct json_node *n, const char *name)
 struct json_node *json_detach_object(struct json_node *n, const char *name)
 {
     struct json_node **np = json_get_objectp(n, name);
-    
+
     if (np)
     {
         struct json_node *n = *np;
@@ -586,6 +648,11 @@ const char *json_parser_get_errmsg(json_parser_t p)
     return p->err_msg;
 }
 
+size_t json_parser_get_position(json_parser_t p)
+{
+    return p->cp - p->buf;
+}
+
 /*
  * Local variables:
  * c-basic-offset: 4