neuronal / engine /include /sbuf.h
amogaddy's picture
amogaddyofficial
claude sonnet 4.6
Neuronal
d601f7c
Raw History Blame Contribute Delete
2.42 kB
// Buffer di stringa crescente con escaping JSON.
#pragma once
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { char *p; size_t n, cap; } SBuf;
static inline void sb_reserve(SBuf *s, size_t extra) {
if (s->n + extra + 1 <= s->cap) return;
size_t cap = s->cap ? s->cap : 256;
while (cap < s->n + extra + 1) cap *= 2;
s->p = realloc(s->p, cap);
s->cap = cap;
}
static inline void sb_putn(SBuf *s, const char *str, size_t n) {
sb_reserve(s, n);
memcpy(s->p + s->n, str, n);
s->n += n;
s->p[s->n] = 0;
}
static inline void sb_puts(SBuf *s, const char *str) { sb_putn(s, str, strlen(str)); }
static inline void sb_printf(SBuf *s, const char *fmt, ...) {
va_list ap, ap2;
va_start(ap, fmt);
va_copy(ap2, ap);
int n = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
if (n > 0) {
sb_reserve(s, (size_t)n);
vsnprintf(s->p + s->n, (size_t)n + 1, fmt, ap2);
s->n += (size_t)n;
}
va_end(ap2);
}
// Lunghezza di una sequenza UTF-8 valida che inizia in c (0 se non valida o incompleta).
static inline int utf8_len(const unsigned char *c) {
int n = c[0] < 0x80 ? 1 : (c[0] >> 5) == 6 ? 2 : (c[0] >> 4) == 14 ? 3 : (c[0] >> 3) == 30 ? 4 : 0;
for (int i = 1; i < n; i++) if ((c[i] & 0xC0) != 0x80) return 0;
return n;
}
// Stringa JSON tra virgolette, con escaping. I byte UTF-8 non validi diventano U+FFFD:
// un solo byte sbagliato farebbe chiudere la connessione al browser.
static inline void sb_json_str(SBuf *s, const char *str) {
sb_putn(s, "\"", 1);
for (const unsigned char *c = (const unsigned char *)str; *c; c++) {
if (*c >= 0x80) {
int n = utf8_len(c);
if (n) { sb_putn(s, (const char *)c, (size_t)n); c += n - 1; }
else sb_putn(s, "\\ufffd", 6);
continue;
}
switch (*c) {
case '"': sb_putn(s, "\\\"", 2); break;
case '\\': sb_putn(s, "\\\\", 2); break;
case '\n': sb_putn(s, "\\n", 2); break;
case '\r': sb_putn(s, "\\r", 2); break;
case '\t': sb_putn(s, "\\t", 2); break;
default:
if (*c < 0x20) sb_printf(s, "\\u%04x", *c);
else sb_putn(s, (const char *)c, 1);
}
}
sb_putn(s, "\"", 1);
}
static inline void sb_free(SBuf *s) { free(s->p); s->p = NULL; s->n = s->cap = 0; }