source: trunk/src/sh_string.c@ 582

Last change on this file since 582 was 516, checked in by katerina, 8 years ago

Fix for ticket #409 and #410 (unprivileged suidcheck and gcc 6.2 compiler warnings).

File size: 25.7 KB
Line 
1
2#include "config_xor.h"
3
4#include <string.h>
5#include <stdio.h>
6#include <sys/types.h>
7
8#include "sh_string.h"
9#include "sh_mem.h"
10
11#undef FIL__
12#define FIL__ _("sh_string.c")
13
14extern int sl_ok_adds (size_t a, size_t b);
15#define S_TRUE 1
16#define S_FALSE 0
17
18#include <ctype.h>
19#include <errno.h>
20
21/* Split array at delim in at most nfields fields.
22 * Empty fields are returned as empty (zero-length) strings.
23 * Leading and trailing WS are removed from token.
24 * The number of fields is returned in 'nfields', their
25 * lengths in 'lengths'.
26 * A single delimiter will return two empty fields.
27 */
28char ** split_array(char *line, unsigned int * nfields,
29 char delim, size_t * lengths)
30{
31 char *a, *e, *s;
32 unsigned int i = 0;
33 int flag = 0;
34 char **arr;
35 unsigned int maxfields = (*nfields);
36
37 arr = SH_ALLOC((maxfields+1) * sizeof (char*));
38
39 e = line;
40
41 do
42 {
43 /* skip leading WS
44 */
45 for (s=e; *s && isspace((int)*s); ++s) /* nothing */;
46
47 if (*s)
48 {
49 /* move a to next delim
50 */
51 for (a=s; *a && *a != delim; ++a) /* nothing */;
52
53 /* set e to next after delim
54 */
55 if (*a == delim)
56 {
57 e = a+1;
58 flag = 1;
59 }
60 else /* (!*a) */
61 {
62 e = a;
63 flag = 0;
64 }
65
66 if (a != line)
67 {
68 if (i < (maxfields -1))
69 {
70
71 /* chop off trailing WS
72 */
73 for (a--; isspace((int)*a) && a > s; a--) /* do nothing */;
74
75 /* terminate string
76 */
77 ++a; *a = '\0';
78 }
79 else
80 {
81 /* If nfields < actual fields, last string
82 * will be remainder, therefore skip to end.
83 */
84 if ( *a )
85 {
86 do {
87 a++;
88 } while ( *a );
89 }
90 }
91 }
92 else
93 {
94 *a = '\0';
95 }
96 }
97 else /* (!*s) */
98 {
99 a = s;
100 /* (i == 0) handles the special case of splitting the empty string */
101 if (flag || i == 0)
102 {
103 flag = 0;
104 goto setnext;
105 }
106 break;
107 }
108
109 setnext:
110 lengths[i] = (size_t) (a-s); /* a >= s always */
111 arr[i] = s;
112 ++i;
113
114 } while (i < maxfields);
115
116 *nfields = i;
117 arr[i] = NULL;
118
119 return arr;
120}
121
122/* Split array at whitespace in at most nfields fields.
123 * Multiple whitespaces are collapsed.
124 * Empty fields are returned as empty (zero-length) strings.
125 * The number of fields is returned in nfields.
126 * An empty string will return zero fields.
127 * If nfields < actual fields, last string will be remainder.
128 */
129
130#define SH_SPLIT_LIST 0
131#define SH_SPLIT_WS 1
132
133char ** split_array_ws_int (char *line,
134 unsigned int * nfields, size_t * lengths,
135 const char *delim, int isList)
136{
137 char *a, *e, *s;
138 unsigned int i = 0;
139 char **arr;
140 unsigned int maxfields = (*nfields);
141
142 arr = SH_ALLOC((maxfields+1) * sizeof (char*));
143
144 e = line;
145
146 do
147 {
148 s = e;
149
150 /* skip leading WS
151 */
152 if (isList == SH_SPLIT_WS)
153 {
154 if ( *s && isspace((int)*s) )
155 {
156 do {
157 ++s;
158 } while ( *s && isspace((int)*s) );
159 }
160 }
161 else
162 {
163 if ( *s && strchr(delim, (int)*s))
164 {
165 do {
166 ++s;
167 } while ( *s && strchr(delim, (int)*s));
168 }
169
170 }
171
172 if (*s)
173 {
174
175 /* s is at non-ws, move a to next ws
176 */
177 a = s;
178 if (isList == SH_SPLIT_WS)
179 {
180 do {
181 a++;
182 } while ( *a && (!isspace((int)*a)) );
183 }
184 else
185 {
186 do {
187 a++;
188 } while ( *a && NULL == strchr(delim, (int)*a));
189 }
190
191 /* next token, *a is either ws or '\0'
192 */
193 e = ( (*a) ? a+1 : a);
194
195 /* terminate and set arr[i]
196 */
197 if (i < (maxfields-1))
198 {
199 *a = '\0';
200 }
201 else
202 {
203 /* If nfields < actual fields, last
204 * string will be remainder. Therefore
205 * skip to end.
206 */
207 if ( *a )
208 {
209 do {
210 a++;
211 } while ( *a );
212 }
213 }
214 lengths[i] = (size_t)(a-s); /* a >= s always */
215 arr[i] = s;
216 ++i;
217 }
218 else /* if (!*s) */
219 {
220 break;
221 }
222
223 } while (i < maxfields);
224
225 *nfields = i;
226 arr[i] = NULL;
227
228 return arr;
229}
230
231char ** split_array_ws (char *line,
232 unsigned int * nfields, size_t * lengths)
233{
234 return split_array_ws_int (line, nfields, lengths, NULL, SH_SPLIT_WS);
235}
236
237char ** split_array_list (char *line,
238 unsigned int * nfields, size_t * lengths)
239{
240 return split_array_ws_int (line, nfields, lengths, ", \t", SH_SPLIT_LIST);
241}
242
243char ** split_array_token (char *line,
244 unsigned int * nfields, size_t * lengths,
245 const char * token)
246{
247 return split_array_ws_int (line, nfields, lengths, token, SH_SPLIT_LIST);
248}
249
250/* return a split() of a list contained in 'PREFIX\s*( list ).*'
251 */
252char ** split_array_braced (char *line, const char * prefix,
253 unsigned int * nfields, size_t * lengths)
254{
255 char * s = line;
256 char * p;
257 unsigned int sind = (prefix) ? strlen(prefix) : 0;
258
259 while ( *s && isspace((int)*s) ) ++s;
260 if (prefix && 0 != strncmp(s, prefix, strlen(prefix)))
261 return NULL;
262 s = &s[sind];
263 while ( *s && isspace((int)*s) ) ++s;
264 if (!s || (*s != '('))
265 return NULL;
266 ++s;
267 p = strchr(s, ')');
268 if (!p || (*p == *s))
269 return NULL;
270 *p = '\0';
271 return split_array_list (s, nfields, lengths);
272}
273
274#define SH_STRING_PARCEL 120
275
276static
277size_t sh_string_read_int(sh_string * s, FILE * fp, size_t maxlen, char *start);
278
279size_t sh_string_read(sh_string * s, FILE * fp, size_t maxlen)
280{
281 return sh_string_read_int(s, fp, maxlen, NULL);
282}
283
284size_t sh_string_read_cont(sh_string * s, FILE * fp, size_t maxlen, char *cont)
285{
286 return sh_string_read_int(s, fp, maxlen, cont);
287}
288
289static char * sh_str_fgets (char *s, int size, FILE *fp)
290{
291 char * ret;
292 do {
293 clearerr(fp);
294 ret = fgets(s, size, fp);
295 } while (ret == NULL && ferror(fp) && errno == EAGAIN);
296
297 return ret;
298}
299
300size_t sh_string_read_int(sh_string * s, FILE * fp, size_t maxlen, char *start)
301{
302
303 /* case 0) start != NULL and first char not in 'start'
304 */
305 if (start)
306 {
307 int first;
308
309 do {
310 clearerr(fp);
311 first = fgetc(fp);
312 } while (first == EOF && ferror(fp) && errno == EAGAIN);
313
314 if (first == EOF)
315 {
316 sh_string_truncate(s, 0);
317 if (ferror(fp))
318 return -1;
319 return 0;
320 }
321
322 if (NULL == strchr(start, first))
323 {
324 ungetc(first, fp);
325 return 0;
326 }
327 ungetc(first, fp);
328 }
329
330 /* case 1) EOF or error
331 */
332 if (sh_str_fgets(s->str, s->siz, fp) == NULL)
333 {
334 sh_string_truncate(s, 0);
335 if (ferror(fp))
336 return -1;
337 return 0;
338 }
339
340 /* case 2) end of line reached. strlen should always be > 0
341 * because of the '\n', but we check.
342 */
343 s->len = strlen(s->str);
344 if (s->len > 0 && (s->str)[s->len-1] == '\n')
345 {
346 (s->str)[s->len-1] = '\0';
347 --(s->len);
348 return (s->len + 1);
349 }
350
351 /* case 3) incomplete string
352 */
353 for (;;) {
354
355 if (maxlen > 0 && (s->siz+SH_STRING_PARCEL) > maxlen)
356 {
357 if (s->siz < maxlen)
358 sh_string_grow(s, (maxlen-s->siz));
359 else
360 return -2;
361 }
362 else
363 {
364 sh_string_grow(s, 0);
365 }
366
367 if (sh_str_fgets(&(s->str[s->len]), (s->siz - s->len), fp) == NULL)
368 {
369 if (ferror(fp))
370 {
371 sh_string_truncate(s, 0);
372 return -1;
373 }
374 return s->len;
375 }
376
377 s->len += strlen( &(s->str[s->len]) );
378 if (s->len > 0 && s->str[s->len-1] == '\n')
379 {
380 (s->str)[s->len-1] = '\0';
381 --(s->len);
382 return (s->len + 1);
383 }
384 }
385
386 /* notreached */
387}
388
389sh_string * sh_string_cat_lchar(sh_string * s, const char * str, size_t len)
390{
391 if (sl_ok_adds(len, s->siz) == S_TRUE)
392 {
393 if ((len + 1 + s->len) > s->siz)
394 {
395 sh_string_grow(s, ((len+1+s->len) - s->siz) );
396 }
397 memcpy(&(s->str[s->len]), str, len);
398 s->len += len;
399 s->str[s->len] = '\0';
400 return s;
401 }
402
403 return NULL;
404}
405
406sh_string * sh_string_set_from_char(sh_string * s, const char * str)
407{
408 size_t len = strlen(str);
409
410 if ((len+1) > s->siz)
411 {
412 sh_string_grow(s, ((len+1) - s->siz) );
413 }
414 memcpy(s->str, str, (len+1));
415 s->len = len;
416 return s;
417}
418
419sh_string * sh_string_add_from_char(sh_string * s, const char * str)
420{
421 size_t len = strlen(str);
422 size_t avail = (s->siz - s->len);
423
424 if ((len+1) > avail)
425 {
426 (void) sh_string_grow(s, ((len+1) - avail) );
427 }
428 memcpy(&(s->str[s->len]), str, (len+1));
429 s->len += len;
430 return s;
431}
432
433sh_string * sh_string_new_from_lchar(const char * str, size_t len)
434{
435 sh_string * s;
436 s = SH_ALLOC(sizeof(sh_string));
437 s->str = SH_ALLOC(len+1);
438 if (str)
439 memcpy(s->str, str, len);
440 else
441 s->str[0] = '\0';
442 s->str[len] = '\0';
443 s->siz = len+1;
444 s->len = len;
445 return s;
446}
447
448sh_string * sh_string_new_from_lchar3(const char * str1, size_t len1,
449 const char * str2, size_t len2,
450 const char * str3, size_t len3)
451{
452 sh_string * s;
453 size_t len = 0;
454
455 if (sl_ok_adds(len1, len2) == S_TRUE)
456 len = len1 + len2;
457 else
458 return NULL;
459 if (sl_ok_adds( len, len3) == S_TRUE)
460 len = len + len3;
461 else
462 return NULL;
463
464 s = SH_ALLOC(sizeof(sh_string));
465 s->str = SH_ALLOC(len+1);
466
467 memcpy(s->str, str1, len1);
468 memcpy(&s->str[len1], str2, len2);
469 memcpy(&s->str[len1+len2], str3, len3);
470
471 s->str[len] = '\0';
472 s->siz = len+1;
473 s->len = len;
474 return s;
475}
476
477sh_string * sh_string_grow(sh_string * s, size_t increase)
478{
479 char * new;
480
481 if (increase == 0)
482 increase = SH_STRING_PARCEL;
483
484 if (s && sl_ok_adds(s->siz, increase) == S_TRUE)
485 {
486 new = SH_ALLOC(s->siz + increase);
487
488 if (s->str)
489 {
490 memcpy(new, s->str, s->len+1);
491 SH_FREE(s->str);
492 }
493 else
494 {
495 new[0] = '\0';
496 }
497 s->str = new;
498 s->siz += increase;
499 return s;
500 }
501 return NULL;
502}
503
504sh_string * sh_string_truncate(sh_string * s, size_t len)
505{
506 if (s)
507 {
508 if (s->str && (s->len > len) )
509 {
510 s->len = len;
511 (s->str)[len] = '\0';
512 }
513 return s;
514 }
515 return NULL;
516}
517
518void sh_string_destroy(sh_string ** s)
519{
520 if (s)
521 {
522 if ((*s) && (*s)->str)
523 SH_FREE ((*s)->str);
524 SH_FREE(*s);
525 *s = NULL;
526 }
527 return;
528}
529
530sh_string * sh_string_new(size_t size)
531{
532 sh_string * s;
533 s = SH_ALLOC (sizeof(sh_string));
534 if (size == 0)
535 size = SH_STRING_PARCEL;
536 s->str = SH_ALLOC (size);
537 s->str[0] = '\0';
538 s->siz = size;
539 s->len = 0;
540 return s;
541}
542
543/* Replaces fields in s with 'replacement'. Fields are given
544 * in the ordered array ovector, comprising ovecnum pairs
545 * ovector[i], ovector[i+1] which list offset of first char
546 * of field, offset of first char after field (this is how
547 * the pcre library does it).
548 */
549sh_string * sh_string_replace(const sh_string * s,
550 const int * ovector, int ovecnum,
551 const char * replacement, size_t rlen)
552{
553 sh_string * r = NULL;
554 char * p;
555 long tlen;
556 size_t len;
557 int end = 0;
558 int start = 0;
559 size_t oldlen = 0;
560 size_t newlen = 0;
561 long diff;
562 int i, curr, last;
563
564 for (i = 0; i < ovecnum; ++i)
565 {
566 start = ovector[2*i]; /* offset of first char of substring */
567 if (start >= end)
568 {
569 end = ovector[2*i+1]; /* offset of first char after substring end*/
570
571 if (end > start && (unsigned int)end <= (s->len + 1))
572 {
573 oldlen += (end - start);
574 newlen += rlen;
575 }
576 else /* inconsistency detected */
577 {
578 return NULL;
579 }
580 }
581 else /* overlap detected */
582 {
583 return NULL;
584 }
585 }
586
587 diff = newlen - oldlen;
588
589 if ((diff > 0) && ((s->len + 1 + diff) > s->siz))
590 {
591 r = sh_string_new_from_lchar(sh_string_str(s),
592 sh_string_len(s));
593 r = sh_string_grow(r, diff);
594 }
595 else
596 {
597 r = sh_string_new_from_lchar(sh_string_str(s),
598 sh_string_len(s));
599 }
600
601
602 curr = -1;
603
604 for (i = 0; i < ovecnum; ++i)
605 {
606 if (ovector[2*i] >= 0)
607 {
608 curr = 2*i;
609 break;
610 }
611 }
612
613 if (r && ovecnum > 0 && ovector[curr] >= 0)
614 {
615 r->len = 0; r->str[0] = '\0'; p = r->str;
616
617 /* First part, until start of first replacement
618 */
619 if (r->siz > (unsigned int)ovector[curr]) {
620 memcpy(p, s->str, (size_t)ovector[curr]);
621 p += ovector[curr];
622 r->len += ovector[curr];
623 }
624 if (r->siz > (r->len + rlen)) {
625 memcpy(p, replacement, rlen);
626 p += rlen;
627 r->len += rlen;
628 }
629 *p = '\0';
630
631 last = curr + 1;
632
633 for (i = 1; i < ovecnum; ++i)
634 {
635 if (ovector[2*i] < 0)
636 continue;
637
638 curr = 2*i;
639
640 /* From end of last replacement to start of this */
641 tlen = (long)(ovector[curr] - ovector[last]);
642 if (tlen >= 0)
643 {
644 len = (size_t) tlen;
645
646 if (tlen > 0 && r->siz > (r->len + len) &&
647 &(s->str[ovector[last]]) )
648 {
649 memcpy(p, &(s->str[ovector[last]]), (size_t)len);
650 p += len;
651 r->len += len;
652 }
653
654 /* The replacement */
655 if (r->siz > (r->len + rlen)) {
656 memcpy(p, replacement, rlen);
657 p += rlen;
658 r->len += rlen;
659 }
660
661 /* null terminate */
662 *p = '\0';
663
664 last = curr + 1;
665 }
666 }
667
668 /* Last part, after last replacement; includes terminating null
669 */
670 if (last > 0)
671 {
672 /* If not, nothing has been replaced, and r is still a copy of s
673 */
674 tlen = (long)((s->len + 1) - ovector[last]);
675 if (tlen > 0)
676 {
677 len = (size_t)tlen;
678 if (r->siz >= (r->len + len) &&
679 &(s->str[ovector[2*i -1]]) ) {
680 memcpy(p, &(s->str[ovector[2*i -1]]), (size_t)len);
681 p += (len - 1);
682 r->len += (len - 1);
683 *p = '\0';
684 }
685 }
686 }
687
688 }
689
690 return r;
691}
692
693
694#ifdef SH_CUTEST
695#include <stdlib.h>
696#include "CuTest.h"
697
698void Test_string (CuTest *tc) {
699 int status, i, max = 120;
700 FILE * fp;
701 sh_string * s = NULL;
702 sh_string * t;
703 static char template[] = "/tmp/xtest.XXXXXX";
704 char ** array;
705 char test[128];
706 size_t lengths[16];
707 unsigned int iarr;
708 int ovector[16];
709 int ovecnum;
710
711 s = sh_string_new(0);
712 CuAssertPtrNotNull(tc, s);
713 sh_string_destroy(&s);
714 CuAssertTrue(tc, s == NULL);
715
716 s = sh_string_new(0);
717 CuAssertPtrNotNull(tc, s);
718
719 status = mkstemp(template);
720 CuAssertTrue(tc, status >= 0);
721
722 fp = fdopen(status, "r+");
723 CuAssertPtrNotNull(tc, fp);
724
725 for (i = 0; i < 80; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 0 */
726 for (i = 0; i < 118; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 1 */
727 for (i = 0; i < 119; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 2 */
728 for (i = 0; i < 120; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 3 */
729 for (i = 0; i < 121; ++i) { fputc ('a', fp); } fputc ('\n', fp); /* 4 */
730 for (i = 0; i < 238; ++i) { fputc ('a', fp); } fputc ('\n', fp);
731 for (i = 0; i < 239; ++i) { fputc ('a', fp); } fputc ('\n', fp);
732 for (i = 0; i < 240; ++i) { fputc ('a', fp); } fputc ('\n', fp);
733 for (i = 0; i < 241; ++i) { fputc ('a', fp); } fputc ('\n', fp);
734
735 rewind(fp);
736
737 for (i = 0; i < 9; ++i)
738 {
739 status = sh_string_read(s, fp, max);
740
741 switch (i) {
742 case 0:
743 CuAssertTrue(tc, s->len == 80);
744 CuAssertTrue(tc, s->siz == 120);
745 CuAssertTrue(tc, status == 81);
746 break;
747 case 1:
748 CuAssertTrue(tc, s->len == 118);
749 CuAssertTrue(tc, s->siz == 120);
750 CuAssertTrue(tc, status == 119);
751 break;
752 case 2:
753 CuAssertTrue(tc, s->len == 119);
754 CuAssertTrue(tc, s->siz == 120);
755 CuAssertTrue(tc, status == -2); /* no terminating '\n', truncated */
756 break;
757 case 3:
758 CuAssertTrue(tc, s->len == 120);
759 CuAssertTrue(tc, s->siz == 240);
760 CuAssertTrue(tc, status == 121);
761 break;
762 case 4:
763 CuAssertTrue(tc, s->len == 121);
764 CuAssertTrue(tc, s->siz == 240);
765 CuAssertTrue(tc, status == 122);
766 break;
767 case 5:
768 CuAssertTrue(tc, s->len == 238);
769 CuAssertTrue(tc, s->siz == 240);
770 CuAssertTrue(tc, status == 239);
771 break;
772 case 6:
773 CuAssertTrue(tc, s->len == 239);
774 CuAssertTrue(tc, s->siz == 240);
775 CuAssertTrue(tc, status == -2); /* no terminating '\n', truncated */
776 break;
777 default:
778 CuAssertTrue(tc, s->len == 239);
779 CuAssertTrue(tc, s->siz == 240);
780 CuAssertTrue(tc, status == -2);
781 }
782 if (status == -2) /* read in rest of string */
783 { max = 240; sh_string_read(s, fp, max); }
784 }
785
786 rewind(fp);
787
788 sh_string_truncate(s, 0);
789 CuAssertTrue(tc, s->len == 0);
790
791 for (i = 0; i < 9; ++i)
792 {
793 status = sh_string_read(s, fp, 240);
794 if (status == -2)
795 sh_string_read(s, fp, 240);
796 else
797 {
798 for (status = 0; status < (int)s->len; ++status)
799 {
800 if (s->str[status] != 'a')
801 {
802 CuFail(tc, "unexpected character");
803 }
804 }
805 }
806 }
807
808 status = fclose(fp);
809 CuAssertTrue(tc, status == 0);
810 status = remove(template);
811 CuAssertTrue(tc, status == 0);
812
813 iarr = 10; strcpy(test, "|a1|| a2| |a3 |a4|a5|");
814 array = split_array(test, &iarr, '|', lengths);
815 CuAssertIntEquals(tc,9,(int)iarr);
816 CuAssertStrEquals(tc,"", array[0]);
817 CuAssertStrEquals(tc,"a1", array[1]);
818 CuAssertStrEquals(tc,"", array[2]);
819 CuAssertStrEquals(tc,"a2", array[3]);
820 CuAssertStrEquals(tc,"", array[4]);
821 CuAssertStrEquals(tc,"a3", array[5]);
822 CuAssertStrEquals(tc,"a4", array[6]);
823 CuAssertStrEquals(tc,"a5", array[7]);
824 CuAssertStrEquals(tc,"", array[8]);
825
826 CuAssertIntEquals(tc, 0, (int)lengths[0]);
827 CuAssertIntEquals(tc, 2, (int)lengths[1]);
828 CuAssertIntEquals(tc, 0, (int)lengths[2]);
829 CuAssertIntEquals(tc, 2, (int)lengths[3]);
830 CuAssertIntEquals(tc, 0, (int)lengths[4]);
831 CuAssertIntEquals(tc, 2, (int)lengths[5]);
832 CuAssertIntEquals(tc, 2, (int)lengths[6]);
833 CuAssertIntEquals(tc, 2, (int)lengths[7]);
834 CuAssertIntEquals(tc, 0, (int)lengths[8]);
835
836 iarr = 10; strcpy(test, "a1|| a2| |a3 |a4|a5|");
837 array = split_array(test, &iarr, '|', lengths);
838 CuAssertIntEquals(tc,8,(int)iarr);
839 CuAssertStrEquals(tc,"a1", array[0]);
840 CuAssertStrEquals(tc,"", array[1]);
841 CuAssertStrEquals(tc,"a2", array[2]);
842 CuAssertStrEquals(tc,"", array[3]);
843 CuAssertStrEquals(tc,"a3", array[4]);
844 CuAssertStrEquals(tc,"a4", array[5]);
845 CuAssertStrEquals(tc,"a5", array[6]);
846 CuAssertStrEquals(tc,"", array[7]);
847
848 CuAssertIntEquals(tc, 2, (int)lengths[0]);
849 CuAssertIntEquals(tc, 0, (int)lengths[1]);
850 CuAssertIntEquals(tc, 2, (int)lengths[2]);
851 CuAssertIntEquals(tc, 0, (int)lengths[3]);
852 CuAssertIntEquals(tc, 2, (int)lengths[4]);
853 CuAssertIntEquals(tc, 2, (int)lengths[5]);
854 CuAssertIntEquals(tc, 2, (int)lengths[6]);
855 CuAssertIntEquals(tc, 0, (int)lengths[7]);
856
857 iarr = 10; strcpy(test, " a1|| a2 | |a3 |a4|a5");
858 array = split_array(test, &iarr, '|', lengths);
859 CuAssertIntEquals(tc,7,(int)iarr);
860 CuAssertStrEquals(tc,"a1", array[0]);
861 CuAssertStrEquals(tc,"", array[1]);
862 CuAssertStrEquals(tc,"a2", array[2]);
863 CuAssertStrEquals(tc,"", array[3]);
864 CuAssertStrEquals(tc,"a3", array[4]);
865 CuAssertStrEquals(tc,"a4", array[5]);
866 CuAssertStrEquals(tc,"a5", array[6]);
867
868 CuAssertIntEquals(tc, 2, (int)lengths[0]);
869 CuAssertIntEquals(tc, 0, (int)lengths[1]);
870 CuAssertIntEquals(tc, 2, (int)lengths[2]);
871 CuAssertIntEquals(tc, 0, (int)lengths[3]);
872 CuAssertIntEquals(tc, 2, (int)lengths[4]);
873 CuAssertIntEquals(tc, 2, (int)lengths[5]);
874 CuAssertIntEquals(tc, 2, (int)lengths[6]);
875
876 iarr = 10; strcpy(test, "a1|| a2 | |a3 |a4|a5 ");
877 array = split_array(test, &iarr, '|', lengths);
878 CuAssertIntEquals(tc,7,(int)iarr);
879 CuAssertStrEquals(tc,"a1", array[0]);
880 CuAssertStrEquals(tc,"", array[1]);
881 CuAssertStrEquals(tc,"a2", array[2]);
882 CuAssertStrEquals(tc,"", array[3]);
883 CuAssertStrEquals(tc,"a3", array[4]);
884 CuAssertStrEquals(tc,"a4", array[5]);
885 CuAssertStrEquals(tc,"a5", array[6]);
886
887 CuAssertIntEquals(tc, 2, (int)lengths[0]);
888 CuAssertIntEquals(tc, 0, (int)lengths[1]);
889 CuAssertIntEquals(tc, 2, (int)lengths[2]);
890 CuAssertIntEquals(tc, 0, (int)lengths[3]);
891 CuAssertIntEquals(tc, 2, (int)lengths[4]);
892 CuAssertIntEquals(tc, 2, (int)lengths[5]);
893 CuAssertIntEquals(tc, 2, (int)lengths[6]);
894
895 iarr = 10; strcpy(test, "|");
896 array = split_array(test, &iarr, '|', lengths);
897 CuAssertIntEquals(tc,2,(int)iarr);
898 CuAssertStrEquals(tc,"", array[0]);
899 CuAssertStrEquals(tc,"", array[1]);
900
901 CuAssertIntEquals(tc, 0, (int)lengths[0]);
902 CuAssertIntEquals(tc, 0, (int)lengths[1]);
903
904 iarr = 10; strcpy(test, "|||");
905 array = split_array(test, &iarr, '|', lengths);
906 CuAssertIntEquals(tc,4,(int)iarr);
907 CuAssertStrEquals(tc,"", array[0]);
908 CuAssertStrEquals(tc,"", array[1]);
909 CuAssertStrEquals(tc,"", array[2]);
910 CuAssertStrEquals(tc,"", array[3]);
911
912 CuAssertIntEquals(tc, 0, (int)lengths[0]);
913 CuAssertIntEquals(tc, 0, (int)lengths[1]);
914 CuAssertIntEquals(tc, 0, (int)lengths[2]);
915 CuAssertIntEquals(tc, 0, (int)lengths[3]);
916
917 iarr = 10; strcpy(test, " a1 ");
918 array = split_array(test, &iarr, '|', lengths);
919 CuAssertIntEquals(tc,1,(int)iarr);
920 CuAssertStrEquals(tc,"a1", array[0]);
921
922 CuAssertIntEquals(tc, 2, (int)lengths[0]);
923
924 iarr = 10; strcpy(test, "");
925 array = split_array(test, &iarr, '|', lengths);
926 CuAssertIntEquals(tc,1,(int)iarr);
927 CuAssertStrEquals(tc,"", array[0]);
928
929 CuAssertIntEquals(tc, 0, (int)lengths[0]);
930
931 /* WS separated */
932
933 iarr = 10; strcpy(test, "a1");
934 array = split_array_ws (test, &iarr, lengths);
935 CuAssertIntEquals(tc,1,(int)iarr);
936 CuAssertStrEquals(tc,"a1", array[0]);
937
938 CuAssertIntEquals(tc, 2, (int)lengths[0]);
939
940 iarr = 10; strcpy(test, " a1");
941 array = split_array_ws (test, &iarr, lengths);
942 CuAssertIntEquals(tc,1,(int)iarr);
943 CuAssertStrEquals(tc,"a1", array[0]);
944
945 CuAssertIntEquals(tc, 2, (int)lengths[0]);
946
947 iarr = 10; strcpy(test, " a1 ");
948 array = split_array_ws (test, &iarr, lengths);
949 CuAssertIntEquals(tc,1,(int)iarr);
950 CuAssertStrEquals(tc,"a1", array[0]);
951
952 CuAssertIntEquals(tc, 2, (int)lengths[0]);
953
954 iarr = 10; strcpy(test, " ");
955 array = split_array_ws (test, &iarr, lengths);
956 CuAssertIntEquals(tc,0,(int)iarr);
957 CuAssertTrue(tc, array[0] == NULL);
958
959 iarr = 10; strcpy(test, " a1 a2");
960 array = split_array_ws (test, &iarr, lengths);
961 CuAssertIntEquals(tc,2,(int)iarr);
962 CuAssertStrEquals(tc,"a1", array[0]);
963 CuAssertStrEquals(tc,"a2", array[1]);
964
965 CuAssertIntEquals(tc, 2, (int)lengths[0]);
966 CuAssertIntEquals(tc, 2, (int)lengths[1]);
967
968 iarr = 10; strcpy(test, " a1 a2 ");
969 array = split_array_ws (test, &iarr, lengths);
970 CuAssertIntEquals(tc,2,(int)iarr);
971 CuAssertStrEquals(tc,"a1", array[0]);
972 CuAssertStrEquals(tc,"a2", array[1]);
973
974 CuAssertIntEquals(tc, 2, (int)lengths[0]);
975 CuAssertIntEquals(tc, 2, (int)lengths[1]);
976
977 iarr = 10; strcpy(test, "");
978 array = split_array_ws (test, &iarr, lengths);
979 CuAssertIntEquals(tc,0,(int)iarr);
980 CuAssertTrue(tc, array[0] == NULL);
981
982 iarr = 3; strcpy(test, " this is a test for remainder");
983 array = split_array_ws (test, &iarr, lengths);
984 CuAssertIntEquals(tc,3,(int)iarr);
985 CuAssertStrEquals(tc,"this", array[0]);
986 CuAssertStrEquals(tc,"is", array[1]);
987 CuAssertStrEquals(tc,"a test for remainder", array[2]);
988 for (i = 0; i < 3; ++i)
989 {
990 CuAssertIntEquals(tc, (int)strlen(array[i]), lengths[i] );
991 }
992
993 /* split_array_list */
994 iarr = 6; strcpy(test, " this(a) is_a(test);for(b),remainder(test)foo(bar)");
995 array = split_array_list (test, &iarr, lengths);
996 CuAssertIntEquals(tc,3,(int)iarr);
997 CuAssertStrEquals(tc,"this(a)", array[0]);
998 CuAssertStrEquals(tc,"is_a(test);for(b)", array[1]);
999 CuAssertStrEquals(tc,"remainder(test)foo(bar)", array[2]);
1000 for (i = 0; i < 3; ++i)
1001 {
1002 CuAssertIntEquals(tc, (int)strlen(array[i]), lengths[i] );
1003 }
1004
1005
1006 /* string replace */
1007 s = sh_string_new_from_lchar3 ("abc ", 4, "def ", 4, "ghi ", 4);
1008 ovecnum = 2;
1009 ovector[0] = 0; ovector[1] = 2;
1010 ovector[2] = 4; ovector[3] = 11;
1011
1012 t = sh_string_replace(s, ovector, ovecnum,
1013 "___", 3);
1014 CuAssertPtrNotNull(tc, t);
1015 CuAssertStrEquals(tc, "___c ___ ", t->str);
1016 CuAssertIntEquals(tc, 9, (int)t->len);
1017
1018 ovector[0] = 0; ovector[1] = 2;
1019 ovector[2] = 4; ovector[3] = 12;
1020 t = sh_string_replace(s, ovector, ovecnum,
1021 "___", 3);
1022 CuAssertPtrNotNull(tc, t);
1023 CuAssertStrEquals(tc, "___c ___", t->str);
1024 CuAssertIntEquals(tc, 8, (int)t->len);
1025
1026 ovector[0] = 0; ovector[1] = 0;
1027 ovector[2] = 0; ovector[3] = 0;
1028 t = sh_string_replace(s, ovector, ovecnum,
1029 "___", 3);
1030 CuAssertTrue(tc, t == NULL);
1031
1032 ovector[0] = 0; ovector[1] = 3;
1033 ovector[2] = 3; ovector[3] = 6;
1034 t = sh_string_replace(s, ovector, ovecnum,
1035 "___", 3);
1036
1037 CuAssertPtrNotNull(tc, t);
1038 CuAssertStrEquals(tc, "______f ghi ", t->str);
1039 CuAssertIntEquals(tc, 12, (int)t->len);
1040
1041 ovector[0] = 4; ovector[1] = 5;
1042 ovector[2] = 11; ovector[3] = 12;
1043 t = sh_string_replace(s, ovector, ovecnum,
1044 "___", 3);
1045 CuAssertPtrNotNull(tc, t);
1046 CuAssertStrEquals(tc, "abc ___ef ghi___", t->str);
1047 CuAssertIntEquals(tc, 16, (int)t->len);
1048
1049 t = sh_string_replace(s, ovector, 0,
1050 "___", 3);
1051 CuAssertPtrNotNull(tc, t);
1052 CuAssertStrEquals(tc, s->str, t->str);
1053 CuAssertIntEquals(tc, (int)s->len, (int)t->len);
1054
1055}
1056
1057#endif
Note: See TracBrowser for help on using the repository browser.