1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include "mstring.h"
7 
8 /* parameters about string length.  START is the starting size and
9 ** START+TAIL should be a power of two */
10 #define START	24
11 #define TAIL	8
12 
msprintf(struct mstring * s,const char * fmt,...)13 void msprintf(struct mstring *s, const char *fmt, ...)
14 {
15 static char	buf[4096];	/* a big static buffer */
16 va_list		args;
17 size_t		len;
18 
19     if (!s || !s->base) return;
20     va_start(args, fmt);
21     vsprintf(buf, fmt, args);
22     va_end(args);
23 
24     len = strlen(buf);
25     if (len > (s->end - s->ptr)) {
26 	int	cp = s->ptr - s->base, cl = s->end - s->base, nl = cl;
27 	while (len > (nl - cp))
28 	    nl = nl + nl + TAIL;
29 	if ((s->base = realloc(s->base, nl))) {
30 	    s->ptr = s->base + cp;
31 	    s->end = s->base + nl; }
32 	else {
33 	    s->ptr = s->end = 0;
34 	    return; } }
35     memcpy(s->ptr, buf, len);
36     s->ptr += len;
37 }
38 
mputchar(struct mstring * s,int ch)39 int mputchar(struct mstring *s, int ch)
40 {
41     if (!s || !s->base) return ch;
42     if (s->ptr == s->end) {
43 	int len = s->end - s->base;
44 	if ((s->base = realloc(s->base, len+len+TAIL))) {
45 	    s->ptr = s->base + len;
46 	    s->end = s->base + len+len+TAIL; }
47 	else {
48 	    s->ptr = s->end = 0;
49 	    return ch; } }
50     *s->ptr++ = ch;
51     return ch;
52 }
53 
msnew(void)54 struct mstring *msnew(void) {
55     struct mstring *n = malloc(sizeof(struct mstring));
56 
57     if (n && (n->base = n->ptr = malloc(START)))
58 	n->end = n->base + START;
59     else if (n) {
60 	free(n);
61 	n = 0; }
62     return n;
63 }
64 
mstrim(struct mstring * s,const char * trim)65 void mstrim(struct mstring *s, const char *trim)
66 {
67     while (s && s->ptr > s->base && strchr(trim, s->ptr[-1]))
68 	s->ptr--;
69 }
70 
msdone(struct mstring * s)71 char *msdone(struct mstring *s)
72 {
73 char	*r = 0;
74     if (s) {
75 	mputc(s, 0);
76 	r = s->base;
77 	free(s); }
78     return r;
79 }
80 
81 /* compare two strings, ignoring whitespace, except between two letters or
82 ** digits (and treat all of these as equal) */
strnscmp(const char * a,const char * b)83 int strnscmp(const char *a, const char *b)
84 {
85     while(1) {
86 	while (isspace(*a)) a++;
87 	while (isspace(*b)) b++;
88 	while (*a && *a == *b) a++,b++;
89 	if (isspace(*a)) {
90 	    if (isalnum(a[-1]) && isalnum(*b))
91 		break; }
92 	else if (isspace(*b)) {
93 	    if (isalnum(b[-1]) && isalnum(*a))
94 		break; }
95 	else
96 	    break; }
97     return *a - *b;
98 }
99 
strnshash(const char * s)100 unsigned int strnshash(const char *s)
101 {
102 unsigned int	h = 0;
103 
104     while (*s) {
105 	if (!isspace(*s))
106 	    h = (h<<5) - h + *s;
107 	s++; }
108     return h;
109 }
110