source: trunk/src/sh_string.c@ 184

Last change on this file since 184 was 183, checked in by katerina, 16 years ago

Support for logfile monitoring (ticket #122). Also improved some configure error messages.

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