1*822ca327SBaptiste Daroussin /* $Id: mstring.c,v 1.10 2023/02/26 10:15:01 tom Exp $ */
20c8de5b0SBaptiste Daroussin
30c8de5b0SBaptiste Daroussin #include <stdlib.h>
40c8de5b0SBaptiste Daroussin #include <stdio.h>
50c8de5b0SBaptiste Daroussin #include <stdarg.h>
60c8de5b0SBaptiste Daroussin #include <ctype.h>
70c8de5b0SBaptiste Daroussin #include <string.h>
80c8de5b0SBaptiste Daroussin #include "defs.h"
90c8de5b0SBaptiste Daroussin
100c8de5b0SBaptiste Daroussin /* parameters about string length. HEAD is the starting size and
110c8de5b0SBaptiste Daroussin ** HEAD+TAIL should be a power of two */
120c8de5b0SBaptiste Daroussin #define HEAD 24
130c8de5b0SBaptiste Daroussin #define TAIL 8
140c8de5b0SBaptiste Daroussin
15497dcf4cSBaptiste Daroussin static char *buf_ptr;
16497dcf4cSBaptiste Daroussin static size_t buf_len;
17497dcf4cSBaptiste Daroussin
180c8de5b0SBaptiste Daroussin void
msprintf(struct mstring * s,const char * fmt,...)190c8de5b0SBaptiste Daroussin msprintf(struct mstring *s, const char *fmt, ...)
200c8de5b0SBaptiste Daroussin {
210c8de5b0SBaptiste Daroussin va_list args;
220c8de5b0SBaptiste Daroussin size_t len;
23497dcf4cSBaptiste Daroussin #ifdef HAVE_VSNPRINTF
24497dcf4cSBaptiste Daroussin int changed;
25497dcf4cSBaptiste Daroussin #endif
260c8de5b0SBaptiste Daroussin
270c8de5b0SBaptiste Daroussin if (!s || !s->base)
280c8de5b0SBaptiste Daroussin return;
290c8de5b0SBaptiste Daroussin
30497dcf4cSBaptiste Daroussin if (buf_len == 0)
31497dcf4cSBaptiste Daroussin {
32497dcf4cSBaptiste Daroussin buf_ptr = malloc(buf_len = 4096);
33497dcf4cSBaptiste Daroussin }
34497dcf4cSBaptiste Daroussin if (buf_ptr == 0)
35497dcf4cSBaptiste Daroussin {
36497dcf4cSBaptiste Daroussin return;
37497dcf4cSBaptiste Daroussin }
38497dcf4cSBaptiste Daroussin
39497dcf4cSBaptiste Daroussin #ifdef HAVE_VSNPRINTF
40497dcf4cSBaptiste Daroussin do
41497dcf4cSBaptiste Daroussin {
42497dcf4cSBaptiste Daroussin va_start(args, fmt);
43497dcf4cSBaptiste Daroussin len = (size_t)vsnprintf(buf_ptr, buf_len, fmt, args);
44497dcf4cSBaptiste Daroussin va_end(args);
45497dcf4cSBaptiste Daroussin if ((changed = (len > buf_len)) != 0)
46497dcf4cSBaptiste Daroussin {
47497dcf4cSBaptiste Daroussin char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2);
48497dcf4cSBaptiste Daroussin if (new_ptr == 0)
49497dcf4cSBaptiste Daroussin {
50497dcf4cSBaptiste Daroussin free(buf_ptr);
51497dcf4cSBaptiste Daroussin buf_ptr = 0;
52497dcf4cSBaptiste Daroussin return;
53497dcf4cSBaptiste Daroussin }
54497dcf4cSBaptiste Daroussin buf_ptr = new_ptr;
55497dcf4cSBaptiste Daroussin }
56497dcf4cSBaptiste Daroussin }
57497dcf4cSBaptiste Daroussin while (changed);
58497dcf4cSBaptiste Daroussin #else
59497dcf4cSBaptiste Daroussin va_start(args, fmt);
60497dcf4cSBaptiste Daroussin len = (size_t)vsprintf(buf_ptr, fmt, args);
61497dcf4cSBaptiste Daroussin va_end(args);
62497dcf4cSBaptiste Daroussin if (len >= buf_len)
63497dcf4cSBaptiste Daroussin return;
64497dcf4cSBaptiste Daroussin #endif
65497dcf4cSBaptiste Daroussin
660c8de5b0SBaptiste Daroussin if (len > (size_t)(s->end - s->ptr))
670c8de5b0SBaptiste Daroussin {
68497dcf4cSBaptiste Daroussin char *new_base;
690c8de5b0SBaptiste Daroussin size_t cp = (size_t)(s->ptr - s->base);
700c8de5b0SBaptiste Daroussin size_t cl = (size_t)(s->end - s->base);
710c8de5b0SBaptiste Daroussin size_t nl = cl;
720c8de5b0SBaptiste Daroussin while (len > (nl - cp))
730c8de5b0SBaptiste Daroussin nl = nl + nl + TAIL;
74497dcf4cSBaptiste Daroussin if ((new_base = realloc(s->base, nl)))
750c8de5b0SBaptiste Daroussin {
76497dcf4cSBaptiste Daroussin s->base = new_base;
770c8de5b0SBaptiste Daroussin s->ptr = s->base + cp;
780c8de5b0SBaptiste Daroussin s->end = s->base + nl;
790c8de5b0SBaptiste Daroussin }
800c8de5b0SBaptiste Daroussin else
810c8de5b0SBaptiste Daroussin {
82497dcf4cSBaptiste Daroussin free(s->base);
83497dcf4cSBaptiste Daroussin s->base = 0;
84497dcf4cSBaptiste Daroussin s->ptr = 0;
85497dcf4cSBaptiste Daroussin s->end = 0;
860c8de5b0SBaptiste Daroussin return;
870c8de5b0SBaptiste Daroussin }
880c8de5b0SBaptiste Daroussin }
89497dcf4cSBaptiste Daroussin memcpy(s->ptr, buf_ptr, len);
900c8de5b0SBaptiste Daroussin s->ptr += len;
910c8de5b0SBaptiste Daroussin }
920c8de5b0SBaptiste Daroussin
930c8de5b0SBaptiste Daroussin int
mputchar(struct mstring * s,int ch)940c8de5b0SBaptiste Daroussin mputchar(struct mstring *s, int ch)
950c8de5b0SBaptiste Daroussin {
960c8de5b0SBaptiste Daroussin if (!s || !s->base)
970c8de5b0SBaptiste Daroussin return ch;
980c8de5b0SBaptiste Daroussin if (s->ptr == s->end)
990c8de5b0SBaptiste Daroussin {
1000c8de5b0SBaptiste Daroussin size_t len = (size_t)(s->end - s->base);
1010c8de5b0SBaptiste Daroussin if ((s->base = realloc(s->base, len + len + TAIL)))
1020c8de5b0SBaptiste Daroussin {
1030c8de5b0SBaptiste Daroussin s->ptr = s->base + len;
1040c8de5b0SBaptiste Daroussin s->end = s->base + len + len + TAIL;
1050c8de5b0SBaptiste Daroussin }
1060c8de5b0SBaptiste Daroussin else
1070c8de5b0SBaptiste Daroussin {
1080c8de5b0SBaptiste Daroussin s->ptr = s->end = 0;
1090c8de5b0SBaptiste Daroussin return ch;
1100c8de5b0SBaptiste Daroussin }
1110c8de5b0SBaptiste Daroussin }
1120c8de5b0SBaptiste Daroussin *s->ptr++ = (char)ch;
1130c8de5b0SBaptiste Daroussin return ch;
1140c8de5b0SBaptiste Daroussin }
1150c8de5b0SBaptiste Daroussin
1160c8de5b0SBaptiste Daroussin struct mstring *
msnew(void)1170c8de5b0SBaptiste Daroussin msnew(void)
1180c8de5b0SBaptiste Daroussin {
119497dcf4cSBaptiste Daroussin struct mstring *n = TMALLOC(struct mstring, 1);
1200c8de5b0SBaptiste Daroussin
1210c8de5b0SBaptiste Daroussin if (n)
1220c8de5b0SBaptiste Daroussin {
123497dcf4cSBaptiste Daroussin if ((n->base = n->ptr = MALLOC(HEAD)) != 0)
1240c8de5b0SBaptiste Daroussin {
1250c8de5b0SBaptiste Daroussin n->end = n->base + HEAD;
1260c8de5b0SBaptiste Daroussin }
1270c8de5b0SBaptiste Daroussin else
1280c8de5b0SBaptiste Daroussin {
1290c8de5b0SBaptiste Daroussin free(n);
1300c8de5b0SBaptiste Daroussin n = 0;
1310c8de5b0SBaptiste Daroussin }
1320c8de5b0SBaptiste Daroussin }
1330c8de5b0SBaptiste Daroussin return n;
1340c8de5b0SBaptiste Daroussin }
1350c8de5b0SBaptiste Daroussin
136b53bb29fSJung-uk Kim struct mstring *
msrenew(char * value)137b53bb29fSJung-uk Kim msrenew(char *value)
138b53bb29fSJung-uk Kim {
139b53bb29fSJung-uk Kim struct mstring *r = 0;
140b53bb29fSJung-uk Kim if (value != 0)
141b53bb29fSJung-uk Kim {
142b53bb29fSJung-uk Kim r = msnew();
143b53bb29fSJung-uk Kim r->base = value;
144b53bb29fSJung-uk Kim r->end = value + strlen(value);
145b53bb29fSJung-uk Kim r->ptr = r->end;
146b53bb29fSJung-uk Kim }
147b53bb29fSJung-uk Kim return r;
148b53bb29fSJung-uk Kim }
149b53bb29fSJung-uk Kim
1500c8de5b0SBaptiste Daroussin char *
msdone(struct mstring * s)1510c8de5b0SBaptiste Daroussin msdone(struct mstring *s)
1520c8de5b0SBaptiste Daroussin {
1530c8de5b0SBaptiste Daroussin char *r = 0;
1540c8de5b0SBaptiste Daroussin if (s)
1550c8de5b0SBaptiste Daroussin {
1560c8de5b0SBaptiste Daroussin mputc(s, 0);
1570c8de5b0SBaptiste Daroussin r = s->base;
1580c8de5b0SBaptiste Daroussin free(s);
1590c8de5b0SBaptiste Daroussin }
1600c8de5b0SBaptiste Daroussin return r;
1610c8de5b0SBaptiste Daroussin }
1620c8de5b0SBaptiste Daroussin
1630c8de5b0SBaptiste Daroussin #if defined(YYBTYACC)
1640c8de5b0SBaptiste Daroussin /* compare two strings, ignoring whitespace, except between two letters or
1650c8de5b0SBaptiste Daroussin ** digits (and treat all of these as equal) */
1660c8de5b0SBaptiste Daroussin int
strnscmp(const char * a,const char * b)1670c8de5b0SBaptiste Daroussin strnscmp(const char *a, const char *b)
1680c8de5b0SBaptiste Daroussin {
1690c8de5b0SBaptiste Daroussin while (1)
1700c8de5b0SBaptiste Daroussin {
1712aca18c7SJung-uk Kim while (isspace(UCH(*a)))
1720c8de5b0SBaptiste Daroussin a++;
1732aca18c7SJung-uk Kim while (isspace(UCH(*b)))
1740c8de5b0SBaptiste Daroussin b++;
1750c8de5b0SBaptiste Daroussin while (*a && *a == *b)
1760c8de5b0SBaptiste Daroussin a++, b++;
1772aca18c7SJung-uk Kim if (isspace(UCH(*a)))
1780c8de5b0SBaptiste Daroussin {
1792aca18c7SJung-uk Kim if (isalnum(UCH(a[-1])) && isalnum(UCH(*b)))
1800c8de5b0SBaptiste Daroussin break;
1810c8de5b0SBaptiste Daroussin }
1822aca18c7SJung-uk Kim else if (isspace(UCH(*b)))
1830c8de5b0SBaptiste Daroussin {
1842aca18c7SJung-uk Kim if (isalnum(UCH(b[-1])) && isalnum(UCH(*a)))
1850c8de5b0SBaptiste Daroussin break;
1860c8de5b0SBaptiste Daroussin }
1870c8de5b0SBaptiste Daroussin else
1880c8de5b0SBaptiste Daroussin break;
1890c8de5b0SBaptiste Daroussin }
1900c8de5b0SBaptiste Daroussin return *a - *b;
1910c8de5b0SBaptiste Daroussin }
1920c8de5b0SBaptiste Daroussin
1930c8de5b0SBaptiste Daroussin unsigned int
strnshash(const char * s)1940c8de5b0SBaptiste Daroussin strnshash(const char *s)
1950c8de5b0SBaptiste Daroussin {
1960c8de5b0SBaptiste Daroussin unsigned int h = 0;
1970c8de5b0SBaptiste Daroussin
1980c8de5b0SBaptiste Daroussin while (*s)
1990c8de5b0SBaptiste Daroussin {
2002aca18c7SJung-uk Kim if (!isspace(UCH(*s)))
2010c8de5b0SBaptiste Daroussin h = (h << 5) - h + (unsigned char)*s;
2020c8de5b0SBaptiste Daroussin s++;
2030c8de5b0SBaptiste Daroussin }
2040c8de5b0SBaptiste Daroussin return h;
2050c8de5b0SBaptiste Daroussin }
2060c8de5b0SBaptiste Daroussin #endif
207497dcf4cSBaptiste Daroussin
208497dcf4cSBaptiste Daroussin #ifdef NO_LEAKS
209497dcf4cSBaptiste Daroussin void
mstring_leaks(void)210497dcf4cSBaptiste Daroussin mstring_leaks(void)
211497dcf4cSBaptiste Daroussin {
212497dcf4cSBaptiste Daroussin free(buf_ptr);
213497dcf4cSBaptiste Daroussin buf_ptr = 0;
214497dcf4cSBaptiste Daroussin buf_len = 0;
215497dcf4cSBaptiste Daroussin }
216497dcf4cSBaptiste Daroussin #endif
217