Mercurial > repo
view src/ploki/Str.c @ 8427:1fc808cd5b1f
<b_jonas> learn can\'t is the most frequent word whose pronunciation varies between /\xc9\x91\xcb\x90/ and /\xc3\xa6/ depending on dialect. The list is: advance after answer ask aunt brass can\'t cast castle chance class command dance demand draft enhance example fast father glass graph grass half last laugh mask master nasty pass past path plant rather sample shan\'t staff task vast
author | HackBot |
---|---|
date | Thu, 09 Jun 2016 21:28:47 +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); }