ucx/string.c

changeset 157
0b33b9396851
parent 152
62921b370c60
child 162
18892c0a9adc
equal deleted inserted replaced
156:62f1a55535e7 157:0b33b9396851
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 2016 Olaf Wintermann. All rights reserved. 4 * Copyright 2017 Mike Becker, 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
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "ucx/string.h"
30
31 #include "ucx/allocator.h"
32
29 #include <stdlib.h> 33 #include <stdlib.h>
30 #include <string.h> 34 #include <string.h>
31 #include <stdarg.h> 35 #include <stdarg.h>
32 #include <stdint.h> 36 #include <stdint.h>
33 #include <ctype.h> 37 #include <ctype.h>
34 38
35 #include "string.h"
36 #include "allocator.h"
37
38 sstr_t sstr(char *cstring) { 39 sstr_t sstr(char *cstring) {
39 sstr_t string; 40 sstr_t string;
40 string.ptr = cstring; 41 string.ptr = cstring;
41 string.length = strlen(cstring); 42 string.length = strlen(cstring);
42 return string; 43 return string;
47 string.ptr = cstring; 48 string.ptr = cstring;
48 string.length = length; 49 string.length = length;
49 return string; 50 return string;
50 } 51 }
51 52
52 size_t sstrnlen(size_t n, sstr_t s, ...) { 53 scstr_t scstr(const char *cstring) {
54 scstr_t string;
55 string.ptr = cstring;
56 string.length = strlen(cstring);
57 return string;
58 }
59
60 scstr_t scstrn(const char *cstring, size_t length) {
61 scstr_t string;
62 string.ptr = cstring;
63 string.length = length;
64 return string;
65 }
66
67
68 size_t scstrnlen(size_t n, ...) {
53 va_list ap; 69 va_list ap;
54 size_t size = s.length; 70 va_start(ap, n);
55 va_start(ap, s); 71
56 72 size_t size = 0;
57 for (size_t i = 1 ; i < n ; i++) { 73
58 sstr_t str = va_arg(ap, sstr_t); 74 for (size_t i = 0 ; i < n ; i++) {
75 scstr_t str = va_arg(ap, scstr_t);
76 if(SIZE_MAX - str.length < size) {
77 size = SIZE_MAX;
78 break;
79 }
59 size += str.length; 80 size += str.length;
60 } 81 }
61 va_end(ap); 82 va_end(ap);
62 83
63 return size; 84 return size;
64 } 85 }
65 86
66 static sstr_t sstrvcat_a( 87 static sstr_t sstrvcat_a(
67 UcxAllocator *a, 88 UcxAllocator *a,
68 size_t count, 89 size_t count,
69 sstr_t s1, 90 scstr_t s1,
70 sstr_t s2,
71 va_list ap) { 91 va_list ap) {
72 sstr_t str; 92 sstr_t str;
73 str.ptr = NULL; 93 str.ptr = NULL;
74 str.length = 0; 94 str.length = 0;
75 if(count < 2) { 95 if(count < 2) {
76 return str; 96 return str;
77 } 97 }
78 98
79 sstr_t *strings = (sstr_t*) calloc(count, sizeof(sstr_t)); 99 scstr_t s2 = va_arg (ap, scstr_t);
100
101 if(((size_t)-1) - s1.length < s2.length) {
102 return str;
103 }
104
105 scstr_t *strings = (scstr_t*) calloc(count, sizeof(scstr_t));
80 if(!strings) { 106 if(!strings) {
81 return str; 107 return str;
82 } 108 }
83 109
84 // get all args and overall length 110 // get all args and overall length
85 strings[0] = s1; 111 strings[0] = s1;
86 strings[1] = s2; 112 strings[1] = s2;
87 size_t strlen = s1.length + s2.length; 113 size_t slen = s1.length + s2.length;
114 int error = 0;
88 for (size_t i=2;i<count;i++) { 115 for (size_t i=2;i<count;i++) {
89 sstr_t s = va_arg (ap, sstr_t); 116 scstr_t s = va_arg (ap, scstr_t);
90 strings[i] = s; 117 strings[i] = s;
91 strlen += s.length; 118 if(((size_t)-1) - s.length < slen) {
119 error = 1;
120 break;
121 }
122 slen += s.length;
123 }
124 if(error) {
125 free(strings);
126 return str;
92 } 127 }
93 128
94 // create new string 129 // create new string
95 str.ptr = (char*) almalloc(a, strlen + 1); 130 str.ptr = (char*) almalloc(a, slen + 1);
96 str.length = strlen; 131 str.length = slen;
97 if(!str.ptr) { 132 if(!str.ptr) {
98 free(strings); 133 free(strings);
99 str.length = 0; 134 str.length = 0;
100 return str; 135 return str;
101 } 136 }
102 137
103 // concatenate strings 138 // concatenate strings
104 size_t pos = 0; 139 size_t pos = 0;
105 for (size_t i=0;i<count;i++) { 140 for (size_t i=0;i<count;i++) {
106 sstr_t s = strings[i]; 141 scstr_t s = strings[i];
107 memcpy(str.ptr + pos, s.ptr, s.length); 142 memcpy(str.ptr + pos, s.ptr, s.length);
108 pos += s.length; 143 pos += s.length;
109 } 144 }
110 145
111 str.ptr[str.length] = '\0'; 146 str.ptr[str.length] = '\0';
113 free(strings); 148 free(strings);
114 149
115 return str; 150 return str;
116 } 151 }
117 152
118 sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) { 153 sstr_t scstrcat(size_t count, scstr_t s1, ...) {
119 va_list ap; 154 va_list ap;
120 va_start(ap, s2); 155 va_start(ap, s1);
121 sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap); 156 sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, ap);
122 va_end(ap); 157 va_end(ap);
123 return s; 158 return s;
124 } 159 }
125 160
126 sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) { 161 sstr_t scstrcat_a(UcxAllocator *a, size_t count, scstr_t s1, ...) {
127 va_list ap; 162 va_list ap;
128 va_start(ap, s2); 163 va_start(ap, s1);
129 sstr_t s = sstrvcat_a(a, count, s1, s2, ap); 164 sstr_t s = sstrvcat_a(a, count, s1, ap);
130 va_end(ap); 165 va_end(ap);
131 return s; 166 return s;
132 } 167 }
133 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
134 sstr_t sstrsubs(sstr_t s, size_t start) { 191 sstr_t sstrsubs(sstr_t s, size_t start) {
135 return sstrsubsl (s, start, s.length-start); 192 return sstrsubsl (s, start, s.length-start);
136 } 193 }
137 194
138 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) {
139 sstr_t new_sstr; 196 size_t pos;
140 if (start >= s.length) { 197 sstr_t ret = { NULL, 0 };
141 new_sstr.ptr = NULL; 198 if(ucx_substring(s.length, start, length, &ret.length, &pos)) {
142 new_sstr.length = 0; 199 ret.ptr = s.ptr + pos;
143 } else { 200 }
144 if (length > s.length-start) { 201 return ret;
145 length = s.length-start; 202 }
146 } 203
147 new_sstr.ptr = &s.ptr[start]; 204 scstr_t scstrsubs(scstr_t string, size_t start) {
148 new_sstr.length = length; 205 return scstrsubsl(string, start, string.length-start);
149 } 206 }
150 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 static int ucx_strchr(const char *str, size_t length, int chr, size_t *pos) {
219 for(size_t i=0;i<length;i++) {
220 if(str[i] == chr) {
221 *pos = i;
222 return 1;
223 }
224 }
225 return 0;
226 }
227
228 static int ucx_strrchr(const char *str, size_t length, int chr, size_t *pos) {
229 if(length > 0) {
230 for(size_t i=length ; i>0 ; i--) {
231 if(str[i-1] == chr) {
232 *pos = i-1;
233 return 1;
234 }
235 }
236 }
237 return 0;
151 } 238 }
152 239
153 sstr_t sstrchr(sstr_t s, int c) { 240 sstr_t sstrchr(sstr_t s, int c) {
154 for(size_t i=0;i<s.length;i++) { 241 size_t pos = 0;
155 if(s.ptr[i] == c) { 242 if(ucx_strchr(s.ptr, s.length, c, &pos)) {
156 return sstrsubs(s, i); 243 return sstrsubs(s, pos);
157 } 244 }
158 } 245 return sstrn(NULL, 0);
159 sstr_t n;
160 n.ptr = NULL;
161 n.length = 0;
162 return n;
163 } 246 }
164 247
165 sstr_t sstrrchr(sstr_t s, int c) { 248 sstr_t sstrrchr(sstr_t s, int c) {
166 if (s.length > 0) { 249 size_t pos = 0;
167 for(size_t i=s.length;i>0;i--) { 250 if(ucx_strrchr(s.ptr, s.length, c, &pos)) {
168 if(s.ptr[i-1] == c) { 251 return sstrsubs(s, pos);
169 return sstrsubs(s, i-1); 252 }
170 } 253 return sstrn(NULL, 0);
171 } 254 }
172 } 255
173 sstr_t n; 256 scstr_t scstrchr(scstr_t s, int c) {
174 n.ptr = NULL; 257 size_t pos = 0;
175 n.length = 0; 258 if(ucx_strchr(s.ptr, s.length, c, &pos)) {
176 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);
177 } 270 }
178 271
179 #define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \ 272 #define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \
180 ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index]) 273 ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index])
181 274
182 #define ptable_w(useheap, ptable, index, src) do {\ 275 #define ptable_w(useheap, ptable, index, src) do {\
183 if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\ 276 if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\
184 else ((size_t*)ptable)[index] = src;\ 277 else ((size_t*)ptable)[index] = src;\
185 } while (0); 278 } while (0);
186 279
187 sstr_t sstrstr(sstr_t string, sstr_t match) { 280
188 if (match.length == 0) { 281 static const char* ucx_strstr(
189 return string; 282 const char *str,
190 } 283 size_t length,
191 284 const char *match,
192 /* prepare default return value in case of no match */ 285 size_t matchlen,
193 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;
194 295
195 /* 296 /*
196 * IMPORTANT: 297 * IMPORTANT:
197 * our prefix table contains the prefix length PLUS ONE 298 * our prefix table contains the prefix length PLUS ONE
198 * 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
203 /* static prefix table */ 304 /* static prefix table */
204 static uint8_t s_prefix_table[256]; 305 static uint8_t s_prefix_table[256];
205 306
206 /* check pattern length and use appropriate prefix table */ 307 /* check pattern length and use appropriate prefix table */
207 /* if the pattern exceeds static prefix table, allocate on the heap */ 308 /* if the pattern exceeds static prefix table, allocate on the heap */
208 register int useheap = match.length > 255; 309 register int useheap = matchlen > 255;
209 register void* ptable = useheap ? 310 register void* ptable = useheap ?
210 calloc(match.length+1, sizeof(size_t)): s_prefix_table; 311 calloc(matchlen+1, sizeof(size_t)): s_prefix_table;
211 312
212 /* keep counter in registers */ 313 /* keep counter in registers */
213 register size_t i, j; 314 register size_t i, j;
214 315
215 /* fill prefix table */ 316 /* fill prefix table */
216 i = 0; j = 0; 317 i = 0; j = 0;
217 ptable_w(useheap, ptable, i, j); 318 ptable_w(useheap, ptable, i, j);
218 while (i < match.length) { 319 while (i < matchlen) {
219 while (j >= 1 && match.ptr[j-1] != match.ptr[i]) { 320 while (j >= 1 && match[j-1] != match[i]) {
220 ptable_r(j, useheap, ptable, j-1); 321 ptable_r(j, useheap, ptable, j-1);
221 } 322 }
222 i++; j++; 323 i++; j++;
223 ptable_w(useheap, ptable, i, j); 324 ptable_w(useheap, ptable, i, j);
224 } 325 }
225 326
226 /* search */ 327 /* search */
227 i = 0; j = 1; 328 i = 0; j = 1;
228 while (i < string.length) { 329 while (i < length) {
229 while (j >= 1 && string.ptr[i] != match.ptr[j-1]) { 330 while (j >= 1 && str[i] != match[j-1]) {
230 ptable_r(j, useheap, ptable, j-1); 331 ptable_r(j, useheap, ptable, j-1);
231 } 332 }
232 i++; j++; 333 i++; j++;
233 if (j-1 == match.length) { 334 if (j-1 == matchlen) {
234 size_t start = i - match.length; 335 size_t start = i - matchlen;
235 result.ptr = string.ptr + start; 336 result = str + start;
236 result.length = string.length - start; 337 resultlen = length - start;
237 break; 338 break;
238 } 339 }
239 } 340 }
240 341
241 /* if prefix table was allocated on the heap, free it */ 342 /* if prefix table was allocated on the heap, free it */
242 if (ptable != s_prefix_table) { 343 if (ptable != s_prefix_table) {
243 free(ptable); 344 free(ptable);
244 } 345 }
245 346
347 *newlen = resultlen;
348 return result;
349 }
350
351 sstr_t scstrsstr(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 scstrscstr(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
246 return result; 384 return result;
247 } 385 }
248 386
249 #undef ptable_r 387 #undef ptable_r
250 #undef ptable_w 388 #undef ptable_w
251 389
252 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) { 390 sstr_t* scstrsplit(scstr_t s, scstr_t d, ssize_t *n) {
253 return sstrsplit_a(ucx_default_allocator(), s, d, n); 391 return scstrsplit_a(ucx_default_allocator(), s, d, n);
254 } 392 }
255 393
256 sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) { 394 sstr_t* scstrsplit_a(UcxAllocator *allocator, scstr_t s, scstr_t d, ssize_t *n) {
257 if (s.length == 0 || d.length == 0) { 395 if (s.length == 0 || d.length == 0) {
258 *n = -1; 396 *n = -1;
259 return NULL; 397 return NULL;
260 } 398 }
261 399
266 *n = 0; 404 *n = 0;
267 return NULL; 405 return NULL;
268 } else /* no match possible */ { 406 } else /* no match possible */ {
269 *n = 1; 407 *n = 1;
270 sstr_t *result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)); 408 sstr_t *result = (sstr_t*) almalloc(allocator, sizeof(sstr_t));
271 *result = sstrdup_a(allocator, s); 409 if(result) {
410 *result = sstrdup_a(allocator, s);
411 } else {
412 *n = -2;
413 }
272 return result; 414 return result;
273 } 415 }
274 } 416 }
275 417
276 ssize_t nmax = *n; 418 ssize_t nmax = *n;
277 size_t arrlen = 16; 419 size_t arrlen = 16;
278 sstr_t* result = (sstr_t*) almalloc(allocator, arrlen*sizeof(sstr_t)); 420 sstr_t* result = (sstr_t*) alcalloc(allocator, arrlen, sizeof(sstr_t));
279 421
280 if (result) { 422 if (result) {
281 sstr_t curpos = s; 423 scstr_t curpos = s;
282 ssize_t j = 1; 424 ssize_t j = 1;
283 while (1) { 425 while (1) {
284 sstr_t match; 426 scstr_t match;
285 /* optimize for one byte delimiters */ 427 /* optimize for one byte delimiters */
286 if (d.length == 1) { 428 if (d.length == 1) {
287 match = curpos; 429 match = curpos;
288 for (size_t i = 0 ; i < curpos.length ; i++) { 430 for (size_t i = 0 ; i < curpos.length ; i++) {
289 if (curpos.ptr[i] == *(d.ptr)) { 431 if (curpos.ptr[i] == *(d.ptr)) {
291 break; 433 break;
292 } 434 }
293 match.length--; 435 match.length--;
294 } 436 }
295 } else { 437 } else {
296 match = sstrstr(curpos, d); 438 match = scstrscstr(curpos, d);
297 } 439 }
298 if (match.length > 0) { 440 if (match.length > 0) {
299 /* is this our last try? */ 441 /* is this our last try? */
300 if (nmax == 0 || j < nmax) { 442 if (nmax == 0 || j < nmax) {
301 /* copy the current string to the array */ 443 /* copy the current string to the array */
302 sstr_t item = sstrn(curpos.ptr, match.ptr - curpos.ptr); 444 scstr_t item = scstrn(curpos.ptr, match.ptr - curpos.ptr);
303 result[j-1] = sstrdup_a(allocator, item); 445 result[j-1] = sstrdup_a(allocator, item);
304 size_t processed = item.length + d.length; 446 size_t processed = item.length + d.length;
305 curpos.ptr += processed; 447 curpos.ptr += processed;
306 curpos.length -= processed; 448 curpos.length -= processed;
307 449
308 /* allocate memory for the next string */ 450 /* allocate memory for the next string */
309 j++; 451 j++;
310 if (j > arrlen) { 452 if (j > arrlen) {
311 arrlen *= 2; 453 arrlen *= 2;
312 sstr_t* reallocated = (sstr_t*) alrealloc( 454 size_t reallocsz;
313 allocator, result, arrlen*sizeof(sstr_t)); 455 sstr_t* reallocated = NULL;
456 if(!ucx_szmul(arrlen, sizeof(sstr_t), &reallocsz)) {
457 reallocated = (sstr_t*) alrealloc(
458 allocator, result, reallocsz);
459 }
314 if (reallocated) { 460 if (reallocated) {
315 result = reallocated; 461 result = reallocated;
316 } else { 462 } else {
317 for (ssize_t i = 0 ; i < j-1 ; i++) { 463 for (ssize_t i = 0 ; i < j-1 ; i++) {
318 alfree(allocator, result[i].ptr); 464 alfree(allocator, result[i].ptr);
339 } 485 }
340 486
341 return result; 487 return result;
342 } 488 }
343 489
344 int sstrcmp(sstr_t s1, sstr_t s2) { 490 int scstrcmp(scstr_t s1, scstr_t s2) {
345 if (s1.length == s2.length) { 491 if (s1.length == s2.length) {
346 return memcmp(s1.ptr, s2.ptr, s1.length); 492 return memcmp(s1.ptr, s2.ptr, s1.length);
347 } else if (s1.length > s2.length) { 493 } else if (s1.length > s2.length) {
348 return 1; 494 return 1;
349 } else { 495 } else {
350 return -1; 496 return -1;
351 } 497 }
352 } 498 }
353 499
354 int sstrcasecmp(sstr_t s1, sstr_t s2) { 500 int scstrcasecmp(scstr_t s1, scstr_t s2) {
355 if (s1.length == s2.length) { 501 if (s1.length == s2.length) {
356 #ifdef _WIN32 502 #ifdef _WIN32
357 return _strnicmp(s1.ptr, s2.ptr, s1.length); 503 return _strnicmp(s1.ptr, s2.ptr, s1.length);
358 #else 504 #else
359 return strncasecmp(s1.ptr, s2.ptr, s1.length); 505 return strncasecmp(s1.ptr, s2.ptr, s1.length);
363 } else { 509 } else {
364 return -1; 510 return -1;
365 } 511 }
366 } 512 }
367 513
368 sstr_t sstrdup(sstr_t s) { 514 sstr_t scstrdup(scstr_t s) {
369 return sstrdup_a(ucx_default_allocator(), s); 515 return sstrdup_a(ucx_default_allocator(), s);
370 } 516 }
371 517
372 sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) { 518 sstr_t scstrdup_a(UcxAllocator *allocator, scstr_t s) {
373 sstr_t newstring; 519 sstr_t newstring;
374 newstring.ptr = (char*)almalloc(allocator, s.length + 1); 520 newstring.ptr = (char*)almalloc(allocator, s.length + 1);
375 if (newstring.ptr) { 521 if (newstring.ptr) {
376 newstring.length = s.length; 522 newstring.length = s.length;
377 newstring.ptr[newstring.length] = 0; 523 newstring.ptr[newstring.length] = 0;
382 } 528 }
383 529
384 return newstring; 530 return newstring;
385 } 531 }
386 532
533
534 static size_t ucx_strtrim(const char *s, size_t len, size_t *newlen) {
535 const char *newptr = s;
536 size_t length = len;
537
538 while(length > 0 && isspace(*newptr)) {
539 newptr++;
540 length--;
541 }
542 while(length > 0 && isspace(newptr[length-1])) {
543 length--;
544 }
545
546 *newlen = length;
547 return newptr - s;
548 }
549
387 sstr_t sstrtrim(sstr_t string) { 550 sstr_t sstrtrim(sstr_t string) {
388 sstr_t newstr = string; 551 sstr_t newstr;
389 552 newstr.ptr = string.ptr
390 while (newstr.length > 0 && isspace(*newstr.ptr)) { 553 + ucx_strtrim(string.ptr, string.length, &newstr.length);
391 newstr.ptr++;
392 newstr.length--;
393 }
394 while (newstr.length > 0 && isspace(newstr.ptr[newstr.length-1])) {
395 newstr.length--;
396 }
397
398 return newstr; 554 return newstr;
399 } 555 }
400 556
401 int sstrprefix(sstr_t string, sstr_t prefix) { 557 scstr_t scstrtrim(scstr_t string) {
558 scstr_t newstr;
559 newstr.ptr = string.ptr
560 + ucx_strtrim(string.ptr, string.length, &newstr.length);
561 return newstr;
562 }
563
564 int scstrprefix(scstr_t string, scstr_t prefix) {
402 if (string.length == 0) { 565 if (string.length == 0) {
403 return prefix.length == 0; 566 return prefix.length == 0;
404 } 567 }
405 if (prefix.length == 0) { 568 if (prefix.length == 0) {
406 return 1; 569 return 1;
411 } else { 574 } else {
412 return memcmp(string.ptr, prefix.ptr, prefix.length) == 0; 575 return memcmp(string.ptr, prefix.ptr, prefix.length) == 0;
413 } 576 }
414 } 577 }
415 578
416 int sstrsuffix(sstr_t string, sstr_t suffix) { 579 int scstrsuffix(scstr_t string, scstr_t suffix) {
417 if (string.length == 0) { 580 if (string.length == 0) {
418 return suffix.length == 0; 581 return suffix.length == 0;
419 } 582 }
420 if (suffix.length == 0) { 583 if (suffix.length == 0) {
421 return 1; 584 return 1;
427 return memcmp(string.ptr+string.length-suffix.length, 590 return memcmp(string.ptr+string.length-suffix.length,
428 suffix.ptr, suffix.length) == 0; 591 suffix.ptr, suffix.length) == 0;
429 } 592 }
430 } 593 }
431 594
432 sstr_t sstrlower(sstr_t string) { 595 sstr_t scstrlower(scstr_t string) {
433 sstr_t ret = sstrdup(string); 596 sstr_t ret = sstrdup(string);
434 for (size_t i = 0; i < ret.length ; i++) { 597 for (size_t i = 0; i < ret.length ; i++) {
435 ret.ptr[i] = tolower(ret.ptr[i]); 598 ret.ptr[i] = tolower(ret.ptr[i]);
436 } 599 }
437 return ret; 600 return ret;
438 } 601 }
439 602
440 sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string) { 603 sstr_t scstrlower_a(UcxAllocator *allocator, scstr_t string) {
441 sstr_t ret = sstrdup_a(allocator, string); 604 sstr_t ret = sstrdup_a(allocator, string);
442 for (size_t i = 0; i < ret.length ; i++) { 605 for (size_t i = 0; i < ret.length ; i++) {
443 ret.ptr[i] = tolower(ret.ptr[i]); 606 ret.ptr[i] = tolower(ret.ptr[i]);
444 } 607 }
445 return ret; 608 return ret;
446 } 609 }
447 610
448 sstr_t sstrupper(sstr_t string) { 611 sstr_t scstrupper(scstr_t string) {
449 sstr_t ret = sstrdup(string); 612 sstr_t ret = sstrdup(string);
450 for (size_t i = 0; i < ret.length ; i++) { 613 for (size_t i = 0; i < ret.length ; i++) {
451 ret.ptr[i] = toupper(ret.ptr[i]); 614 ret.ptr[i] = toupper(ret.ptr[i]);
452 } 615 }
453 return ret; 616 return ret;
454 } 617 }
455 618
456 sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string) { 619 sstr_t scstrupper_a(UcxAllocator *allocator, scstr_t string) {
457 sstr_t ret = sstrdup_a(allocator, string); 620 sstr_t ret = sstrdup_a(allocator, string);
458 for (size_t i = 0; i < ret.length ; i++) { 621 for (size_t i = 0; i < ret.length ; i++) {
459 ret.ptr[i] = toupper(ret.ptr[i]); 622 ret.ptr[i] = toupper(ret.ptr[i]);
460 } 623 }
461 return ret; 624 return ret;
462 } 625 }
626
627 // type adjustment functions
628 scstr_t ucx_sc2sc(scstr_t str) {
629 return str;
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 }

mercurial