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