aboutsummaryrefslogtreecommitdiff
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
parent8a9e6b1bd3be1041792311a86d8aac68b659e891 (diff)
parentd3d71bb044e0ae9af75bd74d4030e1d95f18a68e (diff)
Merge pull request #1 from martinlehoux/json-nested-parsing
json nested parsing
-rw-r--r--.gitignore6
-rw-r--r--.vscode/launch.json16
-rw-r--r--.vscode/settings.json6
-rw-r--r--CMakeLists.txt3
-rw-r--r--Makefile11
-rw-r--r--README.md8
-rw-r--r--json.c100
-rw-r--r--json.h3
-rw-r--r--log.c2
-rw-r--r--main.c44
-rw-r--r--memory.c1
-rw-r--r--string.c2
-rw-r--r--vec.c23
-rw-r--r--vec.h4
14 files changed, 150 insertions, 79 deletions
diff --git a/.gitignore b/.gitignore
index e7ea508..58c83ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,4 @@
main
-cmake_install.cmake
-Makefile
-CMakeFiles/
-CMakeCache.txt
+Debug/
+Release/
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..3b84b2e
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,16 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "lldb",
+ "request": "launch",
+ "name": "Debug",
+ "program": "${workspaceFolder}/Debug/main",
+ "args": [],
+ "cwd": "${workspaceFolder}"
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..36ecaad
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+ "lldb.displayFormat": "auto",
+ "lldb.showDisassembly": "auto",
+ "lldb.dereferencePointers": true,
+ "lldb.consoleMode": "evaluate"
+} \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c94bd65..ddba94b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.30.5)
project(kagamic VERSION 0.1 LANGUAGES C)
+set(CMAKE_C_STANDARD 17)
add_executable(main
main.c
string.h string.c
@@ -9,4 +10,4 @@ add_executable(main
log.h log.c
)
target_link_libraries(main m)
-target_compile_options(main PRIVATE -Wall)
+target_compile_options(main PRIVATE -Wall -pedantic -Wextra)
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..58cdf1f
--- /dev/null
+++ b/Makefile
@@ -0,0 +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;
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6536ed4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# Kagamic
+
+## 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
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;
}
diff --git a/json.h b/json.h
index 588cb6b..44b064e 100644
--- a/json.h
+++ b/json.h
@@ -9,5 +9,6 @@ typedef struct {
Vec *array;
Str *string;
} JSON;
-JSON JSON_parse(Arena *a, Str src);
+JSON JSON_parse(Arena *a, char *src);
+JSON JSON_Int(Arena *a, int val);
#endif
diff --git a/log.c b/log.c
index 9a3211f..76bee11 100644
--- a/log.c
+++ b/log.c
@@ -8,4 +8,4 @@ void info(Logger l, const char *name, const char *str, ...) {
printf(str);
printf("\n");
}
-};
+}
diff --git a/main.c b/main.c
index 0910b3d..88d7855 100644
--- a/main.c
+++ b/main.c
@@ -21,27 +21,53 @@ typedef struct {
} User;
int main() {
+ // Testing string
Arena perm = Arena_new(128e3);
assert(Str_equals(S("Bonjour"), S("Bonjour")));
- // Testing JSON
+ Str s = S("Hello");
+ assert(Str_equals(s, Str_copy(&perm, s.data, s.len)));
printf("Arena: mem=%d B\n", Arena_get_used(perm));
- JSON json_int = JSON_parse(&perm, S("123"));
+ 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));
- JSON json_int_array = JSON_parse(&perm, S("[1,2,3]"));
+ 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(*Vec_get(JSON_parse(&perm, S("[1, 2, 3]")).array, int, 1) == 2);
+ 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) == 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));
- Str a = S("\"abc\"");
- JSON s = JSON_parse(&perm, S("\"abc\""));
- // printf("%s (%d)\n", s.string->data, s.string->len);
- // assert(Str_equals(*JSON_parse(&perm, S("\"abc\"")).string, S("abc")) == 1);
+ assert(Arena_get_used(perm) == 203);
return 0;
}
diff --git a/memory.c b/memory.c
index cfb5dd4..f2248b6 100644
--- a/memory.c
+++ b/memory.c
@@ -1,6 +1,5 @@
#include <assert.h>
#include <stdint.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/string.c b/string.c
index 509163f..b07ba02 100644
--- a/string.c
+++ b/string.c
@@ -25,7 +25,7 @@ uint64_t Str_hash64(Str s) {
}
Str Str_copy(Arena *a, char *data, uintptr_t len) {
- Str str = {0};
+ Str str = {0, len};
str.data = new (a, char, len);
if (str.len)
memcpy(str.data, data, len);
diff --git a/vec.c b/vec.c
index 6962d03..8923f19 100644
--- a/vec.c
+++ b/vec.c
@@ -1,22 +1,20 @@
-#include <stdio.h>
#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) {
- // printf("push: dest=%p, src=%p, size=%d\n", v->data + v->len * v->size,
- // data,
- // v->size);
+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);
@@ -24,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) {
diff --git a/vec.h b/vec.h
index 9fb9590..f7e5295 100644
--- a/vec.h
+++ b/vec.h
@@ -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