From 4bc721c3bf7589b519c5730d093f704ce56e3f09 Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Mon, 29 Jun 2026 21:43:54 +0900 Subject: refactor: MCP層をmcpc APIベースに刷新 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 独自JSON-RPC処理をmcpcへ置き換え - 各MCPツールを個別ソースへ分離 - 共通コンテキストと登録処理を整理 - mcpc互換修正と統合テストを更新 --- src/sys/encoding.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 src/sys/encoding.c (limited to 'src/sys/encoding.c') diff --git a/src/sys/encoding.c b/src/sys/encoding.c new file mode 100644 index 0000000..ccdcc0a --- /dev/null +++ b/src/sys/encoding.c @@ -0,0 +1,208 @@ +#include "sys/encoding.h" + +#include "base/allocator.h" + +#include +#include + +static bool +utf8_codepoint(const unsigned char *input, size_t length, size_t *used, uint32_t *codepoint) +{ + const unsigned char first = input[0]; + size_t width, index; + uint32_t value; + if (first < 0x80) + { + width = 1; + value = first; + } + else if (first >= 0xc2 && first <= 0xdf) + { + width = 2; + value = first & 0x1f; + } + else if (first >= 0xe0 && first <= 0xef) + { + width = 3; + value = first & 0x0f; + } + else if (first >= 0xf0 && first <= 0xf4) + { + width = 4; + value = first & 0x07; + } + else + { + return false; + } + if (width > length) + { + return false; + } + for (index = 1; index < width; ++index) + { + if ((input[index] & 0xc0) != 0x80) + { + return false; + } + value = (value << 6) | (input[index] & 0x3f); + } + if ((width == 3 && ((first == 0xe0 && input[1] < 0xa0) || (first == 0xed && input[1] >= 0xa0))) + || (width == 4 + && ((first == 0xf0 && input[1] < 0x90) || (first == 0xf4 && input[1] >= 0x90)))) + { + return false; + } + *used = width; + *codepoint = value; + return true; +} + +tiny_encoding_status_t +tiny_utf8_to_utf16(const char *input, size_t input_length, uint16_t **output, size_t *output_length) +{ + size_t offset = 0, units = 0; + uint16_t *result; + if (output == NULL || output_length == NULL) + { + return TINY_ENCODING_INVALID; + } + *output = NULL; + *output_length = 0; + if (input == NULL && input_length != 0) + { + return TINY_ENCODING_INVALID; + } + while (offset < input_length) + { + size_t used; + uint32_t point; + if (!utf8_codepoint( + (const unsigned char *)input + offset, input_length - offset, &used, &point)) + { + return TINY_ENCODING_INVALID; + } + if (units > SIZE_MAX - (point >= 0x10000 ? 2U : 1U)) + { + return TINY_ENCODING_OVERFLOW; + } + units += point >= 0x10000 ? 2U : 1U; + offset += used; + } + if (units == SIZE_MAX || units + 1 > SIZE_MAX / sizeof(*result)) + { + return TINY_ENCODING_OVERFLOW; + } + result = malloc((units + 1) * sizeof(*result)); + if (result == NULL) + { + return TINY_ENCODING_NO_MEMORY; + } + offset = 0; + units = 0; + while (offset < input_length) + { + size_t used; + uint32_t point; + (void)utf8_codepoint( + (const unsigned char *)input + offset, input_length - offset, &used, &point); + if (point < 0x10000) + { + result[units++] = (uint16_t)point; + } + else + { + point -= 0x10000; + result[units++] = (uint16_t)(0xd800 + (point >> 10)); + result[units++] = (uint16_t)(0xdc00 + (point & 0x3ff)); + } + offset += used; + } + result[units] = 0; + *output = result; + *output_length = units; + return TINY_ENCODING_OK; +} + +tiny_encoding_status_t +tiny_utf16_to_utf8(const uint16_t *input, size_t input_length, char **output, size_t *output_length) +{ + size_t index = 0, bytes = 0; + char *result; + if (output == NULL || output_length == NULL) + { + return TINY_ENCODING_INVALID; + } + *output = NULL; + *output_length = 0; + if (input == NULL && input_length != 0) + { + return TINY_ENCODING_INVALID; + } + while (index < input_length) + { + uint32_t point = input[index++]; + if (point >= 0xd800 && point <= 0xdbff) + { + if (index >= input_length || input[index] < 0xdc00 || input[index] > 0xdfff) + { + return TINY_ENCODING_INVALID; + } + point = 0x10000 + ((point - 0xd800) << 10) + (input[index++] - 0xdc00); + } + else if (point >= 0xdc00 && point <= 0xdfff) + { + return TINY_ENCODING_INVALID; + } + if (bytes > SIZE_MAX - (point < 0x80 ? 1U : point < 0x800 ? 2U : point < 0x10000 ? 3U : 4U)) + { + return TINY_ENCODING_OVERFLOW; + } + bytes += point < 0x80 ? 1U : point < 0x800 ? 2U : point < 0x10000 ? 3U : 4U; + } + if (bytes == SIZE_MAX) + { + return TINY_ENCODING_OVERFLOW; + } + result = malloc(bytes + 1); + if (result == NULL) + { + return TINY_ENCODING_NO_MEMORY; + } + index = 0; + bytes = 0; + while (index < input_length) + { + uint32_t point = input[index++]; + if (point >= 0xd800 && point <= 0xdbff) + { + point = 0x10000 + ((point - 0xd800) << 10) + (input[index++] - 0xdc00); + } + if (point < 0x80) + { + result[bytes++] = (char)point; + } + else if (point < 0x800) + { + result[bytes++] = (char)(0xc0 | (point >> 6)); + result[bytes++] = (char)(0x80 | (point & 0x3f)); + } + else if (point < 0x10000) + { + result[bytes++] = (char)(0xe0 | (point >> 12)); + result[bytes++] = (char)(0x80 | ((point >> 6) & 0x3f)); + result[bytes++] = (char)(0x80 | (point & 0x3f)); + } + else + { + result[bytes++] = (char)(0xf0 | (point >> 18)); + result[bytes++] = (char)(0x80 | ((point >> 12) & 0x3f)); + result[bytes++] = (char)(0x80 | ((point >> 6) & 0x3f)); + result[bytes++] = (char)(0x80 | (point & 0x3f)); + } + } + result[bytes] = '\0'; + *output = result; + *output_length = bytes; + return TINY_ENCODING_OK; +} -- cgit v1.2.3