source: trunk/src/sh_string.c@ 175

Last change on this file since 175 was 171, checked in by katerina, 16 years ago

Include dnmalloc (ticket #108) and fix bugs #106 (EINPROGRESS) and #107 (compressBound).

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