dyn_string.c
Raw
1#include <cutils/dyn_string.h>
2
3String* string_with_capacity(size_t capacity, bool null_terminated)
4{
5 String* string = malloc(sizeof(*string));
6 if(!string)
7 return NULL;
8 string->chars = malloc(capacity+(null_terminated?1:0));
9 if(!string->chars)
10 {
11 free(string);
12 return NULL;
13 }
14 if(null_terminated)
15 string->chars[0] = '\0';
16 string->length = 0;
17 string->capacity = capacity;
18 string->null_terminated = null_terminated;
19
20 return string;
21}
22
23void string_remove_range(String* string, size_t index, size_t length)
24{
25 memmove(string->chars+index, string->chars+index+length, (string->length-(index+length)+(string->null_terminated?1:0)));
26 string->length -= length;
27}
28
29size_t string_strip(String* string, char character)
30{
31 size_t i, last = 0, offset = 0;
32 bool first = true;
33
34 for(i = 0; i < string->length; i++)
35 {
36 if(string_at(string,i) == character)
37 {
38 if(first)
39 {
40 first = false;
41 } else {
42 memmove(string->chars+last-offset, string->chars+last+1, i-last-1);
43 offset++;
44 }
45
46 last = i;
47 }
48 }
49
50 memmove(string->chars+last-offset, string->chars+last+1, string->length-last-1+(string->null_terminated?1:0));
51
52 string->length -= offset+(first ? 0 : 1);
53 return offset;
54}
55
56bool string_insert(String* string, size_t index, char character)
57{
58 if(!string_grow(string, 1))
59 return false;
60
61 memmove(string->chars+index+1, string->chars+index, (string->length-index+(string->null_terminated?1:0))*sizeof(*string->chars));
62 string->chars[index] = character;
63 string->length++;
64 return true;
65}
66
67char string_pop_at(String* string, size_t index)
68{
69 char tmp = string_at(string, index);
70 string_remove(string, index);
71 return tmp;
72}
73
74bool string_concat(String* string, const String* other)
75{
76 if(other->length == 0)
77 return true;
78 if(!string_grow(string, other->length))
79 return false;
80 memcpy(string->chars+string->length,other->chars,other->length);
81 string->length += other->length;
82 if(string->null_terminated)
83 string->chars[string->length] = '\0';
84 return true;
85}
86
87bool string_find_char(const String* haystack, char needle, size_t* pos)
88{
89 char* ret = memchr(haystack->chars, needle, haystack->length);
90 if(!ret)
91 {
92 return false;
93 } else {
94 *pos = (size_t)(ret-haystack->chars);
95 return true;
96 }
97}
98
99int string_cmp(const String* s1, const String* s2)
100{
101 int ret = memcmp(s1->chars, s2->chars, CUTIL_MIN(s1->length, s2->length));
102 if(ret == 0 && s1->length != s2->length)
103 return s1->length < s2->length ? -1 : 1;
104 else
105 return ret;
106}
107
108int string_cmp_cstr(const String* s1, const char* s2)
109{
110 int ret = memcmp(s1->chars, s2, s1->length < strlen(s2) ? s1->length : strlen(s2));
111 if(ret == 0 && s1->length != strlen(s2))
112 return s1->length < strlen(s2) ? -1 : 1;
113 else
114 return ret;
115}
116
117
118size_t string_count(const String* string, char character)
119{
120 size_t i, ret = 0;
121 for(i = 0; i < string->length; i++)
122 {
123 if(string_at(string, i) == character)
124 ret++;
125 }
126 return ret;
127}
128
129Vector* string_split(const String* string, const char* set, bool null_terminated)
130{
131 #define CHECKRESULT(x) if(!x){delete_vector(ret, delete_string);return NULL;}
132 size_t i, currentvec = 0, currentlen = 0;
133 char c;
134 const char* orig = set;
135 String* tmp;
136 Vector* ret = new_vector();
137 bool is_delimiter = true;
138
139 if(!ret)
140 return NULL;
141
142 for(i = 0; i < string->length; i++)
143 {
144 for(c = *set++; c != '\0'; c = *set++)
145 {
146 if(string_at(string, i) == c)
147 {
148 is_delimiter = true;
149 currentlen = 0;
150 break;
151 } else {
152 is_delimiter = false;
153 }
154 }
155 if(!is_delimiter)
156 {
157 if(currentlen == 0)
158 {
159 tmp = new_string(null_terminated);
160 CHECKRESULT(tmp);
161 CHECKRESULT(vector_push(ret, tmp));
162 currentvec++;
163 }
164 currentlen++;
165 CHECKRESULT(string_push(vector_at(ret, currentvec-1), string_at(string, i)));
166 }
167 set = orig;
168 }
169
170 return ret;
171 #undef CHECKRESULT
172}
173
174bool string_grow(String* string, size_t add)
175{
176 if(string->length+add < string->length)
177 return false;
178 return string_adjust_size(string, string->length+add);
179}
180
181bool string_adjust_size(String* string, size_t size)
182{
183 if(size == SIZE_MAX && string->null_terminated)
184 return false;
185
186 while(string->capacity < size+(string->null_terminated?1:0))
187 {
188 char* tmp = string->chars;
189 string->chars = cutil_reallocarray_inc(string->chars, sizeof(*string->chars), string->capacity, string->capacity);
190 if(!string->chars)
191 {
192 string->chars = tmp;
193 return false;
194 }
195 string->capacity *= 2;
196 }
197 return true;
198}
199
200
201void delete_string(void* string)
202{
203 free(((String*)string)->chars);
204 free(string);
205}
206
207String* from_cstring(const char* cstring, bool null_terminated)
208{
209 String* string = string_with_capacity(strlen(cstring), null_terminated);
210 if(!string)
211 {
212 return NULL;
213 } else {
214 memcpy(string->chars, cstring, strlen(cstring));
215 string->length = strlen(cstring);
216 if(null_terminated)
217 string->chars[string->length] = '\0';
218 return string;
219 }
220}
221
222String* from_cstring_reuse(char* cstring, size_t capacity, bool null_terminated)
223{
224 String* string;
225
226 if(!cstring)
227 return NULL;
228
229 string = malloc(sizeof(*string));
230 if(!string)
231 return NULL;
232
233 string->chars = cstring;
234 string->length = strlen(cstring);
235 string->capacity = capacity;
236 string->null_terminated = null_terminated;
237
238 return string;
239}
240
241String* from_cstring_del(char* cstring, bool null_terminated)
242{
243 String* ret = from_cstring(cstring, null_terminated);
244 if(!ret)
245 return NULL;
246 free(cstring);
247 return ret;
248}
249
250char* to_cstring(const String* string)
251{
252 char* cstring = malloc(string->length+1);
253 memcpy(cstring, string->chars, string->length);
254 cstring[string->length] = '\0';
255
256 return cstring;
257}
258
259char* to_cstring_del(String* string)
260{
261 char* ret = to_cstring(string);
262 delete_string(string);
263 return ret;
264}
265
266void string_move(String* dest, String* src)
267{
268 free(dest->chars);
269 dest->chars = src->chars;
270 free(src);
271}
272