Mercurial > repo
view src/ploki/Str.c @ 4335:c3083517f99c
<int-e> revert
author | HackBot |
---|---|
date | Thu, 16 Jan 2014 23:12:02 +0000 |
parents | ac0403686959 |
children |
line wrap: on
line source
#include "config.h" #include "Str.h" #include "strutil.h" #include "xmalloc.h" #include <ctype.h> #include <errno.h> #include <float.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> enum {MAGIC = 4}; #define OFFSET_OFF(s) \ do { \ if ((s)->offset) { \ memmove((s)->buf - (s)->offset, (s)->buf, (s)->length + 1); \ (s)->buf -= (s)->offset; \ (s)->offset = 0; \ } \ } while (0) void St_init(String *s) { s->buf = xmalloc(s->size = MAGIC, sizeof *s->buf); s->buf[s->offset = s->length = 0] = '\0'; } void St_fake(String *s, char *p, size_t n) { assert(s != NULL); assert(p != NULL); s->buf = p; s->offset = 0; s->length = s->size = n; } void St_clear(String *s) { assert(s != NULL); if (!s->buf) { return; } xfree(s->buf - s->offset); s->buf = NULL; DEBUG(s->offset = s->length = s->size = 0;) } #if 0 void (St_zero)(String *s) { St_zero(s); } char * (St_ptr)(const String *s) { return St_ptr(s); } size_t (St_len)(const String *s) { return St_len(s); } #endif static void St_grow(String *s, size_t n) { if (s->size - s->offset <= n) { OFFSET_OFF(s); if (s->size <= n) { s->buf = xrealloc(s->buf, n + 1u); s->size = n + 1u; } } } void St_trunc(String *s, size_t n) { if (s->length > n) { s->buf[s->length = n] = '\0'; } if (s->size > n + 1 && n >= MAGIC) { OFFSET_OFF(s); s->buf = xrealloc(s->buf, n + 1); s->size = n + 1; } } #if 0 int St_lastchar(const String *s) { return ST_LASTCHAR(s); } int St_firstchar(const String *s) { return ST_FIRSTCHAR(s); } int St_chop(String *s) { int tmp; if (!s->length) { return EOF; } tmp = (unsigned char)s->buf[s->length - 1]; s->buf[--s->length] = '\0'; return tmp; } #endif int St_shift(String *s) { int tmp; if (!s->length) { return EOF; } tmp = (unsigned char)s->buf[0]; ++s->offset; ++s->buf; --s->length; return tmp; } size_t St_shiftws(String *s) { size_t n; for (n = 0; n < s->length && isspace((unsigned char)s->buf[n]); ++n) ; s->offset += n; s->buf += n; s->length -= n; return n; } #if 0 int St_index(const String *s, size_t n) { return ST_INDEX(s, n); } #endif size_t St_chr(const String *s, int c) { const char *tmp; if (!(tmp = memchr(s->buf, c, s->length))) { return -1; } return tmp - s->buf; } #if 0 size_t St_rchr(const String *s, int c) { size_t i; for (i = s->length; i; --i) { if (s->buf[i - 1] == c) return i - 1; } return -1; } #endif int St_cmp(const String *s, const String *t) { return u_cmp(St_ptr(s), St_len(s), St_ptr(t), St_len(t)); } int St_cmp_m(const String *s, const void *m, size_t n) { return u_cmp(St_ptr(s), St_len(s), m, n); } #if 0 int St_cmp_s(const String *s, const char *tz) { return u_cmp(St_ptr(s), St_len(s), tz, strlen(tz)); } #endif #define NCMP(s, m, n) \ do { \ return memcmp((s)->buf, m, (s)->length < (n) ? (s)->length : (n)); \ } while (0) #if 0 int St_ncmp(const String *s, const String *t) { NCMP(s, t->buf, t->length); } #endif int St_ncmp_m(const String *s, const void *m, size_t n) { NCMP(s, m, n); } #if 0 int St_ncmp_s(const String *s, const char *tz) { size_t length = strlen(tz); NCMP(s, tz, length); } static int my_memcasecmp(const void *p, const void *q, size_t n) { const unsigned char *s = p, *t = q; size_t i; for (i = 0; i < n; ++i) { if (tolower(s[i]) < tolower(t[i])) { return -1; } if (tolower(s[i]) > tolower(t[i])) { return 1; } } return 0; } #define CASECMP(s, m, n) \ do { \ int tmp__; \ if (!(tmp__ = my_memcasecmp((s)->buf, m, (s)->length < (n) ? (s)->length : (n)))) { \ if ((s)->length < (n)) \ return -1; \ if ((s)->length > (n)) \ return 1; \ } \ return tmp__; \ } while (0) int St_casecmp(const String *s, const String *t) { CASECMP(s, t->buf, t->length); } int St_casecmp_m(const String *s, const void *m, size_t n) { CASECMP(s, m, n); } int St_casecmp_s(const String *s, const char *tz) { size_t length = strlen(tz); CASECMP(s, tz, length); } #define NCASECMP(s, m, n) \ do { \ return my_memcasecmp((s)->buf, m, n); \ } while (0) int St_ncasecmp(const String *s, const String *t) { NCASECMP(s, t->buf, t->length); } int St_ncasecmp_m(const String *s, const void *m, size_t n) { NCASECMP(s, m, n); } int St_ncasecmp_s(const String *s, const char *tz) { size_t length = strlen(tz); NCASECMP(s, tz, length); } #endif #define STR(s, m, n) \ do { \ size_t i__; \ if ((n) == 0) \ return 0; \ if ((s)->length < (n)) \ return -1; \ for (i__ = 0; i__ <= (s)->length - (n); ++i__) { \ if (!memcmp((s)->buf + i__, m, n)) \ return i__; \ } \ return -1; \ } while (0) size_t St_str(const String *s, const String *t) { STR(s, t->buf, t->length); } size_t St_str_m(const String *s, const void *m, size_t n) { STR(s, m, n); } #if 0 size_t St_str_s(const String *s, const char *tz) { size_t length = strlen(tz); STR(s, tz, length); } #endif #define RSTR(s, m, n) \ do { \ size_t i__; \ if ((n) == 0) \ return (s)->length; \ if ((s)->length < (n)) \ return -1; \ for (i__ = (s)->length - (n) + 1; i__; --i__) { \ if (!memcmp((s)->buf + i__ - 1, m, n)) \ return i__ - 1; \ } \ return -1; \ } while (0) #if 0 size_t St_rstr(const String *s, const String *t) { RSTR(s, t->buf, t->length); } #endif size_t St_rstr_m(const String *s, const void *m, size_t n) { RSTR(s, m, n); } size_t St_rstr_s(const String *s, const char *tz) { size_t length = strlen(tz); RSTR(s, tz, length); } size_t St_stro_m(const String *s, size_t off, const void *m, size_t n) { size_t i; assert(off <= s->length); if (n == 0) { return off; } if (n > s->length - off) { return -1; } for (i = off; i < s->length - n; ++i) { if (memcmp(s->buf + i, m, n) == 0) { return i; } } return -1; } size_t St_rstro_m(const String *s, size_t off, const void *m, size_t n) { size_t i; assert(off <= s->length); if (n == 0) { return off; } if (n > s->length) { return -1; } i = off; if (i > s->length - n) { i = s->length - n; } for (; i + 1u; --i) { if (memcmp(s->buf + i, m, n) == 0) { return i; } } return -1; } #define CPY(s, m, n) \ do { \ if ((s)->size - (s)->offset <= (n)) { \ OFFSET_OFF(s); \ if ((s)->size <= (n)) { \ (s)->buf = xrealloc((s)->buf, (n) + 1); \ (s)->size = (n) + 1; \ } \ } \ memcpy((s)->buf, m, (s)->length = (n)); \ (s)->buf[n] = '\0'; \ } while (0) void St_cpy(String *s, const String *t) { CPY(s, t->buf, t->length); } void St_cpy_m(String *s, const void *m, size_t n) { CPY(s, m, n); } void St_cpy_s(String *s, const char *tz) { size_t length = strlen(tz); CPY(s, tz, length); } void St_cpy_c(String *s, int c) { unsigned char tmp = c; CPY(s, &tmp, 1); } static void cat(String *s, const void *m, size_t n) { if (s->size - s->offset <= s->length + n) { OFFSET_OFF(s); if (s->size <= s->length + n) { do { s->size = s->size / 2 * 3 + 1; } while (s->size <= s->length + n); s->buf = xrealloc(s->buf, s->size); } } memcpy(s->buf + s->length, m, n); s->buf[s->length += n] = '\0'; } void St_cat(String *s, const String *t) { cat(s, t->buf, t->length); } void St_cat_m(String *s, const void *m, size_t n) { cat(s, m, n); } void St_cat_s(String *s, const char *tz) { cat(s, tz, strlen(tz)); } void St_cat_c(String *s, int c) { unsigned char tmp = c; cat(s, &tmp, 1); } #define TAC(s, m, n) \ do { \ if ((s)->offset >= (n)) { \ (s)->buf -= (n); \ (s)->offset -= (n); \ } else if ((s)->size <= (s)->length + (n)) { \ (s)->buf -= (s)->offset; \ (s)->buf = xrealloc((s)->buf, (s)->length + (n) + 1); \ (s)->size = (s)->length + (n) + 1; \ memmove((s)->buf + (n), (s)->buf + (s)->offset, (s)->length + 1); \ (s)->offset = 0; \ } else { \ memmove((s)->buf + (n), (s)->buf, (s)->length + 1); \ } \ memcpy((s)->buf, m, n); \ (s)->length += (n); \ } while (0) #if 0 void St_tac(String *s, const String *t) { TAC(s, t->buf, t->length); } #endif void St_tac_m(String *s, const void *m, size_t n) { TAC(s, m, n); } void St_tac_s(String *s, const char *tz) { size_t length = strlen(tz); TAC(s, tz, length); } void St_tac_c(String *s, int c) { unsigned char tmp = c; TAC(s, &tmp, 1); } void St_reverse(String *s) { size_t i; char tmp; for (i = 0; i < s->length / 2; ++i) { tmp = s->buf[i]; s->buf[i] = s->buf[s->length - i - 1]; s->buf[s->length - i - 1] = tmp; } } #if 0 void St_map(String *s, int (*better)(int)) { size_t i; int tmp; for (i = 0; i < s->length; ++i) { tmp = better((unsigned char)s->buf[i]); if (tmp == EOF) { s->buf[s->length = i] = '\0'; return; } s->buf[i] = tmp; } while ((tmp = better(EOF)) != EOF) { if (s->size <= s->length + 1) { OFFSET_OFF(s); XREALLOC(s->buf, s->size * 2); s->size *= 2; } s->buf[s->length++] = tmp; s->buf[s->length] = '\0'; } } #endif void St_grep(String *s, int (*good)(int)) { size_t r, w; for (r = w = 0; r < s->length; ++r) { if (good((unsigned char)s->buf[r])) { s->buf[w++] = s->buf[r]; } } s->buf[s->length = w] = '\0'; } void St_upper(String *s) { size_t i; for (i = 0; i < s->length; ++i) { s->buf[i] = toupper((unsigned char)s->buf[i]); } } void St_lower(String *s) { size_t i; for (i = 0; i < s->length; ++i) { s->buf[i] = tolower((unsigned char)s->buf[i]); } } void St_del(String *s, size_t p, size_t n) { if (n == 0 || s->length < p) return; if (s->length < n || s->length < p + n) { n = s->length - p; } if (p + n == s->length) { s->buf[p] = '\0'; } else if (p == 0) { s->offset += n; s->buf += n; } else { memmove(s->buf + p, s->buf + n + p, s->length - p - n); } s->length -= n; } #if 0 #define INS(s, p, m, n) \ do { \ if ((n) == 0 || (s)->length < (p)) \ return; \ if ((n) <= (s)->offset) { \ (s)->offset -= (n); \ (s)->buf -= (n); \ memmove((s)->buf, (s)->buf + (n), p); \ } else { \ if ((s)->size - (s)->offset <= (s)->length + (n)) { \ OFFSET_OFF(s); \ XREALLOC((s)->buf, (s)->length + (n) + 1); \ (s)->size = (s)->length + (n) + 1; \ } \ memmove((s)->buf + (p) + (n), (s)->buf + (p), (s)->length - (p) + 1); \ } \ memcpy((s)->buf + (p), m, n); \ (s)->length += (n); \ } while (0) void St_ins(String *s, size_t p, const String *t) { INS(s, p, t->buf, t->length); } void St_ins_m(String *s, size_t p, const void *m, size_t n) { INS(s, p, m, n); } void St_ins_s(String *s, size_t p, const char *tz) { size_t length = strlen(tz); INS(s, p, tz, length); } void St_ins_c(String *s, size_t p, int c) { unsigned char tmp = c; INS(s, p, &tmp, 1); } #endif void St_substr(String *l, String *s, size_t p, size_t n, const String *r) { if (l) { if (p >= s->length) { St_zero(l); } else { size_t length = n; if (p + length > s->length) { length = s->length - p; } St_cpy_m(l, s->buf + p, length); } } if (r) { size_t gap = 0; if (p + n > s->length) { if (p > s->length) { n = 0; gap = p - s->length; } else { n = s->length - p; } } St_grow(s, s->length + r->length - n + gap); if (gap) { memset(s->buf + s->length, '\0', gap); } else if (r->length != n && s->length - p - n) { memmove(s->buf + p + r->length, s->buf + p + n, s->length - p - n); } memcpy(s->buf + p, r->buf, r->length); s->buf[s->length += r->length - n + gap] = '\0'; } } #if HAVE_VSNPRINTF_P size_t St_xprintf(String *s, const char *fmt, ...) { va_list ap; int tmp; va_start(ap, fmt); tmp = vsnprintf(s->buf, s->size, fmt, ap); va_end(ap); if (tmp < 0) { do { St_grow(s, s->size * 2); va_start(ap, fmt); tmp = vsnprintf(s->buf, s->size, fmt, ap); va_end(ap); } while (tmp < 0); } else if (tmp + 1u >= s->size) { St_grow(s, tmp); s->length = 0; va_start(ap, fmt); tmp = vsnprintf(s->buf, s->size, fmt, ap); va_end(ap); if (tmp < 0) { s->buf[0] = '\0'; return -1; } } return s->length = tmp; } #endif void St_num(String *s, double d) { #if HAVE_VSNPRINTF_P St_xprintf(s, "%.*g", DBL_DIG, d); #else St_grow(s, 255); s->length = sprintf(s->buf, "%.*g", DBL_DIG, d); #endif } #if 0 size_t St_write(const String *s, FILE *fp) { return ST_WRITE(s, fp); } #endif #define MIN(a, b) ((a) < (b) ? (a) : (b)) size_t St_read(String *s, FILE *fp, size_t n) { char buf[4096]; size_t red; St_zero(s); while (n && !feof(fp) && (red = fread(buf, sizeof *buf, MIN(n, sizeof buf / sizeof *buf), fp))) { St_cat_m(s, buf, red); n -= red; } return s->length; } #if 0 int St_getline(String *s, FILE *fp, int n) { int c; OFFSET_OFF(s); for (s->length = 0; (c = getc(fp)) != EOF; ++s->length) { if (s->size <= s->length + 1) { XREALLOC(s->buf, s->size * 2); s->size *= 2; } s->buf[s->length] = c; if (c == n) break; } s->buf[s->length] = '\0'; return s->length != 0; } void St_getfile(String *s, FILE *fp) { size_t tmp; OFFSET_OFF(s); if (s->size <= BUFSIZ) { XREALLOC(s->buf, BUFSIZ + 1); s->size = BUFSIZ + 1; } for (s->length = 0; (tmp = fread(s->buf + s->length, 1, BUFSIZ, fp)); ) { s->length += tmp; if (s->size <= s->length + BUFSIZ + 1) { XREALLOC(s->buf, s->size * 2); s->size *= 2; } } s->buf[s->length] = '\0'; } #endif size_t St_hash(const String *s, size_t h) { return u_hash(St_ptr(s), St_len(s), h); }