summaryrefslogtreecommitdiff
path: root/prb_string.h
blob: cd7297f3c2e133e2e60c35ddcd1d1999047690a2 (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
/*
void prb_memset(void *dest, i32 fill, u64 n);
void prb_memmove(void *dest, const void *src, u64 size);
i32 prb_memeq(const void *p1, const void *p2, u64 size);
i32 streq(const char *str1, const char *str2);

char *str8_to_cstr(arena_t *arena, str8_t str);
i32 str8eq(str8_t str1, str8_t str2);
u8 *str8ch(str8_t str, i32 c);
u8 *str8rch(str8_t str, i32 c);
str8_t str8_range(u8 *start, u8 *end);
str8_t str8_getdir(str8_t str);
str8_t str8_pushfv(arena_t *arena, const char *format, va_list args);
str8_t str8_pushf(arena_t *arena, const char *format, ...);
void str8_print(str8_t str);
void str8_printf(const char *format, ...);
void str8_list_push(arena_t *arena, str8_list_t *list, i32 front, str8_t str);
void str8_list_pushf(arena_t *arena, str8_list_t *list, i32 front, const char *format, ...);
str8_t str8_list_join(arena_t *arena, str8_list_t *list);
void str8_list_print(str8_list_t *list);
*/

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);
}