// Buffer di stringa crescente con escaping JSON. #pragma once #include #include #include #include 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; }