aboutsummaryrefslogtreecommitdiff
path: root/json.c
diff options
context:
space:
mode:
authorMartin Lehoux <martin@lehoux.net>2025-02-14 16:39:54 +0000
committerGitHub <noreply@github.com>2025-02-14 16:39:54 +0000
commit03632f51152e5e3b6bb74c29987709fbe97a9a69 (patch)
treedf6a4cbb37f084f64066e4caba0367ad4181984b /json.c
parent8a9e6b1bd3be1041792311a86d8aac68b659e891 (diff)
parentd3d71bb044e0ae9af75bd74d4030e1d95f18a68e (diff)
Merge pull request #1 from martinlehoux/json-nested-parsing
json nested parsing
Diffstat (limited to 'json.c')
-rw-r--r--json.c100
1 files changed, 54 insertions, 46 deletions
diff --git a/json.c b/json.c
index e68d617..197dca3 100644
--- a/json.c
+++ b/json.c
@@ -5,34 +5,39 @@
#include <math.h>
#include <stdint.h>
#include <stdio.h>
-#include <string.h>
#include "string.h"
typedef struct {
- int value;
+ JSON *value;
+ uintptr_t pos;
+} parse_any_result;
+parse_any_result parse_any(Arena *a, char *src, uintptr_t pos);
+
+typedef struct {
+ int *value;
uintptr_t pos;
} parse_integer_result;
-parse_integer_result parse_integer(Arena *a, Str src, uintptr_t pos) {
- int *ints = new (a, int, 16); // TODO: reuse in parsing
+parse_integer_result parse_integer(Arena *a, char *src, uintptr_t pos) {
+ char ints[16];
int i = 0;
- while (isdigit(src.data[pos + i])) {
- int val = (src.data[pos + i] - '0');
+ while (isdigit(src[pos + i])) {
+ int val = (src[pos + i] - '0');
ints[i] = val;
i++;
}
- int result = 0;
+ int *result = new (a, int, 1);
for (int j = 0; j < i; j++) {
- result += ints[j] * pow(10, (i - j - 1));
+ *result += ints[j] * pow(10, (i - j - 1));
}
- printf("json.parse_integer: parsed int=%d at pos=%lu\n", result, pos);
+ printf("json.parse_integer: parsed int=%d at pos=%lu\n", *result, pos);
return (parse_integer_result){result, pos + i};
}
-uintptr_t absorb_whitespaces(Str src, uintptr_t pos) {
+uintptr_t absorb_whitespaces(char *src, uintptr_t pos) {
int i = 0;
- while (isspace(src.data[pos + i])) {
+ while (isspace(src[pos + i])) {
i++;
}
return pos + i;
@@ -43,27 +48,26 @@ typedef struct {
uintptr_t pos;
} parse_array_result;
-parse_array_result parse_array(Arena *a, Str src, uintptr_t start_pos) {
- printf("json.parse_array: parsing array %s\n", src.data + start_pos);
- assert(src.data[start_pos] == '[');
- uintptr_t pos = start_pos + 1;
- Vec *items = Vec_new(a, JSON, 0);
+parse_array_result parse_array(Arena *a, char *src, uintptr_t pos) {
+ printf("json.parse_array: parsing array %s\n", src + pos);
+ assert(src[pos] == '[');
+ pos++;
+ Vec items = Vec_new(a, JSON, 2);
for (;;) {
pos = absorb_whitespaces(src, pos);
- parse_integer_result result = parse_integer(a, src, pos);
- assert(result.pos > pos);
- items = Vec_push(a, items, &result.value);
+ parse_any_result result = parse_any(a, src, pos);
+ Vec_push(a, &items, result.value);
pos = result.pos;
pos = absorb_whitespaces(src, pos);
- if (src.data[pos] == ',') {
+ if (src[pos] == ',') {
pos++;
} else {
break;
}
};
- assert(src.data[pos] == ']');
+ assert(src[pos] == ']');
- return (parse_array_result){items, pos + 1};
+ return (parse_array_result){&items, pos + 1};
}
typedef struct {
@@ -71,43 +75,47 @@ typedef struct {
uintptr_t pos;
} parse_string_result;
-parse_string_result parse_string(Arena *a, Str src, uintptr_t pos) {
- printf("json.parse_string: %s", src.data + pos);
- assert(src.data[pos] == '"');
+parse_string_result parse_string(Arena *a, char *src, uintptr_t pos) {
+ printf("json.parse_string: %s\n", src + pos);
+ assert(src[pos] == '"');
int i = 1;
- while (src.data[pos + i] != '"' && src.data[pos + i - 1] != '\\') {
+ while (src[pos + i] != '"' && src[pos + i - 1] != '\\') {
i++;
- assert(i + pos <= src.len);
}
- assert(src.data[pos + i]);
- char *s;
- memcpy(s, src.data + pos + 1, i - 1);
+ assert(src[pos + i] == '"');
+ Str s = Str_copy(a, &src[pos + 1], i - 1);
- printf("%s", s);
-
- return (parse_string_result){Str_copy(a, src.data + pos + 1, i - 1), pos + i};
+ return (parse_string_result){s, pos + i + 1};
}
-JSON JSON_parse(Arena *a, Str src) {
- JSON json = {0};
- int pos = 0;
- // printf("json.parse: src=%s", src.data);
- if (isdigit(src.data[pos])) {
- parse_integer_result result = parse_integer(a, src, 0);
- json.integer = &result.value;
+parse_any_result parse_any(Arena *a, char *src, uintptr_t pos) {
+ JSON *value = new (a, JSON, 1);
+ if (isdigit(src[pos])) {
+ parse_integer_result result = parse_integer(a, src, pos);
+ value->integer = result.value;
pos = result.pos;
- }
- if (src.data[pos] == '[') {
+ } else if (src[pos] == '[') {
parse_array_result result = parse_array(a, src, pos);
- json.array = result.items;
+ value->array = result.items;
pos = result.pos;
- }
- if (src.data[pos] == '"') {
+ } else if (src[pos] == '"') {
parse_string_result result = parse_string(a, src, pos);
- json.string = &result.string;
+ value->string = &result.string;
pos = result.pos;
}
+ return (parse_any_result){value, pos};
+}
+
+JSON JSON_parse(Arena *a, char *src) {
+ parse_any_result result = parse_any(a, src, 0);
+ return *result.value;
+}
+
+JSON JSON_Int(Arena *a, int val) {
+ JSON json = {0};
+ json.integer = new (a, int, 1);
+ *json.integer = val;
return json;
}