implemented Error struct

This commit is contained in:
Timerix 2025-07-21 17:57:28 +03:00
parent 8999fda11c
commit ba7a81d205
3 changed files with 96 additions and 18 deletions

View File

@ -7,14 +7,14 @@ typedef struct List {
u32 allocated_size; u32 allocated_size;
} List; } List;
#define List_construct(L, T, OCCUPIED_COUNT, ALLOCATED_COUNT) \ #define List_construct(DATA_PTR, T, OCCUPIED_COUNT, ALLOCATED_COUNT) \
List_construct_size(L, (OCCUPIED_COUNT) * sizeof(T), (ALLOCATED_COUNT) * sizeof(T)) List_construct_size(DATA_PTR, (OCCUPIED_COUNT) * sizeof(T), (ALLOCATED_COUNT) * sizeof(T))
static inline List List_construct_size(void* data_ptr, u32 size, u32 allocated_size) { static inline List List_construct_size(void* data_ptr, u32 occupied_size, u32 allocated_size) {
return (List){ .data = data_ptr, .size = size, .allocated_size = allocated_size }; return (List){ .data = data_ptr, .size = occupied_size, .allocated_size = allocated_size };
} }
#define List_alloc(L, T, INITIAL_COUNT) List_alloc_size(L, (INITIAL_COUNT) * sizeof(T)) #define List_alloc(T, INITIAL_COUNT) List_alloc_size((INITIAL_COUNT) * sizeof(T))
List List_alloc_size(u32 initial_size); List List_alloc_size(u32 initial_size);
void* List_expand(List* ptr, u32 expansion_size); void* List_expand(List* ptr, u32 expansion_size);

View File

@ -1,9 +1,34 @@
#pragma once #pragma once
#include "std.h" #include "std.h"
#include "string/cstr.h" #include "string/str.h"
#include "collections/List.h"
typedef struct ErrorCallPos {
i32 line;
str file;
str func;
} ErrorCallPos;
#define ErrorCallPos_here() (ErrorCallPos){\
.line = __LINE__,\
.file = str_construct((char*)(void*)__FILE__, sizeof(__FILE__), true),\
.func = str_construct((char*)(void*)__func__, sizeof(__func__), true)\
}
typedef struct Error {
str msg;
bool is_msg_on_heap;
/* List<ErrorCallPos> */
List call_stack;
} Error;
Error* Error_create(const char* msg, bool is_msg_on_heap, ErrorCallPos);
void Error_destroy(Error* e);
void Error_addCallPos(Error* e, ErrorCallPos p);
str Error_toStr(Error* e);
void Error_printAndExit(Error* e) __attribute__ ((__noreturn__));
typedef struct Result_ { typedef struct Result_ {
cstr error; Error* error;
union { union {
u64 v_u64; u64 v_u64;
i64 v_i64; i64 v_i64;
@ -15,12 +40,22 @@ typedef struct Result_ {
#define Result(T) Result_ #define Result(T) Result_
char* _genErrorMessage(cstr file, i32 line, cstr func, char* msg, bool free_msg);
#define RESULT_ERROR(MSG, IS_MSG_ON_HEAP) (Result_){ .error = Error_create(MSG, IS_MSG_ON_HEAP, ErrorCallPos_here()) }
#define _genErrorMessageHere(MSG, FREE_MSG) \
_genErrorMessage(__FILE__, __LINE__, __func__, MSG, FREE_MSG)
#define RESULT_ERROR(MSG, FREE_MSG) (Result_){ .error = _genErrorMessageHere(MSG, FREE_MSG) }
#define RESULT_VOID (Result_){ .error = NULL } #define RESULT_VOID (Result_){ .error = NULL }
#define RESULT_VALUE(TYPE, V) (Result_){ .error = NULL, .v_##TYPE = V } #define RESULT_VALUE(TYPE, V) (Result_){ .error = NULL, .v_##TYPE = V }
#define try(VAR, RSLT_CALL, DEFER_CODE) \
Result_ VAR = RSLT_CALL;\
if(VAR.error){\
Error_addCallPos(VAR.error, ErrorCallPos_here());\
DEFER_CODE;\
return VAR;\
};
#define try_fatal(VAR, RSLT_CALL, DEFER_CODE) \
Result_ VAR = RSLT_CALL;\
if(VAR.error){\
DEFER_CODE;\
Error_printAndExit(VAR.error);\
};

View File

@ -1,10 +1,53 @@
#include "tlibc/errors.h" #include "tlibc/errors.h"
#include "tlibc/string/StringBuilder.h"
#define ERRMSG_LENGTH 1024 #define ERRMSG_LENGTH 1024
char* _genErrorMessage(cstr file, i32 line, cstr func, char* msg, bool free_msg){ Error* Error_create(const char* msg, bool is_msg_on_heap, ErrorCallPos){
char* result = sprintf_malloc(1024, "[%s:%i] %s() throwed error: %s", file, line, func, msg); Error* e = (Error*)malloc(sizeof(Error));
if(free_msg) e->msg = str_construct((char*)(void*)msg, strlen(msg), true);
free(msg); e->is_msg_on_heap = is_msg_on_heap;
return result; e->call_stack = List_alloc(ErrorCallPos, 1);
return e;
}
void Error_destroy(Error* e){
if(e->is_msg_on_heap)
free(e->msg.data);
free(e->call_stack.data);
}
void Error_addCallPos(Error* e, ErrorCallPos p){
List_push(&e->call_stack, ErrorCallPos, p);
}
str Error_toStr(Error* e){
u32 len = List_len(&e->call_stack, ErrorCallPos);
StringBuilder b = StringBuilder_alloc(e->msg.size + 80 * len);
StringBuilder_append_str(&b, STR("Error: "));
StringBuilder_append_str(&b, e->msg);
for(u32 i = 0; i < len; i++){
ErrorCallPos* ep = (ErrorCallPos*)e->call_stack.data + i;
StringBuilder_append_str(&b, STR("\n at "));
StringBuilder_append_str(&b, ep->file);
StringBuilder_append_char(&b, ':');
StringBuilder_append_i64(&b, ep->line);
StringBuilder_append_char(&b, ' ');
StringBuilder_append_str(&b, ep->func);
StringBuilder_append_str(&b, STR("()\n"));
}
return StringBuilder_getStr(&b);
}
void Error_printAndExit(Error* e){
Error_addCallPos(e, ErrorCallPos_here());\
str e_str = Error_toStr(e);
printfe("%s\n", e_str.data);
free(e_str.data);
Error_destroy(e);
free(e);
exit(111);
} }