215 #define ptable_w(useheap, ptable, index, src) do {\ |
215 #define ptable_w(useheap, ptable, index, src) do {\ |
216 if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\ |
216 if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\ |
217 else ((size_t*)ptable)[index] = src;\ |
217 else ((size_t*)ptable)[index] = src;\ |
218 } while (0); |
218 } while (0); |
219 |
219 |
220 sstr_t sstrstr(sstr_t string, sstr_t match) { |
220 |
221 if (match.length == 0) { |
221 const char* ucx_strstr( |
222 return string; |
222 const char *str, |
223 } |
223 size_t length, |
224 |
224 const char *match, |
225 /* prepare default return value in case of no match */ |
225 size_t matchlen, |
226 sstr_t result = sstrn(NULL, 0); |
226 size_t *newlen) |
|
227 { |
|
228 *newlen = length; |
|
229 if (matchlen == 0) { |
|
230 return str; |
|
231 } |
|
232 |
|
233 const char *result = NULL; |
|
234 size_t resultlen = 0; |
227 |
235 |
228 /* |
236 /* |
229 * IMPORTANT: |
237 * IMPORTANT: |
230 * our prefix table contains the prefix length PLUS ONE |
238 * our prefix table contains the prefix length PLUS ONE |
231 * this is our decision, because we want to use the full range of size_t |
239 * this is our decision, because we want to use the full range of size_t |
236 /* static prefix table */ |
244 /* static prefix table */ |
237 static uint8_t s_prefix_table[256]; |
245 static uint8_t s_prefix_table[256]; |
238 |
246 |
239 /* check pattern length and use appropriate prefix table */ |
247 /* check pattern length and use appropriate prefix table */ |
240 /* if the pattern exceeds static prefix table, allocate on the heap */ |
248 /* if the pattern exceeds static prefix table, allocate on the heap */ |
241 register int useheap = match.length > 255; |
249 register int useheap = matchlen > 255; |
242 register void* ptable = useheap ? |
250 register void* ptable = useheap ? |
243 calloc(match.length+1, sizeof(size_t)): s_prefix_table; |
251 calloc(matchlen+1, sizeof(size_t)): s_prefix_table; |
244 |
252 |
245 /* keep counter in registers */ |
253 /* keep counter in registers */ |
246 register size_t i, j; |
254 register size_t i, j; |
247 |
255 |
248 /* fill prefix table */ |
256 /* fill prefix table */ |
249 i = 0; j = 0; |
257 i = 0; j = 0; |
250 ptable_w(useheap, ptable, i, j); |
258 ptable_w(useheap, ptable, i, j); |
251 while (i < match.length) { |
259 while (i < matchlen) { |
252 while (j >= 1 && match.ptr[j-1] != match.ptr[i]) { |
260 while (j >= 1 && match[j-1] != match[i]) { |
253 ptable_r(j, useheap, ptable, j-1); |
261 ptable_r(j, useheap, ptable, j-1); |
254 } |
262 } |
255 i++; j++; |
263 i++; j++; |
256 ptable_w(useheap, ptable, i, j); |
264 ptable_w(useheap, ptable, i, j); |
257 } |
265 } |
258 |
266 |
259 /* search */ |
267 /* search */ |
260 i = 0; j = 1; |
268 i = 0; j = 1; |
261 while (i < string.length) { |
269 while (i < length) { |
262 while (j >= 1 && string.ptr[i] != match.ptr[j-1]) { |
270 while (j >= 1 && str[i] != match[j-1]) { |
263 ptable_r(j, useheap, ptable, j-1); |
271 ptable_r(j, useheap, ptable, j-1); |
264 } |
272 } |
265 i++; j++; |
273 i++; j++; |
266 if (j-1 == match.length) { |
274 if (j-1 == matchlen) { |
267 size_t start = i - match.length; |
275 size_t start = i - matchlen; |
268 result.ptr = string.ptr + start; |
276 result = str + start; |
269 result.length = string.length - start; |
277 resultlen = length - start; |
270 break; |
278 break; |
271 } |
279 } |
272 } |
280 } |
273 |
281 |
274 /* if prefix table was allocated on the heap, free it */ |
282 /* if prefix table was allocated on the heap, free it */ |
275 if (ptable != s_prefix_table) { |
283 if (ptable != s_prefix_table) { |
276 free(ptable); |
284 free(ptable); |
277 } |
285 } |
278 |
286 |
|
287 *newlen = resultlen; |
|
288 return result; |
|
289 } |
|
290 |
|
291 sstr_t ucx_sstrstr(sstr_t string, scstr_t match) { |
|
292 sstr_t result; |
|
293 |
|
294 size_t reslen; |
|
295 const char *resstr = ucx_strstr(string.ptr, string.length, match.ptr, match.length, &reslen); |
|
296 if(!resstr) { |
|
297 result.ptr = NULL; |
|
298 result.length = 0; |
|
299 return result; |
|
300 } |
|
301 |
|
302 size_t pos = resstr - string.ptr; |
|
303 result.ptr = string.ptr + pos; |
|
304 result.length = reslen; |
|
305 |
|
306 return result; |
|
307 } |
|
308 |
|
309 scstr_t ucx_scstrstr(scstr_t string, scstr_t match) { |
|
310 scstr_t result; |
|
311 |
|
312 size_t reslen; |
|
313 const char *resstr = ucx_strstr(string.ptr, string.length, match.ptr, match.length, &reslen); |
|
314 if(!resstr) { |
|
315 result.ptr = NULL; |
|
316 result.length = 0; |
|
317 return result; |
|
318 } |
|
319 |
|
320 size_t pos = resstr - string.ptr; |
|
321 result.ptr = string.ptr + pos; |
|
322 result.length = reslen; |
|
323 |
279 return result; |
324 return result; |
280 } |
325 } |
281 |
326 |
282 #undef ptable_r |
327 #undef ptable_r |
283 #undef ptable_w |
328 #undef ptable_w |
284 |
329 |
285 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) { |
330 sstr_t* ucx_strsplit(scstr_t s, scstr_t d, ssize_t *n) { |
286 return sstrsplit_a(ucx_default_allocator(), s, d, n); |
331 return ucx_strsplit_a(ucx_default_allocator(), s, d, n); |
287 } |
332 } |
288 |
333 |
289 sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) { |
334 sstr_t* ucx_strsplit_a(UcxAllocator *allocator, scstr_t s, scstr_t d, ssize_t *n) { |
290 if (s.length == 0 || d.length == 0) { |
335 if (s.length == 0 || d.length == 0) { |
291 *n = -1; |
336 *n = -1; |
292 return NULL; |
337 return NULL; |
293 } |
338 } |
294 |
339 |
328 break; |
373 break; |
329 } |
374 } |
330 match.length--; |
375 match.length--; |
331 } |
376 } |
332 } else { |
377 } else { |
333 match = sstrstr(curpos, d); |
378 match = scstrstr(curpos, d); |
334 } |
379 } |
335 if (match.length > 0) { |
380 if (match.length > 0) { |
336 /* is this our last try? */ |
381 /* is this our last try? */ |
337 if (nmax == 0 || j < nmax) { |
382 if (nmax == 0 || j < nmax) { |
338 /* copy the current string to the array */ |
383 /* copy the current string to the array */ |
339 sstr_t item = sstrn(curpos.ptr, match.ptr - curpos.ptr); |
384 scstr_t item = scstrn(curpos.ptr, match.ptr - curpos.ptr); |
340 result[j-1] = sstrdup_a(allocator, item); |
385 result[j-1] = sstrdup_a(allocator, item); |
341 size_t processed = item.length + d.length; |
386 size_t processed = item.length + d.length; |
342 curpos.ptr += processed; |
387 curpos.ptr += processed; |
343 curpos.length -= processed; |
388 curpos.length -= processed; |
344 |
389 |
380 } |
425 } |
381 |
426 |
382 return result; |
427 return result; |
383 } |
428 } |
384 |
429 |
385 int sstrcmp(sstr_t s1, sstr_t s2) { |
430 int ucx_str_cmp(scstr_t s1, scstr_t s2) { |
386 if (s1.length == s2.length) { |
431 if (s1.length == s2.length) { |
387 return memcmp(s1.ptr, s2.ptr, s1.length); |
432 return memcmp(s1.ptr, s2.ptr, s1.length); |
388 } else if (s1.length > s2.length) { |
433 } else if (s1.length > s2.length) { |
389 return 1; |
434 return 1; |
390 } else { |
435 } else { |
391 return -1; |
436 return -1; |
392 } |
437 } |
393 } |
438 } |
394 |
439 |
395 int sstrcasecmp(sstr_t s1, sstr_t s2) { |
440 int ucx_str_casecmp(scstr_t s1, scstr_t s2) { |
396 if (s1.length == s2.length) { |
441 if (s1.length == s2.length) { |
397 #ifdef _WIN32 |
442 #ifdef _WIN32 |
398 return _strnicmp(s1.ptr, s2.ptr, s1.length); |
443 return _strnicmp(s1.ptr, s2.ptr, s1.length); |
399 #else |
444 #else |
400 return strncasecmp(s1.ptr, s2.ptr, s1.length); |
445 return strncasecmp(s1.ptr, s2.ptr, s1.length); |
423 } |
468 } |
424 |
469 |
425 return newstring; |
470 return newstring; |
426 } |
471 } |
427 |
472 |
|
473 |
|
474 size_t ucx_strtrim(const char *s, size_t len, size_t *newlen) { |
|
475 const char *newptr = s; |
|
476 size_t length = len; |
|
477 |
|
478 while(length > 0 && isspace(*newptr)) { |
|
479 newptr++; |
|
480 length--; |
|
481 } |
|
482 while(length > 0 && isspace(newptr[length-1])) { |
|
483 length--; |
|
484 } |
|
485 |
|
486 *newlen = length; |
|
487 return newptr - s; |
|
488 } |
|
489 |
428 sstr_t sstrtrim(sstr_t string) { |
490 sstr_t sstrtrim(sstr_t string) { |
429 sstr_t newstr = string; |
491 sstr_t newstr; |
430 |
492 newstr.ptr = string.ptr |
431 while (newstr.length > 0 && isspace(*newstr.ptr)) { |
493 + ucx_strtrim(string.ptr, string.length, &newstr.length); |
432 newstr.ptr++; |
494 return newstr; |
433 newstr.length--; |
495 } |
434 } |
496 |
435 while (newstr.length > 0 && isspace(newstr.ptr[newstr.length-1])) { |
497 scstr_t scstrtrim(scstr_t string) { |
436 newstr.length--; |
498 scstr_t newstr; |
437 } |
499 newstr.ptr = string.ptr |
438 |
500 + ucx_strtrim(string.ptr, string.length, &newstr.length); |
439 return newstr; |
501 return newstr; |
440 } |
502 } |
441 |
503 |
442 int ucx_strprefix(scstr_t string, scstr_t prefix) { |
504 int ucx_strprefix(scstr_t string, scstr_t prefix) { |
443 if (string.length == 0) { |
505 if (string.length == 0) { |