25 changed files with 1006 additions and 3 deletions
@ -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 |
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); |
Loading…
Reference in new issue