comparison src/ploki/Str.c @ 4223:ac0403686959

<oerjan> rm -rf src/ploki; mv ploki src
author HackBot
date Fri, 20 Dec 2013 22:18:50 +0000
parents
children
comparison
equal deleted inserted replaced
4222:b0f3e267bb1e 4223:ac0403686959
1 #include "config.h"
2 #include "Str.h"
3 #include "strutil.h"
4 #include "xmalloc.h"
5
6 #include <ctype.h>
7 #include <errno.h>
8 #include <float.h>
9 #include <stdarg.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <assert.h>
14
15 enum {MAGIC = 4};
16
17 #define OFFSET_OFF(s) \
18 do { \
19 if ((s)->offset) { \
20 memmove((s)->buf - (s)->offset, (s)->buf, (s)->length + 1); \
21 (s)->buf -= (s)->offset; \
22 (s)->offset = 0; \
23 } \
24 } while (0)
25
26
27 void
28 St_init(String *s) {
29 s->buf = xmalloc(s->size = MAGIC, sizeof *s->buf);
30 s->buf[s->offset = s->length = 0] = '\0';
31 }
32
33 void
34 St_fake(String *s, char *p, size_t n) {
35 assert(s != NULL);
36 assert(p != NULL);
37 s->buf = p;
38 s->offset = 0;
39 s->length = s->size = n;
40 }
41
42 void
43 St_clear(String *s) {
44 assert(s != NULL);
45 if (!s->buf) {
46 return;
47 }
48 xfree(s->buf - s->offset);
49 s->buf = NULL;
50 DEBUG(s->offset = s->length = s->size = 0;)
51 }
52
53 #if 0
54 void
55 (St_zero)(String *s) {
56 St_zero(s);
57 }
58
59 char *
60 (St_ptr)(const String *s) {
61 return St_ptr(s);
62 }
63
64 size_t
65 (St_len)(const String *s) {
66 return St_len(s);
67 }
68 #endif
69
70 static void
71 St_grow(String *s, size_t n) {
72 if (s->size - s->offset <= n) {
73 OFFSET_OFF(s);
74 if (s->size <= n) {
75 s->buf = xrealloc(s->buf, n + 1u);
76 s->size = n + 1u;
77 }
78 }
79 }
80
81 void
82 St_trunc(String *s, size_t n) {
83 if (s->length > n) {
84 s->buf[s->length = n] = '\0';
85 }
86 if (s->size > n + 1 && n >= MAGIC) {
87 OFFSET_OFF(s);
88 s->buf = xrealloc(s->buf, n + 1);
89 s->size = n + 1;
90 }
91 }
92
93 #if 0
94 int
95 St_lastchar(const String *s) {
96 return ST_LASTCHAR(s);
97 }
98
99 int
100 St_firstchar(const String *s) {
101 return ST_FIRSTCHAR(s);
102 }
103
104 int
105 St_chop(String *s) {
106 int tmp;
107
108 if (!s->length) {
109 return EOF;
110 }
111 tmp = (unsigned char)s->buf[s->length - 1];
112 s->buf[--s->length] = '\0';
113 return tmp;
114 }
115 #endif
116
117 int
118 St_shift(String *s) {
119 int tmp;
120
121 if (!s->length) {
122 return EOF;
123 }
124 tmp = (unsigned char)s->buf[0];
125 ++s->offset;
126 ++s->buf;
127 --s->length;
128 return tmp;
129 }
130
131
132 size_t
133 St_shiftws(String *s) {
134 size_t n;
135
136 for (n = 0; n < s->length && isspace((unsigned char)s->buf[n]); ++n)
137 ;
138 s->offset += n;
139 s->buf += n;
140 s->length -= n;
141
142 return n;
143 }
144
145 #if 0
146 int
147 St_index(const String *s, size_t n) {
148 return ST_INDEX(s, n);
149 }
150 #endif
151
152 size_t
153 St_chr(const String *s, int c) {
154 const char *tmp;
155 if (!(tmp = memchr(s->buf, c, s->length))) {
156 return -1;
157 }
158 return tmp - s->buf;
159 }
160
161 #if 0
162 size_t
163 St_rchr(const String *s, int c) {
164 size_t i;
165
166 for (i = s->length; i; --i) {
167 if (s->buf[i - 1] == c)
168 return i - 1;
169 }
170 return -1;
171 }
172 #endif
173
174 int
175 St_cmp(const String *s, const String *t) {
176 return u_cmp(St_ptr(s), St_len(s), St_ptr(t), St_len(t));
177 }
178
179 int
180 St_cmp_m(const String *s, const void *m, size_t n) {
181 return u_cmp(St_ptr(s), St_len(s), m, n);
182 }
183
184 #if 0
185 int
186 St_cmp_s(const String *s, const char *tz) {
187 return u_cmp(St_ptr(s), St_len(s), tz, strlen(tz));
188 }
189 #endif
190
191 #define NCMP(s, m, n) \
192 do { \
193 return memcmp((s)->buf, m, (s)->length < (n) ? (s)->length : (n)); \
194 } while (0)
195
196 #if 0
197 int
198 St_ncmp(const String *s, const String *t) {
199 NCMP(s, t->buf, t->length);
200 }
201 #endif
202
203 int
204 St_ncmp_m(const String *s, const void *m, size_t n) {
205 NCMP(s, m, n);
206 }
207
208 #if 0
209 int
210 St_ncmp_s(const String *s, const char *tz) {
211 size_t length = strlen(tz);
212
213 NCMP(s, tz, length);
214 }
215
216 static int
217 my_memcasecmp(const void *p, const void *q, size_t n) {
218 const unsigned char *s = p, *t = q;
219 size_t i;
220
221 for (i = 0; i < n; ++i) {
222 if (tolower(s[i]) < tolower(t[i])) {
223 return -1;
224 }
225 if (tolower(s[i]) > tolower(t[i])) {
226 return 1;
227 }
228 }
229 return 0;
230 }
231
232 #define CASECMP(s, m, n) \
233 do { \
234 int tmp__; \
235 if (!(tmp__ = my_memcasecmp((s)->buf, m, (s)->length < (n) ? (s)->length : (n)))) { \
236 if ((s)->length < (n)) \
237 return -1; \
238 if ((s)->length > (n)) \
239 return 1; \
240 } \
241 return tmp__; \
242 } while (0)
243
244 int
245 St_casecmp(const String *s, const String *t) {
246 CASECMP(s, t->buf, t->length);
247 }
248
249 int
250 St_casecmp_m(const String *s, const void *m, size_t n) {
251 CASECMP(s, m, n);
252 }
253
254 int
255 St_casecmp_s(const String *s, const char *tz) {
256 size_t length = strlen(tz);
257
258 CASECMP(s, tz, length);
259 }
260
261 #define NCASECMP(s, m, n) \
262 do { \
263 return my_memcasecmp((s)->buf, m, n); \
264 } while (0)
265
266 int
267 St_ncasecmp(const String *s, const String *t) {
268 NCASECMP(s, t->buf, t->length);
269 }
270
271 int
272 St_ncasecmp_m(const String *s, const void *m, size_t n) {
273 NCASECMP(s, m, n);
274 }
275
276 int
277 St_ncasecmp_s(const String *s, const char *tz) {
278 size_t length = strlen(tz);
279
280 NCASECMP(s, tz, length);
281 }
282 #endif
283
284 #define STR(s, m, n) \
285 do { \
286 size_t i__; \
287 if ((n) == 0) \
288 return 0; \
289 if ((s)->length < (n)) \
290 return -1; \
291 for (i__ = 0; i__ <= (s)->length - (n); ++i__) { \
292 if (!memcmp((s)->buf + i__, m, n)) \
293 return i__; \
294 } \
295 return -1; \
296 } while (0)
297
298 size_t
299 St_str(const String *s, const String *t) {
300 STR(s, t->buf, t->length);
301 }
302
303 size_t
304 St_str_m(const String *s, const void *m, size_t n) {
305 STR(s, m, n);
306 }
307
308 #if 0
309 size_t
310 St_str_s(const String *s, const char *tz) {
311 size_t length = strlen(tz);
312
313 STR(s, tz, length);
314 }
315 #endif
316
317 #define RSTR(s, m, n) \
318 do { \
319 size_t i__; \
320 if ((n) == 0) \
321 return (s)->length; \
322 if ((s)->length < (n)) \
323 return -1; \
324 for (i__ = (s)->length - (n) + 1; i__; --i__) { \
325 if (!memcmp((s)->buf + i__ - 1, m, n)) \
326 return i__ - 1; \
327 } \
328 return -1; \
329 } while (0)
330
331 #if 0
332 size_t
333 St_rstr(const String *s, const String *t) {
334 RSTR(s, t->buf, t->length);
335 }
336 #endif
337
338 size_t
339 St_rstr_m(const String *s, const void *m, size_t n) {
340 RSTR(s, m, n);
341 }
342
343 size_t
344 St_rstr_s(const String *s, const char *tz) {
345 size_t length = strlen(tz);
346
347 RSTR(s, tz, length);
348 }
349
350 size_t
351 St_stro_m(const String *s, size_t off, const void *m, size_t n) {
352 size_t i;
353
354 assert(off <= s->length);
355
356 if (n == 0) {
357 return off;
358 }
359
360 if (n > s->length - off) {
361 return -1;
362 }
363
364 for (i = off; i < s->length - n; ++i) {
365 if (memcmp(s->buf + i, m, n) == 0) {
366 return i;
367 }
368 }
369 return -1;
370 }
371
372 size_t
373 St_rstro_m(const String *s, size_t off, const void *m, size_t n) {
374 size_t i;
375
376 assert(off <= s->length);
377
378 if (n == 0) {
379 return off;
380 }
381
382 if (n > s->length) {
383 return -1;
384 }
385
386 i = off;
387 if (i > s->length - n) {
388 i = s->length - n;
389 }
390
391 for (; i + 1u; --i) {
392 if (memcmp(s->buf + i, m, n) == 0) {
393 return i;
394 }
395 }
396 return -1;
397 }
398
399 #define CPY(s, m, n) \
400 do { \
401 if ((s)->size - (s)->offset <= (n)) { \
402 OFFSET_OFF(s); \
403 if ((s)->size <= (n)) { \
404 (s)->buf = xrealloc((s)->buf, (n) + 1); \
405 (s)->size = (n) + 1; \
406 } \
407 } \
408 memcpy((s)->buf, m, (s)->length = (n)); \
409 (s)->buf[n] = '\0'; \
410 } while (0)
411
412 void
413 St_cpy(String *s, const String *t) {
414 CPY(s, t->buf, t->length);
415 }
416
417 void
418 St_cpy_m(String *s, const void *m, size_t n) {
419 CPY(s, m, n);
420 }
421
422 void
423 St_cpy_s(String *s, const char *tz) {
424 size_t length = strlen(tz);
425
426 CPY(s, tz, length);
427 }
428
429 void
430 St_cpy_c(String *s, int c) {
431 unsigned char tmp = c;
432 CPY(s, &tmp, 1);
433 }
434
435 static void cat(String *s, const void *m, size_t n) {
436 if (s->size - s->offset <= s->length + n) {
437 OFFSET_OFF(s);
438 if (s->size <= s->length + n) {
439 do {
440 s->size = s->size / 2 * 3 + 1;
441 } while (s->size <= s->length + n);
442 s->buf = xrealloc(s->buf, s->size);
443 }
444 }
445 memcpy(s->buf + s->length, m, n);
446 s->buf[s->length += n] = '\0';
447 }
448
449 void
450 St_cat(String *s, const String *t) {
451 cat(s, t->buf, t->length);
452 }
453
454 void
455 St_cat_m(String *s, const void *m, size_t n) {
456 cat(s, m, n);
457 }
458
459 void
460 St_cat_s(String *s, const char *tz) {
461 cat(s, tz, strlen(tz));
462 }
463
464 void
465 St_cat_c(String *s, int c) {
466 unsigned char tmp = c;
467 cat(s, &tmp, 1);
468 }
469
470 #define TAC(s, m, n) \
471 do { \
472 if ((s)->offset >= (n)) { \
473 (s)->buf -= (n); \
474 (s)->offset -= (n); \
475 } else if ((s)->size <= (s)->length + (n)) { \
476 (s)->buf -= (s)->offset; \
477 (s)->buf = xrealloc((s)->buf, (s)->length + (n) + 1); \
478 (s)->size = (s)->length + (n) + 1; \
479 memmove((s)->buf + (n), (s)->buf + (s)->offset, (s)->length + 1); \
480 (s)->offset = 0; \
481 } else { \
482 memmove((s)->buf + (n), (s)->buf, (s)->length + 1); \
483 } \
484 memcpy((s)->buf, m, n); \
485 (s)->length += (n); \
486 } while (0)
487
488 #if 0
489 void
490 St_tac(String *s, const String *t) {
491 TAC(s, t->buf, t->length);
492 }
493 #endif
494
495 void
496 St_tac_m(String *s, const void *m, size_t n) {
497 TAC(s, m, n);
498 }
499
500 void
501 St_tac_s(String *s, const char *tz) {
502 size_t length = strlen(tz);
503
504 TAC(s, tz, length);
505 }
506
507 void
508 St_tac_c(String *s, int c) {
509 unsigned char tmp = c;
510 TAC(s, &tmp, 1);
511 }
512
513 void
514 St_reverse(String *s) {
515 size_t i;
516 char tmp;
517
518 for (i = 0; i < s->length / 2; ++i) {
519 tmp = s->buf[i];
520 s->buf[i] = s->buf[s->length - i - 1];
521 s->buf[s->length - i - 1] = tmp;
522 }
523 }
524
525 #if 0
526 void
527 St_map(String *s, int (*better)(int)) {
528 size_t i;
529 int tmp;
530
531 for (i = 0; i < s->length; ++i) {
532 tmp = better((unsigned char)s->buf[i]);
533 if (tmp == EOF) {
534 s->buf[s->length = i] = '\0';
535 return;
536 }
537 s->buf[i] = tmp;
538 }
539
540 while ((tmp = better(EOF)) != EOF) {
541 if (s->size <= s->length + 1) {
542 OFFSET_OFF(s);
543 XREALLOC(s->buf, s->size * 2);
544 s->size *= 2;
545 }
546 s->buf[s->length++] = tmp;
547 s->buf[s->length] = '\0';
548 }
549 }
550 #endif
551
552 void
553 St_grep(String *s, int (*good)(int)) {
554 size_t r, w;
555
556 for (r = w = 0; r < s->length; ++r) {
557 if (good((unsigned char)s->buf[r])) {
558 s->buf[w++] = s->buf[r];
559 }
560 }
561 s->buf[s->length = w] = '\0';
562 }
563
564 void
565 St_upper(String *s) {
566 size_t i;
567
568 for (i = 0; i < s->length; ++i) {
569 s->buf[i] = toupper((unsigned char)s->buf[i]);
570 }
571 }
572
573 void
574 St_lower(String *s) {
575 size_t i;
576
577 for (i = 0; i < s->length; ++i) {
578 s->buf[i] = tolower((unsigned char)s->buf[i]);
579 }
580 }
581
582 void
583 St_del(String *s, size_t p, size_t n) {
584 if (n == 0 || s->length < p)
585 return;
586 if (s->length < n || s->length < p + n) {
587 n = s->length - p;
588 }
589 if (p + n == s->length) {
590 s->buf[p] = '\0';
591 } else if (p == 0) {
592 s->offset += n;
593 s->buf += n;
594 } else {
595 memmove(s->buf + p, s->buf + n + p, s->length - p - n);
596 }
597 s->length -= n;
598 }
599
600 #if 0
601 #define INS(s, p, m, n) \
602 do { \
603 if ((n) == 0 || (s)->length < (p)) \
604 return; \
605 if ((n) <= (s)->offset) { \
606 (s)->offset -= (n); \
607 (s)->buf -= (n); \
608 memmove((s)->buf, (s)->buf + (n), p); \
609 } else { \
610 if ((s)->size - (s)->offset <= (s)->length + (n)) { \
611 OFFSET_OFF(s); \
612 XREALLOC((s)->buf, (s)->length + (n) + 1); \
613 (s)->size = (s)->length + (n) + 1; \
614 } \
615 memmove((s)->buf + (p) + (n), (s)->buf + (p), (s)->length - (p) + 1); \
616 } \
617 memcpy((s)->buf + (p), m, n); \
618 (s)->length += (n); \
619 } while (0)
620
621 void
622 St_ins(String *s, size_t p, const String *t) {
623 INS(s, p, t->buf, t->length);
624 }
625
626 void
627 St_ins_m(String *s, size_t p, const void *m, size_t n) {
628 INS(s, p, m, n);
629 }
630
631 void
632 St_ins_s(String *s, size_t p, const char *tz) {
633 size_t length = strlen(tz);
634
635 INS(s, p, tz, length);
636 }
637
638 void
639 St_ins_c(String *s, size_t p, int c) {
640 unsigned char tmp = c;
641 INS(s, p, &tmp, 1);
642 }
643 #endif
644
645 void
646 St_substr(String *l, String *s, size_t p, size_t n, const String *r) {
647 if (l) {
648 if (p >= s->length) {
649 St_zero(l);
650 } else {
651 size_t length = n;
652
653 if (p + length > s->length) {
654 length = s->length - p;
655 }
656 St_cpy_m(l, s->buf + p, length);
657 }
658 }
659
660 if (r) {
661 size_t gap = 0;
662
663 if (p + n > s->length) {
664 if (p > s->length) {
665 n = 0;
666 gap = p - s->length;
667 } else {
668 n = s->length - p;
669 }
670 }
671 St_grow(s, s->length + r->length - n + gap);
672 if (gap) {
673 memset(s->buf + s->length, '\0', gap);
674 } else if (r->length != n && s->length - p - n) {
675 memmove(s->buf + p + r->length, s->buf + p + n, s->length - p - n);
676 }
677 memcpy(s->buf + p, r->buf, r->length);
678 s->buf[s->length += r->length - n + gap] = '\0';
679 }
680 }
681
682 #if HAVE_VSNPRINTF_P
683 size_t
684 St_xprintf(String *s, const char *fmt, ...) {
685 va_list ap;
686 int tmp;
687
688 va_start(ap, fmt);
689 tmp = vsnprintf(s->buf, s->size, fmt, ap);
690 va_end(ap);
691
692 if (tmp < 0) {
693 do {
694 St_grow(s, s->size * 2);
695
696 va_start(ap, fmt);
697 tmp = vsnprintf(s->buf, s->size, fmt, ap);
698 va_end(ap);
699 } while (tmp < 0);
700 } else if (tmp + 1u >= s->size) {
701 St_grow(s, tmp);
702 s->length = 0;
703
704 va_start(ap, fmt);
705 tmp = vsnprintf(s->buf, s->size, fmt, ap);
706 va_end(ap);
707
708 if (tmp < 0) {
709 s->buf[0] = '\0';
710 return -1;
711 }
712 }
713
714 return s->length = tmp;
715 }
716 #endif
717
718 void
719 St_num(String *s, double d) {
720 #if HAVE_VSNPRINTF_P
721 St_xprintf(s, "%.*g", DBL_DIG, d);
722 #else
723 St_grow(s, 255);
724 s->length = sprintf(s->buf, "%.*g", DBL_DIG, d);
725 #endif
726 }
727
728 #if 0
729 size_t
730 St_write(const String *s, FILE *fp) {
731 return ST_WRITE(s, fp);
732 }
733 #endif
734
735 #define MIN(a, b) ((a) < (b) ? (a) : (b))
736
737 size_t
738 St_read(String *s, FILE *fp, size_t n) {
739 char buf[4096];
740 size_t red;
741
742 St_zero(s);
743 while (n && !feof(fp) && (red = fread(buf, sizeof *buf, MIN(n, sizeof buf / sizeof *buf), fp))) {
744 St_cat_m(s, buf, red);
745 n -= red;
746 }
747 return s->length;
748 }
749
750 #if 0
751 int
752 St_getline(String *s, FILE *fp, int n) {
753 int c;
754
755 OFFSET_OFF(s);
756 for (s->length = 0; (c = getc(fp)) != EOF; ++s->length) {
757 if (s->size <= s->length + 1) {
758 XREALLOC(s->buf, s->size * 2);
759 s->size *= 2;
760 }
761 s->buf[s->length] = c;
762 if (c == n)
763 break;
764 }
765 s->buf[s->length] = '\0';
766
767 return s->length != 0;
768 }
769
770 void
771 St_getfile(String *s, FILE *fp) {
772 size_t tmp;
773
774 OFFSET_OFF(s);
775 if (s->size <= BUFSIZ) {
776 XREALLOC(s->buf, BUFSIZ + 1);
777 s->size = BUFSIZ + 1;
778 }
779
780 for (s->length = 0; (tmp = fread(s->buf + s->length, 1, BUFSIZ, fp)); ) {
781 s->length += tmp;
782 if (s->size <= s->length + BUFSIZ + 1) {
783 XREALLOC(s->buf, s->size * 2);
784 s->size *= 2;
785 }
786 }
787 s->buf[s->length] = '\0';
788 }
789 #endif
790
791 size_t
792 St_hash(const String *s, size_t h) {
793 return u_hash(St_ptr(s), St_len(s), h);
794 }