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(index > string->length || !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-1))
79 return false;
80 memcpy(string->chars+string->length,other->chars,other->length);
81 string->length += other->length;
82 string->chars[string->length] = '\0';
83 return true;
84}
85
86bool string_find_char(const String* haystack, char needle, size_t* pos)
87{
88 char* ret = memchr(haystack->chars, needle, haystack->length);
89 if(!ret)
90 {
91 return false;
92 } else {
93 *pos = (size_t)(ret-haystack->chars);
94 return true;
95 }
96}
97
98int string_cmp(const String* s1, const String* s2)
99{
100 int ret = memcmp(s1->chars, s2->chars, s1->length < s2->length ? s1->length : s2->length);
101 if(ret == 0 && s1->length != s2->length)
102 return s1->length < s2->length ? -1 : 1;
103 else
104 return ret;
105}
106
107
108size_t string_count(const String* string, char character)
109{
110 size_t i, ret = 0;
111 for(i = 0; i < string->length; i++)
112 {
113 if(string_at(string, i) == character)
114 ret++;
115 }
116 return ret;
117}
118
119bool string_grow(String* string, size_t add)
120{
121 if(string->length+add < string->length)
122 return false;
123 return string_adjust_size(string, string->length+add);
124}
125
126bool string_adjust_size(String* string, size_t size)
127{
128 if(size == SIZE_MAX && string->null_terminated)
129 return false;
130
131 while(string->capacity < size+(string->null_terminated?1:0))
132 {
133 char* tmp = string->chars;
134 string->chars = cutil_reallocarray_inc(string->chars, sizeof(*string->chars), string->capacity, string->capacity);
135 if(!string->chars)
136 {
137 string->chars = tmp;
138 return false;
139 }
140 string->capacity *= 2;
141 }
142 return true;
143}
144
145
146void delete_string(String* string)
147{
148 free(string->chars);
149 free(string);
150}
151
152String* from_cstring(const char* cstring, bool null_terminated)
153{
154 String* string = string_with_capacity(strlen(cstring), null_terminated);
155 if(!string)
156 {
157 return NULL;
158 } else {
159 memcpy(string->chars, cstring, strlen(cstring));
160 string->length = strlen(cstring);
161 if(null_terminated)
162 string->chars[string->length] = '\0';
163 return string;
164 }
165}
166
167String* from_cstring_reuse(char* cstring, size_t capacity, bool null_terminated)
168{
169 String* string;
170
171 if(!cstring)
172 return NULL;
173
174 string = malloc(sizeof(*string));
175 if(!string)
176 return NULL;
177
178 string->chars = cstring;
179 string->length = strlen(cstring);
180 string->capacity = capacity;
181
182 return string;
183}
184
185String* from_cstring_del(char* cstring, bool null_terminated)
186{
187 String* ret = from_cstring(cstring, null_terminated);
188 if(!ret)
189 return NULL;
190 free(cstring);
191 return ret;
192}
193
194char* to_cstring(const String* string)
195{
196 char* cstring = malloc(string->length+1);
197 memcpy(cstring, string->chars, string->length);
198 cstring[string->length] = '\0';
199
200 return cstring;
201}
202
203char* to_cstring_del(String* string)
204{
205 char* ret = to_cstring(string);
206 delete_string(string);
207 return ret;
208}
209
210void string_move(String* dest, String* src)
211{
212 free(dest->chars);
213 dest->chars = src->chars;
214 free(src);
215}
216