#include "stralloc.h" #include #include "alloc.h" #include "byte.h" #include "str.h" /** @file stralloc.c @author djb @source qmail, ucspi-tcp @brief genious dynamic string handling */ int stralloc_starts(stralloc *sa, const char *s) { int len; len = str_len(s); return (sa->len >= len) && byte_equal(s, len, sa->s); } int stralloc_cat(stralloc *sato, stralloc *safrom) { return stralloc_catb(sato, safrom->s, safrom->len); } int stralloc_catb(stralloc *sa, const char *s, unsigned int n) { if (!sa->s) return stralloc_copyb(sa, s, n); if (!stralloc_readyplus(sa, n + 1)) return 0; byte_copy(sa->s + sa->len, n, s); sa->len += n; sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ return 1; } int stralloc_cats(stralloc *sa, const char *s) { return stralloc_catb(sa, s, str_len(s)); } int stralloc_copy(stralloc *sato, stralloc *safrom) { return stralloc_copyb(sato, safrom->s, safrom->len); } int stralloc_ready(stralloc *sa, size_t len) { size_t wanted = len + (len >> 3) + 30; /* heuristic from djb */ if (wanted < len) wanted = len; if (!sa->s || sa->a < len) { char *tmp; if (!(tmp = realloc(sa->s, wanted))) // !!! needs stdlib (realloc) return 0; sa->a = wanted; sa->s = tmp; } return 1; } int stralloc_readyplus(stralloc *sa, size_t len) { if (sa->s) { if (sa->len + len < len) return 0; /* catch integer overflow */ return stralloc_ready(sa, sa->len + len); } else return stralloc_ready(sa, len); } int stralloc_copyb(stralloc *sa, const char *s, unsigned int n) { if (!stralloc_ready(sa, n + 1)) return 0; byte_copy(sa->s, n, s); sa->len = n; sa->s[n] = 'Z'; /* ``offensive programming'' */ return 1; } int stralloc_copys(stralloc *sa, const char *s) { return stralloc_copyb(sa, s, str_len(s)); } int stralloc_catulong0(stralloc *sa, unsigned long u, unsigned int n) { unsigned int len; unsigned long q; char *s; len = 1; q = u; while (q > 9) { ++len; q /= 10; } if (len < n) len = n; if (!stralloc_readyplus(sa, len)) return 0; s = sa->s + sa->len; sa->len += len; while (len) { s[--len] = '0' + (u % 10); u /= 10; } return 1; } int stralloc_catlong0(stralloc *sa, long l, unsigned int n) { if (l < 0) { if (!stralloc_append(sa, "-")) return 0; l = -l; } return stralloc_catulong0(sa, l, n); } int stralloc_append(stralloc *sa, const char *in) { if (stralloc_readyplus(sa, 1)) { sa->s[sa->len] = *in; ++sa->len; return 1; } return 0; } void stralloc_free(stralloc *sa) { if (sa->s) free(sa->s); sa->s = 0; sa->a = sa->len = 0; }