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
|
/* Copyright (C) 2025 Aryadev Chavali
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License Version 2 for
* details.
* You may distribute and modify this code under the terms of the GNU General
* Public License Version 2, which you should have received a copy of along with
* this program. If not, please go to <https://www.gnu.org/licenses/>.
* Created: 2025-04-14
* Description: String View implementation
*/
#include <lib/sv.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
sv_t sv_make(arena_t *allocator, const char *data, u64 size)
{
sv_t s = {0};
if (data)
s = sv_append(allocator, s, data, size);
else
{
s.data = arena_alloc(allocator, size);
s.size = size;
}
return s;
}
sv_t sv_copy(arena_t *allocator, sv_t sv)
{
return sv_make(allocator, sv.data, sv.size);
}
sv_t sv_substr(sv_t sv, u64 index, u64 size)
{
sv_t newsv = {0};
if (index + size > sv.size)
return newsv;
newsv.data = sv.data + index;
newsv.size = size;
return newsv;
}
sv_t sv_cut(sv_t sv, u64 index)
{
return sv_substr(sv, index, sv.size < index ? 0 : sv.size - index);
}
sv_t sv_chop(sv_t sv, u64 size)
{
return sv_substr(sv, 0, size);
}
sv_t sv_concat(arena_t *allocator, sv_t a, sv_t b)
{
sv_t c = sv_make(allocator, a.data, a.size + b.size);
memcpy(c.data + a.size, b.data, b.size);
return c;
}
sv_t sv_append(arena_t *allocator, sv_t sv, const char *data, u64 size)
{
if (!allocator)
return (sv_t){0};
sv_t newsv = {0};
newsv.size = sv.size + size;
newsv.data = arena_realloc(allocator, sv.data, sv.size, newsv.size);
if (data)
memcpy(newsv.data + sv.size, data, size);
return newsv;
}
sv_t sv_prepend(arena_t *allocator, sv_t sv, const char *data, u64 size)
{
if (!allocator)
return (sv_t){0};
// TODO: Can we make this cheaper to do?
sv_t newsv = sv_make(allocator, NULL, size + sv.size);
// Copy over `data` to the left side
memcpy(newsv.data, data, size);
// Copy old string to the right side
if (sv.data)
memcpy(newsv.data + size, sv.data, sv.size);
return newsv;
}
sv_t sv_fmt(arena_t *allocator, char *fmt, ...)
{
if (!allocator)
return (sv_t){0};
va_list ap_1, ap_2;
va_start(ap_1, fmt);
va_copy(ap_2, ap_1);
u64 size = vsnprintf(NULL, 0, fmt, ap_2);
va_end(ap_2);
sv_t sv = sv_make(allocator, NULL, size);
vsprintf(sv.data, fmt, ap_1);
va_end(ap_1);
return sv;
}
i64 sv_find_substr(const sv_t sv, const sv_t substr)
{
if (substr.size == 0)
return 0;
else if (sv.size < substr.size)
return -1;
else if (sv.size == substr.size)
return strncmp(sv.data, substr.data, sv.size) == 0 ? 0 : -1;
for (u64 i = 0; i < (sv.size - substr.size); ++i)
if (strncmp(sv.data + i, substr.data, substr.size) == 0)
return i;
return -1;
}
i64 sv_find_subcstr(const sv_t sv, const char *substr, u64 size)
{
return sv_find_substr(sv, SV((char *)substr, size));
}
i64 sv_find_any(const sv_t sv, const char *bag)
{
for (u64 i = 0; i < sv.size; ++i)
if (strchr(bag, sv.data[i]))
return i;
return -1;
}
u64 sv_while(const sv_t sv, bool (*pred)(char))
{
u64 i;
for (i = 0; i < sv.size && pred(sv.data[i]); ++i)
continue;
return i;
}
u64 sv_till(const sv_t sv, bool (*pred)(char))
{
u64 i;
for (i = 0; i < sv.size && !pred(sv.data[i]); ++i)
continue;
return i;
}
|