Cleanup part 2
This commit is contained in:
parent
5e3ce038b5
commit
d42bf63d41
50
cpp_lib.todo
50
cpp_lib.todo
@ -1,50 +0,0 @@
|
||||
[#TODO]
|
||||
[ ] Base layer and OS abstraction for Windows. (Ryan's Win32 platform layer is ~2k lines of code.)
|
||||
• ryan uses os_thread_launch (CreateThread) /join (WaitForSingleObject+CloseHandle)/detach (CloseHandle ?? what type?)
|
||||
See: base_threads
|
||||
just implement the stuff we need for:
|
||||
He launches a bunch of async threads from `main_thread_base_entry_point`
|
||||
• Creating / destroying threads.
|
||||
• rdtsc for timing
|
||||
• Thread primitives (Mutex, Semaphore, etc.)
|
||||
• Thread Creation / Deletion
|
||||
[ ] CreateWindow and other Windows-specific features for handling messaging.
|
||||
[ ] Context should include links to other living thread data (+ save dead threads in debug mode)
|
||||
|
||||
[ ] push_scratch() macro. (basically an auto_release_temp)
|
||||
[ ] Start removing irrelevant header files (for unity build system)
|
||||
|
||||
[ ] ... Mouse / Keyboard inputs
|
||||
[*] This is the order I want to follow, because I need them in thread context.
|
||||
- Entry point(s) `Entry_Point_Main.cpp`
|
||||
-> We can have a lib_init() instead of a clear entry point for now.
|
||||
-> Switch from library to application once I add an entry point
|
||||
-> See how rjf abstracts his entry points for each platform with TCTX.
|
||||
|
||||
[Design Stuff]
|
||||
[ ] "Primary Thread" <- Main entry point thread
|
||||
[ ] "Secondary Thread" <- does all the heavy lifting for the first thread and synchronizes with the first.
|
||||
[ ] Tertiary threads (launched by secondary thread and awaiting work as assigned by Primary and Secondary threads)
|
||||
[ ] Multi-threaded by default with sync points
|
||||
[ ] Need bindings for Semaphore and Mutex
|
||||
[ ] Does calling SetProcessWorkingSetSize(.., -1, -1) cause the program to crash? Why tho.
|
||||
[ ] Maybe we just shouldn't do this?
|
||||
[ ] *our* program memory usage can be calculated by Stack Size + allocations from GPAllocator + allocations from arena.
|
||||
[ ] I want to be able to create new Windows (instances) of the program that can communicate with one another.
|
||||
I want one program to be the "Main" and always in-tray, and the others to be "child instances"
|
||||
[TODO - Low priority]
|
||||
[ ] Fix implementation so all source is just in .cpp files (including templates), and auto-generate forward declares like Vjekoslav does.
|
||||
[ ] Implement Secure Arenas (with VirtualLock, wiping memory with RtlSecureZeroMemory)
|
||||
[ ] Way to serialize and deserialize settings in Text (I think using binary is a mistake here?).
|
||||
[Project Ideas] - order of operations:
|
||||
[ ] Pushbullet replacement should make it easy to understand how data can be securely moved over the internet via a central server.
|
||||
[ ] Signal replacement
|
||||
[ ](Graphics): How do I create a basic overlay that shows the time, date, cpu/gpu temps, frequency, memory usage all the time and responds to global hotkey to show more info
|
||||
|
||||
[Documentation Notes]
|
||||
Main inspirations for this codebase:
|
||||
(1) jonathan blow & jai compiler project
|
||||
(2) casey muratori and "handmade" approach to software
|
||||
(3) ryan fleury and raddebugger codebase
|
||||
|
||||
Always contemplate your impulses
|
||||
@ -1,6 +1,3 @@
|
||||
#include "Allocator.h"
|
||||
#include "Base_Thread_Context.h"
|
||||
|
||||
void* internal_alloc (s64 size) {
|
||||
Allocator allocator = get_context_allocator();
|
||||
void* result = allocator.proc(Allocator_Mode::ALLOCATE, size, 0, nullptr, allocator.data);
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
|
||||
#include "Base.h"
|
||||
|
||||
#include "error-codes.h"
|
||||
|
||||
enum class Allocator_Mode: s32 {
|
||||
ALLOCATE = 0,
|
||||
RESIZE = 1,
|
||||
@ -103,3 +101,4 @@ template <typename T> T* copy_struct(T* src) {
|
||||
T* dst = New<T>(false);
|
||||
memcpy(dst, src, sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arena.h"
|
||||
#include "Arena_Windows.cpp"
|
||||
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Allocator.h"
|
||||
#include "Base.h"
|
||||
#include "Base_Thread_Context.h"
|
||||
|
||||
#if OS_WINDOWS
|
||||
constexpr u32 ARENA_DEFAULT_COMMIT_PAGE_COUNT = 16; // 16 * 4k page = 64kB
|
||||
constexpr s64 ARENA_DEFAULT_COMMIT_SIZE_BYTES = 65536;
|
||||
@ -99,10 +95,6 @@ void extend_committed_pages (Arena* arena, u8* end);
|
||||
void free_pages_down_to (Arena* arena, s64 pages_to_keep);
|
||||
void arena_delete (Arena* arena);
|
||||
|
||||
// Scoped Macros/Functions for auto_reset and auto_release
|
||||
// usage `Auto_Reset guard(arena);` within a scope.
|
||||
#define auto_reset(x) \
|
||||
Auto_Reset Concat(_auto_reset_guard_, __LINE__)(x)
|
||||
struct Auto_Reset {
|
||||
Arena* arena;
|
||||
u8* starting_point;
|
||||
@ -118,10 +110,6 @@ struct Auto_Reset {
|
||||
}
|
||||
};
|
||||
|
||||
#define auto_release_temp() auto_release(get_temp_allocator());
|
||||
|
||||
#define auto_release(x) \
|
||||
Auto_Release Concat(_auto_release_guard_, __LINE__)(x)
|
||||
struct Auto_Release {
|
||||
Arena* arena;
|
||||
u8* starting_point;
|
||||
@ -138,8 +126,6 @@ struct Auto_Release {
|
||||
}
|
||||
};
|
||||
|
||||
#define push_alignment(x, y) \
|
||||
Push_Alignment Concat(_push_align_guard_, __LINE__)(x, y)
|
||||
struct Push_Alignment { // #rename to Arena_Push_Alignment?
|
||||
Arena* arena;
|
||||
u16 original_alignment;
|
||||
@ -156,24 +142,6 @@ struct Push_Alignment { // #rename to Arena_Push_Alignment?
|
||||
}
|
||||
};
|
||||
|
||||
#define push_arena(x) \
|
||||
Push_Arena Concat(_push_alloc_guard_, __LINE__)(x)
|
||||
struct Push_Arena {
|
||||
Thread_Context* context;
|
||||
Allocator original_allocator;
|
||||
|
||||
Push_Arena(Arena* arena) {
|
||||
Assert(is_valid(arena));
|
||||
context = get_thread_context();
|
||||
Assert(context != nullptr);
|
||||
original_allocator = context->allocator;
|
||||
context->allocator = get_allocator(arena);
|
||||
}
|
||||
|
||||
~Push_Arena() {
|
||||
context->allocator = original_allocator;
|
||||
}
|
||||
};
|
||||
|
||||
// Do this later:
|
||||
// arena_lock_pages :: (using arena: *Arena, start_address: *u8, byte_count: s64)
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Allocator.h"
|
||||
#include "Arena.h"
|
||||
|
||||
constexpr s64 ARRAY_ARENA_START_OFFSET = 64;
|
||||
|
||||
template <typename T>
|
||||
@ -13,6 +10,8 @@ struct ArenaArray { // downcasts to an ArrayView.
|
||||
s64 allocated;
|
||||
Arena* arena; // We can probably assume arena is &Array-32
|
||||
|
||||
ArenaArray() {}
|
||||
|
||||
T& operator[] (s64 index) {
|
||||
#if ARRAY_ENABLE_BOUNDS_CHECKING
|
||||
if (index < 0 || index >= count) { debug_break(); } // index out of bounds
|
||||
@ -124,32 +123,32 @@ template <typename T> force_inline void maybe_grow (ArenaArray<T>& array) {
|
||||
}
|
||||
|
||||
template <typename T> force_inline void array_reserve (ArenaArray<T>& array, s64 desired_item_count) {
|
||||
reserve_internal((ArenaArray<void>&)array, desired_item_count, sizeof(T));
|
||||
reserve_internal((ArenaArray<u8>&)array, desired_item_count, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T> void array_resize (ArenaArray<T>& array, s64 desired_item_count, bool initialize) {
|
||||
s64 old_count = array.count;
|
||||
reserve_internal((ArenaArray<void>&)array, desired_item_count, sizeof(T));
|
||||
reserve_internal((ArenaArray<u8>&)array, desired_item_count, sizeof(T));
|
||||
array.count = desired_item_count;
|
||||
if (initialize) {
|
||||
init_range(array.data, old_count, desired_item_count);
|
||||
}
|
||||
}
|
||||
|
||||
s64 max_array_size (ArenaArray<void>& array) {
|
||||
return reserve_size(array.arena) - sizeof(Arena) - sizeof(ArenaArray<void>);
|
||||
s64 max_array_size (ArenaArray<u8>& array) {
|
||||
return reserve_size(array.arena) - sizeof(Arena) - sizeof(ArenaArray<u8>);
|
||||
}
|
||||
|
||||
void array_arena_realloc (ArenaArray<void>& array, s64 new_size, s64 old_size) {
|
||||
void array_arena_realloc (ArenaArray<u8>& array, s64 new_size, s64 old_size) {
|
||||
Assert(new_size <= max_array_size(array));
|
||||
|
||||
void* array_begin = (void*)array.data;
|
||||
void* result_end = array_begin + new_size;
|
||||
u8* array_begin = (u8*)array.data;
|
||||
void* result_end = (void*)(array_begin + new_size);
|
||||
|
||||
// Check if we need more pages:
|
||||
if (result_end > array.arena.first_uncommitted_page) {
|
||||
if (result_end > array.arena->first_uncommitted_page) {
|
||||
// Critical error if we run out of address space!
|
||||
if (result_end > address_limit(array.arena)) {
|
||||
if (result_end > arena_address_limit(array.arena)) {
|
||||
// #TODO Log error.
|
||||
Assert(false); // Failed to allocate because Arena is full and cannot expand
|
||||
return;
|
||||
@ -159,7 +158,7 @@ void array_arena_realloc (ArenaArray<void>& array, s64 new_size, s64 old_size) {
|
||||
}
|
||||
}
|
||||
|
||||
void reserve_internal (ArenaArray<void>& array, s64 desired_item_count, s64 element_size) {
|
||||
void reserve_internal (ArenaArray<u8>& array, s64 desired_item_count, s64 element_size) {
|
||||
if (desired_item_count <= array.allocated) return;
|
||||
|
||||
array_arena_realloc(array, desired_item_count * element_size, array.allocated * element_size);
|
||||
@ -251,20 +250,3 @@ template <typename T> ArrayView<T> array_copy_as_view (ArenaArray<T>& array) {
|
||||
return view;
|
||||
}
|
||||
|
||||
// [x] initialize_range
|
||||
// [x] max_array_size
|
||||
// [x] maybe_grow
|
||||
// [x] resize
|
||||
// [x] reserve
|
||||
// [x] reserve_internal
|
||||
// [x] array_arena_realloc
|
||||
// [x] reset_keeping_memory
|
||||
// [x] ordered_remove_by_index
|
||||
// [x] unordered_remove_by_index
|
||||
// [x] insert_at
|
||||
// [x] pop
|
||||
// [x] peek
|
||||
// [x] peek_pointer
|
||||
// [x] delete_range
|
||||
// [x] array_copy
|
||||
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
// API in Arena.h
|
||||
#include "Arena.h"
|
||||
#include "Array.h"
|
||||
#include "General_Purpose_Allocator.h"
|
||||
#include <mutex>
|
||||
|
||||
global std::mutex arena_table_mutex;
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
// Strongly influenced by Array.jai in Basic module.
|
||||
#pragma once
|
||||
|
||||
#include "Base.h"
|
||||
#include "Allocator.h"
|
||||
|
||||
// #TODO: Array.h
|
||||
// [x] Set allocations to use context.allocator interface
|
||||
// For now, I'm just disabling alignment:
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
#include "Base.h"
|
||||
|
||||
// #TODO Split these up into platform_base (e.g. Windows_Base, Unix_Base...)
|
||||
@ -175,3 +175,16 @@ force_inline s64 Next_Power_Of_Two(s64 v) {
|
||||
#define ForArrayStartingAt(_it_, _array_, _start_) for (s64 _it_ = _start_; _it_ < (_array_).count; _it_ += 1)
|
||||
#define ForUpTo(_it_, _end_) for (s64 _it_ = 0; _it_ < _end_; _it_ += 1)
|
||||
|
||||
// Scoped Macros/Functions for auto_reset and auto_release
|
||||
// usage `Auto_Reset guard(arena);` within a scope.
|
||||
#define auto_reset(x) \
|
||||
Auto_Reset Concat(_auto_reset_guard_, __LINE__)(x)
|
||||
#define push_allocator(x) Push_Allocator Concat(_push_alloc_guard_, __LINE__)(x)
|
||||
#define push_alignment(x, y) \
|
||||
Push_Alignment Concat(_push_align_guard_, __LINE__)(x, y)
|
||||
#define push_arena(x) \
|
||||
Push_Arena Concat(_push_alloc_guard_, __LINE__)(x)
|
||||
#define auto_release_temp() auto_release(get_temp_allocator());
|
||||
#define auto_release(x) \
|
||||
Auto_Release Concat(_auto_release_guard_, __LINE__)(x)
|
||||
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Base.h"
|
||||
|
||||
// Need to sort out how formatted strings and string builders are allocated
|
||||
// Maybe just use context.allocator?
|
||||
// What about temp strings? use context.temp?
|
||||
|
||||
struct string {
|
||||
s64 count;
|
||||
u8* data;
|
||||
// Construct from a string literal or C-string
|
||||
string () { // default constructor
|
||||
count = 0;
|
||||
data = nullptr;
|
||||
}
|
||||
|
||||
string (char* cstr) {
|
||||
count = strlen(cstr);
|
||||
data = (u8*)cstr;
|
||||
}
|
||||
|
||||
string (s64 _count, char* str) { count = _count; data = (u8*)str; }
|
||||
string (s64 _count, u8* str) { count = _count; data = str; }
|
||||
};
|
||||
|
||||
// ~ API ~ #TODO
|
||||
string copy_string (string str);
|
||||
bool strings_match(string first_string, string second_string);
|
||||
|
||||
// Unicode stuff
|
||||
string wide_to_utf8 (u16* source, s32 length);
|
||||
|
||||
// string string_view(string n_string, int start_index, int view_count);
|
||||
// string copy_string(char* c_string);
|
||||
// void free(string& n_string);
|
||||
|
||||
bool is_valid(string n_string);
|
||||
bool is_c_string(string n_string);
|
||||
|
||||
char* to_c_string(string n_string);
|
||||
|
||||
string format_string(char* format, ...);
|
||||
string string_from_literal(char* literal);
|
||||
@ -1,4 +1,63 @@
|
||||
#include "Base_Thread_Context.h"
|
||||
// See Context_Base in jai, and TCTX in raddebugger:
|
||||
struct Thread_Context {
|
||||
Arena* temp; // Used for temporary allocations, scratch space.
|
||||
Arena* arena; // general purpose local arena
|
||||
|
||||
Allocator allocator;
|
||||
s32 thread_idx;
|
||||
u16 _padding0;
|
||||
u16 GPAllocator_alignment = 16;
|
||||
// Logger logger;
|
||||
// Stack_Trace* stack_trace;
|
||||
// #TODO: other debug information
|
||||
// #TODO:
|
||||
// Array<Thread*> threads_created; // maybe should be linked-list?
|
||||
// Thread* thread_that_created_me = nullptr; // so we can remove from above array
|
||||
// Mutex thread_context_mutex;
|
||||
|
||||
string thread_name;
|
||||
};
|
||||
|
||||
Thread_Context* get_thread_context();
|
||||
|
||||
struct Push_Arena {
|
||||
Thread_Context* context;
|
||||
Allocator original_allocator;
|
||||
|
||||
Push_Arena(Arena* arena) {
|
||||
Assert(is_valid(arena));
|
||||
context = get_thread_context();
|
||||
Assert(context != nullptr);
|
||||
original_allocator = context->allocator;
|
||||
context->allocator = get_allocator(arena);
|
||||
}
|
||||
|
||||
~Push_Arena() {
|
||||
context->allocator = original_allocator;
|
||||
}
|
||||
};
|
||||
|
||||
struct Push_Allocator {
|
||||
Thread_Context* context;
|
||||
Allocator old_allocator;
|
||||
|
||||
Push_Allocator (Allocator new_allocator) {
|
||||
context = get_thread_context();
|
||||
old_allocator = context->allocator;
|
||||
context->allocator = new_allocator;
|
||||
}
|
||||
|
||||
~Push_Allocator () {
|
||||
context->allocator = old_allocator;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Thread-local allocators:
|
||||
PROTOTYPING_API Allocator get_temp_allocator();
|
||||
PROTOTYPING_API Allocator get_context_allocator();
|
||||
|
||||
|
||||
|
||||
// C_LINKAGE thread_static TCTX* tctx_thread_local;
|
||||
thread_static Thread_Context* thread_local_context;
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Allocator.h"
|
||||
#include "Base.h"
|
||||
// #include "Arena.h"
|
||||
|
||||
struct Arena; // #TEMP - Base_Thread_Context and Arena rely on each other, so I have to figure out how to make this less messy (maybe with meta-generated forward declares?)
|
||||
|
||||
// See Context_Base in jai, and TCTX in raddebugger:
|
||||
struct Thread_Context {
|
||||
Arena* temp; // Used for temporary allocations, scratch space.
|
||||
Arena* arena; // general purpose local arena
|
||||
|
||||
Allocator allocator;
|
||||
s32 thread_idx;
|
||||
u16 _padding0;
|
||||
u16 GPAllocator_alignment = 16;
|
||||
// Logger logger;
|
||||
// Stack_Trace* stack_trace;
|
||||
// #TODO: other debug information
|
||||
// #TODO:
|
||||
// Array<Thread*> threads_created; // maybe should be linked-list?
|
||||
// Thread* thread_that_created_me = nullptr; // so we can remove from above array
|
||||
// Mutex thread_context_mutex;
|
||||
|
||||
string thread_name;
|
||||
};
|
||||
|
||||
Thread_Context* get_thread_context();
|
||||
|
||||
// maybe should append line number to guard?
|
||||
// This is stupid, and maybe should be something generated by a metaprogram?
|
||||
#define push_allocator(x) Push_Allocator Concat(_push_alloc_guard_, __LINE__)(x)
|
||||
struct Push_Allocator {
|
||||
Thread_Context* context;
|
||||
Allocator old_allocator;
|
||||
|
||||
Push_Allocator (Allocator new_allocator) {
|
||||
context = get_thread_context();
|
||||
old_allocator = context->allocator;
|
||||
context->allocator = new_allocator;
|
||||
}
|
||||
|
||||
~Push_Allocator () {
|
||||
context->allocator = old_allocator;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Thread-local allocators:
|
||||
PROTOTYPING_API Allocator get_temp_allocator();
|
||||
PROTOTYPING_API Allocator get_context_allocator();
|
||||
// PROTOTYPING_API void reset_temp_allocator();
|
||||
// PROTOTYPING_API void free_temp_allocator();
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
#include "General_Purpose_Allocator.h"
|
||||
#include "Basic.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "error-codes.h"
|
||||
#include "Array.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -145,4 +142,4 @@ struct Complex32 { f32 real; f32 imag; };
|
||||
|
||||
Complex exponential (Complex cx);
|
||||
Complex conjugate (Complex cx);
|
||||
f64 fabs(Complex cx);
|
||||
f64 fabs (Complex cx);
|
||||
|
||||
@ -1,4 +1,57 @@
|
||||
#include "error-codes.h"
|
||||
enum ErrorSeverity: s32 {
|
||||
SEVERITY_WARNING = 0,
|
||||
SEVERITY_NON_FATAL = 1,
|
||||
SEVERITY_FATAL = 2
|
||||
};
|
||||
|
||||
// typedef struct string Native_Error;
|
||||
// Note: Native_Error should down-cast to a string.
|
||||
struct Native_Error {
|
||||
s64 count;
|
||||
u8* data;
|
||||
ErrorSeverity severity = SEVERITY_WARNING;
|
||||
};
|
||||
|
||||
#define Null_Pointer_Check(arg) \
|
||||
if (arg == nullptr) { \
|
||||
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is a null pointer.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
|
||||
}
|
||||
|
||||
#define Array_Check(arg) \
|
||||
if (!is_valid(arg)) { \
|
||||
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid array.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
|
||||
}
|
||||
|
||||
#define String_Check(arg) \
|
||||
if (!Is_Valid(arg)) { return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid string.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); }
|
||||
|
||||
#define Error_Check(error) \
|
||||
if (error != nullptr) { \
|
||||
return error; \
|
||||
}
|
||||
|
||||
// An error from which the program cannot continue (e.g. a segmentation fault)
|
||||
#define New_Fatal_Error(message) \
|
||||
New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
||||
|
||||
#define New_Error(message) \
|
||||
New_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
||||
|
||||
#define New_Warning(message) \
|
||||
New_Warning_Internal("%s:%d\n[%s] Warning: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
||||
|
||||
Native_Error* New_Fatal_Error_Internal(char* raw_message, ...);
|
||||
|
||||
Native_Error* New_Error_Internal(char* raw_message, ...);
|
||||
|
||||
Native_Error* New_Warning_Internal(char* raw_message, ...);
|
||||
|
||||
Native_Error* Native_Error_Callstack(Native_Error* new_error, Native_Error* old_error, ErrorSeverity severity);
|
||||
|
||||
PROTOTYPING_API C_API Native_Error* Cleanup_Error(Native_Error* error);
|
||||
|
||||
PROTOTYPING_API C_API Native_Error* Native_Error_Test();
|
||||
|
||||
|
||||
#include "General_Purpose_Allocator.h"
|
||||
#include <stdio.h> // vsnprintf, printf
|
||||
@ -12,7 +65,7 @@
|
||||
Native_Error* Create_New_Native_Error_Internal(char* format, va_list args) {
|
||||
constexpr s64 ERROR_BUFFER_COUNT = 512;
|
||||
|
||||
push_allocator(GPAllocator());
|
||||
// push_allocator(GPAllocator());
|
||||
|
||||
auto error = New<Native_Error>(false);
|
||||
error->data = (u8*)GPAllocator_New(ERROR_BUFFER_COUNT);
|
||||
@ -44,7 +97,7 @@ Native_Error* New_Fatal_Error_Internal(char* format, ...) {
|
||||
}
|
||||
|
||||
Native_Error* Native_Error_Callstack(Native_Error* new_error, Native_Error* old_error, ErrorSeverity severity) {
|
||||
push_allocator(GPAllocator());
|
||||
// push_allocator(GPAllocator());
|
||||
|
||||
auto error_message = format_string("%s\n > %s", new_error->data, old_error->data).data;
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
#include "General_Purpose_Allocator.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if GP_ALLOCATOR_TRACK_ALLOCATIONS
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Base.h"
|
||||
#include "Array.h"
|
||||
|
||||
#define GP_ALLOCATOR_TRACK_ALLOCATIONS BUILD_DEBUG
|
||||
#define GP_ALLOCATOR_VERY_DEBUG 0
|
||||
|
||||
|
||||
@ -1,6 +1,46 @@
|
||||
// #TODO: Integrate Allocator / context.allocator
|
||||
|
||||
#include "Base_String.h"
|
||||
|
||||
// Need to sort out how formatted strings and string builders are allocated
|
||||
// Maybe just use context.allocator?
|
||||
// What about temp strings? use context.temp?
|
||||
|
||||
struct string {
|
||||
s64 count;
|
||||
u8* data;
|
||||
// Construct from a string literal or C-string
|
||||
string () { // default constructor
|
||||
count = 0;
|
||||
data = nullptr;
|
||||
}
|
||||
|
||||
string (char* cstr) {
|
||||
count = strlen(cstr);
|
||||
data = (u8*)cstr;
|
||||
}
|
||||
|
||||
string (s64 _count, char* str) { count = _count; data = (u8*)str; }
|
||||
string (s64 _count, u8* str) { count = _count; data = str; }
|
||||
};
|
||||
|
||||
// ~ API ~ #TODO
|
||||
string copy_string (string str);
|
||||
bool strings_match(string first_string, string second_string);
|
||||
|
||||
// Unicode stuff
|
||||
string wide_to_utf8 (u16* source, s32 length);
|
||||
|
||||
// string string_view(string n_string, int start_index, int view_count);
|
||||
// string copy_string(char* c_string);
|
||||
// void free(string& n_string);
|
||||
|
||||
bool is_valid(string n_string);
|
||||
bool is_c_string(string n_string);
|
||||
|
||||
char* to_c_string(string n_string);
|
||||
|
||||
string format_string(char* format, ...);
|
||||
string string_from_literal(char* literal);
|
||||
|
||||
#include "General_Purpose_Allocator.h"
|
||||
#include <stdio.h> // vsnprintf
|
||||
@ -107,4 +147,5 @@ string wide_to_utf8 (u16* source, s32 length) {
|
||||
}
|
||||
|
||||
return utf8_string;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Base.h"
|
||||
|
||||
enum ErrorSeverity: s32 {
|
||||
SEVERITY_WARNING = 0,
|
||||
SEVERITY_NON_FATAL = 1,
|
||||
SEVERITY_FATAL = 2
|
||||
};
|
||||
|
||||
#include "Base_String.h"
|
||||
// typedef struct string Native_Error;
|
||||
// Note: Native_Error should down-cast to a string.
|
||||
struct Native_Error {
|
||||
s64 count;
|
||||
u8* data;
|
||||
ErrorSeverity severity = SEVERITY_WARNING;
|
||||
};
|
||||
|
||||
#define Null_Pointer_Check(arg) \
|
||||
if (arg == nullptr) { \
|
||||
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is a null pointer.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
|
||||
}
|
||||
|
||||
#define Array_Check(arg) \
|
||||
if (!is_valid(arg)) { \
|
||||
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid array.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
|
||||
}
|
||||
|
||||
#define String_Check(arg) \
|
||||
if (!Is_Valid(arg)) { return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid string.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); }
|
||||
|
||||
#define Error_Check(error) \
|
||||
if (error != nullptr) { \
|
||||
return error; \
|
||||
}
|
||||
|
||||
// An error from which the program cannot continue (e.g. a segmentation fault)
|
||||
#define New_Fatal_Error(message) \
|
||||
New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
||||
|
||||
#define New_Error(message) \
|
||||
New_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
||||
|
||||
#define New_Warning(message) \
|
||||
New_Warning_Internal("%s:%d\n[%s] Warning: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
||||
|
||||
Native_Error* New_Fatal_Error_Internal(char* raw_message, ...);
|
||||
|
||||
Native_Error* New_Error_Internal(char* raw_message, ...);
|
||||
|
||||
Native_Error* New_Warning_Internal(char* raw_message, ...);
|
||||
|
||||
Native_Error* Native_Error_Callstack(Native_Error* new_error, Native_Error* old_error, ErrorSeverity severity);
|
||||
|
||||
PROTOTYPING_API C_API Native_Error* Cleanup_Error(Native_Error* error);
|
||||
|
||||
PROTOTYPING_API C_API Native_Error* Native_Error_Test();
|
||||
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Base.h"
|
||||
#include "error-codes.h"
|
||||
|
||||
#include "General_Purpose_Allocator.h"
|
||||
#include "Array.h"
|
||||
#include "Basic.h"
|
||||
|
||||
@ -136,7 +136,7 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
debug_break();
|
||||
// debug_break();
|
||||
|
||||
{ OS_Process_Info* info = &os_state_w32.process_info;
|
||||
DWORD length = GetCurrentDirectoryW(0, 0);
|
||||
|
||||
@ -1,10 +1,20 @@
|
||||
#include "lib/Base/Base.cpp"
|
||||
// This is quite disorganized. There must be a better way to do this by moving the stuff that requires forward declaration to the top
|
||||
// with a metaprogram.
|
||||
|
||||
#include "lib/Base/Base.h"
|
||||
#include "lib/Base/Allocator.h"
|
||||
#include "lib/Base/Array.h"
|
||||
#include "lib/Base/General_Purpose_Allocator.h"
|
||||
#include "lib/Base/Arena.h"
|
||||
#include "lib/Base/Arena_Array.h"
|
||||
|
||||
#include "lib/Base/String.cpp"
|
||||
#include "lib/Base/ErrorCodes.cpp"
|
||||
#include "lib/Base/Arena.cpp"
|
||||
|
||||
#include "lib/Base/Arena_Table.cpp"
|
||||
#include "lib/Base/Base_Thread_Context.cpp"
|
||||
#include "lib/Base/General_Purpose_Allocator.cpp"
|
||||
#include "lib/Base/Allocator.cpp"
|
||||
#include "lib/Base/General_Purpose_Allocator.cpp"
|
||||
#include "lib/Base/Basic.cpp"
|
||||
#include "lib/Base/ErrorCodes.cpp"
|
||||
#include "lib/Base/String.cpp"
|
||||
#include "lib/Base/Timing.cpp"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user