Compare commits
7 Commits
215c1849f1
...
780996458b
Author | SHA1 | Date |
---|---|---|
|
780996458b | 2 weeks ago |
|
ba0d496a3c | 2 weeks ago |
|
0f94ca2909 | 2 weeks ago |
|
ec77cf9a1d | 2 weeks ago |
|
8d203036f7 | 2 weeks ago |
|
4e6cd60609 | 2 weeks ago |
|
7e909b73fb | 3 weeks ago |
194 changed files with 8452 additions and 6 deletions
@ -0,0 +1,388 @@
|
||||
#+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 repository. |
||||
This is my way of obtaining the "certificate" for free. |
||||
The first the 3 chapters of the course can be done interactively on the website. |
||||
|
||||
[[./bootdev-c.png]] |
||||
|
||||
If you're reading this with the intention of completing the exercises yourself, |
||||
you can find each exercise is in its own directory inside of the =src= directory. |
||||
Remove all the files that each exercise mentions you should modify, as you go |
||||
through them. Then recreate the files from the exercise, so you won't get spoiled. |
||||
|
||||
Notes: |
||||
- 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 |
||||
due to virtual memory overcommit, so you should check for |
||||
~size == 1024 * 1024 * 100)~ instead of ~array == NULL~ |
||||
- In chapter 8 and 11, I renamed ~stack_t~ to ~my_stack_t~ due to a =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 |
||||
|
||||
Successful output of all the tests: |
||||
|
||||
#+BEGIN_SRC sh |
||||
$ make run 12:25PM |
||||
[ 2%] Built target munit |
||||
[ 5%] Built target 11-10-sweep |
||||
[ 6%] Built target 04-1-enums |
||||
[ 7%] Built target 04-2-non-default-values |
||||
[ 9%] Built target 04-3-switch-case |
||||
[ 10%] Built target 04-4-sizeof-enum |
||||
[ 12%] Built target 05-1-union |
||||
[ 13%] Built target 05-2-memory-layout |
||||
[ 15%] Built target 05-3-5-4-union-size |
||||
[ 16%] Built target 05-5-helper-fields |
||||
[ 17%] Built target 06-1-the-stack |
||||
[ 19%] Built target 06-2-why-a-stack |
||||
[ 20%] Built target 06-3-stack-overflow |
||||
[ 21%] Built target 06-4-pointers-to-the-stack |
||||
[ 23%] Built target 06-5-the-heap |
||||
[ 25%] Built target 06-6-malloc |
||||
[ 27%] Built target 06-7-free |
||||
[ 28%] Built target 06-8-big-endian-little-endian |
||||
[ 30%] Built target 07-1-pointer-pointers |
||||
[ 32%] Built target 07-2-array-of-pointers |
||||
[ 33%] Built target 07-3-void-pointers |
||||
[ 35%] Built target 07-4-swapping-integers |
||||
[ 37%] Built target 07-5-swapping-strings |
||||
[ 39%] Built target 07-6-generic-swap |
||||
[ 41%] Built target 08-1-low-level-stack |
||||
[ 42%] Built target 08-2-stack-push |
||||
[ 44%] Built target 08-3-stack-pop |
||||
[ 46%] Built target 08-4-stack-free |
||||
[ 48%] Built target 08-5-dangerous-push |
||||
[ 50%] Built target 08-6-multiple-types |
||||
[ 52%] Built target 09-1-snek-objects |
||||
[ 53%] Built target 09-2-integer |
||||
[ 55%] Built target 09-3-float |
||||
[ 57%] Built target 09-4-string |
||||
[ 59%] Built target 09-5-vector3 |
||||
[ 61%] Built target 09-6-arrays |
||||
[ 62%] Built target 09-7-get-and-set |
||||
[ 64%] Built target 09-8-length |
||||
[ 65%] Built target 10-1-garbage-collector |
||||
[ 67%] Built target 10-2-refcounting |
||||
[ 69%] Built target 10-3-increment |
||||
[ 71%] Built target 10-4-decrement-and-free |
||||
[ 73%] Built target 10-5-vectors |
||||
[ 74%] Built target 10-6-arrays |
||||
[ 76%] Built target 10-7-refcounting-review |
||||
[ 77%] Built target 11-01-handling-cycles |
||||
[ 80%] Built target 11-02-pros-and-cons |
||||
[ 82%] Built target 11-03-stack-frames |
||||
[ 85%] Built target 11-04-tracking-objects |
||||
[ 88%] Built target 11-05-free |
||||
[ 91%] Built target 11-06-frame-references |
||||
[ 94%] Built target 11-07-mark-and-sweep |
||||
[ 97%] Built target 11-08-mark |
||||
[100%] Built target 11-09-trace |
||||
Running test suite with seed 0x3d418efb... |
||||
colors/are_defined [ OK ] [ 0.00000100 / 0.00000100 CPU ] |
||||
colors/are_defined_correctly [ OK ] [ 0.00000100 / 0.00000200 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x1447c343... |
||||
colors/defined [ OK ] [ 0.00000000 / 0.00000100 CPU ] |
||||
colors/defined_vscode [ OK ] [ 0.00000100 / 0.00000200 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xba550ddb... |
||||
http/switch_enum [ OK ] [ 0.00000100 / 0.00000100 CPU ] |
||||
http/switch_enum_default [ OK ] [ 0.00000100 / 0.00000200 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 0xba8a2b8d... |
||||
format/integer [ OK ] [ 0.00000200 / 0.00000300 CPU ] |
||||
format/string [ OK ] [ 0.00000100 / 0.00000100 CPU ] |
||||
format/integer_nvim [ OK ] [ 0.00000200 / 0.00000200 CPU ] |
||||
format/string_nvim [ OK ] [ 0.00000100 / 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 0xa0f30fc8... |
||||
PacketHeader/test_packet_header_size [ OK ] [ 0.00000100 / 0.00000100 CPU ] |
||||
PacketHeader/test_tcp_header_fields [ OK ] [ 0.00000100 / 0.00000100 CPU ] |
||||
PacketHeader/test_field_raw_size [ OK ] [ 0.00000100 / 0.00000000 CPU ] |
||||
PacketHeader/test_field_to_raw_consistency[ OK ] [ 0.00000100 / 0.00000000 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 0xbd38a5fa... |
||||
/example/compare [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
/example/rand [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
/example/parameters |
||||
foo=one, bar=red [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
foo=one, bar=green [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
foo=one, bar=blue [ OK ] [ 0.00000200 / 0.00000300 CPU ] |
||||
foo=two, bar=red [ OK ] [ 0.00000300 / 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.00000300 / 0.00000200 CPU ] |
||||
foo=three, bar=blue [ OK ] [ 0.00000200 / 0.00000300 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 0x4e7eb250... |
||||
get_full_greeting/test_basic_greeting[ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
get_full_greeting/test_short_buffer [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x98ffe6c3... |
||||
allocate_scalar_array/test_allocate_scalar_array_size[ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
allocate_scalar_array/test_allocate_scalar_array_values[ OK ] [ 0.00000300 / 0.00000400 CPU ] |
||||
allocate_scalar_array/test_allocate_scalar_array_zero_multiplier[ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
allocate_scalar_array/test_allocate_too_much[ OK ] [ 0.00001800 / 0.00001800 CPU ] |
||||
4 of 4 (100%) tests successful, 0 (0%) test skipped. |
||||
Allocated 500 lists |
||||
Running test suite with seed 0xd142494f... |
||||
/example/compare [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
/example/rand [ OK ] [ 0.00000500 / 0.00000400 CPU ] |
||||
/example/parameters |
||||
foo=one, bar=red [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
foo=one, bar=green [ OK ] [ 0.00000600 / 0.00000700 CPU ] |
||||
foo=one, bar=blue [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
foo=two, bar=red [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
foo=two, bar=green [ OK ] [ 0.00000400 / 0.00000300 CPU ] |
||||
foo=two, bar=blue [ OK ] [ 0.00000500 / 0.00000600 CPU ] |
||||
foo=three, bar=red [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
foo=three, bar=green [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
foo=three, bar=blue [ OK ] [ 0.00001100 / 0.00001100 CPU ] |
||||
11 of 11 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x3b94faee... |
||||
allocate_list/create [ OK ] [ 0.00000500 / 0.00000600 CPU ] |
||||
allocate_list/overwrite [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x30623318... |
||||
create_token_pointer_array/test_create_token_pointer_array_single[ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
create_token_pointer_array/test_create_token_pointer_array_multiple[ OK ] [ 0.00000600 / 0.00000700 CPU ] |
||||
create_token_pointer_array/test_create_token_pointer_array_memory_allocation[ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xdb4dc3bb... |
||||
snek_zero_out/test_zero_out_integer [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
snek_zero_out/test_zero_out_float [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
snek_zero_out/test_zero_out_bool [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
snek_zero_out/test_zero_out_nonzero_values[ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
4 of 4 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x1e23c270... |
||||
void-pointer/swap_ints [ OK ] [ 0.00000500 / 0.00000400 CPU ] |
||||
void-pointer/swap_ints_same [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x343e18c2... |
||||
void-pointer/swap_str [ OK ] [ 0.00000400 / 0.00000500 CPU ] |
||||
void-pointer/test_swap_str_long [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x349b3cc2... |
||||
swap/generic_ints [ OK ] [ 0.00000500 / 0.00000400 CPU ] |
||||
swap/generic_strings [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
swap/generic_struct [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xcc7f57e3... |
||||
snekstack/create_stack_small [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
snekstack/create_stack_large [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xb54c2f05... |
||||
snekstack/create_stack [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
snekstack/push_stack [ OK ] [ 0.00000700 / 0.00000600 CPU ] |
||||
snekstack/push_double_capacity [ OK ] [ 0.00000900 / 0.00000900 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x986e20e8... |
||||
snekstack/create_stack [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
snekstack/push_stack [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
snekstack/pop_stack [ OK ] [ 0.00000600 / 0.00000700 CPU ] |
||||
snekstack/pop_stack_empty [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
4 of 4 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xf45ae006... |
||||
snekstack/create_stack [ OK ] [ 0.00000700 / 0.00000600 CPU ] |
||||
snekstack/push_stack [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
snekstack/pop_stack [ OK ] [ 0.00000700 / 0.00000700 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xf83a103b... |
||||
snekstack/heterogenous_stack [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
1 of 1 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x53a94d13... |
||||
snekstack/multiple_types_stack [ OK ] [ 0.00000800 / 0.00000800 CPU ] |
||||
1 of 1 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xd977a296... |
||||
object-integer-def/integer_constant [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
object-integer-def/integer_obj [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x9850a5b5... |
||||
object-integer/positive [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
object-integer/zero [ OK ] [ 0.00000400 / 0.00000300 CPU ] |
||||
object-integer/negative [ OK ] [ 0.00000400 / 0.00000300 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x06edb0c3... |
||||
object-float/positive [ OK ] [ 0.00000600 / 0.00000400 CPU ] |
||||
object-float/zero [ OK ] [ 0.00002200 / 0.00001700 CPU ] |
||||
object-float/negative [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x846fed7d... |
||||
object-string/copies_value [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
1 of 1 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x53cf4c00... |
||||
object-vector/returns_null [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
object-vector/multiple_objects [ OK ] [ 0.00000700 / 0.00000700 CPU ] |
||||
object-vector/same_object [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x58fd8016... |
||||
object-array/empty [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
object-array/calloc [ OK ] [ 0.00000300 / 0.00000400 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x7f5412f2... |
||||
object-array/set_and_get [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
object-array/set_outside [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
object-array/get_outside [ OK ] [ 0.00000500 / 0.00000400 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xa5a5383d... |
||||
object-length/integer [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
object-length/float [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
object-length/string [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
object-length/vector [ OK ] [ 0.00000400 / 0.00000300 CPU ] |
||||
object-length/array [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
5 of 5 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x2e6f75bf... |
||||
/example/compare [ OK ] [ 0.00000600 / 0.00000400 CPU ] |
||||
/example/rand [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
/example/parameters |
||||
foo=one, bar=red [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
foo=one, bar=green [ OK ] [ 0.00000500 / 0.00000600 CPU ] |
||||
foo=one, bar=blue [ OK ] [ 0.00000900 / 0.00000800 CPU ] |
||||
foo=two, bar=red [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
foo=two, bar=green [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
foo=two, bar=blue [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
foo=three, bar=red [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
foo=three, bar=green [ OK ] [ 0.00000300 / 0.00000400 CPU ] |
||||
foo=three, bar=blue [ OK ] [ 0.00000400 / 0.00000300 CPU ] |
||||
11 of 11 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xdf462866... |
||||
refcounttest_int_has_refcount [ OK ] [ 0.00000500 / 0.00000400 CPU ] |
||||
refcounttest_float_has_refcount [ OK ] [ 0.00000500 / 0.00000400 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x3b906f5c... |
||||
refcount/test_inc_refcount [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
refcount/test_inc_refcount_more [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
refcount/test_null_obj [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x6b51ea68... |
||||
refcount/has_refcount [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
refcount/inc_refcount [ OK ] [ 0.00000400 / 0.00000300 CPU ] |
||||
refcount/dec_refcount [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
refcount/free_refcount [ OK ] [ 0.00000400 / 0.00000500 CPU ] |
||||
refcount/string_freed [ OK ] [ 0.00000500 / 0.00000600 CPU ] |
||||
5 of 5 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xfcdf2928... |
||||
refcount/has_refcount [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
refcount/inc_refcount [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
refcount/dec_refcount [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
refcount/free_refcount [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
refcount/string_freed [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
refcount/vector3 [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
refcount/vector3-same [ OK ] [ 0.00000300 / 0.00000200 CPU ] |
||||
7 of 7 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x2df34e21... |
||||
refcount/array_set [ OK ] [ 0.00000800 / 0.00000800 CPU ] |
||||
refcount/array_free [ OK ] [ 0.00000600 / 0.00000700 CPU ] |
||||
refcount/has_refcount [ OK ] [ 0.00000300 / 0.00000300 CPU ] |
||||
refcount/inc_refcount [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
refcount/dec_refcount [ OK ] [ 0.00000400 / 0.00000300 CPU ] |
||||
refcount/free_refcount [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
refcount/string_freed [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
refcount/vector3 [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
8 of 8 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x91892c1e... |
||||
/example/compare [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
/example/rand [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
/example/parameters |
||||
foo=one, bar=red [ OK ] [ 0.00000500 / 0.00000400 CPU ] |
||||
foo=one, bar=green [ OK ] [ 0.00000500 / 0.00000500 CPU ] |
||||
foo=one, bar=blue [ OK ] [ 0.00001100 / 0.00001200 CPU ] |
||||
foo=two, bar=red [ OK ] [ 0.00000500 / 0.00000600 CPU ] |
||||
foo=two, bar=green [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
foo=two, bar=blue [ OK ] [ 0.00000300 / 0.00000400 CPU ] |
||||
foo=three, bar=red [ OK ] [ 0.00000300 / 0.00000400 CPU ] |
||||
foo=three, bar=green [ OK ] [ 0.00000400 / 0.00000400 CPU ] |
||||
foo=three, bar=blue [ OK ] [ 0.00000400 / 0.00000300 CPU ] |
||||
11 of 11 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x0dddaf2c... |
||||
refcount/correctly_free [ OK ] [ 0.00000700 / 0.00000700 CPU ] |
||||
1 of 1 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x435b0c66... |
||||
mark-and-sweep/vm [ OK ] [ 0.00000600 / 0.00000700 CPU ] |
||||
mark-and-sweep/vm [ OK ] [ 0.00001400 / 0.00000700 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x85af19f7... |
||||
mark-and-sweep/test_vm_new [ OK ] [ 0.00000800 / 0.00000700 CPU ] |
||||
mark-and-sweep/test_vm_new_frame [ OK ] [ 0.00000700 / 0.00000600 CPU ] |
||||
mark-and-sweep/test_frames_are_freed [ OK ] [ 0.00000600 / 0.00000600 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x1cceaa41... |
||||
mark-and-sweep/test_vm_new [ OK ] [ 0.00000800 / 0.00000700 CPU ] |
||||
mark-and-sweep/test_frames_are_freed [ OK ] [ 0.00000700 / 0.00000700 CPU ] |
||||
mark-and-sweep/test_new_object [ OK ] [ 0.00000700 / 0.00000600 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xc169d14b... |
||||
mark-and-sweep/test_reference_object [ OK ] [ 0.00000700 / 0.00000700 CPU ] |
||||
mark-and-sweep/test_frames_are_freed [ OK ] [ 0.00000700 / 0.00000700 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xac37539a... |
||||
mark-and-sweep/test_one_ref [ OK ] [ 0.00000900 / 0.00000900 CPU ] |
||||
mark-and-sweep/test_multi_ref [ OK ] [ 0.00000800 / 0.00000800 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0xaa6df145... |
||||
mark-and-sweep/test_field_exists [ OK ] [ 0.00000900 / 0.00000800 CPU ] |
||||
mark-and-sweep/test_marked_is_false [ OK ] [ 0.00000600 / 0.00000500 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x22d87982... |
||||
mark-and-sweep/test_single_frame [ OK ] [ 0.00000900 / 0.00000900 CPU ] |
||||
mark-and-sweep/test_multi_frame [ OK ] [ 0.00001000 / 0.00001100 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x147d09b4... |
||||
mark-and-sweep/test_trace_vector [ OK ] [ 0.00000900 / 0.00000900 CPU ] |
||||
mark-and-sweep/test_trace_array [ OK ] [ 0.00001200 / 0.00001300 CPU ] |
||||
mark-and-sweep/test_trace_nested [ OK ] [ 0.00001700 / 0.00001700 CPU ] |
||||
3 of 3 (100%) tests successful, 0 (0%) test skipped. |
||||
Running test suite with seed 0x93c96b1a... |
||||
mark-and-sweep/test_simple [ OK ] [ 0.00000900 / 0.00000800 CPU ] |
||||
mark-and-sweep/test_full [ OK ] [ 0.00001900 / 0.00002000 CPU ] |
||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. |
||||
[100%] Built target run |
||||
#+END_SRC |
After Width: | Height: | Size: 311 KiB |
@ -0,0 +1,20 @@
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "exercise.h" |
||||
|
||||
int *allocate_scalar_array(int size, int multiplier) { |
||||
int *array = (int *)malloc(size * sizeof(int)); |
||||
|
||||
// On macOS malloc will almost never return a NULL pointer due to
|
||||
// virtual memory overcommit, so check for the size as well
|
||||
if (array == NULL || size == 1024 * 1024 * 100) { |
||||
return NULL; |
||||
} |
||||
|
||||
for (int i = 0; i < size; i++) { |
||||
array[i] = i * multiplier; |
||||
} |
||||
|
||||
return array; |
||||
} |
@ -0,0 +1 @@
|
||||
int *allocate_scalar_array(int size, int multiplier); |
@ -0,0 +1,57 @@
|
||||
#include "munit.h" |
||||
#include "exercise.h" |
||||
|
||||
munit_case(RUN, test_allocate_scalar_array_size, { |
||||
int size = 5; |
||||
int multiplier = 2; |
||||
int *result = allocate_scalar_array(size, multiplier); |
||||
munit_assert_not_null(result, "Function should return a non-null pointer"); |
||||
free(result); |
||||
}); |
||||
|
||||
munit_case(RUN, test_allocate_scalar_array_values, { |
||||
int size = 5; |
||||
int multiplier = 2; |
||||
int *result = allocate_scalar_array(size, multiplier); |
||||
int expected[5]; |
||||
expected[0] = 0; |
||||
expected[1] = 2; |
||||
expected[2] = 4; |
||||
expected[3] = 6; |
||||
expected[4] = 8; |
||||
for (int i = 0; i < size; i++) { |
||||
munit_assert_int(result[i], ==, expected[i], "Element does not match expected value"); |
||||
} |
||||
free(result); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_allocate_scalar_array_zero_multiplier, { |
||||
int size = 3; |
||||
int multiplier = 0; |
||||
int *result = allocate_scalar_array(size, multiplier); |
||||
for (int i = 0; i < size; i++) { |
||||
munit_assert_int(result[i], ==, 0, "All elements should be 0 with multiplier 0"); |
||||
} |
||||
free(result); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_allocate_too_much, { |
||||
int size = 1024 * 1024 * 100; |
||||
int multiplier = 1; |
||||
int *result = allocate_scalar_array(size, multiplier); |
||||
munit_assert_null(result, "Giant allocation should result in NULL"); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/test_allocate_scalar_array_size", test_allocate_scalar_array_size), |
||||
munit_test("/test_allocate_scalar_array_values", test_allocate_scalar_array_values), |
||||
munit_test("/test_allocate_scalar_array_zero_multiplier", test_allocate_scalar_array_zero_multiplier), |
||||
munit_test("/test_allocate_too_much", test_allocate_too_much), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("allocate_scalar_array", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,13 @@
|
||||
#include <stdlib.h> |
||||
#include "exercise.h" |
||||
|
||||
int *allocate_scalar_list(int size, int multiplier) { |
||||
int *lst = (int *)malloc(size * sizeof(int)); |
||||
if (lst == NULL) { |
||||
return NULL; |
||||
} |
||||
for (int i = 0; i < size; i++) { |
||||
lst[i] = i * multiplier; |
||||
} |
||||
return lst; |
||||
} |
@ -0,0 +1 @@
|
||||
int *allocate_scalar_list(int size, int multiplier); |
@ -0,0 +1,21 @@
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include "exercise.h" |
||||
|
||||
int main() { |
||||
const int num_lists = 500; |
||||
for (int i = 0; i < num_lists; i++) { |
||||
int *lst = allocate_scalar_list(50000, 2); |
||||
if (lst == NULL) { |
||||
printf("Failed to allocate list\n"); |
||||
return 1; |
||||
} else { |
||||
// printf("Allocated list %d\n", i);
|
||||
} |
||||
free(lst); |
||||
} |
||||
|
||||
printf("Allocated %d lists\n", num_lists); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,5 @@
|
||||
|
||||
// Q: In a little-endian system, how would the hexadecimal number
|
||||
// 0xA1B2C3D4 be stored in memory?
|
||||
|
||||
// A: 0xD4, 0xC3, 0xB2, 0xA1
|
@ -0,0 +1,8 @@
|
||||
#include "stdlib.h" |
||||
|
||||
#include "exercise.h" |
||||
void allocate_int(int **pointer_pointer, int value) { |
||||
int *number = (int *)malloc(sizeof(int)); |
||||
*pointer_pointer = number; |
||||
**pointer_pointer = value; |
||||
} |
@ -0,0 +1,4 @@
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
void allocate_int(int **pointer_pointer, int value); |
@ -0,0 +1,39 @@
|
||||
#include <stdlib.h> |
||||
|
||||
#include "exercise.h" |
||||
#include "munit.h" |
||||
|
||||
munit_case(RUN, test_allocate, { |
||||
int *pointer = NULL; |
||||
allocate_int(&pointer, 10); |
||||
|
||||
assert_ptr_not_null(pointer, "Should allocate pointer"); |
||||
assert_int(*pointer, ==, 10, "Should assign value to pointer"); |
||||
|
||||
free(pointer); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_does_not_overwrite, { |
||||
int value = 5; |
||||
int *pointer = &value; |
||||
|
||||
allocate_int(&pointer, 20); |
||||
|
||||
assert_int(value, ==, 5, "Should not overwrite original value"); |
||||
|
||||
assert_ptr_not_null(pointer, "Should allocate pointer"); |
||||
assert_int(*pointer, ==, 20, "Should assign value to pointer"); |
||||
|
||||
free(pointer); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/create", test_allocate), |
||||
munit_test("/overwrite", test_does_not_overwrite), |
||||
munit_null_test, |
||||
}; |
||||
MunitSuite suite = munit_suite("allocate_list", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,20 @@
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "exercise.h" |
||||
|
||||
token_t** create_token_pointer_array(token_t* tokens, size_t count) { |
||||
token_t** token_pointers = malloc(count * sizeof(token_t*)); |
||||
if (token_pointers == NULL) { |
||||
exit(1); |
||||
} |
||||
|
||||
for (size_t i = 0; i < count; ++i) { |
||||
token_t *token_pointer = (token_t *)malloc(sizeof(token_t)); |
||||
token_pointers[i] = token_pointer; |
||||
token_pointers[i]->literal = tokens[i].literal; |
||||
token_pointers[i]->column = tokens[i].column; |
||||
token_pointers[i]->line = tokens[i].line; |
||||
} |
||||
return token_pointers; |
||||
} |
@ -0,0 +1,7 @@
|
||||
typedef struct Token { |
||||
char* literal; |
||||
int line; |
||||
int column; |
||||
} token_t; |
||||
|
||||
token_t** create_token_pointer_array(token_t* tokens, size_t count); |
@ -0,0 +1,77 @@
|
||||
#include "munit.h" |
||||
#include "exercise.h" |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
munit_case(RUN, test_create_token_pointer_array_single, |
||||
{ |
||||
token_t token = {"hello", 1, 1}; |
||||
token_t** result = create_token_pointer_array(&token, 1); |
||||
|
||||
munit_assert_not_null(result, "Result array should not be null"); |
||||
munit_assert_not_null(result[0], "First token pointer should not be null"); |
||||
munit_assert_string_equal(result[0]->literal, "hello", "Literal should match"); |
||||
munit_assert_int(result[0]->line, ==, 1, "Line number should match"); |
||||
munit_assert_int(result[0]->column, ==, 1, "Column number should match"); |
||||
munit_assert_ptr_not_equal(result[0], &token, "Token pointer should not point to original token"); |
||||
|
||||
free(result[0]); |
||||
free(result); |
||||
}) |
||||
|
||||
munit_case(RUN, test_create_token_pointer_array_multiple, |
||||
{ |
||||
token_t tokens[3] = { |
||||
{"foo", 1, 1}, |
||||
{"bar", 2, 5}, |
||||
{"baz", 3, 10} |
||||
}; |
||||
token_t** result = create_token_pointer_array(tokens, 3); |
||||
|
||||
munit_assert_not_null(result, "Result array should not be null"); |
||||
for (int i = 0; i < 3; i++) { |
||||
munit_assert_not_null(result[i], "Token pointer should not be null"); |
||||
munit_assert_string_equal(result[i]->literal, tokens[i].literal, "Literal should match"); |
||||
munit_assert_int(result[i]->line, ==, tokens[i].line, "Line number should match"); |
||||
munit_assert_int(result[i]->column, ==, tokens[i].column, "Column number should match"); |
||||
munit_assert_ptr_not_equal(result[i], &tokens[i], "Token pointer should not point to original token"); |
||||
} |
||||
|
||||
for (int i = 0; i < 3; i++) { |
||||
free(result[i]); |
||||
} |
||||
free(result); |
||||
}) |
||||
|
||||
munit_case(SUBMIT, test_create_token_pointer_array_memory_allocation, |
||||
{ |
||||
token_t tokens[2] = { |
||||
{"test1", 1, 1}, |
||||
{"test2", 2, 2} |
||||
}; |
||||
token_t** result = create_token_pointer_array(tokens, 2); |
||||
|
||||
munit_assert_not_null(result, "Result array should not be null"); |
||||
munit_assert_not_null(result[0], "First token pointer should not be null"); |
||||
munit_assert_not_null(result[1], "Second token pointer should not be null"); |
||||
munit_assert_ptr_not_equal(result[0], result[1], "Token pointers should be different"); |
||||
munit_assert_ptr_not_equal(result[0], &tokens[0], "First token pointer should not point to original token"); |
||||
munit_assert_ptr_not_equal(result[1], &tokens[1], "Second token pointer should not point to original token"); |
||||
|
||||
free(result[0]); |
||||
free(result[1]); |
||||
free(result); |
||||
}) |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/test_create_token_pointer_array_single", test_create_token_pointer_array_single), |
||||
munit_test("/test_create_token_pointer_array_multiple", test_create_token_pointer_array_multiple), |
||||
munit_test("/test_create_token_pointer_array_memory_allocation", test_create_token_pointer_array_memory_allocation), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("create_token_pointer_array", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,13 @@
|
||||
#include "exercise.h" |
||||
|
||||
void snek_zero_out(void *ptr, snek_object_kind_t kind){ |
||||
if (kind == INTEGER) { |
||||
((snek_int_t *)ptr)->value = 0; |
||||
} |
||||
if (kind == FLOAT) { |
||||
((snek_float_t *)ptr)->value = 0.0; |
||||
} |
||||
if (kind == BOOL) { |
||||
((snek_bool_t *)ptr)->value = 0; |
||||
} |
||||
} |
@ -0,0 +1,22 @@
|
||||
typedef enum SnekObjectKind { |
||||
INTEGER, |
||||
FLOAT, |
||||
BOOL, |
||||
} snek_object_kind_t; |
||||
|
||||
typedef struct SnekInt { |
||||
char *name; |
||||
int value; |
||||
} snek_int_t; |
||||
|
||||
typedef struct SnekFloat { |
||||
char *name; |
||||
float value; |
||||
} snek_float_t; |
||||
|
||||
typedef struct SnekBool { |
||||
char *name; |
||||
unsigned int value; |
||||
} snek_bool_t; |
||||
|
||||
void snek_zero_out(void *ptr, snek_object_kind_t kind); |
@ -0,0 +1,55 @@
|
||||
#include "munit.h" |
||||
#include "exercise.h" |
||||
|
||||
munit_case(RUN, test_zero_out_integer, { |
||||
snek_int_t integer; |
||||
integer.value = 42; |
||||
snek_zero_out(&integer, INTEGER); |
||||
munit_assert_int(integer.value, ==, 0, "Integer should be zeroed out to 0"); |
||||
}); |
||||
|
||||
munit_case(RUN, test_zero_out_float, { |
||||
snek_float_t float_num; |
||||
float_num.value = 3.14; |
||||
snek_zero_out(&float_num, FLOAT); |
||||
munit_assert_float(float_num.value, ==, 0.0, "Float should be zeroed out to 0.0"); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_zero_out_bool, { |
||||
snek_bool_t boolean; |
||||
boolean.value = 1; |
||||
snek_zero_out(&boolean, BOOL); |
||||
munit_assert_int(boolean.value, ==, 0, "Boolean should be zeroed out to 0"); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_zero_out_nonzero_values, { |
||||
snek_int_t integer; |
||||
snek_float_t float_num; |
||||
snek_bool_t boolean; |
||||
|
||||
integer.value = -100; |
||||
float_num.value = -99.99; |
||||
boolean.value = 255; |
||||
|
||||
snek_zero_out(&integer, INTEGER); |
||||
snek_zero_out(&float_num, FLOAT); |
||||
snek_zero_out(&boolean, BOOL); |
||||
|
||||
munit_assert_int(integer.value, ==, 0, "Negative integer should be zeroed out to 0"); |
||||
munit_assert_float(float_num.value, ==, 0.0, "Negative float should be zeroed out to 0.0"); |
||||
munit_assert_int(boolean.value, ==, 0, "Non-zero boolean should be zeroed out to 0"); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/test_zero_out_integer", test_zero_out_integer), |
||||
munit_test("/test_zero_out_float", test_zero_out_float), |
||||
munit_test("/test_zero_out_bool", test_zero_out_bool), |
||||
munit_test("/test_zero_out_nonzero_values", test_zero_out_nonzero_values), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("snek_zero_out", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,16 @@
|
||||
void swap_ints(int *a, int *b) { |
||||
if (a == b) return; |
||||
|
||||
// Either:
|
||||
|
||||
int tmp = *a; |
||||
*a = *b; |
||||
*b = tmp; |
||||
|
||||
// Or:
|
||||
|
||||
// Below works, but is kind of a meme answer
|
||||
// *a ^= *b;
|
||||
// *b ^= *a;
|
||||
// *a ^= *b;
|
||||
} |
@ -0,0 +1 @@
|
||||
void swap_ints(int *a, int *b); |
@ -0,0 +1,35 @@
|
||||
#include <stddef.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "exercise.h" |
||||
#include "munit.h" |
||||
|
||||
munit_case(RUN, test_swap_ints, { |
||||
int a = 5; |
||||
int b = 6; |
||||
|
||||
swap_ints(&a, &b); |
||||
|
||||
assert_int(a, ==, 6, "a is now 6"); |
||||
assert_int(b, ==, 5, "b is now 5"); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_swap_ints_same, { |
||||
int a = 5; |
||||
|
||||
swap_ints(&a, &a); |
||||
|
||||
assert_int(a, ==, 5, "a is still 5"); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/swap_ints", test_swap_ints), |
||||
munit_test("/swap_ints_same", test_swap_ints_same), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("void-pointer", tests); |
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,7 @@
|
||||
void swap_strings(char **a, char **b) { |
||||
if (a == b) return; |
||||
|
||||
char *tmp = *a; |
||||
*a = *b; |
||||
*b = tmp; |
||||
} |
@ -0,0 +1 @@
|
||||
void swap_strings(char **a, char **b); |
@ -0,0 +1,37 @@
|
||||
#include <stddef.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "exercise.h" |
||||
#include "munit.h" |
||||
|
||||
munit_case(RUN, test_swap_str, { |
||||
char *a = "Hello"; |
||||
char *b = "Goodbye"; |
||||
|
||||
swap_strings(&a, &b); |
||||
|
||||
assert_string_equal(a, "Goodbye", "a is now 'Goodbye'"); |
||||
assert_string_equal(b, "Hello", "b is now 'Hello'"); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_swap_str_long, { |
||||
char *a = "terminal.shop"; |
||||
char *b = "ssh"; |
||||
|
||||
swap_strings(&a, &b); |
||||
|
||||
assert_string_equal(a, "ssh", "a is now 'ssh'"); |
||||
assert_string_equal(b, "terminal.shop", "b is now 'terminal.shop'"); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/swap_str", test_swap_str), |
||||
munit_test("/test_swap_str_long", test_swap_str_long), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("void-pointer", tests); |
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,15 @@
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "bootlib.h" |
||||
|
||||
void swap(void *vp1, void *vp2, size_t size) { |
||||
if (vp1 == vp2) return; |
||||
|
||||
void *tmp = boot_malloc(size); |
||||
if (tmp == NULL) return; |
||||
memcpy(tmp, vp1, size); |
||||
memcpy(vp1, vp2, size); |
||||
memcpy(vp2, tmp, size); |
||||
boot_free(tmp); |
||||
} |
@ -0,0 +1,3 @@
|
||||
#include <stdio.h> |
||||
|
||||
void swap(void *vp1, void *vp2, size_t size); |
@ -0,0 +1,60 @@
|
||||
#include "bootlib.h" |
||||
#include "munit.h" |
||||
|
||||
#include "exercise.h" |
||||
#include <stdint.h> |
||||
|
||||
typedef struct CoffeeShop { |
||||
uint64_t quality; |
||||
uint64_t taste; |
||||
uint64_t branding; |
||||
} coffee_shop_t; |
||||
|
||||
munit_case(RUN, test_generic_ints, { |
||||
int i1 = 1234; |
||||
int i2 = 5678; |
||||
|
||||
swap(&i1, &i2, sizeof(int)); |
||||
|
||||
assert_int(i1, ==, 5678, "i1 should be i2's original value"); |
||||
assert_int(i2, ==, 1234, "i2 should be i1's original value"); |
||||
assert_true(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(RUN, test_generic_strings, { |
||||
char *s1 = "dax"; |
||||
char *s2 = "adam"; |
||||
|
||||
swap(&s1, &s2, sizeof(char *)); |
||||
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_true(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_generic_structs, { |
||||
coffee_shop_t sbucks = {2, 3, 4}; |
||||
coffee_shop_t terminalshop = {10, 10, 10}; |
||||
|
||||
swap(&sbucks, &terminalshop, sizeof(coffee_shop_t)); |
||||
|
||||
assert_int(sbucks.quality, ==, 10, "sbucks.quality should be terminalshop.quality"); |
||||
assert_int(sbucks.taste, ==, 10, "sbucks.taste should be terminalshop.taste"); |
||||
assert_int(sbucks.branding, ==, 10, "sbucks.branding should be terminalshop.branding"); |
||||
|
||||
assert_int(terminalshop.quality, ==, 2, "terminalshop.quality should be sbucks.quality"); |
||||
assert_int(terminalshop.taste, ==, 3, "terminalshop.taste should be sbucks.taste"); |
||||
assert_int(terminalshop.branding, ==, 4, "terminalshop.branding should be sbucks.branding"); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/generic_ints", test_generic_ints), |
||||
munit_test("/generic_strings", test_generic_strings), |
||||
munit_test("/generic_struct", test_generic_structs), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("swap", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -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"); |
||||
|
||||
boot_free(s->data); |
||||
boot_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"); |
||||
|
||||
boot_free(s->data); |
||||
boot_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,19 @@
|
||||
#include <stdlib.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "snekstack.h" |
||||
|
||||
my_stack_t *stack_new(size_t capacity) |
||||
{ |
||||
my_stack_t *stack = (my_stack_t *)boot_malloc(sizeof(my_stack_t)); |
||||
if (stack == NULL) return NULL; |
||||
stack->count = 0; |
||||
stack->capacity = capacity; |
||||
stack->data = boot_malloc(sizeof(void*) * capacity); |
||||
if (stack->data == NULL) { |
||||
boot_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.
|
||||
boot_free(s->data); |
||||
boot_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.
|
||||
boot_free(s->data); |
||||
boot_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.
|
||||
boot_free(s->data); |
||||
boot_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,39 @@
|
||||
#include <assert.h> |
||||
#include <stddef.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "snekstack.h" |
||||
|
||||
void stack_push(my_stack_t *stack, void *obj) |
||||
{ |
||||
if (stack->count >= stack->capacity) { |
||||
void **data = boot_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 = boot_malloc(sizeof(my_stack_t)); |
||||
if (stack == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
stack->count = 0; |
||||
stack->capacity = capacity; |
||||
stack->data = boot_malloc(stack->capacity * sizeof(void *)); |
||||
if (stack->data == NULL) { |
||||
boot_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.
|
||||
boot_free(s->data); |
||||
boot_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.
|
||||
boot_free(s->data); |
||||
boot_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.
|
||||
boot_free(s->data); |
||||
boot_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.
|
||||
boot_free(s->data); |
||||
boot_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,47 @@
|
||||
#include <assert.h> |
||||
#include <stddef.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "bootlib.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 = boot_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 = boot_malloc(sizeof(my_stack_t)); |
||||
if (stack == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
stack->count = 0; |
||||
stack->capacity = capacity; |
||||
stack->data = boot_malloc(stack->capacity * sizeof(void *)); |
||||
if (stack->data == NULL) { |
||||
boot_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,60 @@
|
||||
#include <assert.h> |
||||
#include <stddef.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "snekstack.h" |
||||
|
||||
void stack_free(my_stack_t *stack) { |
||||
if (stack == NULL) return; |
||||
|
||||
if (stack->data != NULL) { |
||||
boot_free(stack->data); |
||||
stack->data = NULL; |
||||
} |
||||
|
||||
boot_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 = boot_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 = boot_malloc(sizeof(my_stack_t)); |
||||
if (stack == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
stack->count = 0; |
||||
stack->capacity = capacity; |
||||
stack->data = boot_malloc(stack->capacity * sizeof(void *)); |
||||
if (stack->data == NULL) { |
||||
boot_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); |
@ -0,0 +1,30 @@
|
||||
#include <stdlib.h> |
||||
|
||||
#include "munit.h" |
||||
#include "snekobject.h" |
||||
|
||||
munit_case(RUN, test_integer_constant, { |
||||
assert_int(INTEGER, ==, 0, "INTEGER is defined as 0"); |
||||
}); |
||||
|
||||
munit_case(RUN, test_integer_obj, { |
||||
snek_object_t *obj = malloc(sizeof(snek_object_t)); |
||||
obj->kind = INTEGER; |
||||
obj->data.v_int = 0; |
||||
assert_int(obj->kind, ==, INTEGER, "must be INTEGER type"); |
||||
assert_int(obj->data.v_int, ==, 0, "must equal zero"); |
||||
|
||||
free(obj); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/integer_constant", test_integer_constant), |
||||
munit_test("/integer_obj", test_integer_obj), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("object-integer-def", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,13 @@
|
||||
|
||||
typedef enum SnekObjectKind { |
||||
INTEGER, |
||||
} snek_object_kind_t; |
||||
|
||||
typedef union SnekObjectData { |
||||
int v_int; |
||||
} snek_object_data_t; |
||||
|
||||
typedef struct SnekObject { |
||||
snek_object_kind_t kind; |
||||
snek_object_data_t data; |
||||
} snek_object_t; |
@ -0,0 +1,40 @@
|
||||
#include "munit.h" |
||||
#include "snekobject.h" |
||||
|
||||
munit_case(RUN, test_positive, { |
||||
snek_object_t *int_object = new_snek_integer(42); |
||||
assert_int(int_object->data.v_int, ==, 42, "must allow positive numbers"); |
||||
|
||||
free(int_object); |
||||
}); |
||||
|
||||
munit_case(RUN, test_zero, { |
||||
snek_object_t *int_object = new_snek_integer(0); |
||||
|
||||
assert_int(int_object->kind, ==, INTEGER, "must be INTEGER type"); |
||||
assert_int(int_object->data.v_int, ==, 0, "must equal zero"); |
||||
|
||||
free(int_object); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_negative, { |
||||
snek_object_t *int_object = new_snek_integer(-5); |
||||
|
||||
assert_int(int_object->kind, ==, INTEGER, "must be INTEGER type"); |
||||
assert_int(int_object->data.v_int, ==, -5, "must allow negative numbers"); |
||||
|
||||
free(int_object); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/positive", test_positive), |
||||
munit_test("/zero", test_zero), |
||||
munit_test("/negative", test_negative), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("object-integer", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,11 @@
|
||||
#include <stdlib.h> |
||||
|
||||
#include "snekobject.h" |
||||
|
||||
snek_object_t *new_snek_integer(int value) { |
||||
snek_object_t *number = (snek_object_t *)malloc(sizeof(snek_object_t)); |
||||
if (number == NULL) return NULL; |
||||
number->kind = INTEGER; |
||||
number->data.v_int = value; |
||||
return number; |
||||
} |
@ -0,0 +1,14 @@
|
||||
typedef enum SnekObjectKind { |
||||
INTEGER, |
||||
} snek_object_kind_t; |
||||
|
||||
typedef union SnekObjectData { |
||||
int v_int; |
||||
} snek_object_data_t; |
||||
|
||||
typedef struct SnekObject { |
||||
snek_object_kind_t kind; |
||||
snek_object_data_t data; |
||||
} snek_object_t; |
||||
|
||||
snek_object_t *new_snek_integer(int value); |
@ -0,0 +1,46 @@
|
||||
#include <stdlib.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "munit.h" |
||||
#include "snekobject.h" |
||||
|
||||
munit_case(RUN, test_positive, { |
||||
snek_object_t *obj = new_snek_float(42); |
||||
assert_float(obj->data.v_float, ==, 42, "Must accept positive values"); |
||||
|
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_zero, { |
||||
snek_object_t *obj = new_snek_float(0.0); |
||||
|
||||
assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT"); |
||||
assert_float(obj->data.v_float, ==, 0.0, "Must accept 0.0"); |
||||
|
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_negative, { |
||||
snek_object_t *obj = new_snek_float(-5.0); |
||||
|
||||
assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT"); |
||||
assert_float(obj->data.v_float, ==, -5.0, "Must accept negative numbers"); |
||||
|
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/positive", test_positive), |
||||
munit_test("/zero", test_zero), |
||||
munit_test("/negative", test_negative), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("object-float", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,25 @@
|
||||
#include <stdlib.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "snekobject.h" |
||||
|
||||
snek_object_t *new_snek_float(float value) { |
||||
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) return NULL; |
||||
obj->kind = FLOAT; |
||||
obj->data.v_float = value; |
||||
return obj; |
||||
} |
||||
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_integer(int value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = INTEGER; |
||||
obj->data.v_int = value; |
||||
return obj; |
||||
} |
@ -0,0 +1,17 @@
|
||||
typedef enum SnekObjectKind { |
||||
INTEGER, |
||||
FLOAT, |
||||
} snek_object_kind_t; |
||||
|
||||
typedef union SnekObjectData { |
||||
int v_int; |
||||
float v_float; |
||||
} snek_object_data_t; |
||||
|
||||
typedef struct SnekObject { |
||||
snek_object_kind_t kind; |
||||
snek_object_data_t data; |
||||
} snek_object_t; |
||||
|
||||
snek_object_t *new_snek_integer(int value); |
||||
snek_object_t *new_snek_float(float value); |
@ -0,0 +1,45 @@
|
||||
#include <stdbool.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "munit.h" |
||||
#include "snekobject.h" |
||||
|
||||
munit_case(RUN, test_str_copied, { |
||||
char *input = "Hello, World!"; |
||||
snek_object_t *obj = new_snek_string(input); |
||||
|
||||
assert_int(obj->kind, ==, STRING, "Must be a string!"); |
||||
|
||||
// Should not have pointers be the same, otherwise we didn't copy the value.
|
||||
assert_ptr_not_equal( |
||||
obj->data.v_string, input, "You need to copy the string." |
||||
); |
||||
|
||||
// But should have the same data!
|
||||
// This way the object can free it's own memory later.
|
||||
assert_string_equal( |
||||
obj->data.v_string, input, "Should copy string correctly" |
||||
); |
||||
|
||||
// Should allocate memory for the string with null terminator.
|
||||
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.
|
||||
boot_free(obj->data.v_string); |
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/copies_value", test_str_copied), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("object-string", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,47 @@
|
||||
#include <stddef.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "snekobject.h" |
||||
|
||||
snek_object_t *new_snek_string(char *value) { |
||||
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) return NULL; |
||||
|
||||
size_t size = strlen(value); |
||||
char *str = (char *)boot_malloc(sizeof(char) * size + 1); |
||||
if (str == NULL) { |
||||
boot_free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
strcpy(str, value); |
||||
obj->kind = STRING; |
||||
obj->data.v_string = str; |
||||
return obj; |
||||
} |
||||
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_integer(int value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = INTEGER; |
||||
obj->data.v_int = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_float(float value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = FLOAT; |
||||
obj->data.v_float = value; |
||||
return obj; |
||||
} |
@ -0,0 +1,20 @@
|
||||
typedef enum SnekObjectKind { |
||||
INTEGER, |
||||
FLOAT, |
||||
STRING, |
||||
} snek_object_kind_t; |
||||
|
||||
typedef union SnekObjectData { |
||||
int v_int; |
||||
float v_float; |
||||
char* v_string; |
||||
} snek_object_data_t; |
||||
|
||||
typedef struct SnekObject { |
||||
snek_object_kind_t kind; |
||||
snek_object_data_t data; |
||||
} snek_object_t; |
||||
|
||||
snek_object_t *new_snek_integer(int value); |
||||
snek_object_t *new_snek_float(float value); |
||||
snek_object_t *new_snek_string(char *value); |
@ -0,0 +1,82 @@
|
||||
#include <stdlib.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "munit.h" |
||||
#include "snekobject.h" |
||||
|
||||
munit_case(RUN, test_returns_null, { |
||||
snek_object_t *vec = new_snek_vector3(NULL, NULL, NULL); |
||||
|
||||
assert_null(vec, "Should return null when input is null"); |
||||
|
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
|
||||
munit_case(RUN, test_vec_multiple_objects, { |
||||
snek_object_t *x = new_snek_integer(1); |
||||
snek_object_t *y = new_snek_integer(2); |
||||
snek_object_t *z = new_snek_integer(3); |
||||
snek_object_t *vec = new_snek_vector3(x, y, z); |
||||
|
||||
assert_ptr_not_null(vec, "should allocate a new object"); |
||||
|
||||
// Vectors should not copy objects, they get the reference to the objects.
|
||||
assert_ptr(x, ==, vec->data.v_vector3.x, "should reference x"); |
||||
assert_ptr(y, ==, vec->data.v_vector3.y, "should reference y"); |
||||
assert_ptr(z, ==, vec->data.v_vector3.z, "should reference z"); |
||||
|
||||
// Assert we have integer values correct
|
||||
assert_int(vec->data.v_vector3.x->data.v_int, ==, 1, "should have correct x"); |
||||
assert_int(vec->data.v_vector3.y->data.v_int, ==, 2, "should have correct y"); |
||||
assert_int(vec->data.v_vector3.z->data.v_int, ==, 3, "should have correct z"); |
||||
|
||||
// Free all of our objects.
|
||||
boot_free(x); |
||||
boot_free(y); |
||||
boot_free(z); |
||||
boot_free(vec); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_vec_same_object, { |
||||
snek_object_t *i = new_snek_integer(1); |
||||
snek_object_t *vec = new_snek_vector3(i, i, i); |
||||
|
||||
assert_ptr_not_null(vec, "should allocate a new object"); |
||||
|
||||
// Vectors should not copy objects, they get the reference to the objects.
|
||||
assert_ptr(i, ==, vec->data.v_vector3.x, "should reference x"); |
||||
assert_ptr(i, ==, vec->data.v_vector3.y, "should reference y"); |
||||
assert_ptr(i, ==, vec->data.v_vector3.z, "should reference z"); |
||||
|
||||
// Assert we have integer values correct
|
||||
assert_int(vec->data.v_vector3.x->data.v_int, ==, 1, "should have correct x"); |
||||
assert_int(vec->data.v_vector3.y->data.v_int, ==, 1, "should have correct y"); |
||||
assert_int(vec->data.v_vector3.z->data.v_int, ==, 1, "should have correct z"); |
||||
|
||||
i->data.v_int = 2; |
||||
|
||||
// Assert we have integer values correct, after update
|
||||
assert_int(vec->data.v_vector3.x->data.v_int, ==, 2, "should have correct x"); |
||||
assert_int(vec->data.v_vector3.y->data.v_int, ==, 2, "should have correct y"); |
||||
assert_int(vec->data.v_vector3.z->data.v_int, ==, 2, "should have correct z"); |
||||
|
||||
// Free all of our objects.
|
||||
boot_free(i); |
||||
boot_free(vec); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/returns_null", test_returns_null), |
||||
munit_test("/multiple_objects", test_vec_multiple_objects), |
||||
munit_test("/same_object", test_vec_same_object), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("object-vector", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,61 @@
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "snekobject.h" |
||||
|
||||
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; |
||||
|
||||
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) return NULL; |
||||
|
||||
obj->kind = VECTOR3; |
||||
obj->data.v_vector3 = (snek_vector_t){ .x = x, .y = y, .z = z }; |
||||
return obj; |
||||
} |
||||
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_integer(int value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = INTEGER; |
||||
obj->data.v_int = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_float(float value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = FLOAT; |
||||
obj->data.v_float = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_string(char *value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
int len = strlen(value); |
||||
char *dst = boot_malloc(len + 1); |
||||
if (dst == NULL) { |
||||
boot_free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
strcpy(dst, value); |
||||
|
||||
obj->kind = STRING; |
||||
obj->data.v_string = dst; |
||||
return obj; |
||||
} |
@ -0,0 +1,31 @@
|
||||
typedef struct SnekObject snek_object_t; |
||||
|
||||
typedef enum SnekObjectKind { |
||||
INTEGER, |
||||
FLOAT, |
||||
STRING, |
||||
VECTOR3, |
||||
} snek_object_kind_t; |
||||
|
||||
typedef struct SnekVector { |
||||
snek_object_t *x; |
||||
snek_object_t *y; |
||||
snek_object_t *z; |
||||
} snek_vector_t; |
||||
|
||||
typedef union SnekObjectData { |
||||
int v_int; |
||||
float v_float; |
||||
char* v_string; |
||||
snek_vector_t v_vector3; |
||||
} snek_object_data_t; |
||||
|
||||
typedef struct SnekObject { |
||||
snek_object_kind_t kind; |
||||
snek_object_data_t data; |
||||
} snek_object_t; |
||||
|
||||
snek_object_t *new_snek_integer(int value); |
||||
snek_object_t *new_snek_float(float value); |
||||
snek_object_t *new_snek_string(char *value); |
||||
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z); |
@ -0,0 +1,39 @@
|
||||
#include <stdlib.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "munit.h" |
||||
#include "snekobject.h" |
||||
|
||||
munit_case(RUN, test_create_empty_array, { |
||||
snek_object_t *obj = new_snek_array(2); |
||||
|
||||
assert_int(obj->kind, ==, ARRAY, "Must set type to ARRAY"); |
||||
assert_int(obj->data.v_array.size, ==, 2, "Must set size to 2"); |
||||
|
||||
boot_free(obj->data.v_array.elements); |
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_used_calloc, { |
||||
snek_object_t *obj = new_snek_array(2); |
||||
|
||||
assert_ptr_null(obj->data.v_array.elements[0], "Should use calloc"); |
||||
assert_ptr_null(obj->data.v_array.elements[1], "Should use calloc"); |
||||
|
||||
boot_free(obj->data.v_array.elements); |
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/empty", test_create_empty_array), |
||||
munit_test("/calloc", test_used_calloc), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("object-array", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,82 @@
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "snekobject.h" |
||||
|
||||
snek_object_t *new_snek_array(size_t size) { |
||||
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) return NULL; |
||||
|
||||
snek_object_t **arr = (snek_object_t **)boot_calloc(size, sizeof(snek_object_t *)); |
||||
if (arr == NULL) { |
||||
boot_free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = ARRAY; |
||||
obj->data.v_array = (snek_array_t){ .size = size, .elements = arr }; |
||||
return obj; |
||||
} |
||||
|
||||
// don't touch below this line
|
||||
|
||||
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; |
||||
} |
||||
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = VECTOR3; |
||||
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z}; |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_integer(int value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = INTEGER; |
||||
obj->data.v_int = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_float(float value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = FLOAT; |
||||
obj->data.v_float = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_string(char *value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
int len = strlen(value); |
||||
char *dst = boot_malloc(len + 1); |
||||
if (dst == NULL) { |
||||
boot_free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
strcpy(dst, value); |
||||
|
||||
obj->kind = STRING; |
||||
obj->data.v_string = dst; |
||||
return obj; |
||||
} |
@ -0,0 +1,41 @@
|
||||
#include <stddef.h> |
||||
|
||||
typedef struct SnekObject snek_object_t; |
||||
|
||||
typedef enum SnekObjectKind { |
||||
INTEGER, |
||||
FLOAT, |
||||
STRING, |
||||
VECTOR3, |
||||
ARRAY, |
||||
} snek_object_kind_t; |
||||
|
||||
typedef struct SnekVector { |
||||
snek_object_t *x; |
||||
snek_object_t *y; |
||||
snek_object_t *z; |
||||
} snek_vector_t; |
||||
|
||||
typedef struct SnekArray { |
||||
size_t size; |
||||
snek_object_t **elements; |
||||
} snek_array_t; |
||||
|
||||
typedef union SnekObjectData { |
||||
int v_int; |
||||
float v_float; |
||||
char* v_string; |
||||
snek_vector_t v_vector3; |
||||
snek_array_t v_array; |
||||
} snek_object_data_t; |
||||
|
||||
typedef struct SnekObject { |
||||
snek_object_kind_t kind; |
||||
snek_object_data_t data; |
||||
} snek_object_t; |
||||
|
||||
snek_object_t *new_snek_integer(int value); |
||||
snek_object_t *new_snek_float(float value); |
||||
snek_object_t *new_snek_string(char *value); |
||||
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z); |
||||
snek_object_t *new_snek_array(size_t size); |
@ -0,0 +1,84 @@
|
||||
#include <stdlib.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "munit.h" |
||||
#include "snekobject.h" |
||||
|
||||
munit_case(RUN, test_array, { |
||||
// Create an array
|
||||
snek_object_t *obj = new_snek_array(2); |
||||
|
||||
// Create some objects to put in the array
|
||||
// Can store objects, even though they have different types (just like Python)
|
||||
snek_object_t *first = new_snek_string("First"); |
||||
snek_object_t *second = new_snek_integer(3); |
||||
|
||||
assert(snek_array_set(obj, 0, first)); |
||||
assert(snek_array_set(obj, 1, second)); |
||||
|
||||
snek_object_t *retrieved_first = snek_array_get(obj, 0); |
||||
assert_not_null(retrieved_first, "Should find the first object"); |
||||
assert_int(retrieved_first->kind, ==, STRING, "Should be a string"); |
||||
assert_ptr(first, ==, retrieved_first, "Should be the same object"); |
||||
|
||||
snek_object_t *retrieved_second = snek_array_get(obj, 1); |
||||
assert_not_null(retrieved_second, "Should find the second object"); |
||||
assert_int(retrieved_second->kind, ==, INTEGER, "Should be a integer"); |
||||
assert_ptr(second, ==, retrieved_second, "Should be the same object"); |
||||
|
||||
boot_free(first->data.v_string); |
||||
boot_free(first); |
||||
boot_free(second); |
||||
boot_free(obj->data.v_array.elements); |
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(RUN, test_set_outside_bounds, { |
||||
// Create an array
|
||||
snek_object_t *obj = new_snek_array(2); |
||||
|
||||
snek_object_t *outside = new_snek_string("First"); |
||||
|
||||
// Inside of bound
|
||||
assert(snek_array_set(obj, 1, outside)); |
||||
|
||||
// Outside of bound
|
||||
assert_false(snek_array_set(obj, 100, outside)); |
||||
|
||||
// Free memory
|
||||
boot_free(outside->data.v_string); |
||||
boot_free(outside); |
||||
boot_free(obj->data.v_array.elements); |
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_get_outside_bounds, { |
||||
// Create an array
|
||||
snek_object_t *obj = new_snek_array(1); |
||||
snek_object_t *first = new_snek_string("First"); |
||||
assert(snek_array_set(obj, 0, first)); |
||||
|
||||
// Outside of bound
|
||||
assert_null(snek_array_get(obj, 1), "Should not access outside the array"); |
||||
|
||||
boot_free(first->data.v_string); |
||||
boot_free(first); |
||||
boot_free(obj->data.v_array.elements); |
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/set_and_get", test_array), |
||||
munit_test("/set_outside", test_set_outside_bounds), |
||||
munit_test("/get_outside", test_get_outside_bounds), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("object-array", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,102 @@
|
||||
#include <stdbool.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "bootlib.h" |
||||
#include "snekobject.h" |
||||
|
||||
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value) { |
||||
if (snek_obj == NULL || value == NULL) return false; |
||||
if (snek_obj->kind != ARRAY) return false; |
||||
if (snek_obj->data.v_array.size <= index) return false; |
||||
|
||||
snek_obj->data.v_array.elements[index] = value; |
||||
return true; |
||||
} |
||||
|
||||
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index) { |
||||
if (snek_obj == NULL) return NULL; |
||||
if (snek_obj->kind != ARRAY) return NULL; |
||||
if (snek_obj->data.v_array.size <= index) return NULL; |
||||
|
||||
return snek_obj->data.v_array.elements[index]; |
||||
} |
||||
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_array(size_t size) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *)); |
||||
if (elements == NULL) { |
||||
boot_free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = ARRAY; |
||||
obj->data.v_array = (snek_array_t){.size = size, .elements = elements}; |
||||
return obj; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = VECTOR3; |
||||
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z}; |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_integer(int value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = INTEGER; |
||||
obj->data.v_int = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_float(float value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = FLOAT; |
||||
obj->data.v_float = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_string(char *value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
int len = strlen(value); |
||||
char *dst = boot_malloc(len + 1); |
||||
if (dst == NULL) { |
||||
boot_free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
strcpy(dst, value); |
||||
|
||||
obj->kind = STRING; |
||||
obj->data.v_string = dst; |
||||
return obj; |
||||
} |
@ -0,0 +1,45 @@
|
||||
#include <stdbool.h> |
||||
#include <stddef.h> |
||||
|
||||
typedef struct SnekObject snek_object_t; |
||||
|
||||
typedef enum SnekObjectKind { |
||||
INTEGER, |
||||
FLOAT, |
||||
STRING, |
||||
VECTOR3, |
||||
ARRAY, |
||||
} snek_object_kind_t; |
||||
|
||||
typedef struct SnekVector { |
||||
snek_object_t *x; |
||||
snek_object_t *y; |
||||
snek_object_t *z; |
||||
} snek_vector_t; |
||||
|
||||
typedef struct SnekArray { |
||||
size_t size; |
||||
snek_object_t **elements; |
||||
} snek_array_t; |
||||
|
||||
typedef union SnekObjectData { |
||||
int v_int; |
||||
float v_float; |
||||
char* v_string; |
||||
snek_vector_t v_vector3; |
||||
snek_array_t v_array; |
||||
} snek_object_data_t; |
||||
|
||||
typedef struct SnekObject { |
||||
snek_object_kind_t kind; |
||||
snek_object_data_t data; |
||||
} snek_object_t; |
||||
|
||||
snek_object_t *new_snek_integer(int value); |
||||
snek_object_t *new_snek_float(float value); |
||||
snek_object_t *new_snek_string(char *value); |
||||
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z); |
||||
|
||||
snek_object_t *new_snek_array(size_t size); |
||||
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value); |
||||
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index); |
@ -0,0 +1,75 @@
|
||||
#include "bootlib.h" |
||||
#include "munit.h" |
||||
#include "snekobject.h" |
||||
|
||||
munit_case(RUN, test_integer, { |
||||
snek_object_t *obj = new_snek_integer(42); |
||||
assert_int(snek_length(obj), ==, 1, "Integers are length 1"); |
||||
|
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(RUN, test_float, { |
||||
snek_object_t *obj = new_snek_float(3.14); |
||||
assert_int(snek_length(obj), ==, 1, "Floats are length 1"); |
||||
|
||||
boot_free(obj); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(RUN, test_string, { |
||||
snek_object_t *shorter = new_snek_string("hello"); |
||||
assert_int(snek_length(shorter), ==, 5, "Should return based on input"); |
||||
|
||||
snek_object_t *longer = new_snek_string("hello, world"); |
||||
assert_int( |
||||
snek_length(longer), ==, strlen("hello, world"), "Should use strlen" |
||||
); |
||||
|
||||
boot_free(shorter->data.v_string); |
||||
boot_free(shorter); |
||||
boot_free(longer->data.v_string); |
||||
boot_free(longer); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_vector3, { |
||||
snek_object_t *i = new_snek_integer(1); |
||||
snek_object_t *vec = new_snek_vector3(i, i, i); |
||||
assert_int(snek_length(vec), ==, 3, "Vec3 always has length 3"); |
||||
|
||||
boot_free(i); |
||||
boot_free(vec); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_array, { |
||||
snek_object_t *i = new_snek_integer(1); |
||||
snek_object_t *arr = new_snek_array(4); |
||||
assert(snek_array_set(arr, 0, i)); |
||||
assert(snek_array_set(arr, 1, i)); |
||||
assert(snek_array_set(arr, 2, i)); |
||||
|
||||
assert_int(snek_length(arr), ==, 4, "Length of array should be its size"); |
||||
|
||||
boot_free(i); |
||||
boot_free(arr->data.v_array.elements); |
||||
boot_free(arr); |
||||
assert(boot_all_freed()); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("/integer", test_integer), |
||||
munit_test("/float", test_float), |
||||
munit_test("/string", test_string), |
||||
munit_test("/vector", test_vector3), |
||||
munit_test("/array", test_array), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("object-length", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,128 @@
|
||||
#include "bootlib.h" |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "snekobject.h" |
||||
|
||||
int snek_length(snek_object_t *obj) { |
||||
if (obj == NULL) return -1; |
||||
if (obj->kind == INTEGER || obj->kind == FLOAT) return 1; |
||||
if (obj->kind == STRING) return strlen(obj->data.v_string); |
||||
if (obj->kind == VECTOR3) return 3; |
||||
if (obj->kind == ARRAY) return obj->data.v_array.size; |
||||
return -1; |
||||
} |
||||
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_array(size_t size) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *)); |
||||
if (elements == NULL) { |
||||
boot_free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = ARRAY; |
||||
obj->data.v_array = (snek_array_t){.size = size, .elements = elements}; |
||||
return obj; |
||||
} |
||||
|
||||
bool snek_array_set(snek_object_t *array, size_t index, snek_object_t *value) { |
||||
if (array == NULL || value == NULL) { |
||||
return false; |
||||
} |
||||
|
||||
if (array->kind != ARRAY) { |
||||
return false; |
||||
} |
||||
|
||||
if (index >= array->data.v_array.size) { |
||||
return false; |
||||
} |
||||
|
||||
// Set the value directly now (already checked size constraint)
|
||||
array->data.v_array.elements[index] = value; |
||||
return true; |
||||
} |
||||
|
||||
snek_object_t *snek_array_get(snek_object_t *array, size_t index) { |
||||
if (array == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
if (array->kind != ARRAY) { |
||||
return NULL; |
||||
} |
||||
|
||||
if (index >= array->data.v_array.size) { |
||||
return NULL; |
||||
} |
||||
|
||||
// Get the value directly now (already checked size constraint)
|
||||
return array->data.v_array.elements[index]; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = VECTOR3; |
||||
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z}; |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_integer(int value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = INTEGER; |
||||
obj->data.v_int = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_float(float value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = FLOAT; |
||||
obj->data.v_float = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_string(char *value) { |
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
int len = strlen(value); |
||||
char *dst = boot_malloc(len + 1); |
||||
if (dst == NULL) { |
||||
boot_free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
strcpy(dst, value); |
||||
|
||||
obj->kind = STRING; |
||||
obj->data.v_string = dst; |
||||
return obj; |
||||
} |
@ -0,0 +1,46 @@
|
||||
#include <stdbool.h> |
||||
#include <stddef.h> |
||||
|
||||
typedef struct SnekObject snek_object_t; |
||||
|
||||
typedef enum SnekObjectKind { |
||||
INTEGER, |
||||
FLOAT, |
||||
STRING, |
||||
VECTOR3, |
||||
ARRAY, |
||||
} snek_object_kind_t; |
||||
|
||||
typedef struct SnekVector { |
||||
snek_object_t *x; |
||||
snek_object_t *y; |
||||
snek_object_t *z; |
||||
} snek_vector_t; |
||||
|
||||
typedef struct SnekArray { |
||||
size_t size; |
||||
snek_object_t **elements; |
||||
} snek_array_t; |
||||
|
||||
typedef union SnekObjectData { |
||||
int v_int; |
||||
float v_float; |
||||
char* v_string; |
||||
snek_vector_t v_vector3; |
||||
snek_array_t v_array; |
||||
} snek_object_data_t; |
||||
|
||||
typedef struct SnekObject { |
||||
snek_object_kind_t kind; |
||||
snek_object_data_t data; |
||||
} snek_object_t; |
||||
|
||||
snek_object_t *new_snek_integer(int value); |
||||
snek_object_t *new_snek_float(float value); |
||||
snek_object_t *new_snek_string(char *value); |
||||
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z); |
||||
|
||||
snek_object_t *new_snek_array(size_t size); |
||||
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value); |
||||
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index); |
||||
int snek_length(snek_object_t *obj); |
@ -0,0 +1,3 @@
|
||||
|
||||
// Q: Which language makes use of a garbage collector (automatic memory management)?
|
||||
// A: Go
|
@ -0,0 +1,30 @@
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
// #include "bootlib.h"
|
||||
#include "munit.h" |
||||
#include "snekobject.h" |
||||
|
||||
munit_case(RUN, test_int_has_refcount, { |
||||
snek_object_t *obj = new_snek_integer(10); |
||||
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation"); |
||||
free(obj); |
||||
}); |
||||
|
||||
munit_case(SUBMIT, test_float_has_refcount, { |
||||
snek_object_t *obj = new_snek_float(42.0); |
||||
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation"); |
||||
free(obj); |
||||
}); |
||||
|
||||
int main() { |
||||
MunitTest tests[] = { |
||||
munit_test("test_int_has_refcount", test_int_has_refcount), |
||||
munit_test("test_float_has_refcount", test_float_has_refcount), |
||||
munit_null_test, |
||||
}; |
||||
|
||||
MunitSuite suite = munit_suite("refcount", tests); |
||||
|
||||
return munit_suite_main(&suite, NULL, 0, NULL); |
||||
} |
@ -0,0 +1,91 @@
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "snekobject.h" |
||||
|
||||
snek_object_t *_new_snek_object() { |
||||
snek_object_t *obj = (snek_object_t *)calloc(1, sizeof(snek_object_t)); |
||||
if (obj == NULL) return NULL; |
||||
obj->refcount = 1; |
||||
return obj; |
||||
} |
||||
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_array(size_t size) { |
||||
snek_object_t *obj = _new_snek_object(); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *)); |
||||
if (elements == NULL) { |
||||
free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = ARRAY; |
||||
obj->data.v_array = (snek_array_t){.size = size, .elements = elements}; |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
snek_object_t *obj = _new_snek_object(); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = VECTOR3; |
||||
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z}; |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_integer(int value) { |
||||
snek_object_t *obj = _new_snek_object(); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = INTEGER; |
||||
obj->data.v_int = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_float(float value) { |
||||
snek_object_t *obj = _new_snek_object(); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
obj->kind = FLOAT; |
||||
obj->data.v_float = value; |
||||
return obj; |
||||
} |
||||
|
||||
snek_object_t *new_snek_string(char *value) { |
||||
snek_object_t *obj = _new_snek_object(); |
||||
if (obj == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
int len = strlen(value); |
||||
char *dst = malloc(len + 1); |
||||
if (dst == NULL) { |
||||
free(obj); |
||||
return NULL; |
||||
} |
||||
|
||||
strcpy(dst, value); |
||||
|
||||
obj->kind = STRING; |
||||
obj->data.v_string = dst; |
||||
return obj; |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue