src/json.c

changeset 1060
0a7c1bb2372d
parent 1057
4e8436c3e806
--- a/src/json.c	Fri Dec 27 12:23:14 2024 +0100
+++ b/src/json.c	Fri Dec 27 13:01:31 2024 +0100
@@ -289,35 +289,6 @@
     return result;
 }
 
-static int parse_number(cxmutstr str, void *value, bool asint) {
-    char *endptr = NULL;
-    if (str.length > 30) {
-        return 1;
-    }
-    // the buffer guarantees that we are working on a copied string
-    char c = str.ptr[str.length];
-    str.ptr[str.length] = 0;
-
-    if (asint) {
-        errno = 0;
-        long long v = strtoll(str.ptr, &endptr, 10);
-        if (errno == ERANGE) {
-            return 1;
-        }
-        *((int64_t*)value) = (int64_t) v;
-    } else {
-        // TODO: proper JSON spec number parser
-        // TODO: also return an error when loss of precision is high
-        double v = strtod(str.ptr, &endptr);
-        *((double*)value) = v;
-    }
-
-    // recover from the hack
-    str.ptr[str.length] = c;
-
-    return endptr != &str.ptr[str.length];
-}
-
 static CxJsonValue* create_json_value(CxJson *json, CxJsonValueType type) {
     CxJsonValue *v = cxMalloc(json->allocator, sizeof(CxJsonValue));
     if (v == NULL) {
@@ -400,8 +371,6 @@
 
     json->vbuf = json->vbuf_internal;
     json->vbuf_capacity = cx_nmemb(json->vbuf_internal);
-
-    cxBufferInit(&json->buffer, NULL, 256, NULL, CX_BUFFER_AUTO_EXTEND);
 }
 
 void cxJsonDestroy(CxJson *json) {
@@ -417,16 +386,16 @@
 }
 
 int cxJsonFilln(CxJson *json, const char *buf, size_t size) {
-    // we use the UCX buffer to write the data
-    // but reset the position immediately to enable parsing
-    size_t old_pos = json->buffer.pos;
-    cxBufferSeek(&json->buffer, 0, SEEK_END);
-    size_t written = cxBufferWrite(buf, 1, size, &json->buffer);
-    if (0 == cxBufferTerminate(&json->buffer)) {
-        written++;
+    if (cxBufferEof(&json->buffer)) {
+        // reinitialize the buffer
+        cxBufferDestroy(&json->buffer);
+        cxBufferInit(&json->buffer, (char*) buf, size,
+            NULL, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_COPY_ON_WRITE);
+        json->buffer.size = size;
+        return 0;
+    } else {
+        return size != cxBufferAppend(buf, 1, size, &json->buffer);
     }
-    json->buffer.pos = old_pos;
-    return written != size + 1;
 }
 
 static void json_add_state(CxJson *json, int state) {
@@ -508,8 +477,14 @@
                 if (NULL == (vbuf = create_json_value(json, type))) {
                     return_rec(CX_JSON_VALUE_ALLOC_FAILED);
                 }
-                if (parse_number(token.content, &vbuf->value,type == CX_JSON_INTEGER)) {
-                    return_rec(CX_JSON_FORMAT_ERROR_NUMBER);
+                if (type == CX_JSON_INTEGER) {
+                    if (cx_strtoi64(token.content, &vbuf->value.integer, 10)) {
+                        return_rec(CX_JSON_FORMAT_ERROR_NUMBER);
+                    }
+                } else {
+                    if (cx_strtod(token.content, &vbuf->value.number)) {
+                        return_rec(CX_JSON_FORMAT_ERROR_NUMBER);
+                    }
                 }
                 return_rec(CX_JSON_NO_ERROR);
             }
@@ -600,6 +575,11 @@
 }
 
 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value) {
+    // check if buffer has been filled
+    if (json->buffer.space == NULL) {
+        return CX_JSON_NULL_DATA;
+    }
+
     // initialize output value
     *value = &cx_json_value_nothing;
 
@@ -607,7 +587,6 @@
     CxJsonStatus result;
     do {
         result = json_parse(json);
-        cxBufferShiftLeft(&json->buffer, json->buffer.pos);
         if (result == CX_JSON_NO_ERROR && json->states_size == 1) {
             // final state reached
             assert(json->states[0] == JP_STATE_VALUE_END);

mercurial