source: trunk/src/sh_string.c@ 233

Last change on this file since 233 was 215, checked in by katerina, 16 years ago

Consolidate filtering code (ticket #142) and match on regular expressions (ticket #143).

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