Browse Source

Minor attempt to try to make string cstr() const-correct; deciding to allocate one more for the null term behind the scenes, but required expanding everything, and needs a rewrite. (There is one way to potentially refactor this by giving vector a way to maybe use a macro for allocs that can be supplanted...)

Luiserebii 10 months ago
parent
commit
0824a9ca00
Signed by: Luiserebii <luis@serebii.io> GPG Key ID: 58A745E0A5422230
4 changed files with 236 additions and 15 deletions
  1. 12
    4
      include/cstl/string.h
  2. 1
    0
      scripts/lint.sh
  3. 3
    0
      src/cstring.c
  4. 220
    11
      src/string.c

+ 12
- 4
include/cstl/string.h View File

@@ -29,6 +29,17 @@
29 29
 declare_vector_class(string, char);
30 30
 // clang-format on
31 31
 
32
+/**
33
+ * A value representing the amount of extra capacity to allocate.
34
+ * In this case, it is meant to represent at least one for the
35
+ * null terminator.
36
+ *
37
+ * Note that all allocation/reallocations therefore allocate
38
+ * the capacity of the vector in terms of chars, + 1 (or,
39
+ * STRING_CAPACITY_EXTRA).
40
+ */
41
+#define STRING_CAPACITY_EXTRA 1
42
+
32 43
 /**
33 44
  * Initializes an empty string with the contents of the char* passed. 
34 45
  * It is assumed that that char* is valid.
@@ -64,9 +75,6 @@ void string_cat_cstr(string* str, const char* s);
64 75
  * If s1 < s2, then the result is a negative integer (i.e. n < 0).
65 76
  * If s1 > s2, then the result is a positive integer (i.e. n > 0).
66 77
  * If s1 == s2, then the result is 0.
67
- *
68
- * NOTE/TODO: Known bug, this function will segfault if the string is empty.
69
- * Will need to re-think an invariant, or this function.
70 78
  */
71 79
 int string_cmp_cstr(const string* s1, const char* s2);
72 80
 
@@ -92,6 +100,6 @@ int string_cmp(const string* s1, const string* s2);
92 100
  * to the string occur - best to call once and use quickly before performing
93 101
  * any modifications.
94 102
  */
95
-const char* string_cstr(string* str);
103
+const char* string_cstr(const string* str);
96 104
 
97 105
 #endif

+ 1
- 0
scripts/lint.sh View File

@@ -1,4 +1,5 @@
1 1
 #!/bin/bash
2 2
 find ./include -regex '.*\.\(cpp\|hpp\|cu\|c\|h\)' -exec clang-format -style=file -i {} \;
3
+find ./src -regex '.*\.\(cpp\|hpp\|cu\|c\|h\)' -exec clang-format -style=file -i {} \;
3 4
 find ./test/src -regex '.*\.\(cpp\|hpp\|cu\|c\|h\)' -exec clang-format -style=file -i {} \;
4 5
 find ./test/include -regex '.*\.\(cpp\|hpp\|cu\|c\|h\)' -exec clang-format -style=file -i {} \;

+ 3
- 0
src/cstring.c View File

@@ -2,8 +2,11 @@
2 2
 #include <string.h>
3 3
 
4 4
 void safestrcpy(char* dest, const char* src, size_t lim) {
5
+    //Minor dev-note; *dest++ = *src++ can resolve to '\0'
6
+    //being set, rendering the final statement potentially pointless
5 7
     while(--lim && (*dest++ = *src++))
6 8
         ;
9
+    *dest = '\0';
7 10
 }
8 11
 
9 12
 char* fstrcat(char* dest, const char* src) {

+ 220
- 11
src/string.c View File

@@ -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;

Loading…
Cancel
Save