diff options
| -rw-r--r-- | .gitignore | 6 | ||||
| -rw-r--r-- | .vscode/launch.json | 16 | ||||
| -rw-r--r-- | .vscode/settings.json | 6 | ||||
| -rw-r--r-- | CMakeLists.txt | 3 | ||||
| -rw-r--r-- | Makefile | 11 | ||||
| -rw-r--r-- | README.md | 8 | ||||
| -rw-r--r-- | json.c | 100 | ||||
| -rw-r--r-- | json.h | 3 | ||||
| -rw-r--r-- | log.c | 2 | ||||
| -rw-r--r-- | main.c | 44 | ||||
| -rw-r--r-- | memory.c | 1 | ||||
| -rw-r--r-- | string.c | 2 | ||||
| -rw-r--r-- | vec.c | 23 | ||||
| -rw-r--r-- | vec.h | 4 |
14 files changed, 150 insertions, 79 deletions
@@ -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 @@ -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; } @@ -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 @@ -8,4 +8,4 @@ void info(Logger l, const char *name, const char *str, ...) { printf(str); printf("\n"); } -}; +} @@ -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; } @@ -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}; + Str str = {0, len}; str.data = new (a, char, len); if (str.len) memcpy(str.data, data, len); @@ -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) { @@ -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 |
