Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
a5829ed
feat: json generator #1
debdutdeb Apr 25, 2026
10a661d
refactor: moving string_view to utils
debdutdeb Apr 26, 2026
c5ba612
refactor: remove arena allocator from json generator
debdutdeb Apr 26, 2026
67dda79
wip: recursive string_view_to_json_value
debdutdeb Apr 26, 2026
8ed5200
feat: array_list implementation
debdutdeb Apr 28, 2026
21d5e75
chore(array_list): type specific macro expander
debdutdeb Apr 28, 2026
a9f6124
chore(data::containers): move string_view and array_list to data/cont…
debdutdeb Apr 28, 2026
7742a81
chore: remove unrelated code
debdutdeb Apr 28, 2026
eed0825
feat(iterator): iterator implementation over array_list
debdutdeb Apr 28, 2026
b94d8cc
chore(iterator): use pointer arithmetic
debdutdeb Apr 28, 2026
e8c97b7
fix: temporarily disable arena allocator and remove all void* UB
debdutdeb Apr 28, 2026
33603a3
fix: reenable arena allocator
debdutdeb Apr 28, 2026
2ffdd18
fix(arena): append-only arenas to avoid invalidating old allocation r…
debdutdeb Apr 29, 2026
02fb818
fix(json): finish lexer
debdutdeb Apr 29, 2026
15e0c8b
wip(json/parser): basic recursive pattern
debdutdeb Apr 29, 2026
80d3b32
feat(iterator): experimental transformations over an iterator
debdutdeb Apr 29, 2026
9029f27
feat(iterator_mutating): mutating iterator implementation
debdutdeb Apr 29, 2026
b27da28
fix(progressbar): linux build
debdutdeb May 2, 2026
4a72938
fix(iterator): merge main
debdutdeb May 4, 2026
e8254bb
Merge branch 'main' into feat/json
debdutdeb May 4, 2026
1b874ce
Merge remote-tracking branch 'origin/main' into feat/json
debdutdeb May 27, 2026
717adef
Merge branch 'main' into feat/json
debdutdeb May 28, 2026
2eb1f3f
tests: add lexer tests
debdutdeb May 28, 2026
35f7b2d
chore: remove old examples that have been replaced by tests
debdutdeb May 28, 2026
02e3df5
Merge branch 'main' into feat/json
debdutdeb May 28, 2026
c3774d9
chore: use containers::string for json_value
debdutdeb May 28, 2026
5b9821f
wip
debdutdeb May 28, 2026
0eed6c8
Merge branch 'main' into feat/json
debdutdeb May 31, 2026
45b8df7
chore: parse_string
debdutdeb May 31, 2026
4e6ada4
test: optimize string to cstr compare function
debdutdeb May 31, 2026
3dc8bc7
chore: add eof as token to capture early semantic ends
debdutdeb May 31, 2026
b16b387
refactor: ...
debdutdeb Jun 3, 2026
ac463ee
Merge branch 'main' into feat/json
debdutdeb Jun 9, 2026
fd0a5ab
fix(string): string to cstr comparison for underlying method family
debdutdeb Jun 9, 2026
24b2c1f
feat(data::containers): add stack
debdutdeb Jun 13, 2026
33e0252
refactor(json): using grammar engine-like
debdutdeb Jun 13, 2026
a5243e5
fix(arena): better logs
debdutdeb Jun 13, 2026
cb65baa
chore: update cmakelists.txt with new deps
debdutdeb Jun 13, 2026
b05968c
chore(string_builder): update
debdutdeb Jun 13, 2026
1fd5900
chore: allow filter by tests
debdutdeb Jun 13, 2026
ab8bb24
feat(data::containers): add stack_peek
debdutdeb Jun 13, 2026
2544688
feat(utils): add `unreachable` macro
debdutdeb Jun 13, 2026
48f5df2
refactor(json): add grammar rule table
debdutdeb Jun 13, 2026
441c476
chore(json): add in_key:colon rule
debdutdeb Jun 13, 2026
e096047
wip_replace_me
debdutdeb Jun 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_subdirectory(libs/arena_allocator)
add_subdirectory(libs/data)

add_subdirectory(libs/progressbar)
add_subdirectory(libs/json)
add_subdirectory(libs/mover)
add_subdirectory(examples)

Expand Down
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
compile_commands:
cmake -G Ninja -B build

build: compile_commands
cmake --build build

test: build
ifdef T
cd build && ctest --output-on-failure -R $(T)
else
cd build && ctest --output-on-failure
endif

.PHONY: compile_commands build test
6 changes: 6 additions & 0 deletions docs/libs/containers/string.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ char *raw = string_to_primitive_underlying(s);
printf("Raw: %s\n", raw);
```

Note:
Since inside, string is just an `array_list`, it is not null terminated. Caller must use `string_length` along with `string_to_primitive_underlying` for this to work correctly. Or else use `string_to_primitive` which incurs copy and allocation cost.

For comparisons, use `string_cmp_cstr` instead.


## API Reference

| Function / Macro | Description |
Expand Down
4 changes: 0 additions & 4 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
add_executable(progressbar progressbar.c)
target_link_libraries(progressbar PRIVATE cisastor::progressbar m)
add_executable(array_list array_list.c)
target_link_libraries(array_list PRIVATE cisastor::utils)
target_link_libraries(array_list PRIVATE cisastor::data::containers)
target_link_libraries(array_list PRIVATE cisastor::arena)
86 changes: 0 additions & 86 deletions examples/array_list.c

This file was deleted.

9 changes: 9 additions & 0 deletions libs/arena_allocator/arena.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ void *arena_alloc(size_t size) {
// sizeof(char) == 1 byte most of the time;
size_t required_size = size < ARENA_SIZ ? ARENA_SIZ : size * 2;
arena.chunk = malloc(required_size);
if (arena.chunk == null) {
fprintf(stderr, "Failed to initialize Arena\n");
return null;
}
arena.size = required_size;
arena.ptr = arena.chunk;
atexit(arena_free);
Expand All @@ -62,11 +66,16 @@ void *arena_alloc(size_t size) {
current = new_arena;
size_t new_size = size > ARENA_SIZ ? size * 2 : ARENA_SIZ;
current->chunk = malloc(new_size);
if (current->chunk == null) {
perror("new_arena_chunk_allocation");
return null;
}
current->ptr = current->chunk;
current->size = new_size;
current->next_arena = null;
}
if (null == current->chunk || null == current->ptr) {
perror("no_arena_region");
return null;
}
void *allocated = current->ptr;
Expand Down
9 changes: 9 additions & 0 deletions libs/data/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_library(cisastor_data_containers STATIC
containers/iterator.c
containers/string.c
containers/string_builder.c
containers/stack.c
)

target_include_directories(cisastor_data_containers INTERFACE
Expand Down Expand Up @@ -55,3 +56,11 @@ cisastor_add_test(
IMPLS containers/string_builder.c containers/string.c containers/array_list.c containers/iterator.c
LIBS cisastor::arena cisastor::utils
)

cisastor_add_test(
NAME stack_test
SRCS containers/stack_test.c
IMPLS containers/stack.c containers/array_list.c
LIBS cisastor::arena cisastor::utils
)

3 changes: 3 additions & 0 deletions libs/data/containers/iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,6 @@ void *iterator_mutating_end(struct iterator_mutating *itm);
#define for_each(it, list) \
for (struct iterator *it = iterator_begin(list); \
iterator_end(it) != iterator_element(it); iterator_increment(it))

#define for_each_it(it) \
for (; iterator_end(it) != iterator_element(it); iterator_increment(it))
28 changes: 28 additions & 0 deletions libs/data/containers/stack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "stack.h"
#include "array_list.h"

stack *stack_create(size_t size) { return array_list_create(size); }

byte *stack_peek(stack *s) {
struct array_list *al = cast(struct array_list *, s);
void *element = array_list_get_element_at(al, al->length - 1);
if (element == null) {
return null;
}
return element;
}

byte *stack_pop(stack *s) {
void *element = stack_peek(s);
if (element == null) {
return null;
}
// array_list does not own anything, so this is fine, we aren't leaking memory
// by moving the cursor;
cast(struct array_list *, s)->length--;
return element;
}

void stack_push(stack *s, byte *data) { array_list_append(s, data); }

size_t stack_size(stack *s) { return array_list_get_length(s); }
35 changes: 35 additions & 0 deletions libs/data/containers/stack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include "array_list.h"
#include "macros.h"

typedef struct array_list stack;

stack *stack_create(size_t size);

byte *stack_pop(stack *);
byte *stack_peek(stack *);
void stack_push(stack *, byte *data);

size_t stack_size(stack *);

#define stack_init(type) \
typedef stack stack_##type; \
static inline stack_##type *stack_create_##type() { \
return stack_create(sizeof(type)); \
} \
static inline void stack_push_##type(stack_##type *s, type data) { \
stack_push(s, cast(byte *, &data)); \
} \
static inline void stack_push_##type##_ptr(stack_##type *s, type *data) { \
stack_push(s, cast(byte *, data)); \
} \
static inline type *stack_pop_##type(stack_##type *s) { \
return cast(type *, stack_pop(s)); \
} \
static inline type *stack_peek_##type(stack_##type *s) { \
return cast(type *, stack_peek(s)); \
}

stack_init(int);
stack_init(char);
41 changes: 41 additions & 0 deletions libs/data/containers/stack_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "testing.h"

#include "stack.h"

IT(should_enstack_elements_and_pop) {
stack_int *q = stack_create_int();
for (int i = 1; i <= 10000; i++) {
stack_push_int(q, i);
}
cassert(stack_size(q) == 10000, "invalid stack size, should be 10000");
for (int i = 10000; i > 0; i--) {
int *_got = stack_pop_int(q);
cassertf(_got != null, "popped null data at index %d\n", i);
int got = *_got;
cassertf(got == i, "expected %d got %d\n", i, got);
}
cassert(stack_size(q) == 0, "size should be 0 now");
}

IT(should_peek_pop_correctly) {
stack_int *s = stack_create_int();
stack_push_int(s, 0);
int *i = null;
i = stack_peek_int(s);
cassert(i != null, "peek should not be null, value should be 0 at the "
"beginning that is peeked into");
cassert(*i == 0, "should peek value 0");
stack_push_int(s, 1);
i = stack_peek_int(s);
cassert(i != null,
"peek should not be null, value should be 1 that is peeked into");
cassert(*i == 1, "peek should be 1");
i = stack_pop_int(s);
cassert(i != null,
"pop should not be null, value should be 1 that is popped");
cassert(*i == 1, "pop should be 1");
i = stack_peek_int(s);
cassert(i != null,
"peek should not be null, value should be 0 that is peeked into");
cassert(*i == 0, "peek should be 0");
}
10 changes: 10 additions & 0 deletions libs/data/containers/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,15 @@ char *string_to_primitive(string *str) {
}

char *const string_to_primitive_underlying(string *str) {
// Since inside, string is just an array_list, it is not null terminated.
// Caller must use string_length along with _to_primitive_underlying for this
// to work correctly. Or else use string_to_primitive which incurs copy and
// allocation cost.
// For comparisons, use string_cmp_cstr instead.
return cast(struct array_list *, str)->region;
}

// str[n]cmp for using string with cstrs
uint8_t string_cmp_cstr(string *str, const char *const cstr) {
return strncmp(string_to_primitive_underlying(str), cstr, string_length(str));
}
2 changes: 2 additions & 0 deletions libs/data/containers/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ string *string_from_array_list(struct array_list_char *al);
char *string_to_primitive(string *str);

char *const string_to_primitive_underlying(string *str);

uint8_t string_cmp_cstr(string *str, const char *const cstr);
5 changes: 5 additions & 0 deletions libs/data/containers/string_builder.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "array_list.h"
#include "string.h"

#include <stdarg.h>
#include <string.h>

string_builder *string_builder_create() {
Expand All @@ -22,6 +23,10 @@ string *string_builder_build(string_builder *sb) {
capacity += strlen(*array_list_get_const_char_ptr_at(sb, i));
}
string *str = cast(string *, array_list_create_char_with_capacity(capacity));
if (str == null) {
perror("string_builder_build_new_string");
return null;
}
for (int i = 0; i < array_list_get_length(sb); i++) {
const char *cstr = *array_list_get_const_char_ptr_at(sb, i);
for (int j = 0; cstr[j] != '\0'; j++) {
Expand Down
13 changes: 7 additions & 6 deletions libs/data/containers/string_builder_test.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "testing.h"
#include "string_builder.h"
#include "testing.h"

IT(should_create_string_builder) {
string_builder *sb = string_builder_create();
Expand All @@ -10,10 +10,10 @@ IT(should_join_strings) {
string_builder *sb = string_builder_create();
string_builder_join(sb, "hello ");
string_builder_join(sb, "world");

string *str = string_builder_build(sb);
cassert(string_length(str) == 11, "length should be 11");

string *expected = string_create("hello world");
cassert(string_cmp(str, expected) == 0, "string mismatch");
}
Expand All @@ -23,10 +23,11 @@ IT(should_handle_many_joins) {
for (int i = 0; i < 1000; i++) {
string_builder_join(sb, "a");
}

string *str = string_builder_build(sb);
cassert(string_length(str) == 1000, "length should be 1000");
for(int i = 0; i < 1000; i++) {
cassertf(string_char_at(str, i) == 'a', "mismatch at idx %d", i);
for (int i = 0; i < 1000; i++) {
cassertf(string_char_at(str, i) == 'a', "mismatch at idx %d", i);
}
}

Loading
Loading