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);
+}