summaryrefslogtreecommitdiff
path: root/source/base/base_string.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/base/base_string.cpp')
-rw-r--r--source/base/base_string.cpp498
1 files changed, 498 insertions, 0 deletions
diff --git a/source/base/base_string.cpp b/source/base/base_string.cpp
new file mode 100644
index 0000000..5b006ff
--- /dev/null
+++ b/source/base/base_string.cpp
@@ -0,0 +1,498 @@
1internal b32 is_nil_str8(String8 *a) { return (a == &nil_str8); }
2
3internal b32 is_nil_str8_node(String8Node *a) { return (a == &nil_str8_node); }
4
5internal b32 is_nil_str16(String16 *a) { return (a == &nil_str16); }
6
7internal b32 is_nil_str16_node(String16Node *a) { return (a == &nil_str16_node); }
8
9internal b32 is_nil_str32(String32 *a) { return (a == &nil_str32); }
10
11internal b32 is_nil_str32_node(String32Node *a) { return (a == &nil_str32_node); }
12
13internal void str8_trim_left(String8 *buffer)
14{
15 u64 index = 0;
16 while (cstring_is_whitespace(buffer->data[index])) {
17 ++index;
18 }
19
20 str8_chop_left(*buffer, index);
21}
22
23internal void str16_trim_left(String16 *buffer)
24{
25 u64 index = 0;
26 while (cstring_is_whitespace(buffer->data[index])) {
27 ++index;
28 }
29
30 str16_chop_left(*buffer, index);
31}
32
33internal void str32_trim_left(String32 *buffer)
34{
35 u64 index = 0;
36
37 while (cstring_is_whitespace(buffer->data[index])) {
38 ++index;
39 }
40
41 str32_chop_left(*buffer, index);
42}
43
44internal void str8_trim_right(String8 *buffer)
45{
46 u64 index = buffer->size;
47 while (cstring_is_whitespace(buffer->data[index])) {
48 --index;
49 }
50
51 str8_chop_right(*buffer, index);
52}
53
54internal b32 str8_is_match(String8 a, String8 b)
55{
56 if (a.size != b.size) {
57 return false;
58 }
59
60 if(a.size == 0) { // no need to check if b.size is 0 because both sizes are already equal
61 return true;
62 }
63
64 return (b32)(memcmp(a.data, b.data, b.size) == 0);
65}
66
67internal b32 str8_find_all(MemArena *arena, String8 *buffer, u64 start_pos, String8 element, String8List *out)
68{
69 u64 count = 0; // checks if any we're found to pass that as a error handling mechanism
70 u64 found_pos = 0;
71
72 while (str8_find(buffer, start_pos, element, &found_pos)) {
73 String8Node *node = PushStruct(arena, String8Node);
74 *node = ToString8Node(str8_create_substr(buffer, found_pos, element.size));
75 str8_list_push_node(out, node);
76
77 ++count;
78 start_pos = found_pos + element.size;
79 }
80
81 if (!count)
82 return false;
83 return true;
84}
85
86// TODO: does this work like it should?
87internal b32 str8_find(String8 *buffer, u64 start_pos, String8 element, u64 *out)
88{
89 for (u64 index = start_pos; index < buffer->size - element.size; ++index) {
90 String8 view = str8_chop_left(*buffer, index);
91 view = str8_chop_right(view, view.size - element.size);
92 if (str8_is_match(view, element)) {
93 *out = index;
94 return true;
95 }
96 }
97
98 return false;
99}
100
101internal b32 str8_replace(String8 buffer, String8 element, u64 start_pos) {
102
103 u64 offset = 0;
104 b32 result = str8_find(&buffer, start_pos, element, &offset);
105 if(!result) return false;
106
107 for(u64 index = 0; index < element.size; ++index) {
108 buffer.data[start_pos + index] = element.data[index];
109 }
110
111 return true;
112}
113
114internal b32 str8_trim(String8 buffer) {
115
116 return str8_replace(buffer, str8("\n"), 0);
117}
118
119
120internal b32 str8_is_digit(String8 a, u64 start_pos)
121{
122 for (u64 index = start_pos; index < a.size; ++index) {
123 if (!cstring_is_digit(a.data[index]))
124 return false;
125 }
126
127 return true;
128}
129
130internal void str8_copy(String8 *dest, String8 *src)
131{
132 MemCpy(dest->data, src->data, src->size);
133 Assert(memcmp(dest->data, src->data, src->size) == 0);
134 dest->size = src->size;
135}
136
137internal String8 str8_clone(MemArena *arena, String8 *src)
138{
139 String8 clone = PushString8(arena, src->size);
140 str8_copy(&clone, src);
141 return clone;
142}
143
144// you cant just do this you have to reallocat that thing no?
145internal b32 str8_append_char(String8 *dest, u8 src)
146{
147 if (is_nil_str8(dest) || src == 0)
148 return false;
149 dest->data[dest->size] = src;
150 dest->size += 1;
151 return true;
152}
153
154internal int str8_to_int(String8 *buffer)
155{
156
157 int result = 0;
158
159 for (u64 index = 0; index < buffer->size; ++index) {
160
161 if (buffer->data[index] < 'Z' && buffer->data[index] > 'A') {
162 result = buffer->data[index] - '0';
163 result *= 10;
164 }
165 }
166 return result;
167}
168
169internal b32 str8_append(String8 *dest, String8 src)
170{
171 if (is_nil_str8(dest) || is_nil_str8(&src))
172 return false;
173 MemCpy(dest->data + dest->size, src.data, src.size);
174 dest->size += src.size;
175 return true;
176}
177
178internal String8 str8_zero() { return String8{0}; }
179
180// TODO: error handling
181internal b32 str8_chop_left_ptr(String8 *buffer, u64 count)
182{
183 if (buffer->size < count) return false;
184
185 buffer->data += count;
186 buffer->size -= count;
187 return true;
188
189
190}
191
192internal b32 str8_chop_right_ptr(String8 *buffer, u64 count)
193{
194 if (buffer->size < count) return false;
195
196 buffer->size -= count;
197 return true;
198}
199
200internal String8 str8_chop_left(String8 buffer, u64 count)
201{
202 if (buffer.size < count) {
203 return buffer;
204 }
205
206 buffer.data += count;
207 buffer.size -= count;
208
209 return buffer;
210}
211
212internal String8 str8_chop_right(String8 buffer, u64 count)
213{
214 if (buffer.size < count) {
215 return buffer;
216 }
217
218 buffer.size -= count;
219 return buffer;
220}
221
222internal void str8_list_push_node(String8List *list, String8Node *node)
223{
224 if (list) {
225 if (list->first == NULL) {
226 list->first = node;
227 list->last = node;
228 } else {
229 list->last->next = node;
230 list->last = node;
231 }
232 list->count += 1;
233 }
234}
235
236internal String8 str8_create_substr(String8 *buffer, u64 left_offset, u64 right_offset)
237{
238 return str8_chop_right(str8_chop_left(*buffer, left_offset),
239 (buffer->size - left_offset) -
240 right_offset); // we need to remove all of the excess data to only
241 // retain the substring we want
242}
243
244internal String16 str16_create_substr(String16 *buffer, u64 left_offset, u64 right_offset)
245{
246 return str16_chop_right(str16_chop_left(*buffer, left_offset),
247 (buffer->size - left_offset) - right_offset);
248}
249
250internal String32 str32_create_substr(String32 *buffer, u64 left_offset, u64 right_offset)
251{
252 return str32_chop_right(str32_chop_left(*buffer, left_offset),
253 (buffer->size - left_offset) - right_offset);
254}
255
256internal String16 str16_chop_left(String16 buffer, u64 count)
257{
258 if (buffer.size < count) {
259 return buffer;
260 }
261
262 for (u64 idx = 0; idx < count; ++idx) {
263 buffer.data++;
264 }
265 return buffer;
266}
267
268internal String32 str32_chop_left(String32 buffer, u64 count)
269{
270 if (buffer.size < count) {
271 return buffer;
272 }
273
274 for (u64 idx = 0; idx < count; ++idx) {
275 buffer.data++;
276 }
277 return buffer;
278}
279
280internal String16 str16_chop_right(String16 buffer, u64 count)
281{
282 if (buffer.size < count) {
283 return buffer;
284 }
285
286 buffer.size -= count;
287 return buffer;
288}
289
290internal String32 str32_chop_right(String32 buffer, u64 count)
291{
292 if (buffer.size < count) {
293 return buffer;
294 }
295
296 buffer.size -= count;
297 return buffer;
298}
299
300internal b32 str8_prefix(MemArena *arena, String8 *buffer, String8 *prefix) {
301 b32 result = str8_insert(arena, buffer, prefix, 0);
302 return result;
303}
304
305internal b32 str8_starts_with(String8 buffer, String8 prefix) {
306
307 if(buffer.size < prefix.size) {
308 return false;
309 }
310
311 return str8_is_match(String8{buffer.data, prefix.size}, prefix);
312}
313
314internal b32 str8_is_empty(String8 *buffer)
315{
316 if (cstring8_length(buffer->data) == 0 || buffer->size == 0)
317 return true; // the values can't be lower than 0
318 return false;
319}
320
321internal b32 str8_insert(MemArena *arena, String8 *dest, String8 *src, u64 pos)
322{
323 if (dest->size < pos)
324 return false;
325
326 String8 result = PushString8(arena, dest->size + src->size);
327 result.size = 0;
328
329 String8 head = str8_create_substr(dest, 0, pos);
330 String8 tail = str8_create_substr(dest, pos, dest->size);
331
332 if (!str8_append(&result, head))
333 return false;
334 if (!str8_append(&result, *src))
335 return false;
336 if (!str8_append(&result, tail))
337 return false;
338
339 *dest = result;
340 return true;
341}
342
343internal cstring str8_to_cstring(MemArena *arena, String8 *buffer)
344{
345
346 cstring null_terminated_buffer = null_terminate(arena, buffer);
347 return (cstring)null_terminated_buffer;
348}
349
350//- cstring implementations
351
352internal b32 cstring_is_digit(u8 point) { return (point >= '0' && point <= '9'); }
353
354internal b32 cstring_is_alpha(u8 point)
355{
356 return ((point >= 'a' && point <= 'z') || (point >= 'A' && point <= 'Z') || (point == '_'));
357}
358
359internal b32 cstring_is_alpha_num(u8 point)
360{
361 return (cstring_is_alpha(point) || cstring_is_digit(point));
362}
363
364internal b32 cstring_is_whitespace(u8 point) { return (point == ' ' || point == '\t'); }
365
366internal b32 cstring_is_slash(u8 point) { return (point == '/' || point == '\\'); }
367
368internal b32 cstring_is_newline(u8 point) { return (point == '\n' || point == '\r'); }
369
370internal b32 cstring_is_match(u8 *a, u8 *b)
371{
372 u64 as = cstring8_length(a);
373 u64 bs = cstring8_length(b);
374
375 if (as != bs) {
376 return false;
377 }
378
379 for (u64 idx = 0; idx < as; ++idx) {
380 if (a[idx] != b[idx]) {
381 return false;
382 }
383 }
384 return true;
385}
386
387
388// NOTE: ignores the biggest buffer size
389internal b32 cstring_any_match(u8 *a, u8 *b)
390{
391
392
393
394 u64 lenght = cstring8_length(b);
395 for (u64 idx = 0; idx < lenght; ++idx) {
396 if (a[idx] != b[idx]) {
397 return false;
398 }
399 }
400 return true;
401}
402
403internal u64 cstring8_length(u8 *c)
404{
405 u8 *p = c;
406 if (!c)
407 return 0;
408 for (; *c != 0; ++c)
409 ;
410 return (u64)(c - p);
411}
412
413internal u64 cstring16_length(u16 *c)
414{
415 u16 *p = c;
416
417 if (!c)
418 return 0;
419 for (; *c != 0; ++c)
420 ;
421 return (u64)(p - c);
422}
423
424internal u64 cstring32_length(u32 *c)
425{
426
427 u32 *p = c;
428
429 if (!c)
430 return 0;
431 for (; *c != 0; ++c)
432 ;
433 return (u64)(p - c);
434}
435
436internal cstring null_terminate(MemArena *arena, String8 *buffer)
437{
438 char *text = (char *)arena_alloc(arena, buffer->size + 1, 0);
439 MemCpy(text, buffer->data, buffer->size);
440 text[buffer->size] = '\0';
441 return (cstring)text;
442}
443
444internal String8 remove_null_terminator(MemArena *arena, String8 c)
445{
446 Assert(arena);
447 if ((c.size > 0) && (c.data[c.size - 1] == '\0')) {
448 String8 chopped = {c.data, c.size - 1};
449 return chopped;
450 }
451
452 return c;
453}
454
455// returns the index of where to find it. if not found returns 0.
456internal u64 cstring8_find(u8 *buffer, u8 *element)
457{
458 u8 *c = buffer;
459 while (c != 0) {
460 if (!cstring_is_match(buffer, element)) {
461 return c - buffer;
462 } else {
463 ++c;
464 }
465 }
466
467 return 0;
468}
469
470// returns the index of where to find it. if not found returns 0.
471internal u64 cstring8_find_new_line(u8 *buffer)
472{
473 u8 *c = buffer;
474 while (*c != 0) {
475 if (cstring_is_newline(*c)) {
476 return c - buffer;
477 } else {
478 ++c;
479 }
480 }
481
482 return 0;
483}
484
485// returns the index of where to find it. if not found returns 0.
486internal u64 cstring8_find_needle(u8 *buffer, u8 needle)
487{
488 u8 *c = buffer;
489 while (*c != 0) {
490 if (*c == needle) {
491 return c - buffer;
492 } else {
493 ++c;
494 }
495 }
496
497 return 0;
498}