/* Custom string builder, comparable to functionality provided by SV* * functions, but with less magic and better inlineable. */ typedef struct { size_t len; size_t size; char *buf; } fustr; /* No need to call this, an empty fustr is already usable. * This allows setting a custom initial size. */ static void fustr_init(fustr *s, size_t prealloc) { s->len = 0; s->size = prealloc; s->buf = safemalloc(prealloc); } static void fustr_grow(fustr *s, size_t add) { if (s->size == 0) s->size = 512; while (s->size < s->len + add) s->size *= 2; s->buf = saferealloc(s->buf, s->size); } #define fustr_reserve(s, n) do {\ if (UNLIKELY((s)->size < (s)->len + (n))) fustr_grow(s, n);\ } while(0) #define fustr_write(s, str, n) do {\ fustr_reserve(s, n);\ memcpy((s)->buf+(s)->len, str, (n));\ (s)->len += (n);\ } while(0) /* Move the string buffer into a new SV; fustr should be considered invalid after this call. * Does not set the UTF8 flag. */ static SV *fustr_sv(fustr *s) { SV *r = newSV(0); fustr_write(s, "", 1); // trailing nul sv_usepvn_flags(r, s->buf, s->len-1, SV_HAS_TRAILING_NUL); // TODO: SvPV_shrink_to_cur? return r; }