131 free(strings); |
148 free(strings); |
132 |
149 |
133 return str; |
150 return str; |
134 } |
151 } |
135 |
152 |
136 sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) { |
153 sstr_t ucx_strcat(size_t count, scstr_t s1, ...) { |
137 va_list ap; |
154 va_list ap; |
138 va_start(ap, s2); |
155 va_start(ap, s1); |
139 sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap); |
156 sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, ap); |
140 va_end(ap); |
157 va_end(ap); |
141 return s; |
158 return s; |
142 } |
159 } |
143 |
160 |
144 sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) { |
161 sstr_t ucx_strcat_a(UcxAllocator *a, size_t count, scstr_t s1, ...) { |
145 va_list ap; |
162 va_list ap; |
146 va_start(ap, s2); |
163 va_start(ap, s1); |
147 sstr_t s = sstrvcat_a(a, count, s1, s2, ap); |
164 sstr_t s = sstrvcat_a(a, count, s1, ap); |
148 va_end(ap); |
165 va_end(ap); |
149 return s; |
166 return s; |
150 } |
167 } |
151 |
168 |
|
169 static int ucx_substring( |
|
170 size_t str_length, |
|
171 size_t start, |
|
172 size_t length, |
|
173 size_t *newlen, |
|
174 size_t *newpos) |
|
175 { |
|
176 *newlen = 0; |
|
177 *newpos = 0; |
|
178 |
|
179 if(start > str_length) { |
|
180 return 0; |
|
181 } |
|
182 |
|
183 if(length > str_length - start) { |
|
184 length = str_length - start; |
|
185 } |
|
186 *newlen = length; |
|
187 *newpos = start; |
|
188 return 1; |
|
189 } |
|
190 |
152 sstr_t sstrsubs(sstr_t s, size_t start) { |
191 sstr_t sstrsubs(sstr_t s, size_t start) { |
153 return sstrsubsl (s, start, s.length-start); |
192 return sstrsubsl (s, start, s.length-start); |
154 } |
193 } |
155 |
194 |
156 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) { |
195 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) { |
157 sstr_t new_sstr; |
196 size_t pos; |
158 if (start >= s.length) { |
197 sstr_t ret = { NULL, 0 }; |
159 new_sstr.ptr = NULL; |
198 if(ucx_substring(s.length, start, length, &ret.length, &pos)) { |
160 new_sstr.length = 0; |
199 ret.ptr = s.ptr + pos; |
161 } else { |
200 } |
162 if (length > s.length-start) { |
201 return ret; |
163 length = s.length-start; |
202 } |
164 } |
203 |
165 new_sstr.ptr = &s.ptr[start]; |
204 scstr_t scstrsubs(scstr_t s, size_t start) { |
166 new_sstr.length = length; |
205 return scstrsubsl (s, start, s.length-start); |
167 } |
206 } |
168 return new_sstr; |
207 |
|
208 scstr_t scstrsubsl(scstr_t s, size_t start, size_t length) { |
|
209 size_t pos; |
|
210 scstr_t ret = { NULL, 0 }; |
|
211 if(ucx_substring(s.length, start, length, &ret.length, &pos)) { |
|
212 ret.ptr = s.ptr + pos; |
|
213 } |
|
214 return ret; |
|
215 } |
|
216 |
|
217 |
|
218 int ucx_strchr(const char *string, size_t length, int chr, size_t *pos) { |
|
219 for(size_t i=0;i<length;i++) { |
|
220 if(string[i] == chr) { |
|
221 *pos = i; |
|
222 return 1; |
|
223 } |
|
224 } |
|
225 return 0; |
|
226 } |
|
227 |
|
228 int ucx_strrchr(const char *string, size_t length, int chr, size_t *pos) { |
|
229 if(length > 0) { |
|
230 for(size_t i=length ; i>0 ; i--) { |
|
231 if(string[i-1] == chr) { |
|
232 *pos = i-1; |
|
233 return 1; |
|
234 } |
|
235 } |
|
236 } |
|
237 return 0; |
169 } |
238 } |
170 |
239 |
171 sstr_t sstrchr(sstr_t s, int c) { |
240 sstr_t sstrchr(sstr_t s, int c) { |
172 for(size_t i=0;i<s.length;i++) { |
241 size_t pos = 0; |
173 if(s.ptr[i] == c) { |
242 if(ucx_strchr(s.ptr, s.length, c, &pos)) { |
174 return sstrsubs(s, i); |
243 return sstrsubs(s, pos); |
175 } |
244 } |
176 } |
245 return sstrn(NULL, 0); |
177 sstr_t n; |
|
178 n.ptr = NULL; |
|
179 n.length = 0; |
|
180 return n; |
|
181 } |
246 } |
182 |
247 |
183 sstr_t sstrrchr(sstr_t s, int c) { |
248 sstr_t sstrrchr(sstr_t s, int c) { |
184 if (s.length > 0) { |
249 size_t pos = 0; |
185 for(size_t i=s.length;i>0;i--) { |
250 if(ucx_strrchr(s.ptr, s.length, c, &pos)) { |
186 if(s.ptr[i-1] == c) { |
251 return sstrsubs(s, pos); |
187 return sstrsubs(s, i-1); |
252 } |
188 } |
253 return sstrn(NULL, 0); |
189 } |
254 } |
190 } |
255 |
191 sstr_t n; |
256 scstr_t scstrchr(scstr_t s, int c) { |
192 n.ptr = NULL; |
257 size_t pos = 0; |
193 n.length = 0; |
258 if(ucx_strchr(s.ptr, s.length, c, &pos)) { |
194 return n; |
259 return scstrsubs(s, pos); |
|
260 } |
|
261 return scstrn(NULL, 0); |
|
262 } |
|
263 |
|
264 scstr_t scstrrchr(scstr_t s, int c) { |
|
265 size_t pos = 0; |
|
266 if(ucx_strrchr(s.ptr, s.length, c, &pos)) { |
|
267 return scstrsubs(s, pos); |
|
268 } |
|
269 return scstrn(NULL, 0); |
195 } |
270 } |
196 |
271 |
197 #define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \ |
272 #define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \ |
198 ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index]) |
273 ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index]) |
199 |
274 |
200 #define ptable_w(useheap, ptable, index, src) do {\ |
275 #define ptable_w(useheap, ptable, index, src) do {\ |
201 if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\ |
276 if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\ |
202 else ((size_t*)ptable)[index] = src;\ |
277 else ((size_t*)ptable)[index] = src;\ |
203 } while (0); |
278 } while (0); |
204 |
279 |
205 sstr_t sstrstr(sstr_t string, sstr_t match) { |
280 |
206 if (match.length == 0) { |
281 const char* ucx_strstr( |
207 return string; |
282 const char *str, |
208 } |
283 size_t length, |
209 |
284 const char *match, |
210 /* prepare default return value in case of no match */ |
285 size_t matchlen, |
211 sstr_t result = sstrn(NULL, 0); |
286 size_t *newlen) |
|
287 { |
|
288 *newlen = length; |
|
289 if (matchlen == 0) { |
|
290 return str; |
|
291 } |
|
292 |
|
293 const char *result = NULL; |
|
294 size_t resultlen = 0; |
212 |
295 |
213 /* |
296 /* |
214 * IMPORTANT: |
297 * IMPORTANT: |
215 * our prefix table contains the prefix length PLUS ONE |
298 * our prefix table contains the prefix length PLUS ONE |
216 * this is our decision, because we want to use the full range of size_t |
299 * this is our decision, because we want to use the full range of size_t |
221 /* static prefix table */ |
304 /* static prefix table */ |
222 static uint8_t s_prefix_table[256]; |
305 static uint8_t s_prefix_table[256]; |
223 |
306 |
224 /* check pattern length and use appropriate prefix table */ |
307 /* check pattern length and use appropriate prefix table */ |
225 /* if the pattern exceeds static prefix table, allocate on the heap */ |
308 /* if the pattern exceeds static prefix table, allocate on the heap */ |
226 register int useheap = match.length > 255; |
309 register int useheap = matchlen > 255; |
227 register void* ptable = useheap ? |
310 register void* ptable = useheap ? |
228 calloc(match.length+1, sizeof(size_t)): s_prefix_table; |
311 calloc(matchlen+1, sizeof(size_t)): s_prefix_table; |
229 |
312 |
230 /* keep counter in registers */ |
313 /* keep counter in registers */ |
231 register size_t i, j; |
314 register size_t i, j; |
232 |
315 |
233 /* fill prefix table */ |
316 /* fill prefix table */ |
234 i = 0; j = 0; |
317 i = 0; j = 0; |
235 ptable_w(useheap, ptable, i, j); |
318 ptable_w(useheap, ptable, i, j); |
236 while (i < match.length) { |
319 while (i < matchlen) { |
237 while (j >= 1 && match.ptr[j-1] != match.ptr[i]) { |
320 while (j >= 1 && match[j-1] != match[i]) { |
238 ptable_r(j, useheap, ptable, j-1); |
321 ptable_r(j, useheap, ptable, j-1); |
239 } |
322 } |
240 i++; j++; |
323 i++; j++; |
241 ptable_w(useheap, ptable, i, j); |
324 ptable_w(useheap, ptable, i, j); |
242 } |
325 } |
243 |
326 |
244 /* search */ |
327 /* search */ |
245 i = 0; j = 1; |
328 i = 0; j = 1; |
246 while (i < string.length) { |
329 while (i < length) { |
247 while (j >= 1 && string.ptr[i] != match.ptr[j-1]) { |
330 while (j >= 1 && str[i] != match[j-1]) { |
248 ptable_r(j, useheap, ptable, j-1); |
331 ptable_r(j, useheap, ptable, j-1); |
249 } |
332 } |
250 i++; j++; |
333 i++; j++; |
251 if (j-1 == match.length) { |
334 if (j-1 == matchlen) { |
252 size_t start = i - match.length; |
335 size_t start = i - matchlen; |
253 result.ptr = string.ptr + start; |
336 result = str + start; |
254 result.length = string.length - start; |
337 resultlen = length - start; |
255 break; |
338 break; |
256 } |
339 } |
257 } |
340 } |
258 |
341 |
259 /* if prefix table was allocated on the heap, free it */ |
342 /* if prefix table was allocated on the heap, free it */ |
260 if (ptable != s_prefix_table) { |
343 if (ptable != s_prefix_table) { |
261 free(ptable); |
344 free(ptable); |
262 } |
345 } |
263 |
346 |
|
347 *newlen = resultlen; |
|
348 return result; |
|
349 } |
|
350 |
|
351 sstr_t ucx_sstrstr(sstr_t string, scstr_t match) { |
|
352 sstr_t result; |
|
353 |
|
354 size_t reslen; |
|
355 const char *resstr = ucx_strstr(string.ptr, string.length, match.ptr, match.length, &reslen); |
|
356 if(!resstr) { |
|
357 result.ptr = NULL; |
|
358 result.length = 0; |
|
359 return result; |
|
360 } |
|
361 |
|
362 size_t pos = resstr - string.ptr; |
|
363 result.ptr = string.ptr + pos; |
|
364 result.length = reslen; |
|
365 |
|
366 return result; |
|
367 } |
|
368 |
|
369 scstr_t ucx_scstrstr(scstr_t string, scstr_t match) { |
|
370 scstr_t result; |
|
371 |
|
372 size_t reslen; |
|
373 const char *resstr = ucx_strstr(string.ptr, string.length, match.ptr, match.length, &reslen); |
|
374 if(!resstr) { |
|
375 result.ptr = NULL; |
|
376 result.length = 0; |
|
377 return result; |
|
378 } |
|
379 |
|
380 size_t pos = resstr - string.ptr; |
|
381 result.ptr = string.ptr + pos; |
|
382 result.length = reslen; |
|
383 |
264 return result; |
384 return result; |
265 } |
385 } |
266 |
386 |
267 #undef ptable_r |
387 #undef ptable_r |
268 #undef ptable_w |
388 #undef ptable_w |
269 |
389 |
270 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) { |
390 sstr_t* ucx_strsplit(scstr_t s, scstr_t d, ssize_t *n) { |
271 return sstrsplit_a(ucx_default_allocator(), s, d, n); |
391 return ucx_strsplit_a(ucx_default_allocator(), s, d, n); |
272 } |
392 } |
273 |
393 |
274 sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) { |
394 sstr_t* ucx_strsplit_a(UcxAllocator *allocator, scstr_t s, scstr_t d, ssize_t *n) { |
275 if (s.length == 0 || d.length == 0) { |
395 if (s.length == 0 || d.length == 0) { |
276 *n = -1; |
396 *n = -1; |
277 return NULL; |
397 return NULL; |
278 } |
398 } |
279 |
399 |
453 return memcmp(string.ptr+string.length-suffix.length, |
590 return memcmp(string.ptr+string.length-suffix.length, |
454 suffix.ptr, suffix.length) == 0; |
591 suffix.ptr, suffix.length) == 0; |
455 } |
592 } |
456 } |
593 } |
457 |
594 |
458 sstr_t sstrlower(sstr_t string) { |
595 sstr_t ucx_strlower(scstr_t string) { |
459 sstr_t ret = sstrdup(string); |
596 sstr_t ret = sstrdup(string); |
460 for (size_t i = 0; i < ret.length ; i++) { |
597 for (size_t i = 0; i < ret.length ; i++) { |
461 ret.ptr[i] = tolower(ret.ptr[i]); |
598 ret.ptr[i] = tolower(ret.ptr[i]); |
462 } |
599 } |
463 return ret; |
600 return ret; |
464 } |
601 } |
465 |
602 |
466 sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string) { |
603 sstr_t ucx_strlower_a(UcxAllocator *allocator, scstr_t string) { |
467 sstr_t ret = sstrdup_a(allocator, string); |
604 sstr_t ret = sstrdup_a(allocator, string); |
468 for (size_t i = 0; i < ret.length ; i++) { |
605 for (size_t i = 0; i < ret.length ; i++) { |
469 ret.ptr[i] = tolower(ret.ptr[i]); |
606 ret.ptr[i] = tolower(ret.ptr[i]); |
470 } |
607 } |
471 return ret; |
608 return ret; |
472 } |
609 } |
473 |
610 |
474 sstr_t sstrupper(sstr_t string) { |
611 sstr_t ucx_strupper(scstr_t string) { |
475 sstr_t ret = sstrdup(string); |
612 sstr_t ret = sstrdup(string); |
476 for (size_t i = 0; i < ret.length ; i++) { |
613 for (size_t i = 0; i < ret.length ; i++) { |
477 ret.ptr[i] = toupper(ret.ptr[i]); |
614 ret.ptr[i] = toupper(ret.ptr[i]); |
478 } |
615 } |
479 return ret; |
616 return ret; |
480 } |
617 } |
481 |
618 |
482 sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string) { |
619 sstr_t ucx_strupper_a(UcxAllocator *allocator, scstr_t string) { |
483 sstr_t ret = sstrdup_a(allocator, string); |
620 sstr_t ret = sstrdup_a(allocator, string); |
484 for (size_t i = 0; i < ret.length ; i++) { |
621 for (size_t i = 0; i < ret.length ; i++) { |
485 ret.ptr[i] = toupper(ret.ptr[i]); |
622 ret.ptr[i] = toupper(ret.ptr[i]); |
486 } |
623 } |
487 return ret; |
624 return ret; |
488 } |
625 } |
|
626 |
|
627 // private string conversion functions |
|
628 scstr_t ucx_sc2sc(scstr_t c) { |
|
629 return c; |
|
630 } |
|
631 scstr_t ucx_ss2sc(sstr_t str) { |
|
632 scstr_t cs; |
|
633 cs.ptr = str.ptr; |
|
634 cs.length = str.length; |
|
635 return cs; |
|
636 } |
|
637 scstr_t ucx_ss2c_s(scstr_t c) { |
|
638 return c; |
|
639 } |