source: trunk/src/sh_string.c@ 262

Last change on this file since 262 was 260, checked in by katerina, 15 years ago

Support event correlation (ticket #178).

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