diff --git a/src/base_core.h b/src/base_core.h index 4496069..4899410 100644 --- a/src/base_core.h +++ b/src/base_core.h @@ -252,6 +252,18 @@ typedef unsigned __int128 U128; #define MemAppend(dst, src, len) mempcpy(dst, src, len) #define MemCompare(first, second, len) memcmp(first, second, len) +static INLINE U8 *MemFind(U8 *mem, U64 mem_len, U8 *needle, U64 needle_len) +{ + if (needle_len > mem_len) { + return NULL; + } + for (U64 i = 0 ; i + needle_len <= mem_len; i++) { + if (MemCompare(&mem[i], needle, needle_len) == 0) { + return &mem[i]; + } + } + return NULL; +} // atomics #define Atomic(type) _Atomic(type) #define AtomicSub(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) diff --git a/src/main.c b/src/main.c index 863126a..63c6aa4 100644 --- a/src/main.c +++ b/src/main.c @@ -470,7 +470,35 @@ void string_test_misc(void) Str str4_trim = str_ascii_trim(str4); printf("str4_trim: '%.*s'\n", str4_trim.len, str4_trim.str); + S64 found = str_substr(str1, S("World")); + printf("1. found %ld\n", found); + found = str_substr(str_empty(), S("World")); + printf("2. found %ld\n", found); + found = str_substr(str_empty(), S("")); + printf("3. found %ld\n", found); + found = str_substr(str1, S(" ")); + printf("4. found %ld\n", found); + } +void string_test_join(void) +{ + TRACEF("\n"); + Arena arena; + arena_init(&arena, &ArenaOptions_Default); + Allocator allocator = arena_allocator(&arena); + Str strs[3] = {S("1"), S("two"), S("3-3")}; + StrVec vec = STRVEC_STATIC_INITIALIZER(strs); + + Str str = str_join(&allocator, vec, S("/")); + printf("str_join 1 '%.*s'\n", str.len, str.str); + str = str_join(&allocator, vec, S("")); + printf("str_join 2 '%.*s'\n", str.len, str.str); + vec.len = 0; + str = str_join(&allocator, vec, S("/")); + printf("str_join 2 '%.*s'\n", str.len, str.str); + +} + int main(int argc, char *argv[]) { arena_test_1(); @@ -486,6 +514,7 @@ int main(int argc, char *argv[]) string_test_1(); string_split_test_1(); string_test_misc(); + string_test_join(); } diff --git a/src/string.c b/src/string.c index 8e0ce2e..d8a88d4 100644 --- a/src/string.c +++ b/src/string.c @@ -32,9 +32,7 @@ Str str_concat(Allocator *alloc, Str first, Str second) Str str_push(Allocator *alloc, Str str) { U8 *mem = (U8 *)allocator_push(alloc, str.len, 1); - if (!str_is_empty(str)) { - MemCopy(mem, str.str, str.len); - } + MemCopy(mem, str.str, str.len); return str_create(mem, str.len); } @@ -80,8 +78,21 @@ Str str_ascii_trim(Str str) return new_str; } -S64 str_substr(Str haystack, Str to_find) +S64 str_substr(Str haystack, Str needle) { + if (needle.len == 0) { + return 0; + } + + if (needle.len == 0) { + return str_find_byte(haystack, needle.str[0]); + } + + U8 *found = MemFind(haystack.str, haystack.len, needle.str, needle.len); + if (found != NULL) { + return (S64)(found - haystack.str); + } + return -1; } @@ -112,3 +123,33 @@ void str_split(Str str, Str separators, StrVec *vec) vec->len++; } } + +Str str_join(Allocator *allocator, StrVec strings, Str separator) +{ + + U32 str_len = 0; + + for (U32 i = 0; i < strings.len; i++) { + str_len += strings.strings[i].len; + } + if (strings.len > 0) { + str_len += separator.len * (strings.len - 1); + } + + U8 *joined_str = allocator_push(allocator, str_len, 1); + if (strings.len > 0) { + U32 pos = 0; + Str *str = &strings.strings[0]; + MemCopy(&joined_str[pos], str->str, str->len); + pos += str->len; + for (U32 i = 1; i < strings.len; i++) { + str = &strings.strings[i]; + MemCopy(&joined_str[pos], separator.str, separator.len); + pos += separator.len; + MemCopy(&joined_str[pos], str->str, str->len); + pos += str->len; + } + } + + return str_create(joined_str, str_len); +} diff --git a/src/string.h b/src/string.h index 33592c9..f9bb00c 100644 --- a/src/string.h +++ b/src/string.h @@ -9,7 +9,7 @@ struct Str { Str str_empty(void); Str str_slice(Str str, U32 start, U32 len); -S64 str_substr(Str haystack, Str to_find); +S64 str_substr(Str haystack, Str needle); Str str_concat(Allocator *alloc, Str first, Str second); Str str_push(Allocator *alloc, Str str); @@ -99,12 +99,15 @@ struct StrVec { U32 len; U32 max_len; }; -#define STRVEC_STATIC_INITIALIZER(strings_) STRVEC_INITIALIZER((strings_), ArraySize(strings_)) -#define STRVEC_INITIALIZER(strings_, len_) {.strings = (strings_), .len = 0, .max_len = (len_)} +#define STRVEC_STATIC_INITIALIZER(strings_) STRVEC_INITIALIZER((strings_), ArraySize(strings_), ArraySize(strings_)) +#define STRVEC_STATIC_INITIALIZER_EMPTY(strings_) STRVEC_INITIALIZER((strings_), 0, ArraySize(strings_)) +#define STRVEC_INITIALIZER(strings_, len_, max_len_) {.strings = (strings_), .len = (len_), .max_len = (max_len_)} + #define STRVEC_DEFINE(var_name, len_) \ struct { \ Str strings[len_];\ } var_name##_strvec_array; \ - StrVec var_name = STRVEC_STATIC_INITIALIZER(var_name##_strvec_array.strings) + StrVec var_name = STRVEC_STATIC_INITIALIZER_EMPTY(var_name##_strvec_array.strings) void str_split(Str str, Str separators, StrVec *vec); +Str str_join(Allocator *allocator, StrVec strings, Str separator);