From adb04c233665269c5cbd670dc43d01048b03e1b5 Mon Sep 17 00:00:00 2001 From: EimaMei Date: Sun, 4 Jun 2023 12:08:44 +0300 Subject: [PATCH 01/17] this update took away 10 years of my life --- .gitignore | 3 +- Makefile | 4 +- example.c | 394 --------------------------- examples/array.c | 60 ++++ examples/benchmarking.c | 20 ++ examples/file.c | 87 ++++++ examples/optional.c | 20 ++ examples/pair.c | 27 ++ examples/str.c | 116 ++++++++ examples/thread.c | 63 +++++ sili.h | 591 ++++++++++++++++++++++++++-------------- 11 files changed, 791 insertions(+), 594 deletions(-) delete mode 100644 example.c create mode 100644 examples/array.c create mode 100644 examples/benchmarking.c create mode 100644 examples/file.c create mode 100644 examples/optional.c create mode 100644 examples/pair.c create mode 100644 examples/str.c create mode 100644 examples/thread.c diff --git a/.gitignore b/.gitignore index eb6833f..ba9b875 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ src/ *.7z *.zip *.hide -*.S \ No newline at end of file +*.S +main.c \ No newline at end of file diff --git a/Makefile b/Makefile index 869d3b8..1ad8c50 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ OUTPUT = build NAME = test EXE = $(OUTPUT)/$(NAME) -SRC = example.c -FLAGS = -O0 -std=c99 -Wall -Wextra -Wpedantic +SRC = main.c +FLAGS = -O0 -g -std=c99 -Wall -Wextra -Wpedantic -DSI_MEMORY_LOGGING LIBS = INCLUDE = -I"." diff --git a/example.c b/example.c deleted file mode 100644 index 20fa173..0000000 --- a/example.c +++ /dev/null @@ -1,394 +0,0 @@ -#define SI_IMPLEMENTATION 1 -#include -#include - -#define EXAMPLE_SI_ENABLE_ALL 1 - -#define EXAMPLE_SI_STRING 0 -#define EXAMPLE_SI_ARRAY 0 -#define EXAMPLE_SI_PAIR 0 -#define EXAMPLE_SI_FILE 0 -#define EXAMPLE_SI_OPTIONAL 0 -#define EXAMPLE_SI_THREAD 0 -#define EXAMPLE_SI_PERFORMANCE 0 - -#if EXAMPLE_SI_ENABLE_ALL == 1 - #undef EXAMPLE_SI_STRING - #undef EXAMPLE_SI_ARRAY - #undef EXAMPLE_SI_PAIR - #undef EXAMPLE_SI_FILE - #undef EXAMPLE_SI_OPTIONAL - #undef EXAMPLE_SI_THREAD - #undef EXAMPLE_SI_PERFORMANCE - - #define EXAMPLE_SI_STRING 1 - #define EXAMPLE_SI_ARRAY 1 - #define EXAMPLE_SI_PAIR 1 - #define EXAMPLE_SI_FILE 1 - #define EXAMPLE_SI_OPTIONAL 1 - #define EXAMPLE_SI_THREAD 1 - #define EXAMPLE_SI_PERFORMANCE 1 -#endif - -#if EXAMPLE_SI_OPTIONAL == 1 - siOptional(char*) create(bool value) { - return (value ? si_optional_make((char*)"Godzilla") : SI_OPTIONAL_NULL); - } -#endif - -#if EXAMPLE_SI_THREAD == 1 - rawptr thread_test(bool* arg) { - bool loop = *arg; - i16 count = SI_INT16_MIN; - - if (loop) { - printf("We'll increment 'count' from %d to %d:\n", SI_INT16_MIN, SI_INT16_MAX); - si_sleep(2000); - while (count < SI_INT16_MAX) { - count += 1; - printf("%i\n", count); - } - } - else { - printf("'arg' equals to 'false', so I'll just do nothing and wait for like 3 seconds.\n"); - si_sleep(3000); - printf("...and we're done! Exiting the thread now.\n"); - } - - typeof(count)* res = malloc(sizeof(count)); - SI_ASSERT_NOT_NULL(res); - *res = count; - - return res; - } -#endif - -#if EXAMPLE_SI_PERFORMANCE == 1 - void performance_test(void) { - isize i; - for (i = 0; i < SI_UINT16_MAX; i++); /* NOTE(EimaMei): Should strain the CPU a little. */ - } -#endif - - -int main(void) { - #if EXAMPLE_SI_STRING == 1 - /* Example 1.0: General string usage */ - { - printf("==============\nExample 1.0:\n"); - - siString str = si_string_make("Labas, Pasauli!"); - printf("str: %s\n", str); - - si_string_append(&str, " Lithuanian, more like Russian amirite."); - printf("str: %s\n", str); - - char front = si_string_front(str); - char back = si_string_back(str); - usize length = si_string_len(str); - printf("front: '%c', back: '%c', len: '%zd'\n", front, back, length); - - si_string_set(&str, "Different sentence"); - printf("str: %s\n", str); - - si_string_push_back(&str, '.'); - printf("str: %s\n", str); - - siString str2 = si_string_copy(str); - bool result = si_strings_are_equal(str, str2); - printf("(\"%s\" == \"%s\") returns a '%s' boolean\n", str, str2, (result ? "true" : "false")); - - isize pos = si_string_find(str, "sentence"); - printf("The word 'sentence' was found at position '%zd' (Starting with the letter '%c')\n", pos, str[pos]); - - pos = si_string_find(str, "random"); - printf("However, the word 'random' was not found, thus 'pos' equals to %zd\n", pos); - - si_string_replace(&str, "Different", "Completely new"); - printf("str: %s\n", str); - - si_string_replace(&str2, "Different", "The same"); - printf("str2: %s\n", str2); - - si_string_trim(&str, "sentence."); - printf("str: %s\n", str); - - si_string_clear(&str); - printf("Length of str: %zd\n", si_string_len(str)); - - - si_string_set(&str2, "one.two.three.four.five"); - printf("Current str2: %s\n", str2); - - siArray(siString) list = si_string_split(str2, "."); - usize i; - for (i = 0; i < si_array_len(list); i++) { - printf("\tElement %zd: '%s'\n", i, list[i]); - } - - si_string_free(str); - si_string_free(str2); - } - - /* Example 1.1: int conversions, utilisation of 'char' functions. */ - { - printf("==============\n\n==============\nExample 1.1:\n"); - - /* Int stuff: */ - siString str = si_string_make(si_i64_to_cstr(-342)); - printf("str: \"%s\"\n", str); - - isize num = si_cstr_to_u64("9300"); - printf("num: %zd\n\n", num); - - - /* Join, upper, lower, title, capitalize */ - si_string_set(&str, "/home"); - printf("Original str: \"%s\"\n", str); - - si_string_join(&str, "random.txt", "/"); - printf("Joined str: \"%s\"\n", str); - - si_string_upper(&str); - printf("Upper str: \"%s\"\n", str); - - si_string_set(&str, "I'VE COME TO MAKE AN ANNOUNCEMENT"); - printf("Original str: \"%s\"\n", str); - - si_string_lower(&str); - printf("Lower str: \"%s\"\n", str); - - si_string_title(&str); - printf("Titled str: \"%s\"\n", str); - - si_string_capitalize(&str); - printf("Capitalized str: \"%s\"\n", str); - } - - /* Example 1.2: Other. */ - { - printf("==============\n\n==============\nExample 1.2:\n"); - - siString str = si_string_make("\t dnuora gniliart "); - printf("Before: '%s' (len: '%zd')\n", str, si_string_len(str)); - - si_string_strip(&str); - printf("After: '%s' (len: '%zd')\n", str, si_string_len(str)); - - si_string_reverse(&str); - printf("'str' in reverse: '%s'\n", str); - - si_string_free(str); - } - #endif - - #if EXAMPLE_SI_ARRAY == 1 - /* Example 2.0: General array usage. */ - { - printf("==============\n\n==============\nExample 2.0:\n"); - - siArray(i32) array = si_array_make((i32[]){3, 234, 2, 4, 294, 234, 23}); - - usize count = 0; - foreach (num, array) { - printf("Element %zd: %i\n", count, *num); - count++; - } - - isize find_pos = si_array_find(array, 234); - isize rfind_pos = si_array_rfind(array, 234); - printf("The 1st number '234' is at 'array[%zd]', while the 2nd one is at 'array[%zd]'\n", find_pos, rfind_pos); - - usize previous_len = si_array_len(array); - si_array_append(&array, SI_INT32_MAX); /* si_array_push_back does the same thing. */ - - i32 front = si_any_get(si_array_front(array), i32); - i32 back = si_any_get(si_array_back(array), i32); - printf("We now have %zd elements instead of %zd. The front value is '%i', while the back value is '%X'\n", si_array_len(array), previous_len, front, back); - - isize element_pos = si_array_replace(&array, 4, SI_INT32_MIN); - printf("The element at position '%zd' was replaced with: %X\n", element_pos, array[element_pos]); - - siArray(i32) copy = si_array_copy(array); - bool res = si_arrays_are_equal(array, copy); - - printf("Arrays 'array' and 'copy' are %s\n", (res ? "the same" : "NOT the same")); - - si_array_free(array); - si_array_free(copy); - } - /* Example 2.1: Other usages. */ - { - printf("==============\n\n==============\nExample 2.1:\n"); - siArray(i32) array = si_array_make((i32[]){1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); - - printf("Array in regular order: "); - foreach (num, array) { - printf("%i ", *num); - } - printf("\n"); - - si_array_reverse(&array); - printf("Array in reverse order: "); - - foreach (num, array) { - printf("%i ", *num); - } - printf("\n"); - } - #endif - - #if EXAMPLE_SI_PAIR == 1 - /* Example 3.0: siPair (based on https://cplusplus.com/reference/utility/pair/pair/) */ - { - printf("==============\n\n==============\nExample 3.0:\n"); - - siPair(siString, f64) product1; - siPair(siString, f64) product2 = si_pair_make(si_string_make("tomatoes"), 2.30); - siPair(siString, f64) product3 = si_pair_copy(product2); - siPair(siString, f64) product4 = {si_string_make("bread"), 599.99}; - - product1.first = si_string_make("shoes"); - product1.second = 39.90; - - printf("The price of %s is $%f\n", product1.first, product1.second); - printf("The price of %s is $%f\n", product2.first, product2.second); - printf("The price of %s is $%f\n", product3.first, product3.second); - printf("The price of %s is $%f\n", product4.first, product4.second); - - si_string_free(product1.first); - si_string_free(product2.first); - si_string_free(product4.first); - } - #endif - - #if EXAMPLE_SI_FILE == 1 - /* Example 4.0: siFile. */ - { - printf("==============\n\n==============\nExample 4.0:\n"); - - siFile file = si_file_open("example.c"); /* If the file doesn't exist or fails to open any other way, then we will get an assertion error. */ - printf("About 'example.c':\n\tFull path - '%s'\n\tSize - '%zu' bytes\n", file.path, file.size); - - siFile new_file = si_file_create("random.txt"); - si_file_write(&new_file, "A silly file\nwith a sili newline."); - printf("About 'random.txt':\n\tFull path - '%s'\n\tSize - '%zu' bytes\n", file.path, file.size); - - siString content = si_file_read(new_file); - printf("\tContent - '%s' (len: '%zd')\n", content, si_string_len(content)); - - siArray(siString) file_lines = si_file_readlines(file); - printf("Contents of '%s' ('%zd' lines in total):\n", si_path_base_name(file.path), si_array_len(file_lines)); - - usize i; - for (i = 0; i < si_array_len(file_lines); i++) { - si_string_strip(&file_lines[i]); - printf("\tLine %zd: '%s'\n", i, file_lines[i]); - } - - si_file_write_at_line(&new_file, "but now we have a changed line\n", 1); - siArray(siString) new_file_lines = si_file_readlines(new_file); - printf("Contents of '%s' ('%zd' lines in total):\n", si_path_base_name(new_file.path), si_array_len(new_file_lines)); - - for (i = 0; i < si_array_len(new_file_lines); i++) { - si_string_strip(&new_file_lines[i]); - printf("\tLine %zd: '%s'\n", i, new_file_lines[i]); - } - - si_string_free(content); - - si_array_free(file_lines); - si_array_free(new_file_lines); - - si_file_close(file); - si_file_close(new_file); - } - /* Example 4.1: 'si_path' functions. */ - { - printf("==============\n\n==============\nExample 4.1:\n"); - - bool exist = si_path_exists("example.c"); - printf("File 'example.c' %s\n", (exist ? "DOES exist" : "DOESN'T exist")); - - exist = si_path_exists("random.txt"); - if (!exist) { - printf("Since 'random.txt' doesn't exist, we'll just create one\n"); - - siFile file = si_file_open_mode("random.txt", SI_FILE_MODE_CREATE); - si_file_write(&file, "Creating files is too easy tbh."); - si_file_close(file); - } - - bool res = si_path_copy("random.txt", "random-2.txt"); - printf("Does 'random-2.txt' exist: '%zd' (res: '%zd')\n", si_path_exists("random-2.txt"), res); - - res = si_path_move("random.txt", "renamed.txt"); - printf("Does 'random.txt' exist: '%zd', but 'renamed.txt' outputs a '%zd' (res: '%zd')\n", si_path_exists("random.txt"), si_path_exists("renamed.txt"), res); - - const char* path = "example.c"; - siString full_path = si_path_get_fullname(path); - printf("Information about '%s':\n\tBase name - '%s'\n\tExtension - '%s'\n\tFull path - '%s'\n\tIs relative: %zd\n", path, si_path_base_name(path), si_path_extension(path), full_path, si_path_is_relative(path)); - - res = si_path_remove("random-2.txt"); - printf("Does 'random-2.txt' exist: '%zd' (res: '%zd')\n", si_path_exists("random-2.txt"), res); - - res = si_path_remove("renamed.txt"); - printf("Does 'renamed.txt' exist: '%zd' (res: '%zd')\n", si_path_exists("renamed.txt"), res); - - si_string_free(full_path); - } - - #endif - - #if EXAMPLE_SI_OPTIONAL == 1 - /* Example 5.0: siOptional (based on https://en.cppreference.com/w/cpp/utility/optional). */ - { - printf("==============\n\n==============\nExample 5.0:\n"); - - printf("create(false) returned '%s'\n", si_optional_if_no_value(create(false), (char*)"empty")); - - siOptional(char*) str = create(true); - printf("create2(true) returned '%s'\n", si_any_get(str.value, char*)); - } - #endif - - #if EXAMPLE_SI_THREAD == 1 - siThread thread = si_thread_create(siFunc(thread_test), &(bool){false}); - si_thread_start(&thread); - - while (thread.is_running) { - printf("Even though 'thread' is currently sleeping, it's still running this exact second!\n"); - si_sleep(1000); - } - printf("That loop returned a '%i'. Now we'll re-run the loop with the argument being 'true' instead.\n", *((i16*)thread.return_value)); - free(thread.return_value); - si_sleep(2000); - - thread.arg = &(bool){true}; - si_thread_start(&thread); - si_thread_join(&thread); /* Now we have to wait... */ - - printf("That loop NOW returned a '%i'.\n", *((i16*)thread.return_value)); - free(thread.return_value); - si_sleep(2000); - - #if !defined(SI_SYSTEM_WINDOWS) - si_thread_start(&thread); - si_sleep(2500); - si_thread_cancel(&thread); - printf("Decided to kill it 2.5 seconds later.\n"); - #endif - #endif - - #if EXAMPLE_SI_PERFORMANCE == 1 - - printf("Running 'performance_test()' 30000 times. Lets see how long it takes to execute that many times...\n"); - si_performance_run_per_loop(30000, performance_test()); - - printf("Now lets see how many times 'performance_test()' can be executed in 5 seconds...\n"); - si_performance_executes_per_ms(5000, performance_test()); - - #endif - - return 0; -} diff --git a/examples/array.c b/examples/array.c new file mode 100644 index 0000000..ae30114 --- /dev/null +++ b/examples/array.c @@ -0,0 +1,60 @@ +#define SI_IMPLEMENTATION 1 +#include + + +void example_2_0(void) { + printf("==============\n\n==============\nExample 2.0:\n"); + + siArray(i32) array = si_array_make((i32[]){3, 234, 2, 4, 294, 234, 23}); + + foreach (num, array) { + printf("Element %zd: %i\n", (num - array), *num); + } + + isize find_pos = si_array_find(array, 234); + isize rfind_pos = si_array_rfind(array, 234); + printf("The 1st number '234' is at 'array[%zd]', while the 2nd one is at 'array[%zd]'\n", find_pos, rfind_pos); + + usize previous_len = si_array_len(array); + si_array_append(&array, SI_INT32_MAX); /* si_array_push_back does the same thing. */ + + i32 front = si_any_get(si_array_front(array), i32); + i32 back = si_any_get(si_array_back(array), i32); + printf("We now have %zd elements instead of %zd. The front value is '%i', while the back value is '%X'\n", si_array_len(array), previous_len, front, back); + + isize element_pos = si_array_replace(&array, 4, SI_INT32_MIN); + printf("The element at position '%zd' was replaced with: %X\n", element_pos, array[element_pos]); + + siArray(i32) copy = si_array_copy(array); + bool res = si_arrays_are_equal(array, copy); + + printf("Arrays 'array' and 'copy' are %s\n", (res ? "the same" : "NOT the same")); + + si_array_free(array); + si_array_free(copy); +} + +void example_2_1(void) { + printf("==============\n\n==============\nExample 2.1:\n"); + siArray(i32) array = si_array_make((i32[]){1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + printf("Array in regular order: "); + foreach (num, array) { + printf("%i ", *num); + } + printf("\n"); + si_array_reverse(&array); + printf("Array in reverse order: "); + foreach (num, array) { + printf("%i ", *num); + } + printf("\n"); + si_array_free(array); +} + + +int main(void) { + example_2_0(); + example_2_1(); + + return 0; +} diff --git a/examples/benchmarking.c b/examples/benchmarking.c new file mode 100644 index 0000000..a8d2d61 --- /dev/null +++ b/examples/benchmarking.c @@ -0,0 +1,20 @@ +#define SI_IMPLEMENTATION 1 +#include + + +void performance_test(void) { + isize i; + for (i = 0; i < SI_UINT16_MAX; i++); /* NOTE(EimaMei): Should strain the CPU a little. */ +} + + +int main(void) { + printf("Running 'performance_test()' 30000 times. Lets see how long it takes to execute that many times...\n"); + si_performance_run_per_loop(30000, performance_test()); + + printf("Now lets see how many times 'performance_test()' can be executed in 5 seconds...\n"); + si_performance_executes_per_ms(5000, performance_test()); + + + return 0; +} diff --git a/examples/file.c b/examples/file.c new file mode 100644 index 0000000..dea94ef --- /dev/null +++ b/examples/file.c @@ -0,0 +1,87 @@ +#define SI_IMPLEMENTATION 1 +#include + + +void example_4_0(void) { + printf("==============\n\n==============\nExample 4.0:\n"); + + siFile file = si_file_open("example.c"); /* If the file doesn't exist or fails to open any other way, then we will get an assertion error. */ + printf("About 'example.c':\n\tFull path - '%s'\n\tSize - '%zu' bytes\n", file.path, file.size); + + siFile new_file = si_file_create("random.txt"); + si_file_write(&new_file, "A silly file\nwith a sili newline."); + printf("About 'random.txt':\n\tFull path - '%s'\n\tSize - '%zu' bytes\n", file.path, file.size); + + siString content = si_file_read(new_file); + printf("\tContent - '%s' (len: '%zd')\n", content, si_string_len(content)); + + siArray(siString) file_lines = si_file_readlines(file); + printf("Contents of '%s' ('%zd' lines in total):\n", si_path_base_name(file.path), si_array_len(file_lines)); + + usize i; + for (i = 0; i < si_array_len(file_lines); i++) { + si_string_strip(&file_lines[i]); + printf("\tLine %zd: '%s'\n", i, file_lines[i]); + si_string_free(file_lines[i]); + } + + si_file_write_at_line(&new_file, "but now we have a changed line\n", 1); + siArray(siString) new_file_lines = si_file_readlines(new_file); + printf("Contents of '%s' ('%zd' lines in total):\n", si_path_base_name(new_file.path), si_array_len(new_file_lines)); + + for (i = 0; i < si_array_len(new_file_lines); i++) { + si_string_strip(&new_file_lines[i]); + printf("\tLine %zd: '%s'\n", i, new_file_lines[i]); + si_string_free(new_file_lines[i]); + } + + //si_string_free(content); + + si_array_free(file_lines); + si_array_free(new_file_lines); + + si_file_close(file); + si_file_close(new_file); +} + +void example_4_1(void) { + printf("==============\n\n==============\nExample 4.1:\n"); + + bool exist = si_path_exists("example.c"); + printf("File 'example.c' %s\n", (exist ? "DOES exist" : "DOESN'T exist")); + + exist = si_path_exists("random.txt"); + if (!exist) { + printf("Since 'random.txt' doesn't exist, we'll just create one\n"); + + siFile file = si_file_open_mode("random.txt", SI_FILE_MODE_CREATE); + si_file_write(&file, "Creating files is too easy tbh."); + si_file_close(file); + } + + bool res = si_path_copy("random.txt", "random-2.txt"); + printf("Does 'random-2.txt' exist: '%zd' (res: '%zd')\n", si_path_exists("random-2.txt"), res); + + res = si_path_move("random.txt", "renamed.txt"); + printf("Does 'random.txt' exist: '%zd', but 'renamed.txt' outputs a '%zd' (res: '%zd')\n", si_path_exists("random.txt"), si_path_exists("renamed.txt"), res); + + const char* path = "example.c"; + siString full_path = si_path_get_fullname(path); + printf("Information about '%s':\n\tBase name - '%s'\n\tExtension - '%s'\n\tFull path - '%s'\n\tIs relative: %zd\n", path, si_path_base_name(path), si_path_extension(path), full_path, si_path_is_relative(path)); + + res = si_path_remove("random-2.txt"); + printf("Does 'random-2.txt' exist: '%zd' (res: '%zd')\n", si_path_exists("random-2.txt"), res); + + res = si_path_remove("renamed.txt"); + printf("Does 'renamed.txt' exist: '%zd' (res: '%zd')\n", si_path_exists("renamed.txt"), res); + + si_string_free(full_path); +} + + +int main(void) { + example_4_0(); + example_4_1(); + + return 0; +} diff --git a/examples/optional.c b/examples/optional.c new file mode 100644 index 0000000..0eeaf8e --- /dev/null +++ b/examples/optional.c @@ -0,0 +1,20 @@ +#define SI_IMPLEMENTATION 1 +#include + + +siOptional(char*) create(bool value) { + return (value ? si_optional_make((char*)"Godzilla") : SI_OPTIONAL_NULL); +} + + +int main(void) { + /* Example 5.0: siOptional (based on https://en.cppreference.com/w/cpp/utility/optional). */ + printf("==============\n\n==============\nExample 5.0:\n"); + + printf("create(false) returned '%s'\n", si_optional_if_no_value(create(false), (char*)"empty")); + + siOptional(char*) str = create(true); + printf("create2(true) returned '%s'\n", si_any_get(str.value, char*)); + + return 0; +} diff --git a/examples/pair.c b/examples/pair.c new file mode 100644 index 0000000..1bbd725 --- /dev/null +++ b/examples/pair.c @@ -0,0 +1,27 @@ +#define SI_IMPLEMENTATION 1 +#include + + +int main(void) { + /* Example 3.0: siPair (based on https://cplusplus.com/reference/utility/pair/pair/) */ + printf("==============\n\n==============\nExample 3.0:\n"); + + siPair(siString, f64) product1; + siPair(siString, f64) product2 = si_pair_make(si_string_make("tomatoes"), 2.30); + siPair(siString, f64) product3 = si_pair_copy(product2); + siPair(siString, f64) product4 = {si_string_make("bread"), 599.99}; + + product1.first = si_string_make("shoes"); + product1.second = 39.90; + + printf("The price of %s is $%f\n", product1.first, product1.second); + printf("The price of %s is $%f\n", product2.first, product2.second); + printf("The price of %s is $%f\n", product3.first, product3.second); + printf("The price of %s is $%f\n", product4.first, product4.second); + + si_string_free(product1.first); + si_string_free(product2.first); + si_string_free(product4.first); + + return 0; +} diff --git a/examples/str.c b/examples/str.c new file mode 100644 index 0000000..025e457 --- /dev/null +++ b/examples/str.c @@ -0,0 +1,116 @@ +#define SI_IMPLEMENTATION 1 +#include + + +void example_1_0(void) { + printf("==============\nExample 1.0:\n"); + + siString str = si_string_make("Labas, Pasauli!"); + printf("str: %s\n", str); + + si_string_append(&str, " Lithuanian, more like Russian amirite."); + printf("str: %s\n", str); + + char front = si_string_front(str); + char back = si_string_back(str); + usize length = si_string_len(str); + printf("front: '%c', back: '%c', len: '%zd'\n", front, back, length); + + si_string_set(&str, "Different sentence"); + printf("str: %s\n", str); + + si_string_push_back(&str, '.'); + printf("str: %s\n", str); + + siString str2 = si_string_copy(str); + bool result = si_strings_are_equal(str, str2); + printf("(\"%s\" == \"%s\") returns a '%s' boolean\n", str, str2, (result ? "true" : "false")); + + isize pos = si_string_find(str, "sentence"); + printf("The word 'sentence' was found at position '%zd' (Starting with the letter '%c')\n", pos, str[pos]); + + pos = si_string_find(str, "random"); + printf("However, the word 'random' was not found, thus 'pos' equals to %zd\n", pos); + + si_string_replace(&str, "Different", "Completely new"); + printf("str: %s\n", str); + + si_string_replace(&str2, "Different", "The same"); + printf("str2: %s\n", str2); + + si_string_trim(&str, "sentence."); + printf("str: %s\n", str); + + si_string_clear(&str); + printf("Length of str: %zd\n", si_string_len(str)); + + + si_string_set(&str2, "one.two.three.four.five"); + printf("Current str2: %s\n", str2); + + siArray(siString) list = si_string_split(str2, "."); + usize i; + for (i = 0; i < si_array_len(list); i++) { + printf("\tElement %zd: '%s'\n", i, list[i]); + si_string_free(list[i]); + } + + si_string_free(str); + si_string_free(str2); + si_array_free(list); +} + +void example_1_1(void) { + printf("==============\n\n==============\nExample 1.1:\n"); + /* Int stuff: */ + siString str = si_string_make(si_i64_to_cstr(-342)); + printf("str: \"%s\"\n", str); + + isize num = si_cstr_to_u64("9300"); + printf("num: %zd\n\n", num); + + + /* Join, upper, lower, title, capitalize */ + si_string_set(&str, "/home"); + printf("Original str: \"%s\"\n", str); + + si_string_join(&str, "random.txt", "/"); + printf("Joined str: \"%s\"\n", str); + + si_string_upper(&str); + printf("Upper str: \"%s\"\n", str); + + si_string_set(&str, "I'VE COME TO MAKE AN ANNOUNCEMENT"); + printf("Original str: \"%s\"\n", str); + + si_string_lower(&str); + printf("Lower str: \"%s\"\n", str); + + si_string_title(&str); + printf("Titled str: \"%s\"\n", str); + + si_string_capitalize(&str); + printf("Capitalized str: \"%s\"\n", str); + + si_string_free(str); +} + +void example_1_2(void) { + printf("==============\n\n==============\nExample 1.2:\n"); + siString str = si_string_make("\t dnuora gniliart "); + printf("Before: '%s' (len: '%zd')\n", str, si_string_len(str)); + si_string_strip(&str); + printf("After: '%s' (len: '%zd')\n", str, si_string_len(str)); + si_string_reverse(&str); + printf("'str' in reverse: '%s'\n", str); + si_string_free(str); +} + + +int main(void) { + example_1_0(); + example_1_1(); + example_1_2(); + + return 0; +} diff --git a/examples/thread.c b/examples/thread.c new file mode 100644 index 0000000..6e8cd25 --- /dev/null +++ b/examples/thread.c @@ -0,0 +1,63 @@ +#define SI_IMPLEMENTATION 1 +#include + + +rawptr thread_test(bool* arg) { + bool loop = *arg; + i16 count = SI_INT16_MIN; + + if (loop) { + printf("We'll increment 'count' from %d to %d:\n", SI_INT16_MIN, SI_INT16_MAX); + si_sleep(2000); + while (count < SI_INT16_MAX) { + count += 1; + printf("%i\n", count); + } + } + else { + printf("'arg' equals to 'false', so I'll just do nothing and wait for like 3 seconds.\n"); + si_sleep(3000); + printf("...and we're done! Exiting the thread now.\n"); + } + + typeof(count)* res = malloc(sizeof(count)); + SI_ASSERT_NOT_NULL(res); + *res = count; + + return res; +} + + +int main(void) { + siThread thread = si_thread_create(siFunc(thread_test), &(bool){false}); + si_thread_start(&thread); + + while (thread.is_running) { + printf("Even though 'thread' is currently sleeping, it's still running this exact second!\n"); + si_sleep(1000); + } + printf("That loop returned a '%i'. Now we'll re-run the loop with the argument being 'true' instead.\n", *((i16*)thread.return_value)); + free(thread.return_value); + si_sleep(2000); + + thread.arg = &(bool){true}; + si_thread_start(&thread); + si_thread_join(&thread); /* Now we have to wait... */ + + printf("That loop NOW returned a '%i'.\n", *((i16*)thread.return_value)); + free(thread.return_value); + si_sleep(2000); + + #if !defined(SI_SYSTEM_WINDOWS) + si_thread_start(&thread); + si_sleep(2500); + si_thread_cancel(&thread); + printf("Decided to kill it 2.5 seconds later.\n"); + + if (thread.return_value != nil) { + free(thread.return_value); + } + #endif + + return 0; +} diff --git a/sili.h b/sili.h index 1ec6ade..369ab88 100644 --- a/sili.h +++ b/sili.h @@ -1,8 +1,8 @@ /* sili.h - An alternative to the C/C++ standard library. =========================================================================== - - YOU MUST DEFINE 'SI_IMPLEMENTATION' in EXACTLY _one_ C file that includes this header, BEFORE the - include like this: + - YOU MUST DEFINE 'SI_IMPLEMENTATION' in EXACTLY _one_ C file that includes + this header, BEFORE the include like this: #define SI_IMPLEMENTATION #include "sili.h" @@ -19,24 +19,26 @@ sili.h - An alternative to the C/C++ standard library. - #define SI_FILE_UNDEFINE - #define SI_THREAD_UNDEFINE - #define SI_PERFORMANCE_UNDEFINE - before the SI_IMPLEMENTATION macro, as well as before any other include of `sili.h`. + before the SI_IMPLEMENTATION macro, as well as before any other include of + `sili.h`. - - NOTE: Disabling certain features may or may not create 'undefined' compiler - errors at certain spots. Use it at your own risk. + - NOTE: Disabling certain features may or may not create 'undefined' + compiler errors at certain spots. Use it at your own risk. =========================================================================== LICENSE - - This software is dual-licensed to the public domain and under the MIT license - (see the LICENSEs in the bottom of the file). + - This software is dual-licensed to the public domain and under the MIT + license (see the LICENSEs in the bottom of the file). WARNING - - This library is _slightly_ experimental and features may not work as expected. + - This library is _slightly_ experimental and features may not work as + expected. - This also means that many functions are not documented. CREDITS - - Ginger Bill's 'gb.h' for inspiring me to program the Sili Toolchain, as well as certain - features taken from the library and implemented here. + - Ginger Bill's 'gb.h' for inspiring me to program the Sili Toolchain, as + well as certain features taken from the library and implemented here. */ #ifndef SI_INCLUDE_SI_H @@ -86,6 +88,18 @@ extern "C" { #error Unknown compiler #endif + +#if defined(__CPLUS__) + #define SI_LANGUAGE_CPLUS 1 +#elif defined(__cplusplus) + #define SI_LANGUAGE_CPP 1 +#elif defined(__OBJC__) + #define SI_LANGUAGE_OBJC 1 +#else + #define SI_LANGUAGE_C 1 +#endif + + #if defined(__STDC__) #if defined(__STDC_VERSION__) #define SI_STANDARD_VERSION __STDC_VERSION__ @@ -116,6 +130,8 @@ extern "C" { #define SI_STANDARD_CPP17 1 #elif (SI_STANDARD_VERSION == 202002L) #define SI_STANDARD_CPP20 1 + #elif (SI_STANDARD_VERSION > 202002L) + #define SI_STANDARD_CPP23 1 #endif #endif #endif @@ -145,8 +161,7 @@ extern "C" { #error Unknown CPU Type #endif -#define SI_STATIC_ASSERT3(cond, msg) typedef char static_assertion_##msg[(!!(cond)) * 2 - 1] /* Note(EimaMei): This is absolutely stupid but somehow it works so who cares, really? */ -#define SI_STATIC_ASSERT2(cond, line) SI_STATIC_ASSERT3(cond, static_assertion_at_line_##line) +#define SI_STATIC_ASSERT2(cond, msg) typedef char static_assertion_##msg[(!!(cond)) * 2 - 1] /* Note(EimaMei): This is absolutely stupid but somehow it works so who cares, really? */ #define SI_STATIC_ASSERT1(cond, line) SI_STATIC_ASSERT2(cond, line) #define SI_STATIC_ASSERT(cond) SI_STATIC_ASSERT1(cond, __LINE__) @@ -342,6 +357,7 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); #define SI_UNUSED(x) (void)(x) /* NOTE(EimaMei) Should be used when you want to supress "parameter 'X' set but not used" errors. */ #define si_swap(a, b) do { typeof((a)) tmp = (a); (a) = (b); (b) = tmp; } while (0) +#define si_between(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper))) #if defined(SI_STANDARD_ANSI) || defined(SI_COMPILER_MSVC) /* NOTE(EimaMei): Fuck Microsoft. */ #define typeof(value) __typeof__(value) @@ -445,42 +461,6 @@ typedef struct siFunction { * */ -#if defined(SI_MEMORY_LOGGING) -/* -* -* -* -* -* -* -* -* -* -* -* -* -* -* - ========================= - | Memory Logging (Beta) | - ========================= -*/ - -typedef struct { - usize len; -} siDebugHeader; -#define SI_DEBUG_HEADER(s) ((siDebugHeader*)s - 1) - -rawptr si_debug_alloc(usize function_id, usize size, usize arg2, cstring file, i32 line, cstring function, cstring time, cstring date); -void si_debug_free(rawptr ptr); - -#define malloc(size) si_debug_alloc(1, size, 0, __FILE__, __LINE__, __func__, __TIME__, __DATE__) -#define calloc(num, size) si_debug_alloc(2, size, num, __FILE__, __LINE__, __func__, __TIME__, __DATE__) -#define realloc(ptr, new_size) si_debug_alloc(3, new_size, (usize)(ptr), __FILE__, __LINE__, __func__, __TIME__, __DATE__) -#define free(ptr) si_debug_free(ptr) - -#endif - #if !defined(SI_PAIR_UNDEFINE) /* * @@ -600,23 +580,23 @@ siAny si_array_back(siArray(void) array); #define si_array_rfind(array, value) si_impl_array_rfind_ex(array, si_array_len(array) - 1, 0, si_any_make(value)) #define si_array_rfind_ex(array, start, end, value) si_impl_array_rfind_ex(array, start, end, si_any_make(value)) -#define si_array_replace(array, old_value, new_value) si_impl_array_replace(array, si_any_make(old_value), si_any_make(new_value)) +#define si_array_replace(array_address, old_value, new_value) si_impl_array_replace(array_address, si_any_make(old_value), si_any_make(new_value)) isize si_array_reverse(siArray(void) array); char* si_array_to_sistring(siArray(char*) array, cstring separator); -#define si_array_append(array, value) si_impl_array_append(array, si_any_make(value)) -#define si_array_push_back(array, value) si_array_append(array, value) +#define si_array_append(array_address, value) si_impl_array_append(array_address, si_any_make(value)) +#define si_array_push_back(array_address, value) si_array_append(array_address, value) -isize si_array_clear(rawptr array); +isize si_array_clear(rawptr array_address); bool si_arrays_are_equal(siArray(void) lha, siArray(void) rha); isize si_array_free(siArray(void) array); /* NOTE(EimaMei): The actual implementations. Shouldn't be used in practice, really. */ -isize si_impl_array_append(rawptr array, siAny value); isize si_impl_array_find_ex(rawptr array, usize start, usize end, siAny value); -isize si_impl_array_rfind_ex(rawptr str, usize start, usize end, siAny value); -isize si_impl_array_replace(rawptr array, siAny old_value, siAny new_value); +isize si_impl_array_rfind_ex(rawptr array, usize start, usize end, siAny value); +isize si_impl_array_append(rawptr array_address, siAny value); +isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_value); #endif @@ -954,8 +934,13 @@ typedef SI_ENUM_DECLARE(usize, siWeek) { }; -/*f64 si_time_now(void); -u64 si_time_utc_now(void);*/ +f64 si_time_now(void); +u64 si_time_utc_now(void) { + time_t rawtime; + time(&rawtime); + + return rawtime; +} void si_sleep(usize miliseconds); #endif @@ -963,71 +948,125 @@ void si_sleep(usize miliseconds); #if !defined(SI_PERFORMANCE_UNDEFINE) #if !defined(SI_MEMORY_LOGGING) - #define SI_PERFORMANCE_MSG SI_MULTILINE( \ - "====== BENCHMARK DATA ======\n" \ - "General:\n" \ - "\tFunction - '%s'\n" \ - "\tDuration - '%f' ms\n" \ - "\tExecution count - '%f' million\n" \ + #define SI_PERFORMANCE_MSG SI_MULTILINE(\ + "====== BENCHMARK DATA ======\n"\ + "General:\n"\ + "\tFunction - '%s'\n"\ + "\tDuration - '%f' ms\n"\ + "\tExecution count - '%f' million\n"\ ) #define SI_PERFORMANCE_PRINT_MEMORY(function) do {} while (0) #else - #define SI_PERFORMANCE_MSG SI_MULTILINE( \ - "====== BENCHMARK DATA ======\n" \ - "NOTE: General execution count might be slower due to the memory logging.\n" \ - "General:\n" \ - "\tFunction - '%s'\n" \ - "\tDuration - '%f' ms\n" \ - "\tExecution count - '%f' million\n" \ + #define SI_PERFORMANCE_MSG SI_MULTILINE(\ + "====== BENCHMARK DATA ======\n"\ + "NOTE: General execution count might be slower due to the memory logging.\n"\ + "General:\n"\ + "\tFunction - '%s'\n"\ + "\tDuration - '%f' ms\n"\ + "\tExecution count - '%f' million\n"\ ) - #define SI_PERFORMANCE_MSG_DEBUG SI_MULTILINE( \ - "Memory (per execution):\n" \ - "\tAllocation count - '%zd'\n" \ - "\tFree count - '%zd'\n" \ - "\tTotal RAM usage - '%zd' bytes\n" \ - "\tOverall allocated RAM left - '%zd' bytes\n" \ + #define SI_PERFORMANCE_MSG_DEBUG SI_MULTILINE(\ + "Memory:\n"\ + "\tAllocation count - '%zd'\n"\ + "\tFree count - '%zd'\n"\ + "\tTotal RAM usage - '%zd' bytes\n"\ + "\tOverall allocated RAM left - '%zd' bytes\n"\ ) - #define SI_PERFORMANCE_PRINT_MEMORY(function) \ - { \ - si_debug_allocs = si_debug_frees = si_debug_memory_consumption = si_debug_overall = 0; \ - function; \ - } \ - printf(SI_PERFORMANCE_MSG_DEBUG, si_debug_allocs, si_debug_frees, si_debug_memory_consumption, si_debug_overall) + #define SI_PERFORMANCE_PRINT_MEMORY(function)\ + do {\ + siDebugGlobalVars si_debug_old = si_debug;\ + si_debug = (siDebugGlobalVars){0, 0, 0, 0, nil};\ + function;\ + si_debug_print_all();\ + si_debug_print_allocations();\ + si_debug_cleanup();\ + si_debug = si_debug_old;\ + } while(0) #endif void si_impl_performance_thread(u32* arg); -#define si_performance_run_per_loop(times_to_loop, function) \ - do { \ - usize si_index; \ - clock_t si_time_since = clock(); \ - for (si_index = 0; si_index < (usize)times_to_loop; si_index++) { \ - function; \ - } \ - \ - si_time_since = clock() - si_time_since; \ - f64 si_time_taken = ((f64)si_time_since) / 1000; /* NOTE(EimaMei): This will take the time in ms, not seconds. */ \ - printf(SI_PERFORMANCE_MSG, #function, si_time_taken, (f64)times_to_loop / 1000000.0f); \ - SI_PERFORMANCE_PRINT_MEMORY(function); \ +#define si_performance_run_per_loop(times_to_loop, function)\ + do {\ + usize si_index;\ + clock_t si_time_since = clock();\ + for (si_index = 0; si_index < (usize)times_to_loop; si_index++) {\ + function;\ + }\ + si_time_since = clock() - si_time_since;\ + f64 si_time_taken = ((f64)si_time_since) / 1000; /* NOTE(EimaMei): This will take the time in ms, not seconds. */\ + printf(SI_PERFORMANCE_MSG, #function, si_time_taken, (f64)times_to_loop / 1000000.0f);\ + SI_PERFORMANCE_PRINT_MEMORY(function);\ } while(0) -#define si_performance_executes_per_ms(ms, function) \ - do { \ - u64 si_counter = 0; \ - u32 si_miliseconds = (u32)ms; \ - siThread si_thread = si_thread_create(siFunc(si_impl_performance_thread), &si_miliseconds); \ - si_thread_start(&si_thread); \ - \ - while (si_thread.is_running) { \ - function; \ - si_counter += 1; \ - } \ - \ - printf(SI_PERFORMANCE_MSG, #function, (f64)si_miliseconds, (f64)si_counter / 1000000.0f); \ - SI_PERFORMANCE_PRINT_MEMORY(function); \ +#define si_performance_executes_per_ms(ms, function)\ + do {\ + u64 si_counter = 0;\ + u32 si_miliseconds = (u32)ms;\ + siThread si_thread = si_thread_create(siFunc(si_impl_performance_thread), &si_miliseconds);\ + si_thread_start(&si_thread);\ + while (si_thread.is_running) {\ + function;\ + si_counter += 1;\ + }\ + printf(SI_PERFORMANCE_MSG, #function, (f64)si_miliseconds, (f64)si_counter / 1000000.0f);\ + SI_PERFORMANCE_PRINT_MEMORY(function);\ } while(0) #endif +#if defined(SI_MEMORY_LOGGING) +/* +* +* +* +* +* +* +* +* +* +* +* +* +* +* + ========================= + | Memory Logging (Beta) | + ========================= +*/ + +typedef struct { + cstring type; + usize len; + u8 state; /* 0 - NOT FREED, 1 - FREED, 2 - REALLOCED */ + + cstring date, time, file; + i32 line; + cstring function; + + u32 index; +} siDebugHeader; +#define SI_DEBUG_HEADER(s) ((siDebugHeader*)s - 1) + +typedef siPair(usize, usize) siDebugArgs; + +rawptr si_debug_alloc(usize function_id, rawptr ptr, siDebugArgs args, cstring file, i32 line, cstring function, cstring time, cstring date); +void si_debug_free(rawptr ptr); + +#define malloc(size) si_debug_alloc(1, nil, (siDebugArgs){size, 0}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) +#define calloc(num, size) si_debug_alloc(2, nil, (siDebugArgs){size, num}, num, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) +#define realloc(ptr, new_size) si_debug_alloc(3, ptr, (siDebugArgs){0, new_size}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) +#define si_realloc(ptr, old_size, new_size) si_debug_alloc(4, ptr, (siDebugArgs){old_size, new_size}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) +#define free(ptr) si_debug_free(ptr) + +void si_debug_print_all(void); +void si_debug_print_allocations(void); +void si_debug_cleanup(void); + +#define SI_QUICK_LOG() si_debug_print_all(); si_debug_print_allocations(); + +#endif + /* * * @@ -1085,6 +1124,12 @@ usize si_impl_assert_msg(bool condition, cstring condition_str, cstring message, return 0; } +#if defined(SI_MEMORY_LOGGING) + #undef malloc + #undef si_realloc + #undef free +#endif + rawptr si_realloc(rawptr ptr, usize old_size, usize new_size) { if (ptr == nil) { return malloc(new_size); @@ -1106,6 +1151,12 @@ rawptr si_realloc(rawptr ptr, usize old_size, usize new_size) { return new_ptr; } +#if defined(SI_MEMORY_LOGGING) + #define malloc(size) si_debug_alloc(1, nil, (siDebugArgs){size, 0}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) + #define si_realloc(ptr, old_size, new_size) si_debug_alloc(4, ptr, (siDebugArgs){old_size, new_size}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) + #define free(ptr) si_debug_free(ptr) +#endif + void si_sleep(usize miliseconds) { #if defined(SI_SYSTEM_WINDOWS) Sleep(miliseconds); @@ -1132,6 +1183,9 @@ inline siArray(void) si_array_make_list(rawptr list, usize sizeof_element, usize rawptr array = si_array_make_reserve(sizeof_element, count); memcpy(array, list, sizeof_element * count); + siArrayHeader* header = SI_ARRAY_HEADER(array); + header->len = count; + return array; } inline siArray(void) si_array_copy(siArray(void) array) { @@ -1143,7 +1197,7 @@ siArray(void) si_array_make_reserve(usize sizeof_element, usize count) { siArray(void) array = ptr + sizeof(siArrayHeader); siArrayHeader* header = SI_ARRAY_HEADER(array); - header->len = count; + header->len = 0; /* TODO(EimaMei): FIX THIS!!!!!!!!!!!!!!!!!!!!! */ header->capacity = count; header->type_width = sizeof_element; @@ -1160,26 +1214,25 @@ inline usize si_array_type_width(siArray(void) array) { return SI_ARRAY_HEADER(array)->type_width; } inline usize si_array_size_in_bytes(siArray(void) array) { - return si_array_len(array) * si_array_type_width(array); + return si_array_capacity(array) * si_array_type_width(array); } inline siAny si_array_at(siArray(void) array, usize index) { - SI_ASSERT_MSG(index < si_array_len(array) || si_array_len(array) != 0, "Array is empty OR the provided index is too high."); + SI_ASSERT_MSG(si_between(index, 0, si_array_len(array)), "Array is empty OR the provided index is too high."); rawptr p = (siByte*)array + index * si_array_type_width(array); - return (siAny){.type_width = si_array_type_width(array), .ptr = p}; + return (siAny){si_array_type_width(array), p}; } inline siAny si_array_front(siArray(void) array) { SI_ASSERT_MSG(si_array_len(array) != 0, "Array is empty."); - rawptr p = (siByte*)array + 0 * si_array_type_width(array); - return (siAny){.type_width = si_array_type_width(array), .ptr = p}; + return (siAny){si_array_type_width(array), array}; } inline siAny si_array_back(siArray(void) array) { SI_ASSERT_MSG(si_array_len(array) != 0, "Array is empty."); rawptr p = (siByte*)array + (si_array_len(array) - 1) * si_array_type_width(array); - return (siAny){.type_width = si_array_type_width(array), .ptr = p}; + return (siAny){si_array_type_width(array), p}; } isize si_impl_array_find_ex(rawptr array, usize start, usize end, siAny value) { @@ -1215,16 +1268,17 @@ isize si_impl_array_rfind_ex(rawptr array, usize start, usize end, siAny value) return (found ? i : SI_ERROR); } -isize si_impl_array_replace(rawptr array, siAny old_value, siAny new_value) { - rawptr* array_pointer = (rawptr*)array; - SI_ASSERT_MSG(old_value.type_width <= si_array_type_width(*array_pointer) && new_value.type_width <= old_value.type_width, "The given value's sizeof is too large compared to the elements' in the array."); +isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_value) { + siByte* array = *((siByte**)array_address); + usize type_width = si_array_type_width(array); + SI_ASSERT_MSG(si_between(new_value.type_width, old_value.type_width, type_width), "The given value's sizeof is too large compared to the elements' in the array."); - isize pos = si_impl_array_find_ex(*array_pointer, 0, si_array_len(*array_pointer), old_value); + isize pos = si_impl_array_find_ex(array, 0, si_array_len(array), old_value); if (pos == SI_ERROR) { return SI_ERROR; } - memcpy((siByte*)(*array_pointer) + pos * si_array_type_width(*array_pointer), new_value.ptr, new_value.type_width); + memcpy(array + pos * type_width, new_value.ptr, new_value.type_width); return pos; } @@ -1275,42 +1329,35 @@ siString si_array_to_sistring(siArray(char*) array, cstring separator) { return result; } -isize si_impl_array_append(rawptr array, siAny value) { - rawptr* array_pointer = (rawptr*)array; - siArrayHeader* header = SI_ARRAY_HEADER(*array_pointer); - SI_ASSERT_MSG((value.type_width <= header->type_width), "The given value's sizeof is too large compared to the elements' in the arra"); +isize si_impl_array_append(rawptr array_address, siAny value) { + siByte** array = ((siByte**)array_address); + siArrayHeader* header = SI_ARRAY_HEADER(*array); + SI_ASSERT_MSG(value.type_width <= header->type_width, "The given value's sizeof is too large compared to the elements' in the arra"); if (header->len == header->capacity) { siByte* result = si_realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_width, sizeof(siArrayHeader) + 2 * header->capacity * header->type_width); - if (result == nil) { - return SI_ERROR; - } - *array_pointer = (siByte*)result + sizeof(siArrayHeader); + SI_ASSERT_NOT_NULL(result); + + *array = result + sizeof(siArrayHeader); header = (siArrayHeader*)result; header->capacity *= 2; } - rawptr res = memcpy((siByte*)(*array_pointer) + header->len * header->type_width, value.ptr, header->type_width); - if (res == nil) { - return SI_ERROR; - } + rawptr res = memcpy(*array + header->len * header->type_width, value.ptr, header->type_width); + SI_ASSERT_NOT_NULL(res); header->len += 1; return SI_OKAY; } -isize si_array_clear(siArray(void) array) { - if (array == nil) { - return SI_ERROR; - } +isize si_array_clear(rawptr array_address) { + SI_ASSERT_NOT_NULL(array_address); - rawptr* array_pointer = (rawptr*)array; + rawptr array = *((rawptr*)array_address); - rawptr result = memset(*array_pointer, 0, si_array_size_in_bytes(*array_pointer)); - if (result == nil) { - return SI_ERROR; - } + rawptr result = memset(array, 0, si_array_size_in_bytes(array)); + SI_ASSERT_NOT_NULL(result); return SI_OKAY; } @@ -1323,9 +1370,10 @@ bool si_arrays_are_equal(siArray(void) lha, siArray(void) rha) { return false; } + usize width = lha_header->type_width; usize i; for (i = 0; i < lha_header->len; i++) { - if (memcmp((siByte*)lha + i * lha_header->type_width, (siByte*)rha + i * lha_header->type_width, lha_header->type_width) != SI_OKAY) { + if (memcmp((siByte*)lha + i * width, (siByte*)rha + i * width, width) != SI_OKAY) { return false; } } @@ -1692,14 +1740,18 @@ siArray(siString) si_string_split(siString str, cstring separator) { begin_pos = pos + separator_len; } - siArray(siString) res = si_array_make_reserve(sizeof(*res), count); + siArray(siString) res = si_array_make_list(&(rawptr){nil}, sizeof(*res), count); usize i; for (i = 0; i < count; i++) { + printf("%zd\n", i); res[i] = si_string_make_len(original, pos_buffer[i]); + printf("123\n"); original += pos_buffer[i] + separator_len; + printf("123\n"); } + return res; } @@ -1728,7 +1780,7 @@ inline isize si_string_push_back(siString* str, char other) { } inline siString si_string_copy(siString from) { - return si_string_make(from); + return si_string_make_len(from, si_string_len(from)); } inline isize si_string_clear(siString* str) { char null_terminator = '\0'; @@ -2102,9 +2154,23 @@ siString si_file_read_at(siFile file, usize offset) { return si_string_make_len(tmp, read_len); } +/* + NOTE/TODO(EimaMei): This has a huge performance hit if the file is, lets say, 400 lines in length. That's over 400 + allocations, and even more if the file is larger! An obvious way to imrpove the performance is to allocate one huge + memory block and then just copy over the lines with the headers. Problem is, this means the individual strings cannot + be freed by any means, resulting in crashes. A more optional way is to just output an array of cstrings, but then + we lose the benefits of siString. Maybe by creating siStaticArray (and by extension siStaticString), this will only + then require one allocation. + + This also makes me realize that the old traditional heap allocating system is really, really flawed in performance, + compared to just allocating one HUUUGE memory block (a few MBs minimum) and just writing everything there. I'll think + about it for sure. +*/ siArray(siString) si_file_readlines(siFile file) { siString buffer = si_file_read(file); + printf("finish\n"); siArray(siString) res = si_string_split(buffer, "\n"); + printf("finish2\n"); si_string_free(buffer); return res; @@ -2133,30 +2199,32 @@ isize si_file_write_at_len(siFile* file, cstring content, usize content_len, usi isize si_file_write_at_line(siFile* file, cstring content, usize index) { SI_ASSERT_NOT_NULL(file->ptr); - #if defined(SI_ARRAY_UNDEFINE) - SI_ASSERT_MSG(SI_ARRAY_UNDEFINE != 1, "siArray is undefined, cannot use this function."); - - SI_UNUSED(file); - SI_UNUSED(content); - SI_UNUSED(index); - - return SI_ERROR; - #else - siArray(siString) buffer = si_file_readlines(*file); + siString previous_line = buffer[index]; SI_ASSERT_MSG(0 <= index && index <= si_array_len(buffer), "Index is either not 0 or higher than the amount of lines in the file."); + buffer[index] = (siString)content; siString new_file_content = si_array_to_sistring(buffer, "\n"); siFile new_file = si_file_open_mode(file->path, SI_FILE_MODE_CREATE); si_file_write_len(&new_file, new_file_content, si_string_len(new_file_content)); + usize i; + for (i = 0; i < si_array_len(buffer); i++) { + if (i == index) { + continue; + } + si_string_free(buffer[i]); + } + si_string_free(previous_line); + si_array_free(buffer); + + si_string_free(new_file_content); si_file_close(*file); *file = new_file; return SI_OKAY; - #endif } inline isize si_file_seek(siFile file, usize offset) { @@ -2261,20 +2329,20 @@ void si_thread_join(siThread* t) { } void si_thread_cancel(siThread* t) { #if defined(SI_SYSTEM_WINDOWS) - puts("si_thread_cancel: This feature on Windows is not supported as of now."); - SI_UNUSED(t); + puts("si_thread_cancel: This feature on Windows is not supported as of now."); + SI_UNUSED(t); #else - usize error_code = pthread_cancel(t->id); - t->is_running = false; + usize error_code = pthread_cancel(t->id); + t->is_running = false; - cstring error_msg = nil; - switch (error_code) { - case SI_OKAY: break; - case ESRCH: error_msg = "No thread could be found corresponding to that specified by the given thread ID."; break; - default: error_msg = si_string_make_fmt("Unknown error code (%li).", error_code); - } - SI_ASSERT_MSG(error_code == SI_OKAY, error_msg); + cstring error_msg = nil; + switch (error_code) { + case SI_OKAY: break; + case ESRCH: error_msg = "No thread could be found corresponding to that specified by the given thread ID."; break; + default: error_msg = si_string_make_fmt("Unknown error code (%li).", error_code); + } + SI_ASSERT_MSG(error_code == SI_OKAY, error_msg); #endif } @@ -2284,21 +2352,21 @@ inline void si_thread_destroy(siThread* t) { void si_thread_set_priority(siThread t, i32 priority) { #if defined(SI_SYSTEM_WINDOWS) - isize res = SetThreadPriority(t.id, priority); - SI_ASSERT_MSG(res != 0, "Something went wrong setting the thread priority."); + isize res = SetThreadPriority(t.id, priority); + SI_ASSERT_MSG(res != 0, "Something went wrong setting the thread priority."); #else - usize error_code = pthread_setschedprio(t.id, priority); + usize error_code = pthread_setschedprio(t.id, priority); - cstring error_msg = nil; - switch (error_code) { - case SI_OKAY: break; - case EINVAL: error_msg = "The value of 'priority' is invalid for the scheduling policy of the specified thread."; break; - case ENOTSUP: error_msg = "An attempt was made to set the priority to an unsupported value."; break; - case EPERM: error_msg = "The caller does not have the appropriate permission to set the scheduling policy of the specified thread OR the implementation does not allow the application to modify the priority to the value specified."; break; - case ESRCH: error_msg = "The value specified by thread does not refer to an existing thread."; break; - default: error_msg = si_string_make_fmt("Unknown error code (%li).", error_code); - } - SI_ASSERT_MSG(error_code == SI_OKAY, error_msg); + cstring error_msg = nil; + switch (error_code) { + case SI_OKAY: break; + case EINVAL: error_msg = "The value of 'priority' is invalid for the scheduling policy of the specified thread."; break; + case ENOTSUP: error_msg = "An attempt was made to set the priority to an unsupported value."; break; + case EPERM: error_msg = "The caller does not have the appropriate permission to set the scheduling policy of the specified thread OR the implementation does not allow the application to modify the priority to the value specified."; break; + case ESRCH: error_msg = "The value specified by thread does not refer to an existing thread."; break; + default: error_msg = si_string_make_fmt("Unknown error code (%li).", error_code); + } + SI_ASSERT_MSG(error_code == SI_OKAY, error_msg); #endif } @@ -2306,34 +2374,94 @@ void si_thread_set_priority(siThread t, i32 priority) { #if defined(SI_MEMORY_LOGGING_IMPLEMENTATION) && !defined(SI_MEMORY_LOGGING_UNDEFINE) -usize si_debug_allocs = 0, si_debug_frees = 0, si_debug_memory_consumption = 0, si_debug_overall = 0; +typedef struct siDebugGlobalVars { + usize allocs; + usize frees; + usize total; + usize overall; + siArray(siDebugHeader*) list; +} siDebugGlobalVars; +siDebugGlobalVars si_debug = {0, 0, 0, 0, nil}; #if defined(malloc) /* NOTE(EimaMei): We undef the sili defined macros so that we don't get an infinite loop, where 'malloc' (under the hood si_debug_alloc) calls 'malloc' (under the hood si_debug_alloc) and continue that for the rest of our lives. */ #undef malloc #undef calloc #undef realloc + #undef si_realloc #undef free #endif -rawptr si_debug_alloc(usize function_id, usize size, usize arg2, cstring file, i32 line, cstring function, cstring time, cstring date) { +rawptr si_debug_alloc(usize function_id, rawptr ptr, siDebugArgs args, cstring file, i32 line, cstring function, cstring time, cstring date) { siByte* res = nil; + /*NOTE(EimaMei): args.first - old size ; args.second - new size */ + if (si_debug.list == nil) { + siByte* ptr = malloc(sizeof(siArrayHeader) + (sizeof(siDebugHeader*) * 100)); + si_debug.list = (rawptr)(ptr + sizeof(siArrayHeader)); + + siArrayHeader* header = (siArrayHeader*)ptr; + header->len = 0; + header->capacity = 100; + header->type_width = sizeof(siDebugHeader*); + } + + usize size = 0; + cstring type = nil; switch (function_id) { case 1: { /* malloc*/ - res = malloc(sizeof(siDebugHeader) + size); + printf("hi\n"); + res = malloc(sizeof(siDebugHeader) + args.first); + printf("hi\n"); + size = args.first; + type = "malloc"; break; } case 2: { /* calloc*/ - res = calloc(arg2, sizeof(siDebugHeader) + size); - size *= arg2; + res = calloc(args.second, sizeof(siDebugHeader) + args.first); + size = args.first * args.second; + type = "calloc"; break; } case 3: { /* realloc */ - siDebugHeader* header = SI_DEBUG_HEADER(arg2); - si_debug_overall -= header->len; + siDebugHeader* header = SI_DEBUG_HEADER(ptr); + si_debug.allocs += 1; + si_debug.frees += 1; res = realloc(header, sizeof(siDebugHeader) + size); - break; + + header->type = "si_realloc"; + header->len = args.second; + header->state = 2; + header->date = date; + header->time = time; + header->file = file; + header->line = line; + header->function = function; + + return res + sizeof(siDebugHeader); + } + case 4: { /* si_realloc */ + if (ptr == SI_ARRAY_HEADER(si_debug.list)) { + res = si_realloc(ptr, args.first, args.second); + return res; + } + + siDebugHeader* header = SI_DEBUG_HEADER(ptr); + si_debug.allocs += 1; + si_debug.frees += 1; + + res = si_realloc(header, sizeof(siDebugHeader) + args.first, sizeof(siDebugHeader) + args.second); + + header->type = "si_realloc"; + header->len = args.second; + header->state = 2; + header->date = date; + header->time = time; + header->file = file; + header->line = line; + header->function = function; + + return res + sizeof(siDebugHeader); } default: __builtin_unreachable(); } @@ -2344,34 +2472,103 @@ rawptr si_debug_alloc(usize function_id, usize size, usize arg2, cstring file, i msg = si_string_make_fmt("%s %s at '%s:%i'[%s]: Failed to malloc because the system is out of memory (errno ENOMEM).", date, time, file, line, function); } else { - msg = si_string_make_fmt("%s %s at '%s:%i'[%s]: Failed to malloc because the system is out of memory (errno ENOMEM).", date, time, file, line, function); + msg = si_string_make_fmt("%s %s at '%s:%i'[%s]: Failed to malloc because of an unknown reason (errno '%zd').", date, time, file, line, function, errno); } SI_ASSERT_MSG(res != NULL, msg); } siDebugHeader* header = (siDebugHeader*)res; + header->type = type; header->len = size; + header->state = 0; + header->date = date; + header->time = time; + header->file = file; + header->line = line; + header->function = function; + header->index = si_array_len(si_debug.list); - si_debug_allocs += 1; - si_debug_memory_consumption += size; - si_debug_overall += size; + si_debug.allocs += 1; + si_debug.total += size; + si_debug.overall += size; - return res + sizeof(usize); + si_array_append(&si_debug.list, header); + + return res + sizeof(siDebugHeader); } void si_debug_free(rawptr ptr) { SI_ASSERT_NOT_NULL(ptr); siDebugHeader* header = SI_DEBUG_HEADER(ptr); + siDebugHeader copy = *header; - si_debug_frees += 1; - si_debug_overall -= header->len; + si_debug.frees += 1; + si_debug.overall -= header->len; free(header); + + siDebugHeader* new_header = malloc(sizeof(siDebugHeader)); + *new_header = copy; + new_header->state = 1; + + si_debug.list[new_header->index] = new_header; +} + +void si_debug_print_all(void) { + if (si_debug.list == nil) { + return ; + } + + foreach (x, si_debug.list) { + siDebugHeader* header = *x; + + if (header == nil) { + continue; + } + cstring msg = nil; + switch (header->state) { + case 0: msg = "NOT FREED"; break; + case 1: msg = "FREED"; break; + case 2: msg = "REALLOCED"; break; + default: __builtin_unreachable(); + } + + printf( + "%d: [%p]: %s %s at '%s:%i'[%s]: %s: %s ('%zd' bytes).\n", + header->index, + (rawptr)((siByte*)header + sizeof(siDebugHeader)), + header->date, header->time, + header->file, header->line, + header->function, + header->type, + msg, + header->len + ); + } +} + +void si_debug_print_allocations(void) { + printf(SI_PERFORMANCE_MSG_DEBUG, si_debug.allocs, si_debug.frees, si_debug.total, si_debug.overall); +} + +void si_debug_cleanup(void) { + if (si_debug.list == nil) { + return ; + } + + foreach (x, si_debug.list) { + free(*x); + } + + free(SI_ARRAY_HEADER(si_debug.list)); + + si_debug = (siDebugGlobalVars){0, 0, 0, 0, nil}; } -#define malloc(size) si_debug_alloc(1, size, 0, __FILE__, __LINE__, __func__, __TIME__, __DATE__) -#define calloc(num, size) si_debug_alloc(2, size, num, __FILE__, __LINE__, __func__, __TIME__, __DATE__) -#define realloc(ptr, new_size) si_debug_alloc(3, new_size, (usize)(ptr), __FILE__, __LINE__, __func__, __TIME__, __DATE__) +#define malloc(size) si_debug_alloc(1, nil, (siDebugArgs){size, 0}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) +#define calloc(num, size) si_debug_alloc(2, nil, (siDebugArgs){size, num}, num, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) +#define realloc(ptr, new_size) si_debug_alloc(3, ptr, (siDebugArgs){0, new_size}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) +#define si_realloc(ptr, old_size, new_size) si_debug_alloc(4, ptr, (siDebugArgs){old_size, new_size}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) #define free(ptr) si_debug_free(ptr) #endif From 712a4623d4c1246f2e833679eaf1eb43277e2c1a Mon Sep 17 00:00:00 2001 From: EimaMei Date: Sun, 4 Jun 2023 16:38:20 +0300 Subject: [PATCH 02/17] str reforming --- Makefile | 2 +- sili.h | 198 ++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 140 insertions(+), 60 deletions(-) diff --git a/Makefile b/Makefile index 1ad8c50..351cd7b 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ NAME = test EXE = $(OUTPUT)/$(NAME) SRC = main.c -FLAGS = -O0 -g -std=c99 -Wall -Wextra -Wpedantic -DSI_MEMORY_LOGGING +FLAGS = -O0 -g -std=c99 -Wall -Wextra -Wpedantic LIBS = INCLUDE = -I"." diff --git a/sili.h b/sili.h index 369ab88..5a03e9d 100644 --- a/sili.h +++ b/sili.h @@ -631,7 +631,8 @@ isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_val #endif #endif -typedef char* siString; +typedef siArray(char) siString; +typedef siArray(i32) siRunes; #define SI_STRING_HEADER(s) ((siStringHeader*)s - 1) @@ -643,11 +644,14 @@ siString si_string_make_reserve(usize len); siString si_string_copy(siString from); usize si_string_len(siString str); -usize si_cstr_len(cstring str); +usize si_string_capacity(siString str); +usize si_string_type_width(siString str); +bool si_string_is_empty(siString str); char si_string_at(siString str, usize index); char si_string_front(siString str); char si_string_back(siString str); +void si_string_sub(siString str, usize begin, usize end, char* result); isize si_string_find(siString str, cstring cstr); isize si_string_find_ex(siString str, usize start, usize end, cstring cstr); @@ -659,6 +663,15 @@ isize si_string_set(siString* str, cstring cstr); isize si_string_replace(siString* str, cstring old_str, cstring new_str); isize si_string_trim(siString* str, cstring cut_set); +isize si_string_append(siString* str, cstring other); +isize si_string_append_len(siString* str, cstring other, usize other_len); +isize si_string_push_back(siString* str, char other); + +void si_string_insert(siString* str, cstring cstr, usize index); +void si_string_erase(siString* str, usize begin, usize end); +void si_string_remove_cstr(siString* str, cstring cstr); +void si_string_swap(siString* str, cstring cstr1, cstring cstr2); + isize si_string_upper(siString* str); isize si_string_lower(siString* str); isize si_string_title(siString* str); @@ -667,17 +680,14 @@ isize si_string_strip(siString* str); /* NOTE(EimaMei); This strips any leading isize si_string_reverse(siString* str); isize si_string_reverse_len(siString* str, usize len); -isize si_string_append(siString* str, cstring other); -isize si_string_append_len(siString* str, cstring other, usize other_len); -isize si_string_push_back(siString* str, char other); -siArray(siString) si_string_split(siString str, cstring separator); - -isize si_string_clear(siString* str); +siArray(siString) si_string_split(siString str, cstring separator); bool si_strings_are_equal(cstring lhs, cstring rhs); +isize si_string_clear(siString* str); isize si_string_free(siString str); isize si_string_make_space_for(siString* str, usize add_len); +void si_string_shrink_to_fit(siString str); #endif @@ -698,7 +708,7 @@ isize si_string_make_space_for(siString* str, usize add_len); * * ======================== - | char stuff | + | siChar | ======================== */ char si_char_to_lower(char c); @@ -712,10 +722,20 @@ bool si_char_is_alphanumeric(char c); i32 si_digit_to_int(char c); i32 si_hex_digit_to_int(char c); -cstring si_u64_to_cstr(u64 num); + +/* + ======================== + | cstring | + ======================== +*/ +usize si_cstr_len(cstring str); + u64 si_cstr_to_u64(cstring str); -cstring si_i64_to_cstr(i64 num); i64 si_cstr_to_i64(cstring str); +/* TODO(EimaMei): si_cstr_to_f64 */ + +cstring si_u64_to_cstr(u64 num); +cstring si_i64_to_cstr(i64 num); #endif @@ -1409,7 +1429,6 @@ siString si_string_make_len(cstring str, usize len) { return res_str; } - siString si_string_make_fmt(cstring str, ...) { va_list va; va_start(va, str); @@ -1441,9 +1460,24 @@ siString si_string_make_reserve(usize len) { return res_str; } +inline siString si_string_copy(siString from) { + return si_string_make_len(from, si_string_len(from)); +} + inline usize si_string_len(siString str) { return SI_STRING_HEADER(str)->len; } +inline usize si_string_capacity(siString str) { + return SI_STRING_HEADER(str)->capacity; +} +inline usize si_string_type_width(siString str) { + return SI_STRING_HEADER(str)->type_width; +} +inline bool si_string_is_empty(siString str) { + return (SI_STRING_HEADER(str)->len == 0); +} + + inline usize si_cstr_len(cstring str) { cstring s; for (s = str; *s; s++); @@ -1475,6 +1509,11 @@ inline char si_string_back(siString str) { return str[si_string_len(str) - 1]; } +void si_string_sub(siString str, usize begin, usize end, char* result) { + usize len = end - begin + 1; + memcpy(result, str + begin, len); + *(result + len) = '\0'; +} inline isize si_string_find(siString str, cstring cstr) { return si_string_find_ex(str, 0, si_string_len(str), cstr); @@ -1518,14 +1557,11 @@ isize si_string_rfind_ex(siString str, usize start, usize end, cstring cstr) { if (str[i] == cstr[cur_count]) { cur_count -= 1; - if (cur_count <= 0) { + if (cur_count < 0) { found = true; break; } } - else if (cur_count != 0) { - cur_count = 0; - } } return (found ? i : SI_ERROR); @@ -1631,6 +1667,86 @@ isize si_string_trim(siString* str, cstring cut_set) { return SI_OKAY; } + +inline isize si_string_append(siString* str, cstring other) { + return si_string_append_len(str, other, si_cstr_len(other)); +} +isize si_string_append_len(siString* str, cstring other, usize other_len) { + siStringHeader* header = SI_STRING_HEADER(*str); + usize previous_len = header->len; + header->len += other_len; + + if (header->capacity < header->len) { + isize result = si_string_make_space_for(str, other_len); + SI_ASSERT_MSG(result == SI_OKAY, "Failed to make space for string"); + header = SI_STRING_HEADER(*str); /* NOTE(EimaMei): For some reason we have to refresh the header pointer on Linux. Somewhat makes sense but also what and why. */ + } + + rawptr ptr = memcpy(*str + previous_len, other, other_len); + SI_ASSERT_NOT_NULL(ptr); + (*str)[header->len] = '\0'; + + return SI_OKAY; +} +inline isize si_string_push_back(siString* str, char other) { + return si_string_append_len(str, &other, 1); +} + +void si_string_insert(siString* str, cstring cstr, usize index) { + siStringHeader* header = SI_STRING_HEADER(*str); + usize previous_len = header->len; + usize cstr_len = si_cstr_len(cstr); + usize before_index_len = previous_len - index; + header->len += cstr_len; + + if (header->capacity < header->len) { + isize result = si_string_make_space_for(str, cstr_len); + SI_ASSERT_MSG(result == SI_OKAY, "Failed to make space for string"); + header = SI_STRING_HEADER(*str); /* NOTE(EimaMei): For some reason we have to refresh the header pointer on Linux. Somewhat makes sense but also what and why. */ + } + siString cur_str = *str; + + char* ptr = memcpy(cur_str + header->len - before_index_len, cur_str + index, before_index_len); + memcpy(cur_str + index + 1, cstr, cstr_len); + SI_ASSERT_NOT_NULL(ptr); + ptr[header->len] = '\0'; +} +void si_string_erase(siString* str, usize begin, usize end) { + usize after_index_len = begin + end; + siString cur_str = *str; + + char* ptr = memcpy(cur_str + begin, cur_str + after_index_len, si_string_len(cur_str) - after_index_len); + SI_ASSERT_NOT_NULL(ptr); + ptr[si_string_len(cur_str) - after_index_len] = '\0'; + + SI_STRING_HEADER(cur_str)->len -= after_index_len; +} +void si_string_remove_cstr(siString* str, cstring cstr) { + siStringHeader* header = SI_STRING_HEADER(*str); + usize cstr_len = si_cstr_len(cstr); + + usize cur_len; + siString cur_str; + while (true) { + cur_str = *str; + cur_len = si_string_len(cur_str); + + isize index = si_string_rfind_ex(cur_str, cur_len - 1, 0, cstr); + if (index == -1) { + break; + } + + usize after_index_len = index + cstr_len; + + char* ptr = memcpy(cur_str + index, cur_str + after_index_len, cur_len - after_index_len); + SI_ASSERT_NOT_NULL(ptr); + ptr[cur_len - after_index_len] = '\0'; + + header->len -= cstr_len; + } +} +void si_string_swap(siString* str, cstring cstr1, cstring cstr2); + inline isize si_string_upper(siString* str) { SI_ASSERT_NOT_NULL(str); @@ -1639,7 +1755,6 @@ inline isize si_string_upper(siString* str) { } return SI_OKAY; } - inline isize si_string_lower(siString* str) { SI_ASSERT_NOT_NULL(str); @@ -1744,51 +1859,13 @@ siArray(siString) si_string_split(siString str, cstring separator) { usize i; for (i = 0; i < count; i++) { - printf("%zd\n", i); res[i] = si_string_make_len(original, pos_buffer[i]); - printf("123\n"); original += pos_buffer[i] + separator_len; - printf("123\n"); } return res; } - -inline isize si_string_append(siString* str, cstring other) { - return si_string_append_len(str, other, si_cstr_len(other)); -} -isize si_string_append_len(siString* str, cstring other, usize other_len) { - siStringHeader* header = SI_STRING_HEADER(*str); - usize previous_len = header->len; - header->len += other_len; - - if (header->capacity < header->len) { - isize result = si_string_make_space_for(str, other_len); - SI_ASSERT_MSG(result == SI_OKAY, "Failed to make space for string"); - header = SI_STRING_HEADER(*str); /* NOTE(EimaMei): For some reason we have to refresh the header pointer on Linux. Somewhat makes sense but also what and why. */ - } - - rawptr ptr = memcpy(*str + previous_len, other, other_len); - SI_ASSERT_NOT_NULL(ptr); - (*str)[header->len] = '\0'; - - return SI_OKAY; -} -inline isize si_string_push_back(siString* str, char other) { - return si_string_append_len(str, &other, 1); -} - -inline siString si_string_copy(siString from) { - return si_string_make_len(from, si_string_len(from)); -} -inline isize si_string_clear(siString* str) { - char null_terminator = '\0'; - isize result = si_string_set(str, &null_terminator); - - return result; -} - bool si_strings_are_equal(cstring lhs, cstring rhs) { if (lhs == rhs) { return true; @@ -1809,6 +1886,12 @@ bool si_strings_are_equal(cstring lhs, cstring rhs) { return true; } +inline isize si_string_clear(siString* str) { + char null_terminator = '\0'; + isize result = si_string_set(str, &null_terminator); + + return result; +} inline isize si_string_free(siString str) { if (str == nil) { @@ -1836,6 +1919,7 @@ isize si_string_make_space_for(siString* str, usize add_len) { return SI_OKAY; } +void si_string_shrink_to_fit(siString str); #endif #if defined(SI_CHAR_IMPLEMENTATION) && !defined(SI_STRING_UNDEFINE) @@ -2168,9 +2252,7 @@ siString si_file_read_at(siFile file, usize offset) { */ siArray(siString) si_file_readlines(siFile file) { siString buffer = si_file_read(file); - printf("finish\n"); siArray(siString) res = si_string_split(buffer, "\n"); - printf("finish2\n"); si_string_free(buffer); return res; @@ -2409,9 +2491,7 @@ rawptr si_debug_alloc(usize function_id, rawptr ptr, siDebugArgs args, cstring f cstring type = nil; switch (function_id) { case 1: { /* malloc*/ - printf("hi\n"); res = malloc(sizeof(siDebugHeader) + args.first); - printf("hi\n"); size = args.first; type = "malloc"; break; From 2882a929c3bfa57b1394ddc9f3917e9d7244148c Mon Sep 17 00:00:00 2001 From: EimaMei Date: Sun, 4 Jun 2023 18:48:44 +0300 Subject: [PATCH 03/17] minor adjusments to make it (barely) compile on cunt++ --- .gitignore | 3 +-- Makefile | 4 ++-- sili.h | 40 +++++++++++----------------------------- 3 files changed, 14 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index ba9b875..eb6833f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,4 @@ src/ *.7z *.zip *.hide -*.S -main.c \ No newline at end of file +*.S \ No newline at end of file diff --git a/Makefile b/Makefile index 351cd7b..a3b3cb0 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ OUTPUT = build NAME = test EXE = $(OUTPUT)/$(NAME) -SRC = main.c -FLAGS = -O0 -g -std=c99 -Wall -Wextra -Wpedantic +SRC = src/main.c +FLAGS = -O0 -std=c99 -Wall -Wextra -Wpedantic LIBS = INCLUDE = -I"." diff --git a/sili.h b/sili.h index 5a03e9d..6164f18 100644 --- a/sili.h +++ b/sili.h @@ -759,14 +759,6 @@ cstring si_i64_to_cstr(i64 num); | siFile & siPath | ======================== */ -typedef enum siFileMode { - SI_FILE_MODE_READ = SI_BIT(0), - SI_FILE_MODE_WRITE = SI_BIT(1), - SI_FILE_MODE_READ_WRITE = SI_BIT(2), - SI_FILE_MODE_APPEND = SI_BIT(3), - SI_FILE_MODE_APPEND_READ = SI_BIT(4), - SI_FILE_MODE_CREATE = SI_BIT(5) -} siFileMode; typedef struct siFile { siString path; @@ -804,7 +796,7 @@ bool si_path_is_relative(cstring path); */ siFile si_file_create(cstring path); siFile si_file_open(cstring path); -siFile si_file_open_mode(cstring path, siFileMode mode); +siFile si_file_open_mode(cstring path, const char* mode); usize si_file_size(siFile file); void si_file_size_update(siFile* file); @@ -1189,7 +1181,7 @@ void si_sleep(usize miliseconds) { #if defined(SI_PAIR_IMPLEMENTATION) && !defined(SI_PAIR_UNDEFINE) rawptr si_impl_pair_make(siAny first, siAny second) { - siByte* res = malloc(first.type_width + second.type_width); + siByte* res = (siByte*)malloc(first.type_width + second.type_width); memcpy(res, first.ptr, first.type_width); memcpy(res + first.type_width, second.ptr, second.type_width); @@ -1213,7 +1205,7 @@ inline siArray(void) si_array_copy(siArray(void) array) { return si_array_make_list(array, header->type_width, header->len); } siArray(void) si_array_make_reserve(usize sizeof_element, usize count) { - siByte* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count)); + siByte* ptr = (siByte*)malloc(sizeof(siArrayHeader) + (sizeof_element * count)); siArray(void) array = ptr + sizeof(siArrayHeader); siArrayHeader* header = SI_ARRAY_HEADER(array); @@ -1355,7 +1347,7 @@ isize si_impl_array_append(rawptr array_address, siAny value) { SI_ASSERT_MSG(value.type_width <= header->type_width, "The given value's sizeof is too large compared to the elements' in the arra"); if (header->len == header->capacity) { - siByte* result = si_realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_width, sizeof(siArrayHeader) + 2 * header->capacity * header->type_width); + siByte* result = (siByte*)si_realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_width, sizeof(siArrayHeader) + 2 * header->capacity * header->type_width); SI_ASSERT_NOT_NULL(result); *array = result + sizeof(siArrayHeader); @@ -1706,7 +1698,7 @@ void si_string_insert(siString* str, cstring cstr, usize index) { } siString cur_str = *str; - char* ptr = memcpy(cur_str + header->len - before_index_len, cur_str + index, before_index_len); + char* ptr = (char*)memcpy(cur_str + header->len - before_index_len, cur_str + index, before_index_len); memcpy(cur_str + index + 1, cstr, cstr_len); SI_ASSERT_NOT_NULL(ptr); ptr[header->len] = '\0'; @@ -1715,7 +1707,7 @@ void si_string_erase(siString* str, usize begin, usize end) { usize after_index_len = begin + end; siString cur_str = *str; - char* ptr = memcpy(cur_str + begin, cur_str + after_index_len, si_string_len(cur_str) - after_index_len); + char* ptr = (char*)memcpy(cur_str + begin, cur_str + after_index_len, si_string_len(cur_str) - after_index_len); SI_ASSERT_NOT_NULL(ptr); ptr[si_string_len(cur_str) - after_index_len] = '\0'; @@ -1738,7 +1730,7 @@ void si_string_remove_cstr(siString* str, cstring cstr) { usize after_index_len = index + cstr_len; - char* ptr = memcpy(cur_str + index, cur_str + after_index_len, cur_len - after_index_len); + char* ptr = (char*)memcpy(cur_str + index, cur_str + after_index_len, cur_len - after_index_len); SI_ASSERT_NOT_NULL(ptr); ptr[cur_len - after_index_len] = '\0'; @@ -1855,7 +1847,8 @@ siArray(siString) si_string_split(siString str, cstring separator) { begin_pos = pos + separator_len; } - siArray(siString) res = si_array_make_list(&(rawptr){nil}, sizeof(*res), count); + siArray(siString) res = (siArray(siString))si_array_make_reserve(sizeof(*res), count); /* NOTE(EimaMei): Fuck C++. Seriously, what the fuck? WHY DO WE HAVE TO THIS??? */ + SI_ARRAY_HEADER(res)->len = count; usize i; for (i = 0; i < count; i++) { @@ -2169,25 +2162,14 @@ inline bool si_path_is_relative(cstring path) { inline siFile si_file_create(cstring path) { - return si_file_open_mode(path, SI_FILE_MODE_CREATE); + return si_file_open_mode(path, "w"); } inline siFile si_file_open(cstring path) { - return si_file_open_mode(path, SI_FILE_MODE_READ); + return si_file_open_mode(path, "r"); } siFile si_file_open_mode(cstring path, siFileMode mode) { SI_ASSERT_NOT_NULL(path); - siString mode_str = nil; - switch (mode) { - case SI_FILE_MODE_READ: mode_str = "r"; break; - case SI_FILE_MODE_WRITE: mode_str = "w"; break; - case SI_FILE_MODE_READ_WRITE: mode_str = "r+"; break; - case SI_FILE_MODE_APPEND: mode_str = "a"; break; - case SI_FILE_MODE_APPEND_READ: mode_str = "a+"; break; - case SI_FILE_MODE_CREATE: mode_str = "w+"; break; - default: SI_ASSERT_MSG(mode_str != nil, "Provided mode doesn't exist"); break; - } - FILE* f = fopen(path, mode_str); if (f == nil) { From 6a767664dc786b87df86ba865c094eca3a90323f Mon Sep 17 00:00:00 2001 From: EimaMei Date: Sun, 4 Jun 2023 23:59:26 +0300 Subject: [PATCH 04/17] more str stuff, mostly improved si_string_replace's performance and implemented si_string_shtink_to_fit --- sili.h | 128 +++++++++++++++++++++++++-------------------------------- 1 file changed, 57 insertions(+), 71 deletions(-) diff --git a/sili.h b/sili.h index 6164f18..54e05ed 100644 --- a/sili.h +++ b/sili.h @@ -654,13 +654,13 @@ char si_string_back(siString str); void si_string_sub(siString str, usize begin, usize end, char* result); isize si_string_find(siString str, cstring cstr); -isize si_string_find_ex(siString str, usize start, usize end, cstring cstr); +isize si_string_find_ex(siString str, usize start, usize end, cstring cstr, usize cstr_len); isize si_string_rfind(siString str, cstring cstr); isize si_string_rfind_ex(siString str, usize start, usize end, cstring cstr); isize si_string_join(siString* str, cstring cstr, cstring separator); isize si_string_set(siString* str, cstring cstr); -isize si_string_replace(siString* str, cstring old_str, cstring new_str); +void si_string_replace(siString* str, cstring old_str, cstring new_str); isize si_string_trim(siString* str, cstring cut_set); isize si_string_append(siString* str, cstring other); @@ -668,7 +668,8 @@ isize si_string_append_len(siString* str, cstring other, usize other_len); isize si_string_push_back(siString* str, char other); void si_string_insert(siString* str, cstring cstr, usize index); -void si_string_erase(siString* str, usize begin, usize end); +void si_string_insert_ex(siString* str, cstring cstr, usize cstr_len, usize index, bool erase_index); +void si_string_erase(siString* str, usize index, usize len); void si_string_remove_cstr(siString* str, cstring cstr); void si_string_swap(siString* str, cstring cstr1, cstring cstr2); @@ -680,14 +681,13 @@ isize si_string_strip(siString* str); /* NOTE(EimaMei); This strips any leading isize si_string_reverse(siString* str); isize si_string_reverse_len(siString* str, usize len); - siArray(siString) si_string_split(siString str, cstring separator); bool si_strings_are_equal(cstring lhs, cstring rhs); isize si_string_clear(siString* str); isize si_string_free(siString str); isize si_string_make_space_for(siString* str, usize add_len); -void si_string_shrink_to_fit(siString str); +void si_string_shrink_to_fit(siString* str); #endif @@ -1508,12 +1508,11 @@ void si_string_sub(siString str, usize begin, usize end, char* result) { } inline isize si_string_find(siString str, cstring cstr) { - return si_string_find_ex(str, 0, si_string_len(str), cstr); + return si_string_find_ex(str, 0, si_string_len(str), cstr, si_cstr_len(cstr)); } -isize si_string_find_ex(siString str, usize start, usize end, cstring cstr) { +isize si_string_find_ex(siString str, usize start, usize end, cstring cstr, usize cstr_len) { SI_ASSERT_NOT_NULL(str); - usize cstr_len = si_cstr_len(cstr); bool found = false; usize i; @@ -1588,53 +1587,26 @@ isize si_string_set(siString* str, cstring cstr) { return SI_OKAY; } -isize si_string_replace(siString* str, cstring old_value, cstring new_value) { - usize str_len = si_string_len(*str); - usize new_len = si_cstr_len(new_value); +void si_string_replace(siString* str, cstring old_value, cstring new_value) { usize old_len = si_cstr_len(old_value); + usize new_len = si_cstr_len(new_value); - isize pos = si_string_find(*str, old_value); - - siStringHeader* header = SI_STRING_HEADER(*str); - header->len += new_len - old_len; - - if (pos == SI_ERROR) { - return SI_ERROR; - } - - if (old_len < new_len) { - isize result = si_string_make_space_for(str, new_len - old_len); - SI_ASSERT_MSG(result == SI_OKAY, "Failed to make space for string"); + isize index = 0; + siString cur_str = nil; + bool old_len_bigger = (old_len > new_len); - usize i, j; - char saved_value = '\0'; - for (j = 0; j < new_len - old_len; j++) { /* NOTE(EimaMei): There is probably a much faster way to do this other than looping through the string multiple times. However, as a temporary solution, it works nicely. */ - for (i = pos; i < str_len + new_len - old_len; i++) { - char og = (*str)[j + i]; - (*str)[j + i] = saved_value; - saved_value = og; - } + while (true) { + cur_str = *str; + index = si_string_find_ex(cur_str, index, si_array_len(cur_str), old_value, old_len); + if (index == SI_ERROR) { + break; } - } - if (old_len > new_len) { - usize i, j; - char saved_value = '\0'; - for (j = 0; j < old_len - new_len; j++) { /* NOTE(EimaMei): Read the previous comment above. */ - for (i = str_len; i != (usize)SI_ERROR; i--) { - char og = (*str)[j + i]; - (*str)[j + i] = saved_value; - saved_value = og; - } + if (old_len_bigger) { + si_string_erase(str, index, old_len); } + si_string_insert_ex(str, new_value, new_len, index - old_len_bigger, !old_len_bigger); } - - usize i; - for (i = 0; i < new_len; i++) { - (*str)[i + pos] = new_value[i]; - } - - return pos; } isize si_string_trim(siString* str, cstring cut_set) { char* start = *str; @@ -1684,34 +1656,37 @@ inline isize si_string_push_back(siString* str, char other) { return si_string_append_len(str, &other, 1); } -void si_string_insert(siString* str, cstring cstr, usize index) { +inline void si_string_insert(siString* str, cstring cstr, usize index) { + si_string_insert_ex(str, cstr, si_cstr_len(cstr), index, false); +} +void si_string_insert_ex(siString* str, cstring cstr, usize cstr_len, usize index, bool erase_index) { siStringHeader* header = SI_STRING_HEADER(*str); usize previous_len = header->len; - usize cstr_len = si_cstr_len(cstr); usize before_index_len = previous_len - index; - header->len += cstr_len; + header->len += cstr_len - erase_index; if (header->capacity < header->len) { - isize result = si_string_make_space_for(str, cstr_len); + isize result = si_string_make_space_for(str, header->len - header->capacity); SI_ASSERT_MSG(result == SI_OKAY, "Failed to make space for string"); header = SI_STRING_HEADER(*str); /* NOTE(EimaMei): For some reason we have to refresh the header pointer on Linux. Somewhat makes sense but also what and why. */ } siString cur_str = *str; char* ptr = (char*)memcpy(cur_str + header->len - before_index_len, cur_str + index, before_index_len); - memcpy(cur_str + index + 1, cstr, cstr_len); + memcpy(cur_str + index + !erase_index, cstr, cstr_len); SI_ASSERT_NOT_NULL(ptr); - ptr[header->len] = '\0'; + ptr[before_index_len] = '\0'; } -void si_string_erase(siString* str, usize begin, usize end) { - usize after_index_len = begin + end; +void si_string_erase(siString* str, usize index, usize len) { + usize after_index_len = index + len; siString cur_str = *str; + usize str_len = si_string_len(cur_str); - char* ptr = (char*)memcpy(cur_str + begin, cur_str + after_index_len, si_string_len(cur_str) - after_index_len); + char* ptr = (char*)memcpy(cur_str + index, cur_str + after_index_len, str_len - after_index_len); SI_ASSERT_NOT_NULL(ptr); - ptr[si_string_len(cur_str) - after_index_len] = '\0'; + ptr[str_len - after_index_len] = '\0'; - SI_STRING_HEADER(cur_str)->len -= after_index_len; + SI_STRING_HEADER(cur_str)->len -= len; } void si_string_remove_cstr(siString* str, cstring cstr) { siStringHeader* header = SI_STRING_HEADER(*str); @@ -1835,7 +1810,7 @@ siArray(siString) si_string_split(siString str, cstring separator) { siString original = str; while (true) { - isize pos = si_string_find_ex(str, begin_pos, si_string_len(str), separator); + isize pos = si_string_find_ex(str, begin_pos, si_string_len(str), separator, separator_len); if (pos == SI_ERROR) { pos_buffer[count] = si_string_len(str); @@ -1912,7 +1887,15 @@ isize si_string_make_space_for(siString* str, usize add_len) { return SI_OKAY; } -void si_string_shrink_to_fit(siString str); +void si_string_shrink_to_fit(siString* str) { + SI_ASSERT_NOT_NULL(str); + siString cur_str = *str; + siStringHeader copy = *SI_STRING_HEADER(cur_str); + + siStringHeader* header = realloc(SI_STRING_HEADER(cur_str), sizeof(siStringHeader*) + copy.len + 1); + *header = copy; + header->capacity = header->len; +} #endif #if defined(SI_CHAR_IMPLEMENTATION) && !defined(SI_STRING_UNDEFINE) @@ -2167,10 +2150,10 @@ inline siFile si_file_create(cstring path) { inline siFile si_file_open(cstring path) { return si_file_open_mode(path, "r"); } -siFile si_file_open_mode(cstring path, siFileMode mode) { +siFile si_file_open_mode(cstring path, cstring mode) { SI_ASSERT_NOT_NULL(path); - FILE* f = fopen(path, mode_str); + FILE* f = fopen(path, mode); if (f == nil) { siString message = nil; @@ -2207,18 +2190,21 @@ inline void si_file_size_update(siFile* file) { } inline siString si_file_read(siFile file) { - return si_file_read_at(file, 0); -} -siString si_file_read_at(siFile file, usize offset) { SI_ASSERT_NOT_NULL(file.ptr); - usize read_len = file.size - offset; - char tmp[read_len]; + char tmp[file.size]; + fread(tmp, file.size, 1, file.ptr); + + return si_string_make_len(tmp, file.size); +} +inline siString si_file_read_at(siFile file, usize offset) { si_file_seek(file, offset); - fread(tmp, read_len, 1, file.ptr); + file.size -= offset; + siString res = si_file_read(file); + file.size += offset; si_file_seek_to_end(file); - return si_string_make_len(tmp, read_len); + return res; } /* NOTE/TODO(EimaMei): This has a huge performance hit if the file is, lets say, 400 lines in length. That's over 400 @@ -2271,7 +2257,7 @@ isize si_file_write_at_line(siFile* file, cstring content, usize index) { buffer[index] = (siString)content; siString new_file_content = si_array_to_sistring(buffer, "\n"); - siFile new_file = si_file_open_mode(file->path, SI_FILE_MODE_CREATE); + siFile new_file = si_file_open_mode(file->path, "w"); si_file_write_len(&new_file, new_file_content, si_string_len(new_file_content)); usize i; From a509ea07e32678131974300bb96ad25219a2ccd6 Mon Sep 17 00:00:00 2001 From: EimaMei Date: Tue, 6 Jun 2023 00:21:06 +0300 Subject: [PATCH 05/17] stringify deez nuts --- README.md | 10 +++---- sili.h | 80 ++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index b50dacd..ca7266f 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # Sili Toolchain -Sili Toolchain is a cross-platform public domain software toolchain specialized for C development, featuring many features, improvements and fixes to the language. Made specifically for C99 and up, but can also be used in C++. +Sili Toolchain - a cross-platform software toolchain for modern C programming, featuring many new features, improvements and fixes to the language's barebones STL. Made specifically for C99 and up, but can also be used in C++. -# Main goals of Sili Toolchain +# Main goals ## Modernize C -Implement a proper STL for C that is much more feature-rich, safe, readable and just generally better, while also being an alternative to the C++ one. +Implement a proper STL for C that is much more feature-rich, safe, readable and just generally better, while also being an alternative to the (bloated) C++ one. ## Be fast & useful -Keep a balance between having exceptional performance and giving more options to the end-user. +Keep a balance between having exceptional performance and giving more options to the end-developer. ## Be portable -`sili.h` is a single-header library, meaning it can be drag 'n dropped to any project. Furthermore, Sili Toolchain is cross-platform, meaning it'll work on all major desktop OSses without issue. +`sili.h` is a single-header library, meaning it can be drag 'n dropped to any project. Not only that but Sili Toolchain is designed to be cross-platform between all the dekstop OSses! # Features - Standard types (`u8`, `i32`, `u64` etc). diff --git a/sili.h b/sili.h index 54e05ed..d1dd00a 100644 --- a/sili.h +++ b/sili.h @@ -1,5 +1,5 @@ /* -sili.h - An alternative to the C/C++ standard library. +sili.h - a cross-platform software toolchain for modern C programming =========================================================================== - YOU MUST DEFINE 'SI_IMPLEMENTATION' in EXACTLY _one_ C file that includes this header, BEFORE the include like this: @@ -339,6 +339,9 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); typedef const char* cstring; #endif +#define SI_OKAY 0 +#define SI_ERROR -1 + #define SI_BIT(x) (1 << (x)) #define SI_KILO(x) ( (x) * (usize)1024) @@ -346,23 +349,22 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); #define SI_GIGA(x) (SI_MEGA(x) * (usize)1024) #define SI_TERA(x) (SI_GIGA(x) * (usize)1024) -#define SI_MULTILINE(...) __VA_ARGS__ -#define SI_STR_MULTILINE(...) #__VA_ARGS__ +#define SI_BUILTIN_UNREACHABLE() __builtin_unreachable() -#define SI_ENUM_DECLARE(type, name) type name; enum +#define SI_ENUM(type, name) type name; enum -#define SI_OKAY 0 -#define SI_ERROR -1 +#define SI_MULTILINE(...) __VA_ARGS__ +#define SI_STR_MULTILINE(...) #__VA_ARGS__ #define SI_UNUSED(x) (void)(x) /* NOTE(EimaMei) Should be used when you want to supress "parameter 'X' set but not used" errors. */ -#define si_swap(a, b) do { typeof((a)) tmp = (a); (a) = (b); (b) = tmp; } while (0) -#define si_between(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper))) - #if defined(SI_STANDARD_ANSI) || defined(SI_COMPILER_MSVC) /* NOTE(EimaMei): Fuck Microsoft. */ #define typeof(value) __typeof__(value) #endif +#define si_swap(a, b) do { typeof((a)) tmp = (a); (a) = (b); (b) = tmp; } while (0) +#define si_between(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper))) + #if defined(SI_MEMORY_LOGGING) #define SI_MEMORY_LOGGING_IMPLEMENTATION #endif @@ -409,10 +411,15 @@ usize si_impl_assert_msg(bool condition, cstring condition_str, cstring message, * * ======================== - | siAny & siFunction | + | Mics/General | ======================== */ +/* + ======================== + | siAny | + ======================== +*/ typedef struct siAny { usize type_width; rawptr ptr; @@ -421,12 +428,29 @@ typedef struct siAny { #define si_any_make(value) (siAny){sizeof(typeof(value)), &(typeof(value)){value} } #define si_any_get(any, type) ((any.ptr != nil) ? *((type*)any.ptr) : (type)SI_ASSERT_NOT_NULL(any.ptr)) +/* + ======================== + | siFunction | + ======================== +*/ typedef struct siFunction { rawptr (*ptr)(rawptr); } siFunction; #define siFunc(func) (siFunction){(rawptr (*)(rawptr))func} +/* + ======================== + | Other | + ======================== +*/ +typedef SI_ENUM(usize, siDirection) { + SI_DIRECTION_LEFT, + SI_DIRECTION_RIGHT +}; + +void si_ptr_move_by(rawptr ptr, usize sizeof_ptr, usize move_by, siDirection direction); + /* * * @@ -548,7 +572,8 @@ const siOptionalStruct SI_OPTIONAL_NULL = {{0, nil}, false}; typedef struct siArrayHeader { u32 len; u32 capacity; - u32 type_width; + u16 type_width; + u16 grow; } siArrayHeader; #define siArray(type) type* @@ -662,6 +687,7 @@ isize si_string_join(siString* str, cstring cstr, cstring separator); isize si_string_set(siString* str, cstring cstr); void si_string_replace(siString* str, cstring old_str, cstring new_str); isize si_string_trim(siString* str, cstring cut_set); +void si_string_stringify(siString* str); isize si_string_append(siString* str, cstring other); isize si_string_append_len(siString* str, cstring other, usize other_len); @@ -892,7 +918,7 @@ void si_thread_set_priority(siThread t, i32 priority); #define SI_TIME_FIRST_WEEKDAY_MONDAY #endif -typedef SI_ENUM_DECLARE(usize, siMonth) { +typedef SI_ENUM(usize, siMonth) { siJanuary = 1, siFebruary, siMarch, @@ -909,7 +935,7 @@ typedef SI_ENUM_DECLARE(usize, siMonth) { /* NOTE(EimaMi): For whatever reason some places uses Sunday as the first weekday, while MOST of Europe views monday as the first weekday. So by default Monday will be set as the first weekday with the options to change it depending on your taste. */ -typedef SI_ENUM_DECLARE(usize, siWeek) { +typedef SI_ENUM(usize, siWeek) { #if defined(SI_TIME_FIRST_WEEKDAY_MONDAY) Monday, Tuesday, @@ -1171,11 +1197,20 @@ rawptr si_realloc(rawptr ptr, usize old_size, usize new_size) { void si_sleep(usize miliseconds) { #if defined(SI_SYSTEM_WINDOWS) - Sleep(miliseconds); + Sleep(miliseconds); #else - usleep(miliseconds * 1000); + usleep(miliseconds * 1000); #endif } + +void si_ptr_move_by(rawptr ptr, usize sizeof_ptr, usize move_by, siDirection direction) { + switch (direction) { /* NOTE(EimaMei): Did you really think I was gonna use 'memmove'? That's much slower! */ + case SI_DIRECTION_RIGHT: memcpy((siByte*)ptr + move_by, ptr, sizeof_ptr); break; + case SI_DIRECTION_LEFT: memcpy((siByte*)ptr - move_by, ptr, sizeof_ptr); break; + default: SI_BUILTIN_UNREACHABLE(); + } +} + #endif #if defined(SI_PAIR_IMPLEMENTATION) && !defined(SI_PAIR_UNDEFINE) @@ -1631,6 +1666,21 @@ isize si_string_trim(siString* str, cstring cut_set) { return SI_OKAY; } +void si_string_stringify(siString* str) { + siStringHeader* header = SI_STRING_HEADER(*str); + header->len += 2; + + if (header->capacity < header->len) { + isize res = si_string_make_space_for(str, 2); + SI_ASSERT_MSG(res == SI_OKAY, "Failed to allocate space to str"); + header = SI_STRING_HEADER(*str); + } + siString cur_str = *str; + + si_ptr_move_by(cur_str, header->len, 1, SI_DIRECTION_RIGHT); + cur_str[0] = '\"'; + cur_str[header->len - 1] = '\"'; +} inline isize si_string_append(siString* str, cstring other) { return si_string_append_len(str, other, si_cstr_len(other)); From f020249d43c35f0802f609c80be36d0f9c09b4bc Mon Sep 17 00:00:00 2001 From: EimaMei Date: Tue, 6 Jun 2023 01:23:15 +0300 Subject: [PATCH 06/17] i wanst slep --- sili.h | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/sili.h b/sili.h index d1dd00a..26f8c9e 100644 --- a/sili.h +++ b/sili.h @@ -449,7 +449,7 @@ typedef SI_ENUM(usize, siDirection) { SI_DIRECTION_RIGHT }; -void si_ptr_move_by(rawptr ptr, usize sizeof_ptr, usize move_by, siDirection direction); +void si_ptr_move_by(rawptr src, usize src_len, usize move_by, siDirection direction); /* * @@ -610,7 +610,6 @@ isize si_array_reverse(siArray(void) array); char* si_array_to_sistring(siArray(char*) array, cstring separator); #define si_array_append(array_address, value) si_impl_array_append(array_address, si_any_make(value)) -#define si_array_push_back(array_address, value) si_array_append(array_address, value) isize si_array_clear(rawptr array_address); bool si_arrays_are_equal(siArray(void) lha, siArray(void) rha); @@ -648,7 +647,7 @@ isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_val #if !defined(SI_ARRAY_UNDEFINE) typedef siArrayHeader siStringHeader; #else - typedef struct { u32 len; u32 capacity; u32 type_width; } siStringHeader; + typedef struct { u32 len; u32 capacity; u16 type_width; u16 grow; } siStringHeader; #if defined(SI_STANDARD_C89) #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) #else @@ -657,8 +656,8 @@ isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_val #endif typedef siArray(char) siString; -typedef siArray(i32) siRunes; #define SI_STRING_HEADER(s) ((siStringHeader*)s - 1) +#define SI_STRING_DEFAULT_GROW 128 siString si_string_make(cstring str); @@ -691,11 +690,12 @@ void si_string_stringify(siString* str); isize si_string_append(siString* str, cstring other); isize si_string_append_len(siString* str, cstring other, usize other_len); -isize si_string_push_back(siString* str, char other); +isize si_string_push(siString* str, char other); +void si_string_pop(siString* str); void si_string_insert(siString* str, cstring cstr, usize index); void si_string_insert_ex(siString* str, cstring cstr, usize cstr_len, usize index, bool erase_index); -void si_string_erase(siString* str, usize index, usize len); +void si_string_erase(siString* str, usize index, usize erase_len); void si_string_remove_cstr(siString* str, cstring cstr); void si_string_swap(siString* str, cstring cstr1, cstring cstr2); @@ -1203,10 +1203,10 @@ void si_sleep(usize miliseconds) { #endif } -void si_ptr_move_by(rawptr ptr, usize sizeof_ptr, usize move_by, siDirection direction) { +void si_ptr_move_by(rawptr src, usize src_len, usize move_by, siDirection direction) { switch (direction) { /* NOTE(EimaMei): Did you really think I was gonna use 'memmove'? That's much slower! */ - case SI_DIRECTION_RIGHT: memcpy((siByte*)ptr + move_by, ptr, sizeof_ptr); break; - case SI_DIRECTION_LEFT: memcpy((siByte*)ptr - move_by, ptr, sizeof_ptr); break; + case SI_DIRECTION_RIGHT: memcpy((siByte*)src + move_by, src, src_len); break; + case SI_DIRECTION_LEFT: memcpy((siByte*)src - move_by, src, src_len); break; default: SI_BUILTIN_UNREACHABLE(); } } @@ -1702,9 +1702,13 @@ isize si_string_append_len(siString* str, cstring other, usize other_len) { return SI_OKAY; } -inline isize si_string_push_back(siString* str, char other) { +inline isize si_string_push(siString* str, char other) { return si_string_append_len(str, &other, 1); } +inline void si_string_pop(siString* str) { + siString cur_str = *str; + cur_str[SI_ARRAY_HEADER(cur_str)->len - 1] = '\0'; +} inline void si_string_insert(siString* str, cstring cstr, usize index) { si_string_insert_ex(str, cstr, si_cstr_len(cstr), index, false); @@ -1727,8 +1731,8 @@ void si_string_insert_ex(siString* str, cstring cstr, usize cstr_len, usize inde SI_ASSERT_NOT_NULL(ptr); ptr[before_index_len] = '\0'; } -void si_string_erase(siString* str, usize index, usize len) { - usize after_index_len = index + len; +void si_string_erase(siString* str, usize index, usize erase_len) { + usize after_index_len = index + erase_len; siString cur_str = *str; usize str_len = si_string_len(cur_str); @@ -1736,7 +1740,7 @@ void si_string_erase(siString* str, usize index, usize len) { SI_ASSERT_NOT_NULL(ptr); ptr[str_len - after_index_len] = '\0'; - SI_STRING_HEADER(cur_str)->len -= len; + SI_STRING_HEADER(cur_str)->len -= erase_len; } void si_string_remove_cstr(siString* str, cstring cstr) { siStringHeader* header = SI_STRING_HEADER(*str); From 72d88b6120f82e29520f00d16f2284ba0d6c6e8e Mon Sep 17 00:00:00 2001 From: EimaMei Date: Tue, 6 Jun 2023 01:26:20 +0300 Subject: [PATCH 07/17] small bug fix --- sili.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sili.h b/sili.h index 26f8c9e..c250a5c 100644 --- a/sili.h +++ b/sili.h @@ -1531,7 +1531,7 @@ inline char si_string_front(siString str) { inline char si_string_back(siString str) { SI_ASSERT_NOT_NULL(str); if (si_string_len(str) == 0) { - return SI_OKAY; + return '\0'; } return str[si_string_len(str) - 1]; @@ -1708,6 +1708,7 @@ inline isize si_string_push(siString* str, char other) { inline void si_string_pop(siString* str) { siString cur_str = *str; cur_str[SI_ARRAY_HEADER(cur_str)->len - 1] = '\0'; + SI_ARRAY_HEADER(cur_str)->len -= 1; } inline void si_string_insert(siString* str, cstring cstr, usize index) { From 98b74922fd01bbb802b6bc94fce2cb0a4caea1ac Mon Sep 17 00:00:00 2001 From: EimaMei Date: Thu, 8 Jun 2023 23:17:34 +0300 Subject: [PATCH 08/17] siBuffers, siString/siArray rework, some documentation done --- README.md | 19 +- sili.h | 819 +++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 638 insertions(+), 200 deletions(-) diff --git a/README.md b/README.md index ca7266f..eaf611b 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,16 @@ # Sili Toolchain -Sili Toolchain - a cross-platform software toolchain for modern C programming, featuring many new features, improvements and fixes to the language's barebones STL. Made specifically for C99 and up, but can also be used in C++. +Sili Toolchain is a cross-platform software toolchain for modern C programming, providing many new features, improvements and fixes to the language's barebones STL. It is specifically designed for C99 and above but can also be used in C++ codebases. # Main goals ## Modernize C -Implement a proper STL for C that is much more feature-rich, safe, readable and just generally better, while also being an alternative to the (bloated) C++ one. -## Be fast & useful -Keep a balance between having exceptional performance and giving more options to the end-developer. -## Be portable -`sili.h` is a single-header library, meaning it can be drag 'n dropped to any project. Not only that but Sili Toolchain is designed to be cross-platform between all the dekstop OSses! +The toolchain aims to modernize C by implementing a proper STL that is more feature-rich, fast, safe and understandable. It serves as an alternative to the bloated C++ STL. +## Performance & Utility +Sili Toolchain strives to strike a balance between having exceptional performance and while providing more options to end-developers. +## Portability +`sili.h` is a single-header library, allowing for easy integration into any project. Furthermore, Sili Toolchain is designed to be cross-platform, supporting all major desktop operating systems. # Features -- Standard types (`u8`, `i32`, `u64` etc). -- Macros that define what architecture/OS/compiler/standard you are on (`SI_CPU_X86`, `SI_SYSTEM_WINDOWS`, `SI_COMPILER_CLANG`, `SI_STANDARD_C99`, `SI_STANDARD_ANSI` etc). +- Architecture/OS/Compiler/Standard indentification macros (`SI_CPU_X86`, `SI_SYSTEM_WINDOWS`, `SI_COMPILER_CLANG`, `SI_STANDARD_C99`, `SI_STANDARD_ANSI` etc). - Useful macros (`typeof()`, `SI_ASSERT`/`SI_STATIC_ASSERT`, `SI_BIT`, `foreach` etc). - Robust string implementation (`siString`, fully compatible with `char*`). - Better arrays (`siArray()`, compatible with other C arrays`). @@ -25,7 +24,7 @@ Keep a balance between having exceptional performance and giving more options to - ... and more to come! # Examples -Go to [example.c](example.c) to see examples for almost every feature in the toolchain. You can also unexpand the brackets to hide the examples you're not interested in viewing with your IDE of choice. +[needs a rework later] # License `sili.h` is dual-licensed to the public domain and under the MIT license, meaning it can be used in any want you'd like to. Credit is appreciated but unneeded. @@ -41,6 +40,4 @@ Go to [example.c](example.c) to see examples for almost every feature in the too - `insert()`/`remove()` for siString/siArray. # Improvements -- Improve si_array_make. -- Possible better debugging improvements. - Make thread priority values cross-platform. \ No newline at end of file diff --git a/sili.h b/sili.h index c250a5c..e04c56c 100644 --- a/sili.h +++ b/sili.h @@ -14,6 +14,7 @@ sili.h - a cross-platform software toolchain for modern C programming - #define SI_PAIR_UNDEFINE - #define SI_OPTIONAL_UNDEFINE - #define SI_ARRAY_UNDEFINE + - #define SI_BUFFER_UNDEFINE - #define SI_STRING_UNDEFINE - #define SI_CHAR_UNDEFINE - #define SI_FILE_UNDEFINE @@ -339,6 +340,11 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); typedef const char* cstring; #endif +/* + ======================== + | Constants | + ======================== +*/ #define SI_OKAY 0 #define SI_ERROR -1 @@ -351,25 +357,74 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); #define SI_BUILTIN_UNREACHABLE() __builtin_unreachable() +/* + ======================== + | Declaration macros | + ======================== +*/ #define SI_ENUM(type, name) type name; enum +#define SI_FUNC_PTR(var_name, ...) (*var_name)__VA_ARGS__ +#define SI_UNUSED(x) (void)(x) /* NOTE(EimaMei) Should be used when you want to supress "parameter 'X' set but not used" errors. */ +/* + ======================== + | Macro related | + ======================== +*/ +#define SI_CAT(a, b) a##b #define SI_MULTILINE(...) __VA_ARGS__ #define SI_STR_MULTILINE(...) #__VA_ARGS__ -#define SI_UNUSED(x) (void)(x) /* NOTE(EimaMei) Should be used when you want to supress "parameter 'X' set but not used" errors. */ +/* + ======================== + | Casting | + ======================== +*/ +#define si_cast(type, value) ((type)((value))) +#define si_transmute(type, value) *((type*)&(value)) -#if defined(SI_STANDARD_ANSI) || defined(SI_COMPILER_MSVC) /* NOTE(EimaMei): Fuck Microsoft. */ +/* + ======================== + | Unary operators | + ======================== +*/ +#if !defined(typeof) #define typeof(value) __typeof__(value) #endif +#if !defined(countof) + #define countof(array) (sizeof(array) / sizeof(*(array))) +#endif +#if !defined(offsetof) + #define offsetof(type, element) ((isize)&(((type*)nil)->element)) +#endif +#if !defined(alignof) + #define alignof(type) si_offsetof(struct { char c; type member; }, member) +#endif +/* + ======================== + | Generally functions | + ======================== +*/ #define si_swap(a, b) do { typeof((a)) tmp = (a); (a) = (b); (b) = tmp; } while (0) #define si_between(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper))) +#define si_pause() do { printf("Press any key to continue...\n"); getchar() }; while(0) + +#define for_range_2(count_var, struct_name, ...) \ + siVector2D struct_name = __VA_ARGS__; \ + for (isize count_var = struct_name.x; count_var < struct_name.y; count_var += 1) \ + +#define for_range_1(count_var, line, ...) \ + for_range_2(count_var, SI_CAT(__si_impl_range_, line), __VA_ARGS__) + +#define for_range(count_var, ...) \ + for_range_1(count_var, __LINE__, __VA_ARGS__) + #if defined(SI_MEMORY_LOGGING) #define SI_MEMORY_LOGGING_IMPLEMENTATION #endif - /* * * @@ -386,34 +441,19 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); * * ======================== - | SI_ASSERT | + | Mics/General | ======================== */ -usize si_impl_assert_msg(bool condition, cstring condition_str, cstring message, cstring file, i32 line); -#define SI_ASSERT_MSG(condition, message) si_impl_assert_msg(condition, #condition, message, __FILE__, __LINE__) -#define SI_ASSERT(condition) SI_ASSERT_MSG(condition, nil) -#define SI_ASSERT_NOT_NULL(ptr) SI_ASSERT_MSG((ptr) != nil, #ptr " must not be NULL") - /* -* -* -* -* -* -* -* -* -* -* -* -* -* -* ======================== - | Mics/General | + | SI_ASSERT | ======================== */ +usize si_impl_assert_msg(bool condition, cstring condition_str, cstring message, cstring file, i32 line); +#define SI_ASSERT_MSG(condition, message) si_impl_assert_msg(condition, #condition, message, __FILE__, __LINE__) +#define SI_ASSERT(condition) SI_ASSERT_MSG(condition, nil) +#define SI_ASSERT_NOT_NULL(ptr) SI_ASSERT_MSG((ptr) != nil, #ptr " must not be NULL") /* ======================== @@ -421,11 +461,11 @@ usize si_impl_assert_msg(bool condition, cstring condition_str, cstring message, ======================== */ typedef struct siAny { - usize type_width; rawptr ptr; + usize type_size; } siAny; -#define si_any_make(value) (siAny){sizeof(typeof(value)), &(typeof(value)){value} } +#define si_any_make(value) (siAny){&(typeof(value)){value}, sizeof(typeof(value))} #define si_any_get(any, type) ((any.ptr != nil) ? *((type*)any.ptr) : (type)SI_ASSERT_NOT_NULL(any.ptr)) /* @@ -434,21 +474,35 @@ typedef struct siAny { ======================== */ typedef struct siFunction { - rawptr (*ptr)(rawptr); + rawptr SI_FUNC_PTR(ptr, (rawptr)); } siFunction; -#define siFunc(func) (siFunction){(rawptr (*)(rawptr))func} +#define siFunc(func) (siFunction){(SI_FUNC_PTR(, (rawptr)))func} /* ======================== | Other | ======================== */ +typedef struct siIVector2D { + isize x; + isize y; +} siIVector2D; + +typedef struct siUVector2D { + usize x; + usize y; +} siUVector2D; + +typedef siIVector2D siVector2D; + + typedef SI_ENUM(usize, siDirection) { SI_DIRECTION_LEFT, SI_DIRECTION_RIGHT }; + void si_ptr_move_by(rawptr src, usize src_len, usize move_by, siDirection direction); /* @@ -539,11 +593,11 @@ typedef struct siOptionalStruct { } siOptionalStruct; #define siOptional(type) siOptionalStruct -const siOptionalStruct SI_OPTIONAL_NULL = {{0, nil}, false}; +const siOptionalStruct SI_OPTIONAL_NULL = {{nil, 0}, false}; #define si_optional_make(value) (siOptionalStruct){si_any_make(value), true} -#define si_optional_if_no_value_type(siOptional_var, or_value, type) (siOptional_var.has_value ? si_any_get(siOptional_var.value, type) : (type)or_value) -#define si_optional_if_no_value(siOptional_var, or_value) si_optional_if_no_value_type(siOptional_var, or_value, typeof(or_value)) +#define si_optional_get(type, siOptional_var) si_any_get(siOptional_var.value, type) +#define si_optional_get_or_default(type, siOptional_var, default_value) (siOptional_var.has_value ? si_any_get(siOptional_var.value, type) : (type)default_value) /* NOTE(EimaMei): If the `siOptional` variable is empty, it'll return the 'or_value'. The type of `or_value` must be the same as the type for the `siOptional` variable. */ #endif @@ -572,12 +626,12 @@ const siOptionalStruct SI_OPTIONAL_NULL = {{0, nil}, false}; typedef struct siArrayHeader { u32 len; u32 capacity; - u16 type_width; + u16 type_size; u16 grow; } siArrayHeader; #define siArray(type) type* -#define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1) +#define SI_ARRAY_HEADER(array) ((siArrayHeader*)array - 1) #if defined(SI_STANDARD_C89) #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) @@ -585,45 +639,120 @@ typedef struct siArrayHeader { #define foreach(variable_name, array) for (typeof(array) variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) #endif -/* siArray(void) si_array_make(rawptr array); */ -#define si_array_make(...) si_array_make_list(__VA_ARGS__, sizeof(*(__VA_ARGS__)), sizeof(__VA_ARGS__) / sizeof(*(__VA_ARGS__))) -siArray(void) si_array_make_list(rawptr list, usize sizeof_element, usize count); -siArray(void) si_array_copy(siArray(void) array); -siArray(void) si_array_make_reserve(usize sizeof_element, usize count); +#define si_array_get_ptr(array, index) \ + (si_cast(siByte*, array) + si_array_type_size(array) * (index)) + +/* rawptr si_array_make(rawptr array); */ +#define si_array_make(...) si_array_make_list(__VA_ARGS__, sizeof(*(__VA_ARGS__)), count(__VA_ARGS__)) +rawptr si_array_make_list(rawptr list, usize sizeof_element, usize count); +rawptr si_array_copy(rawptr array); +rawptr si_array_make_reserve(usize sizeof_element, usize count); -usize si_array_len(siArray(void) array); -usize si_array_capacity(siArray(void) array); -usize si_array_type_width(siArray(void) array); -usize si_array_size_in_bytes(siArray(void) array); +usize si_array_len(rawptr array); +usize si_array_capacity(rawptr array); +usize si_array_type_size(rawptr array); +usize si_array_total_size(rawptr array); -siAny si_array_at(siArray(void) array, usize index); -siAny si_array_front(siArray(void) array); -siAny si_array_back(siArray(void) array); +siAny si_array_at(rawptr array, usize index); +siAny si_array_front(rawptr array); +siAny si_array_back(rawptr array); + +#define si_array_append(array_address, value) si_impl_array_append(array_address, si_any_make(value)) -#define si_array_find(array, value) si_impl_array_find_ex(array, 0, si_array_len(array), si_any_make(value)) -#define si_array_find_ex(array, start, end, value) si_impl_array_find_ex(array, start, end, si_any_make(value)) -#define si_array_rfind(array, value) si_impl_array_rfind_ex(array, si_array_len(array) - 1, 0, si_any_make(value)) -#define si_array_rfind_ex(array, start, end, value) si_impl_array_rfind_ex(array, start, end, si_any_make(value)) +#define si_array_find(array, value) si_impl_array_find(array, 0, si_array_len(array), si_any_make(value)) +#define si_array_find_ex(array, start, end, value) si_impl_array_find(array, start, end, si_any_make(value)) +#define si_array_rfind(array, value) si_impl_array_rfind(array, si_array_len(array) - 1, 0, si_any_make(value)) +#define si_array_rfind_ex(array, start, end, value) si_impl_array_rfind(array, start, end, si_any_make(value)) #define si_array_replace(array_address, old_value, new_value) si_impl_array_replace(array_address, si_any_make(old_value), si_any_make(new_value)) -isize si_array_reverse(siArray(void) array); +isize si_array_reverse(rawptr array); char* si_array_to_sistring(siArray(char*) array, cstring separator); -#define si_array_append(array_address, value) si_impl_array_append(array_address, si_any_make(value)) - isize si_array_clear(rawptr array_address); -bool si_arrays_are_equal(siArray(void) lha, siArray(void) rha); +bool si_arrays_are_equal(rawptr lha, rawptr rha); -isize si_array_free(siArray(void) array); +isize si_array_free(rawptr array); /* NOTE(EimaMei): The actual implementations. Shouldn't be used in practice, really. */ -isize si_impl_array_find_ex(rawptr array, usize start, usize end, siAny value); -isize si_impl_array_rfind_ex(rawptr array, usize start, usize end, siAny value); +isize si_impl_array_find(rawptr array, usize start, usize end, siAny value); +isize si_impl_array_rfind(rawptr array, usize start, usize end, siAny value); isize si_impl_array_append(rawptr array_address, siAny value); isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_value); #endif +#if !defined(SI_BUFFER_UNDEFINE) +/* +* +* +* +* +* +* +* +* +* +* +* +* +* +* + ======================== + | siBuffer | + ======================== +*/ +typedef struct siBufferHeader { + usize len; + u32 type_size; +} siBufferHeader; + +#define SI_BUFFER_HEADER(buffer) (&(siBufferHeader){si_buffer_len(buffer), si_buffer_type_width(buffer)}) + +#define si_buffer_get_ptr(buffer, type_size, index) ((siByte*)buffer + type_size * index) + + +#define si_buffer_make(type, ...) (type[])__VA_ARGS__ +#define si_buffer_make_siarray(buffer) si_buffer_make(si_array_len(type), buffer) +/* #define si_buffer_make */ +#define si_buffer_make_reserve(type, count) ((type[count]){}) + +#define si_buffer_len(buffer) countof(buffer) +#define si_buffer_capacity(buffer) countof(buffer) +#define si_buffer_type_width(buffer) sizeof(*buffer) +#define si_buffer_total_size(buffer) (sizeof(buffer) * sizeof(*(buffer))) + +#define si_buffer_at(buffer, index) si_impl_buffer_at(buffer, SI_BUFFER_HEADER(buffer), index) +#define si_buffer_front(buffer) si_impl_buffer_at(buffer, SI_BUFFER_HEADER(buffer), 0) +#define si_buffer_back(buffer) si_impl_buffer_at(buffer, SI_BUFFER_HEADER(buffer), countof(buffer) - 1) + +#define si_buffer_find(buffer, value) si_impl_buffer_find(buffer, SI_BUFFER_HEADER(buffer), 0, countof(buffer), si_any_make(value)) +#define si_buffer_find_ex(buffer, start, end, value) si_impl_buffer_rfind(buffer, SI_BUFFER_HEADER(buffer), start, end si_any_make(value)) +#define si_buffer_rfind(buffer, value) si_impl_buffer_rfind(buffer, SI_BUFFER_HEADER(buffer), countof(buffer) - 1, 0, si_any_make(value)) +#define si_buffer_rfind_ex(buffer, start, end, value) si_impl_buffer_rfind(buffer, SI_BUFFER_HEADER(buffer), start, end si_any_make(value)) + +#define si_buffer_replace(buffer, old_value, new_value) si_impl_buffer_replace(buffer, SI_BUFFER_HEADER(buffer), si_any_make(old_value), si_any_make(new_value)) +#define si_buffer_reverse(buffer) si_impl_buffer_reverse(buffer, SI_BUFFER_HEADER(buffer)) +#define si_buffer_to_sistring(buffer, separator) si_impl_buffer_to_sistring(buffer, SI_BUFFER_HEADER(buffer), separator) + + +#define si_buffer_clear(buffer) si_impl_buffer_clear(buffer, SI_BUFFER_HEADER(buffer)) +#define si_buffer_compare(buffer_left, buffer_right) si_impl_buffer_compare(buffer_left, SI_BUFFER_HEADER(buffer_left), buffer_right, SI_BUFFER_HEADER(buffer_right)) + + +/* NOTE(EimaMei): The actual implementations. Shouldn't be used in practice, really. */ +inline siOptional(rawptr) si_impl_buffer_at(rawptr buffer, siBufferHeader* header, usize index); + +isize si_impl_buffer_find(rawptr buffer, siBufferHeader* header, usize start, usize end, siAny value); +isize si_impl_buffer_rfind(rawptr buffer, siBufferHeader* header, usize start, usize end, siAny value); + +isize si_impl_buffer_replace(rawptr buffer, siBufferHeader* header, siAny old_value, siAny new_value); +isize si_impl_buffer_reverse(rawptr buffer, siBufferHeader* header); +char* si_impl_buffer_to_sistring(rawptr buffer, siBufferHeader* header, cstring separator); + +void si_impl_buffer_clear(rawptr buffer, siBufferHeader* header); +bool si_impl_buffer_compare(rawptr buffer_left, siBufferHeader* header_left, rawptr buffer_right, siBufferHeader* header_right); +#endif + #if !defined(SI_STRING_UNDEFINE) /* * @@ -644,53 +773,255 @@ isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_val | siString | ======================== */ -#if !defined(SI_ARRAY_UNDEFINE) - typedef siArrayHeader siStringHeader; + +/** + * @typedef siString + * @brief siString is a dynamic string type. + */ +typedef siArray(char) siString; + +/** + * @typedef siStringHeader + * @brief siStringHeader is the header structure for siString. + */ +typedef struct siStringHeader { + usize len; + usize capacity; + u16 type_size; + u16 grow; +} siStringHeader; + +/** + * @def foreach(variable_name, array) + * + * @brief Macro to iterate over elements of a siString. + * + * @param variable_name The name of the iterator variable. + * @param array The siString to iterate over. + */ +#if defined(SI_STANDARD_C89) +#define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) #else - typedef struct { u32 len; u32 capacity; u16 type_width; u16 grow; } siStringHeader; - #if defined(SI_STANDARD_C89) - #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) - #else - #define foreach(variable_name, array) for (typeof(array) variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) - #endif +#define foreach(variable_name, array) for (typeof(array) variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) #endif -typedef siArray(char) siString; -#define SI_STRING_HEADER(s) ((siStringHeader*)s - 1) +/** + * @def SI_STRING_HEADER(str) + * @brief Macro to get the header of a siString. + * @param str The siString. + * @return The header pointer of the siString (siDebugHeader*). + */ +#define SI_STRING_HEADER(str) ((siStringHeader*)str - 1) #define SI_STRING_DEFAULT_GROW 128 + + +/** + * @brief Create a new siString from a null-terminated C string. + * + * @param str The null-terminated C string. + * + * @return The created siString. + */ siString si_string_make(cstring str); + +/** + * @brief Create a new siString from a formatted null-terminated C string. + * + * @param str The formatted null-terminated C string. + * + * @return The created siString. + */ siString si_string_make_fmt(cstring str, ...); + +/** + * @brief Create a new siString from a null-terminated C string with a specified length. + * + * @param str The null-terminated C string. + * @param len The length of the string. + * + * @return The created siString. + */ siString si_string_make_len(cstring str, usize len); + +/** + * @brief Create a new siString with a reserved capacity. + * + * @param len The reserved capacity for the siString. + * + * @return The created siString. + */ siString si_string_make_reserve(usize len); + + +/** + * @brief Create a copy of an existing siString. + * + * @param from The siString to copy. + * + * @return The copied siString. + */ siString si_string_copy(siString from); + +/** + * @brief Get the length of a siString. + * @param str The siString. + * @return The length of the siString. + */ usize si_string_len(siString str); + +/** + * @brief Get the capacity of a siString. + * @param str The siString. + * @return The capacity of the siString. + */ usize si_string_capacity(siString str); -usize si_string_type_width(siString str); -bool si_string_is_empty(siString str); +/** + * @brief Get the type size of a siString. + * @param str The siString. + * @return The type size of the siString. + */ +usize si_string_type_size(siString str); + +/** + * @brief Get the character at a specified index in a siString. + * @param str The siString. + * @param index The index of the character. + * @return The character at the specified index. + */ +bool si_string_empty(siString str); + + + +/** + * @brief Get the character at a specified index in a siString. + * + * @param str The siString. + * @param index The index of the character. + * + * @return The character at the specified index. If the function failed to get an + * error + */ char si_string_at(siString str, usize index); + +/** + * @brief Get the first character of a siString. + * + * @param str The siString. + * + * @return The first character of the siString. + */ char si_string_front(siString str); + +/** + * @brief Get the last character of a siString. + * + * @param str The siString. + * + * @return The last character of the siString. + */ char si_string_back(siString str); -void si_string_sub(siString str, usize begin, usize end, char* result); +/** + * @brief Get a substring of a siString and stores it in the provided buffer. + + * @param str The siString from which to extract the substring. + * @param begin The starting index of where to extract. + * @param len The length of the substring. + * @param result A pointer to a buffer to store the substring. The buffer should + * have a size of at least `len + 1` to accommodate the substring + * characters and the NULL terminator. + * + * @attention The result buffer must be large enough to hold the substring, + * including the NULL terminator. See `param result` for more. + */ +void si_string_sub(siString str, usize begin, usize len, char* result); + + +/** + * @brief Find the first occurrence of a substring in a siString. + * + * @param str The siString. + * @param cstr The substring to find. + * + * @return The index of the first occurrence of the substring, or -1 if not found. + */ isize si_string_find(siString str, cstring cstr); + +/** + * @brief Find the first occurrence of a substring within a specific range of a + * siString. + * + * @note This is the expanded version of the `si_string_find` function. Should be + * used for specifying the range and when the substring length is known. + * + * @param str The siString to search within. + * @param start The index to start the search from. + * @param end The index to end the search at. + * @param cstr The substring to find within the siString. + * @param cstr_len The length of the substring. + * + * @return The index of the first occurrence of the substring within the given + * range, or -1 if the substring is not found. + */ isize si_string_find_ex(siString str, usize start, usize end, cstring cstr, usize cstr_len); + +/** + * @brief Find the last occurrence of a substring in a siString. + * + * @param str The siString. + * @param cstr The substring to find. + * + * @return The index of the last occurrence of the substring, or -1 if not found. + */ isize si_string_rfind(siString str, cstring cstr); + +/** + * @brief Find the last occurrence of a substring within a specific range of a + * siString. + * + * @note This is the expanded version of the `si_string_rfind` function. Should be + * used for specifying the range and when the substring length is known. + * + * @param str The siString to search within. + * @param start The index to start the search from (inclusive). + * @param end The index to end the search at (exclusive). + * @param cstr The substring to find within the siString. + * @param cstr_len The length of the substring. + * + * @return The index of the last occurrence of the substring within the given + * range, or -1 if the substring is not found. + */ isize si_string_rfind_ex(siString str, usize start, usize end, cstring cstr); -isize si_string_join(siString* str, cstring cstr, cstring separator); -isize si_string_set(siString* str, cstring cstr); + +/** + * @brief Join a siString with a null-terminated C string using a separator. + * + * This function appends a null-terminated C string, `cstr`, to the end of the + * given siString, `str`, using a specified separator. The separator is inserted + * between `str` and `cstr` in the resulting siString. The function modifies the + * original `str` and returns its new length. + * + * @param str The siString to join. + * @param cstr The null-terminated C string to append. + * @param separator The separator string to insert between `str` and `cstr`. + * + * @return The new length of the siString after the join operation. + */ +void si_string_join(siString* str, cstring cstr, cstring separator); +void si_string_set(siString* str, cstring cstr); void si_string_replace(siString* str, cstring old_str, cstring new_str); -isize si_string_trim(siString* str, cstring cut_set); -void si_string_stringify(siString* str); +void si_string_trim(siString* str, cstring cut_set); +void si_string_enquote(siString* str); -isize si_string_append(siString* str, cstring other); -isize si_string_append_len(siString* str, cstring other, usize other_len); -isize si_string_push(siString* str, char other); +void si_string_append(siString* str, cstring other); +void si_string_append_len(siString* str, cstring other, usize other_len); +void si_string_push(siString* str, char other); void si_string_pop(siString* str); void si_string_insert(siString* str, cstring cstr, usize index); @@ -699,19 +1030,19 @@ void si_string_erase(siString* str, usize index, usize erase_len); void si_string_remove_cstr(siString* str, cstring cstr); void si_string_swap(siString* str, cstring cstr1, cstring cstr2); -isize si_string_upper(siString* str); -isize si_string_lower(siString* str); -isize si_string_title(siString* str); -isize si_string_capitalize(siString* str); -isize si_string_strip(siString* str); /* NOTE(EimaMei); This strips any leading or trailing spaces in the string. */ -isize si_string_reverse(siString* str); -isize si_string_reverse_len(siString* str, usize len); +void si_string_upper(siString* str); +void si_string_lower(siString* str); +void si_string_title(siString* str); +void si_string_capitalize(siString* str); +void si_string_strip(siString* str); /* NOTE(EimaMei); This strips any leading or trailing spaces in the string. */ +void si_string_reverse(siString* str); +void si_string_reverse_len(siString* str, usize len); siArray(siString) si_string_split(siString str, cstring separator); bool si_strings_are_equal(cstring lhs, cstring rhs); -isize si_string_clear(siString* str); +void si_string_clear(siString* str); -isize si_string_free(siString str); +void si_string_free(siString str); isize si_string_make_space_for(siString* str, usize add_len); void si_string_shrink_to_fit(siString* str); @@ -1144,6 +1475,7 @@ void si_debug_cleanup(void); #define SI_PAIR_IMPLEMENTATION #define SI_OPTIONAL_IMPLEMENTATION #define SI_ARRAY_IMPLEMENTATION + #define SI_BUFFER_IMPLEMENTATION #define SI_STRING_IMPLEMENTATION #define SI_CHAR_IMPLEMENTATION #define SI_FILE_IMPLEMENTATION @@ -1216,9 +1548,9 @@ void si_ptr_move_by(rawptr src, usize src_len, usize move_by, siDirection direct #if defined(SI_PAIR_IMPLEMENTATION) && !defined(SI_PAIR_UNDEFINE) rawptr si_impl_pair_make(siAny first, siAny second) { - siByte* res = (siByte*)malloc(first.type_width + second.type_width); - memcpy(res, first.ptr, first.type_width); - memcpy(res + first.type_width, second.ptr, second.type_width); + siByte* res = (siByte*)malloc(first.type_size + second.type_size); + memcpy(res, first.ptr, first.type_size); + memcpy(res + first.type_size, second.ptr, second.type_size); return (rawptr)res; } @@ -1226,7 +1558,7 @@ rawptr si_impl_pair_make(siAny first, siAny second) { #if defined(SI_ARRAY_IMPLEMENTATION) && !defined(SI_ARRAY_UNDEFINE) -inline siArray(void) si_array_make_list(rawptr list, usize sizeof_element, usize count) { +inline rawptr si_array_make_list(rawptr list, usize sizeof_element, usize count) { rawptr array = si_array_make_reserve(sizeof_element, count); memcpy(array, list, sizeof_element * count); @@ -1235,62 +1567,64 @@ inline siArray(void) si_array_make_list(rawptr list, usize sizeof_element, usize return array; } -inline siArray(void) si_array_copy(siArray(void) array) { +inline rawptr si_array_copy(rawptr array) { siArrayHeader* header = SI_ARRAY_HEADER(array); - return si_array_make_list(array, header->type_width, header->len); + return si_array_make_list(array, header->type_size, header->len); } -siArray(void) si_array_make_reserve(usize sizeof_element, usize count) { +rawptr si_array_make_reserve(usize sizeof_element, usize count) { siByte* ptr = (siByte*)malloc(sizeof(siArrayHeader) + (sizeof_element * count)); - siArray(void) array = ptr + sizeof(siArrayHeader); + rawptr array = ptr + sizeof(siArrayHeader); siArrayHeader* header = SI_ARRAY_HEADER(array); header->len = 0; /* TODO(EimaMei): FIX THIS!!!!!!!!!!!!!!!!!!!!! */ header->capacity = count; - header->type_width = sizeof_element; + header->type_size = sizeof_element; return array; } -inline usize si_array_len(siArray(void) array) { +inline usize si_array_len(rawptr array) { return SI_ARRAY_HEADER(array)->len; } -inline usize si_array_capacity(siArray(void) array) { +inline usize si_array_capacity(rawptr array) { return SI_ARRAY_HEADER(array)->capacity; } -inline usize si_array_type_width(siArray(void) array) { - return SI_ARRAY_HEADER(array)->type_width; +inline usize si_array_type_size(rawptr array) { + return SI_ARRAY_HEADER(array)->type_size; } -inline usize si_array_size_in_bytes(siArray(void) array) { - return si_array_capacity(array) * si_array_type_width(array); +inline usize si_array_total_size(rawptr array) { + return si_array_capacity(array) * si_array_type_size(array); } -inline siAny si_array_at(siArray(void) array, usize index) { - SI_ASSERT_MSG(si_between(index, 0, si_array_len(array)), "Array is empty OR the provided index is too high."); +inline siAny si_array_at(rawptr array, usize index) { + if (index >= si_array_len(array)) { + return (siAny){nil, 0}; + } - rawptr p = (siByte*)array + index * si_array_type_width(array); - return (siAny){si_array_type_width(array), p}; + rawptr p = si_array_get_ptr(array, index); + return (siAny){p, si_array_type_size(array)}; } -inline siAny si_array_front(siArray(void) array) { +inline siAny si_array_front(rawptr array) { SI_ASSERT_MSG(si_array_len(array) != 0, "Array is empty."); - return (siAny){si_array_type_width(array), array}; + return (siAny){array, si_array_type_size(array)}; } -inline siAny si_array_back(siArray(void) array) { +inline siAny si_array_back(rawptr array) { SI_ASSERT_MSG(si_array_len(array) != 0, "Array is empty."); - rawptr p = (siByte*)array + (si_array_len(array) - 1) * si_array_type_width(array); - return (siAny){si_array_type_width(array), p}; + rawptr p = (siByte*)array + (si_array_len(array) - 1) * si_array_type_size(array); + return (siAny){p, si_array_type_size(array)}; } -isize si_impl_array_find_ex(rawptr array, usize start, usize end, siAny value) { +isize si_impl_array_find(rawptr array, usize start, usize end, siAny value) { SI_ASSERT_NOT_NULL(array); - SI_ASSERT_MSG(value.type_width <= si_array_type_width(array), "The given value's sizeof is too large compared to the elements' in the array."); + SI_ASSERT_MSG(value.type_size <= si_array_type_size(array), "The given value's sizeof is too large compared to the elements' in the array."); SI_ASSERT_MSG(start < end, "Value 'start' is larger than 'end'"); bool found = false; usize i; for (i = start; i < end; i++) { - if (memcmp((siByte*)array + i * si_array_type_width(array), value.ptr, value.type_width) == 0) { + if (memcmp((siByte*)array + i * si_array_type_size(array), value.ptr, value.type_size) == 0) { found = true; break; } @@ -1298,15 +1632,15 @@ isize si_impl_array_find_ex(rawptr array, usize start, usize end, siAny value) { return (found ? i : SI_ERROR); } -isize si_impl_array_rfind_ex(rawptr array, usize start, usize end, siAny value) { +isize si_impl_array_rfind(rawptr array, usize start, usize end, siAny value) { SI_ASSERT_NOT_NULL(array); - SI_ASSERT_MSG(value.type_width <= si_array_type_width(array), "The given value's sizeof is too large compared to the elements' in the array."); + SI_ASSERT_MSG(value.type_size <= si_array_type_size(array), "The given value's sizeof is too large compared to the elements' in the array."); SI_ASSERT_MSG(start > end, "Value 'end' is larger than 'start'"); bool found = false; usize i; for (i = start; i < end - 1; i--) { - if (memcmp((siByte*)array + i * si_array_type_width(array), value.ptr, value.type_width) == 0) { + if (memcmp((siByte*)array + i * si_array_type_size(array), value.ptr, value.type_size) == 0) { found = true; break; } @@ -1317,37 +1651,37 @@ isize si_impl_array_rfind_ex(rawptr array, usize start, usize end, siAny value) isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_value) { siByte* array = *((siByte**)array_address); - usize type_width = si_array_type_width(array); - SI_ASSERT_MSG(si_between(new_value.type_width, old_value.type_width, type_width), "The given value's sizeof is too large compared to the elements' in the array."); + usize type_size = si_array_type_size(array); + SI_ASSERT_MSG(si_between(new_value.type_size, old_value.type_size, type_size), "The given value's sizeof is too large compared to the elements' in the array."); - isize pos = si_impl_array_find_ex(array, 0, si_array_len(array), old_value); + isize pos = si_impl_array_find(array, 0, si_array_len(array), old_value); if (pos == SI_ERROR) { return SI_ERROR; } - memcpy(array + pos * type_width, new_value.ptr, new_value.type_width); + memcpy(array + pos * type_size, new_value.ptr, new_value.type_size); return pos; } -isize si_array_reverse(siArray(void) array) { +isize si_array_reverse(rawptr array) { SI_ASSERT_NOT_NULL(array); siByte* array_pointer = *((siByte**)array); usize len = si_array_len(array_pointer); - usize type_width = si_array_type_width(array_pointer); + usize type_size = si_array_type_size(array_pointer); SI_ASSERT_MSG(len != 0, "Array is empty"); siByte* a = array_pointer; - siByte* b = array_pointer + (len - 1) * type_width; + siByte* b = array_pointer + (len - 1) * type_size; static rawptr tmp[1]; len *= 0.5; while (len--) { - memcpy(tmp, a, type_width); - memcpy(a, b, type_width); - memcpy(b, tmp, type_width); + memcpy(tmp, a, type_size); + memcpy(a, b, type_size); + memcpy(b, tmp, type_size); - a += type_width, b -= type_width; + a += type_size, b -= type_size; } return SI_OKAY; @@ -1358,7 +1692,6 @@ siString si_array_to_sistring(siArray(char*) array, cstring separator) { usize separator_len = si_cstr_len(separator); usize total_size = 0; - foreach (str, array) { total_size += si_cstr_len(*str) + separator_len; } @@ -1379,10 +1712,10 @@ siString si_array_to_sistring(siArray(char*) array, cstring separator) { isize si_impl_array_append(rawptr array_address, siAny value) { siByte** array = ((siByte**)array_address); siArrayHeader* header = SI_ARRAY_HEADER(*array); - SI_ASSERT_MSG(value.type_width <= header->type_width, "The given value's sizeof is too large compared to the elements' in the arra"); + SI_ASSERT_MSG(value.type_size <= header->type_size, "The given value's sizeof is too large compared to the elements' in the arra"); if (header->len == header->capacity) { - siByte* result = (siByte*)si_realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_width, sizeof(siArrayHeader) + 2 * header->capacity * header->type_width); + siByte* result = (siByte*)si_realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_size, sizeof(siArrayHeader) + 2 * header->capacity * header->type_size); SI_ASSERT_NOT_NULL(result); *array = result + sizeof(siArrayHeader); @@ -1391,7 +1724,7 @@ isize si_impl_array_append(rawptr array_address, siAny value) { header->capacity *= 2; } - rawptr res = memcpy(*array + header->len * header->type_width, value.ptr, header->type_width); + rawptr res = memcpy(*array + header->len * header->type_size, value.ptr, header->type_size); SI_ASSERT_NOT_NULL(res); header->len += 1; @@ -1403,21 +1736,21 @@ isize si_array_clear(rawptr array_address) { rawptr array = *((rawptr*)array_address); - rawptr result = memset(array, 0, si_array_size_in_bytes(array)); + rawptr result = memset(array, 0, si_array_total_size(array)); SI_ASSERT_NOT_NULL(result); return SI_OKAY; } -bool si_arrays_are_equal(siArray(void) lha, siArray(void) rha) { +bool si_arrays_are_equal(rawptr lha, rawptr rha) { siArrayHeader* lha_header = SI_ARRAY_HEADER(lha); siArrayHeader* rha_header = SI_ARRAY_HEADER(rha); - if (lha_header->len != rha_header->len || lha_header->type_width != rha_header->type_width) { + if (lha_header->len != rha_header->len || lha_header->type_size != rha_header->type_size) { return false; } - usize width = lha_header->type_width; + usize width = lha_header->type_size; usize i; for (i = 0; i < lha_header->len; i++) { if (memcmp((siByte*)lha + i * width, (siByte*)rha + i * width, width) != SI_OKAY) { @@ -1428,7 +1761,7 @@ bool si_arrays_are_equal(siArray(void) lha, siArray(void) rha) { return true; } -isize si_array_free(siArray(void) array) { +isize si_array_free(rawptr array) { if (array == nil) { return SI_ERROR; } @@ -1440,6 +1773,129 @@ isize si_array_free(siArray(void) array) { #endif +#if defined(SI_BUFFER_IMPLEMENTATION) && !defined(SI_BUFFER_UNDEFINE) + +inline siOptional(rawptr) si_impl_buffer_at(rawptr buffer, siBufferHeader* header, usize index) { + if (index >= header->len) { + return SI_OPTIONAL_NULL; + } + return (siOptionalStruct){(siAny){si_buffer_get_ptr(buffer, header->type_size, index), header->type_size}, true}; +} + +isize si_impl_buffer_find(rawptr buffer, siBufferHeader* header, usize start, usize end, siAny value) { + SI_ASSERT_MSG(value.type_size <= header->type_size, "The given value's sizeof is too large compared to the elements' in the buffer."); + SI_ASSERT_MSG(start < end, "Value 'start' is larger than 'end'"); + + bool found = false; + usize i; + for (i = start; i < end; i++) { + if (memcmp((siByte*)buffer + i * header->type_size, value.ptr, value.type_size) == 0) { + found = true; + break; + } + } + + return (found ? i : SI_ERROR); +} +isize si_impl_buffer_rfind(rawptr buffer, siBufferHeader* header, usize start, usize end, siAny value) { + SI_ASSERT_MSG(value.type_size <= header->type_size, "The given value's sizeof is too large compared to the elements' in the buffer."); + SI_ASSERT_MSG(start > end, "Value 'end' is larger than 'start'"); + + bool found = false; + usize i; + for (i = start; i < end - 1; i--) { + if (memcmp((siByte*)buffer + i * header->type_size, value.ptr, value.type_size) == 0) { + found = true; + break; + } + } + + return (found ? i : SI_ERROR); +} + +isize si_impl_buffer_replace(rawptr buffer, siBufferHeader* header, siAny old_value, siAny new_value) { + SI_ASSERT_MSG(si_between(new_value.type_size, old_value.type_size, header->type_size), "The given value's sizeof is too large compared to the elements' in the buffer."); + + isize index = 0; + while (true) { + index = si_impl_buffer_find(buffer, header, index, header->len, old_value); + if (index == SI_ERROR) { + return SI_ERROR; + } + + memcpy((siByte*)buffer + index * header->type_size, new_value.ptr, new_value.type_size); + } + + return index; +} +isize si_impl_buffer_reverse(rawptr buffer, siBufferHeader* header) { + usize len = header->len; + usize type_size = header->type_size; + SI_ASSERT_MSG(len != 0, "Buffer is empty"); + + siByte* a = (siByte*)buffer; + siByte* b = (siByte*)buffer + (len - 1) * type_size; + static rawptr tmp[1]; + len *= 0.5; + + while (len--) { + memcpy(tmp, a, type_size); + memcpy(a, b, type_size); + memcpy(b, tmp, type_size); + + a += type_size, b -= type_size; + } + + return SI_OKAY; +} +siString si_impl_buffer_to_sistring(rawptr buffer, siBufferHeader* header, cstring separator) { + usize separator_len = si_cstr_len(separator); + usize total_size = 0; + + for_range (x, {0, header->len}) { + cstring cstr = *si_cast(char**, si_buffer_get_ptr(buffer, header->type_size, x)); + total_size += si_cstr_len(cstr) + separator_len; + } + + siString result = si_string_make_reserve(total_size); + cstring back = si_optional_get(cstring, si_impl_buffer_at(buffer, header, header->len - 1)); + + for_range (i, {0, header->len}) { + cstring cstr = *si_cast(char**, si_buffer_get_ptr(buffer, header->type_size, i)); + + if (separator != nil && !si_strings_are_equal(cstr, back)) { + si_string_join(&result, separator, cstr); + } + else { + si_string_append(&result, cstr); + } + } + + return result; +} + +void si_impl_buffer_clear(rawptr buffer, siBufferHeader* header) { + rawptr result = memset(buffer, 0, header->len * header->type_size); + SI_ASSERT_NOT_NULL(result); +} +bool si_impl_buffer_compare(rawptr buffer_left, siBufferHeader* header_left, rawptr buffer_right, siBufferHeader* header_right) { + if (header_left->len != header_right->len || header_left->type_size != header_right->type_size) { + return false; + } + + usize width = header_left->type_size; + usize i; + for (i = 0; i < header_left->len; i++) { + if (memcmp((siByte*)buffer_left + i * width, (siByte*)buffer_right + i * width, width) != SI_OKAY) { + return false; + } + } + + return true; +} + +#endif + #if defined(SI_STRING_IMPLEMENTATION) && !defined(SI_STRING_UNDEFINE) @@ -1482,7 +1938,7 @@ siString si_string_make_reserve(usize len) { siStringHeader* header = SI_STRING_HEADER(res_str); header->len = 0; header->capacity = len; - header->type_width = sizeof(char); + header->type_size = sizeof(char); return res_str; } @@ -1497,10 +1953,10 @@ inline usize si_string_len(siString str) { inline usize si_string_capacity(siString str) { return SI_STRING_HEADER(str)->capacity; } -inline usize si_string_type_width(siString str) { - return SI_STRING_HEADER(str)->type_width; +inline usize si_string_type_size(siString str) { + return SI_STRING_HEADER(str)->type_size; } -inline bool si_string_is_empty(siString str) { +inline bool si_string_empty(siString str) { return (SI_STRING_HEADER(str)->len == 0); } @@ -1515,7 +1971,7 @@ inline usize si_cstr_len(cstring str) { inline char si_string_at(siString str, usize index) { SI_ASSERT_NOT_NULL(str); if (index > si_string_len(str) || index < 0 || si_string_len(str) == 0) { - return '\0'; + return SI_ERROR; } return str[index]; @@ -1536,8 +1992,7 @@ inline char si_string_back(siString str) { return str[si_string_len(str) - 1]; } -void si_string_sub(siString str, usize begin, usize end, char* result) { - usize len = end - begin + 1; +void si_string_sub(siString str, usize begin, usize len, char* result) { memcpy(result, str + begin, len); *(result + len) = '\0'; } @@ -1593,18 +2048,18 @@ isize si_string_rfind_ex(siString str, usize start, usize end, cstring cstr) { return (found ? i : SI_ERROR); } -isize si_string_join(siString* str, cstring cstr, cstring separator) { +void si_string_join(siString* str, cstring cstr, cstring separator) { usize cstr_len = si_cstr_len(cstr); usize separator_len = si_cstr_len(separator); char tmp[separator_len + cstr_len + 1]; memcpy(tmp, separator, separator_len); memcpy(tmp + separator_len, cstr, cstr_len); - tmp[separator_len + cstr_len] = '\0'; + tmp[separator_len + cstr_len] = '\0'; /* TODO(EimaMei): Pretty sure I can safely remove this. */ - return si_string_append_len(str, tmp, separator_len + cstr_len); + si_string_append_len(str, tmp, separator_len + cstr_len); } -isize si_string_set(siString* str, cstring cstr) { +void si_string_set(siString* str, cstring cstr) { usize cur_len = si_string_len(*str); usize len = si_cstr_len(cstr); @@ -1619,8 +2074,6 @@ isize si_string_set(siString* str, cstring cstr) { rawptr ptr = memcpy(*str, cstr, len); SI_ASSERT_NOT_NULL(ptr); (*str)[len] = '\0'; - - return SI_OKAY; } void si_string_replace(siString* str, cstring old_value, cstring new_value) { usize old_len = si_cstr_len(old_value); @@ -1643,7 +2096,7 @@ void si_string_replace(siString* str, cstring old_value, cstring new_value) { si_string_insert_ex(str, new_value, new_len, index - old_len_bigger, !old_len_bigger); } } -isize si_string_trim(siString* str, cstring cut_set) { +void si_string_trim(siString* str, cstring cut_set) { char* start = *str; char* end = *str + si_string_len(*str) - 1; char* start_pos = start; @@ -1663,10 +2116,8 @@ isize si_string_trim(siString* str, cstring cut_set) { memmove(str, start_pos, len); } (*str)[len] = '\0'; - - return SI_OKAY; } -void si_string_stringify(siString* str) { +void si_string_enquote(siString* str) { siStringHeader* header = SI_STRING_HEADER(*str); header->len += 2; @@ -1682,10 +2133,10 @@ void si_string_stringify(siString* str) { cur_str[header->len - 1] = '\"'; } -inline isize si_string_append(siString* str, cstring other) { - return si_string_append_len(str, other, si_cstr_len(other)); +inline void si_string_append(siString* str, cstring other) { + si_string_append_len(str, other, si_cstr_len(other)); } -isize si_string_append_len(siString* str, cstring other, usize other_len) { +void si_string_append_len(siString* str, cstring other, usize other_len) { siStringHeader* header = SI_STRING_HEADER(*str); usize previous_len = header->len; header->len += other_len; @@ -1698,12 +2149,11 @@ isize si_string_append_len(siString* str, cstring other, usize other_len) { rawptr ptr = memcpy(*str + previous_len, other, other_len); SI_ASSERT_NOT_NULL(ptr); - (*str)[header->len] = '\0'; - return SI_OKAY; + (*str)[header->len] = '\0'; } -inline isize si_string_push(siString* str, char other) { - return si_string_append_len(str, &other, 1); +inline void si_string_push(siString* str, char other) { + si_string_append_len(str, &other, 1); } inline void si_string_pop(siString* str) { siString cur_str = *str; @@ -1769,23 +2219,21 @@ void si_string_remove_cstr(siString* str, cstring cstr) { } void si_string_swap(siString* str, cstring cstr1, cstring cstr2); -inline isize si_string_upper(siString* str) { +inline void si_string_upper(siString* str) { SI_ASSERT_NOT_NULL(str); foreach (x, *str) { *x = si_char_to_upper(*x); } - return SI_OKAY; } -inline isize si_string_lower(siString* str) { +inline void si_string_lower(siString* str) { SI_ASSERT_NOT_NULL(str); foreach (x, *str) { *x = si_char_to_lower(*x); } - return SI_OKAY; } -isize si_string_title(siString* str) { +void si_string_title(siString* str) { si_string_capitalize(str); bool change = false; @@ -1798,21 +2246,17 @@ isize si_string_title(siString* str) { change = false; } } - - return SI_OKAY; } -inline isize si_string_capitalize(siString* str) { +inline void si_string_capitalize(siString* str) { SI_ASSERT_NOT_NULL(str); if (si_string_len(*str) <= 0) { - return SI_ERROR; + return ; } si_string_lower(str); **str = si_char_to_upper(**str); - - return SI_OKAY; } -isize si_string_strip(siString* str) { +void si_string_strip(siString* str) { SI_ASSERT_NOT_NULL(str); usize start = 0, end = 0; @@ -1830,17 +2274,20 @@ isize si_string_strip(siString* str) { } end += 1; } - char* stripped_str = *str + start * SI_STRING_HEADER(*str)->type_width; + char* stripped_str = *str + start * SI_STRING_HEADER(*str)->type_size; stripped_str[si_string_len(*str) - start - end] = '\0'; - return si_string_set(str, stripped_str); + si_string_set(str, stripped_str); } -inline isize si_string_reverse(siString* str) { +inline void si_string_reverse(siString* str) { usize len = si_string_len(*str); - SI_ASSERT_MSG(len != 0, "String is empty"); - return si_string_reverse_len(str, len); + if (len == 0) { + return ; + } + + si_string_reverse_len(str, len); } -isize si_string_reverse_len(siString* str, usize len) { +void si_string_reverse_len(siString* str, usize len) { siString actual_str = *str; char* a = actual_str; @@ -1853,7 +2300,6 @@ isize si_string_reverse_len(siString* str, usize len) { } *str = actual_str; - return SI_OKAY; } siArray(siString) si_string_split(siString str, cstring separator) { @@ -1909,20 +2355,15 @@ bool si_strings_are_equal(cstring lhs, cstring rhs) { return true; } -inline isize si_string_clear(siString* str) { - char null_terminator = '\0'; - isize result = si_string_set(str, &null_terminator); - - return result; +inline void si_string_clear(siString* str) { + **str = '\0'; } -inline isize si_string_free(siString str) { +inline void si_string_free(siString str) { if (str == nil) { - return SI_ERROR; + return ; } free(SI_STRING_HEADER(str)); - - return SI_OKAY; } isize si_string_make_space_for(siString* str, usize add_len) { usize len = si_string_len(*str); @@ -2357,7 +2798,7 @@ isize si_file_close(siFile file) { #if defined(SI_THREAD_IMPLEMENTATION) && !defined(SI_THREAD_UNDEFINE) -inline rawptr si_impl_thread_proc(rawptr arg) { +inline static rawptr si_impl_thread_proc(rawptr arg) { siThread* t = (siThread*)arg; t->return_value = t->func.ptr(t->arg); t->is_running = false; @@ -2507,7 +2948,7 @@ rawptr si_debug_alloc(usize function_id, rawptr ptr, siDebugArgs args, cstring f siArrayHeader* header = (siArrayHeader*)ptr; header->len = 0; header->capacity = 100; - header->type_width = sizeof(siDebugHeader*); + header->type_size = sizeof(siDebugHeader*); } usize size = 0; From c3edd083d640946837f35e8e62652820d23e531f Mon Sep 17 00:00:00 2001 From: EimaMei Date: Sun, 11 Jun 2023 21:58:12 +0300 Subject: [PATCH 09/17] minor improvements, fixed gcc warnings --- .gitignore | 3 +- Makefile | 2 +- examples/array.c | 8 +- examples/str.c | 12 +- sili.h | 378 ++++++++++++++++++++++++----------------------- 5 files changed, 207 insertions(+), 196 deletions(-) diff --git a/.gitignore b/.gitignore index eb6833f..43b50c1 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ src/ *.7z *.zip *.hide -*.S \ No newline at end of file +*.S +*.json \ No newline at end of file diff --git a/Makefile b/Makefile index a3b3cb0..fb681fe 100644 --- a/Makefile +++ b/Makefile @@ -24,4 +24,4 @@ dump_asm: $(CC) -g $(FLAGS) $(INCLUDE) $(LIBS) -S $(SRC) -o sili.S $(OUTPUT): - mkdir $(OUTPUT) \ No newline at end of file + mkdir $(OUTPUT) diff --git a/examples/array.c b/examples/array.c index ae30114..55e7ef1 100644 --- a/examples/array.c +++ b/examples/array.c @@ -1,4 +1,4 @@ -#define SI_IMPLEMENTATION 1 +//#define SI_IMPLEMENTATION 1 #include @@ -20,10 +20,10 @@ void example_2_0(void) { i32 front = si_any_get(si_array_front(array), i32); i32 back = si_any_get(si_array_back(array), i32); - printf("We now have %zd elements instead of %zd. The front value is '%i', while the back value is '%X'\n", si_array_len(array), previous_len, front, back); + printf("We now have %zd elements instead of %zd. The front value is '%i', while the back value is '0x%X'\n", si_array_len(array), previous_len, front, back); - isize element_pos = si_array_replace(&array, 4, SI_INT32_MIN); - printf("The element at position '%zd' was replaced with: %X\n", element_pos, array[element_pos]); + si_array_replace(&array, 4, SI_INT32_MIN); + printf("The element at position '%d' was replaced with: -'-0x%X'\n", 3, array[3]); siArray(i32) copy = si_array_copy(array); bool res = si_arrays_are_equal(array, copy); diff --git a/examples/str.c b/examples/str.c index 025e457..d2364e9 100644 --- a/examples/str.c +++ b/examples/str.c @@ -19,11 +19,11 @@ void example_1_0(void) { si_string_set(&str, "Different sentence"); printf("str: %s\n", str); - si_string_push_back(&str, '.'); + si_string_push(&str, '.'); printf("str: %s\n", str); siString str2 = si_string_copy(str); - bool result = si_strings_are_equal(str, str2); + bool result = si_cstr_equal(str, str2); printf("(\"%s\" == \"%s\") returns a '%s' boolean\n", str, str2, (result ? "true" : "false")); isize pos = si_string_find(str, "sentence"); @@ -77,19 +77,19 @@ void example_1_1(void) { si_string_join(&str, "random.txt", "/"); printf("Joined str: \"%s\"\n", str); - si_string_upper(&str); + si_cstr_upper(str); printf("Upper str: \"%s\"\n", str); si_string_set(&str, "I'VE COME TO MAKE AN ANNOUNCEMENT"); printf("Original str: \"%s\"\n", str); - si_string_lower(&str); + si_cstr_lower(str); printf("Lower str: \"%s\"\n", str); - si_string_title(&str); + si_cstr_title(str); printf("Titled str: \"%s\"\n", str); - si_string_capitalize(&str); + si_cstr_capitalize(str); printf("Capitalized str: \"%s\"\n", str); si_string_free(str); diff --git a/sili.h b/sili.h index e04c56c..3550ae8 100644 --- a/sili.h +++ b/sili.h @@ -45,6 +45,8 @@ CREDITS #ifndef SI_INCLUDE_SI_H #define SI_INCLUDE_SI_H +#define SI_IMPLEMENTATION 1 + #if defined(__cplusplus) extern "C" { #endif @@ -247,36 +249,36 @@ extern "C" { typedef u8 siByte; -static u8 SI_UINT8_MAX = 0xFF; -static u8 SI_UINT8_MIN = 0x00; -static i8 SI_INT8_MAX = 0x7F; -static i8 SI_INT8_MIN = -0x80; +#define SI_UINT8_MAX 0xFF; +#define SI_UINT8_MIN 0x00; +#define SI_INT8_MAX 0x7F; +#define SI_INT8_MIN -0x80; -static u16 SI_UINT16_MAX = 0xFFFF; -static u16 SI_UINT16_MIN = 0x0000; -static i16 SI_INT16_MAX = 0x7FFF; -static i16 SI_INT16_MIN = -0x8000; +#define SI_UINT16_MAX 0xFFFF; +#define SI_UINT16_MIN 0x0000; +#define SI_INT16_MAX 0x7FFF; +#define SI_INT16_MIN -0x8000; -static u32 SI_UINT32_MAX = 0xFFFFFFFF; -static u32 SI_UINT32_MIN = 0x00000000; -static i32 SI_INT32_MAX = 0x7FFFFFFF; -static i32 SI_INT32_MIN = -0x80000000; +#define SI_UINT32_MAX 0xFFFFFFFF; +#define SI_UINT32_MIN 0x00000000; +#define SI_INT32_MAX 0x7FFFFFFF; +#define SI_INT32_MIN -0x80000000; -static u64 SI_UINT64_MAX = 0xFFFFFFFFFFFFFFFF; -static u64 SI_UINT64_MIN = 0x0000000000000000; -static i64 SI_INT64_MAX = 0x7FFFFFFFFFFFFFFF; -static i64 SI_INT64_MIN = -0x8000000000000000; +#define SI_UINT64_MAX 0xFFFFFFFFFFFFFFFF; +#define SI_UINT64_MIN 0x0000000000000000; +#define SI_INT64_MAX 0x7FFFFFFFFFFFFFFF; +#define SI_INT64_MIN -0x8000000000000000; #if defined(SI_ARCH_64_BIT) - #define SI_USIZE_MAX SI_UINT64_MAX - #define SI_USIZE_MIN SI_UINT64_MIN - #define SI_ISIZE_MAX SI_INT64_MAX - #define SI_ISIZE_MIN SI_INT64_MIN + #define SI_USIZE_MAX 0xFFFFFFFFFFFFFFFF; + #define SI_USIZE_MIN 0x0000000000000000; + #define SI_ISIZE_MAX 0x7FFFFFFFFFFFFFFF; + #define SI_ISIZE_MIN -0x8000000000000000; #else - #define SI_USIZE_MAX SI_UINT32_MAX - #define SI_USIZE_MIN SI_UINT32_MIN - #define SI_ISIZE_MAX SI_INT32_MAX - #define SI_ISIZE_MIN SI_INT32_MIN + #define SI_USIZE_MAX 0xFFFFFFFF; + #define SI_USIZE_MIN 0x00000000; + #define SI_ISIZE_MAX 0x7FFFFFFF; + #define SI_ISIZE_MIN -0x80000000; #endif @@ -326,12 +328,20 @@ SI_STATIC_ASSERT(sizeof(usize) == sizeof(isize)); SI_STATIC_ASSERT(sizeof(uintptr) == sizeof(intptr)); + typedef float f32; typedef double f64; SI_STATIC_ASSERT(sizeof(f32) == 4); SI_STATIC_ASSERT(sizeof(f64) == 8); +#define SI_F32_MIN 1.17549435e-38f +#define SI_F32_MAX 3.40282347e+38f + +#define SI_F64_MIN 2.2250738585072014e-308 +#define SI_F64_MAX 1.7976931348623157e+308 + + #if !defined(rawptr) typedef void* rawptr; #endif @@ -346,9 +356,9 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); ======================== */ #define SI_OKAY 0 -#define SI_ERROR -1 +#define SI_ERROR (isize)-1 -#define SI_BIT(x) (1 << (x)) +#define SI_BIT(x) (1 << (x)) #define SI_KILO(x) ( (x) * (usize)1024) #define SI_MEGA(x) (SI_KILO(x) * (usize)1024) @@ -408,7 +418,7 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); */ #define si_swap(a, b) do { typeof((a)) tmp = (a); (a) = (b); (b) = tmp; } while (0) #define si_between(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper))) -#define si_pause() do { printf("Press any key to continue...\n"); getchar() }; while(0) +#define si_pause() do { printf("Press any key to continue...\n"); getchar(); } while(0) #define for_range_2(count_var, struct_name, ...) \ siVector2D struct_name = __VA_ARGS__; \ @@ -636,14 +646,14 @@ typedef struct siArrayHeader { #if defined(SI_STANDARD_C89) #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) #else - #define foreach(variable_name, array) for (typeof(array) variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) + #define foreach(variable_name, array) for (typeof(*(array)) variable_name = *(array); (typeof(array)){&variable_name} != array + si_array_len(array); (typeof(array)){&variable_name} += 1) #endif #define si_array_get_ptr(array, index) \ (si_cast(siByte*, array) + si_array_type_size(array) * (index)) /* rawptr si_array_make(rawptr array); */ -#define si_array_make(...) si_array_make_list(__VA_ARGS__, sizeof(*(__VA_ARGS__)), count(__VA_ARGS__)) +#define si_array_make(...) si_array_make_list(__VA_ARGS__, sizeof(*(__VA_ARGS__)), sizeof(__VA_ARGS__) / sizeof(*(__VA_ARGS__))) rawptr si_array_make_list(rawptr list, usize sizeof_element, usize count); rawptr si_array_copy(rawptr array); rawptr si_array_make_reserve(usize sizeof_element, usize count); @@ -657,18 +667,18 @@ siAny si_array_at(rawptr array, usize index); siAny si_array_front(rawptr array); siAny si_array_back(rawptr array); -#define si_array_append(array_address, value) si_impl_array_append(array_address, si_any_make(value)) +#define si_array_append(array_ptr, value) si_impl_array_append(array_ptr, si_any_make(value)) #define si_array_find(array, value) si_impl_array_find(array, 0, si_array_len(array), si_any_make(value)) #define si_array_find_ex(array, start, end, value) si_impl_array_find(array, start, end, si_any_make(value)) #define si_array_rfind(array, value) si_impl_array_rfind(array, si_array_len(array) - 1, 0, si_any_make(value)) #define si_array_rfind_ex(array, start, end, value) si_impl_array_rfind(array, start, end, si_any_make(value)) -#define si_array_replace(array_address, old_value, new_value) si_impl_array_replace(array_address, si_any_make(old_value), si_any_make(new_value)) -isize si_array_reverse(rawptr array); +#define si_array_replace(array_ptr, old_value, new_value) si_impl_array_replace(array, si_any_make(old_value), si_any_make(new_value)) +void si_array_reverse(rawptr array_ptr); char* si_array_to_sistring(siArray(char*) array, cstring separator); -isize si_array_clear(rawptr array_address); +void si_array_clear(rawptr array_ptr); bool si_arrays_are_equal(rawptr lha, rawptr rha); isize si_array_free(rawptr array); @@ -676,8 +686,8 @@ isize si_array_free(rawptr array); /* NOTE(EimaMei): The actual implementations. Shouldn't be used in practice, really. */ isize si_impl_array_find(rawptr array, usize start, usize end, siAny value); isize si_impl_array_rfind(rawptr array, usize start, usize end, siAny value); -isize si_impl_array_append(rawptr array_address, siAny value); -isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_value); +void si_impl_array_append(rawptr array_ptr, siAny value); +void si_impl_array_replace(rawptr array_ptr, siAny old_value, siAny new_value); #endif @@ -785,10 +795,10 @@ typedef siArray(char) siString; * @brief siStringHeader is the header structure for siString. */ typedef struct siStringHeader { - usize len; - usize capacity; - u16 type_size; - u16 grow; + u32 len; + u32 capacity; + u8 type_size; + u8 grow; } siStringHeader; /** @@ -799,10 +809,12 @@ typedef struct siStringHeader { * @param variable_name The name of the iterator variable. * @param array The siString to iterate over. */ -#if defined(SI_STANDARD_C89) -#define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) -#else -#define foreach(variable_name, array) for (typeof(array) variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) +#if !defined(foreach) + #if defined(SI_STANDARD_C89) + #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) + #else + #define foreach(variable_name, array) for (typeof(*(array)) variable_name = *(array); &variable_name != ((array) + si_array_len(array)); (&variable_name) += 1) + #endif #endif /** @@ -1030,16 +1042,11 @@ void si_string_erase(siString* str, usize index, usize erase_len); void si_string_remove_cstr(siString* str, cstring cstr); void si_string_swap(siString* str, cstring cstr1, cstring cstr2); -void si_string_upper(siString* str); -void si_string_lower(siString* str); -void si_string_title(siString* str); -void si_string_capitalize(siString* str); void si_string_strip(siString* str); /* NOTE(EimaMei); This strips any leading or trailing spaces in the string. */ void si_string_reverse(siString* str); void si_string_reverse_len(siString* str, usize len); siArray(siString) si_string_split(siString str, cstring separator); -bool si_strings_are_equal(cstring lhs, cstring rhs); void si_string_clear(siString* str); void si_string_free(siString str); @@ -1087,12 +1094,21 @@ i32 si_hex_digit_to_int(char c); */ usize si_cstr_len(cstring str); +void si_cstr_upper(char* str); +void si_cstr_lower(char* str); +void si_cstr_title(char* str); +void si_cstr_capitalize(char* str); + +bool si_cstr_equal(cstring str1, cstring str2); +bool si_cstr_equal_len(cstring str1, usize str1_len, cstring str2, usize str2_len); + u64 si_cstr_to_u64(cstring str); i64 si_cstr_to_i64(cstring str); -/* TODO(EimaMei): si_cstr_to_f64 */ +f64 si_cstr_to_f64(cstring str); cstring si_u64_to_cstr(u64 num); cstring si_i64_to_cstr(i64 num); +/* TODO(EimaMei): si_f64_to_cstr */ #endif @@ -1630,7 +1646,7 @@ isize si_impl_array_find(rawptr array, usize start, usize end, siAny value) { } } - return (found ? i : SI_ERROR); + return (found ? (isize)i : SI_ERROR); } isize si_impl_array_rfind(rawptr array, usize start, usize end, siAny value) { SI_ASSERT_NOT_NULL(array); @@ -1646,33 +1662,38 @@ isize si_impl_array_rfind(rawptr array, usize start, usize end, siAny value) { } } - return (found ? i : SI_ERROR); + return (found ? (isize)i : SI_ERROR); } -isize si_impl_array_replace(rawptr array_address, siAny old_value, siAny new_value) { - siByte* array = *((siByte**)array_address); - usize type_size = si_array_type_size(array); - SI_ASSERT_MSG(si_between(new_value.type_size, old_value.type_size, type_size), "The given value's sizeof is too large compared to the elements' in the array."); +void si_impl_array_replace(rawptr array, siAny old_value, siAny new_value) { + SI_ASSERT_NOT_NULL(array); + siArrayHeader* header = SI_ARRAY_HEADER(array); - isize pos = si_impl_array_find(array, 0, si_array_len(array), old_value); - if (pos == SI_ERROR) { - return SI_ERROR; - } + SI_ASSERT_MSG( + si_between(new_value.type_size, old_value.type_size, header->type_size), + "The given value's sizeof is too large compared to the elements' in the array." + ); - memcpy(array + pos * type_size, new_value.ptr, new_value.type_size); + isize index = 0; + while (true) { + index = si_impl_array_find(array, index, header->len, old_value); + if (index == SI_ERROR) { + return ; + } - return pos; + memcpy(si_array_get_ptr(array, index), new_value.ptr, new_value.type_size); + } } -isize si_array_reverse(rawptr array) { - SI_ASSERT_NOT_NULL(array); - siByte* array_pointer = *((siByte**)array); +void si_array_reverse(rawptr array_ptr) { + SI_ASSERT_NOT_NULL(array_ptr); + siByte* array = *si_cast(siByte**, array_ptr); - usize len = si_array_len(array_pointer); - usize type_size = si_array_type_size(array_pointer); + usize len = si_array_len(array); + usize type_size = si_array_type_size(array); SI_ASSERT_MSG(len != 0, "Array is empty"); - siByte* a = array_pointer; - siByte* b = array_pointer + (len - 1) * type_size; + siByte* a = array; + siByte* b = array + (len - 1) * type_size; static rawptr tmp[1]; len *= 0.5; @@ -1683,8 +1704,6 @@ isize si_array_reverse(rawptr array) { a += type_size, b -= type_size; } - - return SI_OKAY; } siString si_array_to_sistring(siArray(char*) array, cstring separator) { SI_ASSERT_NOT_NULL(array); @@ -1693,53 +1712,49 @@ siString si_array_to_sistring(siArray(char*) array, cstring separator) { usize total_size = 0; foreach (str, array) { - total_size += si_cstr_len(*str) + separator_len; + total_size += si_cstr_len(str) + separator_len; } siString result = si_string_make_reserve(total_size); foreach (str, array) { - if (separator != nil && str != si_array_back(array).ptr) { - si_string_join(&result, separator, *str); + if (separator != nil && &str != si_array_back(array).ptr) { + si_string_join(&result, separator, str); } else { - si_string_append(&result, *str); + si_string_append(&result, str); } } return result; } -isize si_impl_array_append(rawptr array_address, siAny value) { - siByte** array = ((siByte**)array_address); - siArrayHeader* header = SI_ARRAY_HEADER(*array); +void si_impl_array_append(rawptr array_ptr, siAny value) { + SI_ASSERT_NOT_NULL(array_ptr); + siByte* array = *si_cast(siByte**, array_ptr); + + siArrayHeader* header = SI_ARRAY_HEADER(array); SI_ASSERT_MSG(value.type_size <= header->type_size, "The given value's sizeof is too large compared to the elements' in the arra"); if (header->len == header->capacity) { siByte* result = (siByte*)si_realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_size, sizeof(siArrayHeader) + 2 * header->capacity * header->type_size); SI_ASSERT_NOT_NULL(result); - *array = result + sizeof(siArrayHeader); - header = (siArrayHeader*)result; + array = result + sizeof(siArrayHeader); + *si_cast(siByte**, array_ptr) = array; + header = (siArrayHeader*)result; header->capacity *= 2; } - rawptr res = memcpy(*array + header->len * header->type_size, value.ptr, header->type_size); - SI_ASSERT_NOT_NULL(res); + memcpy(si_array_get_ptr(array, header->len), value.ptr, header->type_size); header->len += 1; - - return SI_OKAY; } -isize si_array_clear(rawptr array_address) { - SI_ASSERT_NOT_NULL(array_address); +void si_array_clear(rawptr array_ptr) { + SI_ASSERT_NOT_NULL(array_ptr); + rawptr array = *si_cast(siByte**, array_ptr); - rawptr array = *((rawptr*)array_address); - - rawptr result = memset(array, 0, si_array_total_size(array)); - SI_ASSERT_NOT_NULL(result); - - return SI_OKAY; + memset(array, 0, si_array_total_size(array)); } bool si_arrays_are_equal(rawptr lha, rawptr rha) { @@ -1795,7 +1810,7 @@ isize si_impl_buffer_find(rawptr buffer, siBufferHeader* header, usize start, us } } - return (found ? i : SI_ERROR); + return (found ? (isize)i : SI_ERROR); } isize si_impl_buffer_rfind(rawptr buffer, siBufferHeader* header, usize start, usize end, siAny value) { SI_ASSERT_MSG(value.type_size <= header->type_size, "The given value's sizeof is too large compared to the elements' in the buffer."); @@ -1810,7 +1825,7 @@ isize si_impl_buffer_rfind(rawptr buffer, siBufferHeader* header, usize start, u } } - return (found ? i : SI_ERROR); + return (found ? (isize)i : SI_ERROR); } isize si_impl_buffer_replace(rawptr buffer, siBufferHeader* header, siAny old_value, siAny new_value) { @@ -1858,12 +1873,12 @@ siString si_impl_buffer_to_sistring(rawptr buffer, siBufferHeader* header, cstri } siString result = si_string_make_reserve(total_size); - cstring back = si_optional_get(cstring, si_impl_buffer_at(buffer, header, header->len - 1)); + isize back_index = header->len - 1; for_range (i, {0, header->len}) { cstring cstr = *si_cast(char**, si_buffer_get_ptr(buffer, header->type_size, i)); - if (separator != nil && !si_strings_are_equal(cstr, back)) { + if (separator != nil && i != back_index) { si_string_join(&result, separator, cstr); } else { @@ -1900,7 +1915,7 @@ bool si_impl_buffer_compare(rawptr buffer_left, siBufferHeader* header_left, raw inline siString si_string_make(cstring str) { - return si_string_make_len(str, str ? si_cstr_len(str) : 0); + return si_string_make_len(str, str ? si_cstr_len(str) : 0); } siString si_string_make_len(cstring str, usize len) { siString res_str = si_string_make_reserve(len); @@ -1968,9 +1983,29 @@ inline usize si_cstr_len(cstring str) { return (s - str); } +inline bool si_cstr_equal(cstring str1, cstring str2) { + return si_cstr_equal_len(str1, si_cstr_len(str1), str2, si_cstr_len(str2)); +} +bool si_cstr_equal_len(cstring str1, usize str1_len, cstring str2, usize str2_len) { + if (str1 == str2) { + return true; + } + if (str1_len != str2_len) { + return false; + } + + usize i; + for (i = 0; i < str1_len; i++) { + if (str1[i] != str2[i]) + return false; + } + + return true; +} + inline char si_string_at(siString str, usize index) { SI_ASSERT_NOT_NULL(str); - if (index > si_string_len(str) || index < 0 || si_string_len(str) == 0) { + if (index > si_string_len(str) || si_string_len(str) == 0) { return SI_ERROR; } @@ -2001,7 +2036,7 @@ inline isize si_string_find(siString str, cstring cstr) { return si_string_find_ex(str, 0, si_string_len(str), cstr, si_cstr_len(cstr)); } isize si_string_find_ex(siString str, usize start, usize end, cstring cstr, usize cstr_len) { - SI_ASSERT_NOT_NULL(str); + SI_ASSERT_NOT_NULL(str); bool found = false; @@ -2021,13 +2056,13 @@ isize si_string_find_ex(siString str, usize start, usize end, cstring cstr, usiz } } - return (found ? (i - cstr_len + 1) : SI_ERROR); + return (found ? si_cast(isize, i - cstr_len + 1) : SI_ERROR); } inline isize si_string_rfind(siString str, cstring cstr) { return si_string_rfind_ex(str, si_string_len(str) - 1, 0, cstr); } isize si_string_rfind_ex(siString str, usize start, usize end, cstring cstr) { - SI_ASSERT_NOT_NULL(str); + SI_ASSERT_NOT_NULL(str); usize cstr_len = si_cstr_len(cstr); bool found = false; @@ -2045,7 +2080,7 @@ isize si_string_rfind_ex(siString str, usize start, usize end, cstring cstr) { } } - return (found ? i : SI_ERROR); + return (found ? (isize)i : SI_ERROR); } void si_string_join(siString* str, cstring cstr, cstring separator) { @@ -2157,8 +2192,8 @@ inline void si_string_push(siString* str, char other) { } inline void si_string_pop(siString* str) { siString cur_str = *str; - cur_str[SI_ARRAY_HEADER(cur_str)->len - 1] = '\0'; - SI_ARRAY_HEADER(cur_str)->len -= 1; + *(cur_str + SI_STRING_HEADER(cur_str)->len - 1) = '\0'; + SI_STRING_HEADER(cur_str)->len -= 1; } inline void si_string_insert(siString* str, cstring cstr, usize index) { @@ -2183,84 +2218,90 @@ void si_string_insert_ex(siString* str, cstring cstr, usize cstr_len, usize inde ptr[before_index_len] = '\0'; } void si_string_erase(siString* str, usize index, usize erase_len) { - usize after_index_len = index + erase_len; siString cur_str = *str; + SI_ASSERT_NOT_NULL(cur_str); + usize str_len = si_string_len(cur_str); + SI_ASSERT_MSG(index < str_len, "Index is higher than the length of the string."); + + usize after_index_len = index + erase_len; char* ptr = (char*)memcpy(cur_str + index, cur_str + after_index_len, str_len - after_index_len); - SI_ASSERT_NOT_NULL(ptr); ptr[str_len - after_index_len] = '\0'; SI_STRING_HEADER(cur_str)->len -= erase_len; } void si_string_remove_cstr(siString* str, cstring cstr) { - siStringHeader* header = SI_STRING_HEADER(*str); - usize cstr_len = si_cstr_len(cstr); + siString cur_str = *str; + SI_ASSERT_NOT_NULL(cur_str); - usize cur_len; - siString cur_str; + siStringHeader* header = SI_STRING_HEADER(cur_str); + usize cstr_len = si_cstr_len(cstr); while (true) { cur_str = *str; - cur_len = si_string_len(cur_str); - isize index = si_string_rfind_ex(cur_str, cur_len - 1, 0, cstr); + isize index = si_string_rfind_ex(cur_str, header->len - 1, 0, cstr); if (index == -1) { break; } usize after_index_len = index + cstr_len; - char* ptr = (char*)memcpy(cur_str + index, cur_str + after_index_len, cur_len - after_index_len); - SI_ASSERT_NOT_NULL(ptr); - ptr[cur_len - after_index_len] = '\0'; + char* ptr = (char*)memcpy(cur_str + index, cur_str + after_index_len, header->len - after_index_len); + ptr[header->len - after_index_len] = '\0'; header->len -= cstr_len; } } void si_string_swap(siString* str, cstring cstr1, cstring cstr2); -inline void si_string_upper(siString* str) { +inline void si_cstr_upper(char* str) { SI_ASSERT_NOT_NULL(str); - foreach (x, *str) { - *x = si_char_to_upper(*x); + char x = '\0'; + while ((x = *str)) { + *str = si_char_to_upper(x); + str++; } } -inline void si_string_lower(siString* str) { +inline void si_cstr_lower(char* str) { SI_ASSERT_NOT_NULL(str); - foreach (x, *str) { - *x = si_char_to_lower(*x); + char x = '\0'; + while ((x = *str)) { + *str = si_char_to_lower(x); + str += 1; } } -void si_string_title(siString* str) { - si_string_capitalize(str); +void si_cstr_title(char* str) { + SI_ASSERT_NOT_NULL(str); bool change = false; - foreach (x, *str) { - if (si_char_is_space(*x)) { + char x = '\0'; + while ((x = *str)) { + if (si_char_is_space(x)) { change = true; } else if (change) { - *x = si_char_to_upper(*x); + *str = si_char_to_upper(x); change = false; } + str += 1; } } -inline void si_string_capitalize(siString* str) { +inline void si_cstr_capitalize(char* str) { SI_ASSERT_NOT_NULL(str); - if (si_string_len(*str) <= 0) { - return ; - } - si_string_lower(str); - **str = si_char_to_upper(**str); + si_cstr_lower(str); + *str = si_char_to_upper(*str); } void si_string_strip(siString* str) { SI_ASSERT_NOT_NULL(str); usize start = 0, end = 0; - foreach (x, *str) { + siString cur_str = *str; + siString x = nil; + for (x = cur_str; x != cur_str + si_string_len(cur_str); x += 1) { if (!si_char_is_space(*x)) { break; } @@ -2268,24 +2309,19 @@ void si_string_strip(siString* str) { } usize i; - for (i = si_string_len(*str) - 1; i < (usize)(-1); i--) { - if (!si_char_is_space((*str)[i])) { + for (i = si_string_len(cur_str) - 1; i < (usize)(-1); i--) { + if (!si_char_is_space(cur_str[i])) { break; } end += 1; } - char* stripped_str = *str + start * SI_STRING_HEADER(*str)->type_size; - stripped_str[si_string_len(*str) - start - end] = '\0'; + char* stripped_str = cur_str + start * SI_STRING_HEADER(cur_str)->type_size; + stripped_str[si_string_len(cur_str) - start - end] = '\0'; si_string_set(str, stripped_str); } inline void si_string_reverse(siString* str) { - usize len = si_string_len(*str); - if (len == 0) { - return ; - } - - si_string_reverse_len(str, len); + si_string_reverse_len(str, si_string_len(*str)); } void si_string_reverse_len(siString* str, usize len) { siString actual_str = *str; @@ -2335,26 +2371,6 @@ siArray(siString) si_string_split(siString str, cstring separator) { return res; } -bool si_strings_are_equal(cstring lhs, cstring rhs) { - if (lhs == rhs) { - return true; - } - - usize lhs_len = si_cstr_len(lhs); - usize rhs_len = si_cstr_len(rhs); - - if (lhs_len != rhs_len) { - return false; - } - - usize i; - for (i = 0; i < lhs_len; i++) { - if (lhs[i] != rhs[i]) - return false; - } - - return true; -} inline void si_string_clear(siString* str) { **str = '\0'; } @@ -2396,12 +2412,6 @@ void si_string_shrink_to_fit(siString* str) { #if defined(SI_CHAR_IMPLEMENTATION) && !defined(SI_STRING_UNDEFINE) -static const char si_impl_num_to_char_table[] = /* NOTE(EimaMei): Required for converting nums to chars quickly. */ - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "@$"; - inline char si_char_to_lower(char c) { if (c >= 'A' && c <= 'Z') { return c + 32; /* NOTE(EimaMei): 32 is just the math result of 'A' - 'a'. This performs much better, as the previous version required 2 math operations, while this - only one. */ @@ -2453,7 +2463,7 @@ cstring si_u64_to_cstr(u64 num) { char* cur_char = buffer; do { - *cur_char++ = si_impl_num_to_char_table[num % 10]; + *cur_char++ = (num % 10) +'0'; num /= 10; } while (num > 0); *cur_char = '\0'; @@ -2466,18 +2476,18 @@ cstring si_u64_to_cstr(u64 num) { u64 si_cstr_to_u64(cstring str) { SI_ASSERT_NOT_NULL(str); - u64 result = 0; + u64 result = 0; char cur; - while ((cur = *str++)) { - if (cur >= '0' && cur <= '9') { - result = (result * 10) + (cur - '0'); - } + while ((cur = *str++)) { + if (cur >= '0' && cur <= '9') { + result = (result * 10) + (cur - '0'); + } else { SI_ASSERT_MSG(!(cur >= '0' && cur <= '9'), "Attempted to use `si_cstr_to_u64` with a string that contains non numbers."); } - } + } - return result; + return result; } cstring si_i64_to_cstr(i64 num) { static char buffer[20 + 1]; /* NOTE(EimaMei): 19 chars is the maximum of numbers we can have in an i64. One more char for the possible minus symbol. */ @@ -2492,7 +2502,7 @@ cstring si_i64_to_cstr(i64 num) { value = (u64)num; do { - *cur_char++ = si_impl_num_to_char_table[value % 10]; + *cur_char++ = (num % 10) +'0'; value /= 10; } while (value > 0); @@ -2510,7 +2520,7 @@ cstring si_i64_to_cstr(i64 num) { i64 si_cstr_to_i64(cstring str) { SI_ASSERT_NOT_NULL(str); - i64 result = 0; + i64 result = 0; char cur; bool negative = false; @@ -2520,19 +2530,19 @@ i64 si_cstr_to_i64(cstring str) { } while ((cur = *str++)) { - if (cur >= '0' && cur <= '9') { - result = (result * 10) + (cur - '0'); - } + if (cur >= '0' && cur <= '9') { + result = (result * 10) + (cur - '0'); + } else { SI_ASSERT_MSG(!(cur >= '0' && cur <= '9'), "Attempted to use `si_cstr_to_u64` with a string that contains non numbers."); } - } + } if (negative) { result = -result; } - return result; + return result; } #endif @@ -2747,7 +2757,7 @@ isize si_file_write_at_line(siFile* file, cstring content, usize index) { siArray(siString) buffer = si_file_readlines(*file); siString previous_line = buffer[index]; - SI_ASSERT_MSG(0 <= index && index <= si_array_len(buffer), "Index is either not 0 or higher than the amount of lines in the file."); + SI_ASSERT_MSG(index < si_array_len(buffer), "Index is either not 0 or higher than the amount of lines in the file."); buffer[index] = (siString)content; From 48d5febf734e605f466f3d29e554bb40f8f3d8a3 Mon Sep 17 00:00:00 2001 From: EimaMei Date: Sun, 18 Jun 2023 19:59:50 +0300 Subject: [PATCH 10/17] test for mac ver --- examples/str.c | 12 +- sili.h | 626 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 476 insertions(+), 162 deletions(-) diff --git a/examples/str.c b/examples/str.c index d2364e9..97b83fd 100644 --- a/examples/str.c +++ b/examples/str.c @@ -49,15 +49,10 @@ void example_1_0(void) { printf("Current str2: %s\n", str2); siArray(siString) list = si_string_split(str2, "."); - usize i; - for (i = 0; i < si_array_len(list); i++) { + + for_range (i, {0, si_array_len(list)}) { printf("\tElement %zd: '%s'\n", i, list[i]); - si_string_free(list[i]); } - - si_string_free(str); - si_string_free(str2); - si_array_free(list); } void example_1_1(void) { @@ -108,9 +103,12 @@ void example_1_2(void) { int main(void) { + si_init(SI_KILO(1)); + example_1_0(); example_1_1(); example_1_2(); + si_terminate(); return 0; } diff --git a/sili.h b/sili.h index 3550ae8..8ca9370 100644 --- a/sili.h +++ b/sili.h @@ -45,8 +45,6 @@ CREDITS #ifndef SI_INCLUDE_SI_H #define SI_INCLUDE_SI_H -#define SI_IMPLEMENTATION 1 - #if defined(__cplusplus) extern "C" { #endif @@ -92,7 +90,7 @@ extern "C" { #endif -#if defined(__CPLUS__) +#if defined(__cplus__) #define SI_LANGUAGE_CPLUS 1 #elif defined(__cplusplus) #define SI_LANGUAGE_CPP 1 @@ -193,7 +191,6 @@ extern "C" { #include #include - #include #include #include @@ -224,6 +221,7 @@ extern "C" { #endif #if defined(SI_SYSTEM_UNIX) +#include #endif #if !defined(u8) @@ -249,36 +247,36 @@ extern "C" { typedef u8 siByte; -#define SI_UINT8_MAX 0xFF; -#define SI_UINT8_MIN 0x00; -#define SI_INT8_MAX 0x7F; -#define SI_INT8_MIN -0x80; +#define SI_UINT8_MAX 0xFF +#define SI_UINT8_MIN 0x00 +#define SI_INT8_MAX 0x7F +#define SI_INT8_MIN -0x80 -#define SI_UINT16_MAX 0xFFFF; -#define SI_UINT16_MIN 0x0000; -#define SI_INT16_MAX 0x7FFF; -#define SI_INT16_MIN -0x8000; +#define SI_UINT16_MAX 0xFFFF +#define SI_UINT16_MIN 0x0000 +#define SI_INT16_MAX 0x7FFF +#define SI_INT16_MIN -0x8000 -#define SI_UINT32_MAX 0xFFFFFFFF; -#define SI_UINT32_MIN 0x00000000; -#define SI_INT32_MAX 0x7FFFFFFF; -#define SI_INT32_MIN -0x80000000; +#define SI_UINT32_MAX 0xFFFFFFFF +#define SI_UINT32_MIN 0x00000000 +#define SI_INT32_MAX 0x7FFFFFFF +#define SI_INT32_MIN -0x80000000 -#define SI_UINT64_MAX 0xFFFFFFFFFFFFFFFF; -#define SI_UINT64_MIN 0x0000000000000000; -#define SI_INT64_MAX 0x7FFFFFFFFFFFFFFF; -#define SI_INT64_MIN -0x8000000000000000; +#define SI_UINT64_MAX 0xFFFFFFFFFFFFFFFF +#define SI_UINT64_MIN 0x0000000000000000 +#define SI_INT64_MAX 0x7FFFFFFFFFFFFFFF +#define SI_INT64_MIN -0x8000000000000000 #if defined(SI_ARCH_64_BIT) - #define SI_USIZE_MAX 0xFFFFFFFFFFFFFFFF; - #define SI_USIZE_MIN 0x0000000000000000; - #define SI_ISIZE_MAX 0x7FFFFFFFFFFFFFFF; - #define SI_ISIZE_MIN -0x8000000000000000; + #define SI_USIZE_MAX 0xFFFFFFFFFFFFFFFF + #define SI_USIZE_MIN 0x0000000000000000 + #define SI_ISIZE_MAX 0x7FFFFFFFFFFFFFFF + #define SI_ISIZE_MIN -0x8000000000000000 #else - #define SI_USIZE_MAX 0xFFFFFFFF; - #define SI_USIZE_MIN 0x00000000; - #define SI_ISIZE_MAX 0x7FFFFFFF; - #define SI_ISIZE_MIN -0x80000000; + #define SI_USIZE_MAX 0xFFFFFFFF + #define SI_USIZE_MIN 0x00000000 + #define SI_ISIZE_MAX 0x7FFFFFFF + #define SI_ISIZE_MIN -0x80000000 #endif @@ -294,6 +292,20 @@ SI_STATIC_ASSERT(sizeof(u64) == 8); SI_STATIC_ASSERT(sizeof(usize) == sizeof(isize)); + +typedef float f32; +typedef double f64; + +SI_STATIC_ASSERT(sizeof(f32) == 4); +SI_STATIC_ASSERT(sizeof(f64) == 8); + +#define SI_F32_MIN 1.17549435e-38f +#define SI_F32_MAX 3.40282347e+38f + +#define SI_F64_MIN 2.2250738585072014e-308 +#define SI_F64_MAX 1.7976931348623157e+308 + + #if !defined(bool) typedef u8 b8; typedef u16 b16; @@ -329,19 +341,6 @@ SI_STATIC_ASSERT(sizeof(usize) == sizeof(isize)); SI_STATIC_ASSERT(sizeof(uintptr) == sizeof(intptr)); -typedef float f32; -typedef double f64; - -SI_STATIC_ASSERT(sizeof(f32) == 4); -SI_STATIC_ASSERT(sizeof(f64) == 8); - -#define SI_F32_MIN 1.17549435e-38f -#define SI_F32_MAX 3.40282347e+38f - -#define SI_F64_MIN 2.2250738585072014e-308 -#define SI_F64_MAX 1.7976931348623157e+308 - - #if !defined(rawptr) typedef void* rawptr; #endif @@ -356,9 +355,9 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); ======================== */ #define SI_OKAY 0 -#define SI_ERROR (isize)-1 +#define SI_ERROR -1 -#define SI_BIT(x) (1 << (x)) +#define SI_BIT(x) (1 << (x)) #define SI_KILO(x) ( (x) * (usize)1024) #define SI_MEGA(x) (SI_KILO(x) * (usize)1024) @@ -417,6 +416,7 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); ======================== */ #define si_swap(a, b) do { typeof((a)) tmp = (a); (a) = (b); (b) = tmp; } while (0) +#define si_abs(x) ((x) < 0 ? -(x) : (x)) #define si_between(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper))) #define si_pause() do { printf("Press any key to continue...\n"); getchar(); } while(0) @@ -454,16 +454,23 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); | Mics/General | ======================== */ +#define si_init(size) do { SI_GLOBAL_ALLOC = si_allocator_init(size); } while(0) +#define si_terminate() do { si_allocator_free(SI_GLOBAL_ALLOC); } while(0) /* ======================== | SI_ASSERT | ======================== */ -usize si_impl_assert_msg(bool condition, cstring condition_str, cstring message, cstring file, i32 line); -#define SI_ASSERT_MSG(condition, message) si_impl_assert_msg(condition, #condition, message, __FILE__, __LINE__) +usize si_impl_assert_msg(bool condition, cstring condition_str, cstring file, i32 line, cstring message, ...); + #define SI_ASSERT(condition) SI_ASSERT_MSG(condition, nil) +#define SI_ASSERT_MSG(condition, message) si_impl_assert_msg(condition, #condition, __FILE__, __LINE__, message, "") +#define SI_ASSERT_FMT(condition, message, ...) si_impl_assert_msg(condition, #condition, __FILE__, __LINE__, message, __VA_ARGS__) #define SI_ASSERT_NOT_NULL(ptr) SI_ASSERT_MSG((ptr) != nil, #ptr " must not be NULL") +#define SI_PANIC() si_impl_assert_msg(false, "SI_PANIC()", __FILE__, __LINE__, message, "") +#define SI_PANIC_MSG(message) si_impl_assert_msg(false, "SI_PANIC(" message ")", __FILE__, __LINE__, message, "") + /* ======================== @@ -487,7 +494,7 @@ typedef struct siFunction { rawptr SI_FUNC_PTR(ptr, (rawptr)); } siFunction; -#define siFunc(func) (siFunction){(SI_FUNC_PTR(, (rawptr)))func} +#define siFunc(func) (siFunction){(rawptr (*)(rawptr))func} /* ======================== @@ -548,6 +555,51 @@ void si_ptr_move_by(rawptr src, usize src_len, usize move_by, siDirection direct * * */ +#if !defined(SI_ALLOCATOR_UNDEFINE) +/* +* +* +* +* +* +* +* +* +* +* +* +* +* +* + ======================== + | siAllocator | + ======================== +*/ +typedef struct siAllocator { + siByte* ptr; + usize max_size; + usize index; +} siAllocator; + +siAllocator* SI_GLOBAL_ALLOC; + + +inline siAllocator* si_allocator_init(usize bytes); +inline void si_allocator_refill(siAllocator* alloc); +inline void si_allocator_free(siAllocator* alloc); + +inline rawptr si_malloc(siAllocator* alloc, usize bytes); +inline rawptr si_calloc(siAllocator* alloc, usize num, usize bytes); +inline rawptr si_realloc(siAllocator* alloc, rawptr ptr, usize old_size, usize new_size); + + +#if !defined(SI_MEMORY_LOGGING) + #define malloc(bytes) si_malloc(SI_GLOBAL_ALLOC, bytes) + #define calloc(num, bytes) si_calloc(SI_GLOBAL_ALLOC, num, bytes) + #define realloc(ptr, old_size, new_size) si_realloc(SI_GLOBAL_ALLOC, ptr, old_size, new_size) +#endif + +#endif #if !defined(SI_PAIR_UNDEFINE) /* @@ -643,10 +695,20 @@ typedef struct siArrayHeader { #define siArray(type) type* #define SI_ARRAY_HEADER(array) ((siArrayHeader*)array - 1) -#if defined(SI_STANDARD_C89) - #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) -#else - #define foreach(variable_name, array) for (typeof(*(array)) variable_name = *(array); (typeof(array)){&variable_name} != array + si_array_len(array); (typeof(array)){&variable_name} += 1) +/** + * @def foreach(variable_name, array) + * + * @brief Macro to iterate over elements of a siString. + * + * @param variable_name The name of the iterator variable. + * @param array The siString to iterate over. + */ +#if !defined(foreach) + #if !defined(SI_STANDARD_C89) + #define foreach(variable_name, array) for (typeof(*(array)) variable_name = *(array); &variable_name != ((array) + si_array_len(array)); (typeof(array)){&variable_name} += 1) + #else + #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) + #endif #endif #define si_array_get_ptr(array, index) \ @@ -744,9 +806,11 @@ typedef struct siBufferHeader { #define si_buffer_reverse(buffer) si_impl_buffer_reverse(buffer, SI_BUFFER_HEADER(buffer)) #define si_buffer_to_sistring(buffer, separator) si_impl_buffer_to_sistring(buffer, SI_BUFFER_HEADER(buffer), separator) +#define si_buffer_sum_i64(buffer) si_impl_buffer_sum_i64(buffer, SI_BUFFER_HEADER(buffer)) +#define si_buffer_sum_f64(buffer) si_impl_buffer_sum_f64(buffer, SI_BUFFER_HEADER(buffer)) #define si_buffer_clear(buffer) si_impl_buffer_clear(buffer, SI_BUFFER_HEADER(buffer)) -#define si_buffer_compare(buffer_left, buffer_right) si_impl_buffer_compare(buffer_left, SI_BUFFER_HEADER(buffer_left), buffer_right, SI_BUFFER_HEADER(buffer_right)) +#define si_buffer_cmp(buffer_left, buffer_right) si_impl_buffer_cmp(buffer_left, SI_BUFFER_HEADER(buffer_left), buffer_right, SI_BUFFER_HEADER(buffer_right)) /* NOTE(EimaMei): The actual implementations. Shouldn't be used in practice, really. */ @@ -759,8 +823,11 @@ isize si_impl_buffer_replace(rawptr buffer, siBufferHeader* header, siAny old_va isize si_impl_buffer_reverse(rawptr buffer, siBufferHeader* header); char* si_impl_buffer_to_sistring(rawptr buffer, siBufferHeader* header, cstring separator); +i64 si_impl_buffer_sum_i64(rawptr buffer, siBufferHeader* header); +f64 si_impl_buffer_sum_f64(rawptr buffer, siBufferHeader* header); + void si_impl_buffer_clear(rawptr buffer, siBufferHeader* header); -bool si_impl_buffer_compare(rawptr buffer_left, siBufferHeader* header_left, rawptr buffer_right, siBufferHeader* header_right); +bool si_impl_buffer_cmp(rawptr buffer_left, siBufferHeader* header_left, rawptr buffer_right, siBufferHeader* header_right); #endif #if !defined(SI_STRING_UNDEFINE) @@ -801,21 +868,6 @@ typedef struct siStringHeader { u8 grow; } siStringHeader; -/** - * @def foreach(variable_name, array) - * - * @brief Macro to iterate over elements of a siString. - * - * @param variable_name The name of the iterator variable. - * @param array The siString to iterate over. - */ -#if !defined(foreach) - #if defined(SI_STANDARD_C89) - #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) - #else - #define foreach(variable_name, array) for (typeof(*(array)) variable_name = *(array); &variable_name != ((array) + si_array_len(array)); (&variable_name) += 1) - #endif -#endif /** * @def SI_STRING_HEADER(str) @@ -1026,19 +1078,111 @@ isize si_string_rfind_ex(siString str, usize start, usize end, cstring cstr); * @return The new length of the siString after the join operation. */ void si_string_join(siString* str, cstring cstr, cstring separator); + + +/** + * @brief Sets the siString to a null-terminated C string. + * + * @param str The siString to set. + * @param cstr The new contents of the siString. +*/ void si_string_set(siString* str, cstring cstr); + +/** + * @brief Replaces all occurences of first null-terminated C string, `old_str`, + * in the siString to the second null-terminted C string, `new_str`. + * + * @param str The siString to edit. + * @param old_str The string to be replaced. + * @param new_str The string that'll replace the old string. +*/ void si_string_replace(siString* str, cstring old_str, cstring new_str); + +/** + * @brief Cuts all occurences of the null-terminated C string in the siString. + * + * @param str The siString. + * @param cut_set The string you want to be completely cut. +*/ void si_string_trim(siString* str, cstring cut_set); + +/** + * @brief Enquotes siString (String 'test' becomes '"test"'). + * + * @param str The siString to enquote. +*/ void si_string_enquote(siString* str); +/** + * @brief Appends a null-terminated C string to the siString. + * + * @param str The siString to append to. + * @param other The C string to append. +*/ void si_string_append(siString* str, cstring other); + +/** + * @brief Appends a C string to the siString. + * + * @note This is the expanded version of the `si_string_append` function. Should + * be used when the length of the C string is known. + * + * @param str The siString to append to. + * @param other The C string to append. + * @param other_len Length of the C string (or how much of it to append). + * +*/ void si_string_append_len(siString* str, cstring other, usize other_len); + +/** + * @brief Pushes [appends] the character into the siString. + * + * @param str The siString to push to. + * @param other The character to push. +*/ void si_string_push(siString* str, char other); + +/** + * @brief Pops [erases] the last character of siString. + * + * @param str The siString to pop. +*/ void si_string_pop(siString* str); +/** + * @brief Inserts a null-terimnated C-string to the siString at the specified index. + * + * @param str The siString to edit. + * @param cstr The null-terminated C-string to insert. + * @param index The index in which the string is inserted. +*/ void si_string_insert(siString* str, cstring cstr, usize index); + +/** + * @brief Inserts a C-string to the siString at the specified index. + * + * @note This is the expanded version of the `si_string_insert` function. Should + * be used when the length of the C string is known and if to erase the + * character at the index. + * + * @param str The siString to edit. + * @param cstr The C string to insert. + * @param cstr_len The length of the C string to insert. + * @param index The index in which the string is inserted. + * @param erase_index Deletes the character at the specified index depending on + * the given boolean. +*/ void si_string_insert_ex(siString* str, cstring cstr, usize cstr_len, usize index, bool erase_index); + +/** + * @brief Erases a substring from the specified index. + * + * @param str The siString to edit. + * @param index The first index to erase. + * @param erase_len How much of the substring must be erased. +*/ void si_string_erase(siString* str, usize index, usize erase_len); + void si_string_remove_cstr(siString* str, cstring cstr); void si_string_swap(siString* str, cstring cstr1, cstring cstr2); @@ -1050,7 +1194,7 @@ siArray(siString) si_string_split(siString str, cstring separator); void si_string_clear(siString* str); void si_string_free(siString str); -isize si_string_make_space_for(siString* str, usize add_len); +void si_string_make_space_for(siString* str, usize add_len); void si_string_shrink_to_fit(siString* str); #endif @@ -1397,6 +1541,43 @@ void si_impl_performance_thread(u32* arg); printf(SI_PERFORMANCE_MSG, #function, (f64)si_miliseconds, (f64)si_counter / 1000000.0f);\ SI_PERFORMANCE_PRINT_MEMORY(function);\ } while(0) + +#define si_performance_loop_median(increments_of_10, function)\ + do { \ + usize si_array_len = 0; \ + usize si_num = increments_of_10; \ + while (si_num) { \ + si_num /= 10; \ + si_array_len += 1; \ + } \ + f64 si_exec_durations[si_array_len]; \ + \ + usize si_median_index, si_array_index = 0; \ + for (si_median_index = 1; si_median_index < 10 * increments_of_10; si_median_index *= 10) { \ + usize si_index = 0; \ + clock_t si_begin = clock(); \ + for (; si_index < si_median_index; si_index++) { \ + function; \ + } \ + si_begin = clock() - si_begin; \ + si_exec_durations[si_array_index] = (f64)(si_begin) / 1000.0; /* NOTE(EimaMei): This will take the time in ms, not seconds. */\ + si_array_index += 1; \ + } \ + printf( \ + "====== BENCHMARK DATA ======\n"\ + "General:\n"\ + "\tFunction - '%s'\n" \ + "Runs:\n", \ + #function \ + ); \ + si_array_index = 0; \ + for (si_median_index = 1; si_median_index < 10 * increments_of_10; si_median_index *= 10) { \ + printf("\t%zd run(s) - '%f' ms\n", si_median_index, si_exec_durations[si_array_index]); \ + si_array_index += 1; \ + } \ + printf("Final result:\n\tMedian - '%f' ms\n", si_buffer_sum_f64(si_exec_durations) / (f64)countof(si_exec_durations)); \ + SI_PERFORMANCE_PRINT_MEMORY(function); \ + } while(0) #endif #if defined(SI_MEMORY_LOGGING) @@ -1486,8 +1667,9 @@ void si_debug_cleanup(void); * */ -#ifdef SI_IMPLEMENTATION +#if defined(SI_IMPLEMENTATION) #define SI_GENERAL_IMPLEMENTATION + #define SI_ALLOCATOR_IMPLEMENTATION #define SI_PAIR_IMPLEMENTATION #define SI_OPTIONAL_IMPLEMENTATION #define SI_ARRAY_IMPLEMENTATION @@ -1501,13 +1683,26 @@ void si_debug_cleanup(void); #if defined(SI_GENERAL_IMPLEMENTATION) -usize si_impl_assert_msg(bool condition, cstring condition_str, cstring message, cstring file, i32 line) { - if (!condition) { - fprintf(stderr, "Assertion \"%s\" at \"%s:%d\"%s %s\n", condition_str, file, line, (message != nil ? ":" : ""), (message != nil ? message : "")); - abort(); +usize si_impl_assert_msg(bool condition, cstring condition_str, cstring file, i32 line, cstring message, ...) { + if (condition) { + return 0; + } + + + fprintf(stderr, "Assertion \"%s\" at \"%s:%d\"%s", condition_str, file, line, (message != nil ? ": " : "")); + + if (message != nil) { + va_list va; + + va_start(va, message); + vprintf(message, va); + puts(""); + va_end(va); } - return 0; + abort(); + + return 1; } #if defined(SI_MEMORY_LOGGING) @@ -1516,7 +1711,7 @@ usize si_impl_assert_msg(bool condition, cstring condition_str, cstring message, #undef free #endif -rawptr si_realloc(rawptr ptr, usize old_size, usize new_size) { +rawptr si_realloc_cpy(rawptr ptr, usize old_size, usize new_size) { if (ptr == nil) { return malloc(new_size); } @@ -1561,6 +1756,107 @@ void si_ptr_move_by(rawptr src, usize src_len, usize move_by, siDirection direct #endif +#if defined(SI_ALLOCATOR_IMPLEMENTATION) && !defined(SI_ALLOCATOR_UNDEFINE) + +#if !defined(SI_MEMORY_LOGGING) + #undef malloc + #undef calloc + #undef realloc +#endif + +inline siAllocator* si_allocator_init(usize bytes) { + rawptr ptr = malloc(sizeof(siAllocator) + bytes); + + siAllocator* res = (rawptr)ptr; + res->ptr = (siByte*)ptr + sizeof(siAllocator); + res->index = 0; + res->max_size = bytes; + + return res; +} +inline void si_allocator_refill(siAllocator* alloc) { + SI_ASSERT_MSG(alloc->ptr == nil, "Specified allocator hasn't been freed once, cannot refill."); + *alloc = *si_allocator_init(alloc->max_size); +} +inline void si_allocator_free(siAllocator* alloc) { + free(alloc->ptr - sizeof(siAllocator)); +} + +inline rawptr si_malloc(siAllocator* alloc, usize bytes) { + SI_ASSERT_NOT_NULL(alloc); + + siByte* res = alloc->ptr + alloc->index; + alloc->index += bytes; + + SI_ASSERT_FMT(alloc->index <= alloc->max_size, "Exceeded the available memory for allocation (Tried writing '%zd' bytes into a already filled allocator with '%zd' bytes. Current index: '%zd').", bytes, alloc->max_size, alloc->index); + + return res; +} + +inline rawptr si_calloc(siAllocator* alloc, usize num, usize bytes) { + rawptr res = si_malloc(alloc, num * bytes); + memset(res, 0, num * bytes); + + return res; +} + +inline void si_free(siAllocator* alloc, rawptr ptr) { + SI_ASSERT_NOT_NULL(alloc); + SI_ASSERT_NOT_NULL(ptr); + SI_ASSERT(si_between((siByte*)ptr, alloc->ptr, alloc->ptr + alloc->max_size)); + + alloc->index = (siByte*)ptr - alloc->ptr; +} +inline rawptr si_realloc(siAllocator* alloc, rawptr ptr, usize new_size, usize old_size) { + if (alloc == NULL) { + return NULL; + } + + if (ptr == NULL) { + return si_malloc(alloc, new_size); + } + + siByte* base_ptr = alloc->ptr; + siByte* byte_ptr = (siByte*)ptr; + + if (byte_ptr < base_ptr || byte_ptr >= base_ptr + alloc->max_size) { + // Error: ptr is not within the allocator's memory range + // Handle the error accordingly + return NULL; + } + + usize old_index = byte_ptr - base_ptr; + + if (new_size == 0) { + si_free(alloc, ptr); + return NULL; + } + + isize size_diff = new_size - old_size; + + if (size_diff > 0) { + rawptr new_ptr = si_malloc(alloc, new_size); + if (new_ptr == NULL) { + return NULL; + } + memcpy(new_ptr, ptr, old_size); + si_free(alloc, ptr); + return new_ptr; + } + + alloc->index = old_index + new_size; + return ptr; +} + + +#if !defined(SI_MEMORY_LOGGING) + #define malloc(bytes) si_malloc(SI_GLOBAL_ALLOC, bytes) + #define calloc(num, bytes) si_calloc(SI_GLOBAL_ALLOC, num, bytes) + #define realloc(ptr, old_size, new_size) si_realloc(SI_GLOBAL_ALLOC, ptr, old_size, new_size) +#endif + +#endif + #if defined(SI_PAIR_IMPLEMENTATION) && !defined(SI_PAIR_UNDEFINE) rawptr si_impl_pair_make(siAny first, siAny second) { @@ -1588,11 +1884,11 @@ inline rawptr si_array_copy(rawptr array) { return si_array_make_list(array, header->type_size, header->len); } rawptr si_array_make_reserve(usize sizeof_element, usize count) { - siByte* ptr = (siByte*)malloc(sizeof(siArrayHeader) + (sizeof_element * count)); + siByte* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count)); rawptr array = ptr + sizeof(siArrayHeader); - siArrayHeader* header = SI_ARRAY_HEADER(array); - header->len = 0; /* TODO(EimaMei): FIX THIS!!!!!!!!!!!!!!!!!!!!! */ + siArrayHeader* header = (siArrayHeader*)ptr; + header->len = 0; header->capacity = count; header->type_size = sizeof_element; @@ -1679,10 +1975,10 @@ void si_impl_array_replace(rawptr array, siAny old_value, siAny new_value) { index = si_impl_array_find(array, index, header->len, old_value); if (index == SI_ERROR) { return ; - } + } memcpy(si_array_get_ptr(array, index), new_value.ptr, new_value.type_size); - } +} } void si_array_reverse(rawptr array_ptr) { SI_ASSERT_NOT_NULL(array_ptr); @@ -1716,8 +2012,9 @@ siString si_array_to_sistring(siArray(char*) array, cstring separator) { } siString result = si_string_make_reserve(total_size); + rawptr back_ptr = si_array_back(array).ptr; foreach (str, array) { - if (separator != nil && &str != si_array_back(array).ptr) { + if (separator != nil && (&str) != back_ptr) { si_string_join(&result, separator, str); } else { @@ -1736,11 +2033,15 @@ void si_impl_array_append(rawptr array_ptr, siAny value) { SI_ASSERT_MSG(value.type_size <= header->type_size, "The given value's sizeof is too large compared to the elements' in the arra"); if (header->len == header->capacity) { - siByte* result = (siByte*)si_realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_size, sizeof(siArrayHeader) + 2 * header->capacity * header->type_size); + if (header->capacity == 0) { + header->capacity = 1; + } + + siByte* result = realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_size, sizeof(siArrayHeader) + 2 * header->capacity * header->type_size); SI_ASSERT_NOT_NULL(result); array = result + sizeof(siArrayHeader); - *si_cast(siByte**, array_ptr) = array; + *si_cast(siByte**, array_ptr) = array; header = (siArrayHeader*)result; header->capacity *= 2; @@ -1889,11 +2190,31 @@ siString si_impl_buffer_to_sistring(rawptr buffer, siBufferHeader* header, cstri return result; } -void si_impl_buffer_clear(rawptr buffer, siBufferHeader* header) { +inline i64 si_impl_buffer_sum_i64(rawptr buffer, siBufferHeader* header) { + i64 res = 0; + usize i; + for (i = 0; i < header->len; i++) { + res += *si_buffer_get_ptr(buffer, header->type_size, i); + } + + return res; +} +inline f64 si_impl_buffer_sum_f64(rawptr buffer, siBufferHeader* header) { + f64 res = 0; + usize i; + for (i = 0; i < header->len; i++) { + f64 num = *si_cast(f64*, si_buffer_get_ptr(buffer, header->type_size, i)); + res += num; + } + + return res; +} + +inline void si_impl_buffer_clear(rawptr buffer, siBufferHeader* header) { rawptr result = memset(buffer, 0, header->len * header->type_size); SI_ASSERT_NOT_NULL(result); } -bool si_impl_buffer_compare(rawptr buffer_left, siBufferHeader* header_left, rawptr buffer_right, siBufferHeader* header_right) { +bool si_impl_buffer_cmp(rawptr buffer_left, siBufferHeader* header_left, rawptr buffer_right, siBufferHeader* header_right) { if (header_left->len != header_right->len || header_left->type_size != header_right->type_size) { return false; } @@ -1915,7 +2236,7 @@ bool si_impl_buffer_compare(rawptr buffer_left, siBufferHeader* header_left, raw inline siString si_string_make(cstring str) { - return si_string_make_len(str, str ? si_cstr_len(str) : 0); + return si_string_make_len(str, str ? si_cstr_len(str) : 0); } siString si_string_make_len(cstring str, usize len) { siString res_str = si_string_make_reserve(len); @@ -2036,7 +2357,7 @@ inline isize si_string_find(siString str, cstring cstr) { return si_string_find_ex(str, 0, si_string_len(str), cstr, si_cstr_len(cstr)); } isize si_string_find_ex(siString str, usize start, usize end, cstring cstr, usize cstr_len) { - SI_ASSERT_NOT_NULL(str); + SI_ASSERT_NOT_NULL(str); bool found = false; @@ -2062,7 +2383,7 @@ inline isize si_string_rfind(siString str, cstring cstr) { return si_string_rfind_ex(str, si_string_len(str) - 1, 0, cstr); } isize si_string_rfind_ex(siString str, usize start, usize end, cstring cstr) { - SI_ASSERT_NOT_NULL(str); + SI_ASSERT_NOT_NULL(str); usize cstr_len = si_cstr_len(cstr); bool found = false; @@ -2095,40 +2416,38 @@ void si_string_join(siString* str, cstring cstr, cstring separator) { si_string_append_len(str, tmp, separator_len + cstr_len); } void si_string_set(siString* str, cstring cstr) { - usize cur_len = si_string_len(*str); + SI_ASSERT_NOT_NULL(str); + siString cur_str = *str; + usize len = si_cstr_len(cstr); - siStringHeader* header = SI_STRING_HEADER(*str); - header->len += len - cur_len; + siStringHeader* header = SI_STRING_HEADER(cur_str); - if (header->capacity < header->len) { - isize result = si_string_make_space_for(str, len - cur_len); - SI_ASSERT_MSG(result == SI_OKAY, "Failed to make space for string"); + if (header->capacity < len) { + si_string_make_space_for(str, len - header->capacity); + cur_str = *str; + header = SI_STRING_HEADER(cur_str); } + header->len = len; - rawptr ptr = memcpy(*str, cstr, len); - SI_ASSERT_NOT_NULL(ptr); - (*str)[len] = '\0'; + memcpy(cur_str, cstr, len); + cur_str[len] = '\0'; } void si_string_replace(siString* str, cstring old_value, cstring new_value) { usize old_len = si_cstr_len(old_value); usize new_len = si_cstr_len(new_value); isize index = 0; - siString cur_str = nil; - bool old_len_bigger = (old_len > new_len); + siString cur_str = *str; while (true) { - cur_str = *str; - index = si_string_find_ex(cur_str, index, si_array_len(cur_str), old_value, old_len); + index = si_string_find_ex(cur_str, index, si_string_len(cur_str), old_value, old_len); if (index == SI_ERROR) { break; } - if (old_len_bigger) { - si_string_erase(str, index, old_len); - } - si_string_insert_ex(str, new_value, new_len, index - old_len_bigger, !old_len_bigger); + si_string_erase(str, index, old_len); + si_string_insert_ex(str, new_value, new_len, index, false); } } void si_string_trim(siString* str, cstring cut_set) { @@ -2157,8 +2476,7 @@ void si_string_enquote(siString* str) { header->len += 2; if (header->capacity < header->len) { - isize res = si_string_make_space_for(str, 2); - SI_ASSERT_MSG(res == SI_OKAY, "Failed to allocate space to str"); + si_string_make_space_for(str, 2); header = SI_STRING_HEADER(*str); } siString cur_str = *str; @@ -2177,9 +2495,8 @@ void si_string_append_len(siString* str, cstring other, usize other_len) { header->len += other_len; if (header->capacity < header->len) { - isize result = si_string_make_space_for(str, other_len); - SI_ASSERT_MSG(result == SI_OKAY, "Failed to make space for string"); - header = SI_STRING_HEADER(*str); /* NOTE(EimaMei): For some reason we have to refresh the header pointer on Linux. Somewhat makes sense but also what and why. */ + si_string_make_space_for(str, other_len); + header = SI_STRING_HEADER(*str); } rawptr ptr = memcpy(*str + previous_len, other, other_len); @@ -2206,14 +2523,13 @@ void si_string_insert_ex(siString* str, cstring cstr, usize cstr_len, usize inde header->len += cstr_len - erase_index; if (header->capacity < header->len) { - isize result = si_string_make_space_for(str, header->len - header->capacity); - SI_ASSERT_MSG(result == SI_OKAY, "Failed to make space for string"); + si_string_make_space_for(str, header->len - header->capacity); header = SI_STRING_HEADER(*str); /* NOTE(EimaMei): For some reason we have to refresh the header pointer on Linux. Somewhat makes sense but also what and why. */ } siString cur_str = *str; char* ptr = (char*)memcpy(cur_str + header->len - before_index_len, cur_str + index, before_index_len); - memcpy(cur_str + index + !erase_index, cstr, cstr_len); + memcpy(cur_str + index, cstr, cstr_len); SI_ASSERT_NOT_NULL(ptr); ptr[before_index_len] = '\0'; } @@ -2339,18 +2655,19 @@ void si_string_reverse_len(siString* str, usize len) { } siArray(siString) si_string_split(siString str, cstring separator) { + SI_ASSERT_NOT_NULL(str); + + usize str_len = si_string_len(str); usize separator_len = si_cstr_len(separator); usize count = 0; usize begin_pos = 0; - usize pos_buffer[si_string_len(str)]; - siString original = str; + usize pos_buffer[str_len]; while (true) { - isize pos = si_string_find_ex(str, begin_pos, si_string_len(str), separator, separator_len); - + isize pos = si_string_find_ex(str, begin_pos, str_len, separator, separator_len); if (pos == SI_ERROR) { - pos_buffer[count] = si_string_len(str); + pos_buffer[count] = pos_buffer[count - 1]; count++; break; } @@ -2359,20 +2676,24 @@ siArray(siString) si_string_split(siString str, cstring separator) { begin_pos = pos + separator_len; } - siArray(siString) res = (siArray(siString))si_array_make_reserve(sizeof(*res), count); /* NOTE(EimaMei): Fuck C++. Seriously, what the fuck? WHY DO WE HAVE TO THIS??? */ + printf("%s\n", str); + siArray(siString) res = si_array_make_reserve(sizeof(*res), count); + printf("%s\n", str); + SI_ARRAY_HEADER(res)->len = count; - usize i; - for (i = 0; i < count; i++) { - res[i] = si_string_make_len(original, pos_buffer[i]); - original += pos_buffer[i] + separator_len; + for_range (i, {0, count}) { + printf("%s\n", str); + res[i] = si_string_make_len(str, pos_buffer[i]); + str += pos_buffer[i] + separator_len; } - return res; } inline void si_string_clear(siString* str) { - **str = '\0'; + siString cur_str = *str; + *cur_str = '\0'; + SI_STRING_HEADER(cur_str)->len = 0; } inline void si_string_free(siString str) { @@ -2381,30 +2702,25 @@ inline void si_string_free(siString str) { } free(SI_STRING_HEADER(str)); } -isize si_string_make_space_for(siString* str, usize add_len) { +void si_string_make_space_for(siString* str, usize add_len) { usize len = si_string_len(*str); - usize new_len = len + add_len; - - rawptr ptr = *str - sizeof(siStringHeader); + rawptr ptr = SI_STRING_HEADER(*str); usize old_size = sizeof(siStringHeader) + len + 1; - usize new_size = sizeof(siStringHeader) + new_len + 1; + usize new_size = old_size + add_len; - rawptr new_ptr = si_realloc(ptr, old_size, new_size); + siStringHeader* new_ptr = realloc(ptr, old_size, new_size); SI_ASSERT_NOT_NULL(new_ptr); *str = (char*)new_ptr + sizeof(siStringHeader); - - SI_STRING_HEADER(*str)->capacity += add_len; - - return SI_OKAY; + new_ptr->capacity += add_len; } void si_string_shrink_to_fit(siString* str) { SI_ASSERT_NOT_NULL(str); siString cur_str = *str; siStringHeader copy = *SI_STRING_HEADER(cur_str); - siStringHeader* header = realloc(SI_STRING_HEADER(cur_str), sizeof(siStringHeader*) + copy.len + 1); + siStringHeader* header = realloc(SI_STRING_HEADER(cur_str), sizeof(siStringHeader*) + copy.capacity + 1, sizeof(siStringHeader*) + copy.len + 1); *header = copy; header->capacity = header->len; } @@ -2476,18 +2792,18 @@ cstring si_u64_to_cstr(u64 num) { u64 si_cstr_to_u64(cstring str) { SI_ASSERT_NOT_NULL(str); - u64 result = 0; + u64 result = 0; char cur; - while ((cur = *str++)) { - if (cur >= '0' && cur <= '9') { - result = (result * 10) + (cur - '0'); - } + while ((cur = *str++)) { + if (cur >= '0' && cur <= '9') { + result = (result * 10) + (cur - '0'); + } else { SI_ASSERT_MSG(!(cur >= '0' && cur <= '9'), "Attempted to use `si_cstr_to_u64` with a string that contains non numbers."); } - } + } - return result; + return result; } cstring si_i64_to_cstr(i64 num) { static char buffer[20 + 1]; /* NOTE(EimaMei): 19 chars is the maximum of numbers we can have in an i64. One more char for the possible minus symbol. */ @@ -2520,7 +2836,7 @@ cstring si_i64_to_cstr(i64 num) { i64 si_cstr_to_i64(cstring str) { SI_ASSERT_NOT_NULL(str); - i64 result = 0; + i64 result = 0; char cur; bool negative = false; @@ -2530,19 +2846,19 @@ i64 si_cstr_to_i64(cstring str) { } while ((cur = *str++)) { - if (cur >= '0' && cur <= '9') { - result = (result * 10) + (cur - '0'); - } + if (cur >= '0' && cur <= '9') { + result = (result * 10) + (cur - '0'); + } else { SI_ASSERT_MSG(!(cur >= '0' && cur <= '9'), "Attempted to use `si_cstr_to_u64` with a string that contains non numbers."); } - } + } if (negative) { result = -result; } - return result; + return result; } #endif @@ -2983,7 +3299,7 @@ rawptr si_debug_alloc(usize function_id, rawptr ptr, siDebugArgs args, cstring f res = realloc(header, sizeof(siDebugHeader) + size); - header->type = "si_realloc"; + header->type = "realloc"; header->len = args.second; header->state = 2; header->date = date; @@ -2994,9 +3310,9 @@ rawptr si_debug_alloc(usize function_id, rawptr ptr, siDebugArgs args, cstring f return res + sizeof(siDebugHeader); } - case 4: { /* si_realloc */ + case 4: { /* si_realloc_cpy */ if (ptr == SI_ARRAY_HEADER(si_debug.list)) { - res = si_realloc(ptr, args.first, args.second); + res = si_realloc_cpy(ptr, args.first, args.second); return res; } @@ -3004,9 +3320,9 @@ rawptr si_debug_alloc(usize function_id, rawptr ptr, siDebugArgs args, cstring f si_debug.allocs += 1; si_debug.frees += 1; - res = si_realloc(header, sizeof(siDebugHeader) + args.first, sizeof(siDebugHeader) + args.second); + res = si_realloc_cpy(header, sizeof(siDebugHeader) + args.first, sizeof(siDebugHeader) + args.second); - header->type = "si_realloc"; + header->type = "si_realloc_cpy"; header->len = args.second; header->state = 2; header->date = date; @@ -3122,7 +3438,7 @@ void si_debug_cleanup(void) { #define malloc(size) si_debug_alloc(1, nil, (siDebugArgs){size, 0}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) #define calloc(num, size) si_debug_alloc(2, nil, (siDebugArgs){size, num}, num, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) #define realloc(ptr, new_size) si_debug_alloc(3, ptr, (siDebugArgs){0, new_size}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) -#define si_realloc(ptr, old_size, new_size) si_debug_alloc(4, ptr, (siDebugArgs){old_size, new_size}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) +#define si_realloc_cpy(ptr, old_size, new_size) si_debug_alloc(4, ptr, (siDebugArgs){old_size, new_size}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) #define free(ptr) si_debug_free(ptr) #endif From 484114b03d7c6f2705997c6352c5ed2169cb402a Mon Sep 17 00:00:00 2001 From: EimaMei Date: Sun, 18 Jun 2023 10:27:13 -0700 Subject: [PATCH 11/17] i like vim (fixed mac version) --- sili.h | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/sili.h b/sili.h index 8ca9370..a3a7eb8 100644 --- a/sili.h +++ b/sili.h @@ -218,6 +218,7 @@ extern "C" { #endif #if defined(SI_SYSTEM_OSX) +#include #endif #if defined(SI_SYSTEM_UNIX) @@ -1361,7 +1362,7 @@ typedef struct siThread { #if defined(SI_SYSTEM_WINDOWS) HANDLE id; #else - usize id; + pthread_t id; #endif volatile bool is_running; rawptr return_value; @@ -2885,8 +2886,12 @@ isize si_path_copy(cstring existing_path, cstring new_path) { struct stat stat_existing; fstat(existing_fd, &stat_existing); - - isize size = sendfile(new_fd, existing_fd, 0, stat_existing.st_size); + + #if defined(SI_SYSTEM_UNIX) + isize size = sendfile(new_fd, existing_fd, 0, stat_existing.st_size); + #else + isize size = sendfile(new_fd, existing_fd, 0, &stat_existing.st_size, NULL, 0); + #endif close(new_fd); close(existing_fd); @@ -2913,8 +2918,6 @@ inline isize si_path_remove(cstring path) { else { return (RemoveDirectoryA(path) != 0); } - #elif defined(SI_SYSTEM_OSX) - return unlink(filename); #else return remove(path); #endif @@ -3143,11 +3146,7 @@ inline siThread si_thread_create(siFunction function, rawptr arg) { inline void si_thread_start(siThread* t) { - usize minimum = 0; - #if !defined(SI_SYSTEM_WINDOWS) - minimum = PTHREAD_STACK_MIN; - #endif - si_thread_start_stack(t, minimum); + si_thread_start_stack(t, 0); } void si_thread_start_stack(siThread* t, usize stack_size) { @@ -3181,20 +3180,19 @@ void si_thread_join(siThread* t) { t->is_running = true; #if defined(SI_SYSTEM_WINDOWS) - WaitForSingleObject(t->id, INFINITE); - CloseHandle(t->id); - t->id = INVALID_HANDLE_VALUE; + WaitForSingleObject(t->id, INFINITE); + CloseHandle(t->id); + t->id = INVALID_HANDLE_VALUE; #else + usize error_code = pthread_join(t->id, nil); - usize error_code = pthread_join(t->id, nil); - - cstring error_msg = nil; - switch (error_code) { - case SI_OKAY: break; - case EDEADLK: error_msg = "A deadlock was detected."; break; - default: error_msg = si_string_make_fmt("Unknown error code (%li).", error_code); - } - SI_ASSERT_MSG(error_code == SI_OKAY, error_msg); + cstring error_msg = nil; + switch (error_code) { + case SI_OKAY: break; + case EDEADLK: error_msg = "A deadlock was detected."; break; + default: error_msg = si_string_make_fmt("Unknown error code (%li).", error_code); + } + SI_ASSERT_MSG(error_code == SI_OKAY, error_msg); #endif t->is_running = false; @@ -3226,7 +3224,7 @@ void si_thread_set_priority(siThread t, i32 priority) { #if defined(SI_SYSTEM_WINDOWS) isize res = SetThreadPriority(t.id, priority); SI_ASSERT_MSG(res != 0, "Something went wrong setting the thread priority."); - #else + #elif defined(SI_SYSTEM_UNIX) usize error_code = pthread_setschedprio(t.id, priority); cstring error_msg = nil; @@ -3239,6 +3237,10 @@ void si_thread_set_priority(siThread t, i32 priority) { default: error_msg = si_string_make_fmt("Unknown error code (%li).", error_code); } SI_ASSERT_MSG(error_code == SI_OKAY, error_msg); + #else + SI_PANIC_MSG("si_thread_set_priority: Not supported on MacOS."); + SI_UNUSED(t); + SI_UNUSED(priority); #endif } From b0cfe794f07cbd89dd456fe47caa5ee012640968 Mon Sep 17 00:00:00 2001 From: EimaMei Date: Mon, 19 Jun 2023 00:23:25 +0300 Subject: [PATCH 12/17] sili.h fixed (allah) --- examples/array.c | 27 ++++++---- examples/benchmarking.c | 4 +- examples/file.c | 33 +++++------- examples/optional.c | 6 +-- examples/pair.c | 11 ++-- examples/str.c | 18 +++---- examples/thread.c | 13 +++-- sili.h | 109 ++++++++++++++++++---------------------- 8 files changed, 103 insertions(+), 118 deletions(-) diff --git a/examples/array.c b/examples/array.c index 55e7ef1..c4ef302 100644 --- a/examples/array.c +++ b/examples/array.c @@ -1,14 +1,14 @@ -//#define SI_IMPLEMENTATION 1 +#define SI_IMPLEMENTATION 1 #include void example_2_0(void) { - printf("==============\n\n==============\nExample 2.0:\n"); + printf("==============\n\n==============\nExample 2.0:\n"); siArray(i32) array = si_array_make((i32[]){3, 234, 2, 4, 294, 234, 23}); - foreach (num, array) { - printf("Element %zd: %i\n", (num - array), *num); + for_range (i, {0, si_array_len(array)}) { + printf("Element %zd: %i\n", i, array[i]); } isize find_pos = si_array_find(array, 234); @@ -29,32 +29,37 @@ void example_2_0(void) { bool res = si_arrays_are_equal(array, copy); printf("Arrays 'array' and 'copy' are %s\n", (res ? "the same" : "NOT the same")); - - si_array_free(array); - si_array_free(copy); } void example_2_1(void) { printf("==============\n\n==============\nExample 2.1:\n"); + + siArray(i32) array = si_array_make((i32[]){1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + printf("Array in regular order: "); foreach (num, array) { printf("%i ", *num); } printf("\n"); + + si_array_reverse(&array); + printf("Array in reverse order: "); foreach (num, array) { printf("%i ", *num); } printf("\n"); - si_array_free(array); } int main(void) { - example_2_0(); - example_2_1(); + si_init(SI_KILO(1)); + + example_2_0(); + example_2_1(); - return 0; + si_terminate(); + return 0; } diff --git a/examples/benchmarking.c b/examples/benchmarking.c index a8d2d61..90afa01 100644 --- a/examples/benchmarking.c +++ b/examples/benchmarking.c @@ -15,6 +15,8 @@ int main(void) { printf("Now lets see how many times 'performance_test()' can be executed in 5 seconds...\n"); si_performance_executes_per_ms(5000, performance_test()); + printf("The median performance:\n"); + si_performance_loop_median(10000, performance_test()); - return 0; + return 0; } diff --git a/examples/file.c b/examples/file.c index dea94ef..01a910d 100644 --- a/examples/file.c +++ b/examples/file.c @@ -5,12 +5,12 @@ void example_4_0(void) { printf("==============\n\n==============\nExample 4.0:\n"); - siFile file = si_file_open("example.c"); /* If the file doesn't exist or fails to open any other way, then we will get an assertion error. */ - printf("About 'example.c':\n\tFull path - '%s'\n\tSize - '%zu' bytes\n", file.path, file.size); + siFile file = si_file_open("examples/array.c"); /* If the file doesn't exist or fails to open any other way, then we will get an assertion error. */ + printf("About 'examples/array.c':\n\tFull path - '%s'\n\tSize - '%zu' bytes\n", file.path, file.size); siFile new_file = si_file_create("random.txt"); si_file_write(&new_file, "A silly file\nwith a sili newline."); - printf("About 'random.txt':\n\tFull path - '%s'\n\tSize - '%zu' bytes\n", file.path, file.size); + printf("About 'random.txt':\n\tFull path - '%s'\n\tSize - '%zu' bytes\n", new_file.path, new_file.size); siString content = si_file_read(new_file); printf("\tContent - '%s' (len: '%zd')\n", content, si_string_len(content)); @@ -18,28 +18,20 @@ void example_4_0(void) { siArray(siString) file_lines = si_file_readlines(file); printf("Contents of '%s' ('%zd' lines in total):\n", si_path_base_name(file.path), si_array_len(file_lines)); - usize i; - for (i = 0; i < si_array_len(file_lines); i++) { + for_range (i, {0, si_array_len(file_lines)}) { si_string_strip(&file_lines[i]); printf("\tLine %zd: '%s'\n", i, file_lines[i]); - si_string_free(file_lines[i]); } - si_file_write_at_line(&new_file, "but now we have a changed line\n", 1); + si_file_write_at_line(&new_file, "but now we have a changed line", 1); siArray(siString) new_file_lines = si_file_readlines(new_file); printf("Contents of '%s' ('%zd' lines in total):\n", si_path_base_name(new_file.path), si_array_len(new_file_lines)); - for (i = 0; i < si_array_len(new_file_lines); i++) { + for_range (i, {0, si_array_len(new_file_lines)}) { si_string_strip(&new_file_lines[i]); printf("\tLine %zd: '%s'\n", i, new_file_lines[i]); - si_string_free(new_file_lines[i]); } - //si_string_free(content); - - si_array_free(file_lines); - si_array_free(new_file_lines); - si_file_close(file); si_file_close(new_file); } @@ -54,7 +46,7 @@ void example_4_1(void) { if (!exist) { printf("Since 'random.txt' doesn't exist, we'll just create one\n"); - siFile file = si_file_open_mode("random.txt", SI_FILE_MODE_CREATE); + siFile file = si_file_create("random.txt"); si_file_write(&file, "Creating files is too easy tbh."); si_file_close(file); } @@ -74,14 +66,15 @@ void example_4_1(void) { res = si_path_remove("renamed.txt"); printf("Does 'renamed.txt' exist: '%zd' (res: '%zd')\n", si_path_exists("renamed.txt"), res); - - si_string_free(full_path); } int main(void) { - example_4_0(); - example_4_1(); + si_init(SI_KILO(6)); + + example_4_0(); + example_4_1(); - return 0; + si_terminate(); + return 0; } diff --git a/examples/optional.c b/examples/optional.c index 0eeaf8e..0029d80 100644 --- a/examples/optional.c +++ b/examples/optional.c @@ -8,13 +8,13 @@ siOptional(char*) create(bool value) { int main(void) { - /* Example 5.0: siOptional (based on https://en.cppreference.com/w/cpp/utility/optional). */ + /* Example 5.0: siOptional (based on https://en.cppreference.com/w/cpp/utility/optional). */ printf("==============\n\n==============\nExample 5.0:\n"); - printf("create(false) returned '%s'\n", si_optional_if_no_value(create(false), (char*)"empty")); + printf("create(false) returned '%s'\n", si_optional_get_or_default(char*, create(false), "empty")); siOptional(char*) str = create(true); printf("create2(true) returned '%s'\n", si_any_get(str.value, char*)); - return 0; + return 0; } diff --git a/examples/pair.c b/examples/pair.c index 1bbd725..924daba 100644 --- a/examples/pair.c +++ b/examples/pair.c @@ -3,7 +3,9 @@ int main(void) { - /* Example 3.0: siPair (based on https://cplusplus.com/reference/utility/pair/pair/) */ + si_init(SI_KILO(1)); + + /* Example 3.0: siPair (based on https://cplusplus.com/reference/utility/pair/pair/) */ printf("==============\n\n==============\nExample 3.0:\n"); siPair(siString, f64) product1; @@ -19,9 +21,6 @@ int main(void) { printf("The price of %s is $%f\n", product3.first, product3.second); printf("The price of %s is $%f\n", product4.first, product4.second); - si_string_free(product1.first); - si_string_free(product2.first); - si_string_free(product4.first); - - return 0; + si_terminate(); + return 0; } diff --git a/examples/str.c b/examples/str.c index 97b83fd..4d66675 100644 --- a/examples/str.c +++ b/examples/str.c @@ -3,7 +3,7 @@ void example_1_0(void) { - printf("==============\nExample 1.0:\n"); + printf("==============\nExample 1.0:\n"); siString str = si_string_make("Labas, Pasauli!"); printf("str: %s\n", str); @@ -56,7 +56,7 @@ void example_1_0(void) { } void example_1_1(void) { - printf("==============\n\n==============\nExample 1.1:\n"); + printf("==============\n\n==============\nExample 1.1:\n"); /* Int stuff: */ siString str = si_string_make(si_i64_to_cstr(-342)); printf("str: \"%s\"\n", str); @@ -86,29 +86,29 @@ void example_1_1(void) { si_cstr_capitalize(str); printf("Capitalized str: \"%s\"\n", str); - - si_string_free(str); } void example_1_2(void) { printf("==============\n\n==============\nExample 1.2:\n"); + siString str = si_string_make("\t dnuora gniliart "); printf("Before: '%s' (len: '%zd')\n", str, si_string_len(str)); + si_string_strip(&str); printf("After: '%s' (len: '%zd')\n", str, si_string_len(str)); + si_string_reverse(&str); printf("'str' in reverse: '%s'\n", str); - si_string_free(str); } int main(void) { si_init(SI_KILO(1)); - example_1_0(); - example_1_1(); - example_1_2(); + example_1_0(); + example_1_1(); + example_1_2(); si_terminate(); - return 0; + return 0; } diff --git a/examples/thread.c b/examples/thread.c index 6e8cd25..0d29564 100644 --- a/examples/thread.c +++ b/examples/thread.c @@ -29,6 +29,8 @@ rawptr thread_test(bool* arg) { int main(void) { + si_init(SI_KILO(1)); + siThread thread = si_thread_create(siFunc(thread_test), &(bool){false}); si_thread_start(&thread); @@ -36,8 +38,8 @@ int main(void) { printf("Even though 'thread' is currently sleeping, it's still running this exact second!\n"); si_sleep(1000); } + printf("That loop returned a '%i'. Now we'll re-run the loop with the argument being 'true' instead.\n", *((i16*)thread.return_value)); - free(thread.return_value); si_sleep(2000); thread.arg = &(bool){true}; @@ -45,19 +47,16 @@ int main(void) { si_thread_join(&thread); /* Now we have to wait... */ printf("That loop NOW returned a '%i'.\n", *((i16*)thread.return_value)); - free(thread.return_value); si_sleep(2000); #if !defined(SI_SYSTEM_WINDOWS) si_thread_start(&thread); si_sleep(2500); si_thread_cancel(&thread); - printf("Decided to kill it 2.5 seconds later.\n"); - if (thread.return_value != nil) { - free(thread.return_value); - } + printf("Decided to kill it 2.5 seconds later.\n"); #endif - return 0; + si_terminate(); + return 0; } diff --git a/sili.h b/sili.h index a3a7eb8..b55152e 100644 --- a/sili.h +++ b/sili.h @@ -706,9 +706,9 @@ typedef struct siArrayHeader { */ #if !defined(foreach) #if !defined(SI_STANDARD_C89) - #define foreach(variable_name, array) for (typeof(*(array)) variable_name = *(array); &variable_name != ((array) + si_array_len(array)); (typeof(array)){&variable_name} += 1) + #define foreach(variable_name, array) for (typeof(array) variable_name = array; variable_name != (typeof(array))si_array_get_ptr(array, si_array_len(array)); variable_name += 1) #else - #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = (array); variable_name != (array) + si_array_len((array)); variable_name += 1) + #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = array; variable_name != (typeof(array))si_array_get_ptr(array, si_array_len(array)); variable_name += 1) #endif #endif @@ -1802,50 +1802,39 @@ inline rawptr si_calloc(siAllocator* alloc, usize num, usize bytes) { } inline void si_free(siAllocator* alloc, rawptr ptr) { - SI_ASSERT_NOT_NULL(alloc); - SI_ASSERT_NOT_NULL(ptr); - SI_ASSERT(si_between((siByte*)ptr, alloc->ptr, alloc->ptr + alloc->max_size)); + SI_ASSERT_NOT_NULL(alloc); + SI_ASSERT_NOT_NULL(ptr); + SI_ASSERT(si_between((siByte*)ptr, alloc->ptr, alloc->ptr + alloc->max_size)); - alloc->index = (siByte*)ptr - alloc->ptr; + alloc->index = (siByte*)ptr - alloc->ptr; } inline rawptr si_realloc(siAllocator* alloc, rawptr ptr, usize new_size, usize old_size) { - if (alloc == NULL) { - return NULL; - } + SI_ASSERT_NOT_NULL(alloc); - if (ptr == NULL) { + if (ptr == nil) { return si_malloc(alloc, new_size); } + SI_ASSERT(si_between((siByte*)ptr, alloc->ptr, alloc->ptr + alloc->max_size)); - siByte* base_ptr = alloc->ptr; - siByte* byte_ptr = (siByte*)ptr; - - if (byte_ptr < base_ptr || byte_ptr >= base_ptr + alloc->max_size) { - // Error: ptr is not within the allocator's memory range - // Handle the error accordingly - return NULL; - } - - usize old_index = byte_ptr - base_ptr; + isize copy_size = (new_size < old_size) ? new_size : old_size; if (new_size == 0) { si_free(alloc, ptr); - return NULL; + return nil; } isize size_diff = new_size - old_size; if (size_diff > 0) { rawptr new_ptr = si_malloc(alloc, new_size); - if (new_ptr == NULL) { - return NULL; - } - memcpy(new_ptr, ptr, old_size); + memcpy(new_ptr, ptr, copy_size); si_free(alloc, ptr); + return new_ptr; } - alloc->index = old_index + new_size; + usize old_index = (siByte*)ptr - alloc->ptr + copy_size; + alloc->index = old_index + copy_size; return ptr; } @@ -2009,17 +1998,17 @@ siString si_array_to_sistring(siArray(char*) array, cstring separator) { usize total_size = 0; foreach (str, array) { - total_size += si_cstr_len(str) + separator_len; + total_size += si_cstr_len(*str) + separator_len; } siString result = si_string_make_reserve(total_size); rawptr back_ptr = si_array_back(array).ptr; foreach (str, array) { if (separator != nil && (&str) != back_ptr) { - si_string_join(&result, separator, str); + si_string_join(&result, separator, *str); } else { - si_string_append(&result, str); + si_string_append(&result, *str); } } @@ -2237,7 +2226,7 @@ bool si_impl_buffer_cmp(rawptr buffer_left, siBufferHeader* header_left, rawptr inline siString si_string_make(cstring str) { - return si_string_make_len(str, str ? si_cstr_len(str) : 0); + return si_string_make_len(str, str ? si_cstr_len(str) : 0); } siString si_string_make_len(cstring str, usize len) { siString res_str = si_string_make_reserve(len); @@ -2358,7 +2347,7 @@ inline isize si_string_find(siString str, cstring cstr) { return si_string_find_ex(str, 0, si_string_len(str), cstr, si_cstr_len(cstr)); } isize si_string_find_ex(siString str, usize start, usize end, cstring cstr, usize cstr_len) { - SI_ASSERT_NOT_NULL(str); + SI_ASSERT_NOT_NULL(str); bool found = false; @@ -2384,7 +2373,7 @@ inline isize si_string_rfind(siString str, cstring cstr) { return si_string_rfind_ex(str, si_string_len(str) - 1, 0, cstr); } isize si_string_rfind_ex(siString str, usize start, usize end, cstring cstr) { - SI_ASSERT_NOT_NULL(str); + SI_ASSERT_NOT_NULL(str); usize cstr_len = si_cstr_len(cstr); bool found = false; @@ -2677,14 +2666,10 @@ siArray(siString) si_string_split(siString str, cstring separator) { begin_pos = pos + separator_len; } - printf("%s\n", str); siArray(siString) res = si_array_make_reserve(sizeof(*res), count); - printf("%s\n", str); - SI_ARRAY_HEADER(res)->len = count; for_range (i, {0, count}) { - printf("%s\n", str); res[i] = si_string_make_len(str, pos_buffer[i]); str += pos_buffer[i] + separator_len; } @@ -2793,18 +2778,18 @@ cstring si_u64_to_cstr(u64 num) { u64 si_cstr_to_u64(cstring str) { SI_ASSERT_NOT_NULL(str); - u64 result = 0; + u64 result = 0; char cur; - while ((cur = *str++)) { - if (cur >= '0' && cur <= '9') { - result = (result * 10) + (cur - '0'); - } + while ((cur = *str++)) { + if (cur >= '0' && cur <= '9') { + result = (result * 10) + (cur - '0'); + } else { SI_ASSERT_MSG(!(cur >= '0' && cur <= '9'), "Attempted to use `si_cstr_to_u64` with a string that contains non numbers."); } - } + } - return result; + return result; } cstring si_i64_to_cstr(i64 num) { static char buffer[20 + 1]; /* NOTE(EimaMei): 19 chars is the maximum of numbers we can have in an i64. One more char for the possible minus symbol. */ @@ -2837,7 +2822,7 @@ cstring si_i64_to_cstr(i64 num) { i64 si_cstr_to_i64(cstring str) { SI_ASSERT_NOT_NULL(str); - i64 result = 0; + i64 result = 0; char cur; bool negative = false; @@ -2847,19 +2832,19 @@ i64 si_cstr_to_i64(cstring str) { } while ((cur = *str++)) { - if (cur >= '0' && cur <= '9') { - result = (result * 10) + (cur - '0'); - } + if (cur >= '0' && cur <= '9') { + result = (result * 10) + (cur - '0'); + } else { SI_ASSERT_MSG(!(cur >= '0' && cur <= '9'), "Attempted to use `si_cstr_to_u64` with a string that contains non numbers."); } - } + } if (negative) { result = -result; } - return result; + return result; } #endif @@ -2886,7 +2871,7 @@ isize si_path_copy(cstring existing_path, cstring new_path) { struct stat stat_existing; fstat(existing_fd, &stat_existing); - + #if defined(SI_SYSTEM_UNIX) isize size = sendfile(new_fd, existing_fd, 0, stat_existing.st_size); #else @@ -2970,10 +2955,10 @@ inline bool si_path_is_relative(cstring path) { inline siFile si_file_create(cstring path) { - return si_file_open_mode(path, "w"); + return si_file_open_mode(path, "w+"); } inline siFile si_file_open(cstring path) { - return si_file_open_mode(path, "r"); + return si_file_open_mode(path, "r+"); } siFile si_file_open_mode(cstring path, cstring mode) { SI_ASSERT_NOT_NULL(path); @@ -3020,7 +3005,9 @@ inline siString si_file_read(siFile file) { char tmp[file.size]; fread(tmp, file.size, 1, file.ptr); - return si_string_make_len(tmp, file.size); + siString txt = si_string_make_len(tmp, file.size); + + return txt; } inline siString si_file_read_at(siFile file, usize offset) { si_file_seek(file, offset); @@ -3044,9 +3031,9 @@ inline siString si_file_read_at(siFile file, usize offset) { about it for sure. */ siArray(siString) si_file_readlines(siFile file) { - siString buffer = si_file_read(file); + siString buffer = si_file_read_at(file, 0); siArray(siString) res = si_string_split(buffer, "\n"); - si_string_free(buffer); + //si_string_free(buffer); return res; } @@ -3075,17 +3062,17 @@ isize si_file_write_at_line(siFile* file, cstring content, usize index) { SI_ASSERT_NOT_NULL(file->ptr); siArray(siString) buffer = si_file_readlines(*file); - siString previous_line = buffer[index]; + //siString previous_line = buffer[index]; SI_ASSERT_MSG(index < si_array_len(buffer), "Index is either not 0 or higher than the amount of lines in the file."); buffer[index] = (siString)content; siString new_file_content = si_array_to_sistring(buffer, "\n"); - siFile new_file = si_file_open_mode(file->path, "w"); + siFile new_file = si_file_create(file->path); si_file_write_len(&new_file, new_file_content, si_string_len(new_file_content)); - usize i; + /*usize i; for (i = 0; i < si_array_len(buffer); i++) { if (i == index) { continue; @@ -3096,7 +3083,7 @@ isize si_file_write_at_line(siFile* file, cstring content, usize index) { si_array_free(buffer); si_string_free(new_file_content); - si_file_close(*file); + si_file_close(*file);*/ *file = new_file; return SI_OKAY; @@ -3113,7 +3100,7 @@ inline isize si_file_seek_to_end(siFile file) { isize si_file_close(siFile file) { if (file.path != nil) { - si_string_free(file.path); + // si_string_free(file.path); } if (file.ptr != nil) { @@ -3238,7 +3225,7 @@ void si_thread_set_priority(siThread t, i32 priority) { } SI_ASSERT_MSG(error_code == SI_OKAY, error_msg); #else - SI_PANIC_MSG("si_thread_set_priority: Not supported on MacOS."); + SI_PANIC_MSG("si_thread_set_priority: Not supported on MacOS."); SI_UNUSED(t); SI_UNUSED(priority); #endif From e97890fd2e4db7564bba707a15d6856617d448f6 Mon Sep 17 00:00:00 2001 From: EimaMei Date: Fri, 23 Jun 2023 20:13:33 +0300 Subject: [PATCH 13/17] a bunch of bug fixes --- examples/array.c | 19 +- examples/benchmarking.c | 2 +- examples/file.c | 4 +- examples/optional.c | 19 +- examples/str.c | 22 +- examples/thread.c | 12 +- sili.h | 499 ++++++++++++++++++++++------------------ 7 files changed, 322 insertions(+), 255 deletions(-) diff --git a/examples/array.c b/examples/array.c index c4ef302..607a706 100644 --- a/examples/array.c +++ b/examples/array.c @@ -7,8 +7,9 @@ void example_2_0(void) { siArray(i32) array = si_array_make((i32[]){3, 234, 2, 4, 294, 234, 23}); - for_range (i, {0, si_array_len(array)}) { - printf("Element %zd: %i\n", i, array[i]); + puts("All of the elements in 'array':"); + for_range (i, 0, si_array_len(array)) { + printf("\tElement %zd: %i\n", i, array[i]); } isize find_pos = si_array_find(array, 234); @@ -16,17 +17,17 @@ void example_2_0(void) { printf("The 1st number '234' is at 'array[%zd]', while the 2nd one is at 'array[%zd]'\n", find_pos, rfind_pos); usize previous_len = si_array_len(array); - si_array_append(&array, SI_INT32_MAX); /* si_array_push_back does the same thing. */ + si_array_append(&array, INT32_MAX); /* si_array_push_back does the same thing. */ - i32 front = si_any_get(si_array_front(array), i32); - i32 back = si_any_get(si_array_back(array), i32); + i32 front = si_any_get(i32, si_array_front(array)); + i32 back = si_any_get(i32, si_array_back(array)); printf("We now have %zd elements instead of %zd. The front value is '%i', while the back value is '0x%X'\n", si_array_len(array), previous_len, front, back); - si_array_replace(&array, 4, SI_INT32_MIN); + si_array_replace(&array, 4, INT32_MIN); printf("The element at position '%d' was replaced with: -'-0x%X'\n", 3, array[3]); siArray(i32) copy = si_array_copy(array); - bool res = si_arrays_are_equal(array, copy); + bool res = si_array_equal(array, copy); printf("Arrays 'array' and 'copy' are %s\n", (res ? "the same" : "NOT the same")); } @@ -47,8 +48,8 @@ void example_2_1(void) { si_array_reverse(&array); printf("Array in reverse order: "); - foreach (num, array) { - printf("%i ", *num); + for_range (num, 0, si_array_len(array)) { + printf("%i ", array[num]); } printf("\n"); } diff --git a/examples/benchmarking.c b/examples/benchmarking.c index 90afa01..c594b30 100644 --- a/examples/benchmarking.c +++ b/examples/benchmarking.c @@ -4,7 +4,7 @@ void performance_test(void) { isize i; - for (i = 0; i < SI_UINT16_MAX; i++); /* NOTE(EimaMei): Should strain the CPU a little. */ + for (i = 0; i < UINT16_MAX; i++); /* NOTE(EimaMei): Should strain the CPU just a little. */ } diff --git a/examples/file.c b/examples/file.c index 01a910d..37c559a 100644 --- a/examples/file.c +++ b/examples/file.c @@ -18,7 +18,7 @@ void example_4_0(void) { siArray(siString) file_lines = si_file_readlines(file); printf("Contents of '%s' ('%zd' lines in total):\n", si_path_base_name(file.path), si_array_len(file_lines)); - for_range (i, {0, si_array_len(file_lines)}) { + for_range (i, 0, si_array_len(file_lines)) { si_string_strip(&file_lines[i]); printf("\tLine %zd: '%s'\n", i, file_lines[i]); } @@ -27,7 +27,7 @@ void example_4_0(void) { siArray(siString) new_file_lines = si_file_readlines(new_file); printf("Contents of '%s' ('%zd' lines in total):\n", si_path_base_name(new_file.path), si_array_len(new_file_lines)); - for_range (i, {0, si_array_len(new_file_lines)}) { + for_range (i, 0, si_array_len(new_file_lines)) { si_string_strip(&new_file_lines[i]); printf("\tLine %zd: '%s'\n", i, new_file_lines[i]); } diff --git a/examples/optional.c b/examples/optional.c index 0029d80..980aabc 100644 --- a/examples/optional.c +++ b/examples/optional.c @@ -2,19 +2,22 @@ #include -siOptional(char*) create(bool value) { - return (value ? si_optional_make((char*)"Godzilla") : SI_OPTIONAL_NULL); +siOptional(cstring) create(bool value) { + return (value ? si_optional_make("Godzilla") : SI_OPTIONAL_NULL); } int main(void) { - /* Example 5.0: siOptional (based on https://en.cppreference.com/w/cpp/utility/optional). */ - printf("==============\n\n==============\nExample 5.0:\n"); + /* Example 5.0: siOptional (based on https://en.cppreference.com/w/cpp/utility/optional). */ + printf("==============\n\n==============\nExample 5.0:\n"); - printf("create(false) returned '%s'\n", si_optional_get_or_default(char*, create(false), "empty")); + printf("create(false) returned '%s'\n", si_optional_get_or_default(cstring, create(false), "empty")); - siOptional(char*) str = create(true); - printf("create2(true) returned '%s'\n", si_any_get(str.value, char*)); + siOptional(cstring) str = create(true); + printf("create2(true) returned '%s'\n", si_optional_get(cstring, str)); - return 0; + si_optional_reset(str); + printf("str.has_value: %zd\n", str.has_value); + + return 0; } diff --git a/examples/str.c b/examples/str.c index 4d66675..b19c54a 100644 --- a/examples/str.c +++ b/examples/str.c @@ -6,10 +6,10 @@ void example_1_0(void) { printf("==============\nExample 1.0:\n"); siString str = si_string_make("Labas, Pasauli!"); - printf("str: %s\n", str); + printf("str: \"%s\"\n", str); si_string_append(&str, " Lithuanian, more like Russian amirite."); - printf("str: %s\n", str); + printf("str: \"%s\"\n", str); char front = si_string_front(str); char back = si_string_back(str); @@ -17,10 +17,10 @@ void example_1_0(void) { printf("front: '%c', back: '%c', len: '%zd'\n", front, back, length); si_string_set(&str, "Different sentence"); - printf("str: %s\n", str); + printf("str: \"%s\"\n", str); si_string_push(&str, '.'); - printf("str: %s\n", str); + printf("str: \"%s\"\n", str); siString str2 = si_string_copy(str); bool result = si_cstr_equal(str, str2); @@ -33,25 +33,25 @@ void example_1_0(void) { printf("However, the word 'random' was not found, thus 'pos' equals to %zd\n", pos); si_string_replace(&str, "Different", "Completely new"); - printf("str: %s\n", str); + printf("str: \"%s\"\n", str); si_string_replace(&str2, "Different", "The same"); - printf("str2: %s\n", str2); + printf("str2: \"%s\"\n", str2); si_string_trim(&str, "sentence."); - printf("str: %s\n", str); + printf("str: \"%s\"\n", str); si_string_clear(&str); - printf("Length of str: %zd\n", si_string_len(str)); + printf("Length of str: '%zd'\n", si_string_len(str)); si_string_set(&str2, "one.two.three.four.five"); - printf("Current str2: %s\n", str2); + printf("Current str2:\" %s\"\n", str2); siArray(siString) list = si_string_split(str2, "."); - for_range (i, {0, si_array_len(list)}) { - printf("\tElement %zd: '%s'\n", i, list[i]); + for_range (i, 0, si_array_len(list)) { + printf("\tElement %zd: \"%s\"\n", i, list[i]); } } diff --git a/examples/thread.c b/examples/thread.c index 0d29564..c348b27 100644 --- a/examples/thread.c +++ b/examples/thread.c @@ -4,12 +4,12 @@ rawptr thread_test(bool* arg) { bool loop = *arg; - i16 count = SI_INT16_MIN; + i16 count = INT16_MIN; if (loop) { - printf("We'll increment 'count' from %d to %d:\n", SI_INT16_MIN, SI_INT16_MAX); + printf("We'll increment 'count' from %d to %d:\n", INT16_MIN, INT16_MAX); si_sleep(2000); - while (count < SI_INT16_MAX) { + while (count < INT16_MAX) { count += 1; printf("%i\n", count); } @@ -46,15 +46,15 @@ int main(void) { si_thread_start(&thread); si_thread_join(&thread); /* Now we have to wait... */ - printf("That loop NOW returned a '%i'.\n", *((i16*)thread.return_value)); + printf("That loop NOW returned a '%i'.\n", *si_cast(i16*, thread.return_value)); si_sleep(2000); - #if !defined(SI_SYSTEM_WINDOWS) + #if !defined(SI_SYSTEM_WINDOWS) /* si_thread_cancel is not supported on windows. */ si_thread_start(&thread); si_sleep(2500); si_thread_cancel(&thread); - printf("Decided to kill it 2.5 seconds later.\n"); + puts("Decided to kill it 2.5 seconds later."); #endif si_terminate(); diff --git a/sili.h b/sili.h index b55152e..7ccc2e6 100644 --- a/sili.h +++ b/sili.h @@ -81,10 +81,10 @@ extern "C" { #if defined(_MSC_VER) #define SI_COMPILER_MSVC 1 +#elif defined(__clang__) + #define SI_COMPILER_CLANG 1 #elif defined(__GNUC__) #define SI_COMPILER_GCC 1 -#elif defined(__clang__) - #define SI_COMPILER_CLANG 1 #else #error Unknown compiler #endif @@ -102,39 +102,28 @@ extern "C" { #if defined(__STDC__) - #if defined(__STDC_VERSION__) - #define SI_STANDARD_VERSION __STDC_VERSION__ - #if (SI_STANDARD_VERSION == 199409L) - #define SI_STANDARD_C94 1 - #elif (SI_STANDARD_VERSION == 199901L) - #define SI_STANDARD_C99 1 - #elif (SI_STANDARD_VERSION == 201112L) - #define SI_STANDARD_C11 1 - #elif (SI_STANDARD_VERSION == 201710L) - #define SI_STANDARD_C17 1 - #define SI_STANDARD_C18 1 - #elif (SI_STANDARD_VERSION > 201710L) - #define SI_STANDARD_C23 1 - #endif + #if !defined(SI_LANGUAGE_CPP) + #if defined(__STDC_VERSION__) + #define SI_STANDARD_VERSION __STDC_VERSION__ + #else + #define SI_STANDARD_VERSION 198900L + #endif + + #define SI_STANDARD_C89 198900L + #define SI_STANDARD_C94 199409L + #define SI_STANDARD_C99 199901l + #define SI_STANDARD_C11 201112L + #define SI_STANDARD_C17 201710L + #define SI_STANDARD_C23 202300L #else - #if !defined(__cplusplus) - #define SI_STANDARD_C89 1 - #else - #define SI_STANDARD_VERSION __cplusplus - #if (SI_STANDARD_VERSION == 199711L) - #define SI_STANDARD_CPP98 1 - #elif (SI_STANDARD_VERSION == 201103L) - #define SI_STANDARD_CPP11 1 - #elif (SI_STANDARD_VERSION == 201402L) - #define SI_STANDARD_CPP14 1 - #elif (SI_STANDARD_VERSION == 201703L) - #define SI_STANDARD_CPP17 1 - #elif (SI_STANDARD_VERSION == 202002L) - #define SI_STANDARD_CPP20 1 - #elif (SI_STANDARD_VERSION > 202002L) - #define SI_STANDARD_CPP23 1 - #endif - #endif + #define SI_STANDARD_VERSION __cplusplus + + #define SI_STANDARD_CPP98 199711L + #define SI_STANDARD_CPP11 201103L + #define SI_STANDARD_CPP14 201402L + #define SI_STANDARD_CPP17 201703L + #define SI_STANDARD_CPP20 202002L + #define SI_STANDARD_CPP23 202311L #endif #endif @@ -178,9 +167,12 @@ extern "C" { #if !defined(_GNU_SOURCE) #define _GNU_SOURCE #endif - #define _LARGEFILE64_SOURCE + #if !defined(_LARGEFILE64_SOURCE) + #define _LARGEFILE64_SOURCE + #endif #endif + #if !defined(SI_SYSTEM_WINDOWS) #include #include @@ -226,58 +218,54 @@ extern "C" { #endif #if !defined(u8) - typedef unsigned char u8; - typedef char i8; - typedef unsigned short u16; - typedef short i16; - typedef unsigned int u32; - typedef int i32; - typedef unsigned long long u64; - typedef long long i64; + #include + + typedef uint8_t u8; + typedef int8_t i8; + typedef uint16_t u16; + typedef int16_t i16; + typedef uint32_t u32; + typedef int32_t i32; + typedef uint64_t u64; + typedef int64_t i64; + + typedef i8 s8; + typedef i16 s16; + typedef i32 s32; + typedef i64 s64; + + #if defined(__SIZEOF_INT128__) && (!defined(SI_STANDARD_ANSI) || defined(SI_COMPILER_MSVC)) + typedef unsigned __int128 u128; /* NOTE(EimaMei): Would not recommend using this type, not portable and rarely warrants the use of it. */ + typedef __int128 i128; + typedef i128 s128; + + SI_STATIC_ASSERT(sizeof(u128) == sizeof(i128)); + SI_STATIC_ASSERT(sizeof(u128) == 16); + #endif #endif #if !defined(usize) - typedef size_t usize; - typedef ptrdiff_t isize; + typedef size_t usize; /* NOTE(EimaMei): Use this as the default int type! */ + typedef ptrdiff_t isize; #endif #if !defined(uintptr) - typedef usize uintptr; + typedef usize uintptr; typedef isize intptr; #endif typedef u8 siByte; -#define SI_UINT8_MAX 0xFF -#define SI_UINT8_MIN 0x00 -#define SI_INT8_MAX 0x7F -#define SI_INT8_MIN -0x80 - -#define SI_UINT16_MAX 0xFFFF -#define SI_UINT16_MIN 0x0000 -#define SI_INT16_MAX 0x7FFF -#define SI_INT16_MIN -0x8000 - -#define SI_UINT32_MAX 0xFFFFFFFF -#define SI_UINT32_MIN 0x00000000 -#define SI_INT32_MAX 0x7FFFFFFF -#define SI_INT32_MIN -0x80000000 - -#define SI_UINT64_MAX 0xFFFFFFFFFFFFFFFF -#define SI_UINT64_MIN 0x0000000000000000 -#define SI_INT64_MAX 0x7FFFFFFFFFFFFFFF -#define SI_INT64_MIN -0x8000000000000000 - #if defined(SI_ARCH_64_BIT) - #define SI_USIZE_MAX 0xFFFFFFFFFFFFFFFF - #define SI_USIZE_MIN 0x0000000000000000 - #define SI_ISIZE_MAX 0x7FFFFFFFFFFFFFFF - #define SI_ISIZE_MIN -0x8000000000000000 + #define USIZE_MAX UINT64_MAX + #define USIZE_MIN UINT64_MIN + #define ISIZE_MAX INT64_MAX + #define ISIZE_MIN INT64_MIN #else - #define SI_USIZE_MAX 0xFFFFFFFF - #define SI_USIZE_MIN 0x00000000 - #define SI_ISIZE_MAX 0x7FFFFFFF - #define SI_ISIZE_MIN -0x80000000 + #define USIZE_MAX UINT32_MAX + #define USIZE_MIN UINT64_MIN + #define ISIZE_MAX UINT32_MAX + #define ISIZE_MIN UINT32_MIN #endif @@ -285,13 +273,13 @@ SI_STATIC_ASSERT(sizeof(u8) == sizeof(i8)); SI_STATIC_ASSERT(sizeof(u16) == sizeof(i16)); SI_STATIC_ASSERT(sizeof(u32) == sizeof(i32)); SI_STATIC_ASSERT(sizeof(u64) == sizeof(i64)); +SI_STATIC_ASSERT(sizeof(usize) == sizeof(isize)); SI_STATIC_ASSERT(sizeof(u8) == 1); SI_STATIC_ASSERT(sizeof(u16) == 2); SI_STATIC_ASSERT(sizeof(u32) == 4); SI_STATIC_ASSERT(sizeof(u64) == 8); - -SI_STATIC_ASSERT(sizeof(usize) == sizeof(isize)); +SI_STATIC_ASSERT(sizeof(usize) == sizeof(size_t)); typedef float f32; @@ -307,29 +295,39 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); #define SI_F64_MAX 1.7976931348623157e+308 -#if !defined(bool) - typedef u8 b8; - typedef u16 b16; - typedef u32 b32; - typedef u64 b64; +#if !defined(b8) + typedef u8 b8; /* NOTE(EimaMei): Don't use this. Please. :D */ + typedef u16 b16; + typedef u32 b32; + typedef u64 b64; +#endif - #ifndef __cplusplus - typedef usize bool; +#if !defined(SI_LANGUAGE_CPP) && SI_STANDARD_VERSION <= SI_STANDARD_C17 + #undef bool + typedef usize bool; - #ifndef true - #define true 1 - #endif - #ifndef false - #define false 0 - #endif - #endif + #if !defined(true) + #define true 1 + #endif + #ifndef false + #define false 0 + #endif +#else + #define bool usize #endif -#if !defined(nil) - #define nil NULL -#endif -#if !defined(__cplusplus) +SI_STATIC_ASSERT(sizeof(b8) == sizeof(u8)); +SI_STATIC_ASSERT(sizeof(b16) == sizeof(u16)); +SI_STATIC_ASSERT(sizeof(b32) == sizeof(u32)); +SI_STATIC_ASSERT(sizeof(b64) == sizeof(u64)); +SI_STATIC_ASSERT(sizeof(bool) == sizeof(usize)); /* NOTE(EimaMei): Make it consistent for all our sake. */ + +SI_STATIC_ASSERT(true == 1); +SI_STATIC_ASSERT(false == 0); + + +#if !defined(SI_LANGUAGE_CPP) #if defined(_MSC_VER) && _MSC_VER <= 1800 #define inline __inline #elif !defined(__STDC_VERSION__) @@ -339,7 +337,19 @@ SI_STATIC_ASSERT(sizeof(f64) == 8); #endif #endif -SI_STATIC_ASSERT(sizeof(uintptr) == sizeof(intptr)); + +#if (defined(SI_LANGUAGE_CPP) && (SI_STANDARD_VERSION >= SI_STANDARD_CPP17)) || (!defined (SI_LANGUAGE_CPP) && SI_STANDARD_VERSION > SI_STANDARD_C17) + #define fallthrough [[fallthrough]] +#elif defined(SI_STANDARD_ANSI) || defined(SI_COMPILER_MSVC) + #define fallthrough do {} while (0) /* NOTE(EimaMei): This does nothing, it's just syntax sugar. */ +#else + #define fallthrough __attribute__((fallthrough)) /* NOTE(EimaMei): Properly notifies the compiler that this IS a fallthrough. */ +#endif + + +#if defined(SI_LANGUAGE_C) && (!defined(SI_STANDARD_ANSI) && !defined(SI_COMPILER_MSVC)) + #define auto __auto_type /* NOTE(EimaMei): Wouldn't recommend to use (not portable and generally unclear). */ +#endif #if !defined(rawptr) @@ -367,6 +377,12 @@ SI_STATIC_ASSERT(sizeof(uintptr) == sizeof(intptr)); #define SI_BUILTIN_UNREACHABLE() __builtin_unreachable() +#if !defined(nil) + #define nil NULL +#endif + +SI_STATIC_ASSERT(sizeof(nil) == sizeof(NULL)); + /* ======================== | Declaration macros | @@ -391,45 +407,49 @@ SI_STATIC_ASSERT(sizeof(uintptr) == sizeof(intptr)); ======================== */ #define si_cast(type, value) ((type)((value))) -#define si_transmute(type, value) *((type*)&(value)) +#define si_transmute(type, value) ((union { typeof(value) in; type out; }){value}.out) /* ======================== | Unary operators | ======================== */ -#if !defined(typeof) +#if !defined(typeof) && SI_STANDARD_VERSION <= SI_STANDARD_C17 #define typeof(value) __typeof__(value) #endif #if !defined(countof) - #define countof(array) (sizeof(array) / sizeof(*(array))) + #define countof(value) ((f64)sizeof(value) / sizeof(*(value))) #endif #if !defined(offsetof) #define offsetof(type, element) ((isize)&(((type*)nil)->element)) #endif -#if !defined(alignof) +#if !defined(alignof) || (defined(SI_LANGUAGE_CPP) && SI_STANDARD_VERSION < SI_STANDARD_CPP11) #define alignof(type) si_offsetof(struct { char c; type member; }, member) #endif /* ======================== - | Generally functions | + | General functions | ======================== */ + +#define likely(x) __builtin_expect(!!(x), true) +#define unlikely(x) __builtin_expect(!!(x), false) + #define si_swap(a, b) do { typeof((a)) tmp = (a); (a) = (b); (b) = tmp; } while (0) #define si_abs(x) ((x) < 0 ? -(x) : (x)) #define si_between(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper))) #define si_pause() do { printf("Press any key to continue...\n"); getchar(); } while(0) -#define for_range_2(count_var, struct_name, ...) \ - siVector2D struct_name = __VA_ARGS__; \ +#define for_range_2(count_var, struct_name, start, end) \ + siVector2D struct_name = {(isize)start, (isize)end}; \ for (isize count_var = struct_name.x; count_var < struct_name.y; count_var += 1) \ -#define for_range_1(count_var, line, ...) \ - for_range_2(count_var, SI_CAT(__si_impl_range_, line), __VA_ARGS__) +#define for_range_1(count_var, line, start, end) \ + for_range_2(count_var, SI_CAT(__si_impl_range_, line), start, end) -#define for_range(count_var, ...) \ - for_range_1(count_var, __LINE__, __VA_ARGS__) +#define for_range(count_var, start, end) \ + for_range_1(count_var, __LINE__, start, end) #if defined(SI_MEMORY_LOGGING) @@ -463,13 +483,14 @@ SI_STATIC_ASSERT(sizeof(uintptr) == sizeof(intptr)); | SI_ASSERT | ======================== */ -usize si_impl_assert_msg(bool condition, cstring condition_str, cstring file, i32 line, cstring message, ...); +usize si_impl_assert_msg(bool condition, cstring condition_str, cstring file, i32 line, cstring func, cstring message, ...); #define SI_ASSERT(condition) SI_ASSERT_MSG(condition, nil) -#define SI_ASSERT_MSG(condition, message) si_impl_assert_msg(condition, #condition, __FILE__, __LINE__, message, "") -#define SI_ASSERT_FMT(condition, message, ...) si_impl_assert_msg(condition, #condition, __FILE__, __LINE__, message, __VA_ARGS__) -#define SI_ASSERT_NOT_NULL(ptr) SI_ASSERT_MSG((ptr) != nil, #ptr " must not be NULL") -#define SI_PANIC() si_impl_assert_msg(false, "SI_PANIC()", __FILE__, __LINE__, message, "") +#define SI_ASSERT_MSG(condition, message) si_impl_assert_msg(condition, #condition, __FILE__, __LINE__, __func__, message, "") +#define SI_ASSERT_FMT(condition, message, ...) si_impl_assert_msg(condition, #condition, __FILE__, __LINE__, __func__, message, __VA_ARGS__) +#define SI_ASSERT_NOT_NULL(ptr) SI_ASSERT_MSG((ptr) != nil, #ptr " must not be NULL.") + +#define SI_PANIC() si_impl_assert_msg(false, "SI_PANIC()", __FILE__, __LINE__, nil, "") #define SI_PANIC_MSG(message) si_impl_assert_msg(false, "SI_PANIC(" message ")", __FILE__, __LINE__, message, "") @@ -483,8 +504,15 @@ typedef struct siAny { usize type_size; } siAny; -#define si_any_make(value) (siAny){&(typeof(value)){value}, sizeof(typeof(value))} -#define si_any_get(any, type) ((any.ptr != nil) ? *((type*)any.ptr) : (type)SI_ASSERT_NOT_NULL(any.ptr)) +#define si_any_make(...) \ + (siAny){ \ + __builtin_types_compatible_p(typeof(__VA_ARGS__), char[]) == true ? \ + (rawptr)&((struct { char* in; }){(char*)__VA_ARGS__}.in) : \ + (rawptr)&((struct { typeof(__VA_ARGS__) in; }){__VA_ARGS__}.in), \ + sizeof(typeof(__VA_ARGS__)) \ + } + +#define si_any_get(type, any) ((any.ptr != nil) ? *((type*)any.ptr) : (type)SI_ASSERT_NOT_NULL(any.ptr)) /* ======================== @@ -502,18 +530,14 @@ typedef struct siFunction { | Other | ======================== */ -typedef struct siIVector2D { - isize x; - isize y; -} siIVector2D; - -typedef struct siUVector2D { - usize x; - usize y; -} siUVector2D; - +typedef struct { isize x, y; } siIVector2D; +typedef struct { usize x, y; } siUVector2D; typedef siIVector2D siVector2D; +typedef struct { u8 r, g, b, a; } siColor; +#define SI_RGBA(r, g, b, a) (siColor){r, g, b, a} +#define SI_RGB(r, g, b) (siColor){r, g, b, 255} + typedef SI_ENUM(usize, siDirection) { SI_DIRECTION_LEFT, @@ -582,22 +606,25 @@ typedef struct siAllocator { usize index; } siAllocator; -siAllocator* SI_GLOBAL_ALLOC; +extern siAllocator* SI_GLOBAL_ALLOC; + +siAllocator* si_allocator_init(usize bytes); +void si_allocator_refill(siAllocator* alloc); +void si_allocator_free(siAllocator* alloc); -inline siAllocator* si_allocator_init(usize bytes); -inline void si_allocator_refill(siAllocator* alloc); -inline void si_allocator_free(siAllocator* alloc); +rawptr si_malloc(siAllocator* alloc, usize bytes); +rawptr si_calloc(siAllocator* alloc, usize num, usize bytes); +rawptr si_realloc(siAllocator* alloc, rawptr ptr, usize old_size, usize new_size); +void si_free(siAllocator* alloc, rawptr ptr); -inline rawptr si_malloc(siAllocator* alloc, usize bytes); -inline rawptr si_calloc(siAllocator* alloc, usize num, usize bytes); -inline rawptr si_realloc(siAllocator* alloc, rawptr ptr, usize old_size, usize new_size); #if !defined(SI_MEMORY_LOGGING) #define malloc(bytes) si_malloc(SI_GLOBAL_ALLOC, bytes) #define calloc(num, bytes) si_calloc(SI_GLOBAL_ALLOC, num, bytes) #define realloc(ptr, old_size, new_size) si_realloc(SI_GLOBAL_ALLOC, ptr, old_size, new_size) + #define free(ptr) si_free(SI_GLOBAL_ALLOC, ptr) #endif #endif @@ -658,10 +685,17 @@ typedef struct siOptionalStruct { #define siOptional(type) siOptionalStruct const siOptionalStruct SI_OPTIONAL_NULL = {{nil, 0}, false}; -#define si_optional_make(value) (siOptionalStruct){si_any_make(value), true} -#define si_optional_get(type, siOptional_var) si_any_get(siOptional_var.value, type) -#define si_optional_get_or_default(type, siOptional_var, default_value) (siOptional_var.has_value ? si_any_get(siOptional_var.value, type) : (type)default_value) -/* NOTE(EimaMei): If the `siOptional` variable is empty, it'll return the 'or_value'. The type of `or_value` must be the same as the type for the `siOptional` variable. */ +#define si_optional_make(...) (siOptionalStruct){si_any_make(__VA_ARGS__), true} +#define si_optional_reset(optional_var) \ + do { \ + siOptionalStruct si_new = SI_OPTIONAL_NULL;\ + si_new.value.type_size = optional_var.value.type_size; \ + \ + optional_var = si_new; \ + } while(0) +#define si_optional_get(type, optional_var) (*((type*)optional_var.value.ptr)) +#define si_optional_get_or_default(type, optional_var, default_value) \ + (optional_var.has_value ? si_optional_get(type, optional_var) : (type)(default_value)) #endif @@ -690,7 +724,7 @@ typedef struct siArrayHeader { u32 len; u32 capacity; u16 type_size; - u16 grow; + /* u16 grow; */ } siArrayHeader; #define siArray(type) type* @@ -705,7 +739,7 @@ typedef struct siArrayHeader { * @param array The siString to iterate over. */ #if !defined(foreach) - #if !defined(SI_STANDARD_C89) + #if defined(SI_LANGUAGE_C) && SI_STANDARD_VERSION > SI_STANDARD_C89 #define foreach(variable_name, array) for (typeof(array) variable_name = array; variable_name != (typeof(array))si_array_get_ptr(array, si_array_len(array)); variable_name += 1) #else #define foreach(variable_name, array) typeof(array) variable_name; for (variable_name = array; variable_name != (typeof(array))si_array_get_ptr(array, si_array_len(array)); variable_name += 1) @@ -732,17 +766,17 @@ siAny si_array_back(rawptr array); #define si_array_append(array_ptr, value) si_impl_array_append(array_ptr, si_any_make(value)) -#define si_array_find(array, value) si_impl_array_find(array, 0, si_array_len(array), si_any_make(value)) -#define si_array_find_ex(array, start, end, value) si_impl_array_find(array, start, end, si_any_make(value)) -#define si_array_rfind(array, value) si_impl_array_rfind(array, si_array_len(array) - 1, 0, si_any_make(value)) -#define si_array_rfind_ex(array, start, end, value) si_impl_array_rfind(array, start, end, si_any_make(value)) +#define si_array_find(array, ...) si_impl_array_find(array, 0, si_array_len(array), si_any_make(__VA_ARGS__)) +#define si_array_find_ex(array, start, end, ...) si_impl_array_find(array, start, end, si_any_make(__VA_ARGS__)) +#define si_array_rfind(array, ...) si_impl_array_rfind(array, si_array_len(array) - 1, 0, si_any_make(__VA_ARGS__)) +#define si_array_rfind_ex(array, start, end, ...) si_impl_array_rfind(array, start, end, si_any_make(__VA_ARGS__)) -#define si_array_replace(array_ptr, old_value, new_value) si_impl_array_replace(array, si_any_make(old_value), si_any_make(new_value)) +#define si_array_replace(array_ptr, old_value, ...) si_impl_array_replace(array, si_any_make(old_value), si_any_make(__VA_ARGS__)) void si_array_reverse(rawptr array_ptr); char* si_array_to_sistring(siArray(char*) array, cstring separator); void si_array_clear(rawptr array_ptr); -bool si_arrays_are_equal(rawptr lha, rawptr rha); +bool si_array_equal(rawptr lha, rawptr rha); isize si_array_free(rawptr array); @@ -775,8 +809,8 @@ void si_impl_array_replace(rawptr array_ptr, siAny old_value, siAny new_value); ======================== */ typedef struct siBufferHeader { - usize len; - u32 type_size; + u32 len; + u16 type_size; } siBufferHeader; #define SI_BUFFER_HEADER(buffer) (&(siBufferHeader){si_buffer_len(buffer), si_buffer_type_width(buffer)}) @@ -865,8 +899,8 @@ typedef siArray(char) siString; typedef struct siStringHeader { u32 len; u32 capacity; - u8 type_size; - u8 grow; + /* u8 type_size; + u8 grow; */ } siStringHeader; @@ -874,7 +908,7 @@ typedef struct siStringHeader { * @def SI_STRING_HEADER(str) * @brief Macro to get the header of a siString. * @param str The siString. - * @return The header pointer of the siString (siDebugHeader*). + * @return The header pointer of the siString (siStringHeader*). */ #define SI_STRING_HEADER(str) ((siStringHeader*)str - 1) #define SI_STRING_DEFAULT_GROW 128 @@ -1425,7 +1459,7 @@ typedef SI_ENUM(usize, siMonth) { siDecember }; -/* NOTE(EimaMi): For whatever reason some places uses Sunday as the first weekday, while MOST of Europe views monday as the first weekday. +/* NOTE(EimaMei): For whatever reason some places uses Sunday as the first weekday, while MOST of Europe views monday as the first weekday. So by default Monday will be set as the first weekday with the options to change it depending on your taste. */ typedef SI_ENUM(usize, siWeek) { #if defined(SI_TIME_FIRST_WEEKDAY_MONDAY) @@ -1465,7 +1499,9 @@ typedef SI_ENUM(usize, siWeek) { f64 si_time_now(void); -u64 si_time_utc_now(void) { +u64 si_time_utc_now(void); + +inline u64 si_time_utc_now(void) { time_t rawtime; time(&rawtime); @@ -1576,7 +1612,9 @@ void si_impl_performance_thread(u32* arg); printf("\t%zd run(s) - '%f' ms\n", si_median_index, si_exec_durations[si_array_index]); \ si_array_index += 1; \ } \ - printf("Final result:\n\tMedian - '%f' ms\n", si_buffer_sum_f64(si_exec_durations) / (f64)countof(si_exec_durations)); \ + printf("Final result:\n\tMedian - '%f' ms\n", \ + si_buffer_sum_f64(si_exec_durations) / countof(si_exec_durations) \ + ); \ SI_PERFORMANCE_PRINT_MEMORY(function); \ } while(0) #endif @@ -1684,13 +1722,13 @@ void si_debug_cleanup(void); #if defined(SI_GENERAL_IMPLEMENTATION) -usize si_impl_assert_msg(bool condition, cstring condition_str, cstring file, i32 line, cstring message, ...) { +usize si_impl_assert_msg(bool condition, cstring condition_str, cstring file, i32 line, cstring func, cstring message, ...) { if (condition) { return 0; } - fprintf(stderr, "Assertion \"%s\" at \"%s:%d\"%s", condition_str, file, line, (message != nil ? ": " : "")); + fprintf(stderr, "Assertion \"%s\" at \"%s:%d\": %s%s", condition_str, file, line, func, (message != nil ? ": " : "")); if (message != nil) { va_list va; @@ -1763,12 +1801,16 @@ void si_ptr_move_by(rawptr src, usize src_len, usize move_by, siDirection direct #undef malloc #undef calloc #undef realloc + #undef free #endif +siAllocator* SI_GLOBAL_ALLOC; + + inline siAllocator* si_allocator_init(usize bytes) { rawptr ptr = malloc(sizeof(siAllocator) + bytes); - siAllocator* res = (rawptr)ptr; + siAllocator* res = (siAllocator*)ptr; res->ptr = (siByte*)ptr + sizeof(siAllocator); res->index = 0; res->max_size = bytes; @@ -1776,10 +1818,11 @@ inline siAllocator* si_allocator_init(usize bytes) { return res; } inline void si_allocator_refill(siAllocator* alloc) { - SI_ASSERT_MSG(alloc->ptr == nil, "Specified allocator hasn't been freed once, cannot refill."); + SI_ASSERT_MSG(alloc->ptr == nil, "Specified allocator hasn't been freed, cannot refill."); *alloc = *si_allocator_init(alloc->max_size); } inline void si_allocator_free(siAllocator* alloc) { + SI_ASSERT_NOT_NULL(alloc->ptr); free(alloc->ptr - sizeof(siAllocator)); } @@ -1804,19 +1847,26 @@ inline rawptr si_calloc(siAllocator* alloc, usize num, usize bytes) { inline void si_free(siAllocator* alloc, rawptr ptr) { SI_ASSERT_NOT_NULL(alloc); SI_ASSERT_NOT_NULL(ptr); - SI_ASSERT(si_between((siByte*)ptr, alloc->ptr, alloc->ptr + alloc->max_size)); + SI_ASSERT_FMT( + si_between((siByte*)ptr, alloc->ptr, alloc->ptr + alloc->max_size), + "Provided pointer wasn't allocated through the provided allocator (ptr is '%p', which isn't between '%p' and '%p')", + ptr, alloc->ptr, alloc->ptr + alloc->max_size + ); alloc->index = (siByte*)ptr - alloc->ptr; } -inline rawptr si_realloc(siAllocator* alloc, rawptr ptr, usize new_size, usize old_size) { - SI_ASSERT_NOT_NULL(alloc); +rawptr si_realloc(siAllocator* alloc, rawptr ptr, usize old_size, usize new_size) { + SI_ASSERT_NOT_NULL(alloc); - if (ptr == nil) { + if (ptr == NULL) { return si_malloc(alloc, new_size); } - SI_ASSERT(si_between((siByte*)ptr, alloc->ptr, alloc->ptr + alloc->max_size)); - isize copy_size = (new_size < old_size) ? new_size : old_size; + SI_ASSERT_FMT( + si_between((siByte*)ptr, alloc->ptr, alloc->ptr + alloc->max_size), + "Provided pointer wasn't allocated through the provided allocator (ptr is '%p', which isn't between '%p' and '%p')", + ptr, alloc->ptr, alloc->ptr + alloc->max_size + ); if (new_size == 0) { si_free(alloc, ptr); @@ -1825,16 +1875,18 @@ inline rawptr si_realloc(siAllocator* alloc, rawptr ptr, usize new_size, usize o isize size_diff = new_size - old_size; - if (size_diff > 0) { + if (size_diff < 0) { rawptr new_ptr = si_malloc(alloc, new_size); - memcpy(new_ptr, ptr, copy_size); + memmove(new_ptr, ptr, new_size); si_free(alloc, ptr); return new_ptr; } + else if (size_diff > 0) { + usize old_index = (siByte*)ptr - alloc->ptr; + alloc->index = old_index + new_size; + } - usize old_index = (siByte*)ptr - alloc->ptr + copy_size; - alloc->index = old_index + copy_size; return ptr; } @@ -1843,6 +1895,7 @@ inline rawptr si_realloc(siAllocator* alloc, rawptr ptr, usize new_size, usize o #define malloc(bytes) si_malloc(SI_GLOBAL_ALLOC, bytes) #define calloc(num, bytes) si_calloc(SI_GLOBAL_ALLOC, num, bytes) #define realloc(ptr, old_size, new_size) si_realloc(SI_GLOBAL_ALLOC, ptr, old_size, new_size) + #define free(ptr) si_free(SI_GLOBAL_ALLOC, ptr) #endif #endif @@ -1874,8 +1927,12 @@ inline rawptr si_array_copy(rawptr array) { return si_array_make_list(array, header->type_size, header->len); } rawptr si_array_make_reserve(usize sizeof_element, usize count) { - siByte* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count)); - rawptr array = ptr + sizeof(siArrayHeader); + if (count == 0) { + count = 1; + } + + rawptr ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count)); + rawptr array = (siByte*)ptr + sizeof(siArrayHeader); siArrayHeader* header = (siArrayHeader*)ptr; header->len = 0; @@ -1900,22 +1957,33 @@ inline usize si_array_total_size(rawptr array) { inline siAny si_array_at(rawptr array, usize index) { if (index >= si_array_len(array)) { - return (siAny){nil, 0}; + siAny res = {nil, 0}; + return res; } - rawptr p = si_array_get_ptr(array, index); - return (siAny){p, si_array_type_size(array)}; + siAny res = { + si_array_get_ptr(array, index), + si_array_type_size(array) + }; + return res; } inline siAny si_array_front(rawptr array) { SI_ASSERT_MSG(si_array_len(array) != 0, "Array is empty."); - return (siAny){array, si_array_type_size(array)}; + siAny res = { + array, + si_array_type_size(array) + }; + return res; } inline siAny si_array_back(rawptr array) { SI_ASSERT_MSG(si_array_len(array) != 0, "Array is empty."); - rawptr p = (siByte*)array + (si_array_len(array) - 1) * si_array_type_size(array); - return (siAny){p, si_array_type_size(array)}; + siAny res = { + si_array_get_ptr(array, si_array_len(array) -1), + si_array_type_size(array) + }; + return res; } isize si_impl_array_find(rawptr array, usize start, usize end, siAny value) { @@ -1997,8 +2065,8 @@ siString si_array_to_sistring(siArray(char*) array, cstring separator) { usize separator_len = si_cstr_len(separator); usize total_size = 0; - foreach (str, array) { - total_size += si_cstr_len(*str) + separator_len; + for_range (i, 0, si_array_len(array)) { + total_size += si_cstr_len(array[i]) + separator_len; } siString result = si_string_make_reserve(total_size); @@ -2023,14 +2091,10 @@ void si_impl_array_append(rawptr array_ptr, siAny value) { SI_ASSERT_MSG(value.type_size <= header->type_size, "The given value's sizeof is too large compared to the elements' in the arra"); if (header->len == header->capacity) { - if (header->capacity == 0) { - header->capacity = 1; - } - - siByte* result = realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_size, sizeof(siArrayHeader) + 2 * header->capacity * header->type_size); + rawptr result = realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_size, sizeof(siArrayHeader) + 2 * header->capacity * header->type_size); SI_ASSERT_NOT_NULL(result); - array = result + sizeof(siArrayHeader); + array = (siByte*)result + sizeof(siArrayHeader); *si_cast(siByte**, array_ptr) = array; header = (siArrayHeader*)result; @@ -2048,7 +2112,7 @@ void si_array_clear(rawptr array_ptr) { memset(array, 0, si_array_total_size(array)); } -bool si_arrays_are_equal(rawptr lha, rawptr rha) { +bool si_array_equal(rawptr lha, rawptr rha) { siArrayHeader* lha_header = SI_ARRAY_HEADER(lha); siArrayHeader* rha_header = SI_ARRAY_HEADER(rha); @@ -2085,7 +2149,12 @@ inline siOptional(rawptr) si_impl_buffer_at(rawptr buffer, siBufferHeader* heade if (index >= header->len) { return SI_OPTIONAL_NULL; } - return (siOptionalStruct){(siAny){si_buffer_get_ptr(buffer, header->type_size, index), header->type_size}, true}; + siOptional(rawptr) res = { + {si_buffer_get_ptr(buffer, header->type_size, index), header->type_size}, + true + }; + + return res; } isize si_impl_buffer_find(rawptr buffer, siBufferHeader* header, usize start, usize end, siAny value) { @@ -2158,7 +2227,7 @@ siString si_impl_buffer_to_sistring(rawptr buffer, siBufferHeader* header, cstri usize separator_len = si_cstr_len(separator); usize total_size = 0; - for_range (x, {0, header->len}) { + for_range (x, 0, header->len) { cstring cstr = *si_cast(char**, si_buffer_get_ptr(buffer, header->type_size, x)); total_size += si_cstr_len(cstr) + separator_len; } @@ -2166,7 +2235,7 @@ siString si_impl_buffer_to_sistring(rawptr buffer, siBufferHeader* header, cstri siString result = si_string_make_reserve(total_size); isize back_index = header->len - 1; - for_range (i, {0, header->len}) { + for_range (i, 0, header->len) { cstring cstr = *si_cast(char**, si_buffer_get_ptr(buffer, header->type_size, i)); if (separator != nil && i != back_index) { @@ -2231,7 +2300,6 @@ inline siString si_string_make(cstring str) { siString si_string_make_len(cstring str, usize len) { siString res_str = si_string_make_reserve(len); memcpy(res_str, str, len); - res_str[len] = '\0'; siStringHeader* header = SI_STRING_HEADER(res_str); header->len = len; @@ -2248,10 +2316,6 @@ siString si_string_make_fmt(cstring str, ...) { va_end(va); - if (size < SI_OKAY) { - return nil; - } - return si_string_make_len(buf, size); } siString si_string_make_reserve(usize len) { @@ -2264,7 +2328,7 @@ siString si_string_make_reserve(usize len) { siStringHeader* header = SI_STRING_HEADER(res_str); header->len = 0; header->capacity = len; - header->type_size = sizeof(char); + /*header->type_size = sizeof(char); */ return res_str; } @@ -2280,10 +2344,11 @@ inline usize si_string_capacity(siString str) { return SI_STRING_HEADER(str)->capacity; } inline usize si_string_type_size(siString str) { - return SI_STRING_HEADER(str)->type_size; + return sizeof(char); + SI_UNUSED(str); } inline bool si_string_empty(siString str) { - return (SI_STRING_HEADER(str)->len == 0); + return (str == nil || SI_STRING_HEADER(str)->len == 0); } @@ -2480,19 +2545,21 @@ inline void si_string_append(siString* str, cstring other) { si_string_append_len(str, other, si_cstr_len(other)); } void si_string_append_len(siString* str, cstring other, usize other_len) { - siStringHeader* header = SI_STRING_HEADER(*str); + SI_ASSERT_NOT_NULL(str); + siString cur_str = *str; + + siStringHeader* header = SI_STRING_HEADER(cur_str); usize previous_len = header->len; header->len += other_len; if (header->capacity < header->len) { - si_string_make_space_for(str, other_len); - header = SI_STRING_HEADER(*str); + si_string_make_space_for(str, other_len); + cur_str = *str; + header = SI_STRING_HEADER(cur_str); } - rawptr ptr = memcpy(*str + previous_len, other, other_len); - SI_ASSERT_NOT_NULL(ptr); - - (*str)[header->len] = '\0'; + memcpy(cur_str + previous_len, other, other_len); + cur_str[header->len] = '\0'; } inline void si_string_push(siString* str, char other) { si_string_append_len(str, &other, 1); @@ -2510,6 +2577,8 @@ void si_string_insert_ex(siString* str, cstring cstr, usize cstr_len, usize inde siStringHeader* header = SI_STRING_HEADER(*str); usize previous_len = header->len; usize before_index_len = previous_len - index; + + SI_ASSERT_FMT(index < previous_len, "Index is higher than the length of the string (str_len - '%zd', index - '%zd')", previous_len, index); header->len += cstr_len - erase_index; if (header->capacity < header->len) { @@ -2621,7 +2690,7 @@ void si_string_strip(siString* str) { } end += 1; } - char* stripped_str = cur_str + start * SI_STRING_HEADER(cur_str)->type_size; + char* stripped_str = cur_str + start * si_string_type_size(cur_str); stripped_str[si_string_len(cur_str) - start - end] = '\0'; si_string_set(str, stripped_str); @@ -2666,10 +2735,10 @@ siArray(siString) si_string_split(siString str, cstring separator) { begin_pos = pos + separator_len; } - siArray(siString) res = si_array_make_reserve(sizeof(*res), count); + siArray(siString) res = (typeof(res))si_array_make_reserve(sizeof(*res), count); SI_ARRAY_HEADER(res)->len = count; - for_range (i, {0, count}) { + for_range (i, 0, count) { res[i] = si_string_make_len(str, pos_buffer[i]); str += pos_buffer[i] + separator_len; } @@ -2689,24 +2758,21 @@ inline void si_string_free(siString str) { free(SI_STRING_HEADER(str)); } void si_string_make_space_for(siString* str, usize add_len) { - usize len = si_string_len(*str); - - rawptr ptr = SI_STRING_HEADER(*str); - usize old_size = sizeof(siStringHeader) + len + 1; + siStringHeader* header = SI_STRING_HEADER(*str); + usize old_size = sizeof(siStringHeader) + header->len + 1; usize new_size = old_size + add_len; - siStringHeader* new_ptr = realloc(ptr, old_size, new_size); - SI_ASSERT_NOT_NULL(new_ptr); + siStringHeader* new_header = (siStringHeader*)realloc(header, old_size, new_size); - *str = (char*)new_ptr + sizeof(siStringHeader); - new_ptr->capacity += add_len; + *str = (char*)new_header + sizeof(siStringHeader); + new_header->capacity += add_len; } void si_string_shrink_to_fit(siString* str) { SI_ASSERT_NOT_NULL(str); siString cur_str = *str; siStringHeader copy = *SI_STRING_HEADER(cur_str); - siStringHeader* header = realloc(SI_STRING_HEADER(cur_str), sizeof(siStringHeader*) + copy.capacity + 1, sizeof(siStringHeader*) + copy.len + 1); + siStringHeader* header = (typeof(header))realloc(SI_STRING_HEADER(cur_str), sizeof(siStringHeader*) + copy.capacity + 1, sizeof(siStringHeader*) + copy.len + 1); *header = copy; header->capacity = header->len; } @@ -2966,15 +3032,12 @@ siFile si_file_open_mode(cstring path, cstring mode) { FILE* f = fopen(path, mode); if (f == nil) { - siString message = nil; switch (errno) { - case ENOENT: message = "Failed to read the provided file, as it doesn't exist."; break; - case EACCES: message = "Failed to read the provided file, as I don't have suffice permissions to read the file."; break; - case EINVAL: message = "Failed to read the provided file, as an invalid argument was given."; break; - default: message = "Failed to read the provided file due to an unspecified reason."; break; + case ENOENT: SI_PANIC_MSG("Failed to read the provided file, as it doesn't exist."); break; + case EACCES: SI_PANIC_MSG("Failed to read the provided file, as I don't have suffice permissions to read the file."); break; + case EINVAL: SI_PANIC_MSG("Failed to read the provided file, as an invalid argument was given."); break; + default: SI_PANIC_MSG("Failed to read the provided file due to an unspecified reason."); } - - SI_ASSERT_MSG(f != nil, message); } siFile result = { From 47e82e83cebdf42022f0a34ec2e7c7971fb35726 Mon Sep 17 00:00:00 2001 From: EimaMei Date: Tue, 27 Jun 2023 18:59:35 +0300 Subject: [PATCH 14/17] bit functions --- sili.h | 244 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 210 insertions(+), 34 deletions(-) diff --git a/sili.h b/sili.h index 7ccc2e6..eb0a4f4 100644 --- a/sili.h +++ b/sili.h @@ -62,8 +62,10 @@ extern "C" { #define SI_ARCH_32_BIT 1 #endif -#define SI_ENDIAN_BIG (!*(u8*)&(u16){1}) -#define SI_ENDIAN_LITTLE (!SI_IS_BIG_ENDIAN) +#define SI_LITTLE_ENDIAN 0 +#define SI_BIG_ENDIAN 1 + +#define SI_TARGET_ENDIAN (!*(u8*)&(u16){1}) #if defined(_WIN32) || defined(_WIN64) #define SI_SYSTEM_WINDOWS 1 @@ -368,21 +370,52 @@ SI_STATIC_ASSERT(false == 0); #define SI_OKAY 0 #define SI_ERROR -1 -#define SI_BIT(x) (1 << (x)) +#define SI_BIT(x) (1ULL << (x)) +#define SI_NUM_GET_BIT(num, x) ((num & SI_BIT(x)) != 0) #define SI_KILO(x) ( (x) * (usize)1024) #define SI_MEGA(x) (SI_KILO(x) * (usize)1024) #define SI_GIGA(x) (SI_MEGA(x) * (usize)1024) #define SI_TERA(x) (SI_GIGA(x) * (usize)1024) -#define SI_BUILTIN_UNREACHABLE() __builtin_unreachable() - #if !defined(nil) #define nil NULL #endif SI_STATIC_ASSERT(sizeof(nil) == sizeof(NULL)); +/* + ======================== + | Builtin functions | + ======================== +*/ +#if !defined(__has_builtin) + #define __has_builtin(x) 0 +#endif + +#if __has_builtin(__builtin_unreachable) + #define SI_BUILTIN_UNREACHABLE() __builtin_unreachable() +#else + #define SI_BUILTSI_BUILTIN_UNREACHABLE() 0 +#endif + +#if __has_builtin(__builtin_types_compatible_p) + #define SI_BUILTIN_TYPES_CMP(type1, type2) __builtin_types_compatible_p(type1, type2) +#else + #define SI_BUILTIN_TYPES_CMP(type1, type2) 0 +#endif + +#if __has_builtin(__builtin_expect) + #define SI_BUILTIN_EXPECT(exp, c) __builtin_expect(exp, c) +#else + #define SI_BUILTINT_EXPECT(exp, c) (exp) +#endif + +#if __has_builtin(__builtin_constant_p) + #define SI_BUILTIN_CONSTANT(exp) __builtin_constant_p(exp) +#else + #define SI_BUILTIN_CONSTANT(exp) 0 +#endif /* ======================== | Declaration macros | @@ -418,7 +451,7 @@ SI_STATIC_ASSERT(sizeof(nil) == sizeof(NULL)); #define typeof(value) __typeof__(value) #endif #if !defined(countof) - #define countof(value) ((f64)sizeof(value) / sizeof(*(value))) + #define countof(value) si_cast(usize, (f64)sizeof(value) / sizeof(*(value))) #endif #if !defined(offsetof) #define offsetof(type, element) ((isize)&(((type*)nil)->element)) @@ -433,8 +466,8 @@ SI_STATIC_ASSERT(sizeof(nil) == sizeof(NULL)); ======================== */ -#define likely(x) __builtin_expect(!!(x), true) -#define unlikely(x) __builtin_expect(!!(x), false) +#define likely(x) SI_BUILTIN_EXPECT(!!(x), true) +#define unlikely(x) SI_BUILTIN_EXPECT(!!(x), false) #define si_swap(a, b) do { typeof((a)) tmp = (a); (a) = (b); (b) = tmp; } while (0) #define si_abs(x) ((x) < 0 ? -(x) : (x)) @@ -506,7 +539,7 @@ typedef struct siAny { #define si_any_make(...) \ (siAny){ \ - __builtin_types_compatible_p(typeof(__VA_ARGS__), char[]) == true ? \ + SI_BUILTIN_TYPES_CMP(typeof(__VA_ARGS__), char[]) == true ? \ (rawptr)&((struct { char* in; }){(char*)__VA_ARGS__}.in) : \ (rawptr)&((struct { typeof(__VA_ARGS__) in; }){__VA_ARGS__}.in), \ sizeof(typeof(__VA_ARGS__)) \ @@ -530,8 +563,8 @@ typedef struct siFunction { | Other | ======================== */ -typedef struct { isize x, y; } siIVector2D; -typedef struct { usize x, y; } siUVector2D; +typedef struct { i32 x, y; } siIVector2D; +typedef struct { u32 x, y; } siUVector2D; typedef siIVector2D siVector2D; typedef struct { u8 r, g, b, a; } siColor; @@ -1271,6 +1304,11 @@ i32 si_hex_digit_to_int(char c); | cstring | ======================== */ +char* si_cstr_make(cstring cstr); +char* si_cstr_make_len(cstring cstr, usize len); +char* si_cstr_make_static(cstring cstr); +char* si_cstr_make_static_len(cstring cstr, usize len); + usize si_cstr_len(cstring str); void si_cstr_upper(char* str); @@ -1509,6 +1547,147 @@ inline u64 si_time_utc_now(void) { } void si_sleep(usize miliseconds); +#endif + +#if !defined(SI_USIZE_BIT_UNDEFINE) +/* +* +* +* +* +* +* +* +* +* +* +* +* +* +* + ======================== + | usize/bit functions | + ======================== +*/ + +typedef SI_ENUM(usize, siBitType) { + SI_BIT_ZERO, + SI_BIT_ONE +}; + +#define si_num_count_bit(num, bit_type) si_num_count_bit_ex(num, sizeof(typeof(num)), bit_type) +#define si_num_leading_bit(num, bit_type) si_num_leading_bit_ex(num, sizeof(typeof(num)), bit_type) +#define si_num_trailing_bit(num, bit_type) si_num_trailing_bit_ex(num, sizeof(typeof(num)), bit_type) + +#define si_num_rotate_left(num, bits) si_num_rotate_left_ex(num, sizeof(typeof(num)), bits) +#define si_num_rotate_right(num, bits) si_num_rotate_right_ex(num, sizeof(typeof(num)), bits) +#define si_num_reverse_bits(num) si_num_reverse_bits_ex(num, sizeof(typeof(num))) + +#define si_num_change_endian(num) si_num_change_endian_ex(num, sizeof(typeof(num))) + +usize si_num_leading_bit_ex(usize num, usize sizeof_num, siBitType bit); +usize si_num_count_bit_ex(usize num, usize sizeof_num, siBitType bit); +usize si_num_trailing_bit_ex(usize num, usize number_sizeof, siBitType bit); + +usize si_num_rotate_left_ex(usize num, usize num_sizeof, usize bits); +usize si_num_rotate_right_ex(usize num, usize num_sizeof, usize n); +usize si_num_reverse_bits_ex(usize num, usize num_sizeof); + +usize si_num_change_endian_ex(usize num, usize num_sizeof); + +usize si_num_pow(isize base, isize exp); +usize si_num_pow2(isize base); + + +inline usize si_num_count_bit_ex(usize num, usize sizeof_num, siBitType bit) { + usize count = 0; + + for_range (i, 0, sizeof_num * 8) { + if (SI_NUM_GET_BIT(num, i) == bit) { + count += 1; + } + } + + return count; +} +inline usize si_num_leading_bit_ex(usize num, usize sizeof_num, siBitType bit) { + usize count = 0; + + usize i; + for (i = sizeof_num * 8 - 1; i < USIZE_MAX; i -= 1) { + if (SI_NUM_GET_BIT(num, i) == bit) { + count += 1; + } + else { + return count; + } + } + + return count; +} +inline usize si_num_trailing_bit_ex(usize num, usize sizeof_num, siBitType bit) { + usize count = 0; + + for_range (i, 0, sizeof_num * 8) { + if (SI_NUM_GET_BIT(num, i) == bit) { + count += 1; + } + else { + return count; + } + } + + return count; +} +inline usize si_num_rotate_left_ex(usize num, usize num_sizeof, usize bits) { + return (num << bits) | (num >> (num_sizeof * 8 - bits)); +} +inline usize si_num_rotate_right_ex(usize num, usize num_sizeof, usize bits) { + return (num >> bits) | (num << (num_sizeof * 8 - bits)); +} + +inline usize si_num_reverse_bits_ex(usize num, usize num_sizeof) { + usize res = 0LL; + + for_range(i, 0, num_sizeof * 8) { + res <<= 1; + res |= (num & 1); + num >>= 1; + } + + return res; +} + +inline usize si_num_change_endian_ex(usize num, usize num_sizeof) { + usize result = 0; + + for_range (i, 0, num_sizeof) { + result |= ((num >> (i * 8)) & 0xFF) << ((num_sizeof - 1 - i) * 8); + } + + return result; +} + +usize si_num_pow(isize base, isize exp) { + SI_ASSERT_MSG(exp > 0, "Currently not possible to do base powered by negative exp."); + + usize result = 1; + while (exp > 0) { + if (exp & 1) { + result *= base; + } + base *= base; + exp >>= 1; + } + + return result; +} + +inline usize si_num_pow2(isize base) { + return 1 << base; +} + + #endif #if !defined(SI_PERFORMANCE_UNDEFINE) @@ -1750,27 +1929,6 @@ usize si_impl_assert_msg(bool condition, cstring condition_str, cstring file, i3 #undef free #endif -rawptr si_realloc_cpy(rawptr ptr, usize old_size, usize new_size) { - if (ptr == nil) { - return malloc(new_size); - } - - if (old_size == new_size) { - return ptr; - } - else if (new_size < old_size) { - new_size = old_size; - } - - rawptr new_ptr = malloc(new_size); - SI_ASSERT_NOT_NULL(new_ptr); - - memcpy(new_ptr, ptr, old_size); - free(ptr); - - return new_ptr; -} - #if defined(SI_MEMORY_LOGGING) #define malloc(size) si_debug_alloc(1, nil, (siDebugArgs){size, 0}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) #define si_realloc(ptr, old_size, new_size) si_debug_alloc(4, ptr, (siDebugArgs){old_size, new_size}, __FILE__, __LINE__, __func__, si_u64_to_cstr(si_time_utc_now()), __DATE__) @@ -2351,6 +2509,24 @@ inline bool si_string_empty(siString str) { return (str == nil || SI_STRING_HEADER(str)->len == 0); } +inline char* si_cstr_make(cstring cstr) { + return si_cstr_make_len(cstr, si_cstr_len(cstr)); +} +inline char* si_cstr_make_len(cstring cstr, usize len) { + char* str = malloc(len + 1); + memcpy(str, cstr, len + 1); + + return str; +} +inline char* si_cstr_make_static(cstring cstr) { + return si_cstr_make_static_len(cstr, si_cstr_len(cstr)); +} +inline char* si_cstr_make_static_len(cstring cstr, usize len) { + char* str = alloca(len + 1); + memcpy(str, cstr, len + 1); + + return str; +} inline usize si_cstr_len(cstring str) { cstring s; @@ -3385,7 +3561,7 @@ rawptr si_debug_alloc(usize function_id, rawptr ptr, siDebugArgs args, cstring f return res + sizeof(siDebugHeader); } - default: __builtin_unreachable(); + default: SI_BUILTIN_UNREACHABLE(); } if (res == nil) { @@ -3452,7 +3628,7 @@ void si_debug_print_all(void) { case 0: msg = "NOT FREED"; break; case 1: msg = "FREED"; break; case 2: msg = "REALLOCED"; break; - default: __builtin_unreachable(); + default: SI_BUILTIN_UNREACHABLE(); } printf( From 68d60f4a6cce47110e053ca38ac5bf79291d258e Mon Sep 17 00:00:00 2001 From: EimaMei Date: Wed, 28 Jun 2023 22:25:33 +0300 Subject: [PATCH 15/17] Added some new bit functions and macros, ported most string funcs to array, si_array_fill --- examples/array.c | 40 +++++ sili.h | 385 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 309 insertions(+), 116 deletions(-) diff --git a/examples/array.c b/examples/array.c index 607a706..8b1c88a 100644 --- a/examples/array.c +++ b/examples/array.c @@ -55,11 +55,51 @@ void example_2_1(void) { } +void example_2_2(void) { + siArray(siColor) array = si_array_make((siColor[]){SI_RGB(255, 0, 0), SI_RGBA(0, 255, 0, 127), SI_RGB(0, 0, 255)}); + + si_array_append(&array, (siColor){255, 255, 255, 255}); + + printf("All of the elements in 'array' (len - '%zd'):\n", si_array_len(array)); + for_range (i, 0, si_array_len(array)) { + printf("\tElement %zd: (%i, %i, %i, %i)\n", i, array[i].r, array[i].g, array[i].g, array[i].b); + } + + si_array_pop(&array); + printf("Current length now - '%zd'\n", si_array_len(array)); + + + si_array_insert(&array, SI_RGB(127, 127, 127), 2); + + printf("All of the elements in 'array' (len - '%zd'):\n", si_array_len(array)); + for_range (i, 0, si_array_len(array)) { + printf("\tElement %zd: (%i, %i, %i, %i)\n", i, array[i].r, array[i].g, array[i].g, array[i].b); + } + + si_array_erase(&array, 2); + + printf("All of the elements in 'array' (len - '%zd'):\n", si_array_len(array)); + for_range (i, 0, si_array_len(array)) { + printf("\tElement %zd: (%i, %i, %i, %i)\n", i, array[i].r, array[i].g, array[i].g, array[i].b); + } + + si_array_erase_count(&array, 0, 3); + printf("array_empty: '%zd', capacity: '%zd'\n", si_array_empty(array), si_array_capacity(array)); + + si_array_fill(&array, 0, si_array_capacity(array), SI_RGBA(0xFF, 0xFF, 0xFF, 0xFF)); + printf("All of the elements in 'array' (len - '%zd'):\n", si_array_len(array)); + for_range (i, 0, si_array_len(array)) { + printf("\tElement %zd: (%i, %i, %i, %i)\n", i, array[i].r, array[i].g, array[i].g, array[i].b); + } +} + + int main(void) { si_init(SI_KILO(1)); example_2_0(); example_2_1(); + example_2_2(); si_terminate(); return 0; diff --git a/sili.h b/sili.h index eb0a4f4..c92c851 100644 --- a/sili.h +++ b/sili.h @@ -19,6 +19,7 @@ sili.h - a cross-platform software toolchain for modern C programming - #define SI_CHAR_UNDEFINE - #define SI_FILE_UNDEFINE - #define SI_THREAD_UNDEFINE + - #define SI_BIT_UNDEFINE - #define SI_PERFORMANCE_UNDEFINE before the SI_IMPLEMENTATION macro, as well as before any other include of `sili.h`. @@ -216,7 +217,7 @@ extern "C" { #endif #if defined(SI_SYSTEM_UNIX) -#include + #include #endif #if !defined(u8) @@ -370,9 +371,6 @@ SI_STATIC_ASSERT(false == 0); #define SI_OKAY 0 #define SI_ERROR -1 -#define SI_BIT(x) (1ULL << (x)) -#define SI_NUM_GET_BIT(num, x) ((num & SI_BIT(x)) != 0) - #define SI_KILO(x) ( (x) * (usize)1024) #define SI_MEGA(x) (SI_KILO(x) * (usize)1024) #define SI_GIGA(x) (SI_MEGA(x) * (usize)1024) @@ -448,7 +446,7 @@ SI_STATIC_ASSERT(sizeof(nil) == sizeof(NULL)); ======================== */ #if !defined(typeof) && SI_STANDARD_VERSION <= SI_STANDARD_C17 - #define typeof(value) __typeof__(value) + #define typeof(...) __typeof__((__VA_ARGS__)) #endif #if !defined(countof) #define countof(value) si_cast(usize, (f64)sizeof(value) / sizeof(*(value))) @@ -539,8 +537,7 @@ typedef struct siAny { #define si_any_make(...) \ (siAny){ \ - SI_BUILTIN_TYPES_CMP(typeof(__VA_ARGS__), char[]) == true ? \ - (rawptr)&((struct { char* in; }){(char*)__VA_ARGS__}.in) : \ + /* NOTE(EimaMei): check strings for this later. */ (rawptr)&((struct { typeof(__VA_ARGS__) in; }){__VA_ARGS__}.in), \ sizeof(typeof(__VA_ARGS__)) \ } @@ -568,8 +565,8 @@ typedef struct { u32 x, y; } siUVector2D; typedef siIVector2D siVector2D; typedef struct { u8 r, g, b, a; } siColor; -#define SI_RGBA(r, g, b, a) (siColor){r, g, b, a} -#define SI_RGB(r, g, b) (siColor){r, g, b, 255} +#define SI_RGBA(r, g, b, a) ((siColor){r, g, b, a}) +#define SI_RGB(r, g, b) ((siColor){r, g, b, 255}) typedef SI_ENUM(usize, siDirection) { @@ -792,12 +789,20 @@ usize si_array_len(rawptr array); usize si_array_capacity(rawptr array); usize si_array_type_size(rawptr array); usize si_array_total_size(rawptr array); +usize si_array_empty(rawptr array); siAny si_array_at(rawptr array, usize index); siAny si_array_front(rawptr array); siAny si_array_back(rawptr array); -#define si_array_append(array_ptr, value) si_impl_array_append(array_ptr, si_any_make(value)) +#define si_array_append(array_ptr, ...) si_impl_array_append(array_ptr, si_any_make(__VA_ARGS__)) +#define si_array_push(array_ptr, ...) si_array_append(array_ptr, __VA_ARGS__) +void si_array_pop(rawptr array_ptr); +#define si_array_insert(array_ptr, new_item, index) si_impl_array_insert(array_ptr, si_any_make(new_item), index) +void si_array_erase(rawptr array_ptr, usize index); +void si_array_erase_count(rawptr array_ptr, usize index, usize count); +#define si_array_remove_item(array_ptr, ...) si_impl_array_remove_item(array_ptr, si_any_make(__VA_ARGS__)) +#define si_array_fill(array_ptr, index, count, ...) si_impl_array_fill(array_ptr, index, count, si_any_make(__VA_ARGS__)) #define si_array_find(array, ...) si_impl_array_find(array, 0, si_array_len(array), si_any_make(__VA_ARGS__)) #define si_array_find_ex(array, start, end, ...) si_impl_array_find(array, start, end, si_any_make(__VA_ARGS__)) @@ -811,13 +816,17 @@ char* si_array_to_sistring(siArray(char*) array, cstring separator); void si_array_clear(rawptr array_ptr); bool si_array_equal(rawptr lha, rawptr rha); -isize si_array_free(rawptr array); +void si_array_free(rawptr array); +/* NOTE(EimaMei): TODO void si_array_shrink_to_fit(rawptr array_ptr); */ /* NOTE(EimaMei): The actual implementations. Shouldn't be used in practice, really. */ isize si_impl_array_find(rawptr array, usize start, usize end, siAny value); isize si_impl_array_rfind(rawptr array, usize start, usize end, siAny value); void si_impl_array_append(rawptr array_ptr, siAny value); +void si_impl_array_insert(rawptr array_ptr, siAny value, usize index); void si_impl_array_replace(rawptr array_ptr, siAny old_value, siAny new_value); +void si_impl_array_remove_item(rawptr array_ptr, siAny item); +void si_impl_array_fill(rawptr array_ptr, usize index, usize count, siAny item); #endif @@ -1203,7 +1212,7 @@ void si_string_append(siString* str, cstring other); void si_string_append_len(siString* str, cstring other, usize other_len); /** - * @brief Pushes [appends] the character into the siString. + * @brief Pushes (appends) the character into the siString. * * @param str The siString to push to. * @param other The character to push. @@ -1252,7 +1261,7 @@ void si_string_insert_ex(siString* str, cstring cstr, usize cstr_len, usize inde void si_string_erase(siString* str, usize index, usize erase_len); void si_string_remove_cstr(siString* str, cstring cstr); -void si_string_swap(siString* str, cstring cstr1, cstring cstr2); +/* TODO(EimaMei): void si_string_swap(siString* str, cstring cstr1, cstring cstr2); */ void si_string_strip(siString* str); /* NOTE(EimaMei); This strips any leading or trailing spaces in the string. */ void si_string_reverse(siString* str); @@ -1549,7 +1558,7 @@ void si_sleep(usize miliseconds); #endif -#if !defined(SI_USIZE_BIT_UNDEFINE) +#if !defined(SI_BIT_UNDEFINE) /* * * @@ -1566,7 +1575,7 @@ void si_sleep(usize miliseconds); * * ======================== - | usize/bit functions | + | Bit functions | ======================== */ @@ -1575,6 +1584,21 @@ typedef SI_ENUM(usize, siBitType) { SI_BIT_ONE }; + +#define SI_BIT(x) ((usize)1 << (x)) +#define SI_HIGH_BIT(value) ((value & ((typeof(value))0xFF << SI_BYTE_TO_BIT(sizeof(typeof(value)) - 1))) >> SI_BYTE_TO_BIT(sizeof(typeof(value)) - 1)) +#define SI_LOW_BIT(value) (value & ((typeof(value))0xFF)) + +#define SI_NUM_GET_BIT(num, x) ((num & SI_BIT(x)) != 0) +#define SI_BYTE_TO_BIT(bits) ((bits) * (usize)8) + + +#define BIT_00000000 0 +#define BIT_00000001 1 +#define BIT_10000000 128 +#define BIT_11111111 255 + + #define si_num_count_bit(num, bit_type) si_num_count_bit_ex(num, sizeof(typeof(num)), bit_type) #define si_num_leading_bit(num, bit_type) si_num_leading_bit_ex(num, sizeof(typeof(num)), bit_type) #define si_num_trailing_bit(num, bit_type) si_num_trailing_bit_ex(num, sizeof(typeof(num)), bit_type) @@ -1583,8 +1607,17 @@ typedef SI_ENUM(usize, siBitType) { #define si_num_rotate_right(num, bits) si_num_rotate_right_ex(num, sizeof(typeof(num)), bits) #define si_num_reverse_bits(num) si_num_reverse_bits_ex(num, sizeof(typeof(num))) +#define si_num_to_bytes(num) si_num_to_bytes_ex(num, sizeof(typeof(num))) +usize si_bytes_to_num(siArray(u8)); + #define si_num_change_endian(num) si_num_change_endian_ex(num, sizeof(typeof(num))) +usize si_num_pow(isize base, usize exp); +usize si_num_pow2(isize base, usize exp); + + + +#if 1 /* NOTE(EimaMei): The actual header definition for the macros. No reason to use these in practice. */ usize si_num_leading_bit_ex(usize num, usize sizeof_num, siBitType bit); usize si_num_count_bit_ex(usize num, usize sizeof_num, siBitType bit); usize si_num_trailing_bit_ex(usize num, usize number_sizeof, siBitType bit); @@ -1593,99 +1626,10 @@ usize si_num_rotate_left_ex(usize num, usize num_sizeof, usize bits); usize si_num_rotate_right_ex(usize num, usize num_sizeof, usize n); usize si_num_reverse_bits_ex(usize num, usize num_sizeof); -usize si_num_change_endian_ex(usize num, usize num_sizeof); - -usize si_num_pow(isize base, isize exp); -usize si_num_pow2(isize base); - - -inline usize si_num_count_bit_ex(usize num, usize sizeof_num, siBitType bit) { - usize count = 0; - - for_range (i, 0, sizeof_num * 8) { - if (SI_NUM_GET_BIT(num, i) == bit) { - count += 1; - } - } - - return count; -} -inline usize si_num_leading_bit_ex(usize num, usize sizeof_num, siBitType bit) { - usize count = 0; - - usize i; - for (i = sizeof_num * 8 - 1; i < USIZE_MAX; i -= 1) { - if (SI_NUM_GET_BIT(num, i) == bit) { - count += 1; - } - else { - return count; - } - } - - return count; -} -inline usize si_num_trailing_bit_ex(usize num, usize sizeof_num, siBitType bit) { - usize count = 0; +siArray(u8) si_num_to_bytes_ex(usize num, usize num_sizeof); - for_range (i, 0, sizeof_num * 8) { - if (SI_NUM_GET_BIT(num, i) == bit) { - count += 1; - } - else { - return count; - } - } - - return count; -} -inline usize si_num_rotate_left_ex(usize num, usize num_sizeof, usize bits) { - return (num << bits) | (num >> (num_sizeof * 8 - bits)); -} -inline usize si_num_rotate_right_ex(usize num, usize num_sizeof, usize bits) { - return (num >> bits) | (num << (num_sizeof * 8 - bits)); -} - -inline usize si_num_reverse_bits_ex(usize num, usize num_sizeof) { - usize res = 0LL; - - for_range(i, 0, num_sizeof * 8) { - res <<= 1; - res |= (num & 1); - num >>= 1; - } - - return res; -} - -inline usize si_num_change_endian_ex(usize num, usize num_sizeof) { - usize result = 0; - - for_range (i, 0, num_sizeof) { - result |= ((num >> (i * 8)) & 0xFF) << ((num_sizeof - 1 - i) * 8); - } - - return result; -} - -usize si_num_pow(isize base, isize exp) { - SI_ASSERT_MSG(exp > 0, "Currently not possible to do base powered by negative exp."); - - usize result = 1; - while (exp > 0) { - if (exp & 1) { - result *= base; - } - base *= base; - exp >>= 1; - } - - return result; -} - -inline usize si_num_pow2(isize base) { - return 1 << base; -} +usize si_num_change_endian_ex(usize num, usize num_sizeof); +#endif #endif @@ -1896,6 +1840,7 @@ void si_debug_cleanup(void); #define SI_CHAR_IMPLEMENTATION #define SI_FILE_IMPLEMENTATION #define SI_THREAD_IMPLEMENTATION + #define SI_BIT_IMPLEMENTATION #define SI_PERFORMANCE_IMPLEMENTATION #endif @@ -2112,6 +2057,9 @@ inline usize si_array_type_size(rawptr array) { inline usize si_array_total_size(rawptr array) { return si_array_capacity(array) * si_array_type_size(array); } +inline usize si_array_empty(rawptr array) { + return (si_array_len(array) == 0 || array == nil); +} inline siAny si_array_at(rawptr array, usize index) { if (index >= si_array_len(array)) { @@ -2241,14 +2189,110 @@ siString si_array_to_sistring(siArray(char*) array, cstring separator) { return result; } +inline void si_array_pop(rawptr array_ptr) { + siByte* array = *si_cast(siByte**, array_ptr); + SI_ARRAY_HEADER(array)->len -= 1; +} + +void si_impl_array_insert(rawptr array_ptr, siAny new_item, usize index) { + SI_ASSERT_NOT_NULL(array_ptr); + + siByte* array = *si_cast(siByte**, array_ptr); + siArrayHeader* header = SI_ARRAY_HEADER(array); + + usize previous_len = header->len; + usize before_index_len = previous_len - index; + + SI_ASSERT_FMT(index < previous_len, "Index is higher than the length of the array (array - '%zd', index - '%zd')", previous_len, index); + header->len += 1; + + if (header->capacity < header->len) { + rawptr result = realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_size, sizeof(siArrayHeader) + 2 * header->capacity * header->type_size); + + array = (siByte*)result + sizeof(siArrayHeader); + *si_cast(siByte**, array_ptr) = array; + + header = (siArrayHeader*)result; + header->capacity *= 2; + } + + memcpy( + array + (header->len - before_index_len) * header->type_size, + array + index * header->type_size, + before_index_len * header->type_size + ); + memcpy(array + index * header->type_size, new_item.ptr, new_item.type_size); +} +inline void si_array_erase(rawptr array_ptr, usize index) { + si_array_erase_count(array_ptr, index, 1); +} +void si_array_erase_count(rawptr array_ptr, usize index, usize count) { + SI_ASSERT_NOT_NULL(array_ptr); + siByte* array = *si_cast(siByte**, array_ptr); + + usize len = si_array_len(array); + SI_ASSERT_MSG(index < len, "Index is higher than the length of the string."); + SI_ASSERT_FMT(index + count <= len, "Index + count is higher than the length of the array (%zd > %zd).", index + count, len); + + memcpy(array + index * si_array_type_size(array), array + (index + count) * si_array_type_size(array), (len - index - count) * si_array_type_size(array)); + + SI_ARRAY_HEADER(array)->len -= count; +} +void si_impl_array_remove_item(rawptr array_ptr, siAny item) { + SI_ASSERT_NOT_NULL(array_ptr); + siByte* array = *si_cast(siByte**, array_ptr); + + siArrayHeader* header = SI_ARRAY_HEADER(array); + usize len = header->len; + while (true) { + isize index = si_impl_array_rfind(array, header->len - 1, 0, item); + if (index == -1) { + break; + } + + usize after_index_len = index + len; + + memcpy(array + index, array + arawptrfter_index_len, header->len - after_index_len); + header->len -= 1; + } +} +void si_impl_array_fill(rawptr array_ptr, usize index, usize count, siAny value) { + SI_ASSERT_NOT_NULL(array_ptr); + siByte* array = *si_cast(siByte**, array_ptr); + + siArrayHeader* header = SI_ARRAY_HEADER(array); + SI_ASSERT_MSG(value.type_size <= header->type_size, "The given value's sizeof is too large compared to the elements' in the array."); + SI_ASSERT_MSG(index < header->capacity, "Index is higher than the array's length."); + + usize previous_len = header->len; + isize size_dif = si_abs((isize)index - (isize)count); + header->len += size_dif; + + if (header->capacity < header->len) { + rawptr result = realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_size, sizeof(siArrayHeader) + size_dif + 2 * header->capacity * header->type_size); + SI_ASSERT_NOT_NULL(result); + + array = (siByte*)result + sizeof(siArrayHeader); + *si_cast(siByte**, array_ptr) = array; + + header = (siArrayHeader*)result; + header->capacity = header->capacity * 2 + size_dif; + } + + for_range(i, index, count) { + memcpy(si_array_get_ptr(array, previous_len + i), value.ptr, header->type_size); + } +} + void si_impl_array_append(rawptr array_ptr, siAny value) { SI_ASSERT_NOT_NULL(array_ptr); siByte* array = *si_cast(siByte**, array_ptr); siArrayHeader* header = SI_ARRAY_HEADER(array); SI_ASSERT_MSG(value.type_size <= header->type_size, "The given value's sizeof is too large compared to the elements' in the arra"); + header->len += 1; - if (header->len == header->capacity) { + if (header->capacity < header->len) { rawptr result = realloc(header, sizeof(siArrayHeader) + header->capacity * header->type_size, sizeof(siArrayHeader) + 2 * header->capacity * header->type_size); SI_ASSERT_NOT_NULL(result); @@ -2260,7 +2304,6 @@ void si_impl_array_append(rawptr array_ptr, siAny value) { } memcpy(si_array_get_ptr(array, header->len), value.ptr, header->type_size); - header->len += 1; } void si_array_clear(rawptr array_ptr) { @@ -2289,14 +2332,9 @@ bool si_array_equal(rawptr lha, rawptr rha) { return true; } -isize si_array_free(rawptr array) { - if (array == nil) { - return SI_ERROR; - } - +inline void si_array_free(rawptr array) { + SI_ASSERT_NOT_NULL(array); free(SI_ARRAY_HEADER(array)); - - return SI_OKAY; } #endif @@ -3470,6 +3508,121 @@ void si_thread_set_priority(siThread t, i32 priority) { #endif } +#if defined(SI_BIT_IMPLEMENTATION) && !defined(SI_BIT_UNDEFINE) + +inline usize si_num_count_bit_ex(usize num, usize sizeof_num, siBitType bit) { + usize count = 0; + + for_range (i, 0, SI_BYTE_TO_BIT(sizeof_num)) { + if (SI_NUM_GET_BIT(num, i) == bit) { + count += 1; + } + } + + return count; +} +inline usize si_num_leading_bit_ex(usize num, usize sizeof_num, siBitType bit) { + usize count = 0; + + usize i; + for (i = sizeof_num * 8 - 1; i < USIZE_MAX; i -= 1) { + if (SI_NUM_GET_BIT(num, i) == bit) { + count += 1; + } + else { + return count; + } + } + + return count; +} +inline usize si_num_trailing_bit_ex(usize num, usize sizeof_num, siBitType bit) { + usize count = 0; + + for_range (i, 0, sizeof_num * 8) { + if (SI_NUM_GET_BIT(num, i) == bit) { + count += 1; + } + else { + return count; + } + } + + return count; +} +inline usize si_num_rotate_left_ex(usize num, usize num_sizeof, usize bits) { + return (num << bits) | (num >> (num_sizeof * 8 - bits)); +} +inline usize si_num_rotate_right_ex(usize num, usize num_sizeof, usize bits) { + return (num >> bits) | (num << (num_sizeof * 8 - bits)); +} + +inline usize si_num_reverse_bits_ex(usize num, usize num_sizeof) { + usize res = 0LL; + + for_range(i, 0, num_sizeof * 8) { + res <<= 1; + res |= (num & BIT_00000001); + num >>= 1; + } + + return res; +} + +siArray(u8) si_num_to_bytes_ex(usize num, usize num_sizeof) { + siArray(u8) res = si_array_make_reserve(sizeof(*res), num_sizeof); + SI_ARRAY_HEADER(res)->len = num_sizeof; + + for_range (i, 0, num_sizeof) { + res[i] = (num >> ((num_sizeof - 1 - i) * 8)) & BIT_11111111; + } + + return res; +} +inline usize si_bytes_to_num(siArray(u8) bytes) { + SI_ASSERT_NOT_NULL(bytes); + usize res = 0; + usize shift = (si_array_len(bytes) - 1) * 8; + + foreach (byte, bytes) { + res |= si_cast(usize, *byte) << shift; + shift -= 8; + } + + return res; +} + +inline usize si_num_change_endian_ex(usize num, usize num_sizeof) { + usize result = 0; + + for_range (i, 0, num_sizeof) { + result |= ((num >> SI_BYTE_TO_BIT(i)) & BIT_11111111) << SI_BYTE_TO_BIT(num_sizeof - 1 - i); + } + + return result; +} + +usize si_num_pow(isize base, usize exp) { + usize result = 1; + + while (exp > 0) { + if (exp & BIT_00000001) { + result *= base; + } + base *= base; + exp >>= 1; + } + + return result; +} + +inline usize si_num_pow2(isize base, usize exp) { + return exp << base; +} + + +#endif + #endif #if defined(SI_MEMORY_LOGGING_IMPLEMENTATION) && !defined(SI_MEMORY_LOGGING_UNDEFINE) From 5a77603d592150dc90e195c9885e5c58726bad45 Mon Sep 17 00:00:00 2001 From: EimaMei Date: Thu, 29 Jun 2023 00:12:37 +0300 Subject: [PATCH 16/17] some minor bug fixes + added new array functions --- Makefile | 2 +- examples/array.c | 7 ++++- examples/thread.c | 2 +- sili.h | 69 ++++++++++++++++++++++++++++++++--------------- 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index fb681fe..41c7fc8 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ OUTPUT = build NAME = test EXE = $(OUTPUT)/$(NAME) -SRC = src/main.c +SRC = examples/array.c FLAGS = -O0 -std=c99 -Wall -Wextra -Wpedantic LIBS = INCLUDE = -I"." diff --git a/examples/array.c b/examples/array.c index 8b1c88a..36c9041 100644 --- a/examples/array.c +++ b/examples/array.c @@ -1,3 +1,4 @@ +#define SI_ALLOCATOR_UNDEFINE 1 #define SI_IMPLEMENTATION 1 #include @@ -7,7 +8,7 @@ void example_2_0(void) { siArray(i32) array = si_array_make((i32[]){3, 234, 2, 4, 294, 234, 23}); - puts("All of the elements in 'array':"); + print("All of the elements in 'array':"); for_range (i, 0, si_array_len(array)) { printf("\tElement %zd: %i\n", i, array[i]); } @@ -87,10 +88,14 @@ void example_2_2(void) { printf("array_empty: '%zd', capacity: '%zd'\n", si_array_empty(array), si_array_capacity(array)); si_array_fill(&array, 0, si_array_capacity(array), SI_RGBA(0xFF, 0xFF, 0xFF, 0xFF)); + printf("All of the elements in 'array' (len - '%zd'):\n", si_array_len(array)); for_range (i, 0, si_array_len(array)) { printf("\tElement %zd: (%i, %i, %i, %i)\n", i, array[i].r, array[i].g, array[i].g, array[i].b); } + + si_array_remove_item(&array, SI_RGBA(0xFF, 0xFF, 0xFF, 0xFF)); + printf("All of the elements in 'array' (len - '%zd'):\n", si_array_len(array)); } diff --git a/examples/thread.c b/examples/thread.c index c348b27..9ec8dcd 100644 --- a/examples/thread.c +++ b/examples/thread.c @@ -54,7 +54,7 @@ int main(void) { si_sleep(2500); si_thread_cancel(&thread); - puts("Decided to kill it 2.5 seconds later."); + print("Decided to kill it 2.5 seconds later."); #endif si_terminate(); diff --git a/sili.h b/sili.h index c92c851..1dd5765 100644 --- a/sili.h +++ b/sili.h @@ -464,6 +464,8 @@ SI_STATIC_ASSERT(sizeof(nil) == sizeof(NULL)); ======================== */ +#define print(msg) puts(msg) + #define likely(x) SI_BUILTIN_EXPECT(!!(x), true) #define unlikely(x) SI_BUILTIN_EXPECT(!!(x), false) @@ -506,8 +508,13 @@ SI_STATIC_ASSERT(sizeof(nil) == sizeof(NULL)); | Mics/General | ======================== */ -#define si_init(size) do { SI_GLOBAL_ALLOC = si_allocator_init(size); } while(0) -#define si_terminate() do { si_allocator_free(SI_GLOBAL_ALLOC); } while(0) +#if !defined(SI_ALLOCATOR_UNDEFINE) + #define si_init(size) do { SI_GLOBAL_ALLOC = si_allocator_init(size); } while(0) + #define si_terminate() do { si_allocator_free(SI_GLOBAL_ALLOC); } while(0) +#else + #define si_init(size) do {} while(0) + #define si_terminate() do {} while(0) +#endif /* ======================== @@ -537,7 +544,7 @@ typedef struct siAny { #define si_any_make(...) \ (siAny){ \ - /* NOTE(EimaMei): check strings for this later. */ + /* NOTE(EimaMei): check strings for this later. */ \ (rawptr)&((struct { typeof(__VA_ARGS__) in; }){__VA_ARGS__}.in), \ sizeof(typeof(__VA_ARGS__)) \ } @@ -610,6 +617,7 @@ void si_ptr_move_by(rawptr src, usize src_len, usize move_by, siDirection direct * * */ + #if !defined(SI_ALLOCATOR_UNDEFINE) /* * @@ -657,6 +665,8 @@ void si_free(siAllocator* alloc, rawptr ptr); #define free(ptr) si_free(SI_GLOBAL_ALLOC, ptr) #endif +#else + #define realloc(ptr, old_size, new_size) realloc(ptr, new_size) #endif #if !defined(SI_PAIR_UNDEFINE) @@ -817,7 +827,7 @@ void si_array_clear(rawptr array_ptr); bool si_array_equal(rawptr lha, rawptr rha); void si_array_free(rawptr array); -/* NOTE(EimaMei): TODO void si_array_shrink_to_fit(rawptr array_ptr); */ +void si_array_shrink_to_fit(rawptr array_ptr); /* NOTE(EimaMei): The actual implementations. Shouldn't be used in practice, really. */ isize si_impl_array_find(rawptr array, usize start, usize end, siAny value); @@ -1859,7 +1869,7 @@ usize si_impl_assert_msg(bool condition, cstring condition_str, cstring file, i3 va_start(va, message); vprintf(message, va); - puts(""); + print(""); va_end(va); } @@ -2111,7 +2121,7 @@ isize si_impl_array_find(rawptr array, usize start, usize end, siAny value) { isize si_impl_array_rfind(rawptr array, usize start, usize end, siAny value) { SI_ASSERT_NOT_NULL(array); SI_ASSERT_MSG(value.type_size <= si_array_type_size(array), "The given value's sizeof is too large compared to the elements' in the array."); - SI_ASSERT_MSG(start > end, "Value 'end' is larger than 'start'"); + SI_ASSERT_MSG(start >= end, "Value 'end' is larger than 'start'"); bool found = false; usize i; @@ -2139,10 +2149,10 @@ void si_impl_array_replace(rawptr array, siAny old_value, siAny new_value) { index = si_impl_array_find(array, index, header->len, old_value); if (index == SI_ERROR) { return ; - } + } - memcpy(si_array_get_ptr(array, index), new_value.ptr, new_value.type_size); -} + memcpy(si_array_get_ptr(array, index), new_value.ptr, new_value.type_size); + } } void si_array_reverse(rawptr array_ptr) { SI_ASSERT_NOT_NULL(array_ptr); @@ -2238,22 +2248,24 @@ void si_array_erase_count(rawptr array_ptr, usize index, usize count) { SI_ARRAY_HEADER(array)->len -= count; } -void si_impl_array_remove_item(rawptr array_ptr, siAny item) { +void si_impl_array_remove_item(rawptr array_ptr, siAny value) { SI_ASSERT_NOT_NULL(array_ptr); siByte* array = *si_cast(siByte**, array_ptr); + SI_ASSERT_MSG(value.type_size <= si_array_type_size(array), "The given value's sizeof is too large compared to the elements' in the array."); siArrayHeader* header = SI_ARRAY_HEADER(array); - usize len = header->len; - while (true) { - isize index = si_impl_array_rfind(array, header->len - 1, 0, item); + + while (header->len != 0) { + isize index = si_impl_array_rfind(array, header->len - 1, 0, value); if (index == -1) { break; } - usize after_index_len = index + len; + memcpy(si_array_get_ptr(array, index), si_array_get_ptr(array, index + header->len), value.type_size); - memcpy(array + index, array + arawptrfter_index_len, header->len - after_index_len); - header->len -= 1; + if (header->len != 0) { + header->len -= 1; + } } } void si_impl_array_fill(rawptr array_ptr, usize index, usize count, siAny value) { @@ -2337,6 +2349,18 @@ inline void si_array_free(rawptr array) { free(SI_ARRAY_HEADER(array)); } +void si_array_shrink_to_fit(rawptr array_ptr) { + SI_ASSERT_NOT_NULL(array_ptr); + siByte* array = *si_cast(siByte**, array_ptr); + siArrayHeader* header = SI_ARRAY_HEADER(array); + + header = (typeof(header))realloc( + header, + sizeof(siArrayHeader*) + header->capacity * header->type_size, + sizeof(siArrayHeader*) + header->len * header->type_size + ); + header->capacity = header->len; +} #endif #if defined(SI_BUFFER_IMPLEMENTATION) && !defined(SI_BUFFER_UNDEFINE) @@ -2983,11 +3007,14 @@ void si_string_make_space_for(siString* str, usize add_len) { } void si_string_shrink_to_fit(siString* str) { SI_ASSERT_NOT_NULL(str); - siString cur_str = *str; - siStringHeader copy = *SI_STRING_HEADER(cur_str); + siString cur_str = *str; + siStringHeader* header = SI_STRING_HEADER(cur_str); - siStringHeader* header = (typeof(header))realloc(SI_STRING_HEADER(cur_str), sizeof(siStringHeader*) + copy.capacity + 1, sizeof(siStringHeader*) + copy.len + 1); - *header = copy; + header = (typeof(header))realloc( + header, + sizeof(siStringHeader*) + header->capacity + 1, + sizeof(siStringHeader*) + header->len + 1 + ); header->capacity = header->len; } #endif @@ -3463,7 +3490,7 @@ void si_thread_join(siThread* t) { } void si_thread_cancel(siThread* t) { #if defined(SI_SYSTEM_WINDOWS) - puts("si_thread_cancel: This feature on Windows is not supported as of now."); + print("si_thread_cancel: This feature on Windows is not supported as of now."); SI_UNUSED(t); #else From a54026f294026eb107d2c9d86375c6b39661a138 Mon Sep 17 00:00:00 2001 From: EimaMei <69605234+EimaMei@users.noreply.github.com> Date: Thu, 29 Jun 2023 00:15:31 +0300 Subject: [PATCH 17/17] Create linux.yml --- .github/workflows/linux.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/linux.yml diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 0000000..affcdee --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,19 @@ +name: linux + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: apt + run: sudo apt-get install libxcursor-dev + - name: make + run: make