diff options
Diffstat (limited to 'src/mcp/json.c')
| -rw-r--r-- | src/mcp/json.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/mcp/json.c b/src/mcp/json.c new file mode 100644 index 0000000..dcef91b --- /dev/null +++ b/src/mcp/json.c @@ -0,0 +1,137 @@ +#include "mcp/json.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +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); +} |
