System/Libraries/Json: Implement @json_stringify_string to eliminate StrLen() bottleneck

This commit is contained in:
Alec Murphy 2025-02-27 11:30:08 -05:00
parent 4b7e5b2836
commit 81d65056a9

View file

@ -41,6 +41,12 @@
#define JSON_SIG 0xFABACEAE
class @json_stringify_string
{
I64 length;
U8* value;
}
class @json_element
{
U32 sig;
@ -206,8 +212,11 @@ U0 @json_rstrip(U8* str)
{
if (!str || !StrLen(str))
return;
while (str[StrLen(str) - 1] == ' ' || str[StrLen(str) - 1] == '\r' || str[StrLen(str) - 1] == '\n' || str[StrLen(str) - 1] == '\t ')
str[StrLen(str) - 1] = NULL;
I64 r_pos = StrLen(str) - 1;
while (str[r_pos] == ' ' || str[r_pos] == '\r' || str[r_pos] == '\n' || str[r_pos] == '\t') {
str[r_pos] = NULL;
--r_pos;
}
}
extern @json_element* @json_parse_object_or_array(@json_parser* parser);
@ -788,102 +797,88 @@ U0 @json_insert_item(@json_array* arr, @json_item* insert_item, I64 index)
arr->length++;
}
U0 @json_stringify_append_char(U8* str, U8 char)
U0 @json_stringify_append_char(@json_stringify_string* str, U8 char)
{
// FIXME: unicode
I64 len = StrLen(str);
switch (char) {
case '\\':
str[len] = '\\';
str[len + 1] = '\\';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = '\\';
break;
case 0x08:
str[len] = '\\';
str[len + 1] = 'b';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 'b';
break;
case 0x0c:
str[len] = '\\';
str[len + 1] = 'f';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 'f';
break;
case 0x0a:
str[len] = '\\';
str[len + 1] = 'n';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 'n';
break;
case 0x0d:
str[len] = '\\';
str[len + 1] = 'r';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 'r';
break;
case 0x09:
str[len] = '\\';
str[len + 1] = 't';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 't';
break;
default:
str[len] = char;
str[len + 1] = NULL;
str->value[str->length++] = char;
break;
}
str->value[str->length] = NULL;
}
U0 @json_stringify_append_char_escape_quotes(U8* str, U8 char)
U0 @json_stringify_append_char_escape_quotes(@json_stringify_string* str, U8 char)
{
// FIXME: unicode
I64 len = StrLen(str);
switch (char) {
case '"':
str[len] = '\\';
str[len + 1] = '"';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = '"';
break;
case '\\':
str[len] = '\\';
str[len + 1] = '\\';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = '\\';
break;
case 0x08:
str[len] = '\\';
str[len + 1] = 'b';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 'b';
break;
case 0x0c:
str[len] = '\\';
str[len + 1] = 'f';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 'f';
break;
case 0x0a:
str[len] = '\\';
str[len + 1] = 'n';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 'n';
break;
case 0x0d:
str[len] = '\\';
str[len + 1] = 'r';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 'r';
break;
case 0x09:
str[len] = '\\';
str[len + 1] = 't';
str[len + 2] = NULL;
str->value[str->length++] = '\\';
str->value[str->length++] = 't';
break;
default:
str[len] = char;
str[len + 1] = NULL;
str->value[str->length++] = char;
break;
}
str->value[str->length] = NULL;
}
U0 @json_stringify_append_str(U8* str, U8* str2)
U0 @json_stringify_append_str(@json_stringify_string* str, U8* str2)
{
while (*str2) {
// NOTE: We keep escaped unicode in its original form, and let the program ingesting the JSON handle the UTF-8 conversion.
if (*str2 == '\\' && *(str2 + 1) == 'u') {
str[StrLen(str)] = '\\';
str[StrLen(str)] = 'u';
str->value[str->length++] = '\\';
str->value[str->length++] = 'u';
str->value[str->length] = NULL;
str2++;
} else {
@json_stringify_append_char_escape_quotes(str, *str2);
@ -892,7 +887,7 @@ U0 @json_stringify_append_str(U8* str, U8* str2)
}
}
U0 @json_stringify_append_number(U8* str, F64 num)
U0 @json_stringify_append_number(@json_stringify_string* str, F64 num)
{
U8 buf[256];
MemSet(buf, 0, 256);
@ -908,9 +903,9 @@ U0 @json_stringify_append_number(U8* str, F64 num)
@json_stringify_append_str(str, buf);
}
extern U0 @json_stringify_object_or_array(U8* str, @json_element* el);
extern U0 @json_stringify_object_or_array(@json_stringify_string* str, @json_element* el);
U0 @json_stringify_object(U8* str, @json_object* obj)
U0 @json_stringify_object(@json_stringify_string* str, @json_object* obj)
{
@json_stringify_append_char(str, '{');
@json_key* key = obj->keys;
@ -951,7 +946,7 @@ U0 @json_stringify_object(U8* str, @json_object* obj)
@json_stringify_append_char(str, '}');
}
U0 @json_stringify_array(U8* str, @json_array* arr)
U0 @json_stringify_array(@json_stringify_string* str, @json_array* arr)
{
@json_stringify_append_char(str, '[');
@json_item* item = arr->items;
@ -988,7 +983,7 @@ U0 @json_stringify_array(U8* str, @json_array* arr)
@json_stringify_append_char(str, ']');
}
U0 @json_stringify_object_or_array(U8* str, @json_element* el)
U0 @json_stringify_object_or_array(@json_stringify_string* str, @json_element* el)
{
while (el) {
switch (el->type) {
@ -1011,9 +1006,13 @@ U0 @json_stringify_object_or_array(U8* str, @json_element* el)
U8* @json_stringify(@json_element* el, I64 buf_size = JSON_STRINGIFY_BUF_SIZE)
{
U8* str = CAlloc(buf_size, adam_task);
// U8* str = CAlloc(buf_size, adam_task);
@json_stringify_string* str = CAlloc(sizeof(@json_stringify_string), adam_task);
U8* value = CAlloc(buf_size, adam_task);
str->value = value;
@json_stringify_object_or_array(str, el);
return str;
Free(str);
return value;
}
U64 @json_get(@json_object* obj, U8* key, Bool return_key = FALSE)