Implement allocation checking in the unit tests
This commit is contained in:
@@ -33,6 +33,7 @@ foreach(LESSON ${LESSONS})
|
|||||||
if(NOT LESSON_SOURCES)
|
if(NOT LESSON_SOURCES)
|
||||||
continue()
|
continue()
|
||||||
endif()
|
endif()
|
||||||
|
list(APPEND LESSON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/bootlib.c)
|
||||||
|
|
||||||
# Get last directory name of the path to use as exe
|
# Get last directory name of the path to use as exe
|
||||||
get_filename_component(EXE_NAME ${LESSON} NAME)
|
get_filename_component(EXE_NAME ${LESSON} NAME)
|
||||||
|
|||||||
+6
-3
@@ -13,11 +13,14 @@ The first the 3 chapters of the course can be done interactively on the website.
|
|||||||
[[./bootdev-c.png]]
|
[[./bootdev-c.png]]
|
||||||
|
|
||||||
If you're reading this with the intention of completing the exercises yourself,
|
If you're reading this with the intention of completing the exercises yourself,
|
||||||
just remove the directories from the =src= directory and recreate the directory
|
you can find each exercise is in its own directory inside of the =src= directory.
|
||||||
with the files from the exercise. Alternatively, just remove the file the
|
Remove all the files that are not called =main.c= and recreate them from the
|
||||||
exercise is asking you to modify as you go.
|
exercises on the boot.dev website as you go through them, so you won't get spoiled.
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
|
- In order to verify allocations in the unit tests, please use the wrapper
|
||||||
|
functions =boot_malloc=, =boot_calloc=, =boot_realloc= and =boot_free= from
|
||||||
|
=boot_lib.h= instead of the =stdlib.h= allocation functions
|
||||||
- In chapter 6 exercise 6, macOS malloc will almost never return a NULL pointer
|
- In chapter 6 exercise 6, macOS malloc will almost never return a NULL pointer
|
||||||
due to virtual memory overcommit, so you should check for
|
due to virtual memory overcommit, so you should check for
|
||||||
~size == 1024 * 1024 * 100)~ instead of ~array == NULL~
|
~size == 1024 * 1024 * 100)~ instead of ~array == NULL~
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
// #include "bootlib.h"
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ munit_case(RUN, test_int_has_refcount, {
|
|||||||
snek_object_t *obj = new_snek_integer(10);
|
snek_object_t *obj = new_snek_integer(10);
|
||||||
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_inc_refcount, {
|
munit_case(RUN, test_inc_refcount, {
|
||||||
@@ -19,7 +19,7 @@ munit_case(RUN, test_inc_refcount, {
|
|||||||
refcount_inc(obj);
|
refcount_inc(obj);
|
||||||
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_dec_refcount, {
|
munit_case(RUN, test_dec_refcount, {
|
||||||
@@ -31,10 +31,10 @@ munit_case(RUN, test_dec_refcount, {
|
|||||||
refcount_dec(obj);
|
refcount_dec(obj);
|
||||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
// assert(!boot_is_freed(obj));
|
assert(!boot_is_freed(obj));
|
||||||
|
|
||||||
// Object is still alive, so we will free manually.
|
// Object is still alive, so we will free manually.
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_refcount_free_is_called, {
|
munit_case(SUBMIT, test_refcount_free_is_called, {
|
||||||
@@ -47,8 +47,8 @@ munit_case(SUBMIT, test_refcount_free_is_called, {
|
|||||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
refcount_dec(obj);
|
refcount_dec(obj);
|
||||||
// assert(boot_is_freed(obj));
|
assert(boot_is_freed(obj));
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_allocated_string_is_freed, {
|
munit_case(SUBMIT, test_allocated_string_is_freed, {
|
||||||
@@ -62,8 +62,8 @@ munit_case(SUBMIT, test_allocated_string_is_freed, {
|
|||||||
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
||||||
|
|
||||||
refcount_dec(obj);
|
refcount_dec(obj);
|
||||||
// assert(boot_is_freed(obj));
|
assert(boot_is_freed(obj));
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
void refcount_dec(snek_object_t *obj) {
|
void refcount_dec(snek_object_t *obj) {
|
||||||
@@ -14,11 +15,11 @@ void refcount_dec(snek_object_t *obj) {
|
|||||||
void refcount_free(snek_object_t *obj) {
|
void refcount_free(snek_object_t *obj) {
|
||||||
if (obj == NULL) return;
|
if (obj == NULL) return;
|
||||||
if (obj->kind == INTEGER || obj->kind == FLOAT) {
|
if (obj->kind == INTEGER || obj->kind == FLOAT) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
}
|
}
|
||||||
if (obj->kind == STRING) {
|
if (obj->kind == STRING) {
|
||||||
free(obj->data.v_string);
|
boot_free(obj->data.v_string);
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ void refcount_inc(snek_object_t *obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *_new_snek_object() {
|
snek_object_t *_new_snek_object() {
|
||||||
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
snek_object_t *obj = boot_calloc(1, sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -50,9 +51,9 @@ snek_object_t *new_snek_array(size_t size) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||||
if (elements == NULL) {
|
if (elements == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,9 +110,9 @@ snek_object_t *new_snek_string(char *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(value);
|
int len = strlen(value);
|
||||||
char *dst = malloc(len + 1);
|
char *dst = boot_malloc(len + 1);
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-17
@@ -1,7 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
// #include "bootlib.h"
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
@@ -17,20 +17,20 @@ munit_case(RUN, test_vector3_refcounting, {
|
|||||||
|
|
||||||
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
||||||
refcount_dec(foo);
|
refcount_dec(foo);
|
||||||
// assert(!boot_is_freed(foo));
|
assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
refcount_dec(vec);
|
refcount_dec(vec);
|
||||||
// assert(boot_is_freed(foo));
|
assert(boot_is_freed(foo));
|
||||||
|
|
||||||
// These are still alive, they have the original reference still.
|
// These are still alive, they have the original reference still.
|
||||||
// assert(!boot_is_freed(bar));
|
assert(!boot_is_freed(bar));
|
||||||
// assert(!boot_is_freed(baz));
|
assert(!boot_is_freed(baz));
|
||||||
|
|
||||||
// Decrement the last reference to the objects, so they will be freed.
|
// Decrement the last reference to the objects, so they will be freed.
|
||||||
refcount_dec(bar);
|
refcount_dec(bar);
|
||||||
refcount_dec(baz);
|
refcount_dec(baz);
|
||||||
|
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_vector3_refcounting_same, {
|
munit_case(SUBMIT, test_vector3_refcounting_same, {
|
||||||
@@ -41,19 +41,19 @@ munit_case(SUBMIT, test_vector3_refcounting_same, {
|
|||||||
|
|
||||||
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
||||||
refcount_dec(foo);
|
refcount_dec(foo);
|
||||||
// assert(!boot_is_freed(foo));
|
assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
refcount_dec(vec);
|
refcount_dec(vec);
|
||||||
// assert(boot_is_freed(foo));
|
assert(boot_is_freed(foo));
|
||||||
// assert(boot_is_freed(vec));
|
assert(boot_is_freed(vec));
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_int_has_refcount, {
|
munit_case(RUN, test_int_has_refcount, {
|
||||||
snek_object_t *obj = new_snek_integer(10);
|
snek_object_t *obj = new_snek_integer(10);
|
||||||
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_inc_refcount, {
|
munit_case(RUN, test_inc_refcount, {
|
||||||
@@ -63,7 +63,7 @@ munit_case(RUN, test_inc_refcount, {
|
|||||||
refcount_inc(obj);
|
refcount_inc(obj);
|
||||||
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_dec_refcount, {
|
munit_case(RUN, test_dec_refcount, {
|
||||||
@@ -78,7 +78,7 @@ munit_case(RUN, test_dec_refcount, {
|
|||||||
// assert(!boot_is_freed(obj));
|
// assert(!boot_is_freed(obj));
|
||||||
|
|
||||||
// Object is still alive, so we will free manually.
|
// Object is still alive, so we will free manually.
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_refcount_free_is_called, {
|
munit_case(RUN, test_refcount_free_is_called, {
|
||||||
@@ -91,8 +91,8 @@ munit_case(RUN, test_refcount_free_is_called, {
|
|||||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
refcount_dec(obj);
|
refcount_dec(obj);
|
||||||
// assert(boot_is_freed(obj));
|
assert(boot_is_freed(obj));
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_allocated_string_is_freed, {
|
munit_case(RUN, test_allocated_string_is_freed, {
|
||||||
@@ -106,8 +106,8 @@ munit_case(RUN, test_allocated_string_is_freed, {
|
|||||||
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
||||||
|
|
||||||
refcount_dec(obj);
|
refcount_dec(obj);
|
||||||
// assert(boot_is_freed(obj));
|
assert(boot_is_freed(obj));
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
snek_object_t *_new_snek_object();
|
snek_object_t *_new_snek_object();
|
||||||
@@ -31,7 +32,7 @@ void refcount_free(snek_object_t *obj)
|
|||||||
case FLOAT:
|
case FLOAT:
|
||||||
break;
|
break;
|
||||||
case STRING:
|
case STRING:
|
||||||
free(obj->data.v_string);
|
boot_free(obj->data.v_string);
|
||||||
break;
|
break;
|
||||||
case VECTOR3: {
|
case VECTOR3: {
|
||||||
refcount_dec(obj->data.v_vector3.x);
|
refcount_dec(obj->data.v_vector3.x);
|
||||||
@@ -43,7 +44,7 @@ void refcount_free(snek_object_t *obj)
|
|||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't touch below this line
|
// don't touch below this line
|
||||||
@@ -69,7 +70,7 @@ void refcount_dec(snek_object_t *obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *_new_snek_object() {
|
snek_object_t *_new_snek_object() {
|
||||||
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
snek_object_t *obj = boot_calloc(1, sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -85,9 +86,9 @@ snek_object_t *new_snek_array(size_t size) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||||
if (elements == NULL) {
|
if (elements == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,9 +127,9 @@ snek_object_t *new_snek_string(char *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(value);
|
int len = strlen(value);
|
||||||
char *dst = malloc(len + 1);
|
char *dst = boot_malloc(len + 1);
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-19
@@ -1,7 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
// #include "bootlib.h"
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
@@ -12,11 +12,11 @@ munit_case(RUN, test_array_set, {
|
|||||||
snek_array_set(array, 0, foo);
|
snek_array_set(array, 0, foo);
|
||||||
assert_int(foo->refcount, ==, 2, "foo is now referenced by array");
|
assert_int(foo->refcount, ==, 2, "foo is now referenced by array");
|
||||||
|
|
||||||
// assert(!boot_is_freed(foo));
|
assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
refcount_dec(foo);
|
refcount_dec(foo);
|
||||||
refcount_dec(array);
|
refcount_dec(array);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_array_free, {
|
munit_case(SUBMIT, test_array_free, {
|
||||||
@@ -33,17 +33,17 @@ munit_case(SUBMIT, test_array_free, {
|
|||||||
|
|
||||||
// `foo` is stil referenced in the `array`, so it should not be freed.
|
// `foo` is stil referenced in the `array`, so it should not be freed.
|
||||||
refcount_dec(foo);
|
refcount_dec(foo);
|
||||||
// assert(!boot_is_freed(foo));
|
assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
// Overwrite index 0, which is `foo`, with `baz`.
|
// Overwrite index 0, which is `foo`, with `baz`.
|
||||||
// Now `foo` is not referenced by `array`, so it should be freed.
|
// Now `foo` is not referenced by `array`, so it should be freed.
|
||||||
snek_array_set(array, 0, baz);
|
snek_array_set(array, 0, baz);
|
||||||
// assert(boot_is_freed(foo));
|
assert(boot_is_freed(foo));
|
||||||
|
|
||||||
refcount_dec(bar);
|
refcount_dec(bar);
|
||||||
refcount_dec(baz);
|
refcount_dec(baz);
|
||||||
refcount_dec(array);
|
refcount_dec(array);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_vector3_refcounting, {
|
munit_case(RUN, test_vector3_refcounting, {
|
||||||
@@ -58,27 +58,27 @@ munit_case(RUN, test_vector3_refcounting, {
|
|||||||
|
|
||||||
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
||||||
refcount_dec(foo);
|
refcount_dec(foo);
|
||||||
// assert(!boot_is_freed(foo));
|
assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
refcount_dec(vec);
|
refcount_dec(vec);
|
||||||
// assert(boot_is_freed(foo));
|
assert(boot_is_freed(foo));
|
||||||
|
|
||||||
// These are still alive, they have the original reference still.
|
// These are still alive, they have the original reference still.
|
||||||
// assert(!boot_is_freed(bar));
|
assert(!boot_is_freed(bar));
|
||||||
// assert(!boot_is_freed(baz));
|
assert(!boot_is_freed(baz));
|
||||||
|
|
||||||
// Decrement the last reference to the objects, so they will be freed.
|
// Decrement the last reference to the objects, so they will be freed.
|
||||||
refcount_dec(bar);
|
refcount_dec(bar);
|
||||||
refcount_dec(baz);
|
refcount_dec(baz);
|
||||||
|
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_int_has_refcount, {
|
munit_case(RUN, test_int_has_refcount, {
|
||||||
snek_object_t *obj = new_snek_integer(10);
|
snek_object_t *obj = new_snek_integer(10);
|
||||||
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_inc_refcount, {
|
munit_case(RUN, test_inc_refcount, {
|
||||||
@@ -88,7 +88,7 @@ munit_case(RUN, test_inc_refcount, {
|
|||||||
refcount_inc(obj);
|
refcount_inc(obj);
|
||||||
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_dec_refcount, {
|
munit_case(RUN, test_dec_refcount, {
|
||||||
@@ -100,10 +100,10 @@ munit_case(RUN, test_dec_refcount, {
|
|||||||
refcount_dec(obj);
|
refcount_dec(obj);
|
||||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
// assert(!boot_is_freed(obj));
|
assert(!boot_is_freed(obj));
|
||||||
|
|
||||||
// Object is still alive, so we will free manually.
|
// Object is still alive, so we will free manually.
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_refcount_free_is_called, {
|
munit_case(RUN, test_refcount_free_is_called, {
|
||||||
@@ -116,8 +116,8 @@ munit_case(RUN, test_refcount_free_is_called, {
|
|||||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
refcount_dec(obj);
|
refcount_dec(obj);
|
||||||
// assert(boot_is_freed(obj));
|
assert(boot_is_freed(obj));
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_allocated_string_is_freed, {
|
munit_case(RUN, test_allocated_string_is_freed, {
|
||||||
@@ -131,8 +131,8 @@ munit_case(RUN, test_allocated_string_is_freed, {
|
|||||||
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
||||||
|
|
||||||
refcount_dec(obj);
|
refcount_dec(obj);
|
||||||
// assert(boot_is_freed(obj));
|
assert(boot_is_freed(obj));
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value)
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value)
|
||||||
@@ -31,7 +32,7 @@ void refcount_free(snek_object_t *obj)
|
|||||||
case FLOAT:
|
case FLOAT:
|
||||||
break;
|
break;
|
||||||
case STRING:
|
case STRING:
|
||||||
free(obj->data.v_string);
|
boot_free(obj->data.v_string);
|
||||||
break;
|
break;
|
||||||
case VECTOR3: {
|
case VECTOR3: {
|
||||||
snek_vector_t vec = obj->data.v_vector3;
|
snek_vector_t vec = obj->data.v_vector3;
|
||||||
@@ -44,13 +45,13 @@ void refcount_free(snek_object_t *obj)
|
|||||||
for (int i = 0; i < obj->data.v_array.size; i++) {
|
for (int i = 0; i < obj->data.v_array.size; i++) {
|
||||||
refcount_dec(obj->data.v_array.elements[i]);
|
refcount_dec(obj->data.v_array.elements[i]);
|
||||||
}
|
}
|
||||||
free(obj->data.v_array.elements);
|
boot_free(obj->data.v_array.elements);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't touch below this line
|
// don't touch below this line
|
||||||
@@ -92,7 +93,7 @@ void refcount_dec(snek_object_t *obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *_new_snek_object() {
|
snek_object_t *_new_snek_object() {
|
||||||
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
snek_object_t *obj = boot_calloc(1, sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -108,9 +109,9 @@ snek_object_t *new_snek_array(size_t size) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||||
if (elements == NULL) {
|
if (elements == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,9 +150,9 @@ snek_object_t *new_snek_string(char *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(value);
|
int len = strlen(value);
|
||||||
char *dst = malloc(len + 1);
|
char *dst = boot_malloc(len + 1);
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,4 +2,5 @@
|
|||||||
// Q: Why doesn't the snek_add function need to take care of
|
// Q: Why doesn't the snek_add function need to take care of
|
||||||
// garbage collecting the resulting object?
|
// garbage collecting the resulting object?
|
||||||
|
|
||||||
// A:
|
// A: Because we've coded the GC logic to happen automatically whenever a
|
||||||
|
// reference count hits 0
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
|
|
||||||
void swap(void *vp1, void *vp2, size_t size) {
|
void swap(void *vp1, void *vp2, size_t size) {
|
||||||
if (vp1 == vp2) return;
|
if (vp1 == vp2) return;
|
||||||
|
|
||||||
void *tmp = malloc(size);
|
void *tmp = boot_malloc(size);
|
||||||
if (tmp == NULL) return;
|
if (tmp == NULL) return;
|
||||||
memcpy(tmp, vp1, size);
|
memcpy(tmp, vp1, size);
|
||||||
memcpy(vp1, vp2, size);
|
memcpy(vp1, vp2, size);
|
||||||
memcpy(vp2, tmp, size);
|
memcpy(vp2, tmp, size);
|
||||||
free(tmp);
|
boot_free(tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #include "bootlib.h"
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
|
|
||||||
#include "exercise.h"
|
#include "exercise.h"
|
||||||
@@ -18,7 +18,7 @@ munit_case(RUN, test_generic_ints, {
|
|||||||
|
|
||||||
assert_int(i1, ==, 5678, "i1 should be i2's original value");
|
assert_int(i1, ==, 5678, "i1 should be i2's original value");
|
||||||
assert_int(i2, ==, 1234, "i2 should be i1's original value");
|
assert_int(i2, ==, 1234, "i2 should be i1's original value");
|
||||||
// assert_true(boot_all_freed());
|
assert_true(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_generic_strings, {
|
munit_case(RUN, test_generic_strings, {
|
||||||
@@ -28,7 +28,7 @@ munit_case(RUN, test_generic_strings, {
|
|||||||
swap(&s1, &s2, sizeof(char *));
|
swap(&s1, &s2, sizeof(char *));
|
||||||
assert_string_equal(s1, "adam", "s1 should be s2's original value");
|
assert_string_equal(s1, "adam", "s1 should be s2's original value");
|
||||||
assert_string_equal(s2, "dax", "s2 should be s1's original value");
|
assert_string_equal(s2, "dax", "s2 should be s1's original value");
|
||||||
// assert_true(boot_all_freed());
|
assert_true(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_generic_structs, {
|
munit_case(SUBMIT, test_generic_structs, {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #include "bootlib.h"
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekstack.h"
|
#include "snekstack.h"
|
||||||
|
|
||||||
@@ -8,10 +8,10 @@ munit_case(RUN, create_stack_small, {
|
|||||||
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
free(s->data);
|
boot_free(s->data);
|
||||||
free(s);
|
boot_free(s);
|
||||||
|
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, create_stack_large, {
|
munit_case(SUBMIT, create_stack_large, {
|
||||||
@@ -20,10 +20,10 @@ munit_case(SUBMIT, create_stack_large, {
|
|||||||
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
free(s->data);
|
boot_free(s->data);
|
||||||
free(s);
|
boot_free(s);
|
||||||
|
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekstack.h"
|
#include "snekstack.h"
|
||||||
|
|
||||||
my_stack_t *stack_new(size_t capacity)
|
my_stack_t *stack_new(size_t capacity)
|
||||||
{
|
{
|
||||||
my_stack_t *stack = (my_stack_t *)malloc(sizeof(my_stack_t));
|
my_stack_t *stack = (my_stack_t *)boot_malloc(sizeof(my_stack_t));
|
||||||
if (stack == NULL) return NULL;
|
if (stack == NULL) return NULL;
|
||||||
stack->count = 0;
|
stack->count = 0;
|
||||||
stack->capacity = capacity;
|
stack->capacity = capacity;
|
||||||
stack->data = malloc(sizeof(void*) * capacity);
|
stack->data = boot_malloc(sizeof(void*) * capacity);
|
||||||
if (stack->data == NULL) {
|
if (stack->data == NULL) {
|
||||||
free(stack);
|
boot_free(stack);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-11
@@ -1,4 +1,4 @@
|
|||||||
// #include "bootlib.h"
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekstack.h"
|
#include "snekstack.h"
|
||||||
|
|
||||||
@@ -9,11 +9,11 @@ munit_case(RUN, create_stack, {
|
|||||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
// Clean up our allocated data.
|
// Clean up our allocated data.
|
||||||
free(s->data);
|
boot_free(s->data);
|
||||||
free(s);
|
boot_free(s);
|
||||||
|
|
||||||
// Should be nothing left that is allocated.
|
// Should be nothing left that is allocated.
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, push_stack, {
|
munit_case(RUN, push_stack, {
|
||||||
@@ -34,11 +34,11 @@ munit_case(RUN, push_stack, {
|
|||||||
assert_ptr_equal(s->data[0], &a, "element inserted into stack");
|
assert_ptr_equal(s->data[0], &a, "element inserted into stack");
|
||||||
|
|
||||||
// Clean up our allocated data.
|
// Clean up our allocated data.
|
||||||
free(s->data);
|
boot_free(s->data);
|
||||||
free(s);
|
boot_free(s);
|
||||||
|
|
||||||
// Should be nothing left that is allocated.
|
// Should be nothing left that is allocated.
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, push_double_capacity, {
|
munit_case(SUBMIT, push_double_capacity, {
|
||||||
@@ -62,14 +62,14 @@ munit_case(SUBMIT, push_double_capacity, {
|
|||||||
assert_int(s->count, ==, 3, "3 elements in the stack");
|
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||||
|
|
||||||
// Should reallocate memory.
|
// Should reallocate memory.
|
||||||
// assert_int_equal(boot_realloc_count(), 1, "Must reallocate memory for stack");
|
assert_int_equal(boot_realloc_count(), 1, "Must reallocate memory for stack");
|
||||||
|
|
||||||
// Clean up our allocated data.
|
// Clean up our allocated data.
|
||||||
free(s->data);
|
boot_free(s->data);
|
||||||
free(s);
|
boot_free(s);
|
||||||
|
|
||||||
// Should be nothing left that is allocated.
|
// Should be nothing left that is allocated.
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekstack.h"
|
#include "snekstack.h"
|
||||||
|
|
||||||
void stack_push(my_stack_t *stack, void *obj) {
|
void stack_push(my_stack_t *stack, void *obj)
|
||||||
|
{
|
||||||
if (stack->count >= stack->capacity) {
|
if (stack->count >= stack->capacity) {
|
||||||
void **data = realloc(stack->data, sizeof(void *) * stack->capacity * 2);
|
void **data = boot_realloc(stack->data, sizeof(void *) * stack->capacity * 2);
|
||||||
if (data == NULL) return;
|
if (data == NULL) return;
|
||||||
stack->data = data;
|
stack->data = data;
|
||||||
stack->capacity *= 2;
|
stack->capacity *= 2;
|
||||||
@@ -21,16 +22,16 @@ void stack_push(my_stack_t *stack, void *obj) {
|
|||||||
// don't touch below this line
|
// don't touch below this line
|
||||||
|
|
||||||
my_stack_t *stack_new(size_t capacity) {
|
my_stack_t *stack_new(size_t capacity) {
|
||||||
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
my_stack_t *stack = boot_malloc(sizeof(my_stack_t));
|
||||||
if (stack == NULL) {
|
if (stack == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack->count = 0;
|
stack->count = 0;
|
||||||
stack->capacity = capacity;
|
stack->capacity = capacity;
|
||||||
stack->data = malloc(stack->capacity * sizeof(void *));
|
stack->data = boot_malloc(stack->capacity * sizeof(void *));
|
||||||
if (stack->data == NULL) {
|
if (stack->data == NULL) {
|
||||||
free(stack);
|
boot_free(stack);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-13
@@ -1,4 +1,4 @@
|
|||||||
// #include "bootlib.h"
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekstack.h"
|
#include "snekstack.h"
|
||||||
|
|
||||||
@@ -37,11 +37,11 @@ munit_case(RUN, pop_stack, {
|
|||||||
assert_null(popped, "No remaining elements");
|
assert_null(popped, "No remaining elements");
|
||||||
|
|
||||||
// Clean up our allocated data.
|
// Clean up our allocated data.
|
||||||
free(s->data);
|
boot_free(s->data);
|
||||||
free(s);
|
boot_free(s);
|
||||||
|
|
||||||
// Should be nothing left that is allocated.
|
// Should be nothing left that is allocated.
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, pop_stack_empty, {
|
munit_case(SUBMIT, pop_stack_empty, {
|
||||||
@@ -56,11 +56,11 @@ munit_case(SUBMIT, pop_stack_empty, {
|
|||||||
assert_null(popped, "Should return null when popping an empty stack");
|
assert_null(popped, "Should return null when popping an empty stack");
|
||||||
|
|
||||||
// Clean up our allocated data.
|
// Clean up our allocated data.
|
||||||
free(s->data);
|
boot_free(s->data);
|
||||||
free(s);
|
boot_free(s);
|
||||||
|
|
||||||
// Should be nothing left that is allocated.
|
// Should be nothing left that is allocated.
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, push_stack, {
|
munit_case(RUN, push_stack, {
|
||||||
@@ -84,11 +84,11 @@ munit_case(RUN, push_stack, {
|
|||||||
assert_int(s->count, ==, 3, "3 elements in the stack");
|
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||||
|
|
||||||
// Clean up our allocated data.
|
// Clean up our allocated data.
|
||||||
free(s->data);
|
boot_free(s->data);
|
||||||
free(s);
|
boot_free(s);
|
||||||
|
|
||||||
// Should be nothing left that is allocated.
|
// Should be nothing left that is allocated.
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, create_stack, {
|
munit_case(RUN, create_stack, {
|
||||||
@@ -98,11 +98,11 @@ munit_case(RUN, create_stack, {
|
|||||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
// Clean up our allocated data.
|
// Clean up our allocated data.
|
||||||
free(s->data);
|
boot_free(s->data);
|
||||||
free(s);
|
boot_free(s);
|
||||||
|
|
||||||
// Should be nothing left that is allocated.
|
// Should be nothing left that is allocated.
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekstack.h"
|
#include "snekstack.h"
|
||||||
|
|
||||||
void *stack_pop(my_stack_t *stack) {
|
void *stack_pop(my_stack_t *stack) {
|
||||||
@@ -15,7 +16,7 @@ void *stack_pop(my_stack_t *stack) {
|
|||||||
void stack_push(my_stack_t *stack, void *obj) {
|
void stack_push(my_stack_t *stack, void *obj) {
|
||||||
if (stack->count == stack->capacity) {
|
if (stack->count == stack->capacity) {
|
||||||
stack->capacity *= 2;
|
stack->capacity *= 2;
|
||||||
void **temp = realloc(stack->data, stack->capacity * sizeof(void *));
|
void **temp = boot_realloc(stack->data, stack->capacity * sizeof(void *));
|
||||||
if (temp == NULL) {
|
if (temp == NULL) {
|
||||||
stack->capacity /= 2;
|
stack->capacity /= 2;
|
||||||
|
|
||||||
@@ -29,16 +30,16 @@ void stack_push(my_stack_t *stack, void *obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my_stack_t *stack_new(size_t capacity) {
|
my_stack_t *stack_new(size_t capacity) {
|
||||||
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
my_stack_t *stack = boot_malloc(sizeof(my_stack_t));
|
||||||
if (stack == NULL) {
|
if (stack == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack->count = 0;
|
stack->count = 0;
|
||||||
stack->capacity = capacity;
|
stack->capacity = capacity;
|
||||||
stack->data = malloc(stack->capacity * sizeof(void *));
|
stack->data = boot_malloc(stack->capacity * sizeof(void *));
|
||||||
if (stack->data == NULL) {
|
if (stack->data == NULL) {
|
||||||
free(stack);
|
boot_free(stack);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #include "bootlib.h"
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekstack.h"
|
#include "snekstack.h"
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ munit_case(RUN, pop_stack, {
|
|||||||
assert_null(popped, "No remaining elements");
|
assert_null(popped, "No remaining elements");
|
||||||
|
|
||||||
stack_free(s);
|
stack_free(s);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, push_stack, {
|
munit_case(RUN, push_stack, {
|
||||||
@@ -61,7 +61,7 @@ munit_case(RUN, push_stack, {
|
|||||||
assert_int(s->count, ==, 3, "3 elements in the stack");
|
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||||
|
|
||||||
stack_free(s);
|
stack_free(s);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, create_stack, {
|
munit_case(RUN, create_stack, {
|
||||||
@@ -71,7 +71,7 @@ munit_case(RUN, create_stack, {
|
|||||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
stack_free(s);
|
stack_free(s);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -2,17 +2,18 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekstack.h"
|
#include "snekstack.h"
|
||||||
|
|
||||||
void stack_free(my_stack_t *stack) {
|
void stack_free(my_stack_t *stack) {
|
||||||
if (stack == NULL) return;
|
if (stack == NULL) return;
|
||||||
|
|
||||||
if (stack->data != NULL) {
|
if (stack->data != NULL) {
|
||||||
free(stack->data);
|
boot_free(stack->data);
|
||||||
stack->data = NULL;
|
stack->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(stack);
|
boot_free(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't touch below this line
|
// don't touch below this line
|
||||||
@@ -29,7 +30,7 @@ void *stack_pop(my_stack_t *stack) {
|
|||||||
void stack_push(my_stack_t *stack, void *obj) {
|
void stack_push(my_stack_t *stack, void *obj) {
|
||||||
if (stack->count == stack->capacity) {
|
if (stack->count == stack->capacity) {
|
||||||
stack->capacity *= 2;
|
stack->capacity *= 2;
|
||||||
void **temp = realloc(stack->data, stack->capacity * sizeof(void *));
|
void **temp = boot_realloc(stack->data, stack->capacity * sizeof(void *));
|
||||||
if (temp == NULL) {
|
if (temp == NULL) {
|
||||||
stack->capacity /= 2;
|
stack->capacity /= 2;
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -42,16 +43,16 @@ void stack_push(my_stack_t *stack, void *obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my_stack_t *stack_new(size_t capacity) {
|
my_stack_t *stack_new(size_t capacity) {
|
||||||
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
my_stack_t *stack = boot_malloc(sizeof(my_stack_t));
|
||||||
if (stack == NULL) {
|
if (stack == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack->count = 0;
|
stack->count = 0;
|
||||||
stack->capacity = capacity;
|
stack->capacity = capacity;
|
||||||
stack->data = malloc(stack->capacity * sizeof(void *));
|
stack->data = boot_malloc(stack->capacity * sizeof(void *));
|
||||||
if (stack->data == NULL) {
|
if (stack->data == NULL) {
|
||||||
free(stack);
|
boot_free(stack);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
@@ -7,8 +8,8 @@ munit_case(RUN, test_positive, {
|
|||||||
snek_object_t *obj = new_snek_float(42);
|
snek_object_t *obj = new_snek_float(42);
|
||||||
assert_float(obj->data.v_float, ==, 42, "Must accept positive values");
|
assert_float(obj->data.v_float, ==, 42, "Must accept positive values");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_zero, {
|
munit_case(SUBMIT, test_zero, {
|
||||||
@@ -17,8 +18,8 @@ munit_case(SUBMIT, test_zero, {
|
|||||||
assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT");
|
assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT");
|
||||||
assert_float(obj->data.v_float, ==, 0.0, "Must accept 0.0");
|
assert_float(obj->data.v_float, ==, 0.0, "Must accept 0.0");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_negative, {
|
munit_case(SUBMIT, test_negative, {
|
||||||
@@ -27,8 +28,8 @@ munit_case(SUBMIT, test_negative, {
|
|||||||
assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT");
|
assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT");
|
||||||
assert_float(obj->data.v_float, ==, -5.0, "Must accept negative numbers");
|
assert_float(obj->data.v_float, ==, -5.0, "Must accept negative numbers");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
snek_object_t *new_snek_float(float value) {
|
snek_object_t *new_snek_float(float value) {
|
||||||
snek_object_t *obj = (snek_object_t *)malloc(sizeof(snek_object_t));
|
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) return NULL;
|
if (obj == NULL) return NULL;
|
||||||
obj->kind = FLOAT;
|
obj->kind = FLOAT;
|
||||||
obj->data.v_float = value;
|
obj->data.v_float = value;
|
||||||
@@ -13,7 +14,7 @@ snek_object_t *new_snek_float(float value) {
|
|||||||
// don't touch below this line
|
// don't touch below this line
|
||||||
|
|
||||||
snek_object_t *new_snek_integer(int value) {
|
snek_object_t *new_snek_integer(int value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
@@ -21,12 +23,14 @@ munit_case(RUN, test_str_copied, {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Should allocate memory for the string with null terminator.
|
// Should allocate memory for the string with null terminator.
|
||||||
// assert_int_equal(boot_alloc_size(), 22, "Must allocate memory for string");
|
bool is_32_bit = sizeof(void *) == 4;
|
||||||
|
int allocated = 14 + (is_32_bit ? 8 : 16); // pointers are larger on x64
|
||||||
|
assert_int_equal(boot_alloc_size(), allocated, "Must allocate memory for string");
|
||||||
|
|
||||||
// Free the string, and then free the object.
|
// Free the string, and then free the object.
|
||||||
free(obj->data.v_string);
|
boot_free(obj->data.v_string);
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -2,16 +2,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
snek_object_t *new_snek_string(char *value) {
|
snek_object_t *new_snek_string(char *value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) return NULL;
|
if (obj == NULL) return NULL;
|
||||||
|
|
||||||
size_t size = strlen(value);
|
size_t size = strlen(value);
|
||||||
char *str = (char *)malloc(sizeof(char) * size + 1);
|
char *str = (char *)boot_malloc(sizeof(char) * size + 1);
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ snek_object_t *new_snek_string(char *value) {
|
|||||||
// don't touch below this line
|
// don't touch below this line
|
||||||
|
|
||||||
snek_object_t *new_snek_integer(int value) {
|
snek_object_t *new_snek_integer(int value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -35,7 +36,7 @@ snek_object_t *new_snek_integer(int value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_float(float value) {
|
snek_object_t *new_snek_float(float value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-9
@@ -1,5 +1,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ munit_case(RUN, test_returns_null, {
|
|||||||
|
|
||||||
assert_null(vec, "Should return null when input is null");
|
assert_null(vec, "Should return null when input is null");
|
||||||
|
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -31,11 +32,11 @@ munit_case(RUN, test_vec_multiple_objects, {
|
|||||||
assert_int(vec->data.v_vector3.z->data.v_int, ==, 3, "should have correct z");
|
assert_int(vec->data.v_vector3.z->data.v_int, ==, 3, "should have correct z");
|
||||||
|
|
||||||
// Free all of our objects.
|
// Free all of our objects.
|
||||||
free(x);
|
boot_free(x);
|
||||||
free(y);
|
boot_free(y);
|
||||||
free(z);
|
boot_free(z);
|
||||||
free(vec);
|
boot_free(vec);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_vec_same_object, {
|
munit_case(SUBMIT, test_vec_same_object, {
|
||||||
@@ -62,9 +63,9 @@ munit_case(SUBMIT, test_vec_same_object, {
|
|||||||
assert_int(vec->data.v_vector3.z->data.v_int, ==, 2, "should have correct z");
|
assert_int(vec->data.v_vector3.z->data.v_int, ==, 2, "should have correct z");
|
||||||
|
|
||||||
// Free all of our objects.
|
// Free all of our objects.
|
||||||
free(i);
|
boot_free(i);
|
||||||
free(vec);
|
boot_free(vec);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -1,33 +1,25 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z)
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z)
|
||||||
{
|
{
|
||||||
if (x == NULL || y == NULL || z == NULL) return NULL;
|
if (x == NULL || y == NULL || z == NULL) return NULL;
|
||||||
|
|
||||||
snek_object_t *obj = (snek_object_t *)malloc(sizeof(snek_object_t));
|
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) return NULL;
|
if (obj == NULL) return NULL;
|
||||||
|
|
||||||
snek_vector_t *vec = (snek_vector_t *)malloc(sizeof(snek_vector_t));
|
|
||||||
if (vec == NULL) {
|
|
||||||
free(obj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec->x = x;
|
|
||||||
vec->y = y;
|
|
||||||
vec->z = z;
|
|
||||||
obj->kind = VECTOR3;
|
obj->kind = VECTOR3;
|
||||||
obj->data.v_vector3 = *vec;
|
obj->data.v_vector3 = (snek_vector_t){ .x = x, .y = y, .z = z };
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't touch below this line
|
// don't touch below this line
|
||||||
|
|
||||||
snek_object_t *new_snek_integer(int value) {
|
snek_object_t *new_snek_integer(int value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -38,7 +30,7 @@ snek_object_t *new_snek_integer(int value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_float(float value) {
|
snek_object_t *new_snek_float(float value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -49,15 +41,15 @@ snek_object_t *new_snek_float(float value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_string(char *value) {
|
snek_object_t *new_snek_string(char *value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(value);
|
int len = strlen(value);
|
||||||
char *dst = malloc(len + 1);
|
char *dst = boot_malloc(len + 1);
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
@@ -9,9 +10,9 @@ munit_case(RUN, test_create_empty_array, {
|
|||||||
assert_int(obj->kind, ==, ARRAY, "Must set type to ARRAY");
|
assert_int(obj->kind, ==, ARRAY, "Must set type to ARRAY");
|
||||||
assert_int(obj->data.v_array.size, ==, 2, "Must set size to 2");
|
assert_int(obj->data.v_array.size, ==, 2, "Must set size to 2");
|
||||||
|
|
||||||
free(obj->data.v_array.elements);
|
boot_free(obj->data.v_array.elements);
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_used_calloc, {
|
munit_case(SUBMIT, test_used_calloc, {
|
||||||
@@ -20,9 +21,9 @@ munit_case(SUBMIT, test_used_calloc, {
|
|||||||
assert_ptr_null(obj->data.v_array.elements[0], "Should use calloc");
|
assert_ptr_null(obj->data.v_array.elements[0], "Should use calloc");
|
||||||
assert_ptr_null(obj->data.v_array.elements[1], "Should use calloc");
|
assert_ptr_null(obj->data.v_array.elements[1], "Should use calloc");
|
||||||
|
|
||||||
free(obj->data.v_array.elements);
|
boot_free(obj->data.v_array.elements);
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
snek_object_t *new_snek_array(size_t size) {
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
snek_object_t *obj = (snek_object_t *)malloc(sizeof(snek_object_t));
|
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) return NULL;
|
if (obj == NULL) return NULL;
|
||||||
|
|
||||||
snek_object_t **arr = (snek_object_t **)calloc(size, sizeof(snek_object_t *));
|
snek_object_t **arr = (snek_object_t **)boot_calloc(size, sizeof(snek_object_t *));
|
||||||
if (arr == NULL) {
|
if (arr == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ snek_object_t *new_snek_vector3(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -39,7 +40,7 @@ snek_object_t *new_snek_vector3(
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_integer(int value) {
|
snek_object_t *new_snek_integer(int value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -50,7 +51,7 @@ snek_object_t *new_snek_integer(int value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_float(float value) {
|
snek_object_t *new_snek_float(float value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -61,15 +62,15 @@ snek_object_t *new_snek_float(float value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_string(char *value) {
|
snek_object_t *new_snek_string(char *value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(value);
|
int len = strlen(value);
|
||||||
char *dst = malloc(len + 1);
|
char *dst = boot_malloc(len + 1);
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-16
@@ -1,5 +1,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
@@ -25,12 +26,12 @@ munit_case(RUN, test_array, {
|
|||||||
assert_int(retrieved_second->kind, ==, INTEGER, "Should be a integer");
|
assert_int(retrieved_second->kind, ==, INTEGER, "Should be a integer");
|
||||||
assert_ptr(second, ==, retrieved_second, "Should be the same object");
|
assert_ptr(second, ==, retrieved_second, "Should be the same object");
|
||||||
|
|
||||||
free(first->data.v_string);
|
boot_free(first->data.v_string);
|
||||||
free(first);
|
boot_free(first);
|
||||||
free(second);
|
boot_free(second);
|
||||||
free(obj->data.v_array.elements);
|
boot_free(obj->data.v_array.elements);
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_set_outside_bounds, {
|
munit_case(RUN, test_set_outside_bounds, {
|
||||||
@@ -46,11 +47,11 @@ munit_case(RUN, test_set_outside_bounds, {
|
|||||||
assert_false(snek_array_set(obj, 100, outside));
|
assert_false(snek_array_set(obj, 100, outside));
|
||||||
|
|
||||||
// Free memory
|
// Free memory
|
||||||
free(outside->data.v_string);
|
boot_free(outside->data.v_string);
|
||||||
free(outside);
|
boot_free(outside);
|
||||||
free(obj->data.v_array.elements);
|
boot_free(obj->data.v_array.elements);
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_get_outside_bounds, {
|
munit_case(SUBMIT, test_get_outside_bounds, {
|
||||||
@@ -62,11 +63,11 @@ munit_case(SUBMIT, test_get_outside_bounds, {
|
|||||||
// Outside of bound
|
// Outside of bound
|
||||||
assert_null(snek_array_get(obj, 1), "Should not access outside the array");
|
assert_null(snek_array_get(obj, 1), "Should not access outside the array");
|
||||||
|
|
||||||
free(first->data.v_string);
|
boot_free(first->data.v_string);
|
||||||
free(first);
|
boot_free(first);
|
||||||
free(obj->data.v_array.elements);
|
boot_free(obj->data.v_array.elements);
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value) {
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value) {
|
||||||
@@ -24,14 +25,14 @@ snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index) {
|
|||||||
// don't touch below this line
|
// don't touch below this line
|
||||||
|
|
||||||
snek_object_t *new_snek_array(size_t size) {
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||||
if (elements == NULL) {
|
if (elements == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ snek_object_t *new_snek_vector3(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -59,7 +60,7 @@ snek_object_t *new_snek_vector3(
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_integer(int value) {
|
snek_object_t *new_snek_integer(int value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -70,7 +71,7 @@ snek_object_t *new_snek_integer(int value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_float(float value) {
|
snek_object_t *new_snek_float(float value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -81,15 +82,15 @@ snek_object_t *new_snek_float(float value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_string(char *value) {
|
snek_object_t *new_snek_string(char *value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(value);
|
int len = strlen(value);
|
||||||
char *dst = malloc(len + 1);
|
char *dst = boot_malloc(len + 1);
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-16
@@ -1,3 +1,4 @@
|
|||||||
|
#include "bootlib.h"
|
||||||
#include "munit.h"
|
#include "munit.h"
|
||||||
#include "snekobject.h"
|
#include "snekobject.h"
|
||||||
|
|
||||||
@@ -5,16 +6,16 @@ munit_case(RUN, test_integer, {
|
|||||||
snek_object_t *obj = new_snek_integer(42);
|
snek_object_t *obj = new_snek_integer(42);
|
||||||
assert_int(snek_length(obj), ==, 1, "Integers are length 1");
|
assert_int(snek_length(obj), ==, 1, "Integers are length 1");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_float, {
|
munit_case(RUN, test_float, {
|
||||||
snek_object_t *obj = new_snek_float(3.14);
|
snek_object_t *obj = new_snek_float(3.14);
|
||||||
assert_int(snek_length(obj), ==, 1, "Floats are length 1");
|
assert_int(snek_length(obj), ==, 1, "Floats are length 1");
|
||||||
|
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(RUN, test_string, {
|
munit_case(RUN, test_string, {
|
||||||
@@ -26,11 +27,11 @@ munit_case(RUN, test_string, {
|
|||||||
snek_length(longer), ==, strlen("hello, world"), "Should use strlen"
|
snek_length(longer), ==, strlen("hello, world"), "Should use strlen"
|
||||||
);
|
);
|
||||||
|
|
||||||
free(shorter->data.v_string);
|
boot_free(shorter->data.v_string);
|
||||||
free(shorter);
|
boot_free(shorter);
|
||||||
free(longer->data.v_string);
|
boot_free(longer->data.v_string);
|
||||||
free(longer);
|
boot_free(longer);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_vector3, {
|
munit_case(SUBMIT, test_vector3, {
|
||||||
@@ -38,9 +39,9 @@ munit_case(SUBMIT, test_vector3, {
|
|||||||
snek_object_t *vec = new_snek_vector3(i, i, i);
|
snek_object_t *vec = new_snek_vector3(i, i, i);
|
||||||
assert_int(snek_length(vec), ==, 3, "Vec3 always has length 3");
|
assert_int(snek_length(vec), ==, 3, "Vec3 always has length 3");
|
||||||
|
|
||||||
free(i);
|
boot_free(i);
|
||||||
free(vec);
|
boot_free(vec);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
munit_case(SUBMIT, test_array, {
|
munit_case(SUBMIT, test_array, {
|
||||||
@@ -52,10 +53,10 @@ munit_case(SUBMIT, test_array, {
|
|||||||
|
|
||||||
assert_int(snek_length(arr), ==, 4, "Length of array should be its size");
|
assert_int(snek_length(arr), ==, 4, "Length of array should be its size");
|
||||||
|
|
||||||
free(i);
|
boot_free(i);
|
||||||
free(arr->data.v_array.elements);
|
boot_free(arr->data.v_array.elements);
|
||||||
free(arr);
|
boot_free(arr);
|
||||||
// assert(boot_all_freed());
|
assert(boot_all_freed());
|
||||||
});
|
});
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "bootlib.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -15,14 +16,14 @@ int snek_length(snek_object_t *obj) {
|
|||||||
// don't touch below this line
|
// don't touch below this line
|
||||||
|
|
||||||
snek_object_t *new_snek_array(size_t size) {
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||||
if (elements == NULL) {
|
if (elements == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ snek_object_t *new_snek_vector3(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ snek_object_t *new_snek_vector3(
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_integer(int value) {
|
snek_object_t *new_snek_integer(int value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -96,7 +97,7 @@ snek_object_t *new_snek_integer(int value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_float(float value) {
|
snek_object_t *new_snek_float(float value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -107,15 +108,15 @@ snek_object_t *new_snek_float(float value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snek_object_t *new_snek_string(char *value) {
|
snek_object_t *new_snek_string(char *value) {
|
||||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(value);
|
int len = strlen(value);
|
||||||
char *dst = malloc(len + 1);
|
char *dst = boot_malloc(len + 1);
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
free(obj);
|
boot_free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+127
@@ -0,0 +1,127 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
|
|
||||||
|
typedef struct Allocation {
|
||||||
|
void* ptr;
|
||||||
|
size_t size;
|
||||||
|
bool freed;
|
||||||
|
struct Allocation *next;
|
||||||
|
} Allocation;
|
||||||
|
|
||||||
|
static Allocation *allocations = NULL; // backwards linked list
|
||||||
|
static int allocated_count = 0;
|
||||||
|
static int reallocated_count = 0;
|
||||||
|
static int total_size = 0;
|
||||||
|
|
||||||
|
void *create_allocation(void *allocated, size_t size);
|
||||||
|
Allocation *find_allocation(void *ptr);
|
||||||
|
|
||||||
|
void *boot_malloc(size_t size)
|
||||||
|
{
|
||||||
|
void *allocated = malloc(size);
|
||||||
|
if (allocated == NULL) return NULL;
|
||||||
|
|
||||||
|
return create_allocation(allocated, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *boot_calloc (size_t num, size_t size)
|
||||||
|
{
|
||||||
|
void *allocated = calloc(num, size);
|
||||||
|
if (allocated == NULL) return NULL;
|
||||||
|
|
||||||
|
return create_allocation(allocated, num * size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *boot_realloc(void* ptr, size_t size)
|
||||||
|
{
|
||||||
|
if (ptr == NULL) return NULL;
|
||||||
|
|
||||||
|
void *allocated = realloc(ptr, size);
|
||||||
|
if (allocated == NULL) return NULL;
|
||||||
|
|
||||||
|
reallocated_count++;
|
||||||
|
|
||||||
|
Allocation *allocation = find_allocation(ptr);
|
||||||
|
if (allocated == ptr) { // realloc resized the existing ptr's memory block
|
||||||
|
allocation->size = size;
|
||||||
|
total_size += size - allocation->size;
|
||||||
|
return allocated;
|
||||||
|
}
|
||||||
|
allocation->freed = true;
|
||||||
|
allocated_count--;
|
||||||
|
total_size -= allocation->size;
|
||||||
|
|
||||||
|
return create_allocation(allocated, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void boot_free (void *ptr)
|
||||||
|
{
|
||||||
|
if (ptr == NULL) return;
|
||||||
|
|
||||||
|
free(ptr);
|
||||||
|
|
||||||
|
Allocation *allocation = find_allocation(ptr);
|
||||||
|
allocation->freed = true;
|
||||||
|
allocated_count--;
|
||||||
|
total_size -= allocation->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
bool boot_all_freed()
|
||||||
|
{
|
||||||
|
return allocated_count == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool boot_is_freed(void *ptr)
|
||||||
|
{
|
||||||
|
return find_allocation(ptr)->freed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int boot_realloc_count()
|
||||||
|
{
|
||||||
|
return reallocated_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int boot_alloc_size()
|
||||||
|
{
|
||||||
|
return total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void *create_allocation(void *allocated, size_t size)
|
||||||
|
{
|
||||||
|
if (allocated == NULL) return NULL;
|
||||||
|
|
||||||
|
total_size += size;
|
||||||
|
|
||||||
|
Allocation *allocation = (Allocation *)malloc(sizeof(Allocation));
|
||||||
|
if (allocation == NULL) return NULL;
|
||||||
|
allocation->ptr = allocated;
|
||||||
|
allocation->size = size;
|
||||||
|
allocation->freed = false;
|
||||||
|
allocation->next = allocations;
|
||||||
|
allocations = allocation;
|
||||||
|
|
||||||
|
allocated_count++;
|
||||||
|
|
||||||
|
return allocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
Allocation *find_allocation(void *ptr)
|
||||||
|
{
|
||||||
|
if (allocations == NULL) return NULL;
|
||||||
|
|
||||||
|
Allocation *current = allocations;
|
||||||
|
while (true) {
|
||||||
|
if (current == NULL) return NULL;
|
||||||
|
if (current->ptr == ptr) return current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void *boot_malloc(size_t size);
|
||||||
|
void *boot_calloc (size_t num, size_t size);
|
||||||
|
void *boot_realloc(void* ptr, size_t size);
|
||||||
|
void boot_free (void *ptr);
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
bool boot_all_freed();
|
||||||
|
bool boot_is_freed(void *ptr);
|
||||||
|
int boot_realloc_count();
|
||||||
|
int boot_alloc_size();
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#define MUNIT_ENABLE_ASSERT_ALIASES
|
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||||
#include "../vendor/munit/munit.h"
|
#include "../vendor/munit/munit.h"
|
||||||
|
|
||||||
@@ -40,6 +42,9 @@
|
|||||||
#define assert_int(A, OP, B, MSG) \
|
#define assert_int(A, OP, B, MSG) \
|
||||||
munit_assert_int(A, OP, B, MSG);
|
munit_assert_int(A, OP, B, MSG);
|
||||||
|
|
||||||
|
#define assert_int_equal(A, B, MSG) \
|
||||||
|
munit_assert_int(A, ==, B, MSG);
|
||||||
|
|
||||||
#undef assert_uint
|
#undef assert_uint
|
||||||
#define assert_uint(A, OP, B, MSG) \
|
#define assert_uint(A, OP, B, MSG) \
|
||||||
munit_assert_uint(A, OP, B);
|
munit_assert_uint(A, OP, B);
|
||||||
|
|||||||
Reference in New Issue
Block a user