void prb_memset(void *dest, i32 fill, u64 n) { u8 *byte = dest; while (n--) *byte++ = fill; } void prb_memmove(void *dest, const void *src, u64 size) { u8 *byte_dest = dest; const u8 *byte_src = src; while (size--) *byte_dest++ = *byte_src++; } i32 prb_memeq(const void *p1, const void *p2, u64 size) { const u8 *byte_p1 = p1; const u8 *byte_p2 = p2; while (size--) if (*byte_p1++ != *byte_p2++) return 0; return 1; } i32 streq(const char *str1, const char *str2) { if (!str1 || !str2) return 0; while (*str1++ == *str2++) if (!*str1) return 1; return 0; } // fixed length strings #define str8lit(str) (str8_t){(u8 *)(str), sizeof(str) - 1} #define str8exp(str) (i32)((str).len), ((str).ptr) #define MAX_FLS_BUFFER 1024 typedef struct { u8 *ptr; u64 len; } str8_t; typedef struct str8_node_t { str8_t str; struct str8_node_t *next; struct str8_node_t *prev; } str8_node_t; typedef struct { struct str8_node_t *first; struct str8_node_t *last; u64 len; i32 cnt; } str8_list_t; char *str8_to_cstr(arena_t *arena, str8_t str) { u64 len = str.len + 1; char *cstr = push_arena(arena, len); prb_memmove(cstr, str.ptr, len); cstr[str.len] = 0; return cstr; } i32 str8eq(str8_t str1, str8_t str2) { if (str1.len != str2.len) return 0; for (u64 i = 0; i < str1.len; ++i) if (str1.ptr[i] != str2.ptr[i]) return 0; return 1; } u8 *str8ch(str8_t str, i32 c) { for (u64 i = 0; i < str.len; ++i) if (str.ptr[i] == c) return str.ptr + i; return 0; } u8 *str8rch(str8_t str, i32 c) { for (u64 i = str.len - 1; i > 0; --i) if (str.ptr[i] == c) return str.ptr + i; return 0; } str8_t str8_range(u8 *start, u8 *end) { assert(start); assert(end); assert(start < end); str8_t result = {start, end - start}; return result; } str8_t str8_getdir(str8_t str) { assert(str.len); u8 *slash = str8rch(str, '/'); if (!slash) return str; str8_t result = str8_range(str.ptr, slash); return result; } str8_t str8_pushfv(arena_t *arena, const char *format, va_list args) { char tmp[MAX_FLS_BUFFER]; i32 n = vsnprintf(tmp, MAX_FLS_BUFFER, format, args); str8_t str = {0}; if (n > 0) { u8 *ptr = push_arena(arena, n); prb_memmove(ptr, tmp, n); str = (str8_t){ptr, n}; str.ptr = ptr; str.len = n; } return str; } str8_t str8_pushf(arena_t *arena, const char *format, ...) { va_list args; va_start(args, format); str8_t str = str8_pushfv(arena, format, args); va_end(args); return str; } void str8_print(str8_t str) { assert(str.ptr); assert(str.len); printf("%.*s", str8exp(str)); } void str8_printf(const char *format, ...) { va_list args; va_start(args, format); arena_t temp = alloc_arena(MAX_FLS_BUFFER); str8_t str = str8_pushfv(&temp, format, args); va_end(args); str8_print(str); release_arena(&temp); } void str8_list_push(arena_t *arena, str8_list_t *list, i32 front, str8_t str) { str8_node_t *node = push_arena(arena, sizeof(str8_node_t)); node->str = str; if (front) dllpushfront(list->first, list->last, node); else dllpushback(list->first, list->last, node); list->len += str.len; list->cnt++; } void str8_list_pushf(arena_t *arena, str8_list_t *list, i32 front, const char *format, ...) { va_list args; va_start(args, format); str8_t str = str8_pushfv(arena, format, args); va_end(args); str8_list_push(arena, list, front, str); } /* TODO(pryazha): Check if that works :) */ str8_t str8_list_join(arena_t *arena, str8_list_t *list) { assert(arena); assert(list); str8_t str = {arena->memory + arena->used, 0}; for (str8_node_t *node = list->first; node; node = node->next) { u8 *ptr = push_arena(arena, node->str.len); prb_memmove(ptr, node->str.ptr, node->str.len); str.len += node->str.len; } return str; } void str8_list_print(str8_list_t *list) { for (str8_node_t *node = list->first; node; node = node->next) str8_print(node->str); }