source: trunk/src/sh_string.c@ 270

Last change on this file since 270 was 265, checked in by katerina, 15 years ago

Enhance logfile monitoring (tickets #183, #184, #185).

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