Compare commits
7
Commits
215c1849f1
...
780996458b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
780996458b | ||
|
|
ba0d496a3c | ||
|
|
0f94ca2909 | ||
|
|
ec77cf9a1d | ||
|
|
8d203036f7 | ||
|
|
4e6cd60609 | ||
|
|
7e909b73fb |
@@ -5,3 +5,5 @@
|
||||
build/
|
||||
|
||||
# Files
|
||||
|
||||
.DS_Store
|
||||
|
||||
@@ -33,6 +33,7 @@ foreach(LESSON ${LESSONS})
|
||||
if(NOT LESSON_SOURCES)
|
||||
continue()
|
||||
endif()
|
||||
list(APPEND LESSON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/bootlib.c)
|
||||
|
||||
# Get last directory name of the path to use as exe
|
||||
get_filename_component(EXE_NAME ${LESSON} NAME)
|
||||
|
||||
+388
@@ -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
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 311 KiB |
@@ -4,7 +4,7 @@
|
||||
|
||||
char* get_full_greeting(char* greeting, char* name, int size)
|
||||
{
|
||||
char full_greeting[100];
|
||||
snprintf(full_greeting, 100, "%s %s", greeting, name);
|
||||
char *full_greeting = (char*)malloc(size * sizeof(char));
|
||||
snprintf(full_greeting, size, "%s %s", greeting, name);
|
||||
return full_greeting;
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user