1 /* |
1 /* |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 * |
3 * |
4 * Copyright 2013 Olaf Wintermann. All rights reserved. |
4 * Copyright 2015 Olaf Wintermann. All rights reserved. |
5 * |
5 * |
6 * Redistribution and use in source and binary forms, with or without |
6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions are met: |
7 * modification, are permitted provided that the following conditions are met: |
8 * |
8 * |
9 * 1. Redistributions of source code must retain the above copyright |
9 * 1. Redistributions of source code must retain the above copyright |
59 va_end(ap); |
60 va_end(ap); |
60 |
61 |
61 return size; |
62 return size; |
62 } |
63 } |
63 |
64 |
64 sstr_t sstrncat(sstr_t s, size_t n, sstr_t c1, ...) { |
65 static sstr_t sstrvcat_a( |
|
66 UcxAllocator *a, |
|
67 size_t count, |
|
68 sstr_t s1, |
|
69 sstr_t s2, |
|
70 va_list ap) { |
|
71 sstr_t str; |
|
72 str.ptr = NULL; |
|
73 str.length = 0; |
|
74 if(count < 2) { |
|
75 return str; |
|
76 } |
|
77 |
|
78 sstr_t *strings = (sstr_t*) calloc(count, sizeof(sstr_t)); |
|
79 if(!strings) { |
|
80 return str; |
|
81 } |
|
82 |
|
83 // get all args and overall length |
|
84 strings[0] = s1; |
|
85 strings[1] = s2; |
|
86 size_t strlen = s1.length + s2.length; |
|
87 for (size_t i=2;i<count;i++) { |
|
88 sstr_t s = va_arg (ap, sstr_t); |
|
89 strings[i] = s; |
|
90 strlen += s.length; |
|
91 } |
|
92 |
|
93 // create new string |
|
94 str.ptr = (char*) almalloc(a, strlen + 1); |
|
95 str.length = strlen; |
|
96 if(!str.ptr) { |
|
97 free(strings); |
|
98 str.length = 0; |
|
99 return str; |
|
100 } |
|
101 |
|
102 // concatenate strings |
|
103 size_t pos = 0; |
|
104 for (size_t i=0;i<count;i++) { |
|
105 sstr_t s = strings[i]; |
|
106 memcpy(str.ptr + pos, s.ptr, s.length); |
|
107 pos += s.length; |
|
108 } |
|
109 |
|
110 str.ptr[str.length] = '\0'; |
|
111 |
|
112 free(strings); |
|
113 |
|
114 return str; |
|
115 } |
|
116 |
|
117 sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) { |
65 va_list ap; |
118 va_list ap; |
66 va_start(ap, c1); |
119 va_start(ap, s2); |
67 s.ptr[0] = 0; |
120 sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap); |
68 |
|
69 size_t len = s.length; |
|
70 size_t cplen = c1.length > len ? len : c1.length; |
|
71 char *ptr = s.ptr; |
|
72 |
|
73 memcpy(ptr, c1.ptr, cplen); |
|
74 len -= cplen; |
|
75 ptr += cplen; |
|
76 for (size_t i = 1 ; i < n ; i++) { |
|
77 sstr_t str = va_arg (ap, sstr_t); |
|
78 cplen = str.length > len ? len : str.length; |
|
79 if(cplen <= 0) { |
|
80 va_end(ap); |
|
81 return s; |
|
82 } |
|
83 memcpy(ptr, str.ptr, cplen); |
|
84 len -= cplen; |
|
85 ptr += cplen; |
|
86 } |
|
87 va_end(ap); |
121 va_end(ap); |
88 s.length = ptr - s.ptr; |
122 return s; |
89 |
123 } |
|
124 |
|
125 sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) { |
|
126 va_list ap; |
|
127 va_start(ap, s2); |
|
128 sstr_t s = sstrvcat_a(a, count, s1, s2, ap); |
|
129 va_end(ap); |
90 return s; |
130 return s; |
91 } |
131 } |
92 |
132 |
93 sstr_t sstrsubs(sstr_t s, size_t start) { |
133 sstr_t sstrsubs(sstr_t s, size_t start) { |
94 return sstrsubsl (s, start, s.length-start); |
134 return sstrsubsl (s, start, s.length-start); |
95 } |
135 } |
96 |
136 |
97 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) { |
137 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) { |
98 sstr_t new_sstr; |
138 sstr_t new_sstr; |
99 if (start >= s.length) { |
139 if (start >= s.length) { |
100 return s; |
140 new_sstr.ptr = NULL; |
101 } |
141 new_sstr.length = 0; |
102 if (length > s.length-start) { |
142 } else { |
103 length = s.length-start; |
143 if (length > s.length-start) { |
104 } |
144 length = s.length-start; |
105 new_sstr.ptr = &s.ptr[start]; |
145 } |
106 new_sstr.length = length; |
146 new_sstr.ptr = &s.ptr[start]; |
|
147 new_sstr.length = length; |
|
148 } |
107 return new_sstr; |
149 return new_sstr; |
108 } |
150 } |
109 |
151 |
110 sstr_t sstrchr(sstr_t s, int c) { |
152 sstr_t sstrchr(sstr_t s, int c) { |
111 for(size_t i=0;i<s.length;i++) { |
153 for(size_t i=0;i<s.length;i++) { |
131 n.ptr = NULL; |
173 n.ptr = NULL; |
132 n.length = 0; |
174 n.length = 0; |
133 return n; |
175 return n; |
134 } |
176 } |
135 |
177 |
136 sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n) { |
178 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) { |
137 return sstrsplit_a(ucx_default_allocator(), s, d, n); |
179 return sstrsplit_a(ucx_default_allocator(), s, d, n); |
138 } |
180 } |
139 |
181 |
140 sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, size_t *n) { |
182 sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) { |
141 if (s.length == 0 || d.length == 0) { |
183 if (s.length == 0 || d.length == 0) { |
142 *n = -1; |
184 *n = -1; |
143 return NULL; |
185 return NULL; |
144 } |
186 } |
145 |
187 |
146 sstr_t* result; |
188 sstr_t* result; |
147 size_t nmax = *n; |
189 ssize_t nmax = *n; |
148 *n = 1; |
190 *n = 1; |
149 |
191 |
150 /* special case: exact match - no processing needed */ |
192 /* special case: exact match - no processing needed */ |
151 if (sstrcmp(s, d) == 0) { |
193 if (sstrcmp(s, d) == 0) { |
152 *n = 0; |
194 *n = 0; |
177 i += d.length; |
219 i += d.length; |
178 } |
220 } |
179 } |
221 } |
180 if ((*n) == nmax) break; |
222 if ((*n) == nmax) break; |
181 } |
223 } |
182 result = (sstr_t*) allocator->malloc(allocator->pool, sizeof(sstr_t)*(*n)); |
224 result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)*(*n)); |
183 |
225 |
184 if (result) { |
226 if (result) { |
185 char *pptr = sv.ptr; |
227 char *pptr = sv.ptr; |
186 for (size_t i = 0 ; i < *n ; i++) { |
228 for (ssize_t i = 0 ; i < *n ; i++) { |
187 size_t l = strlen(pptr); |
229 size_t l = strlen(pptr); |
188 char* ptr = (char*) allocator->malloc(allocator->pool, l + 1); |
230 char* ptr = (char*) almalloc(allocator, l + 1); |
189 memcpy(ptr, pptr, l); |
231 if (ptr) { |
190 ptr[l] = 0; |
232 memcpy(ptr, pptr, l); |
191 |
233 ptr[l] = 0; |
192 result[i] = sstrn(ptr, l); |
234 |
193 pptr += l + d.length; |
235 result[i] = sstrn(ptr, l); |
|
236 pptr += l + d.length; |
|
237 } else { |
|
238 for (ssize_t j = i-1 ; j >= 0 ; j--) { |
|
239 alfree(allocator, result[j].ptr); |
|
240 } |
|
241 alfree(allocator, result); |
|
242 *n = -2; |
|
243 break; |
|
244 } |
194 } |
245 } |
195 } else { |
246 } else { |
196 *n = -2; |
247 *n = -2; |
197 } |
248 } |
198 |
249 |
229 return sstrdup_a(ucx_default_allocator(), s); |
280 return sstrdup_a(ucx_default_allocator(), s); |
230 } |
281 } |
231 |
282 |
232 sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) { |
283 sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) { |
233 sstr_t newstring; |
284 sstr_t newstring; |
234 newstring.ptr = (char*)allocator->malloc(allocator->pool, s.length + 1); |
285 newstring.ptr = (char*)almalloc(allocator, s.length + 1); |
235 if (newstring.ptr) { |
286 if (newstring.ptr) { |
236 newstring.length = s.length; |
287 newstring.length = s.length; |
237 newstring.ptr[newstring.length] = 0; |
288 newstring.ptr[newstring.length] = 0; |
238 |
289 |
239 memcpy(newstring.ptr, s.ptr, s.length); |
290 memcpy(newstring.ptr, s.ptr, s.length); |
244 return newstring; |
295 return newstring; |
245 } |
296 } |
246 |
297 |
247 sstr_t sstrtrim(sstr_t string) { |
298 sstr_t sstrtrim(sstr_t string) { |
248 sstr_t newstr = string; |
299 sstr_t newstr = string; |
249 if (string.length == 0) { |
300 |
250 return newstr; |
301 while (newstr.length > 0 && isspace(*newstr.ptr)) { |
251 } |
302 newstr.ptr++; |
252 |
303 newstr.length--; |
253 size_t i; |
304 } |
254 for(i=0;i<string.length;i++) { |
305 while (newstr.length > 0 && isspace(newstr.ptr[newstr.length-1])) { |
255 char c = string.ptr[i]; |
306 newstr.length--; |
256 if(c > 32) { |
307 } |
257 break; |
|
258 } |
|
259 } |
|
260 newstr.ptr = &string.ptr[i]; |
|
261 newstr.length = string.length - i; |
|
262 |
|
263 if(newstr.length == 0) { |
|
264 return newstr; |
|
265 } |
|
266 |
|
267 i = newstr.length - 1; |
|
268 for(;;) { |
|
269 char c = newstr.ptr[i]; |
|
270 if(c > 32) { |
|
271 break; |
|
272 } |
|
273 if(i > 0) { |
|
274 i--; |
|
275 } else { |
|
276 break; |
|
277 } |
|
278 } |
|
279 newstr.length = i + 1; |
|
280 |
308 |
281 return newstr; |
309 return newstr; |
282 } |
310 } |
283 |
311 |
284 int sstrprefix(sstr_t string, sstr_t prefix) { |
312 int sstrprefix(sstr_t string, sstr_t prefix) { |
309 } else { |
337 } else { |
310 return memcmp(string.ptr+string.length-suffix.length, |
338 return memcmp(string.ptr+string.length-suffix.length, |
311 suffix.ptr, suffix.length) == 0; |
339 suffix.ptr, suffix.length) == 0; |
312 } |
340 } |
313 } |
341 } |
|
342 |
|
343 sstr_t sstrlower(sstr_t string) { |
|
344 sstr_t ret = sstrdup(string); |
|
345 for (size_t i = 0; i < ret.length ; i++) { |
|
346 ret.ptr[i] = tolower(ret.ptr[i]); |
|
347 } |
|
348 return ret; |
|
349 } |
|
350 |
|
351 sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string) { |
|
352 sstr_t ret = sstrdup_a(allocator, string); |
|
353 for (size_t i = 0; i < ret.length ; i++) { |
|
354 ret.ptr[i] = tolower(ret.ptr[i]); |
|
355 } |
|
356 return ret; |
|
357 } |
|
358 |
|
359 sstr_t sstrupper(sstr_t string) { |
|
360 sstr_t ret = sstrdup(string); |
|
361 for (size_t i = 0; i < ret.length ; i++) { |
|
362 ret.ptr[i] = toupper(ret.ptr[i]); |
|
363 } |
|
364 return ret; |
|
365 } |
|
366 |
|
367 sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string) { |
|
368 sstr_t ret = sstrdup_a(allocator, string); |
|
369 for (size_t i = 0; i < ret.length ; i++) { |
|
370 ret.ptr[i] = toupper(ret.ptr[i]); |
|
371 } |
|
372 return ret; |
|
373 } |