Add more exercises
This commit is contained in:
+207
@@ -0,0 +1,207 @@
|
|||||||
|
#+TITLE: Learn Memory Management in C
|
||||||
|
#+AUTHOR: Riyyi
|
||||||
|
#+LANGUAGE: en
|
||||||
|
#+OPTIONS: toc:nil
|
||||||
|
|
||||||
|
Completed course from
|
||||||
|
[[https://www.boot.dev/courses/learn-memory-management-c][boot.dev]].
|
||||||
|
|
||||||
|
The exercises from the course have been worked out in this repo.
|
||||||
|
This is my way of having the "certificate" for free.
|
||||||
|
|
||||||
|
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
|
||||||
|
with the files from the exercise. Alternatively, just remove the file the
|
||||||
|
exercise is asking you to modify as you go.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
- In chapter 6 exercise 6, macOS malloc will almost never return a NULL pointer
|
||||||
|
due to virtual memory overcommit, so you should check for
|
||||||
|
=size \=\= 1024 * 1024 * 100)= instead of =array \=\= NULL=
|
||||||
|
- In chapter 8, I renamed =stack_t= to =my_stack_t= due to =std= naming conflict
|
||||||
|
on macOS
|
||||||
|
|
||||||
|
** Build instructions
|
||||||
|
|
||||||
|
Compiling and running all the tests can be done with the following commands:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh
|
||||||
|
$ mkdir build
|
||||||
|
$ cd build
|
||||||
|
$ cmake ..
|
||||||
|
$ make run
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Output
|
||||||
|
|
||||||
|
The first the 3 chapters of the course can be done interactively on the website.
|
||||||
|
|
||||||
|
[[./bootdev-c.png]]
|
||||||
|
|
||||||
|
Successful output of all the tests:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh
|
||||||
|
$ make run 12:25PM
|
||||||
|
[ 3%] Built target munit
|
||||||
|
[ 8%] Built target 8-6-multiple-types
|
||||||
|
[ 11%] Built target 4-1-enums
|
||||||
|
[ 14%] Built target 4-2-non-default-values
|
||||||
|
[ 17%] Built target 4-3-switch-case
|
||||||
|
[ 20%] Built target 4-4-sizeof-enum
|
||||||
|
[ 24%] Built target 5-1-union
|
||||||
|
[ 26%] Built target 5-2-memory-layout
|
||||||
|
[ 29%] Built target 5-3-5-4-union-size
|
||||||
|
[ 32%] Built target 5-5-helper-fields
|
||||||
|
[ 34%] Built target 6-1-the-stack
|
||||||
|
[ 37%] Built target 6-2-why-a-stack
|
||||||
|
[ 39%] Built target 6-3-stack-overflow
|
||||||
|
[ 42%] Built target 6-4-pointers-to-the-stack
|
||||||
|
[ 46%] Built target 6-5-the-heap
|
||||||
|
[ 50%] Built target 6-6-malloc
|
||||||
|
[ 53%] Built target 6-7-free
|
||||||
|
[ 56%] Built target 6-8-big-endian-little-endian
|
||||||
|
[ 60%] Built target 7-1-pointer-pointers
|
||||||
|
[ 64%] Built target 7-2-array-of-pointers
|
||||||
|
[ 67%] Built target 7-3-void-pointers
|
||||||
|
[ 71%] Built target 7-4-swapping-integers
|
||||||
|
[ 75%] Built target 7-5-swapping-strings
|
||||||
|
[ 79%] Built target 7-6-generic-swap
|
||||||
|
[ 83%] Built target 8-1-low-level-stack
|
||||||
|
[ 87%] Built target 8-2-stack-push
|
||||||
|
[ 91%] Built target 8-3-stack-pop
|
||||||
|
[ 94%] Built target 8-4-stack-free
|
||||||
|
[100%] Built target 8-5-dangerous-push
|
||||||
|
Running test suite with seed 0x039ca6b1...
|
||||||
|
colors/are_defined [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
colors/are_defined_correctly [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xbf68f4fa...
|
||||||
|
colors/defined [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
colors/defined_vscode [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x40b17fef...
|
||||||
|
http/switch_enum [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
http/switch_enum_default [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
The size of BigNumbers is 8 bytes
|
||||||
|
The size of HttpErrorCode is 4 bytes
|
||||||
|
Running test suite with seed 0xde548fa9...
|
||||||
|
format/integer [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
format/string [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
format/integer_nvim [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
format/string_nvim [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
value (set): -420
|
||||||
|
err (unset): 4294966876
|
||||||
|
value (unset): -1
|
||||||
|
err (set): 4294967295
|
||||||
|
Running test suite with seed 0xa7197940...
|
||||||
|
PacketHeader/test_packet_header_size [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
PacketHeader/test_tcp_header_fields [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
PacketHeader/test_field_raw_size [ OK ] [ 0.00000000 / 0.00000100 CPU ]
|
||||||
|
PacketHeader/test_field_to_raw_consistency[ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
--------------------------------- Stack pointer offset: 0 bytes
|
||||||
|
---------------------------------
|
||||||
|
Dark mode?
|
||||||
|
---------------------------------
|
||||||
|
Stack pointer offset: 0 bytes
|
||||||
|
---------------------------------
|
||||||
|
More like...
|
||||||
|
|
||||||
|
---------------------------------
|
||||||
|
Stack pointer offset: 0 bytes
|
||||||
|
---------------------------------
|
||||||
|
dark roast.
|
||||||
|
Running test suite with seed 0x7dcfad3b...
|
||||||
|
/example/compare [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
|
/example/rand [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
|
/example/parameters
|
||||||
|
foo=one, bar=red [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
foo=one, bar=green [ OK ] [ 0.00000200 / 0.00000300 CPU ]
|
||||||
|
foo=one, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
foo=two, bar=red [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
foo=two, bar=green [ OK ] [ 0.00000200 / 0.00000200 CPU ] foo=two, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
foo=three, bar=red [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
foo=three, bar=green [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
foo=three, bar=blue [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
11 of 11 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Size of pool: 10240
|
||||||
|
Initial string: snek
|
||||||
|
c1: 10, 20
|
||||||
|
c2: 30, 40
|
||||||
|
c3: 50, 60 Running test suite with seed 0x53c7e720...
|
||||||
|
get_full_greeting/test_basic_greeting[ OK ] [ 0.00000200 / 0.00000300 CPU ]
|
||||||
|
get_full_greeting/test_short_buffer [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xee42ee28...
|
||||||
|
allocate_scalar_array/test_allocate_scalar_array_size[ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
allocate_scalar_array/test_allocate_scalar_array_values[ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
allocate_scalar_array/test_allocate_scalar_array_zero_multiplier[ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
allocate_scalar_array/test_allocate_too_much[ OK ] [ 0.00001000 / 0.00000900 CPU ]
|
||||||
|
4 of 4 (100%) tests successful, 0 (0%) test skipped. Allocated 500 lists
|
||||||
|
Running test suite with seed 0x9d78388e...
|
||||||
|
/example/compare [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
/example/rand [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
/example/parameters
|
||||||
|
foo=one, bar=red [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
foo=one, bar=green [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
foo=one, bar=blue [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
foo=two, bar=red [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
foo=two, bar=green [ OK ] [ 0.00000200 / 0.00000000 CPU ] foo=two, bar=blue [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
foo=three, bar=red [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
foo=three, bar=green [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
foo=three, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
11 of 11 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x07fdd526...
|
||||||
|
allocate_list/create [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
|
allocate_list/overwrite [ OK ] [ 0.00000100 / 0.00000100 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xf26a30e1...
|
||||||
|
create_token_pointer_array/test_create_token_pointer_array_single[ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
create_token_pointer_array/test_create_token_pointer_array_multiple[ OK ] [ 0.00000300 / 0.00000200 CPU ]
|
||||||
|
create_token_pointer_array/test_create_token_pointer_array_memory_allocation[ OK ] [ 0.00000200 / 0.00000300 CPU ]
|
||||||
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x4c18af41...
|
||||||
|
snek_zero_out/test_zero_out_integer [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
snek_zero_out/test_zero_out_float [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
snek_zero_out/test_zero_out_bool [ OK ] [ 0.00000100 / 0.00000000 CPU ] snek_zero_out/test_zero_out_nonzero_values[ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xb0750720...
|
||||||
|
void-pointer/swap_ints [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
void-pointer/swap_ints_same [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xc10a0ca0...
|
||||||
|
void-pointer/swap_str [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
void-pointer/test_swap_str_long [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xa27e09af...
|
||||||
|
swap/generic_ints [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
swap/generic_strings [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
swap/generic_struct [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xd1be93bf...
|
||||||
|
snekstack/create_stack_small [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
|
snekstack/create_stack_large [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x92735306...
|
||||||
|
snekstack/create_stack [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
snekstack/push_stack [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
snekstack/push_double_capacity [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xd641eade...
|
||||||
|
snekstack/create_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
snekstack/push_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
snekstack/pop_stack [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
snekstack/pop_stack_empty [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xd1d1136d...
|
||||||
|
snekstack/create_stack [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
snekstack/push_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
snekstack/pop_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x5493a18d...
|
||||||
|
snekstack/heterogenous_stack [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
1 of 1 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x0dc3c3f9...
|
||||||
|
snekstack/multiple_types_stack [ OK ] [ 0.00000300 / 0.00000200 CPU ]
|
||||||
|
1 of 1 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
[100%] Built target run
|
||||||
|
#+END_SRC
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 311 KiB |
@@ -0,0 +1,39 @@
|
|||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
munit_case(RUN, create_stack_small, {
|
||||||
|
my_stack_t *s = stack_new(3);
|
||||||
|
assert_int(s->capacity, ==, 3, "Sets capacity to 3");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
free(s->data);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, create_stack_large, {
|
||||||
|
my_stack_t *s = stack_new(100);
|
||||||
|
assert_int(s->capacity, ==, 100, "Sets capacity to 100");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
free(s->data);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/create_stack_small", create_stack_small),
|
||||||
|
munit_test("/create_stack_large", create_stack_large),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("snekstack", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity)
|
||||||
|
{
|
||||||
|
my_stack_t *stack = (my_stack_t *)malloc(sizeof(my_stack_t));
|
||||||
|
if (stack == NULL) return NULL;
|
||||||
|
stack->count = 0;
|
||||||
|
stack->capacity = capacity;
|
||||||
|
stack->data = malloc(sizeof(void*) * capacity);
|
||||||
|
if (stack->data == NULL) {
|
||||||
|
free(stack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct Stack {
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
void **data;
|
||||||
|
} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity);
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
munit_case(RUN, create_stack, {
|
||||||
|
my_stack_t *s = stack_new(10);
|
||||||
|
assert_int(s->capacity, ==, 10, "Sets capacity to 10");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
// Clean up our allocated data.
|
||||||
|
free(s->data);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
// Should be nothing left that is allocated.
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, push_stack, {
|
||||||
|
my_stack_t *s = stack_new(2);
|
||||||
|
assert_ptr_not_null(s, "Must allocate a new stack");
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
int a = 1;
|
||||||
|
|
||||||
|
stack_push(s, &a);
|
||||||
|
stack_push(s, &a);
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 2, "2 elements in the stack");
|
||||||
|
assert_ptr_equal(s->data[0], &a, "element inserted into stack");
|
||||||
|
|
||||||
|
// Clean up our allocated data.
|
||||||
|
free(s->data);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
// Should be nothing left that is allocated.
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, push_double_capacity, {
|
||||||
|
my_stack_t *s = stack_new(2);
|
||||||
|
assert_ptr_not_null(s, "Must allocate a new stack");
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
int a = 1;
|
||||||
|
|
||||||
|
stack_push(s, &a);
|
||||||
|
stack_push(s, &a);
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 2, "2 elements in the stack");
|
||||||
|
|
||||||
|
stack_push(s, &a);
|
||||||
|
assert_int(s->capacity, ==, 4, "Capacity is doubled");
|
||||||
|
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||||
|
|
||||||
|
// Should reallocate memory.
|
||||||
|
// assert_int_equal(boot_realloc_count(), 1, "Must reallocate memory for stack");
|
||||||
|
|
||||||
|
// Clean up our allocated data.
|
||||||
|
free(s->data);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
// Should be nothing left that is allocated.
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/create_stack", create_stack),
|
||||||
|
munit_test("/push_stack", push_stack),
|
||||||
|
munit_test("/push_double_capacity", push_double_capacity),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("snekstack", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
void stack_push(my_stack_t *stack, void *obj) {
|
||||||
|
|
||||||
|
if (stack->count >= stack->capacity) {
|
||||||
|
void **data = realloc(stack->data, sizeof(void *) * stack->capacity * 2);
|
||||||
|
if (data == NULL) return;
|
||||||
|
stack->data = data;
|
||||||
|
stack->capacity *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->data[stack->count] = obj;
|
||||||
|
stack->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity) {
|
||||||
|
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
||||||
|
if (stack == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->count = 0;
|
||||||
|
stack->capacity = capacity;
|
||||||
|
stack->data = malloc(stack->capacity * sizeof(void *));
|
||||||
|
if (stack->data == NULL) {
|
||||||
|
free(stack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct Stack {
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
void **data;
|
||||||
|
} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity);
|
||||||
|
void stack_push(my_stack_t *stack, void *obj);
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
munit_case(RUN, pop_stack, {
|
||||||
|
my_stack_t *s = stack_new(2);
|
||||||
|
assert_ptr_not_null(s, "Must allocate a new stack");
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
int one = 1;
|
||||||
|
int two = 2;
|
||||||
|
int three = 3;
|
||||||
|
|
||||||
|
stack_push(s, &one);
|
||||||
|
stack_push(s, &two);
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 2, "2 elements in the stack");
|
||||||
|
|
||||||
|
stack_push(s, &three);
|
||||||
|
assert_int(s->capacity, ==, 4, "Capacity is doubled");
|
||||||
|
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||||
|
|
||||||
|
int *popped = stack_pop(s);
|
||||||
|
assert_int(*popped, ==, three, "Should pop the last element");
|
||||||
|
|
||||||
|
popped = stack_pop(s);
|
||||||
|
assert_int(*popped, ==, two, "Should pop the last element");
|
||||||
|
|
||||||
|
popped = stack_pop(s);
|
||||||
|
assert_int(*popped, ==, one, "Should pop the only remaining element");
|
||||||
|
|
||||||
|
popped = stack_pop(s);
|
||||||
|
assert_null(popped, "No remaining elements");
|
||||||
|
|
||||||
|
// Clean up our allocated data.
|
||||||
|
free(s->data);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
// Should be nothing left that is allocated.
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, pop_stack_empty, {
|
||||||
|
my_stack_t *s = stack_new(2);
|
||||||
|
assert_ptr_not_null(s, "Must allocate a new stack");
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
int *popped = stack_pop(s);
|
||||||
|
assert_null(popped, "Should return null when popping an empty stack");
|
||||||
|
|
||||||
|
// Clean up our allocated data.
|
||||||
|
free(s->data);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
// Should be nothing left that is allocated.
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, push_stack, {
|
||||||
|
my_stack_t *s = stack_new(2);
|
||||||
|
assert_ptr_not_null(s, "Must allocate a new stack");
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
int a = 1;
|
||||||
|
|
||||||
|
stack_push(s, &a);
|
||||||
|
stack_push(s, &a);
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 2, "2 elements in the stack");
|
||||||
|
|
||||||
|
stack_push(s, &a);
|
||||||
|
assert_int(s->capacity, ==, 4, "Capacity is doubled");
|
||||||
|
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||||
|
|
||||||
|
// Clean up our allocated data.
|
||||||
|
free(s->data);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
// Should be nothing left that is allocated.
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, create_stack, {
|
||||||
|
my_stack_t *s = stack_new(10);
|
||||||
|
assert_int(s->capacity, ==, 10, "Sets capacity to 10");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
// Clean up our allocated data.
|
||||||
|
free(s->data);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
// Should be nothing left that is allocated.
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/create_stack", create_stack),
|
||||||
|
munit_test("/push_stack", push_stack),
|
||||||
|
munit_test("/pop_stack", pop_stack),
|
||||||
|
munit_test("/pop_stack_empty", pop_stack_empty),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("snekstack", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
void *stack_pop(my_stack_t *stack) {
|
||||||
|
if (stack->count == 0) return NULL;
|
||||||
|
stack->count--;
|
||||||
|
return stack->data[stack->count];
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line'
|
||||||
|
|
||||||
|
void stack_push(my_stack_t *stack, void *obj) {
|
||||||
|
if (stack->count == stack->capacity) {
|
||||||
|
stack->capacity *= 2;
|
||||||
|
void **temp = realloc(stack->data, stack->capacity * sizeof(void *));
|
||||||
|
if (temp == NULL) {
|
||||||
|
stack->capacity /= 2;
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
stack->data = temp;
|
||||||
|
}
|
||||||
|
stack->data[stack->count] = obj;
|
||||||
|
stack->count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity) {
|
||||||
|
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
||||||
|
if (stack == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->count = 0;
|
||||||
|
stack->capacity = capacity;
|
||||||
|
stack->data = malloc(stack->capacity * sizeof(void *));
|
||||||
|
if (stack->data == NULL) {
|
||||||
|
free(stack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct Stack {
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
void **data;
|
||||||
|
} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity);
|
||||||
|
void stack_push(my_stack_t *stack, void *obj);
|
||||||
|
void *stack_pop(my_stack_t *stack);
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
munit_case(RUN, pop_stack, {
|
||||||
|
my_stack_t *s = stack_new(2);
|
||||||
|
assert_ptr_not_null(s, "Must allocate a new stack");
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
int one = 1;
|
||||||
|
int two = 2;
|
||||||
|
int three = 3;
|
||||||
|
|
||||||
|
stack_push(s, &one);
|
||||||
|
stack_push(s, &two);
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 2, "2 elements in the stack");
|
||||||
|
|
||||||
|
stack_push(s, &three);
|
||||||
|
assert_int(s->capacity, ==, 4, "Capacity is doubled");
|
||||||
|
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||||
|
|
||||||
|
int *popped = stack_pop(s);
|
||||||
|
assert_int(*popped, ==, three, "Should pop the last element");
|
||||||
|
|
||||||
|
popped = stack_pop(s);
|
||||||
|
assert_int(*popped, ==, two, "Should pop the last element");
|
||||||
|
|
||||||
|
popped = stack_pop(s);
|
||||||
|
assert_int(*popped, ==, one, "Should pop the only remaining element");
|
||||||
|
|
||||||
|
popped = stack_pop(s);
|
||||||
|
assert_null(popped, "No remaining elements");
|
||||||
|
|
||||||
|
stack_free(s);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, push_stack, {
|
||||||
|
my_stack_t *s = stack_new(2);
|
||||||
|
assert_ptr_not_null(s, "Must allocate a new stack");
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
int a = 1;
|
||||||
|
|
||||||
|
stack_push(s, &a);
|
||||||
|
stack_push(s, &a);
|
||||||
|
|
||||||
|
assert_int(s->capacity, ==, 2, "Sets capacity to 2");
|
||||||
|
assert_int(s->count, ==, 2, "2 elements in the stack");
|
||||||
|
|
||||||
|
stack_push(s, &a);
|
||||||
|
assert_int(s->capacity, ==, 4, "Capacity is doubled");
|
||||||
|
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||||
|
|
||||||
|
stack_free(s);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, create_stack, {
|
||||||
|
my_stack_t *s = stack_new(10);
|
||||||
|
assert_int(s->capacity, ==, 10, "Sets capacity to 10");
|
||||||
|
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||||
|
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||||
|
|
||||||
|
stack_free(s);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/create_stack", create_stack),
|
||||||
|
munit_test("/push_stack", push_stack),
|
||||||
|
munit_test("/pop_stack", pop_stack),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("snekstack", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
void stack_free(my_stack_t *stack) {
|
||||||
|
if (stack == NULL) return;
|
||||||
|
|
||||||
|
if (stack->data != NULL) {
|
||||||
|
free(stack->data);
|
||||||
|
stack->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
void *stack_pop(my_stack_t *stack) {
|
||||||
|
if (stack->count == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->count--;
|
||||||
|
return stack->data[stack->count];
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_push(my_stack_t *stack, void *obj) {
|
||||||
|
if (stack->count == stack->capacity) {
|
||||||
|
stack->capacity *= 2;
|
||||||
|
void **temp = realloc(stack->data, stack->capacity * sizeof(void *));
|
||||||
|
if (temp == NULL) {
|
||||||
|
stack->capacity /= 2;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
stack->data = temp;
|
||||||
|
}
|
||||||
|
stack->data[stack->count] = obj;
|
||||||
|
stack->count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity) {
|
||||||
|
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
||||||
|
if (stack == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->count = 0;
|
||||||
|
stack->capacity = capacity;
|
||||||
|
stack->data = malloc(stack->capacity * sizeof(void *));
|
||||||
|
if (stack->data == NULL) {
|
||||||
|
free(stack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct Stack {
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
void **data;
|
||||||
|
} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity);
|
||||||
|
void stack_push(my_stack_t *stack, void *obj);
|
||||||
|
void *stack_pop(my_stack_t *stack);
|
||||||
|
void stack_free(my_stack_t *stack);
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "snekstack.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
void scary_double_push(my_stack_t *s) {
|
||||||
|
stack_push(s, (void *)1337);
|
||||||
|
int *number = malloc(sizeof(int));
|
||||||
|
if (number == NULL) return;
|
||||||
|
*number = 1024;
|
||||||
|
stack_push(s, number);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
void scary_double_push(my_stack_t *s);
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#include "exercise.h"
|
||||||
|
|
||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
munit_case(RUN, heterogenous_stack, {
|
||||||
|
my_stack_t *s = stack_new(2);
|
||||||
|
assert_ptr_not_null(s, "Must allocate a new stack");
|
||||||
|
|
||||||
|
scary_double_push(s);
|
||||||
|
assert_int(s->count, ==, 2, "Should have two items in the stack");
|
||||||
|
|
||||||
|
int value = (int)s->data[0];
|
||||||
|
assert_int(value, ==, 1337, "Zero item should be 1337");
|
||||||
|
|
||||||
|
int *pointer = s->data[1];
|
||||||
|
assert_int(*pointer, ==, 1024, "Top item should be 1024");
|
||||||
|
|
||||||
|
free(pointer);
|
||||||
|
stack_free(s);
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/heterogenous_stack", heterogenous_stack),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("snekstack", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
void stack_free(my_stack_t *stack) {
|
||||||
|
if (stack == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack->data != NULL) {
|
||||||
|
free(stack->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stack_pop(my_stack_t *stack) {
|
||||||
|
if (stack->count == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->count--;
|
||||||
|
return stack->data[stack->count];
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_push(my_stack_t *stack, void *obj) {
|
||||||
|
if (stack->count == stack->capacity) {
|
||||||
|
stack->capacity *= 2;
|
||||||
|
void **temp = realloc(stack->data, stack->capacity * sizeof(void *));
|
||||||
|
if (temp == NULL) {
|
||||||
|
stack->capacity /= 2;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
stack->data = temp;
|
||||||
|
}
|
||||||
|
stack->data[stack->count] = obj;
|
||||||
|
stack->count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity) {
|
||||||
|
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
||||||
|
if (stack == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->count = 0;
|
||||||
|
stack->capacity = capacity;
|
||||||
|
stack->data = malloc(stack->capacity * sizeof(void *));
|
||||||
|
if (stack->data == NULL) {
|
||||||
|
free(stack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct Stack {
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
void **data;
|
||||||
|
} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity);
|
||||||
|
void stack_push(my_stack_t *stack, void *obj);
|
||||||
|
void *stack_pop(my_stack_t *stack);
|
||||||
|
void stack_free(my_stack_t *stack);
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
void stack_push_multiple_types(my_stack_t *s)
|
||||||
|
{
|
||||||
|
float *pi = (float *)malloc(sizeof(float));
|
||||||
|
if (pi == NULL) return;
|
||||||
|
*pi = 3.14;
|
||||||
|
|
||||||
|
stack_push(s, pi);
|
||||||
|
|
||||||
|
const char *text = "Sneklang is blazingly slow!";
|
||||||
|
char *str = (char *)malloc(sizeof(char) * strlen(text));
|
||||||
|
if (str == NULL) return;
|
||||||
|
strcpy(str, text);
|
||||||
|
|
||||||
|
stack_push(s, str);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
void stack_push_multiple_types(my_stack_t *s);
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#include "exercise.h"
|
||||||
|
|
||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
munit_case(RUN, multiple_types_stack, {
|
||||||
|
my_stack_t *s = stack_new(4);
|
||||||
|
assert_ptr_not_null(s, "Must allocate a new stack");
|
||||||
|
|
||||||
|
stack_push_multiple_types(s);
|
||||||
|
assert_int(s->count, ==, 2, "Should have two items in the stack");
|
||||||
|
|
||||||
|
float *f = s->data[0];
|
||||||
|
assert_float(*f, ==, 3.14, "Float is equal");
|
||||||
|
|
||||||
|
char *string = s->data[1];
|
||||||
|
assert_string_equal(string, "Sneklang is blazingly slow!", "char* is equal");
|
||||||
|
|
||||||
|
free(f);
|
||||||
|
free(string);
|
||||||
|
stack_free(s);
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/multiple_types_stack", multiple_types_stack),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("snekstack", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "snekstack.h"
|
||||||
|
|
||||||
|
void stack_free(my_stack_t *stack) {
|
||||||
|
if (stack == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack->data != NULL) {
|
||||||
|
free(stack->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stack_pop(my_stack_t *stack) {
|
||||||
|
if (stack->count == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->count--;
|
||||||
|
return stack->data[stack->count];
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_push(my_stack_t *stack, void *obj) {
|
||||||
|
if (stack->count == stack->capacity) {
|
||||||
|
stack->capacity *= 2;
|
||||||
|
void **temp = realloc(stack->data, stack->capacity * sizeof(void *));
|
||||||
|
if (temp == NULL) {
|
||||||
|
stack->capacity /= 2;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
stack->data = temp;
|
||||||
|
}
|
||||||
|
stack->data[stack->count] = obj;
|
||||||
|
stack->count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity) {
|
||||||
|
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
||||||
|
if (stack == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->count = 0;
|
||||||
|
stack->capacity = capacity;
|
||||||
|
stack->data = malloc(stack->capacity * sizeof(void *));
|
||||||
|
if (stack->data == NULL) {
|
||||||
|
free(stack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct Stack {
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
void **data;
|
||||||
|
} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
|
||||||
|
|
||||||
|
my_stack_t *stack_new(size_t capacity);
|
||||||
|
void stack_push(my_stack_t *stack, void *obj);
|
||||||
|
void *stack_pop(my_stack_t *stack);
|
||||||
|
void stack_free(my_stack_t *stack);
|
||||||
+13
-3
@@ -43,6 +43,10 @@
|
|||||||
#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);
|
||||||
|
|
||||||
|
#undef assert_float
|
||||||
|
#define assert_float(A, OP, B, MSG) \
|
||||||
|
munit_assert_float(A, OP, B, MSG);
|
||||||
|
|
||||||
#undef assert_double
|
#undef assert_double
|
||||||
#define assert_double(A, OP, B, MSG) \
|
#define assert_double(A, OP, B, MSG) \
|
||||||
munit_assert_double(A, OP, B);
|
munit_assert_double(A, OP, B);
|
||||||
@@ -92,11 +96,17 @@
|
|||||||
#define munit_assert_not_null(PTR, MSG) \
|
#define munit_assert_not_null(PTR, MSG) \
|
||||||
munit_assert_ptr(PTR, !=, NULL)
|
munit_assert_ptr(PTR, !=, NULL)
|
||||||
|
|
||||||
// ptr
|
#undef assert_null
|
||||||
|
#define assert_null(PTR, MSG) munit_assert_null(PTR, MSG)
|
||||||
|
|
||||||
#undef assert_ptr_not_null
|
// ptr
|
||||||
#define assert_ptr_not_null(PTR, MSG) munit_assert_not_null(PTR, MSG)
|
|
||||||
|
|
||||||
#undef munit_assert_ptr_not_equal
|
#undef munit_assert_ptr_not_equal
|
||||||
#define munit_assert_ptr_not_equal(A, B, MSG) \
|
#define munit_assert_ptr_not_equal(A, B, MSG) \
|
||||||
munit_assert_ptr(A, !=, B)
|
munit_assert_ptr(A, !=, B)
|
||||||
|
|
||||||
|
#undef assert_ptr_not_null
|
||||||
|
#define assert_ptr_not_null(PTR, MSG) munit_assert_not_null(PTR, MSG)
|
||||||
|
|
||||||
|
#undef assert_ptr_equal
|
||||||
|
#define assert_ptr_equal(A, B, MSG) munit_assert_ptr_equal(A, B)
|
||||||
|
|||||||
Reference in New Issue
Block a user