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 */