Mercurial > repo
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 } |