#include "String.h" #include "Types.h" #include #include struct StringMeta { MemoryManager *mm; usize length; }; static inline struct StringMeta* S_metadata(String s) { return (struct StringMeta*)(s - sizeof(struct StringMeta)); } static inline void* S_start(MemoryManager *mm, usize length) { if (NULL == mm) return NULL; struct StringMeta sm = { .mm = mm, .length = length, }; void* start = NULL; if (R_Ok != mm->alloc(*mm, &start, sizeof(sm) + sm.length + 1) || NULL == start) { return NULL; } memcpy(start, &sm, sizeof(sm)); return start + sizeof(sm); } String S_new(MemoryManager *mm, const char* str) { if (NULL == str) return NULL; usize strlength = strlen(str); void* start = S_start(mm, strlength); if (NULL != start) memcpy(start, str, strlength + 1); return start; } String S_newlen(MemoryManager *mm, usize length) { void* start = S_start(mm, length); if (NULL != start) memset(start, '\0', length + 1); return start; } static inline usize S_allocated(String s) { return sizeof(struct StringMeta) + S_length(s) + 1; } String S_dup(MemoryManager *mm, String s) { if (NULL == mm || NULL == s) return NULL; usize allocated = S_allocated(s); void* start = NULL; if (R_Ok != mm->alloc(*mm, &start, allocated) || NULL == start) { return NULL; } memcpy(start, s - sizeof(struct StringMeta), allocated); return start + sizeof(struct StringMeta); } String S_vconcat(MemoryManager *mm, va_list args) { if (NULL == mm) return NULL; 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); String result = S_newlen(mm, length); if (NULL == result) return NULL; 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 S_concat(MemoryManager *mm, ...) { va_list args; usize length = 0; va_start(args, mm); String result = S_vconcat(mm, args); va_end(args); return result; } String S_vprintf(MemoryManager *mm, const char* fmt, va_list args) { if (NULL == mm) return NULL; va_list temp; va_copy(temp, args); usize length = vsnprintf(NULL, 0, fmt, temp); va_end(temp); String result = S_newlen(mm, length); if (NULL == result) return NULL; vsnprintf(result, length + 1, fmt, args); return result; } String S_printf(MemoryManager *mm, const char* fmt, ...) { va_list args; va_start(args, fmt); String result = S_vprintf(mm, fmt, args); va_end(args); return result; } usize S_length(String s) { if (NULL == s) return 0; return S_metadata(s)->length; } static inline Result S_resize(String *s, usize length) { if (NULL == s || NULL == *s) return R_Uninitialized; struct StringMeta *sm = S_metadata(*s); void *start = sm; RETURN_NOTOK( sm->mm->realloc(*sm->mm, &start, S_allocated(*s) + length)); *s = start + sizeof(*sm); return R_Ok; } Result S_append(String *s, const char* str) { if (NULL == str) return R_Uninitialized; usize strlength = strlen(str); RETURN_NOTOK(S_resize(s, strlength)); strcat(*s, str); S_metadata(*s)->length += strlength; return R_Ok; } Result S_prepend(String *s, const char* str) { if (NULL == s) return R_Uninitialized; usize strlength = strlen(str); RETURN_NOTOK(S_resize(s, strlength)); struct StringMeta *sm = S_metadata(*s); for (usize i = sm->length; i > 0; --i) *s[i - 1 + strlength] = *s[i - 1]; for (usize i = 0; i < strlength; ++i) *s[i] = str[i]; sm->length += strlength; return R_Ok; } usize S_find(String s, char c) { if (NULL == s) return -1; unsigned index = 0; while (s[index] != '\0' && s[index] != c) ++index; return index; }