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