#include "dstr.h" #include "aliases.h" #include "mem_arena.h" #include "platform.h" #include #include #include // Use this scalar to allocate extra memory in order to avoid having to // constantly reallocate #define CAPACITY_SCALAR 8 #define MINIMUM_DSTR_CAPACITY 1024 struct dstr { u64 capacity; u64 size; #ifdef WAPP_PLATFORM_WINDOWS char *buf; #else char buf[]; #endif // WAPP_PLATFORM_WINDOWS }; String *wapp_dstr_with_capacity(u64 capacity, Arena *arena) { if (!arena) { return NULL; } String *out = (String *)wapp_mem_arena_alloc(arena, sizeof(String) + capacity + 1); if (!out) { return NULL; } out->capacity = capacity; out->size = 0; return out; } String *wapp_dstr_from_string(const char *str, Arena *arena) { if (!str || !arena) { return NULL; } u64 length = strlen(str); u64 capacity = length * CAPACITY_SCALAR; capacity = capacity >= MINIMUM_DSTR_CAPACITY ? capacity : MINIMUM_DSTR_CAPACITY; String *out = wapp_dstr_with_capacity(capacity, arena); if (!out) { return NULL; } out->size = length; strncpy(out->buf, str, length + 1); return out; } StringUpdate wapp_dstr_update(String **dst, const char *src, Arena *arena) { if (!dst || !(*dst)) { return (StringUpdate){.updated = false, .str = *dst}; } u64 length = strlen(src); String *str = *dst; if (length >= str->capacity) { if (!arena) { return (StringUpdate){.updated = false, .str = *dst}; } String *new_str = wapp_dstr_from_string(src, arena); if (!new_str) { return (StringUpdate){.updated = false, .str = *dst}; } return (StringUpdate){.updated = true, .str = new_str}; } memset(str->buf, 0, str->capacity); str->size = length; strncpy(str->buf, src, length + 1); return (StringUpdate){.updated = true, .str = *dst}; } StringUpdate wapp_dstr_concat(String **dst, const char *src, Arena *arena) { if (!dst || !(*dst)) { return (StringUpdate){.updated = false, .str = *dst}; } u64 src_length = strlen(src); if (src_length == 0) { return (StringUpdate){.updated = false, .str = *dst}; } u64 new_length = (*dst)->size + src_length; #ifdef WAPP_PLATFORM_WINDOWS char *str = wapp_mem_util_alloc(NULL, new_length + 1, WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, WAPP_MEM_INIT_INITIALISED); if (!str) { return (StringUpdate){.updated = false, .str = *dst}; } #else char str[new_length + 1]; memset(str, 0, new_length + 1); #endif /* ifdef WAPP_PLATFORM_WINDOWS */ strncpy(str, (*dst)->buf, (*dst)->size); strncat(str, src, new_length + 1 - (*dst)->size); return wapp_dstr_update(dst, str, arena); } void wapp_dstr_clear(String *str) { if (!str || str->size == 0) { return; } memset(str->buf, 0, str->capacity); str->size = 0; } void wapp_dstr_print(const String *str) { if (!str) { return; } printf("%.*s\n", (i32)str->size, str->buf); } i64 wapp_dstr_find(const String *str, const char *substr) { if (!str || !substr) { return -1; } u64 substr_length = strlen(substr); if (substr_length == 0 || substr_length > str->size) { return -1; } const char *s1; for (u64 i = 0; i < str->size; ++i) { if (i + substr_length > str->size) { break; } s1 = &(str->buf[i]); if (strncmp(s1, substr, substr_length) == 0) { return i; } } return -1; } u64 wapp_dstr_length(const String *str) { if (!str) { return 0; } return str->size; } u64 wapp_dstr_capacity(const String *str) { if (!str) { return 0; } return str->capacity; } const char *wapp_dstr_to_cstr(const String *str) { if (!str) { return ""; } return str->buf; }