From 8f9e448b2ef6db7cd905540c21f3c5b190e7a1e7 Mon Sep 17 00:00:00 2001 From: Kacper Date: Sun, 7 Dec 2025 22:22:16 +0100 Subject: Add bin/true and bin/false implementations - Added assembly implementations for `true` and `false` commands. - Updated Kbuild files to include new binaries. - Removed unused libraries and headers. - Cleaned up makefile and unused code. --- lib/libjson/json.c | 1607 ---------------------------------------------------- 1 file changed, 1607 deletions(-) delete mode 100644 lib/libjson/json.c (limited to 'lib/libjson/json.c') diff --git a/lib/libjson/json.c b/lib/libjson/json.c deleted file mode 100644 index a50a6275..00000000 --- a/lib/libjson/json.c +++ /dev/null @@ -1,1607 +0,0 @@ -#include "json.h" - -#include -#include -#include - -inline struct json_value *json_array_get(struct json_value *array, int index) -{ - return index < array->array.length ? array->array.items[index] : NULL; -} - -/** - * @brief Represents a JSON parser for decoding JSON strings. - * - * This structure is used internally by the JSON library to parse - * JSON-encoded strings into structured `json_value` objects. - * - * @note This structure is private and should not be accessed directly - * outside of the JSON library's internal implementation. - */ -struct json_parser { - /** - * @brief The input JSON string to be parsed. - * - * This is a pointer to the null-terminated JSON string that the parser - * operates on. - */ - const char *input; - - /** - * @brief The length of the input JSON string. - * - * This value represents the total number of characters in the input - * JSON string, excluding the null terminator. - */ - int length; - - /** - * @brief The current position in the input JSON string. - * - * This value indicates the index of the character currently being - * processed by the parser. - */ - int position; - -#if defined(JSON_ERROR) - /** - * @brief Represents error information for the JSON parser. - * - * This structure is used to store details about any errors encountered - * during the parsing process. - */ - struct { - /** - * @brief Enum representing the type of error encountered. - * - * - `JSON_ERROR_NONE`: No error occurred. - * - `JSON_ERROR_SYNTAX`: A syntax error was encountered. - * - `JSON_ERROR_MEMORY`: A memory allocation error occurred. - * - `JSON_ERROR_EOF`: Unexpected end of input was encountered. - */ - enum { - JSON_ERROR_NONE, /**< No error occurred. */ - JSON_ERROR_SYNTAX, /**< A syntax error was encountered. - */ - JSON_ERROR_MEMORY, /**< A memory allocation error - occurred. */ - JSON_ERROR_EOF, /**< Unexpected end of input was - encountered. */ - JSON_ERROR_INVALID_NUMBER, /**< Failed to parse number - */ - } code; - - /** - * @brief The line number where the error occurred. - * - * This value is used for debugging purposes to identify the - * location of the error in the source code. - */ - int line; - - /** - * @brief The name of the function where the error occurred. - * - * This is a pointer to a string containing the name of the - * function in which the error was detected. - */ - const char *func; - - /** - * @brief A descriptive message about the error. - * - * This is a pointer to a string containing a human-readable - * description of the error. - */ - const char *message; - } error; -#endif -}; - -/** - * Initializes a JSON object. - * - * This function is responsible for setting up the internal structure - * of a JSON object, ensuring it is ready for use. It is invoked by - * both json_object_new() and json_object_free() to manage the lifecycle - * of JSON objects. - * - * @param object A pointer to the JSON object to be initialized. - * - * @note This function is marked as privative and should not be used - * directly outside of the JSON library's internal implementation. - */ -void json_object_init(struct json_value *object); - -#if defined(JSON_ERROR) -/** - * @brief Sets an error in the JSON parser. - * - * This macro assigns error details to the JSON parser's error structure. - * It captures the error code, the line number, the function name, and - * a descriptive error message. - * - * @param PARSER The JSON parser where the error occurred. - * @param CODE The error code to set. - * @param MESSAGE A descriptive message about the error. - */ -#define JSON_PARSER_ERROR(PARSER, CODE, MESSAGE) \ - (PARSER)->error.code = (CODE); \ - (PARSER)->error.line = __LINE__; \ - (PARSER)->error.func = __func__; \ - (PARSER)->error.message = (MESSAGE) -#else -/** - * @brief No-op macro for JSON parser errors. - * - * When JSON_ERROR is not defined, this macro does nothing. - * - * @param PARSER The JSON parser (unused). - * @param CODE The error code (unused). - * @param MESSAGE The error message (unused). - */ -#define JSON_PARSER_ERROR(PARSER, CODE, MESSAGE) -#endif - -static int json__decode_value(struct json_parser *parser, - struct json_value *value); - -static int json__strlen(const char *str) -{ - int len = 0; - while (*str++) - len++; - return len; -} - -static int json__streq(const char *s1, const char *s2) -{ - if (json__strlen(s1) != json__strlen(s2)) - return 0; - - while (*s1 && *s1 == *s2) { - s1++; - s2++; - } - - if (*s1 == 0 && *s2 == 0) - return 1; - - return 0; -} - -static int json__streqn(const char *s1, const char *s2, int limit) -{ - while (*s1 && *s2 && *s1 == *s2 && limit-- > 1) { - s1++; - s2++; - } - - return *s1 == *s2 ? 1 : 0; -} - -static void json__parse_whitespace(struct json_parser *parser) -{ - const char *ptr = parser->input; - int pos = parser->position; - int len = parser->length; - - while (pos < len && (ptr[pos] == ' ' || ptr[pos] == '\t' || - ptr[pos] == '\n' || ptr[pos] == '\r')) - pos++; - - parser->position = pos; -} - -static int json__decode_string(struct json_parser *parser, - struct json_value *value) -{ - int start = parser->position + 1; - int end = start; - int buffer_size = 16; - int buffer_length = 0; - char *buffer = malloc(buffer_size); - - if (buffer == NULL) { - JSON_PARSER_ERROR(parser, JSON_ERROR_MEMORY, - "Memory allocation failed"); - return -1; - } - - while (end < parser->length && parser->input[end] != '"') { - if (parser->input[end] == '\\') { - end++; - if (end >= parser->length) { - free(buffer); - JSON_PARSER_ERROR( - parser, JSON_ERROR_SYNTAX, - "Unterminated escape sequence"); - return -1; - } - - if (parser->input[end] == 'u') { - // Handle \uXXXX Unicode escape sequences - end++; - if (end + 3 >= parser->length) { - free(buffer); - JSON_PARSER_ERROR( - parser, JSON_ERROR_SYNTAX, - "Incomplete Unicode escape sequence"); - return -1; - } - - // Parse 4 hex digits - unsigned int code_point = 0; - for (int i = 0; i < 4; i++) { - char c = parser->input[end + i]; - code_point <<= 4; - - if (c >= '0' && c <= '9') { - code_point |= (c - '0'); - } else if (c >= 'a' && c <= 'f') { - code_point |= (c - 'a' + 10); - } else if (c >= 'A' && c <= 'F') { - code_point |= (c - 'A' + 10); - } else { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_SYNTAX, - "Invalid hex digit in Unicode escape"); - return -1; - } - } - - // Check for surrogate pair - if (code_point >= 0xD800 && - code_point <= 0xDBFF) { - // High surrogate - need to get the low - // surrogate - end += 4; // Move past the first \uXXXX - - // Check for the sequence \uYYYY where - // YYYY is the low surrogate - if (end + 1 >= parser->length || - parser->input[end] != '\\' || - parser->input[end + 1] != 'u') { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_SYNTAX, - "Expected low surrogate after high surrogate"); - return -1; - } - - end += 2; // Move past \u - if (end + 3 >= parser->length) { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_SYNTAX, - "Incomplete Unicode escape sequence for low surrogate"); - return -1; - } - - // Parse 4 hex digits for low surrogate - unsigned int low_surrogate = 0; - for (int i = 0; i < 4; i++) { - char c = parser->input[end + i]; - low_surrogate <<= 4; - - if (c >= '0' && c <= '9') { - low_surrogate |= - (c - '0'); - } else if (c >= 'a' && - c <= 'f') { - low_surrogate |= - (c - 'a' + 10); - } else if (c >= 'A' && - c <= 'F') { - low_surrogate |= - (c - 'A' + 10); - } else { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_SYNTAX, - "Invalid hex digit in low surrogate"); - return -1; - } - } - - // Validate low surrogate range - if (low_surrogate < 0xDC00 || - low_surrogate > 0xDFFF) { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_SYNTAX, - "Invalid low surrogate value"); - return -1; - } - - // Combine surrogate pair to get actual - // code point - code_point = - 0x10000 + - ((code_point - 0xD800) << 10) + - (low_surrogate - 0xDC00); - end += 4; // Move past the second \uXXXX - } else { - end += 4; // Move past \uXXXX for - // non-surrogate case - } - - // Encode code point as UTF-8 - if (code_point < 0x80) { - // 1-byte character - if (buffer_length + 1 >= buffer_size) { - buffer_size *= 2; - char *new_buffer = realloc( - buffer, buffer_size); - if (new_buffer == NULL) { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_MEMORY, - "Memory allocation failed"); - return -1; - } - buffer = new_buffer; - } - buffer[buffer_length++] = - (char)code_point; - } else if (code_point < 0x800) { - // 2-byte character - if (buffer_length + 2 >= buffer_size) { - buffer_size *= 2; - char *new_buffer = realloc( - buffer, buffer_size); - if (new_buffer == NULL) { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_MEMORY, - "Memory allocation failed"); - return -1; - } - buffer = new_buffer; - } - buffer[buffer_length++] = - (char)(0xC0 | - (code_point >> 6)); - buffer[buffer_length++] = - (char)(0x80 | - (code_point & 0x3F)); - } else if (code_point < 0x10000) { - // 3-byte character - if (buffer_length + 3 >= buffer_size) { - buffer_size *= 2; - char *new_buffer = realloc( - buffer, buffer_size); - if (new_buffer == NULL) { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_MEMORY, - "Memory allocation failed"); - return -1; - } - buffer = new_buffer; - } - buffer[buffer_length++] = - (char)(0xE0 | - (code_point >> 12)); - buffer[buffer_length++] = - (char)(0x80 | - ((code_point >> 6) & - 0x3F)); - buffer[buffer_length++] = - (char)(0x80 | - (code_point & 0x3F)); - } else { - // 4-byte character - if (buffer_length + 4 >= buffer_size) { - buffer_size *= 2; - char *new_buffer = realloc( - buffer, buffer_size); - if (new_buffer == NULL) { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_MEMORY, - "Memory allocation failed"); - return -1; - } - buffer = new_buffer; - } - buffer[buffer_length++] = - (char)(0xF0 | - (code_point >> 18)); - buffer[buffer_length++] = - (char)(0x80 | - ((code_point >> 12) & - 0x3F)); - buffer[buffer_length++] = - (char)(0x80 | - ((code_point >> 6) & - 0x3F)); - buffer[buffer_length++] = - (char)(0x80 | - (code_point & 0x3F)); - } - - continue; // Skip the increment at the end of - // the loop - } else { - // Handle standard escape sequences - char escaped_char; - switch (parser->input[end]) { - case '"': - escaped_char = '"'; - break; - case '\\': - escaped_char = '\\'; - break; - case '/': - escaped_char = '/'; - break; - case 'b': - escaped_char = '\b'; - break; - case 'f': - escaped_char = '\f'; - break; - case 'n': - escaped_char = '\n'; - break; - case 'r': - escaped_char = '\r'; - break; - case 't': - escaped_char = '\t'; - break; - default: - free(buffer); - JSON_PARSER_ERROR( - parser, JSON_ERROR_SYNTAX, - "Invalid escape character"); - return -1; - } - - if (buffer_length + 1 >= buffer_size) { - buffer_size *= 2; - char *new_buffer = - realloc(buffer, buffer_size); - if (new_buffer == NULL) { - free(buffer); - JSON_PARSER_ERROR( - parser, - JSON_ERROR_MEMORY, - "Memory allocation failed"); - return -1; - } - buffer = new_buffer; - } - - buffer[buffer_length++] = escaped_char; - } - } else { - if (buffer_length + 1 >= buffer_size) { - buffer_size *= 2; - char *new_buffer = realloc(buffer, buffer_size); - if (new_buffer == NULL) { - free(buffer); - JSON_PARSER_ERROR( - parser, JSON_ERROR_MEMORY, - "Memory allocation failed"); - return -1; - } - buffer = new_buffer; - } - - buffer[buffer_length++] = parser->input[end]; - } - end++; - } - - if (end == parser->length) { - free(buffer); - JSON_PARSER_ERROR(parser, JSON_ERROR_SYNTAX, - "Unterminated string"); - return -1; - } - - buffer[buffer_length] = 0; - - value->type = JSON_TYPE_STRING; - value->string.value = buffer; - value->string.length = buffer_length; - - parser->position = end + 1; - return 0; -} - -static void json__parser_consume_digits(struct json_parser *parser) -{ - while (parser->position < parser->length && - parser->input[parser->position] >= '0' && - parser->input[parser->position] <= '9') { - parser->position++; - } -} - -static int json__decode_number(struct json_parser *parser, - struct json_value *value) -{ - int start = parser->position; - char *endptr; - - if (parser->position < parser->length && - parser->input[parser->position] == '-') - parser->position++; - - if (parser->position < parser->length && - parser->input[parser->position] == '0') { - parser->position++; - } else if (parser->position < parser->length && - parser->input[parser->position] >= '1' && - parser->input[parser->position] <= '9') { - json__parser_consume_digits(parser); - } else { - JSON_PARSER_ERROR(parser, JSON_ERROR_INVALID_NUMBER, - "Invalid number"); - return -1; - } - - if (parser->position < parser->length && - parser->input[parser->position] == '.') { - parser->position++; - if (parser->position < parser->length && - parser->input[parser->position] >= '0' && - parser->input[parser->position] <= '9') { - json__parser_consume_digits(parser); - } else { - JSON_PARSER_ERROR(parser, JSON_ERROR_INVALID_NUMBER, - "Invalid number"); - return -1; - } - } - - if (parser->position < parser->length && - (parser->input[parser->position] == 'e' || - parser->input[parser->position] == 'E')) { - parser->position++; - if (parser->position < parser->length && - (parser->input[parser->position] == '-' || - parser->input[parser->position] == '+')) { - parser->position++; - } - if (parser->position < parser->length && - parser->input[parser->position] >= '0' && - parser->input[parser->position] <= '9') { - json__parser_consume_digits(parser); - } else { - JSON_PARSER_ERROR(parser, JSON_ERROR_INVALID_NUMBER, - "Invalid number"); - return -1; - } - } - - if (start == parser->position) { - JSON_PARSER_ERROR(parser, JSON_ERROR_INVALID_NUMBER, - "Invalid number"); - return -1; - } - - value->type = JSON_TYPE_NUMBER; - endptr = NULL; - value->number = strtod(parser->input + start, &endptr); - - if (endptr != parser->input + parser->position) { - JSON_PARSER_ERROR(parser, JSON_ERROR_INVALID_NUMBER, - "Invalid number"); - return -1; - } - - return 0; -} - -static int json__decode_array(struct json_parser *parser, - struct json_value *array) -{ - if (parser->length - parser->position < 1) { - JSON_PARSER_ERROR(parser, JSON_ERROR_EOF, - "Unexpected end of input"); - return -1; - } - - if (parser->input[parser->position] != '[') { - JSON_PARSER_ERROR(parser, JSON_ERROR_SYNTAX, "Expected '['"); - return -1; - } - - array->type = JSON_TYPE_ARRAY; - json_array_init(array); - - if (parser->position + 1 < parser->length && - parser->input[parser->position + 1] == ']') { - parser->position += 2; - return 0; - } - - parser->position += 1; // Skip '[' - while (parser->position < parser->length && - parser->input[parser->position] != ']') { - json__parse_whitespace(parser); - - struct json_value *item; - if ((item = malloc(sizeof(struct json_value))) == NULL) { - JSON_PARSER_ERROR(parser, JSON_ERROR_MEMORY, - "Memory allocation failed"); - json_array_free(array); - return -1; - } - - if (json__decode_value(parser, item) != 0) { - free(item); - json_array_free(array); - return -1; - } - - json_array_push(array, item); - json__parse_whitespace(parser); - - if (parser->position < parser->length && - parser->input[parser->position] == ',') // Skip ',' - parser->position++; - } - - if (parser->position >= parser->length || - parser->input[parser->position] != ']') { - JSON_PARSER_ERROR(parser, JSON_ERROR_SYNTAX, - "Expected closing ']' for array"); - json_array_free(array); - return -1; - } - - if (parser->position < parser->length) // Skip ']' - parser->position++; - return 0; -} - -static int json__decode_object(struct json_parser *parser, - struct json_value *object) -{ - object->type = JSON_TYPE_OBJECT; - json_object_init(object); - - parser->position++; - json__parse_whitespace(parser); - - while (parser->position < parser->length && - parser->input[parser->position] != '}') { - struct json_value key, *value; - json__parse_whitespace(parser); - - if (parser->input[parser->position] != '"') { - JSON_PARSER_ERROR(parser, JSON_ERROR_SYNTAX, - "Expected string key"); - return -1; - } - - if (json__decode_string(parser, &key) != 0) { - JSON_PARSER_ERROR(parser, JSON_ERROR_SYNTAX, - "Failed to parse string key"); - return -1; - } - - json__parse_whitespace(parser); - if (parser->position >= parser->length || - parser->input[parser->position] != ':') { - free(key.string.value); - JSON_PARSER_ERROR(parser, JSON_ERROR_SYNTAX, - "Expected ':' after string key"); - return -1; - } - parser->position++; // Skip the colon - - value = malloc(sizeof(struct json_value)); - if (value == NULL) { - free(key.string.value); - JSON_PARSER_ERROR( - parser, JSON_ERROR_MEMORY, - "Failed to allocate memory for JSON item"); - return -1; - } - - json__parse_whitespace(parser); - if (json__decode_value(parser, value) != 0) { - free(value); - free(key.string.value); - JSON_PARSER_ERROR(parser, JSON_ERROR_SYNTAX, - "Failed to parse JSON value"); - return -1; - } - - if (json_object_set(object, key.string.value, value) != 0) { - free(value); - free(key.string.value); - JSON_PARSER_ERROR( - parser, JSON_ERROR_MEMORY, - "Failed to set key-value pair in object"); - return -1; - } - - free(key.string.value); - json__parse_whitespace(parser); - if (parser->position < parser->length && - parser->input[parser->position] == ',') - parser->position++; // Skip comma or closing brace - } - - if (parser->position >= parser->length || - parser->input[parser->position] != '}') { - JSON_PARSER_ERROR(parser, JSON_ERROR_SYNTAX, - "Expected '}' after JSON object"); - return -1; - } - - parser->position++; // Skip the closing brace - - return 0; -} - -static int json__decode_value(struct json_parser *parser, - struct json_value *value) -{ - int rc; - char c = parser->input[parser->position]; - - if (c == '"') { - rc = json__decode_string(parser, value); - } else if (c == '[') { - rc = json__decode_array(parser, value); - } else if (c == '{') { - rc = json__decode_object(parser, value); - } else if (json__streqn(parser->input + parser->position, "true", 4)) { - value->type = JSON_TYPE_BOOLEAN; - value->number = 1; - parser->position += 4; - return 0; - } else if (json__streqn(parser->input + parser->position, "false", 4)) { - value->type = JSON_TYPE_BOOLEAN; - value->number = 0; - parser->position += 5; - return 0; - } else if (json__streqn(parser->input + parser->position, "null", 4)) { - value->type = JSON_TYPE_NULL; - parser->position += 4; - return 0; - } else { - rc = json__decode_number(parser, value); - } - -#if defined(JSON_ERROR) - if (rc != 0 && parser->error.code == JSON_ERROR_NONE) { - JSON_PARSER_ERROR(parser, JSON_ERROR_SYNTAX, "Expected value"); - } -#endif - - return rc; -} - -struct json_value *json_decode_with_length(const char *json, int length) -{ - struct json_parser parser; - struct json_value *value = NULL; - - parser.input = json; - parser.length = length; - parser.position = 0; - -#if defined(JSON_ERROR) - parser.error.code = JSON_ERROR_NONE; - parser.error.message = NULL; -#endif - - if ((value = malloc(sizeof(struct json_value))) == NULL) - return NULL; - - if (json__decode_value(&parser, value) != 0) { -#if defined(JSON_ERROR) && !defined(JSON_ERROR_HANDLER) - if (parser.error.code != JSON_ERROR_NONE) { - fprintf(stderr, - "JSON(\033[1merror\033[m): %s:%d %s at\n", - parser.error.func, parser.error.line, - parser.error.message); - } -#elif defined(JSON_ERROR) && defined(JSON_ERROR_HANDLER) - if (parser.error.code != JSON_ERROR_NONE) { - JSON_ERROR_HANDLER(parser.error.code, - parser.error.message); - } -#endif - free(value); - return NULL; - } - - return value; -} - -struct json_value *json_decode(const char *json) -{ - return json_decode_with_length(json, json__strlen(json)); -} - -static char *json__encode_array(struct json_value *value) -{ - int length; - int buffer_size; - char *encoded_array; - if (value == NULL) { - return NULL; - } - - buffer_size = 512; - encoded_array = malloc(buffer_size); - if (encoded_array == NULL) { - return NULL; - } - - length = 1; - encoded_array[0] = '['; - - for (int i = 0; i < value->array.length; i++) { - int needed; - int encoded_item_len; - char *encoded_item = json_encode(value->array.items[i]); - if (encoded_item == NULL) { - free(encoded_array); - return NULL; - } - - encoded_item_len = json__strlen(encoded_item); - if (encoded_item_len < 0) { - free(encoded_array); - free(encoded_item); - return NULL; - } - - needed = length + encoded_item_len + (i > 0 ? 1 : 0) + 1; - if (needed > buffer_size) { - char *new_encoded_array = realloc( - encoded_array, (buffer_size = needed * 2)); - if (new_encoded_array == NULL) { - free(encoded_array); - free(encoded_item); - return NULL; - } - encoded_array = new_encoded_array; - } - - if (i > 0) { - encoded_array[length++] = ','; - } - - for (int i = 0; i < encoded_item_len; i++) { - if (encoded_item[i] == '\0') - break; - encoded_array[length + i] = encoded_item[i]; - } - - length += encoded_item_len; - - free(encoded_item); - } - - encoded_array[length++] = ']'; - encoded_array[length] = '\0'; - - return encoded_array; -} - -static char *json__encode_object(struct json_value *object) -{ - int length; - int buffer_size = 256; - char *encoded_object = malloc(buffer_size); - if (encoded_object == NULL) { - return NULL; - } - - encoded_object[0] = '{'; - length = 1; - - for (int i = 0; i < object->object.n_items; i++) { - char *new_buffer; - char *key = object->object.items[i]->key; - char *value = json_encode(object->object.items[i]->value); - if (value == NULL) { - free(encoded_object); - return NULL; - } - - int key_length = json__strlen(key); - int value_length = json__strlen(value); - if (value_length < 0) { - free(encoded_object); - free(value); - return NULL; - } - - int needed = length + key_length + value_length + 4 + - (i < object->object.n_items - 1 ? 1 : 0); - - if (needed > buffer_size) { - buffer_size = needed * 2; - new_buffer = realloc(encoded_object, buffer_size); - if (new_buffer == NULL) { - free(encoded_object); - free(value); - return NULL; - } - encoded_object = new_buffer; - } - - encoded_object[length++] = '"'; - for (int j = 0; j < key_length; j++) - encoded_object[length++] = key[j]; - - encoded_object[length++] = '"'; - encoded_object[length++] = ':'; - for (int j = 0; j < value_length; j++) { - if (value[j] == '\0') - break; - encoded_object[length++] = value[j]; - } - - free(value); - - if (i < object->object.n_items - 1) { - encoded_object[length++] = ','; - } - } - - encoded_object[length++] = '}'; - encoded_object[length] = '\0'; - - return encoded_object; -} - -static char *json__encode_string(struct json_value *value) -{ - const char *str = value->string.value; - int length = value->string.length; - int buffer_size = length * 6 + 3; // Maximum possible size (all chars - // escaped + quotes) - char *buffer = malloc(buffer_size); - int pos = 0; - - if (!buffer) - return NULL; - - buffer[pos++] = '"'; - - for (int i = 0; i < length; i++) { - unsigned char c = (unsigned char)str[i]; - - if (c == '"' || c == '\\' || c == '/') { - buffer[pos++] = '\\'; - buffer[pos++] = c; - } else if (c == '\b') { - buffer[pos++] = '\\'; - buffer[pos++] = 'b'; - } else if (c == '\f') { - buffer[pos++] = '\\'; - buffer[pos++] = 'f'; - } else if (c == '\n') { - buffer[pos++] = '\\'; - buffer[pos++] = 'n'; - } else if (c == '\r') { - buffer[pos++] = '\\'; - buffer[pos++] = 'r'; - } else if (c == '\t') { - buffer[pos++] = '\\'; - buffer[pos++] = 't'; - } else if (c < 32) { - // Control characters must be escaped as \uXXXX - buffer[pos++] = '\\'; - buffer[pos++] = 'u'; - buffer[pos++] = '0'; - buffer[pos++] = '0'; - buffer[pos++] = "0123456789ABCDEF"[(c >> 4) & 0xF]; - buffer[pos++] = "0123456789ABCDEF"[c & 0xF]; - } else if (c < 128) { - // ASCII characters - buffer[pos++] = c; - } else { - // UTF-8 encoded characters - // Check if this is a multi-byte sequence - const unsigned char *bytes = - (const unsigned char *)&str[i]; - if ((c & 0xE0) == 0xC0) { - // Two-byte sequence - if (i + 1 >= length || - (bytes[i + 1] & 0xC0) != 0x80) { - // Invalid UTF-8 sequence, escape as - // replacement character - buffer[pos++] = '\\'; - buffer[pos++] = 'u'; - buffer[pos++] = 'F'; - buffer[pos++] = 'F'; - buffer[pos++] = 'F'; - buffer[pos++] = 'D'; - } else { - // Valid two-byte sequence, keep as is - buffer[pos++] = c; - buffer[pos++] = str[++i]; - } - } else if ((c & 0xF0) == 0xE0) { - // Three-byte sequence - if (i + 2 >= length || - (bytes[i + 1] & 0xC0) != 0x80 || - (bytes[i + 2] & 0xC0) != 0x80) { - // Invalid UTF-8 sequence - buffer[pos++] = '\\'; - buffer[pos++] = 'u'; - buffer[pos++] = 'F'; - buffer[pos++] = 'F'; - buffer[pos++] = 'F'; - buffer[pos++] = 'D'; - } else { - // Valid three-byte sequence, keep as is - buffer[pos++] = c; - buffer[pos++] = str[++i]; - buffer[pos++] = str[++i]; - } - } else if ((c & 0xF8) == 0xF0) { - // Four-byte sequence - if (i + 3 >= length || - (bytes[i + 1] & 0xC0) != 0x80 || - (bytes[i + 2] & 0xC0) != 0x80 || - (bytes[i + 3] & 0xC0) != 0x80) { - // Invalid UTF-8 sequence - buffer[pos++] = '\\'; - buffer[pos++] = 'u'; - buffer[pos++] = 'F'; - buffer[pos++] = 'F'; - buffer[pos++] = 'F'; - buffer[pos++] = 'D'; - } else { - // Valid four-byte sequence, keep as is - buffer[pos++] = c; - buffer[pos++] = str[++i]; - buffer[pos++] = str[++i]; - buffer[pos++] = str[++i]; - } - } else { - // Invalid UTF-8 start byte - buffer[pos++] = '\\'; - buffer[pos++] = 'u'; - buffer[pos++] = 'F'; - buffer[pos++] = 'F'; - buffer[pos++] = 'F'; - buffer[pos++] = 'D'; - } - } - } - - buffer[pos++] = '"'; - buffer[pos] = '\0'; - - // Reallocate to actual size - char *result = realloc(buffer, pos + 1); - return result ? result : buffer; -} - -char *json_encode(struct json_value *value) -{ - switch (value->type) { - case JSON_TYPE_STRING: - return json__encode_string(value); - case JSON_TYPE_NUMBER: { - char *ptr; - char buffer[32]; - int length = snprintf(buffer, sizeof(buffer), "%.17g", - value->number); - - if ((ptr = malloc(length + 1)) == NULL) - return NULL; - - for (int i = 0; i < length; i++) - ptr[i] = buffer[i]; - - ptr[length] = 0; - return ptr; - } - case JSON_TYPE_BOOLEAN: { - char *ptr; - const char *boolean_str = value->number != 0.0 ? "true" : - "false"; - int length = json__strlen(boolean_str); - - if ((ptr = malloc(length + 1)) == NULL) - return NULL; - - for (int i = 0; i < length; i++) - ptr[i] = boolean_str[i]; - - ptr[length] = 0; - return ptr; - } - case JSON_TYPE_NULL: { - char *ptr; - const char *null_str = "null"; - int length = json__strlen(null_str); - - if ((ptr = malloc(length + 1)) == NULL) - return NULL; - - for (int i = 0; i < length; i++) - ptr[i] = null_str[i]; - - ptr[length] = 0; - return ptr; - } - case JSON_TYPE_ARRAY: - return json__encode_array(value); - case JSON_TYPE_OBJECT: - return json__encode_object(value); - default: - return NULL; - } -} - -void json_object_init(struct json_value *object) -{ - object->object.n_items = 0; - object->object.capacity = 0; - object->object.items = NULL; -} - -struct json_value *json_object_new(void) -{ - struct json_value *object = malloc(sizeof(struct json_value)); - if (!object) { - return NULL; - } - - object->type = JSON_TYPE_OBJECT; - json_object_init(object); - - return object; -} - -void json_object_free(struct json_value *object) -{ - for (int i = 0; i < object->object.n_items; i++) { - json_free(object->object.items[i]->value); - free(object->object.items[i]->key); - free(object->object.items[i]); - } - - free(object->object.items); - free(object); -} - -int json_object_set(struct json_value *object, const char *key, - struct json_value *value) -{ - if (object->object.n_items >= - object->object.capacity * JSON_OBJECT_CAPACITY_THRESHOLD) { - void *items; - int capacity; - - if (object->object.capacity) - capacity = object->object.capacity * - JSON_OBJECT_CAPACITY_MULTIPLIER; - else - capacity = JSON_OBJECT_INITIAL_CAPACITY; - - if ((items = realloc( - object->object.items, - capacity * sizeof(*object->object.items))) == NULL) - return -1; - - object->object.items = items; - object->object.capacity = capacity; - } - - for (int i = 0; i < object->object.n_items; i++) { - if (json__streq(object->object.items[i]->key, key)) { - json_free(object->object.items[i]->value); - object->object.items[i]->value = value; - return 0; - } - } - - int idx = object->object.n_items++; - object->object.items[idx] = malloc(sizeof(*object->object.items[idx])); - - if (object->object.items[idx] == NULL) - return -1; - - int key_len = json__strlen(key); - object->object.items[idx]->key = malloc(key_len + 1); - strncpy(object->object.items[idx]->key, key, key_len); - object->object.items[idx]->key[key_len] = '\0'; - object->object.items[idx]->value = value; - - return 0; -} - -int json_object_has(struct json_value *object, const char *key) -{ - for (int i = 0; i < object->object.n_items; i++) - if (json__streq(object->object.items[i]->key, key)) - return 1; - - return 0; -} - -struct json_value *json_object_get(struct json_value *object, const char *key) -{ - if (object == NULL || object->object.items == NULL) - return NULL; - - for (int i = 0; i < object->object.n_items; i++) - if (object->object.items[i] != NULL && - object->object.items[i]->key != NULL && - json__streq(object->object.items[i]->key, key)) - return object->object.items[i]->value; - - return NULL; -} - -void json_object_remove(struct json_value *object, const char *key) -{ - for (int i = 0; i < object->object.n_items; i++) { - if (json__streq(object->object.items[i]->key, key)) { - switch (object->object.items[i]->value->type) { - case JSON_TYPE_ARRAY: - json_array_free(object->object.items[i]->value); - break; - case JSON_TYPE_OBJECT: - json_object_free( - object->object.items[i]->value); - break; - case JSON_TYPE_STRING: - json_string_free( - object->object.items[i]->value); - break; - default: - free(object->object.items[i]->value); - break; - } - - free(object->object.items[i]->key); - free(object->object.items[i]); - - if (i < object->object.n_items - 1) { - object->object.items[i] = - object->object - .items[object->object.n_items - - 1]; - } - - object->object.n_items--; - } - } -} - -int json_object_iter(const struct json_value *object, int *iter, char **key, - struct json_value **value) -{ - if (*iter >= object->object.n_items) - return 0; - - *key = object->object.items[*iter]->key; - *value = object->object.items[(*iter)++]->value; - - return 1; -} - -void json_object_clear(struct json_value *object) -{ - char *key; - int iter = 0; - struct json_value *value; - - while (json_object_iter(object, &iter, &key, &value)) { - json_object_remove(object, key); - iter--; - } -} - -void json_array_init(struct json_value *array) -{ - array->array.length = 0; - array->array.capacity = 0; - array->array.items = NULL; -} - -struct json_value *json_array_new(void) -{ - struct json_value *value; - if ((value = malloc(sizeof(struct json_value))) == NULL) - return NULL; - - value->type = JSON_TYPE_ARRAY; - json_array_init(value); - - return value; -} - -void json_array_free(struct json_value *value) -{ - for (int i = 0; i < value->array.length; i++) { - switch (value->array.items[i]->type) { - case JSON_TYPE_OBJECT: - json_object_free(value->array.items[i]); - break; - case JSON_TYPE_ARRAY: - json_array_free(value->array.items[i]); - break; - case JSON_TYPE_STRING: - json_string_free(value->array.items[i]); - break; - default: - free(value->array.items[i]); - break; - } - } - free(value->array.items); - free(value); -} - -void json_free(struct json_value *value) -{ - switch (value->type) { - case JSON_TYPE_OBJECT: - json_object_free(value); - break; - case JSON_TYPE_ARRAY: - json_array_free(value); - break; - case JSON_TYPE_STRING: - json_string_free(value); - break; - default: - free(value); - } -} - -struct json_value *json_deep_copy(struct json_value *value) -{ - struct json_value *new_value; - struct json_value *element; - char *key; - int iter; - - iter = 0; - - switch (value->type) { - case JSON_TYPE_OBJECT: - new_value = json_object_new(); - while (json_object_iter(value, &iter, &key, &element)) - json_object_set(new_value, key, - json_deep_copy(element)); - return new_value; - - case JSON_TYPE_ARRAY: - new_value = json_array_new(); - while (json_array_iter(value, &iter, &element)) - json_array_push(new_value, json_deep_copy(element)); - return new_value; - - case JSON_TYPE_STRING: - return json_string_new(value->string.value); - - default: - new_value = malloc(sizeof(struct json_value)); - memcpy(new_value, value, sizeof(*value)); - return new_value; - } - - return NULL; -} - -void json_array_remove(struct json_value *array, int index) -{ - switch (array->array.items[index]->type) { - case JSON_TYPE_OBJECT: - json_object_free(array->array.items[index]); - break; - case JSON_TYPE_ARRAY: - json_array_free(array->array.items[index]); - break; - case JSON_TYPE_STRING: - json_string_free(array->array.items[index]); - break; - default: - break; - } - - for (int i = index; i < array->array.length - 1; i++) - array->array.items[i] = array->array.items[i + 1]; - array->array.length--; -} - -inline int json_array_length(struct json_value *array) -{ - return array->array.length; -} - -int json_array_push(struct json_value *array, struct json_value *value) -{ - if (array == NULL) { - return -1; - } - - int index = array->array.length; - int capacity = array->array.capacity; - int capacity_threshold = capacity * JSON_ARRAY_CAPACITY_THRESHOLD; - - if (index >= capacity_threshold) { - int capacity; - if (array->array.capacity > 0) - capacity = array->array.capacity * - JSON_ARRAY_CAPACITY_MULTIPLIER; - else - capacity = JSON_ARRAY_INITIAL_CAPACITY; - - struct json_value **items; - int size = capacity * sizeof(struct json_value *); - if ((items = realloc(array->array.items, size)) == NULL) - return -1; - - array->array.items = items; - array->array.capacity = capacity; - } - - array->array.items[array->array.length++] = value; - return 0; -} - -int json_array_iter(struct json_value *array, int *index, - struct json_value **value) -{ - if (*index >= array->array.length) - return 0; - - *value = array->array.items[(*index)++]; - return 1; -} - -void json_array_clear(struct json_value *array) -{ - int iter = 0; - struct json_value *value; - - while (json_array_iter(array, &iter, &value)) - json_array_remove(array, iter--); -} - -struct json_value *json_string_new(const char *string) -{ - struct json_value *value; - if ((value = malloc(sizeof(struct json_value))) == NULL) - return NULL; - - value->type = JSON_TYPE_STRING; - value->string.length = json__strlen(string); - if ((value->string.value = malloc(value->string.length + 1)) == NULL) { - free(value); - return NULL; - } - - for (int i = 0; i < value->string.length; i++) - value->string.value[i] = string[i]; - - value->string.value[value->string.length] = 0; - return value; -} - -struct json_value *json_number_new(double value) -{ - struct json_value *number; - if ((number = malloc(sizeof(struct json_value))) == NULL) - return NULL; - - number->type = JSON_TYPE_NUMBER; - number->number = value; - - return number; -} - -struct json_value *json_boolean_new(int value) -{ - struct json_value *boolean; - if ((boolean = malloc(sizeof(struct json_value))) == NULL) - return NULL; - - boolean->type = JSON_TYPE_BOOLEAN; - boolean->number = value; - - return boolean; -} - -void json_string_free(struct json_value *string) -{ - free(string->string.value); - free(string); -} - -static inline void json__print_indent(int indent) -{ - for (int i = 0; i < indent; i++) { - putchar(' '); - } -} - -static void json__print_internal(struct json_value *value, int indent) -{ - if (value == NULL) { - printf("null"); - return; - } - - switch (value->type) { - case JSON_TYPE_STRING: - printf("\"%s\"", value->string.value); - break; - case JSON_TYPE_NUMBER: - printf("%.17g", value->number); - break; - case JSON_TYPE_BOOLEAN: - printf("%s", value->number == 0.0 ? "false" : "true"); - break; - case JSON_TYPE_NULL: - printf("null"); - break; - case JSON_TYPE_ARRAY: - printf("[\n"); - for (int i = 0; i < value->array.length; i++) { - json__print_indent(indent + 2); - json__print_internal(value->array.items[i], indent + 2); - if (i < value->array.length - 1) { - printf(",\n"); - } else { - printf("\n"); - } - } - json__print_indent(indent); - printf("]"); - break; - case JSON_TYPE_OBJECT: - printf("{\n"); - for (int i = 0; i < value->object.n_items; i++) { - json__print_indent(indent + 2); - printf("\"%s\": ", value->object.items[i]->key); - json__print_internal(value->object.items[i]->value, - indent + 2); - if (i < value->object.n_items - 1) { - printf(",\n"); - } else { - printf("\n"); - } - } - json__print_indent(indent); - printf("}"); - break; - default: - break; - } -} - -void json_print(struct json_value *value) -{ - json__print_internal(value, 0); -} - -void json_println(struct json_value *value) -{ - json_print(value); - putchar('\n'); -} -- cgit v1.2.3