X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/fb467548a1501cae398e5bdab6794926da2690ef..ee9b1404a97247490a09fcf10af83a76a3d3d72d:/dstr.c diff --git a/dstr.c b/dstr.c index 6304351..e43e138 100644 --- a/dstr.c +++ b/dstr.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: dstr.c,v 1.6 1999/05/21 08:38:33 mdw Exp $ + * $Id: dstr.c,v 1.9 1999/07/06 19:16:06 mdw Exp $ * * Handle dynamically growing strings * @@ -30,6 +30,15 @@ /*----- Revision history --------------------------------------------------* * * $Log: dstr.c,v $ + * Revision 1.9 1999/07/06 19:16:06 mdw + * Simplify buffer-growing algorithm. Just double it each time. + * + * Revision 1.8 1999/06/01 09:47:52 mdw + * Fix nasty bugs in `dstr_vputf'. + * + * Revision 1.7 1999/05/21 22:14:30 mdw + * Take advantage of the new dynamic string macros. + * * Revision 1.6 1999/05/21 08:38:33 mdw * Implement some more functions in terms of macros. * @@ -66,8 +75,21 @@ /*----- Tunable constants -------------------------------------------------*/ +/* --- Buffer expansion parameters --- * + * + * If the buffer is empty, it is set to @DSTR_INITSZ@ bytes in size. + * Otherwise, it's set to the next power of two that's large enough. This is + * memory-hungry, but efficient. + */ + #define DSTR_INITSZ 256 /* Initial buffer size */ -#define DSTR_INCSZ 4096 /* Threshhold for doubling */ + +/* --- Parameters for @dstr_putf@ --- * + * + * For each format specifier, at least @DSTR_PUTFSTEP@ bytes are ensured + * before writing the formatted result. + */ + #define DSTR_PUTFSTEP 64 /* Buffer size for @putf@ */ /*----- Main code ---------------------------------------------------------*/ @@ -126,22 +148,14 @@ void dstr_ensure(dstr *d, size_t sz) if (rq <= d->sz) return; - /* --- Grow the buffer --- * - * - * For small buffers, just double the size. For big buffers, make them - * a multiple of some suitably large chunk size. - */ + /* --- Grow the buffer --- */ nsz = d->sz; - do { - if (nsz == 0) - nsz = DSTR_INITSZ; - else if (d->sz < 0x1000) - nsz <<= 1; - else - nsz = (rq + 0x0fff) & ~0x0fff; - } while (rq > nsz); + if (nsz == 0 && rq < DSTR_INITSZ) + nsz = DSTR_INITSZ; + else + do nsz <<= 1; while (nsz < rq); if (d->buf) d->buf = xrealloc(d->buf, nsz); @@ -205,11 +219,11 @@ int dstr_vputf(dstr *d, const char *p, va_list ap) const char *q = p; size_t n = d->len; size_t sz; + dstr dd = DSTR_INIT; while (*p) { unsigned f; int wd, prec; - dstr dd; enum { f_short = 1, @@ -233,7 +247,6 @@ int dstr_vputf(dstr *d, const char *p, va_list ap) /* --- Sort out the various silly flags and things --- */ - dstr_create(&dd); DPUTC(&dd, '%'); f = 0; sz = DSTR_PUTFSTEP; @@ -276,7 +289,7 @@ int dstr_vputf(dstr *d, const char *p, va_list ap) goto getnum; default: if (isdigit((unsigned char)*p)) { - f |= f_prec; + f |= f_wd; ip = &wd; goto getnum; } @@ -289,12 +302,12 @@ int dstr_vputf(dstr *d, const char *p, va_list ap) DENSURE(&dd, DSTR_PUTFSTEP); dd.len += sprintf(dd.buf + dd.len, "%i", *ip); } else { - *ip = *p + '0'; + *ip = *p - '0'; DPUTC(&dd, *p); p++; while (isdigit((unsigned char)*p)) { DPUTC(&dd, *p); - *ip = 10 * *ip + *p++ + '0'; + *ip = 10 * *ip + *p++ - '0'; } } break; @@ -396,13 +409,14 @@ int dstr_vputf(dstr *d, const char *p, va_list ap) } formatted: - dstr_destroy(&dd); + DRESET(&dd); q = ++p; } DPUTM(d, q, p - q); finished: DPUTZ(d); + DDESTROY(&dd); return (d->len - n); }