#include "str.h" #include "mem.h" #include #include #include #include static void need(tobi_sb *sb, size_t add) { size_t req = tobi_xadd_size(tobi_xadd_size(sb->len, add), 1u); if (req <= sb->cap) { return; } size_t cap = tobi_xgrow_cap(sb->cap, req, 64u); sb->buf = tobi_xrealloc(sb->buf, cap); sb->cap = cap; } void tobi_sb_init(tobi_sb *sb) { sb->buf = NULL; sb->len = 0; sb->cap = 0; need(sb, 0); sb->buf[0] = '\0'; } void tobi_sb_free(tobi_sb *sb) { free(sb->buf); sb->buf = NULL; sb->len = 0; sb->cap = 0; } void tobi_sb_add(tobi_sb *sb, const char *s) { tobi_sb_addn(sb, s, strlen(s)); } void tobi_sb_addn(tobi_sb *sb, const char *s, size_t n) { need(sb, n); memcpy(sb->buf + sb->len, s, n); sb->len += n; sb->buf[sb->len] = '\0'; } void tobi_sb_ch(tobi_sb *sb, char c) { need(sb, 1); sb->buf[sb->len++] = c; sb->buf[sb->len] = '\0'; } void tobi_sb_printf(tobi_sb *sb, const char *fmt, ...) { va_list ap; va_start(ap, fmt); va_list cp; va_copy(cp, ap); int n = vsnprintf(NULL, 0, fmt, cp); va_end(cp); if (n < 0) { va_end(ap); return; } need(sb, (size_t)n); (void)vsnprintf(sb->buf + sb->len, sb->cap - sb->len, fmt, ap); va_end(ap); sb->len += (size_t)n; } char *tobi_sb_take(tobi_sb *sb) { char *out = sb->buf; sb->buf = NULL; sb->len = 0; sb->cap = 0; return out; } void tobi_json_string(tobi_sb *sb, const char *s) { tobi_sb_ch(sb, '"'); for (const unsigned char *p = (const unsigned char *)s; *p; p++) { unsigned char c = *p; switch (c) { case '"': tobi_sb_add(sb, "\\\""); break; case '\\': tobi_sb_add(sb, "\\\\"); break; case '\b': tobi_sb_add(sb, "\\b"); break; case '\f': tobi_sb_add(sb, "\\f"); break; case '\n': tobi_sb_add(sb, "\\n"); break; case '\r': tobi_sb_add(sb, "\\r"); break; case '\t': tobi_sb_add(sb, "\\t"); break; default: if (c < 0x20) { char e[7]; (void)snprintf(e, sizeof(e), "\\u%04x", (unsigned)c); tobi_sb_add(sb, e); } else { tobi_sb_ch(sb, (char)c); } break; } } tobi_sb_ch(sb, '"'); } void tobi_hex(tobi_sb *sb, const uint8_t *data, size_t len) { static const char hex[] = "0123456789abcdef"; for (size_t i = 0; i < len; i++) { char b[2] = {hex[data[i] >> 4], hex[data[i] & 15]}; tobi_sb_addn(sb, b, 2); } }