source: trunk/src/sh_string.c@ 205

Last change on this file since 205 was 185, checked in by katerina, 16 years ago

Bugfixes for log monitoring, samba logfile parser.

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