diff options
| author | nasr <nsrddyn@gmail.com> | 2026-10-05 22:02:56 +0200 |
|---|---|---|
| committer | nasr <nsrddyn@gmail.com> | 2026-10-05 22:02:56 +0200 |
| commit | f6d3090f7fa76eb8e0dbe060b8490cb49c001c39 (patch) | |
| tree | 433c773997e51f22738acb8b04c4fd2fc6b1bdc9 /source/base/base_string.h | |
init: base
Diffstat (limited to 'source/base/base_string.h')
| -rw-r--r-- | source/base/base_string.h | 240 |
1 files changed, 240 insertions, 0 deletions
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 @@ | |||
| 1 | #ifndef BASE_STRING_H | ||
| 2 | #define BASE_STRING_H | ||
| 3 | |||
| 4 | //- cstring | ||
| 5 | |||
| 6 | typedef char *cstring; | ||
| 7 | |||
| 8 | // - str8 | ||
| 9 | typedef struct String8 String8; | ||
| 10 | typedef struct String16 String16; | ||
| 11 | typedef struct String32 String32; | ||
| 12 | |||
| 13 | typedef struct String8Node String8Node; | ||
| 14 | typedef struct String16Node String16Node; | ||
| 15 | typedef struct String32Node String32Node; | ||
| 16 | |||
| 17 | typedef struct String8List String8List; | ||
| 18 | typedef struct String16List String16List; | ||
| 19 | typedef struct String32List String32List; | ||
| 20 | |||
| 21 | //- strings | ||
| 22 | |||
| 23 | struct String8 { | ||
| 24 | u8 *data; | ||
| 25 | u64 size; | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct String16 { | ||
| 29 | u16 *data; | ||
| 30 | u64 size; | ||
| 31 | }; | ||
| 32 | |||
| 33 | struct String32 { | ||
| 34 | u32 *data; | ||
| 35 | u64 size; | ||
| 36 | }; | ||
| 37 | |||
| 38 | //- nodes | ||
| 39 | struct String8Node { | ||
| 40 | String8Node *next; | ||
| 41 | String8 value; | ||
| 42 | }; | ||
| 43 | |||
| 44 | struct String16Node { | ||
| 45 | String16Node *next; | ||
| 46 | String16 string; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct String32Node { | ||
| 50 | String32Node *next; | ||
| 51 | String32 value; | ||
| 52 | }; | ||
| 53 | |||
| 54 | //- lists | ||
| 55 | struct String8List { | ||
| 56 | String8Node *first; | ||
| 57 | String8Node *last; | ||
| 58 | u64 count; | ||
| 59 | }; | ||
| 60 | |||
| 61 | struct String16List { | ||
| 62 | String16Node *first; | ||
| 63 | String16Node *last; | ||
| 64 | u64 count; | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct String32List { | ||
| 68 | String32Node *first; | ||
| 69 | String32Node *last; | ||
| 70 | u64 count; | ||
| 71 | }; | ||
| 72 | |||
| 73 | //- nil / zero-value checks and constructors | ||
| 74 | internal b32 is_nil_str8(String8 *a); | ||
| 75 | internal b32 is_nil_str8_node(String8Node *a); | ||
| 76 | internal b32 is_nil_str16(String16 *a); | ||
| 77 | internal b32 is_nil_str16_node(String16Node *a); | ||
| 78 | internal b32 is_nil_str32(String32 *a); | ||
| 79 | internal b32 is_nil_str32_node(String32Node *a); | ||
| 80 | internal String8 str8_zero(); | ||
| 81 | |||
| 82 | //- str8 copy / clone / append | ||
| 83 | internal String8 str8_clone(MemArena *arena, String8 *src); | ||
| 84 | internal void str8_copy(String8 *dest, String8 *src); | ||
| 85 | internal b32 str8_append(String8 *dest, String8 src); | ||
| 86 | internal b32 str8_append_char(String8 *dest, u8 src); | ||
| 87 | internal b32 str8_insert(MemArena *arena, String8 *dest, String8 *src, u64 pos); | ||
| 88 | |||
| 89 | //- str8 trim / chop | ||
| 90 | internal void str8_trim_left(String8 *buffer); | ||
| 91 | internal void str8_trim_right(String8 *buffer); | ||
| 92 | internal String8 str8_chop_left(String8 buffer, u64 count); | ||
| 93 | internal String8 str8_chop_right(String8 buffer, u64 count); | ||
| 94 | internal b32 str8_chop_left_ptr(String8 *buffer, u64 count); | ||
| 95 | internal b32 str8_chop_right_ptr(String8 *buffer, u64 count); | ||
| 96 | |||
| 97 | //- str8 substrings, matching, search | ||
| 98 | internal String8 str8_create_substr(String8 *buffer, u64 left_offset, u64 right_offset); | ||
| 99 | internal b32 str8_is_match(String8 a, String8 b); | ||
| 100 | internal b32 str8_find(String8 *buffer, u64 start_pos, String8 element, u64 *out); | ||
| 101 | internal b32 str8_is_digit(String8 a, u64 start_pos); | ||
| 102 | internal b32 str8_is_empty(String8 *buffer); | ||
| 103 | |||
| 104 | //- str8 list | ||
| 105 | internal void str8_list_push_node(String8List *list, String8Node *node); | ||
| 106 | |||
| 107 | //- str16 / str32 chop and substrings | ||
| 108 | internal String16 str16_chop_left(String16 buffer, u64 count); | ||
| 109 | internal String16 str16_chop_right(String16 buffer, u64 count); | ||
| 110 | internal String16 str16_create_substr(String16 *buffer, u64 left_offset, u64 right_offset); | ||
| 111 | internal String32 str32_chop_left(String32 buffer, u64 count); | ||
| 112 | internal String32 str32_chop_right(String32 buffer, u64 count); | ||
| 113 | internal String32 str32_create_substr(String32 *buffer, u64 left_offset, u64 right_offset); | ||
| 114 | |||
| 115 | //- null-termination helpers | ||
| 116 | internal cstring null_terminate(MemArena *arena, String8 *c); | ||
| 117 | internal String8 remove_null_terminator(MemArena *arena, String8 c); | ||
| 118 | |||
| 119 | //- convert | ||
| 120 | |||
| 121 | internal cstring str8_to_cstring(String8 *buffer); | ||
| 122 | |||
| 123 | //- cstring character classification | ||
| 124 | internal b32 cstring_is_digit(u8 point); | ||
| 125 | internal b32 cstring_is_alpha(u8 point); | ||
| 126 | internal b32 cstring_is_alpha_num(u8 point); | ||
| 127 | internal b32 cstring_is_whitespace(u8 point); | ||
| 128 | internal b32 cstring_is_slash(u8 point); | ||
| 129 | internal b32 cstring_is_newline(u8 point); | ||
| 130 | |||
| 131 | #define CstringIsMatch(a, b) cstring_is_match((u8 *)(a), (u8 *)(b)) | ||
| 132 | #define CstringAnyMatch(a, b) cstring_any_match((u8 *)(a), (u8 *)(b)) | ||
| 133 | |||
| 134 | |||
| 135 | //- cstring matching, length, search | ||
| 136 | internal b32 cstring_is_match(u8 *a, u8 *b); | ||
| 137 | internal b32 cstring_any_match(u8 *a, u8 *b); | ||
| 138 | internal u64 cstring8_length(u8 *c); | ||
| 139 | internal u64 cstring16_length(u16 *c); | ||
| 140 | internal u64 cstring32_length(u32 *c); | ||
| 141 | internal u64 cstring8_find(u8 *buffer, u8 *element); | ||
| 142 | internal u64 cstring8_find_new_line(u8 *buffer); | ||
| 143 | internal u64 cstring8_find_needle(u8 *buffer, u8 needle); | ||
| 144 | |||
| 145 | //- | ||
| 146 | |||
| 147 | #if COMPILER_GCC | ||
| 148 | #pragma GCC diagnostic push | ||
| 149 | #pragma GCC diagnostic ignored "-Wconversion" | ||
| 150 | #endif | ||
| 151 | |||
| 152 | //- | ||
| 153 | ReadOnly global_variable String8 nil_str8 = {NULL, 0}; | ||
| 154 | ReadOnly global_variable String16 nil_str16 = {NULL, 0}; | ||
| 155 | ReadOnly global_variable String32 nil_str32 = {NULL, 0}; | ||
| 156 | |||
| 157 | ReadOnly global_variable String8Node nil_str8_node = {NULL, {}}; | ||
| 158 | ReadOnly global_variable String16Node nil_str16_node = {NULL, {}}; | ||
| 159 | ReadOnly global_variable String32Node nil_str32_node = {NULL, {}}; | ||
| 160 | ReadOnly global_variable String8List nil_str8_list = {NULL, {}}; | ||
| 161 | ReadOnly global_variable String16List nil_str16_list = {NULL, {}}; | ||
| 162 | ReadOnly global_variable String32List nil_str32_list = {NULL, {}}; | ||
| 163 | |||
| 164 | //- macros | ||
| 165 | #define PushString8(arena, count) {(u8 *)(PushArrayZero(arena, u8, (count))), (u64)(count)} | ||
| 166 | #define PushString16(arena, count) {(u16 *)(PushArrayZero(arena, u16, (count))), (u64)(count)} | ||
| 167 | #define PushString32(arena, count) {(u32 *)(PushArrayZero(arena, u32, (count))), (u64)(count)} | ||
| 168 | |||
| 169 | // TODO: is this null terminated? this is generally a concept i struggle with. when is the string | ||
| 170 | // null terminated and when not. because in thi case I am the one passing a string "/" or something | ||
| 171 | // like that. is that null terminated or not? | ||
| 172 | #define ToString8(data) \ | ||
| 173 | String8 { (u8 *)(data), (u64)(cstring8_length((u8 *)data)) } | ||
| 174 | #define ToString16(data) \ | ||
| 175 | String16 { (u16 *)(data), (u64)(cstring16_length((u16 *)data)) } | ||
| 176 | #define ToString32(data) \ | ||
| 177 | String32 { (u32 *)(data), (u64)(cstring32_length((u32 *)data)) } | ||
| 178 | |||
| 179 | #define str8(buffer) ToString8(buffer) | ||
| 180 | #define str16(buffer) ToString16(buffer) | ||
| 181 | #define str32(buffer) ToString32(buffer) | ||
| 182 | |||
| 183 | #define ToString8Size(data, size) \ | ||
| 184 | String8 { (u8 *)(data), (u64)(size) } | ||
| 185 | #define ToString16Size(data, size) \ | ||
| 186 | String16 { (u16 *)(data), (u64)(size) } | ||
| 187 | #define ToString32Size(data, size) \ | ||
| 188 | String32 { (u32 *)(data), (u64)(size) } | ||
| 189 | |||
| 190 | #define ToString8Node(string) \ | ||
| 191 | String8Node { &nil_str8_node, string } | ||
| 192 | #define ToString16Node(string) \ | ||
| 193 | String16Node { &nil_str8_node, string } | ||
| 194 | #define ToString32Node(string) \ | ||
| 195 | String32Node { &nil_str8_node, string } | ||
| 196 | |||
| 197 | #define str8_node(text) ToString8Node(str8(text)) | ||
| 198 | #define str16_node(text) ToString16Node(str16(text)) | ||
| 199 | #define str32_node(text) ToString32Node(str32(text)) | ||
| 200 | |||
| 201 | #define LOOP(expr, exec) for (; expr; exec) | ||
| 202 | |||
| 203 | // arbitratry amount of parameters can be passed to this function | ||
| 204 | // TODO: put the index name as a paramter so that the reference can be made later without it being | ||
| 205 | // so hidden | ||
| 206 | |||
| 207 | #define FOR_STR8_CHOP_LEFT(index, buffer, count) FOR_STR8_CHOP(index, buffer, count, str8_chop_left) | ||
| 208 | |||
| 209 | #define FOR_STR8_CHOP_RIGHT(index, buffer, count) \ | ||
| 210 | FOR_STR8_CHOP(index, buffer, count, str8_chop_right) | ||
| 211 | |||
| 212 | // NOTE: we face an issue with returning an rvalue. to solve this we should only use the pointer | ||
| 213 | // functions that we create (str8_chop_left_ptr and str8_chop_right_ptr) | ||
| 214 | #define FOR_STR8_CHOP(index, buffer, count, function) \ | ||
| 215 | for (u64 index = 0; (index < (buffer.size)) && ((buffer.size) > (count)); \ | ||
| 216 | function((buffer), (count)), ++index) | ||
| 217 | |||
| 218 | #define FOR_STR8_ARB_FN(expr, function, ...) LOOP(expr, function(__VA_ARGS__)) | ||
| 219 | |||
| 220 | #define FOR_STR8_MATCH(buffa, buffb) LOOP(str8_is_match(buffa, buffb), str8_chop_left(buffa, 1)) | ||
| 221 | |||
| 222 | #define FOR_STR8_NODE(str8_list, current) \ | ||
| 223 | for (String8Node *current = str8_list->first; !is_nil_str8_node(current); \ | ||
| 224 | current = current->next) | ||
| 225 | |||
| 226 | internal b32 is_nil_str8(String8 *a); | ||
| 227 | internal b32 is_nil_str8_node(String8Node *a); | ||
| 228 | internal b32 is_nil_str16(String16 *a); | ||
| 229 | internal b32 is_nil_str16_node(String16Node *a); | ||
| 230 | internal b32 is_nil_str32(String32 *a); | ||
| 231 | internal b32 is_nil_str32_node(String32Node *a); | ||
| 232 | |||
| 233 | #if COMPILER_GCC | ||
| 234 | #pragma GCC diagnostic pop | ||
| 235 | #endif | ||
| 236 | |||
| 237 | #define Str8Fmt "%.*s" | ||
| 238 | #define Str8Arg(buffer) (unsigned int)((buffer).size), (char *)((buffer).data) | ||
| 239 | |||
| 240 | #endif /* BASE_STRING_H */ | ||
