source: trunk/src/sh_string.c@ 376

Last change on this file since 376 was 276, checked in by katerina, 15 years ago

Fix for bugs in log monitoring (tickets #196, #199), and allow shell command monitoring (ticket #197).

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