diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2025-02-14 08:08:57 +0100 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2025-02-14 17:36:38 +0100 |
| commit | d3d71bb044e0ae9af75bd74d4030e1d95f18a68e (patch) | |
| tree | df6a4cbb37f084f64066e4caba0367ad4181984b | |
| parent | 92a97df033086d0ed88c38ad1efe4a2a023eb5fe (diff) | |
feat(json): Nested parsing
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | README.md | 3 | ||||
| -rw-r--r-- | json.c | 67 | ||||
| -rw-r--r-- | json.h | 1 | ||||
| -rw-r--r-- | main.c | 37 | ||||
| -rw-r--r-- | memory.c | 1 | ||||
| -rw-r--r-- | string.c | 2 | ||||
| -rw-r--r-- | vec.c | 19 | ||||
| -rw-r--r-- | vec.h | 4 |
9 files changed, 87 insertions, 49 deletions
@@ -1,9 +1,11 @@ debug: + mkdir -p Debug; \ cd Debug; \ cmake -DCMAKE_BUILD_TYPE=Debug ..; \ make; release: + mkdir -p Release; \ cd Release; \ cmake -DCMAKE_BUILD_TYPE=Release ..; \ make; @@ -3,3 +3,6 @@ ## TODO - Testing setup +- JSON objet as kv +- Vec push no need to reallocate vec, only items. Same for Str? Read about stack pointers in C +- Vec_get not safe, I made a type mistake. And should be more efficient for loops @@ -9,7 +9,13 @@ #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; @@ -21,11 +27,11 @@ parse_integer_result parse_integer(Arena *a, char *src, uintptr_t pos) { 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}; } @@ -42,16 +48,15 @@ typedef struct { uintptr_t pos; } parse_array_result; -parse_array_result parse_array(Arena *a, char *src, uintptr_t start_pos) { - printf("json.parse_array: parsing array %s\n", src + start_pos); - assert(src[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[pos] == ',') { @@ -62,7 +67,7 @@ parse_array_result parse_array(Arena *a, char *src, uintptr_t start_pos) { }; assert(src[pos] == ']'); - return (parse_array_result){items, pos + 1}; + return (parse_array_result){&items, pos + 1}; } typedef struct { @@ -78,31 +83,39 @@ parse_string_result parse_string(Arena *a, char *src, uintptr_t pos) { while (src[pos + i] != '"' && src[pos + i - 1] != '\\') { i++; } - assert(src[pos + i]); + assert(src[pos + i] == '"'); Str s = Str_copy(a, &src[pos + 1], i - 1); - return (parse_string_result){s, pos + i}; + return (parse_string_result){s, pos + i + 1}; } -JSON JSON_parse(Arena *a, char *src) { - JSON json = {0}; - int pos = 0; - printf("json.parse: src=%s\n", src); +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, 0); - json.integer = &result.value; + parse_integer_result result = parse_integer(a, src, pos); + value->integer = result.value; pos = result.pos; - } - if (src[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[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; } @@ -10,4 +10,5 @@ typedef struct { Str *string; } JSON; JSON JSON_parse(Arena *a, char *src); +JSON JSON_Int(Arena *a, int val); #endif @@ -21,34 +21,53 @@ typedef struct { } User; int main() { - Arena perm = Arena_new(128e3); // Testing string + Arena perm = Arena_new(128e3); assert(Str_equals(S("Bonjour"), S("Bonjour"))); Str s = S("Hello"); assert(Str_equals(s, Str_copy(&perm, s.data, s.len))); - // Testing JSON printf("Arena: mem=%d B\n", Arena_get_used(perm)); assert(Arena_get_used(perm) == 5); + // Testing JSON + perm = Arena_new(128e3); JSON json_int = JSON_parse(&perm, "123"); assert(*json_int.integer == 123); printf("Arena: mem=%d B\n", Arena_get_used(perm)); - assert(Arena_get_used(perm) == 5); + assert(Arena_get_used(perm) == 28); + // JSON Int Array + perm = Arena_new(128e3); JSON json_int_array = JSON_parse(&perm, "[1,2,3]"); assert(json_int_array.integer == NULL); assert(json_int_array.array->len == 3); + int ints[3]; int sum = 0; for (int i = 0; i < json_int_array.array->len; i++) { - sum += *Vec_get(json_int_array.array, int, i); + JSON *item = Vec_get(json_int_array.array, JSON, i); + ints[i] = *item->integer; + sum += *item->integer; } + printf("sum=%d\n", sum); + assert(ints[0] == 1); + assert(ints[1] == 2); + assert(ints[2] == 3); assert(sum == 6); printf("Arena: mem=%d B\n", Arena_get_used(perm)); - assert(Arena_get_used(perm) == 48); - assert(*Vec_get(JSON_parse(&perm, "[1, 2, 3]").array, int, 1) == 2); - printf("Arena: mem=%d B\n", Arena_get_used(perm)); - assert(Arena_get_used(perm) == 88); + assert(Arena_get_used(perm) == 264); + // JSON String + perm = Arena_new(128e3); JSON js = JSON_parse(&perm, "\"abc\""); assert(Str_equals(*js.string, S("abc")) == 1); printf("Arena: mem=%d B\n", Arena_get_used(perm)); - assert(Arena_get_used(perm) == 91); + assert(Arena_get_used(perm) == 27); + // JSON Nested hybrid array + perm = Arena_new(128e3); + JSON jaa = JSON_parse(&perm, "[[1,\"abc\"]]"); + JSON sub_array = *Vec_get(jaa.array, JSON, 0); + JSON *val_1 = Vec_get(sub_array.array, JSON, 0); + assert(*val_1->integer == 1); + JSON *val_2 = Vec_get(sub_array.array, JSON, 1); + assert(Str_equals(*val_2->string, S("abc"))); + printf("Arena: mem=%d B\n", Arena_get_used(perm)); + assert(Arena_get_used(perm) == 203); return 0; } @@ -1,6 +1,5 @@ #include <assert.h> #include <stdint.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -25,7 +25,7 @@ uint64_t Str_hash64(Str s) { } Str Str_copy(Arena *a, char *data, uintptr_t len) { - Str str = {0,len}; + Str str = {0, len}; str.data = new (a, char, len); if (str.len) memcpy(str.data, data, len); @@ -1,18 +1,20 @@ #include <string.h> +#include "assert.h" #include "vec.h" -Vec *_Vec_new(Arena *a, int size, ptrdiff_t cap, int align) { - Vec *v = new (a, Vec, 1); - v->data = alloc(a, cap, size, align); - v->size = size; - v->align = align; - v->cap = cap; - v->len = 0; +Vec _Vec_new(Arena *a, int size, ptrdiff_t cap, int align) { + assert(cap > 0); + Vec v = {0}; + v.data = alloc(a, cap, size, align); + v.size = size; + v.align = align; + v.cap = cap; + v.len = 0; return v; } -Vec *Vec_push(Arena *a, Vec *v, void *data) { +void Vec_push(Arena *a, Vec *v, void *data) { if (v->len == v->cap) { void *cpy = alloc(a, v->cap * 2, v->size, v->align); memcpy(cpy, v->data, v->len * v->size); @@ -20,7 +22,6 @@ Vec *Vec_push(Arena *a, Vec *v, void *data) { } memcpy(v->data + v->len * v->size, data, v->size); v->len++; - return v; } void *_Vec_get(Vec *v, int pos) { @@ -13,8 +13,8 @@ typedef struct { int align; } Vec; #define Vec_new(a, T, cap) _Vec_new(a, sizeof(T), cap, _Alignof(T)) -Vec *_Vec_new(Arena *a, int size, ptrdiff_t cap, int align); -Vec *Vec_push(Arena *a, Vec *v, void *data); +Vec _Vec_new(Arena *a, int size, ptrdiff_t cap, int align); +void Vec_push(Arena *a, Vec *v, void *data); #define Vec_get(v, T, p) (T *)_Vec_get(v, p) void *_Vec_get(Vec *v, int pos); #endif |
