aboutsummaryrefslogtreecommitdiff
path: root/String.c
diff options
context:
space:
mode:
Diffstat (limited to 'String.c')
-rw-r--r--String.c230
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;
+}