#include "String.h" #include "GlobalArena.h" #include "Types.h" #include #include #include 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; }