diff --git a/exe_main.cpp b/exe_main.cpp index 8d19f99..f265224 100644 --- a/exe_main.cpp +++ b/exe_main.cpp @@ -1,7 +1,7 @@ // Treat library files as a single-file (single translation unit) header #include "lib_main.cpp" -#define BASE_RUN_TESTS 0 +#define BASE_RUN_TESTS BUILD_DEBUG #define BUILD_EXPLORER_APP_WIN32 1 #define BUILD_CUSTOM_GUI 0 diff --git a/lib/Base/Arena_Array.h b/lib/Base/Arena_Array.h index db9fbd4..2a192e5 100644 --- a/lib/Base/Arena_Array.h +++ b/lib/Base/Arena_Array.h @@ -209,6 +209,7 @@ template void init_range (T* ptr, s64 start_offset, s64 end_offset) template void array_poison_range (ArenaArray& array, s64 start, s64 count) { #if BUILD_DEBUG + if (count == 0) return; Assert(start >= 0 && start < array.count); Assert(start + count <= array.count); // Check that these ranges make sense diff --git a/lib/Base/Base.h b/lib/Base/Base.h index bb65530..f95c7af 100644 --- a/lib/Base/Base.h +++ b/lib/Base/Base.h @@ -342,6 +342,7 @@ force_inline s64 Next_Power_Of_Two(s64 v) { #define temp() allocator(thread_context()->temp) #define context_allocator() thread_context()->allocator #define context_logger() &thread_context()->logger +#define context_builder() thread_context()->string_builder // CHECK THAT THESE ARE CORRECT! constexpr f32 TAU = 6.283185f; diff --git a/lib/Base/Base_Thread_Context.cpp b/lib/Base/Base_Thread_Context.cpp index e46b65b..3e1a480 100644 --- a/lib/Base/Base_Thread_Context.cpp +++ b/lib/Base/Base_Thread_Context.cpp @@ -22,13 +22,14 @@ internal void Bootstrap_Main_Thread_Context () { ExpandableArena* arena_ex = bootstrap_expandable_arena(Arena_Reserve::Size_64M); thread_local_context = New(allocator(arena_ex)); - thread_local_context->temp = bootstrap_expandable_arena(Arena_Reserve::Size_2M); - thread_local_context->arena = arena_ex; - thread_local_context->allocator = allocator(arena_ex); - thread_local_context->thread_idx = 0; - thread_local_context->thread_name = "Main Thread"; - thread_local_context->log_builder = new_string_builder(Arena_Reserve::Size_64M); - thread_local_context->error_arena = bootstrap_arena(Arena_Reserve::Size_64M); + thread_local_context->temp = bootstrap_expandable_arena(Arena_Reserve::Size_2M); + thread_local_context->arena = arena_ex; + thread_local_context->allocator = allocator(arena_ex); + thread_local_context->thread_idx = 0; + thread_local_context->thread_name = "Main Thread"; + thread_local_context->log_builder = new_string_builder(Arena_Reserve::Size_64M); + thread_local_context->string_builder = new_string_builder(Arena_Reserve::Size_2M); + thread_local_context->error_arena = bootstrap_arena(Arena_Reserve::Size_64M); default_logger_initialize(); thread_local_context->logger = {default_logger_proc, &default_logger}; diff --git a/lib/Base/Base_Thread_Context.h b/lib/Base/Base_Thread_Context.h index fa6aacf..ce48a8b 100644 --- a/lib/Base/Base_Thread_Context.h +++ b/lib/Base/Base_Thread_Context.h @@ -24,7 +24,8 @@ struct Thread_Context { // u16 _padding0; u16 default_allocator_alignment = 16; Logger logger = {nullptr, nullptr}; - String_Builder* log_builder; + String_Builder* log_builder; // String builder used by log() and log_error_internal() + String_Builder* string_builder; // Secondary builder just for convenience! Stack_Trace_Node* stack_trace; // use `list(stack_trace)` in watch window of raddbg to view as array! Array child_threads; // maybe should be linked-list? @@ -127,7 +128,8 @@ struct Push_Stack_Trace { }; // #TODO: precede with something like: os_write_string_unsynchronized("Fatal Error!\n\nStack trace:", true); -string generate_stack_trace (Thread_Context* context) { // #no_context +string generate_stack_trace (Thread_Context* context) { + // #no_context - we want this to work even if context is utterly broken. String_Builder* sb = new_string_builder(Arena_Reserve::Size_64K); Stack_Trace_Node* node = context->stack_trace; @@ -143,7 +145,12 @@ string generate_stack_trace (Thread_Context* context) { // #no_context append(sb, "\n"); push_allocator(default_allocator()); - return builder_to_string(sb); + + string stack_trace_copy = builder_to_string(sb); + + free_string_builder(sb); + + return stack_trace_copy; } // We don't want to use context logger here! diff --git a/lib/Base/String.cpp b/lib/Base/String.cpp index b2446c3..ab45329 100644 --- a/lib/Base/String.cpp +++ b/lib/Base/String.cpp @@ -282,7 +282,7 @@ internal force_inline void reset_string_builder (String_Builder* sb, bool keep_m force_inline string builder_to_string (String_Builder* sb) { string final_string = copy_string(to_string(to_view(*sb))); - free_string_builder(sb); + // reset_string_builder(sb, false); // maybe this shouldn't be here! Too magical... return final_string; } diff --git a/lib/Base/String_Builder.h b/lib/Base/String_Builder.h index 62d3322..f0d657f 100644 --- a/lib/Base/String_Builder.h +++ b/lib/Base/String_Builder.h @@ -1,10 +1,14 @@ // #string_builder // #limitations This won't be as fast as Jon's String_Builder in jai because we're backing it with an -// Arena, which requires a variable number of cycles depending on if our process has -// memory available already. It also has a max capacity depending on what Arena_Reserve we choose. -// That being said, the implementation is much simpler. +// Arena, which calls VirtualAlloc, which is much slower than just using stack space to start. +// It also has a max capacity depending on what Arena_Reserve we choose. +// That being said, the implementation is much simpler, and we can keep it around for a bit. +// We can make it a lot faster by always having a string builder available in the thread_context, +// and just fetching that when we need it. + typedef ArenaArray String_Builder; // struct String_Builder + force_inline String_Builder* new_string_builder (Arena_Reserve new_reserve=Arena_Reserve::Size_64K); force_inline void append (String_Builder* sb, string s); void append (String_Builder* sb, ArrayView strings); @@ -18,3 +22,5 @@ internal force_inline void reset_string_builder (String_Builder* sb, bool keep_m // #rename copy_string_and_free_builder force_inline string builder_to_string (String_Builder* sb); // returns copy and frees string_builder internal force_inline void free_string_builder (String_Builder* sb); + + diff --git a/lib/Base/run_tests.cpp b/lib/Base/run_tests.cpp index cadf5ea..99b440e 100644 --- a/lib/Base/run_tests.cpp +++ b/lib/Base/run_tests.cpp @@ -19,7 +19,9 @@ void run_post_setup_tests() { // String builder example: // OK. I can work with this. - auto sb = new_string_builder(Arena_Reserve::Size_64K); + String_Builder* sb = context_builder(); + reset_string_builder(sb, true); + append(sb, "string_literal_example"); append(sb, " "); print_to_builder(sb, "There are %d cats in the %s", 64, "house.\n"); @@ -47,9 +49,9 @@ void run_post_setup_tests() { // push_allocator(allocator(thread_context()->arena)); push_allocator(default_allocator()); string file_path = "D:/Work/OpenBCI/ToolZ/prototyping-gui-main/modules/native-proto-lib/native-sdk-prototyping/src/SignalProcessing.cpp"; - ArrayView file_data = read_entire_file(file_path, true); + ArrayView file_data = read_entire_file(file_path, true, true); log("file_data: \n"); - log("%s\n", file_data.data); + log("%s\n", file_data.data); // #note this is not null-terminated } { // Test hashing: u64 start = 0x512585; diff --git a/lib/OS/OS_Filesystem.cpp b/lib/OS/OS_Filesystem.cpp index a33f838..5085869 100644 --- a/lib/OS/OS_Filesystem.cpp +++ b/lib/OS/OS_Filesystem.cpp @@ -84,8 +84,8 @@ string get_full_path (string drive_label, Dense_FS* dfs, s32 first_parent_index, array_add(path_list_reverse, drive_letter_with_colon); - // reset_string_builder(sb, true); - String_Builder* sb = new_string_builder(); + String_Builder* sb = context_builder(); + reset_string_builder(sb, true); for (s64 i = path_list_reverse.count-1; i >= 0; i -= 1) { append(sb, path_list_reverse[i]); diff --git a/lib/OS/OS_Win32.cpp b/lib/OS/OS_Win32.cpp index 9218596..a5d2754 100644 --- a/lib/OS/OS_Win32.cpp +++ b/lib/OS/OS_Win32.cpp @@ -296,15 +296,16 @@ internal bool thread_init (Thread* thread, Thread_Proc proc, string thread_name) // #NOTE: we don't assign thread_local_context until we hit the #thread_entry_point thread->context = New(); - thread->context->temp = bootstrap_expandable_arena(Arena_Reserve::Size_2M); - thread->context->arena = arena_ex; - thread->context->allocator = allocator(arena_ex); - thread->context->thread_idx = (s32)this_thread_index; + thread->context->temp = bootstrap_expandable_arena(Arena_Reserve::Size_2M); + thread->context->arena = arena_ex; + thread->context->allocator = allocator(arena_ex); + thread->context->thread_idx = (s32)this_thread_index; // #NOTE: This will disappear once the thread is de-initted. If we want this string, copy it! - thread->context->thread_name = copy_string(thread_name); - thread->context->log_builder = new_string_builder(Arena_Reserve::Size_64M); - thread->context->error_arena = bootstrap_arena(Arena_Reserve::Size_64M); - thread->context->logger = {default_logger_proc, &default_logger}; + thread->context->thread_name = copy_string(thread_name); + thread->context->log_builder = new_string_builder(Arena_Reserve::Size_64M); + thread->context->string_builder = new_string_builder(Arena_Reserve::Size_2M); + thread->context->error_arena = bootstrap_arena(Arena_Reserve::Size_64M); + thread->context->logger = {default_logger_proc, &default_logger}; thread->context->parent_thread_context = thread_context(); @@ -557,7 +558,7 @@ internal bool file_set_position (File file, s64 position) { return (bool)SetFilePointerEx(file.handle, position_li, nullptr, FILE_BEGIN); } -internal ArrayView read_entire_file (File file) { +ArrayView read_entire_file (File file, bool add_null_terminator) { ArrayView file_data; bool result = file_length(file, &file_data.count); @@ -565,7 +566,13 @@ internal ArrayView read_entire_file (File file) { result = file_set_position(file, 0); if (!result) return {}; - file_data.data = NewArray(file_data.count, false); + s64 total_file_size = file_data.count; + + if (add_null_terminator) { + total_file_size += 1; + } + + file_data.data = NewArray(total_file_size, false); if (file_data.data == nullptr) return {}; s64 bytes_read = 0; @@ -575,17 +582,21 @@ internal ArrayView read_entire_file (File file) { return {}; } + if (add_null_terminator) { + file_data[total_file_size-1] = 0; + } + Assert(bytes_read == file_data.count); file_data.count = bytes_read; return file_data; } -internal ArrayView read_entire_file (string file_path, bool log_errors) { +internal ArrayView read_entire_file (string file_path, bool add_null_terminator, bool log_errors) { File f = file_open(file_path, false, false, log_errors); if (!file_is_valid(f)) return {}; - ArrayView file_data = read_entire_file(f); + ArrayView file_data = read_entire_file(f, add_null_terminator); file_close(&f); @@ -1416,7 +1427,7 @@ bool Deserialize_ST_File_Enumeration (string file_path) { push_allocator(temp()); auto_release_temp(); - Deserializer deserializer = read_entire_file(file_path, true); + Deserializer deserializer = read_entire_file(file_path, false, true); if (deserializer.count == 0) return false; auto d = &deserializer; diff --git a/lib/OS/OS_Win32.h b/lib/OS/OS_Win32.h index 7bc37fb..4616590 100644 --- a/lib/OS/OS_Win32.h +++ b/lib/OS/OS_Win32.h @@ -41,8 +41,8 @@ internal bool file_length (File file, s64* length); internal bool file_length (string file_path, s64* length); internal s64 file_current_position (File file); internal bool file_set_position (File file, s64 position); -internal ArrayView read_entire_file (File file); -internal ArrayView read_entire_file (string file_path, bool log_errors=false); +internal ArrayView read_entire_file (File file, bool add_null_terminator); +internal ArrayView read_entire_file (string file_path, bool add_null_terminator=false, bool log_errors=false); // use to_byte_view to convert ArrayView to ArrayView internal bool file_write (File* file, void* data, s64 length); diff --git a/lib/OS/OS_Win32_File_Enumeration.cpp b/lib/OS/OS_Win32_File_Enumeration.cpp index a35ffed..e1567fe 100644 --- a/lib/OS/OS_Win32_File_Enumeration.cpp +++ b/lib/OS/OS_Win32_File_Enumeration.cpp @@ -105,7 +105,9 @@ string directory_get_full_path (Thread_Group* group, Parent_Index pid, string di } // go in reverse order and add together string - String_Builder* sb = new_string_builder(Arena_Reserve::Size_64K); + String_Builder* sb = context_builder(); + reset_string_builder(sb, true); + for (s64 i = paths.count-1; i >= 0; i -= 1) { append(sb, paths[i]); append(sb, "\\"); diff --git a/lib/OS/OS_Win32_NTFS.cpp b/lib/OS/OS_Win32_NTFS.cpp index 40a6834..b00dd4a 100644 --- a/lib/OS/OS_Win32_NTFS.cpp +++ b/lib/OS/OS_Win32_NTFS.cpp @@ -457,7 +457,7 @@ bool Deserialize_Win32_Drives (string file_path) { push_allocator(temp()); auto_release_temp(); - Deserializer deserializer = read_entire_file(file_path, true); + Deserializer deserializer = read_entire_file(file_path, false, true); if (deserializer.count == 0) return false; auto d = &deserializer;