Commit d136be8b59b103e303ce2a965b8b21f5b657bba3

Thomas de Grivel 2024-01-25T11:49:18

wip str

diff --git a/libc3/list_init.c b/libc3/list_init.c
index 532c7d8..3d18caa 100644
--- a/libc3/list_init.c
+++ b/libc3/list_init.c
@@ -286,6 +286,18 @@ s_list * list_init_str_1 (s_list *list, char *p_free, const char *p,
   return list;
 }
 
+s_list * list_init_str_cat (s_list *list, const s_str *a, 
+                            const s_str *b, s_list *next)
+{
+  s_list tmp;
+  assert(list);
+  list_init(&tmp, next);
+  if (! tag_init_str_cat(&tmp.tag, a, b))
+    return NULL;
+  *list = tmp;
+  return list;
+}
+
 s_list * list_init_struct (s_list *list, const s_sym *module, 
                            s_list *next)
 {
@@ -721,6 +733,19 @@ s_list * list_new_str_1 (char *p_free, const char *p, s_list *next)
   return list;
 }
 
+s_list * list_new_str_cat (const s_str *a, const s_str *b, s_list *next)
+{
+  s_list *list;
+  list = list_new(next);
+  if (! list)
+    return NULL;
+  if (! tag_init_str_cat(&list->tag, a, b)) {
+    free(list);
+    return NULL;
+  }
+  return list;
+}
+
 s_list * list_new_struct (const s_sym *module, s_list *next)
 {
   s_list *list;
diff --git a/libc3/list_init.h b/libc3/list_init.h
index 97988c3..418120b 100644
--- a/libc3/list_init.h
+++ b/libc3/list_init.h
@@ -47,6 +47,8 @@ s_list * list_init_str (s_list *list, char *p_free, uw size,
                         const char *p, s_list *next);
 s_list * list_init_str_1 (s_list *list, char *p_free, const char *p, 
                           s_list *next);
+s_list * list_init_str_cat (s_list *list, const s_str *a, 
+                            const s_str *b, s_list *next);
 s_list * list_init_struct (s_list *list, const s_sym *module, 
                            s_list *next);
 s_list * list_init_struct_with_data (s_list *list, const s_sym *module, 
@@ -93,6 +95,8 @@ s_list * list_new_s64 (s64 i, s_list *next);
 s_list * list_new_str (char *p_free, uw size, const char *p, 
                        s_list *next);
 s_list * list_new_str_1 (char *p_free, const char *p, s_list *next);
+s_list * list_new_str_cat (const s_str *a, const s_str *b, 
+                           s_list *next);
 s_list * list_new_struct (const s_sym *module, s_list *next);
 s_list * list_new_struct_with_data (const s_sym *module, 
                                     bool free_data, void *data, 
@@ -137,6 +141,7 @@ s_list * list_s32 (s_list *list, s32 i);
 s_list * list_s64 (s_list *list, s64 i);
 s_list * list_str (s_list *list, char *p_free, uw size, const char *p);
 s_list * list_str_1 (s_list *list, char *p_free, const char *p);
+s_list * list_str_cat (s_list *list, const s_str *a, const s_str *b);
 s_list * list_struct (s_list *list, const s_sym *module);
 s_list * list_struct_with_data (s_list *list, const s_sym *module, 
                                 bool free_data, void *data);
diff --git a/libc3/str.c b/libc3/str.c
index 185129c..fc92bd7 100644
--- a/libc3/str.c
+++ b/libc3/str.c
@@ -97,31 +97,39 @@ bool str_has_reserved_characters (const s_str *src)
 
 s_str * str_init (s_str *str, char *free, uw size, const char *p)
 {
+  s_str tmp = {0};
   assert(str);
-  str->free.p = free;
-  str->size = size;
-  str->ptr.p = p;
+  tmp.free.p = free;
+  tmp.size = size;
+  tmp.ptr.p = p;
+  *str = tmp;
   return str;
 }
 
 s_str * str_init_1 (s_str *str, char *free, const char *p)
 {
+  s_str tmp = {0};
   assert(str);
-  str->free.p = free;
-  str->size = strlen(p);
-  str->ptr.p = p;
+  tmp.free.p = free;
+  tmp.size = strlen(p);
+  tmp.ptr.p = p;
+  *str = tmp;
   return str;
 }
 
 s_str * str_init_alloc (s_str *str, uw size, const char *p)
 {
+  s_str tmp;
   assert(str);
-  str->free.p = calloc(size + 1, 1);
-  str->size = size;
-  str->ptr.p = str->free.p;
-  if (! str->ptr.p)
-    err(1, "out of memory");
-  memcpy(str->free.p, p, size);
+  tmp.free.p = calloc(size + 1, 1);
+  if (! tmp.free.p) {
+    err_puts("str_init_alloc: failed to allocate memory.");
+    assert(! "str_init_alloc: failed to allocate memory.");
+    return NULL;
+  }
+  tmp.size = size;
+  tmp.ptr.p = tmp.free.p;
+  memcpy(tmp.free.p, p, size);
   return str;
 }
 
@@ -144,51 +152,90 @@ s_str * str_init_cast (s_str *str, const s_tag *tag)
   return NULL;
 }
 
+s_str * str_init_cat (s_str *str, const s_str *a, const s_str *b)
+{
+  s_str tmp = {0};
+  assert(str);
+  assert(a);
+  assert(b);
+  tmp.size = a->size + b->size;
+  tmp.free.p = calloc(tmp.size + 1, 1);
+  if (! tmp.free.p) {
+    err_puts("str_init_cat: failed to allocate memory.");
+    assert(! "str_init_cat: failed to allocate memory.");
+    return NULL;
+  }
+  tmp.ptr.p = tmp.free.p;
+  memcpy(tmp.free.ps8, a->ptr.p, a->size);
+  memcpy(tmp.free.ps8 + a->size, b->ptr.p, b->size);
+  *str = tmp;
+  return str;
+}
+
 s_str * str_init_copy (s_str *str, const s_str *src)
 {
+  s_str tmp = {0};
   assert(str);
   assert(src);
-  str->free.p = calloc(src->size + 1, 1);
-  str->size = src->size;
-  str->ptr.p = str->free.p;
-  memcpy(str->free.p, src->ptr.p, str->size);
+  tmp.free.p = calloc(src->size + 1, 1);
+  if (! tmp.free.p) {
+    err_puts("str_init_copy: failed to allocate memory.");
+    assert(! "str_init_copy: failed to allocate memory.");
+    return NULL;
+  }
+  tmp.size = src->size;
+  tmp.ptr.p = tmp.free.p;
+  memcpy(tmp.free.p, src->ptr.p, tmp.size);
+  *str = tmp;
   return str;
 }
 
 s_str * str_init_copy_1 (s_str *str, const char *src)
 {
   uw len;
+  s_str tmp = {0};
   assert(str);
   assert(src);
   len = strlen(src);
-  str->free.p = calloc(len + 1, 1);
-  str->size = len;
-  str->ptr.p = str->free.p;
-  memcpy(str->free.p, src, len + 1);
+  tmp.free.p = calloc(len + 1, 1);
+  if (! tmp.free.p) {
+    err_puts("str_init_copy_1: failed to allocate memory.");
+    assert(! "str_init_copy_1: failed to allocate memory.");
+    return NULL;
+  }
+  tmp.size = len;
+  tmp.ptr.p = tmp.free.p;
+  memcpy(tmp.free.p, src, len + 1);
+  *str = tmp;
   return str;
 }
 
 s_str * str_init_empty (s_str *str)
 {
+  s_str tmp = {0};
   assert(str);
-  str->free.p = NULL;
-  str->size = 0;
-  str->ptr.p = NULL;
+  *str = tmp;
   return str;
 }
 
 s_str * str_init_f (s_str *str, const char *fmt, ...)
 {
   va_list ap;
+  s_str tmp = {0};
   va_start(ap, fmt);
-  str_init_vf(str, fmt, ap);
+  if (! str_init_vf(&tmp, fmt, ap)) {
+    va_end(ap);
+    return NULL;
+  }
   va_end(ap);
+  *str = tmp;
   return str;
 }
 
 s_str * str_init_slice (s_str *str, const s_str *src, sw start, sw end)
 {
   s_buf buf;
+  s_str tmp = {0};
   assert(str);
   assert(src);
   buf_init(&buf, false, src->size, (char *) src->ptr.pchar);
@@ -201,8 +248,9 @@ s_str * str_init_slice (s_str *str, const s_str *src, sw start, sw end)
     assert(! "str_init_slice: invalid positions");
     return NULL;
   }
-  if (! buf_read_to_str(&buf, str))
+  if (! buf_read_to_str(&buf, &tmp))
     return NULL;
+  *str = tmp;
   return str;
 }
 
diff --git a/libc3/str.h b/libc3/str.h
index f44f532..924319a 100644
--- a/libc3/str.h
+++ b/libc3/str.h
@@ -32,6 +32,7 @@ s_str * str_init (s_str *str, char *free, uw size, const char *p);
 s_str * str_init_1 (s_str *str, char *free, const char *p);
 s_str * str_init_alloc (s_str *str, uw size, const char *p);
 s_str * str_init_cast (s_str *str, const s_tag *tag);
+s_str * str_init_cat (s_str *str, const s_str *a, const s_str *b);
 s_str * str_init_copy (s_str *str, const s_str *src);
 s_str * str_init_copy_1 (s_str *str, const char *p);
 s_str * str_init_empty (s_str *str);
diff --git a/libc3/tag_add.c b/libc3/tag_add.c
index 87f8656..1ddb007 100644
--- a/libc3/tag_add.c
+++ b/libc3/tag_add.c
@@ -1207,6 +1207,13 @@ s_tag * tag_add (const s_tag *a, const s_tag *b, s_tag *dest)
     default:
       goto ko;
     }
+  case TAG_STR:
+    switch (b->type) {
+    case TAG_STR:
+      return tag_init_str_cat(dest, &a->data.str, &b->data.str);
+    default:
+      goto ko;
+    }
   default:
     goto ko;
   }
diff --git a/libc3/tag_init.c b/libc3/tag_init.c
index 1373c60..d12c67b 100644
--- a/libc3/tag_init.c
+++ b/libc3/tag_init.c
@@ -281,6 +281,17 @@ s_tag * tag_init_str_1 (s_tag *tag, char *p_free, const char *p)
   return tag;
 }
 
+s_tag * tag_init_str_cat (s_tag *tag, const s_str *a, const s_str *b)
+{
+  s_tag tmp = {0};
+  assert(tag);
+  tmp.type = TAG_STR;
+  if (! str_init_cat(&tmp.data.str, a, b))
+    return NULL;
+  *tag = tmp;
+  return tag;
+}
+
 s_tag * tag_init_struct (s_tag *tag, const s_sym *module)
 {
   s_tag tmp = {0};
@@ -728,6 +739,21 @@ s_tag * tag_new_str_1 (char *p_free, const char *p)
   return tag;
 }
 
+s_tag * tag_new_str_cat (const s_str *a, const s_str *b)
+{
+  s_tag *tag;
+  if (! (tag = calloc(1, sizeof(s_tag)))) {
+    warn("tag_new_str_cat: calloc");
+    return NULL;
+  }
+  tag->type = TAG_STR;
+  if (! str_init_cat(&tag->data.str, a, b)) {
+    free(tag);
+    return NULL;
+  }
+  return tag;
+}
+
 s_tag * tag_new_struct (const s_sym *module)
 {
   s_tag *tag;
@@ -1162,6 +1188,18 @@ s_tag * tag_str_1 (s_tag *tag, char *p_free, const char *p)
   return tag;
 }
 
+s_tag * tag_str_cat (s_tag *tag, const s_str *a, const s_str *b)
+{
+  s_tag tmp = {0};
+  assert(tag);
+  tag_clean(tag);
+  tmp.type = TAG_STR;
+  if (! str_init_cat(&tmp.data.str, a, b))
+    return NULL;
+  *tag = tmp;
+  return tag;
+}
+
 s_tag * tag_struct (s_tag *tag, const s_sym *module)
 {
   s_tag tmp = {0};
diff --git a/libc3/tag_init.h b/libc3/tag_init.h
index 0b97f9d..e4662af 100644
--- a/libc3/tag_init.h
+++ b/libc3/tag_init.h
@@ -41,6 +41,7 @@ s_tag * tag_init_s32 (s_tag *tag, s32 i);
 s_tag * tag_init_s64 (s_tag *tag, s64 i);
 s_tag * tag_init_str (s_tag *tag, char *p_free, uw size, const char *p);
 s_tag * tag_init_str_1 (s_tag *tag, char *p_free, const char *p);
+s_tag * tag_init_str_cat (s_tag *tag, const s_str *a, const s_str *b);
 s_tag * tag_init_struct (s_tag *tag, const s_sym *module);
 s_tag * tag_init_struct_with_data (s_tag *tag, const s_sym *module, 
                                    bool free_data, void *data);
@@ -83,6 +84,7 @@ s_tag * tag_new_s32 (s32 i);
 s_tag * tag_new_s64 (s64 i);
 s_tag * tag_new_str (char *p_free, uw size, const char *p);
 s_tag * tag_new_str_1 (char *p_free, const char *p);
+s_tag * tag_new_str_cat (const s_str *a, const s_str *b);
 s_tag * tag_new_struct (const s_sym *module);
 s_tag * tag_new_struct_with_data (const s_sym *module, bool free_data, 
                                   void *data);
@@ -125,6 +127,7 @@ s_tag * tag_s32 (s_tag *tag, s32 i);
 s_tag * tag_s64 (s_tag *tag, s64 i);
 s_tag * tag_str (s_tag *tag, char *p_free, uw size, const char *p);
 s_tag * tag_str_1 (s_tag *tag, char *p_free, const char *p);
+s_tag * tag_str_cat (s_tag *tag, const s_str *a, const s_str *b);
 s_tag * tag_struct (s_tag *tag, const s_sym *module);
 s_tag * tag_struct_with_data (s_tag *tag, const s_sym *module, 
                               bool free_data, void *data);
diff --git a/libc3/tag_init.rb b/libc3/tag_init.rb
index 8aa0200..a37224c 100644
--- a/libc3/tag_init.rb
+++ b/libc3/tag_init.rb
@@ -353,6 +353,9 @@ class TagInitList
        TagInit.new("str", "1", "TAG_STR", :init_mode_init,
                    [Arg.new("char *", "p_free"),
                     Arg.new("const char *", "p")]),
+       TagInit.new("str", "cat", "TAG_STR", :init_mode_init,
+                   [Arg.new("const s_str *", "a"),
+                    Arg.new("const s_str *", "b")]),
        TagInit.new("struct", "TAG_STRUCT", :init_mode_init,
                    [Arg.new("const s_sym *", "module")]),
        TagInit.new("struct", "with_data", "TAG_STRUCT", :init_mode_init,