Commit 573b9988c1d8afd55b7687a6f11a6c62c00dcd5f

Thomas de Grivel 2024-07-02T01:19:35

ec3: work in progress

diff --git a/libc3_web/ec3.c b/libc3_web/ec3.c
index da03676..d669bfc 100644
--- a/libc3_web/ec3.c
+++ b/libc3_web/ec3.c
@@ -13,28 +13,167 @@
 #include <libc3/c3.h>
 #include "ec3.h"
 
-sw ec3_buf_parse (s_ec3 *ec3, s_buf *buf)
+#define EC3_BUF_PARSE_STR_BUF_SIZE (1024 * 1024)
+
+s_list ** ec3_append_and_empty_buf (s_list **tail, s_buf *buf)
 {
-  assert(ec3);
+  sw r;
+  s_str str;
+  assert(tail);
+  assert(! *tail);
   assert(buf);
-  (void) ec3;
-  (void) buf;
-  return -42;
+  r = buf_read_to_str(buf, &str);
+  if (r < 0)
+    return NULL;
+  if (! r) {
+    buf_empty(buf);
+    return tail;
+  }
+  *tail = list_new(NULL);
+  if (! *tail) {
+    str_clean(&str);
+    return NULL;
+  }
+  (*tail)->tag.type = TAG_STR;
+  (*tail)->tag.data.str = str;
+  buf_empty(buf);
+  return tail;
+}
+
+s_list ** ec3_append_block (s_list **tail, s_block *block)
+{
+  assert(tail);
+  assert(! *tail);
+  assert(block);
+  *tail = list_new(NULL);
+  if (! *tail)
+    return NULL;
+  (*tail)->tag.type = TAG_BLOCK;
+  (*tail)->tag.data.block = *block;
+  return tail;
+}
+
+s_list ** ec3_append_silent_block (s_list **tail, s_block *block)
+{
+  assert(tail);
+  assert(! *tail);
+  assert(block);
+  if (! ec3_append_sym(tail, sym_1("silent")))
+    return NULL;
+  if (! ec3_append_block(tail, block))
+    return NULL;
+  return tail;
+}
+
+s_list ** ec3_append_str (s_list **tail, s_str *str)
+{
+  assert(tail);
+  assert(! *tail);
+  assert(str);
+  *tail = list_new(NULL);
+  if (! *tail)
+    return NULL;
+  (*tail)->tag.type = TAG_STR;
+  (*tail)->tag.data.str = *str;
+  return tail;
+}
+
+s_list ** ec3_append_sym (s_list **tail, const s_sym *sym)
+{
+  assert(tail);
+  assert(! *tail);
+  assert(sym);
+  *tail = list_new(NULL);
+  if (! *tail)
+    return NULL;
+  (*tail)->tag.type = TAG_SYM;
+  (*tail)->tag.data.sym = sym;
+  return tail;
+}
+
+sw ec3_buf_parse (s_buf *buf, p_ec3 *dest)
+{
+  s_block block;
+  character c;
+  sw r;
+  sw result = 0;
+  s_buf_save save;
+  s_buf str_buf;
+  s_list **tail;
+  p_ec3 tmp;
+  assert(dest);
+  assert(buf);
+  if (! buf_init_alloc(&str_buf, EC3_BUF_PARSE_STR_BUF_SIZE))
+    return -1;
+  ec3_init(&tmp);
+  tail = &tmp;
+  buf_save_init(buf, &save);
+  while (1) {
+    r = buf_read_1(buf, "<%=");
+    if (r < 0)
+      goto restore;
+    if (r > 0) {
+      result += r;
+      if (! ec3_append_and_empty_buf(tail, &str_buf))
+        goto ko;
+      r = ec3_buf_parse_c3_block(buf, &block);
+      if (r <= 0)
+        goto restore;
+      if (! ec3_append_block(tail, &block))
+        goto ko;
+      continue;
+    }
+    r = buf_read_1(buf, "<%");
+    if (r < 0)
+      goto restore;
+    if (r > 0) {
+      result += r;
+      if (! ec3_append_and_empty_buf(tail, &str_buf))
+        goto ko;
+      r = ec3_buf_parse_c3_block(buf, &block);
+      if (r <= 0)
+        goto restore;
+      if (! ec3_append_block(tail, &block))
+        goto ko;
+      continue;
+    }
+    r = buf_read_character_utf8(buf, &c);
+    if (r < 0)
+      goto restore;
+    if (! r) {
+      *dest = tmp;
+      r = result;
+      goto clean;
+    }
+    result += r;
+    r = buf_write_character_utf8(&str_buf, c);
+    if (r <= 0)
+      goto restore;
+  }
+ ko:
+  r = -1;
+ restore:
+  buf_save_restore_rpos(buf, &save);
+  ec3_clean(&tmp);
+ clean:
+  buf_clean(&str_buf);
+  buf_save_clean(buf, &save);
+  return r;
 }
 
-void ec3_clean (s_ec3 *ec3)
+void ec3_clean (p_ec3 *ec3)
 {
-  list_clean(ec3);
+  list_delete_all(*ec3);
 }
 
-s_ec3 * ec3_init (s_ec3 *ec3)
+p_ec3 * ec3_init (p_ec3 *ec3)
 {
-  s_ec3 tmp = {0};
+  p_ec3 tmp = {0};
   *ec3 = tmp;
   return ec3;
 }
 
-sw ec3_render (const s_ec3 *ec3, s_buf *buf, s_map *map)
+sw ec3_render (const p_ec3 *ec3, s_buf *buf, s_map *map)
 {
   assert(ec3);
   assert(buf);
@@ -45,7 +184,7 @@ sw ec3_render (const s_ec3 *ec3, s_buf *buf, s_map *map)
   return -42;
 }
 
-s_fn * ec3_to_render_fn (const s_ec3 *ec3, s_fn *dest)
+s_fn * ec3_to_render_fn (const p_ec3 *ec3, s_fn *dest)
 {
   assert(ec3);
   assert(dest);
diff --git a/libc3_web/ec3.h b/libc3_web/ec3.h
index ba122ec..6149f4d 100644
--- a/libc3_web/ec3.h
+++ b/libc3_web/ec3.h
@@ -16,14 +16,20 @@
 #include "types.h"
 
 /* Stack-allocation compatible functions, call ec3_clean after use. */
-void    ec3_clean (s_ec3 *ec3);
-s_ec3 * ec3_init (s_ec3 *ec3);
+void    ec3_clean (p_ec3 *ec3);
+p_ec3 * ec3_init (p_ec3 *ec3);
 
 /* Operators. */
-sw     ec3_buf_parse (s_ec3 *ec3, s_buf *buf);
+s_list ** ec3_append_and_empty_buf (s_list **tail, s_buf *buf);
+s_list ** ec3_append_block (s_list **tail, s_block *block);
+s_list ** ec3_append_silent_block (s_list **tail, s_block *block);
+s_list ** ec3_append_str (s_list **tail, s_str *str);
+s_list ** ec3_append_sym (s_list **tail, const s_sym *sym);
+sw        ec3_buf_parse (s_buf *buf, p_ec3 *dest);
+sw        ec3_buf_parse_c3_block (s_buf *buf, s_block *dest);
 
 /* Observers. */
-sw     ec3_render (const s_ec3 *ec3, s_buf *buf, s_map *map);
-s_fn * ec3_to_render_fn (const s_ec3 *ec3, s_fn *dest);
+sw     ec3_render (const p_ec3 *ec3, s_buf *buf, s_map *map);
+s_fn * ec3_to_render_fn (const p_ec3 *ec3, s_fn *dest);
 
 #endif /* LIBC3_WEB_EC3_H */
diff --git a/libc3_web/types.h b/libc3_web/types.h
index 4dda64b..82e1cc5 100644
--- a/libc3_web/types.h
+++ b/libc3_web/types.h
@@ -15,6 +15,6 @@
 
 #include <libc3/types.h>
 
-typedef s_list s_ec3;
+typedef s_list *p_ec3;
 
 #endif /* LIBC3_WEB_TYPES_H */