aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--json.c279
-rw-r--r--json.h27
-rw-r--r--string.c12
-rw-r--r--string.h2
-rw-r--r--test_json.c99
-rw-r--r--test_string.c6
-rw-r--r--test_vec.c12
-rw-r--r--vec.c17
-rw-r--r--vec.h4
10 files changed, 244 insertions, 216 deletions
diff --git a/README.md b/README.md
index b8b1035..7083968 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,8 @@
- Static functions for private?
- JSON: tagged union for memory, remove pointer and use bitflag
- `valgrind --leak-check=full ./your_program`
+- assert with error msg?
+- negative numbers
## Resources
diff --git a/json.c b/json.c
index cf78baa..e189032 100644
--- a/json.c
+++ b/json.c
@@ -14,77 +14,121 @@
JSONObject *JSONObject_new(Arena *a) {
JSONObject *object = new(a, JSONObject, 1);
object->len = 0;
- object->keys = *Vec_new(a, Str, 2);
- object->values = *Vec_new(a, JSON, 2);
+ object->keys = Vec_new(a, Str, 2);
+ object->values = Vec_new(a, JSON, 2);
return object;
}
+JSON JSON_integer(i32 value) {
+ JSON json = {0};
+ json.type = JSON_INTEGER;
+ json.as.integer = value;
+ return json;
+}
+
+JSON JSON_float(f32 value) {
+ JSON json = {0};
+ json.type = JSON_FLOAT;
+ json.as.floating = value;
+ return json;
+}
+
+JSON JSON_array(Vec items) {
+ JSON json = {0};
+ json.type = JSON_ARRAY;
+ json.as.array = items;
+ return json;
+}
+
+JSON JSON_string(Str value) {
+ JSON json = {0};
+ json.type = JSON_STRING;
+ json.as.string = value;
+ return json;
+}
+
+JSON JSON_object(size len, Vec keys, Vec values) {
+ assert(len == keys.len && len == values.len);
+ JSON json = {0};
+ json.type = JSON_OBJECT;
+ json.as.object.len = len;
+ json.as.object.keys = keys;
+ json.as.object.values = values;
+ return json;
+}
+
+JSON JSON_boolean(bool value) {
+ JSON json = {0};
+ json.type = JSON_BOOL;
+ json.as.boolean = value;
+ return json;
+}
+
+JSON JSON_null() {
+ JSON json = {0};
+ json.type = JSON_NULL;
+ return json;
+}
+
i32 JSON_fprint(FILE *w, JSON json) {
- if (json.string != 0) {
+ switch (json.type) {
+ case JSON_STRING:
fprintf(w, "\"");
- Str_fprint(w, *json.string);
+ Str_fprint(w, json.as.string);
return fprintf(w, "\"");
- }
- if (json.integer != 0)
- return fprintf(w, "%d", *json.integer);
- if (json.floating != 0)
- return fprintf(w, "%f", *json.floating);
- if (json.boolean != 0)
- return fprintf(w, "%s", *json.boolean ? "true" : "false");
- if (json.object != 0) {
+ case JSON_INTEGER:
+ return fprintf(w, "%d", json.as.integer);
+ case JSON_FLOAT:
+ return fprintf(w, "%f", json.as.floating);
+ case JSON_NULL:
+ return fprintf(w, "null");
+ case JSON_BOOL:
+ return fprintf(w, "%s", json.as.boolean ? "true" : "false");
+ case JSON_ARRAY:
+ fprintf(w, "[");
+ for (size i = 0; i < json.as.array.len; i++) {
+ JSON value = *Vec_get(json.as.array, JSON, i);
+ JSON_fprint(w, value);
+ if (i < json.as.array.len - 1)
+ fprintf(w, ", ");
+ }
+ fprintf(w, "]");
+ return 0;
+ case JSON_OBJECT:
fprintf(w, "{");
- for (size i = 0; i < json.object->len; i++) {
- Str key = *Vec_get(&json.object->keys, Str, i);
+ for (size i = 0; i < json.as.object.len; i++) {
+ Str key = *Vec_get(json.as.object.keys, Str, i);
fprintf(w, "\"");
Str_fprint(w, key);
fprintf(w, "\": ");
- JSON value = *Vec_get(&json.object->values, JSON, i);
+ JSON value = *Vec_get(json.as.object.values, JSON, i);
JSON_fprint(w, value);
- if (i < json.object->len - 1)
+ if (i < json.as.object.len - 1)
fprintf(w, ", ");
}
fprintf(w, "}");
return 0;
}
- if (json.array != 0) {
- fprintf(w, "[");
- for (size i = 0; i < json.array->len; i++) {
- JSON value = *Vec_get(json.array, JSON, i);
- JSON_fprint(w, value);
- if (i < json.array->len - 1)
- fprintf(w, ", ");
- }
- fprintf(w, "]");
- return 0;
- }
- return fprintf(w, "null");
+ assert(false);
}
typedef struct {
- JSON *value;
+ JSON value;
uptr pos;
-} parse_any_result;
-parse_any_result parse_any(Arena *a, byte *src, uptr pos);
+} parse_result;
-typedef struct {
- i32 *integer;
- f32 *floating;
- uptr pos;
-} parse_number_result;
+parse_result parse_any(Arena *a, byte *src, uptr pos);
-parse_number_result parse_number(Arena *a, byte *src, uptr start_pos) {
- parse_number_result result = {0};
+parse_result parse_number(byte *src, uptr start_pos) {
+ parse_result result = {0};
result.pos = start_pos;
- result.floating = 0;
- result.integer = 0;
i32 integer = 0;
while (isdigit(src[result.pos])) {
integer = integer * 10 + (src[result.pos] - '0');
result.pos++;
}
if (src[result.pos] != '.') {
- result.integer = new(a, int, 1);
- *result.integer = integer;
+ result.value = JSON_integer(integer);
return result;
}
result.pos++;
@@ -95,8 +139,7 @@ parse_number_result parse_number(Arena *a, byte *src, uptr start_pos) {
decimal_place *= 0.1;
result.pos++;
}
- result.floating = new(a, f32, 1);
- *result.floating = (f32)integer + fractional_part;
+ result.value = JSON_float((f32)integer + fractional_part);
return result;
}
@@ -108,25 +151,20 @@ uptr absorb_whitespaces(byte *src, uptr start_pos) {
return pos;
}
-typedef struct {
- Vec *items; // Vec<JSON>
- uptr pos;
-} parse_array_result;
-
-parse_array_result parse_array(Arena *a, byte *src, uptr start_pos) {
+parse_result parse_array(Arena *a, byte *src, uptr start_pos) {
assert(src[start_pos] == '[');
- parse_array_result result = {0};
+ parse_result result = {0};
result.pos = start_pos + 1;
- result.items = Vec_new(a, JSON, 2);
if (src[result.pos] == ']') {
result.pos++;
return result;
}
+ Vec items = Vec_new(a, JSON, 2);
for (;;) {
result.pos = absorb_whitespaces(src, result.pos);
- parse_any_result any_result = parse_any(a, src, result.pos);
- Vec_push(a, result.items, any_result.value);
- result.pos = absorb_whitespaces(src, any_result.pos);
+ parse_result item_result = parse_any(a, src, result.pos);
+ Vec_push(a, &items, &item_result.value);
+ result.pos = absorb_whitespaces(src, item_result.pos);
if (src[result.pos] == ',') {
result.pos++;
} else {
@@ -135,55 +173,49 @@ parse_array_result parse_array(Arena *a, byte *src, uptr start_pos) {
};
assert(src[result.pos] == ']');
result.pos++;
+ result.value = JSON_array(items);
return result;
}
-typedef struct {
- Str *string;
- uptr pos;
-} parse_string_result;
-
-parse_string_result parse_string(Arena *a, byte *src, uptr start_pos) {
+parse_result parse_string(Arena *a, byte *src, uptr start_pos) {
assert(src[start_pos] == '"');
- parse_string_result result = {0};
+ parse_result result = {0};
result.pos = start_pos + 1;
while (src[result.pos] != '"' && src[result.pos - 1] != '\\') {
result.pos++;
}
assert(src[result.pos] == '"');
- result.string =
- Str_copy(a, &src[start_pos + 1], result.pos - start_pos - 1);
+ result.value = JSON_string(
+ Str_copy(a, &src[start_pos + 1], result.pos - start_pos - 1));
result.pos++;
return result;
}
-typedef struct {
- JSONObject *object;
- uptr pos;
-} parse_object_result;
-
-parse_object_result parse_object(Arena *a, byte *src, uptr start_pos) {
+parse_result parse_object(Arena *a, byte *src, uptr start_pos) {
assert(src[start_pos] == '{');
- parse_object_result result = {0};
- result.pos = start_pos + 1;
- result.object = JSONObject_new(a);
- result.pos = absorb_whitespaces(src, result.pos);
+ parse_result result = {0};
+ result.pos = absorb_whitespaces(src, start_pos + 1);
+ size len = 0;
+ Vec keys = Vec_new(a, Str, 2);
+ Vec values = Vec_new(a, JSON, 2);
if (src[result.pos] == '}') {
result.pos++;
+ result.value = JSON_object(len, keys, values);
return result;
}
for (;;) {
assert(src[result.pos] == '"');
- parse_string_result key_result = parse_string(a, src, result.pos);
+ parse_result key_result = parse_string(a, src, result.pos);
result.pos = absorb_whitespaces(src, key_result.pos);
assert(src[result.pos] == ':');
result.pos = absorb_whitespaces(src, result.pos + 1);
- parse_any_result value_result = parse_any(a, src, result.pos);
- result.object->len++;
- Vec_push(a, &result.object->keys, key_result.string);
- Vec_push(a, &result.object->values, value_result.value);
+ parse_result value_result = parse_any(a, src, result.pos);
+ len++;
+ assert(key_result.value.type == JSON_STRING);
+ Vec_push(a, &keys, &key_result.value.as.string);
+ Vec_push(a, &values, &value_result.value);
result.pos = absorb_whitespaces(src, value_result.pos);
if (src[result.pos] != ',') {
break;
@@ -192,67 +224,48 @@ parse_object_result parse_object(Arena *a, byte *src, uptr start_pos) {
}
assert(src[result.pos] == '}');
result.pos++;
+ result.value = JSON_object(len, keys, values);
return result;
}
-parse_any_result parse_any(Arena *a, byte *src, uptr start_pos) {
- parse_any_result result = {0};
- result.pos = start_pos;
- result.value = new(a, JSON, 1);
- if (isdigit(src[result.pos])) {
- parse_number_result number_result = parse_number(a, src, result.pos);
- if (number_result.integer != 0)
- result.value->integer = number_result.integer;
- else if (number_result.floating != 0)
- result.value->floating = number_result.floating;
- result.pos = number_result.pos;
- } else if (src[result.pos] == '[') {
- parse_array_result array_result = parse_array(a, src, result.pos);
- result.value->array = array_result.items;
- result.pos = array_result.pos;
- } else if (src[result.pos] == '"') {
- parse_string_result string_result = parse_string(a, src, result.pos);
- result.value->string = string_result.string;
- result.pos = string_result.pos;
- } else if (src[result.pos] == '{') {
- parse_object_result object_result = parse_object(a, src, result.pos);
- result.value->object = object_result.object;
- result.pos = object_result.pos;
- } else if (memcmp(src + result.pos, "true", 4) == 0) {
- result.value->boolean = new(a, i32, 1);
- *result.value->boolean = 1;
- result.pos = start_pos + 4;
- } else if (memcmp(src + result.pos, "false", 5) == 0) {
- result.value->boolean = new(a, i32, 1);
- *result.value->boolean = 0;
- result.pos = start_pos + 5;
- } else if (memcmp(src + result.pos, "null", 4) == 0) {
- result.value->null = new(a, i32, 1);
- result.pos = start_pos + 4;
- } else {
- assert(false);
+parse_result parse_any(Arena *a, byte *src, uptr pos) {
+ pos = absorb_whitespaces(src, pos);
+ if (isdigit(src[pos]))
+ return parse_number(src, pos);
+ if (src[pos] == '[')
+ return parse_array(a, src, pos);
+ if (src[pos] == '"')
+ return parse_string(a, src, pos);
+ if (src[pos] == '{')
+ return parse_object(a, src, pos);
+ if (memcmp(src + pos, "true", 4) == 0) {
+ parse_result result = {0};
+ result.value = JSON_boolean(true);
+ result.pos = pos + 4;
+ return result;
}
-
- return result;
-}
-
-JSON JSON_parse(Arena *a, byte *src) {
- parse_any_result result = parse_any(a, src, 0);
- return *result.value;
+ if (memcmp(src + pos, "false", 5) == 0) {
+ parse_result result = {0};
+ result.value = JSON_boolean(false);
+ result.pos = pos + 5;
+ return result;
+ }
+ if (memcmp(src + pos, "null", 4) == 0) {
+ parse_result result = {0};
+ result.value = JSON_null();
+ result.pos = pos + 4;
+ return result;
+ }
+ assert(false);
}
-JSON JSON_Int(Arena *a, i32 val) {
- JSON json = {0};
- json.integer = new(a, i32, 1);
- *json.integer = val;
- return json;
-}
+JSON JSON_parse(Arena *a, byte *src) { return parse_any(a, src, 0).value; }
-JSON *JSONObject_get(JSONObject *obj, Str key) {
- for (size i = 0; i < obj->len; i++) {
- if (Str_equals(*Vec_get(&obj->keys, Str, i), key)) {
- return Vec_get(&obj->values, JSON, i);
+JSON *JSONObject_get(JSONObject obj, Str key) {
+ for (size i = 0; i < obj.len; i++) {
+ if (Str_equals(*Vec_get(obj.keys, Str, i), key)) {
+ return Vec_get(obj.values, JSON, i);
}
}
- return 0;
+ assert(false);
}
diff --git a/json.h b/json.h
index 99e3e75..60e853c 100644
--- a/json.h
+++ b/json.h
@@ -9,16 +9,27 @@ typedef struct {
Vec values; // Vec<JSON>
size len;
} JSONObject;
+typedef enum {
+ JSON_NULL,
+ JSON_BOOL,
+ JSON_INTEGER,
+ JSON_FLOAT,
+ JSON_STRING,
+ JSON_ARRAY,
+ JSON_OBJECT
+} JSONType;
typedef struct {
- i32 *boolean;
- i32 *integer;
- f32 *floating;
- Vec *array; // Vec<JSON>
- Str *string;
- void *null;
- JSONObject *object;
+ JSONType type;
+ union {
+ bool boolean;
+ i32 integer;
+ f32 floating;
+ Vec array; // Vec<JSON>
+ Str string;
+ JSONObject object;
+ } as;
} JSON;
-JSON *JSONObject_get(JSONObject *obj, Str key);
+JSON *JSONObject_get(JSONObject obj, Str key);
i32 JSON_fprint(FILE *w, JSON json);
JSON JSON_parse(Arena *a, byte *src);
JSON JSON_Int(Arena *a, i32 val);
diff --git a/string.c b/string.c
index 2c4e749..0d6fa7c 100644
--- a/string.c
+++ b/string.c
@@ -20,12 +20,12 @@ u64 Str_hash64(Str s) {
return h;
}
-Str *Str_copy(Arena *a, byte *data, size len) {
- Str *str = new(a, Str, 1);
- str->len = len;
- str->data = new(a, byte, len);
- if (str->len)
- memcpy(str->data, data, len);
+Str Str_copy(Arena *a, byte *data, size len) {
+ Str str = {0};
+ str.len = len;
+ str.data = new(a, byte, len);
+ if (str.len)
+ memcpy(str.data, data, len);
return str;
}
diff --git a/string.h b/string.h
index aed7945..a4c1e1a 100644
--- a/string.h
+++ b/string.h
@@ -15,6 +15,6 @@ typedef struct {
} Str;
i32 Str_equals(Str a, Str b);
u64 Str_hash64(Str s);
-Str *Str_copy(Arena *a, byte *data, size len);
+Str Str_copy(Arena *a, byte *data, size len);
i32 Str_fprint(FILE *w, Str s);
#endif
diff --git a/test_json.c b/test_json.c
index 7f0d07c..7243a34 100644
--- a/test_json.c
+++ b/test_json.c
@@ -6,8 +6,8 @@ i32 test_json_integer() {
JSON json_int = JSON_parse(&perm, "123");
- t_assert(*json_int.integer == 123);
- t_assert_equal(Arena_get_used(perm), 60);
+ t_assert(json_int.as.integer == 123);
+ t_assert_equal(Arena_get_used(perm), 0);
return 0;
}
@@ -16,20 +16,20 @@ i32 test_json_int_array() {
JSON json_int_array = JSON_parse(&perm, "[1,2,3]");
- t_assert(json_int_array.integer == 0);
- t_assert_equal(json_int_array.array->len, 3);
+ t_assert(json_int_array.type == JSON_ARRAY);
+ t_assert_equal(json_int_array.as.array.len, 3);
int ints[3];
int sum = 0;
- for (int i = 0; i < json_int_array.array->len; i++) {
- JSON *item = Vec_get(json_int_array.array, JSON, i);
- ints[i] = *item->integer;
- sum += *item->integer;
+ for (int i = 0; i < json_int_array.as.array.len; i++) {
+ JSON *item = Vec_get(json_int_array.as.array, JSON, i);
+ ints[i] = item->as.integer;
+ sum += item->as.integer;
}
t_assert(ints[0] == 1);
t_assert(ints[1] == 2);
t_assert(ints[2] == 3);
t_assert(sum == 6);
- t_assert_equal(Arena_get_used(perm), 624);
+ t_assert_equal(Arena_get_used(perm), 576);
return 0;
}
@@ -39,8 +39,8 @@ i32 test_json_empty_array() {
JSON json_empty_array = JSON_parse(&perm, "[]");
- t_assert(json_empty_array.array->len == 0);
- t_assert_equal(Arena_get_used(perm), 208);
+ t_assert(json_empty_array.as.array.len == 0);
+ t_assert_equal(Arena_get_used(perm), 0); // TODO: weird
return 0;
}
@@ -50,14 +50,14 @@ i32 test_json_nested_array() {
JSON doc = JSON_parse(&perm, "[[1,\"abc\"]]");
- JSON sub_array = *Vec_get(doc.array, JSON, 0);
- JSON val_1 = *Vec_get(sub_array.array, JSON, 0);
- t_assert(*val_1.integer == 1);
- JSON val_2 = *Vec_get(sub_array.array, JSON, 1);
- Str str = *val_2.string;
+ JSON sub_array = *Vec_get(doc.as.array, JSON, 0);
+ JSON val_1 = *Vec_get(sub_array.as.array, JSON, 0);
+ t_assert(val_1.as.integer == 1);
+ JSON val_2 = *Vec_get(sub_array.as.array, JSON, 1);
+ Str str = val_2.as.string;
Str expected = S("abc");
t_assert(Str_equals(str, expected));
- t_assert_equal(Arena_get_used(perm), 555);
+ t_assert_equal(Arena_get_used(perm), 387);
return 0;
}
@@ -67,8 +67,8 @@ i32 test_json_string() {
JSON js = JSON_parse(&perm, "\"abc\"");
- t_assert(Str_equals(*js.string, S("abc")));
- t_assert_equal(Arena_get_used(perm), 75);
+ t_assert(Str_equals(js.as.string, S("abc")));
+ t_assert_equal(Arena_get_used(perm), 3);
return 0;
}
@@ -78,8 +78,8 @@ i32 test_json_empty_object() {
JSON doc = JSON_parse(&perm, "{}");
- t_assert_equal(doc.object->len, 0);
- t_assert_equal(Arena_get_used(perm), 368);
+ t_assert_equal(doc.as.object.len, 0);
+ t_assert_equal(Arena_get_used(perm), 224);
return 0;
}
@@ -89,11 +89,11 @@ i32 test_json_object() {
JSON doc = JSON_parse(&perm, "{\"key\": \"value\"}");
- t_assert_equal(doc.object->len, 1);
- t_assert(Str_equals(*Vec_get(&doc.object->keys, Str, 0), S("key")));
- JSON value = *JSONObject_get(doc.object, S("key"));
- t_assert(Str_equals(*value.string, S("value")));
- t_assert_equal(Arena_get_used(perm), 469);
+ t_assert_equal(doc.as.object.len, 1);
+ t_assert(Str_equals(*Vec_get(doc.as.object.keys, Str, 0), S("key")));
+ JSON value = *JSONObject_get(doc.as.object, S("key"));
+ t_assert(Str_equals(value.as.string, S("value")));
+ t_assert_equal(Arena_get_used(perm), 232);
return 0;
}
@@ -103,11 +103,11 @@ i32 test_json_boolean() {
JSON doc = JSON_parse(&perm, "{\"a\": true, \"b\": false}");
- JSON a = *JSONObject_get(doc.object, S("a"));
- t_assert(*a.boolean == 1);
- JSON b = *JSONObject_get(doc.object, S("b"));
- t_assert(*b.boolean == 0);
- t_assert_equal(Arena_get_used(perm), 540);
+ JSON a = *JSONObject_get(doc.as.object, S("a"));
+ t_assert(a.as.boolean == true);
+ JSON b = *JSONObject_get(doc.as.object, S("b"));
+ t_assert(b.as.boolean == false);
+ t_assert_equal(Arena_get_used(perm), 226);
return 0;
}
@@ -116,12 +116,12 @@ i32 test_json_float() {
Arena perm = Arena_new(128e3);
JSON doc = JSON_parse(&perm, "[1.2, 2.3]");
- t_assert_equal(doc.array->len, 2);
- JSON first = *Vec_get(doc.array, JSON, 0);
- t_assert_fequal(*first.floating, 1.2);
- JSON second = *Vec_get(doc.array, JSON, 1);
- t_assert_fequal(*second.floating, 2.3);
- t_assert_equal(Arena_get_used(perm), 332);
+ t_assert_equal(doc.as.array.len, 2);
+ JSON first = *Vec_get(doc.as.array, JSON, 0);
+ t_assert_fequal(first.as.floating, 1.2);
+ JSON second = *Vec_get(doc.as.array, JSON, 1);
+ t_assert_fequal(second.as.floating, 2.3);
+ t_assert_equal(Arena_get_used(perm), 192);
return 0;
}
@@ -130,10 +130,10 @@ i32 test_json_null() {
Arena perm = Arena_new(128e3);
JSON doc = JSON_parse(&perm, "[null]");
- t_assert_equal(doc.array->len, 1);
- JSON first = *Vec_get(doc.array, JSON, 0);
- t_assert(first.null != 0);
- t_assert_equal(Arena_get_used(perm), 268);
+ t_assert_equal(doc.as.array.len, 1);
+ JSON first = *Vec_get(doc.as.array, JSON, 0);
+ t_assert(first.type == JSON_NULL);
+ t_assert_equal(Arena_get_used(perm), 192);
return 0;
}
@@ -147,10 +147,11 @@ i32 test_json_multiline() {
" \"target_size_mb\": 1,\n"
" \"generator_version\": \"1.0\"\n"
"}");
- JSON target_size_mb = *JSONObject_get(doc.object, S("target_size_mb"));
- t_assert(*target_size_mb.integer == 1);
- JSON generated_at = *JSONObject_get(doc.object, S("generated_at"));
- t_assert(Str_equals(*generated_at.string, S("2025-07-22T10:36:30.974926")));
+ JSON target_size_mb = *JSONObject_get(doc.as.object, S("target_size_mb"));
+ t_assert(target_size_mb.as.integer == 1);
+ JSON generated_at = *JSONObject_get(doc.as.object, S("generated_at"));
+ t_assert(
+ Str_equals(generated_at.as.string, S("2025-07-22T10:36:30.974926")));
return 0;
}
@@ -160,9 +161,9 @@ i32 test_json_nested_object() {
JSON doc = JSON_parse(&perm, "{\"1\":{\"2\":{}}}");
- JSON lvl_1 = *JSONObject_get(doc.object, S("1"));
- t_assert(lvl_1.object != 0);
- JSON lvl_2 = *JSONObject_get(lvl_1.object, S("2"));
- t_assert(lvl_2.object != 0);
+ JSON lvl_1 = *JSONObject_get(doc.as.object, S("1"));
+ t_assert(lvl_1.type == JSON_OBJECT);
+ JSON lvl_2 = *JSONObject_get(lvl_1.as.object, S("2"));
+ t_assert(lvl_2.type == JSON_OBJECT);
return 0;
}
diff --git a/test_string.c b/test_string.c
index 7b37e0d..0d6dd71 100644
--- a/test_string.c
+++ b/test_string.c
@@ -10,10 +10,10 @@ i32 test_string_copy() {
Arena perm = Arena_new(128e3);
Str src = S("Hello");
- Str *cpy = Str_copy(&perm, src.data, src.len);
+ Str cpy = Str_copy(&perm, src.data, src.len);
- t_assert(Str_equals(src, *cpy));
- t_assert_equal(Arena_get_used(perm), 21);
+ t_assert(Str_equals(src, cpy));
+ t_assert_equal(Arena_get_used(perm), 5);
return 0;
}
diff --git a/test_vec.c b/test_vec.c
index 18cb880..180ba41 100644
--- a/test_vec.c
+++ b/test_vec.c
@@ -4,22 +4,22 @@
i32 test_int_vec() {
Arena perm = Arena_new(128e3);
- Vec *vec = Vec_new(&perm, i32, 2);
+ Vec vec = Vec_new(&perm, i32, 2);
i32 *tmp = new(&perm, i32, 1);
*tmp = 1;
- Vec_push(&perm, vec, tmp);
+ Vec_push(&perm, &vec, tmp);
*tmp = 2;
- Vec_push(&perm, vec, tmp);
+ Vec_push(&perm, &vec, tmp);
t_assert_equal(*Vec_get(vec, i32, 0), 1);
t_assert_equal(*Vec_get(vec, i32, 1), 2);
- t_assert_equal(vec->cap, 2);
+ t_assert_equal(vec.cap, 2);
*tmp = 3;
- Vec_push(&perm, vec, tmp);
+ Vec_push(&perm, &vec, tmp);
t_assert_equal(*Vec_get(vec, i32, 2), 3);
- t_assert_equal(vec->cap, 4);
+ t_assert_equal(vec.cap, 4);
return 0;
}
diff --git a/vec.c b/vec.c
index e91147e..3dfbf31 100644
--- a/vec.c
+++ b/vec.c
@@ -4,14 +4,14 @@
#include "types.h"
#include "vec.h"
-Vec *_Vec_new(Arena *a, size tsize, size cap, size align) {
+Vec _Vec_new(Arena *a, size tsize, size cap, size align) {
assert(cap > 0);
- Vec *v = new(a, Vec, 1);
- v->tsize = tsize;
- v->cap = cap;
- v->align = align;
- v->len = 0;
- v->data = alloc(a, cap, tsize, align);
+ Vec v = {0};
+ v.tsize = tsize;
+ v.cap = cap;
+ v.align = align;
+ v.len = 0;
+ v.data = alloc(a, cap, tsize, align);
return v;
}
@@ -20,9 +20,10 @@ void Vec_push(Arena *a, Vec *v, void *data) {
void *cpy = alloc(a, v->cap * 2, v->tsize, v->align);
memcpy(cpy, v->data, v->len * v->tsize);
v->cap *= 2;
+ v->data = cpy;
}
memcpy(v->data + v->len * v->tsize, data, v->tsize);
v->len++;
}
-void *_Vec_get(Vec *v, size pos) { return v->data + v->tsize * pos; }
+void *_Vec_get(Vec v, size pos) { return v.data + v.tsize * pos; }
diff --git a/vec.h b/vec.h
index 8a9a0e8..1d1999b 100644
--- a/vec.h
+++ b/vec.h
@@ -14,8 +14,8 @@ typedef struct {
size align;
} Vec;
#define Vec_new(a, T, cap) _Vec_new(a, sizeof(T), cap, _Alignof(T))
-Vec *_Vec_new(Arena *a, size tsize, size cap, size align);
+Vec _Vec_new(Arena *a, size tsize, size cap, size 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, size pos);
+void *_Vec_get(Vec v, size pos);
#endif