summaryrefslogtreecommitdiff
path: root/source/base/base_string.h
blob: 4fdd4d5b3681cedda89451e3c8da966273c3db2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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 */