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,