src/json.c

changeset 1667
608cc0b25352
parent 1654
5ab3fe0b7859
child 1668
3ffdfe1776b4
--- a/src/json.c	Wed Dec 24 12:13:59 2025 +0100
+++ b/src/json.c	Thu Dec 25 11:10:13 2025 +0100
@@ -96,23 +96,27 @@
 }
 
 static CxJsonToken token_create(CxJson *json, bool isstring, size_t start, size_t end) {
-    cxmutstr str = cx_mutstrn(json->buffer.space + start, end - start);
-    bool allocated = false;
-    if (json->uncompleted.tokentype != CX_JSON_NO_TOKEN) {
+    cxmutstr buf_str = cx_mutstrn(json->buffer.space + start, end - start);
+    cxmutstr str;
+    bool allocated;
+    if (json->uncompleted_tokentype != CX_JSON_NO_TOKEN) {
         allocated = true;
-        str = cx_strcat_m(json->uncompleted.content, 1, str);
-        if (str.ptr == NULL) { // LCOV_EXCL_START
-            return (CxJsonToken){CX_JSON_NO_TOKEN, false, {NULL, 0}};
-        } // LCOV_EXCL_STOP
+        str = json->uncompleted_content;
+        if (cx_strcat(&str, 1, buf_str)) {
+            return (CxJsonToken){CX_JSON_NO_TOKEN, false, {NULL, 0}}; // LCOV_EXCL_LINE
+        }
+        json->uncompleted_content = (cxmutstr){NULL, 0};
+        json->uncompleted_tokentype = CX_JSON_NO_TOKEN;
+    } else {
+        allocated = false;
+        str = buf_str;
     }
-    json->uncompleted = (CxJsonToken){0};
     CxJsonTokenType ttype;
     if (isstring) {
         ttype = CX_JSON_TOKEN_STRING;
     } else {
-        cxstring s = cx_strcast(str);
-        if (!cx_strcmp(s, "true") || !cx_strcmp(s, "false")
-            || !cx_strcmp(s, "null")) {
+        if (!cx_strcmp(str, "true") || !cx_strcmp(str, "false")
+            || !cx_strcmp(str, "null")) {
             ttype = CX_JSON_TOKEN_LITERAL;
         } else {
             ttype = token_numbertype(str.ptr, str.length);
@@ -162,16 +166,16 @@
 static enum cx_json_status token_parse_next(CxJson *json, CxJsonToken *result) {
     // check if there is data in the buffer
     if (cxBufferEof(&json->buffer)) {
-        return json->uncompleted.tokentype == CX_JSON_NO_TOKEN ?
+        return json->uncompleted_tokentype == CX_JSON_NO_TOKEN ?
             CX_JSON_NO_DATA : CX_JSON_INCOMPLETE_DATA;
     }
 
     // current token type and start index
-    CxJsonTokenType ttype = json->uncompleted.tokentype;
+    CxJsonTokenType ttype = json->uncompleted_tokentype;
     size_t token_part_start = json->buffer.pos;
 
     bool escape_end_of_string = ttype == CX_JSON_TOKEN_STRING
-        && json->uncompleted.content.ptr[json->uncompleted.content.length-1] == '\\';
+        && json->uncompleted_content.ptr[json->uncompleted_content.length-1] == '\\';
 
     for (size_t i = json->buffer.pos; i < json->buffer.size; i++) {
         char c = json->buffer.space[i];
@@ -232,31 +236,23 @@
         return CX_JSON_NO_DATA;
     } else {
         // uncompleted token
-        size_t uncompleted_len = json->buffer.size - token_part_start;
-        if (json->uncompleted.tokentype == CX_JSON_NO_TOKEN) {
-            // current token is uncompleted
-            // save current token content
-            CxJsonToken uncompleted = {
-                ttype, true,
-                cx_strdup(cx_strn(json->buffer.space + token_part_start, uncompleted_len))
-            };
-            if (uncompleted.content.ptr == NULL) {
+        cxstring uncompleted = cx_strn(json->buffer.space + token_part_start, json->buffer.size - token_part_start);
+        if (json->uncompleted_tokentype == CX_JSON_NO_TOKEN) {
+            assert(json->uncompleted_content.ptr == NULL);
+            json->uncompleted_content = cx_strdup(uncompleted);
+            if (json->uncompleted_content.ptr == NULL) {
                 return CX_JSON_BUFFER_ALLOC_FAILED; // LCOV_EXCL_LINE
             }
-            json->uncompleted = uncompleted;
+            json->uncompleted_tokentype = ttype;
         } else {
             // previously we also had an uncompleted token
             // combine the uncompleted token with the current token
-            assert(json->uncompleted.allocated);
-            cxmutstr str = cx_strcat_m(json->uncompleted.content, 1,
-                cx_strn(json->buffer.space + token_part_start, uncompleted_len));
-            if (str.ptr == NULL) {
+            if (cx_strcat(&json->uncompleted_content, 1, uncompleted)) {
                 return CX_JSON_BUFFER_ALLOC_FAILED; // LCOV_EXCL_LINE
             }
-            json->uncompleted.content = str;
         }
         // advance the buffer position - we saved the stuff in the uncompleted token
-        json->buffer.pos += uncompleted_len;
+        json->buffer.pos += uncompleted.length;
         return CX_JSON_INCOMPLETE_DATA;
     }
 }
@@ -564,7 +560,8 @@
     }
     cxJsonValueFree(json->parsed);
     json->parsed = NULL;
-    token_destroy(&json->uncompleted);
+    json->uncompleted_tokentype = CX_JSON_NO_TOKEN;
+    cx_strfree(&json->uncompleted_content);
     cx_strfree_a(json->allocator, &json->uncompleted_member_name);
 }
 

mercurial