From f6d3090f7fa76eb8e0dbe060b8490cb49c001c39 Mon Sep 17 00:00:00 2001 From: nasr Date: Mon, 5 Oct 2026 22:02:56 +0200 Subject: init: base --- source/base/base_string.h | 240 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 source/base/base_string.h (limited to 'source/base/base_string.h') diff --git a/source/base/base_string.h b/source/base/base_string.h new file mode 100644 index 0000000..4fdd4d5 --- /dev/null +++ b/source/base/base_string.h @@ -0,0 +1,240 @@ +#ifndef BASE_STRING_H +#define BASE_STRING_H + +//- cstring + +typedef char *cstring; + +// - str8 +typedef struct String8 String8; +typedef struct String16 String16; +typedef struct String32 String32; + +typedef struct String8Node String8Node; +typedef struct String16Node String16Node; +typedef struct String32Node String32Node; + +typedef struct String8List String8List; +typedef struct String16List String16List; +typedef struct String32List String32List; + +//- strings + +struct String8 { + u8 *data; + u64 size; +}; + +struct String16 { + u16 *data; + u64 size; +}; + +struct String32 { + u32 *data; + u64 size; +}; + +//- nodes +struct String8Node { + String8Node *next; + String8 value; +}; + +struct String16Node { + String16Node *next; + String16 string; +}; + +struct String32Node { + String32Node *next; + String32 value; +}; + +//- lists +struct String8List { + String8Node *first; + String8Node *last; + u64 count; +}; + +struct String16List { + String16Node *first; + String16Node *last; + u64 count; +}; + +struct String32List { + String32Node *first; + String32Node *last; + u64 count; +}; + +//- nil / zero-value checks and constructors +internal b32 is_nil_str8(String8 *a); +internal b32 is_nil_str8_node(String8Node *a); +internal b32 is_nil_str16(String16 *a); +internal b32 is_nil_str16_node(String16Node *a); +internal b32 is_nil_str32(String32 *a); +internal b32 is_nil_str32_node(String32Node *a); +internal String8 str8_zero(); + +//- str8 copy / clone / append +internal String8 str8_clone(MemArena *arena, String8 *src); +internal void str8_copy(String8 *dest, String8 *src); +internal b32 str8_append(String8 *dest, String8 src); +internal b32 str8_append_char(String8 *dest, u8 src); +internal b32 str8_insert(MemArena *arena, String8 *dest, String8 *src, u64 pos); + +//- str8 trim / chop +internal void str8_trim_left(String8 *buffer); +internal void str8_trim_right(String8 *buffer); +internal String8 str8_chop_left(String8 buffer, u64 count); +internal String8 str8_chop_right(String8 buffer, u64 count); +internal b32 str8_chop_left_ptr(String8 *buffer, u64 count); +internal b32 str8_chop_right_ptr(String8 *buffer, u64 count); + +//- str8 substrings, matching, search +internal String8 str8_create_substr(String8 *buffer, u64 left_offset, u64 right_offset); +internal b32 str8_is_match(String8 a, String8 b); +internal b32 str8_find(String8 *buffer, u64 start_pos, String8 element, u64 *out); +internal b32 str8_is_digit(String8 a, u64 start_pos); +internal b32 str8_is_empty(String8 *buffer); + +//- str8 list +internal void str8_list_push_node(String8List *list, String8Node *node); + +//- str16 / str32 chop and substrings +internal String16 str16_chop_left(String16 buffer, u64 count); +internal String16 str16_chop_right(String16 buffer, u64 count); +internal String16 str16_create_substr(String16 *buffer, u64 left_offset, u64 right_offset); +internal String32 str32_chop_left(String32 buffer, u64 count); +internal String32 str32_chop_right(String32 buffer, u64 count); +internal String32 str32_create_substr(String32 *buffer, u64 left_offset, u64 right_offset); + +//- null-termination helpers +internal cstring null_terminate(MemArena *arena, String8 *c); +internal String8 remove_null_terminator(MemArena *arena, String8 c); + +//- convert + +internal cstring str8_to_cstring(String8 *buffer); + +//- cstring character classification +internal b32 cstring_is_digit(u8 point); +internal b32 cstring_is_alpha(u8 point); +internal b32 cstring_is_alpha_num(u8 point); +internal b32 cstring_is_whitespace(u8 point); +internal b32 cstring_is_slash(u8 point); +internal b32 cstring_is_newline(u8 point); + +#define CstringIsMatch(a, b) cstring_is_match((u8 *)(a), (u8 *)(b)) +#define CstringAnyMatch(a, b) cstring_any_match((u8 *)(a), (u8 *)(b)) + + +//- cstring matching, length, search +internal b32 cstring_is_match(u8 *a, u8 *b); +internal b32 cstring_any_match(u8 *a, u8 *b); +internal u64 cstring8_length(u8 *c); +internal u64 cstring16_length(u16 *c); +internal u64 cstring32_length(u32 *c); +internal u64 cstring8_find(u8 *buffer, u8 *element); +internal u64 cstring8_find_new_line(u8 *buffer); +internal u64 cstring8_find_needle(u8 *buffer, u8 needle); + +//- + +#if COMPILER_GCC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + +//- +ReadOnly global_variable String8 nil_str8 = {NULL, 0}; +ReadOnly global_variable String16 nil_str16 = {NULL, 0}; +ReadOnly global_variable String32 nil_str32 = {NULL, 0}; + +ReadOnly global_variable String8Node nil_str8_node = {NULL, {}}; +ReadOnly global_variable String16Node nil_str16_node = {NULL, {}}; +ReadOnly global_variable String32Node nil_str32_node = {NULL, {}}; +ReadOnly global_variable String8List nil_str8_list = {NULL, {}}; +ReadOnly global_variable String16List nil_str16_list = {NULL, {}}; +ReadOnly global_variable String32List nil_str32_list = {NULL, {}}; + +//- macros +#define PushString8(arena, count) {(u8 *)(PushArrayZero(arena, u8, (count))), (u64)(count)} +#define PushString16(arena, count) {(u16 *)(PushArrayZero(arena, u16, (count))), (u64)(count)} +#define PushString32(arena, count) {(u32 *)(PushArrayZero(arena, u32, (count))), (u64)(count)} + +// TODO: is this null terminated? this is generally a concept i struggle with. when is the string +// null terminated and when not. because in thi case I am the one passing a string "/" or something +// like that. is that null terminated or not? +#define ToString8(data) \ + String8 { (u8 *)(data), (u64)(cstring8_length((u8 *)data)) } +#define ToString16(data) \ + String16 { (u16 *)(data), (u64)(cstring16_length((u16 *)data)) } +#define ToString32(data) \ + String32 { (u32 *)(data), (u64)(cstring32_length((u32 *)data)) } + +#define str8(buffer) ToString8(buffer) +#define str16(buffer) ToString16(buffer) +#define str32(buffer) ToString32(buffer) + +#define ToString8Size(data, size) \ + String8 { (u8 *)(data), (u64)(size) } +#define ToString16Size(data, size) \ + String16 { (u16 *)(data), (u64)(size) } +#define ToString32Size(data, size) \ + String32 { (u32 *)(data), (u64)(size) } + +#define ToString8Node(string) \ + String8Node { &nil_str8_node, string } +#define ToString16Node(string) \ + String16Node { &nil_str8_node, string } +#define ToString32Node(string) \ + String32Node { &nil_str8_node, string } + +#define str8_node(text) ToString8Node(str8(text)) +#define str16_node(text) ToString16Node(str16(text)) +#define str32_node(text) ToString32Node(str32(text)) + +#define LOOP(expr, exec) for (; expr; exec) + +// arbitratry amount of parameters can be passed to this function +// TODO: put the index name as a paramter so that the reference can be made later without it being +// so hidden + +#define FOR_STR8_CHOP_LEFT(index, buffer, count) FOR_STR8_CHOP(index, buffer, count, str8_chop_left) + +#define FOR_STR8_CHOP_RIGHT(index, buffer, count) \ + FOR_STR8_CHOP(index, buffer, count, str8_chop_right) + +// NOTE: we face an issue with returning an rvalue. to solve this we should only use the pointer +// functions that we create (str8_chop_left_ptr and str8_chop_right_ptr) +#define FOR_STR8_CHOP(index, buffer, count, function) \ + for (u64 index = 0; (index < (buffer.size)) && ((buffer.size) > (count)); \ + function((buffer), (count)), ++index) + +#define FOR_STR8_ARB_FN(expr, function, ...) LOOP(expr, function(__VA_ARGS__)) + +#define FOR_STR8_MATCH(buffa, buffb) LOOP(str8_is_match(buffa, buffb), str8_chop_left(buffa, 1)) + +#define FOR_STR8_NODE(str8_list, current) \ + for (String8Node *current = str8_list->first; !is_nil_str8_node(current); \ + current = current->next) + +internal b32 is_nil_str8(String8 *a); +internal b32 is_nil_str8_node(String8Node *a); +internal b32 is_nil_str16(String16 *a); +internal b32 is_nil_str16_node(String16Node *a); +internal b32 is_nil_str32(String32 *a); +internal b32 is_nil_str32_node(String32Node *a); + +#if COMPILER_GCC +#pragma GCC diagnostic pop +#endif + +#define Str8Fmt "%.*s" +#define Str8Arg(buffer) (unsigned int)((buffer).size), (char *)((buffer).data) + +#endif /* BASE_STRING_H */ -- cgit v1.3.1