diff options
| author | Martin Lehoux <martin@lehoux.net> | 2025-02-14 16:39:54 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-14 16:39:54 +0000 |
| commit | 03632f51152e5e3b6bb74c29987709fbe97a9a69 (patch) | |
| tree | df6a4cbb37f084f64066e4caba0367ad4181984b /json.c | |
| parent | 8a9e6b1bd3be1041792311a86d8aac68b659e891 (diff) | |
| parent | d3d71bb044e0ae9af75bd74d4030e1d95f18a68e (diff) | |
Merge pull request #1 from martinlehoux/json-nested-parsing
json nested parsing
Diffstat (limited to 'json.c')
| -rw-r--r-- | json.c | 100 |
1 files changed, 54 insertions, 46 deletions
@@ -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; } |
