#include "mcp/json.h" #include #include #include static bool reserve(tiny_json_buffer_t *buffer, size_t addition) { size_t needed, capacity; char *resized; if (buffer->failed || addition > SIZE_MAX - buffer->length - 1) { return false; } needed = buffer->length + addition + 1; if (needed <= buffer->capacity) { return true; } capacity = buffer->capacity == 0 ? 256 : buffer->capacity; while (capacity < needed) { if (capacity > SIZE_MAX / 2) { buffer->failed = true; return false; } capacity *= 2; } resized = realloc(buffer->data, capacity); if (resized == NULL) { buffer->failed = true; return false; } buffer->data = resized; buffer->capacity = capacity; return true; } void tiny_json_init(tiny_json_buffer_t *buffer) { memset(buffer, 0, sizeof(*buffer)); } void tiny_json_free(tiny_json_buffer_t *buffer) { free(buffer->data); tiny_json_init(buffer); } bool tiny_json_raw_n(tiny_json_buffer_t *buffer, const char *value, size_t length) { if (!reserve(buffer, length)) { return false; } memcpy(buffer->data + buffer->length, value, length); buffer->length += length; buffer->data[buffer->length] = '\0'; return true; } bool tiny_json_raw(tiny_json_buffer_t *buffer, const char *value) { return tiny_json_raw_n(buffer, value, strlen(value)); } bool tiny_json_string(tiny_json_buffer_t *buffer, const char *value) { const unsigned char *position = (const unsigned char *)value; if (!tiny_json_raw(buffer, "\"")) { return false; } while (*position) { char escaped[7]; if (*position == '"' || *position == '\\') { escaped[0] = '\\'; escaped[1] = (char)*position; escaped[2] = '\0'; tiny_json_raw(buffer, escaped); } else if (*position == '\b') { tiny_json_raw(buffer, "\\b"); } else if (*position == '\f') { tiny_json_raw(buffer, "\\f"); } else if (*position == '\n') { tiny_json_raw(buffer, "\\n"); } else if (*position == '\r') { tiny_json_raw(buffer, "\\r"); } else if (*position == '\t') { tiny_json_raw(buffer, "\\t"); } else if (*position < 0x20) { snprintf(escaped, sizeof(escaped), "\\u%04x", *position); tiny_json_raw(buffer, escaped); } else { tiny_json_raw_n(buffer, (const char *)position, 1); } ++position; } return tiny_json_raw(buffer, "\""); } bool tiny_json_u64(tiny_json_buffer_t *buffer, unsigned long long value) { char text[32]; snprintf(text, sizeof(text), "%llu", value); return tiny_json_raw(buffer, text); } bool tiny_json_i64(tiny_json_buffer_t *buffer, long long value) { char text[32]; snprintf(text, sizeof(text), "%lld", value); return tiny_json_raw(buffer, text); }