|
@@ -18,17 +18,230 @@
|
18
|
18
|
*/
|
19
|
19
|
|
20
|
20
|
#include "../include/cstl/string.h"
|
21
|
|
-#include "../include/cstl/vector.h"
|
22
|
21
|
#include "../include/cstl/algorithm.h"
|
|
22
|
+#include "../include/cstl/vector.h"
|
23
|
23
|
|
24
|
24
|
#include <string.h>
|
25
|
25
|
|
26
|
26
|
/**
|
27
|
27
|
* Generate a set of vector functions for our string
|
28
|
28
|
*/
|
29
|
|
-// clang-format off
|
30
|
|
-define_vector_class(string, char)
|
31
|
|
-// clang-format on
|
|
29
|
+
|
|
30
|
+static void string_autogrow(string* v);
|
|
31
|
+void string_init(string* v) {
|
|
32
|
+ v->head = v->avail = v->tail = ((void*) 0);
|
|
33
|
+}
|
|
34
|
+void string_init_size(string* v, size_t s) {
|
|
35
|
+ v->head = (char*) safemalloc(sizeof(char) * s + STRING_CAPACITY_EXTRA);
|
|
36
|
+ v->tail = v->avail = v->head + s;
|
|
37
|
+}
|
|
38
|
+void string_init_capacity(string* v, size_t s) {
|
|
39
|
+ v->head = v->avail = (char*) safemalloc(sizeof(char) * s + STRING_CAPACITY_EXTRA);
|
|
40
|
+ v->tail = v->head + s;
|
|
41
|
+}
|
|
42
|
+void string_init_fill(string* v, size_t n, char val) {
|
|
43
|
+ string_init_size(v, n);
|
|
44
|
+ {
|
|
45
|
+ for(char* _alg_copy_it = v->head; _alg_copy_it != v->tail; *_alg_copy_it++ = val)
|
|
46
|
+ ;
|
|
47
|
+ };
|
|
48
|
+}
|
|
49
|
+void string_init_range(string* v, const char* first, const char* last) {
|
|
50
|
+ string_init_size(v, last - first);
|
|
51
|
+ {
|
|
52
|
+ const char* _alg_copy_it = first;
|
|
53
|
+ for(char* _alg_copy_dest = v->head; _alg_copy_it != last; *_alg_copy_dest++ = *_alg_copy_it++)
|
|
54
|
+ ;
|
|
55
|
+ };
|
|
56
|
+}
|
|
57
|
+string* string_create(void) {
|
|
58
|
+ string* v = (string*) safemalloc(sizeof(string));
|
|
59
|
+ string_init(v);
|
|
60
|
+ return v;
|
|
61
|
+}
|
|
62
|
+string* string_create_size(size_t s) {
|
|
63
|
+ string* v = (string*) safemalloc(sizeof(string));
|
|
64
|
+ string_init_size(v, s);
|
|
65
|
+ return v;
|
|
66
|
+}
|
|
67
|
+string* string_create_capacity(size_t s) {
|
|
68
|
+ string* v = (string*) safemalloc(sizeof(string));
|
|
69
|
+ string_init_capacity(v, s);
|
|
70
|
+ return v;
|
|
71
|
+}
|
|
72
|
+string* string_create_fill(size_t n, char val) {
|
|
73
|
+ string* v = string_create_size(n);
|
|
74
|
+ string_init_fill(v, n, val);
|
|
75
|
+ return v;
|
|
76
|
+}
|
|
77
|
+string* string_create_range(const char* first, const char* last) {
|
|
78
|
+ string* v = string_create_size(last - first);
|
|
79
|
+ string_init_range(v, first, last);
|
|
80
|
+ return v;
|
|
81
|
+}
|
|
82
|
+string* string_copy(const string* src) {
|
|
83
|
+ if(src->head == ((void*) 0)) {
|
|
84
|
+ return string_create();
|
|
85
|
+ }
|
|
86
|
+ string* copy = string_create_size(string_size(src));
|
|
87
|
+ {
|
|
88
|
+ const char* _alg_copy_it = src->head;
|
|
89
|
+ for(char* _alg_copy_dest = copy->head; _alg_copy_it != src->avail; *_alg_copy_dest++ = *_alg_copy_it++)
|
|
90
|
+ ;
|
|
91
|
+ };
|
|
92
|
+ return copy;
|
|
93
|
+}
|
|
94
|
+void string_asn(string* dest, const string* src) {
|
|
95
|
+ string_assign(dest, string_begin(src), string_end(src));
|
|
96
|
+}
|
|
97
|
+void string_assign(string* v, const char* first, const char* last) {
|
|
98
|
+ size_t sz = last - first;
|
|
99
|
+ if(string_capacity(v) < sz) {
|
|
100
|
+ v->head = (char*) saferealloc(v->head, sizeof(char) * sz + STRING_CAPACITY_EXTRA);
|
|
101
|
+ v->tail = v->head + sz;
|
|
102
|
+ }
|
|
103
|
+ {
|
|
104
|
+ const char* _alg_copy_it = first;
|
|
105
|
+ for(char* _alg_copy_dest = v->head; _alg_copy_it != last; *_alg_copy_dest++ = *_alg_copy_it++)
|
|
106
|
+ ;
|
|
107
|
+ };
|
|
108
|
+ v->avail = v->head + sz;
|
|
109
|
+}
|
|
110
|
+void string_set(string* v, size_t pos, char val) {
|
|
111
|
+ v->head[pos] = val;
|
|
112
|
+}
|
|
113
|
+void string_push_back(string* v, char e) {
|
|
114
|
+ if(v->avail == v->tail) {
|
|
115
|
+ string_autogrow(v);
|
|
116
|
+ }
|
|
117
|
+ *(v->avail++) = e;
|
|
118
|
+}
|
|
119
|
+void string_push_back_r(string* v, const char* e) {
|
|
120
|
+ if(v->avail == v->tail) {
|
|
121
|
+ string_autogrow(v);
|
|
122
|
+ }
|
|
123
|
+ *(v->avail++) = *e;
|
|
124
|
+}
|
|
125
|
+void string_insert(string* v, char* p, char val) {
|
|
126
|
+ size_t pos = p - v->head;
|
|
127
|
+ if(v->avail == v->tail) {
|
|
128
|
+ string_grow(v, string_capacity(v) + 1);
|
|
129
|
+ }
|
|
130
|
+ p = v->head + pos;
|
|
131
|
+ char* it = v->avail;
|
|
132
|
+ for(; it != p; --it) {
|
|
133
|
+ *it = *(it - 1);
|
|
134
|
+ }
|
|
135
|
+ *p = val;
|
|
136
|
+ ++v->avail;
|
|
137
|
+}
|
|
138
|
+void string_insert_r(string* v, char* p, const char* val) {
|
|
139
|
+ size_t pos = p - v->head;
|
|
140
|
+ if(v->avail == v->tail) {
|
|
141
|
+ string_grow(v, string_capacity(v) + 1);
|
|
142
|
+ }
|
|
143
|
+ p = v->head + pos;
|
|
144
|
+ char* it = v->avail;
|
|
145
|
+ for(; it != p; --it) {
|
|
146
|
+ *it = *(it - 1);
|
|
147
|
+ }
|
|
148
|
+ *p = *val;
|
|
149
|
+ ++v->avail;
|
|
150
|
+}
|
|
151
|
+void string_insert_range(string* v, char* p, const char* begin, const char* end) {
|
|
152
|
+ size_t pos = p - v->head;
|
|
153
|
+ size_t sz = end - begin;
|
|
154
|
+ if(v->avail == v->tail) {
|
|
155
|
+ string_grow(v, string_capacity(v) + sz);
|
|
156
|
+ }
|
|
157
|
+ p = v->head + pos;
|
|
158
|
+ char* it = v->avail;
|
|
159
|
+ for(; it != p; --it) {
|
|
160
|
+ *(it + sz - 1) = *(it - 1);
|
|
161
|
+ }
|
|
162
|
+ {
|
|
163
|
+ const char* _alg_copy_it = begin;
|
|
164
|
+ for(char* _alg_copy_dest = p; _alg_copy_it != end; *_alg_copy_dest++ = *_alg_copy_it++)
|
|
165
|
+ ;
|
|
166
|
+ };
|
|
167
|
+ v->avail += sz;
|
|
168
|
+}
|
|
169
|
+void string_pop_back(string* v) {
|
|
170
|
+ ((string_size(v) != 0)
|
|
171
|
+ ? (void) (0)
|
|
172
|
+ : __assert_fail("string_size(v) != 0", "/home/luiserebii/github/gitid/./src/cli.c", 71, __PRETTY_FUNCTION__));
|
|
173
|
+ --v->avail;
|
|
174
|
+ return;
|
|
175
|
+}
|
|
176
|
+char* string_erase(string* v, char* pos) {
|
|
177
|
+ for(; pos + 1 != v->avail; ++pos) {
|
|
178
|
+ *pos = *(pos + 1);
|
|
179
|
+ }
|
|
180
|
+ return --v->avail;
|
|
181
|
+}
|
|
182
|
+char* string_erase_range(string* v, char* begin, char* end) {
|
|
183
|
+ size_t diff = end - begin;
|
|
184
|
+ for(; begin + diff != v->avail; ++begin) {
|
|
185
|
+ *begin = *(begin + diff);
|
|
186
|
+ }
|
|
187
|
+ return v->avail -= diff;
|
|
188
|
+}
|
|
189
|
+char* string_begin(const string* v) {
|
|
190
|
+ return v->head;
|
|
191
|
+}
|
|
192
|
+char* string_end(const string* v) {
|
|
193
|
+ return v->avail;
|
|
194
|
+}
|
|
195
|
+void string_autogrow(string* v) {
|
|
196
|
+ size_t old_sz = string_size(v);
|
|
197
|
+ size_t n_size = v->head ? old_sz * 2 : 1;
|
|
198
|
+ v->head = (char*) saferealloc(v->head, sizeof(char) * n_size + STRING_CAPACITY_EXTRA);
|
|
199
|
+ v->avail = v->head + old_sz;
|
|
200
|
+ v->tail = v->head + n_size;
|
|
201
|
+}
|
|
202
|
+size_t string_size(const string* v) {
|
|
203
|
+ return v->avail - v->head;
|
|
204
|
+}
|
|
205
|
+size_t string_capacity(const string* v) {
|
|
206
|
+ return v->tail - v->head;
|
|
207
|
+}
|
|
208
|
+char string_at(const string* v, size_t n) {
|
|
209
|
+ return *(v->head + n);
|
|
210
|
+}
|
|
211
|
+void string_resize(string* v, size_t n) {
|
|
212
|
+ size_t old_sz = string_size(v);
|
|
213
|
+ if(n > old_sz) {
|
|
214
|
+ v->head = (char*) saferealloc(v->head, sizeof(char) * n + STRING_CAPACITY_EXTRA);
|
|
215
|
+ v->avail = v->head + old_sz;
|
|
216
|
+ v->tail = v->head + n;
|
|
217
|
+ } else {
|
|
218
|
+ v->avail -= (old_sz - n);
|
|
219
|
+ }
|
|
220
|
+}
|
|
221
|
+void string_grow(string* v, size_t n) {
|
|
222
|
+ size_t old_sz = string_size(v);
|
|
223
|
+ ((n >= old_sz) ? (void) (0) : __assert_fail("n >= old_sz", "/home/luiserebii/github/gitid/./src/cli.c", 71,
|
|
224
|
+ __PRETTY_FUNCTION__));
|
|
225
|
+ v->head = (char*) saferealloc(v->head, sizeof(char) * n + STRING_CAPACITY_EXTRA);
|
|
226
|
+ v->avail = v->head + old_sz;
|
|
227
|
+ v->tail = v->head + n;
|
|
228
|
+}
|
|
229
|
+void string_shrink(string* v, size_t n) {
|
|
230
|
+ ((n < string_size(v))
|
|
231
|
+ ? (void) (0)
|
|
232
|
+ : __assert_fail("n < string_size(v)", "/home/luiserebii/github/gitid/./src/cli.c", 71, __PRETTY_FUNCTION__));
|
|
233
|
+ v->avail -= (string_size(v) - n);
|
|
234
|
+}
|
|
235
|
+void string_clear(string* v) {
|
|
236
|
+ v->avail = v->head;
|
|
237
|
+}
|
|
238
|
+void string_deinit(string* v) {
|
|
239
|
+ free(v->head);
|
|
240
|
+}
|
|
241
|
+void string_destroy(string* v) {
|
|
242
|
+ string_deinit(v);
|
|
243
|
+ free(v);
|
|
244
|
+}
|
32
|
245
|
|
33
|
246
|
void string_init_cstr(string* str, const char* s) {
|
34
|
247
|
size_t len = strlen(s);
|
|
@@ -71,7 +284,7 @@ int string_cmp_cstr(const string* s1, const char* s2) {
|
71
|
284
|
}
|
72
|
285
|
if(it1 == end1 && *s2 == '\0') {
|
73
|
286
|
return 0;
|
74
|
|
- }
|
|
287
|
+ }
|
75
|
288
|
if(it1 == end1) {
|
76
|
289
|
return -1;
|
77
|
290
|
}
|
|
@@ -90,18 +303,14 @@ int string_cmp(const string* s1, const string* s2) {
|
90
|
303
|
}
|
91
|
304
|
if(it1 == end1 && it2 == end2) {
|
92
|
305
|
return 0;
|
93
|
|
- }
|
|
306
|
+ }
|
94
|
307
|
if(it1 == end1) {
|
95
|
308
|
return -1;
|
96
|
309
|
}
|
97
|
310
|
return 1;
|
98
|
311
|
}
|
99
|
312
|
|
100
|
|
-const char* string_cstr(string* str) {
|
101
|
|
- //Grow capacity if necessary
|
102
|
|
- if(str->avail == str->tail) {
|
103
|
|
- string_grow(str, string_capacity(str) + 1);
|
104
|
|
- }
|
|
313
|
+const char* string_cstr(const string* str) {
|
105
|
314
|
//Set a null-terminator at avail
|
106
|
315
|
*(str->avail) = '\0';
|
107
|
316
|
return str->head;
|