diff options
Diffstat (limited to 'String.c')
| -rw-r--r-- | String.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/String.c b/String.c new file mode 100644 index 0000000..2467189 --- /dev/null +++ b/String.c @@ -0,0 +1,230 @@ +#include "String.h" +#include "GlobalArena.h" +#include "Types.h" +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +struct StringMeta { + BumpArena b; + usize length; +}; + +static inline struct StringMeta* +String_metadata(String s) { + return (struct StringMeta*)(s - sizeof(struct StringMeta)); +} + +String +String_new(BumpArena b, const char* str) { + if (NULL == b || NULL == str) + return NULL; + + struct StringMeta sm = { + .b = b, + .length = strlen(str), + }; + + void* start = Balloc(b, sizeof(sm) + sm.length + 1); + + memcpy(start, &sm, sizeof(sm)); + start += sizeof(sm); + memcpy(start, str, sm.length + 1); + + return start; +} + +String +String_newlen(BumpArena b, usize length) { + if (NULL == b) + return NULL; + + struct StringMeta sm = { + .b = b, + .length = length, + }; + + void* start = Balloc(b, sizeof(sm) + sm.length + 1); + + memcpy(start, &sm, sizeof(sm)); + start += sizeof(sm); + memset(start, '\0', sm.length + 1); + + return start; +} + +static inline usize +String_allocated(String s) { + return sizeof(struct StringMeta) + String_length(s) + 1; +} + +String +String_dup(BumpArena b, String s) { + if (NULL == b || NULL == s) + return NULL; + + usize allocated = String_allocated(s); + + void* start = Balloc(b, allocated); + memcpy(start, s - sizeof(struct StringMeta), allocated); + + return NULL; +} + +usize +String_length(String s) { + if (NULL == s) + return 0; + return String_metadata(s)->length; +} + +Result +String_append(String s, const char* str) { + if (NULL == s) + return R_Uninitialized; + + struct StringMeta* sm = String_metadata(s); + + usize strlength = strlen(str); + if (sm->length - strlen(s) < strlength) { + if (!Bresizeable(sm->b, s)) + return R_Err; + Bresize(sm->b, sizeof(*sm) + (sm->length += strlength) + 1); + } + + strcat(s, str); + return R_Ok; +} + +Result +String_prepend(String s, const char* str) { + if (NULL == s) + return R_Uninitialized; + + struct StringMeta* sm = String_metadata(s); + + usize strlength = strlen(str); + if (!Bresizeable(sm->b, s)) + return R_Err; + + usize orig_len = sm->length; + RETURN_NOTOK(Bresize(sm->b, sizeof(*sm) + (sm->length += strlength) + 1)); + + for (usize i = orig_len; i > 0; --i) + s[i - 1 + strlength] = s[i - 1]; + for (usize i = 0; i < strlength; ++i) + s[i] = str[i]; + + return R_Ok; +} + +usize +String_find(String s, char c) { + if (NULL == s) + return -1; + + unsigned index = 0; + while (s[index] != '\0' && s[index] != c) + ++index; + + return index; +} + +static String +String_vconcat(BumpArena b, va_list args) { + usize length = 0; + + va_list temp; + va_copy(temp, args); + for (const char* str = va_arg(temp, const char*); str != NULL; str = va_arg(temp, const char*)) { + length += strlen(str); + } + va_end(temp); + printf("%lu\n", length); + + String result = String_newlen(b, length); + + if (0 < length) { + for (const char* str = va_arg(args, const char*); str != NULL; str = va_arg(args, const char*)) + strncat(result, str, length); + } + return result; +} + +String +String_concat(BumpArena b, ...) { + va_list args; + usize length = 0; + + va_start(args, b); + String result = String_vconcat(b, args); + va_end(args); + + return result; +} + +static String +String_vprintf(BumpArena b, const char* fmt, va_list args) { + va_list temp; + va_copy(temp, args); + usize length = vsnprintf(NULL, 0, fmt, temp); + va_end(temp); + + String result = String_newlen(b, length); + vsnprintf(result, length, fmt, args); + + return result; +} + +String +String_printf(BumpArena b, const char* fmt, ...) { + va_list args; + + va_start(args, fmt); + String result = String_vprintf(b, fmt, args); + va_end(args); + + return result; +} + +String +String_Gnew(const char* str) { + return String_new(g_arena, str); +} + +String +String_Gnewlen(usize length) { + return String_newlen(g_arena, length); +} + +String +String_Gdup(String s) { + return String_dup(g_arena, s); +} + +String +String_Gconcat(const char* str, ...) { + if (str == NULL) + return NULL; + + va_list args; + + va_start(args, str); + String result = String_vconcat(g_arena, args); + va_end(args); + + String_prepend(result, str); + + return result; +} + +String +String_Gprintf(const char* fmt, ...) { + va_list args; + + va_start(args, fmt); + String result = String_vprintf(g_arena, fmt, args); + va_end(args); + + return result; +} |
