Commit 3822706525ec50108fac255fb52f02c2bf1ba5f3

Thomas de Grivel 2024-08-14T15:12:07

json_buf_parse

diff --git a/json/json.c b/json/json.c
index beba289..e0ea300 100644
--- a/json/json.c
+++ b/json/json.c
@@ -13,27 +13,53 @@
 #include <libkc3/kc3.h>
 #include "json.h"
 
-/*s_tag * json_buf_parse_null (const s_buf *buf, s_tag *dest) {
+s_tag * json_buf_parse (s_buf *buf, s_tag *dest)
+{
   character c;
   sw r;
   s_buf_save save;
+  s_tag tmp;
   assert(buf);
   assert(dest);
   buf_save_init(buf, &save);
-  if ((r = buf_read_1(buf, "void")) <= 0)
-    goto clean;
-  if (buf_peek_character_utf8(buf, &c) > 0 &&
-      ! ident_character_is_reserved(c)) {
-    r = 0;
-    goto restore;
+  if ((r = buf_peek_character_utf8(buf, &c)) < 0)
+    return NULL;
+  switch (c) {
+    case '{':
+      return json_buf_parse_map(buf, dest);
+    case '"':
+      return json_buf_parse_str(buf, dest);
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case '-':
+      return json_buf_parse_number(buf, dest);
+      break;
+    case 't':
+    case 'f':
+      return json_buf_parse_bool(buf, dest);
+      break;
+    default:
+      return NULL;
   }
-  goto clean;
- restore:
-  buf_save_restore_rpos(buf, &save);
- clean:
-  buf_save_clean(buf, &save);
-  return r;
-}*/
+  *dest = tmp;
+  return dest;
+}
+
+s_tag * json_buf_parse_bool (s_buf *buf, s_tag *dest)
+{
+  sw r;
+  if ((r = buf_parse_tag_bool(buf, dest)) <= 0)
+    return NULL;
+  return dest;
+}
 
 s_tag * json_buf_parse_map (s_buf *buf, s_tag *dest)
 {
@@ -45,13 +71,13 @@ s_tag * json_buf_parse_map (s_buf *buf, s_tag *dest)
   s_list  *values;
   assert(buf);
   assert(dest);
-  buf_save_init(buf, &save);
-  if ((r = buf_read_1(buf, "{")) <= 0)
-    goto clean;
   keys = NULL;
   k = &keys;
   values = NULL;
   v = &values;
+  buf_save_init(buf, &save);
+  if ((r = buf_read_1(buf, "{")) <= 0)
+    goto clean;
   while (1) {
     if ((r = buf_ignore_spaces(buf)) <= 0)
       goto restore;
@@ -59,14 +85,16 @@ s_tag * json_buf_parse_map (s_buf *buf, s_tag *dest)
       goto restore;
     if (r > 0)
       break;
-    buf_parse_tag_str(buf, &(*k)->tag);
-    buf_parse_tag(buf, &(*v)->tag);
+    if ((r = buf_parse_tag_str(buf, &(*k)->tag)) <= 0)
+      goto restore;
+    if (! json_buf_parse(buf, &(*v)->tag))
+      goto restore;
   }
-  dest->type = TAG_MAP;
-  if (! map_init_from_lists(&dest->data.map, keys, values))
+  if (! tag_init_map_from_lists(dest, keys, values))
     goto restore;
   list_delete_all(keys);
   list_delete_all(values);
+  buf_save_clean(buf, &save);
   return dest;
  restore:
   buf_save_restore_rpos(buf, &save);
@@ -77,58 +105,49 @@ s_tag * json_buf_parse_map (s_buf *buf, s_tag *dest)
   return NULL;
 }
 
-s_tag * json_buf_parse_numbers (s_buf *buf, s_tag *dest)
+s_tag * json_buf_parse_null (s_buf *buf, s_tag *dest)
 {
+  character c;
+  sw r;
   s_buf_save save;
   assert(buf);
   assert(dest);
   buf_save_init(buf, &save);
-  if (! buf_parse_tag_number(buf, dest)) {
-    buf_save_restore_rpos(buf, &save);
-    return NULL;
+  if ((r = buf_read_1(buf, "null")) <= 0)
+    goto clean;
+  if (buf_peek_character_utf8(buf, &c) > 0 &&
+      ! ident_character_is_reserved(c)) {
+    r = 0;
+    goto restore;
   }
+  tag_init_void(dest);
+  buf_save_clean(buf, &save);
   return dest;
+ restore:
+  buf_save_restore_rpos(buf, &save);
+ clean:
+  buf_save_clean(buf, &save);
+  return NULL;
 }
 
-s_tag * json_buf_parse (s_buf *buf, s_tag *dest)
+s_tag * json_buf_parse_number (s_buf *buf, s_tag *dest)
 {
-  character c;
-  sw r;
   s_buf_save save;
-  s_tag tmp;
   assert(buf);
   assert(dest);
   buf_save_init(buf, &save);
-  if ((r =buf_peek_character_utf8(buf, &c)) < 0)
+  if (! buf_parse_tag_number(buf, dest)) {
+    buf_save_restore_rpos(buf, &save);
     return NULL;
-  switch (c) {
-    case '{':
-      json_buf_parse_map(buf, &tmp);
-      break;
-    case '"':
-      buf_parse_tag_str(buf, &tmp);
-      break;
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-    case '-':
-      json_buf_parse_numbers(buf, &tmp);
-      break;
-    case 't':
-    case 'f':
-      buf_parse_tag_bool(buf, &tmp);
-      break;
-    default:
-      return NULL;
   }
-  *dest = tmp;
+  return dest;
+}
+
+s_tag * json_buf_parse_str (s_buf *buf, s_tag *dest)
+{
+  sw r;
+  if ((r = buf_parse_tag_str(buf, dest)) <= 0)
+    return NULL;
   return dest;
 }
 
diff --git a/json/json.h b/json/json.h
index 27c83b4..809fb76 100644
--- a/json/json.h
+++ b/json/json.h
@@ -16,6 +16,11 @@
 #include <libkc3/types.h>
 
 s_tag * json_buf_parse (s_buf *buf, s_tag *dest);
+s_tag * json_buf_parse_bool (s_buf *buf, s_tag *dest);
+s_tag * json_buf_parse_map (s_buf *buf, s_tag *dest);
+s_tag * json_buf_parse_null (s_buf *buf, s_tag *dest);
+s_tag * json_buf_parse_number (s_buf *buf, s_tag *dest);
+s_tag * json_buf_parse_str (s_buf *buf, s_tag *dest);
 s_tag * json_from_str (const s_str *src, s_tag *dest);
 
 #endif /* KC3_JSON_H */
diff --git a/libkc3/list_init.c b/libkc3/list_init.c
index d5b2414..403ea6a 100644
--- a/libkc3/list_init.c
+++ b/libkc3/list_init.c
@@ -230,6 +230,18 @@ s_list * list_init_map_1 (s_list *list, const char *p, s_list *next)
   return list;
 }
 
+s_list * list_init_map_from_lists (s_list *list, const s_list *keys,
+                                   const s_list *values, s_list *next)
+{
+  s_list tmp = {0};
+  assert(list);
+  list_init(&tmp, next);
+  if (! tag_init_map_from_lists(&tmp.tag, keys, values))
+    return NULL;
+  *list = tmp;
+  return list;
+}
+
 s_list * list_init_ptr (s_list *list, void *p, s_list *next)
 {
   s_list tmp = {0};
@@ -879,6 +891,20 @@ s_list * list_new_map_1 (const char *p, s_list *next)
   return list;
 }
 
+s_list * list_new_map_from_lists (const s_list *keys,
+                                  const s_list *values, s_list *next)
+{
+  s_list *list;
+  list = list_new(next);
+  if (! list)
+    return NULL;
+  if (! tag_init_map_from_lists(&list->tag, keys, values)) {
+    free(list);
+    return NULL;
+  }
+  return list;
+}
+
 s_list * list_new_ptr (void *p, s_list *next)
 {
   s_list *list;
diff --git a/libkc3/list_init.h b/libkc3/list_init.h
index fb94a63..fa7c587 100644
--- a/libkc3/list_init.h
+++ b/libkc3/list_init.h
@@ -41,6 +41,8 @@ s_list * list_init_integer_zero (s_list *list, s_list *next);
 
 s_list * list_init_map (s_list *list, uw count, s_list *next);
 s_list * list_init_map_1 (s_list *list, const char *p, s_list *next);
+s_list * list_init_map_from_lists (s_list *list, const s_list *keys,
+                                   const s_list *values, s_list *next);
 s_list * list_init_ptr (s_list *list, void *p, s_list *next);
 s_list * list_init_ptr_free (s_list *list, void *p, s_list *next);
 s_list * list_init_quote_copy (s_list *list, const s_quote *quote,
@@ -122,6 +124,8 @@ s_list * list_new_integer_zero (s_list *next);
 
 s_list * list_new_map (uw count, s_list *next);
 s_list * list_new_map_1 (const char *p, s_list *next);
+s_list * list_new_map_from_lists (const s_list *keys,
+                                  const s_list *values, s_list *next);
 s_list * list_new_ptr (void *p, s_list *next);
 s_list * list_new_ptr_free (void *p, s_list *next);
 s_list * list_new_quote_copy (const s_quote *quote, s_list *next);
@@ -191,6 +195,8 @@ s_list * list_integer_zero (s_list *list);
 
 s_list * list_map (s_list *list, uw count);
 s_list * list_map_1 (s_list *list, const char *p);
+s_list * list_map_from_lists (s_list *list, const s_list *keys,
+                              const s_list *values);
 s_list * list_ptr (s_list *list, void *p);
 s_list * list_ptr_free (s_list *list, void *p);
 s_list * list_quote_copy (s_list *list, const s_quote *quote);
diff --git a/libkc3/tag_init.c b/libkc3/tag_init.c
index d0a95ee..5ebc612 100644
--- a/libkc3/tag_init.c
+++ b/libkc3/tag_init.c
@@ -232,6 +232,18 @@ s_tag * tag_init_map_1 (s_tag *tag, const char *p)
   return tag;
 }
 
+s_tag * tag_init_map_from_lists (s_tag *tag, const s_list *keys,
+                                 const s_list *values)
+{
+  s_tag tmp = {0};
+  assert(tag);
+  tmp.type = TAG_MAP;
+  if (! map_init_from_lists(&tmp.data.map, keys, values))
+    return NULL;
+  *tag = tmp;
+  return tag;
+}
+
 s_tag * tag_init_ptr (s_tag *tag, void *p)
 {
   s_tag tmp = {0};
@@ -861,6 +873,21 @@ s_tag * tag_new_map_1 (const char *p)
   return tag;
 }
 
+s_tag * tag_new_map_from_lists (const s_list *keys,
+                                const s_list *values)
+{
+  s_tag *tag;
+  tag = alloc(sizeof(s_tag));
+  if (! tag)
+    return NULL;
+  tag->type = TAG_MAP;
+  if (! map_init_from_lists(&tag->data.map, keys, values)) {
+    free(tag);
+    return NULL;
+  }
+  return tag;
+}
+
 s_tag * tag_new_ptr (void *p)
 {
   s_tag *tag;
@@ -1555,6 +1582,19 @@ s_tag * tag_map_1 (s_tag *tag, const char *p)
   return tag;
 }
 
+s_tag * tag_map_from_lists (s_tag *tag, const s_list *keys,
+                            const s_list *values)
+{
+  s_tag tmp = {0};
+  assert(tag);
+  tag_clean(tag);
+  tmp.type = TAG_MAP;
+  if (! map_init_from_lists(&tmp.data.map, keys, values))
+    return NULL;
+  *tag = tmp;
+  return tag;
+}
+
 s_tag * tag_ptr (s_tag *tag, void *p)
 {
   s_tag tmp = {0};
diff --git a/libkc3/tag_init.h b/libkc3/tag_init.h
index a086916..7ff3bbf 100644
--- a/libkc3/tag_init.h
+++ b/libkc3/tag_init.h
@@ -36,6 +36,8 @@ s_tag * tag_init_integer_zero (s_tag *tag);
 s_tag * tag_init_list (s_tag *tag, s_list *list);
 s_tag * tag_init_map (s_tag *tag, uw count);
 s_tag * tag_init_map_1 (s_tag *tag, const char *p);
+s_tag * tag_init_map_from_lists (s_tag *tag, const s_list *keys,
+                                 const s_list *values);
 s_tag * tag_init_ptr (s_tag *tag, void *p);
 s_tag * tag_init_ptr_free (s_tag *tag, void *p);
 s_tag * tag_init_quote_copy (s_tag *tag, const s_quote *quote);
@@ -102,6 +104,8 @@ s_tag * tag_new_integer_zero (void);
 s_tag * tag_new_list (s_list *list);
 s_tag * tag_new_map (uw count);
 s_tag * tag_new_map_1 (const char *p);
+s_tag * tag_new_map_from_lists (const s_list *keys,
+                                const s_list *values);
 s_tag * tag_new_ptr (void *p);
 s_tag * tag_new_ptr_free (void *p);
 s_tag * tag_new_quote_copy (const s_quote *quote);
@@ -164,6 +168,8 @@ s_tag * tag_integer_zero (s_tag *tag);
 s_tag * tag_list (s_tag *tag, s_list *list);
 s_tag * tag_map (s_tag *tag, uw count);
 s_tag * tag_map_1 (s_tag *tag, const char *p);
+s_tag * tag_map_from_lists (s_tag *tag, const s_list *keys,
+                            const s_list *values);
 s_tag * tag_ptr (s_tag *tag, void *p);
 s_tag * tag_ptr_free (s_tag *tag, void *p);
 s_tag * tag_quote_copy (s_tag *tag, const s_quote *quote);
diff --git a/libkc3/tag_init.rb b/libkc3/tag_init.rb
index ccf62a9..4f88f33 100644
--- a/libkc3/tag_init.rb
+++ b/libkc3/tag_init.rb
@@ -339,6 +339,9 @@ class TagInitList
        TagInit.new("map", "TAG_MAP", :init_mode_init,
                    [Arg.new("uw", "count")]),
        TagInit1.new("map", "1", "TAG_MAP", :init_mode_init),
+       TagInit.new("map", "from_lists", "TAG_MAP", :init_mode_init,
+                   [Arg.new("const s_list *", "keys"),
+                    Arg.new("const s_list *", "values")]),
        TagInit.new("ptr", "TAG_PTR", :init_mode_init,
                    [Arg.new("void *", "p")]),
        TagInit.new("ptr_free", "TAG_PTR_FREE", :init_mode_init,