Mercurial > repo
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ploki/Str.c Fri Dec 20 22:18:50 2013 +0000 @@ -0,0 +1,794 @@ +#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); +}