Mon, 14 Jul 2014 16:54:10 +0200
merged sstrcat function
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2014 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
33 #include "string.h"
34 #include "allocator.h"
36 sstr_t sstr(char *cstring) {
37 sstr_t string;
38 string.ptr = cstring;
39 string.length = strlen(cstring);
40 return string;
41 }
43 sstr_t sstrn(char *cstring, size_t length) {
44 sstr_t string;
45 string.ptr = cstring;
46 string.length = length;
47 return string;
48 }
50 size_t sstrnlen(size_t n, sstr_t s, ...) {
51 va_list ap;
52 size_t size = s.length;
53 va_start(ap, s);
55 for (size_t i = 1 ; i < n ; i++) {
56 sstr_t str = va_arg(ap, sstr_t);
57 size += str.length;
58 }
59 va_end(ap);
61 return size;
62 }
64 static sstr_t sstrvcat_a(
65 UcxAllocator *a,
66 size_t count,
67 sstr_t s1,
68 sstr_t s2,
69 va_list ap) {
70 sstr_t str;
71 str.ptr = NULL;
72 str.length = 0;
73 if(count < 2) {
74 return str;
75 }
77 sstr_t *strings = calloc(count, sizeof(sstr_t));
78 if(!strings) {
79 return str;
80 }
82 // get all args and overall length
83 strings[0] = s1;
84 strings[1] = s2;
85 size_t strlen = s1.length + s2.length;
86 for (size_t i=2;i<count;i++) {
87 sstr_t s = va_arg (ap, sstr_t);
88 strings[i] = s;
89 strlen += s.length;
90 }
92 // create new string
93 str.ptr = almalloc(a, strlen + 1);
94 str.length = strlen;
95 if(!str.ptr) {
96 free(strings);
97 str.length = 0;
98 return str;
99 }
101 // concatenate strings
102 size_t pos = 0;
103 for (size_t i=0;i<count;i++) {
104 sstr_t s = strings[i];
105 memcpy(str.ptr + pos, s.ptr, s.length);
106 pos += s.length;
107 }
109 str.ptr[str.length] = '\0';
111 free(strings);
113 return str;
114 }
116 sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) {
117 va_list ap;
118 va_start(ap, s2);
119 sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap);
120 va_end(ap);
121 return s;
122 }
124 sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) {
125 va_list ap;
126 va_start(ap, s2);
127 sstr_t s = sstrvcat_a(a, count, s1, s2, ap);
128 va_end(ap);
129 return s;
130 }
132 sstr_t sstrsubs(sstr_t s, size_t start) {
133 return sstrsubsl (s, start, s.length-start);
134 }
136 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) {
137 sstr_t new_sstr;
138 if (start >= s.length) {
139 new_sstr.ptr = NULL;
140 new_sstr.length = 0;
141 } else {
142 if (length > s.length-start) {
143 length = s.length-start;
144 }
145 new_sstr.ptr = &s.ptr[start];
146 new_sstr.length = length;
147 }
148 return new_sstr;
149 }
151 sstr_t sstrchr(sstr_t s, int c) {
152 for(size_t i=0;i<s.length;i++) {
153 if(s.ptr[i] == c) {
154 return sstrsubs(s, i);
155 }
156 }
157 sstr_t n;
158 n.ptr = NULL;
159 n.length = 0;
160 return n;
161 }
163 sstr_t sstrrchr(sstr_t s, int c) {
164 if (s.length > 0) {
165 for(size_t i=s.length;i>0;i--) {
166 if(s.ptr[i-1] == c) {
167 return sstrsubs(s, i-1);
168 }
169 }
170 }
171 sstr_t n;
172 n.ptr = NULL;
173 n.length = 0;
174 return n;
175 }
177 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) {
178 return sstrsplit_a(ucx_default_allocator(), s, d, n);
179 }
181 sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) {
182 if (s.length == 0 || d.length == 0) {
183 *n = -1;
184 return NULL;
185 }
187 sstr_t* result;
188 ssize_t nmax = *n;
189 *n = 1;
191 /* special case: exact match - no processing needed */
192 if (sstrcmp(s, d) == 0) {
193 *n = 0;
194 return NULL;
195 }
196 sstr_t sv = sstrdup(s);
197 if (sv.length == 0) {
198 *n = -2;
199 return NULL;
200 }
202 for (size_t i = 0 ; i < s.length ; i++) {
203 if (sv.ptr[i] == d.ptr[0]) {
204 _Bool match = 1;
205 for (size_t j = 1 ; j < d.length ; j++) {
206 if (j+i < s.length) {
207 match &= (sv.ptr[i+j] == d.ptr[j]);
208 } else {
209 match = 0;
210 break;
211 }
212 }
213 if (match) {
214 (*n)++;
215 for (size_t j = 0 ; j < d.length ; j++) {
216 sv.ptr[i+j] = 0;
217 }
218 i += d.length;
219 }
220 }
221 if ((*n) == nmax) break;
222 }
223 result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)*(*n));
225 if (result) {
226 char *pptr = sv.ptr;
227 for (ssize_t i = 0 ; i < *n ; i++) {
228 size_t l = strlen(pptr);
229 char* ptr = (char*) almalloc(allocator, l + 1);
230 if (ptr) {
231 memcpy(ptr, pptr, l);
232 ptr[l] = 0;
234 result[i] = sstrn(ptr, l);
235 pptr += l + d.length;
236 } else {
237 for (ssize_t j = i-1 ; j >= 0 ; j--) {
238 alfree(allocator, result[j].ptr);
239 }
240 alfree(allocator, result);
241 *n = -2;
242 break;
243 }
244 }
245 } else {
246 *n = -2;
247 }
249 free(sv.ptr);
251 return result;
252 }
254 int sstrcmp(sstr_t s1, sstr_t s2) {
255 if (s1.length == s2.length) {
256 return memcmp(s1.ptr, s2.ptr, s1.length);
257 } else if (s1.length > s2.length) {
258 return 1;
259 } else {
260 return -1;
261 }
262 }
264 int sstrcasecmp(sstr_t s1, sstr_t s2) {
265 if (s1.length == s2.length) {
266 #ifdef _WIN32
267 return _strnicmp(s1.ptr, s2.ptr, s1.length);
268 #else
269 return strncasecmp(s1.ptr, s2.ptr, s1.length);
270 #endif
271 } else if (s1.length > s2.length) {
272 return 1;
273 } else {
274 return -1;
275 }
276 }
278 sstr_t sstrdup(sstr_t s) {
279 return sstrdup_a(ucx_default_allocator(), s);
280 }
282 sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) {
283 sstr_t newstring;
284 newstring.ptr = (char*)almalloc(allocator, s.length + 1);
285 if (newstring.ptr) {
286 newstring.length = s.length;
287 newstring.ptr[newstring.length] = 0;
289 memcpy(newstring.ptr, s.ptr, s.length);
290 } else {
291 newstring.length = 0;
292 }
294 return newstring;
295 }
297 sstr_t sstrtrim(sstr_t string) {
298 sstr_t newstr = string;
299 if (string.length == 0) {
300 return newstr;
301 }
303 size_t i;
304 for(i=0;i<string.length;i++) {
305 char c = string.ptr[i];
306 if(c > 32) {
307 break;
308 }
309 }
310 newstr.ptr = &string.ptr[i];
311 newstr.length = string.length - i;
313 if(newstr.length == 0) {
314 return newstr;
315 }
317 i = newstr.length - 1;
318 for(;;) {
319 char c = newstr.ptr[i];
320 if(c > 32) {
321 break;
322 }
323 if(i > 0) {
324 i--;
325 } else {
326 break;
327 }
328 }
329 newstr.length = i + 1;
331 return newstr;
332 }
334 int sstrprefix(sstr_t string, sstr_t prefix) {
335 if (string.length == 0) {
336 return prefix.length == 0;
337 }
338 if (prefix.length == 0) {
339 return 1;
340 }
342 if (prefix.length > string.length) {
343 return 0;
344 } else {
345 return memcmp(string.ptr, prefix.ptr, prefix.length) == 0;
346 }
347 }
349 int sstrsuffix(sstr_t string, sstr_t suffix) {
350 if (string.length == 0) {
351 return suffix.length == 0;
352 }
353 if (suffix.length == 0) {
354 return 1;
355 }
357 if (suffix.length > string.length) {
358 return 0;
359 } else {
360 return memcmp(string.ptr+string.length-suffix.length,
361 suffix.ptr, suffix.length) == 0;
362 }
363 }