It works and can format all "plain" Perl data, but has a few known bugs and limitations that still need to be worked out. It's about 8x smaller than JSON::XS's encoder and *much* smaller than Cpanel::JSON::XS, but this is just a first attempt, it'll grow.
43 lines
1.2 KiB
C
43 lines
1.2 KiB
C
/* 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;
|
|
}
|