Commit 5f0f12a5193f842563f338f156a98a1f27533bed

Baptiste 2024-08-13T17:35:05

json_parse: wip

diff --git a/json/json.c b/json/json.c
index 0fe9a55..faf90be 100644
--- a/json/json.c
+++ b/json/json.c
@@ -12,12 +12,116 @@
  */
 #include <libkc3/kc3.h>
 #include "json.h"
+#include "buf.h"
+#include "buf_parse.h"
+#include "err.h"
+#include "tag.h"
+
+s_tag * json_buf_parse_map (const s_buf *buf, s_tag *dest) {
+  s_buf_save save;
+  assert(buf);
+  assert(dest);
+  dest->type = TAG_MAP
+  dest->data.map = map_new();
+  buf_save_init(buf, &save);
+  if (! buf_parse_map(buf, dest->data.map)) {
+    buf_restore_rpos(buf, &save);
+    return NULL;
+  }
+  return dest;
+}
+
+s_tag * json_buf_parse_list (const s_buf *buf, s_tag *dest) {
+  s_buf_save save;
+  assert(buf);
+  assert(dest);
+  dest->type = TAG_LIST;
+  dest->data.list = list_new();
+  buf_save_init(buf, &save);
+  if (! buf_parse_list(buf, dest->data.list)) {
+    buf_restore_rpos(buf, &save);
+    return NULL;
+  }
+  return dest;
+}
+
+s_tag * json_buf_parse_str (const s_buf *buf, s_tag *dest) {
+  s_buf_save save;
+  assert(buf);
+  assert(dest);
+  dest->type = TAG_STR;
+  dest->data.str = str_new();
+  buf_save_init(buf, &save);
+  if (! buf_parse_str(buf, dest->data.str)) {
+    buf_restore_rpos(buf, &save);
+    return NULL;
+  }
+  return dest;
+}
+
+s_tag * json_buf_parse_numbers (const s_buf *buf, s_tag *dest) {
+  assert(buf);
+  assert(dest);
+  if (! buf_parse_tag_number(buf, dest)) {
+    buf_restore_rpos(buf, &save);
+    return NULL;
+  }
+  return dest;
+}
+
+s_tag * json_buf_parse_boolean (const s_buf *buf, s_tag *dest) {
+  assert(buf);
+  assert(dest);
+  if (buf_peek(buf) == 't') {
+    dest->type = TAG_BOOL;
+    dest->data.boolean = true;
+    buf_skip(buf, 4);
+  } else {
+    dest->type = TAG_BOOL;
+    dest->data.boolean = false;
+    buf_skip(buf, 5);
+  }
+  return dest;
+}
 
 static bool parse_json(const s_buf *buf, s_tag *dest) {
   assert(buf);
   assert(dest);
-  if (buf_parse_tag_number(buf, dest) == 0)
-    return false;
+  switch (buf_peek(buf)) {
+    case '{':
+      json_buf_parse_map(buf, dest);
+      if (buf_peek(buf) != '}') {
+        errputs("json_parse: expected '}'");
+        return false;
+      }
+      break;
+    case '[':
+      json_buf_parse_list(buf, dest);
+        if (buf_peek(buf) != ']') {
+          errputs("json_parse: expected ']'");
+          return false;
+       }
+      break;
+    case '"':
+      json_buf_parse_str(buf, dest);
+      if (buf_peek(buf) != '"') {
+        errputs("json_parse: expected '\"'");
+        return false;
+      }
+      break;
+    case '0' ... '9':
+      json_buf_parse_numbers(buf, dest);
+      break;
+    case 't':
+    case 'f':
+      json_buf_parse_boolean(buf, dest);
+      break;
+    case 'n':
+      dest->type = TAG_NULL;
+      break;
+    default:
+      return false;
+  }
   return true;
 }
 
@@ -26,7 +130,7 @@ s_tag *json_parse(const s_buf *buf, s_tag *dest) {
   assert(dest);
   s_buf_save save;
   buf_save_init(buf, &save);
-  if (!parse_json(buf, dest)) {
+  if (! parse_json(buf, dest)) {
     buf_restore_rpos(buf, &save);
     return NULL;
   }