130 lines
3.4 KiB
C
130 lines
3.4 KiB
C
/**
|
|
* Copyright (c) 2025 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "assert/assert.h"
|
|
#include "error.h"
|
|
#include "util/memory.h"
|
|
#include "util/string.h"
|
|
|
|
errorret_t errorThrowImpl(
|
|
errorstate_t *state,
|
|
errorcode_t code,
|
|
const char_t *file,
|
|
const char_t *function,
|
|
const int32_t line,
|
|
const char_t *message,
|
|
...
|
|
) {
|
|
assertNotNull(state, "Error state cannot be NULL");
|
|
assertTrue(code != ERROR_OK, "Error code must not be OK");
|
|
assertNotNull(file, "File cannot be NULL");
|
|
assertNotNull(function, "Function cannot be NULL");
|
|
assertTrue(line >= 0, "File pointer must be valid");
|
|
assertNotNull(message, "Message cannot be NULL");
|
|
|
|
memoryZero(state, sizeof(errorstate_t));
|
|
state->code = code;
|
|
|
|
// Format args.
|
|
va_list args;
|
|
va_start(args, message);
|
|
|
|
// Get length of formatted message
|
|
va_list argsCopy;
|
|
va_copy(argsCopy, args);
|
|
int32_t len = stringFormatVA(NULL, 0, message, argsCopy);
|
|
va_end(argsCopy);
|
|
|
|
// Create string to hold the formatted message
|
|
state->message = (char_t *)memoryAllocate(len + 1);
|
|
stringFormatVA(state->message, len + 1, message, args);
|
|
va_end(args);
|
|
|
|
// Format lines
|
|
len = stringFormat(NULL, 0, ERROR_LINE_FORMAT, file, line, function);
|
|
assertTrue(len >= 0, "Line formatting failed");
|
|
state->lines = (char_t *)memoryAllocate(len + 1);
|
|
stringFormat(state->lines, len + 1, ERROR_LINE_FORMAT, file, line, function);
|
|
|
|
return (errorret_t) {
|
|
.code = code,
|
|
.state = state
|
|
};
|
|
}
|
|
|
|
errorret_t errorOkImpl() {
|
|
assertTrue(
|
|
ERROR_STATE.code == ERROR_OK,
|
|
"Global error state is not OK (Likely missing errorCatch)"
|
|
);
|
|
|
|
return (errorret_t) {
|
|
.code = ERROR_OK,
|
|
.state = NULL
|
|
};
|
|
}
|
|
|
|
errorret_t errorChainImpl(
|
|
const errorret_t retval,
|
|
const char_t *file,
|
|
const char_t *function,
|
|
const int32_t line
|
|
) {
|
|
if (retval.code == ERROR_OK) return retval;
|
|
|
|
assertNotNull(retval.state, "Error state NULL (Likely missing errorOk)");
|
|
assertNotNull(retval.state->message, "Message cannot be NULL");
|
|
|
|
// Create a new line string.
|
|
int32_t newLineLen = snprintf(NULL, 0, ERROR_LINE_FORMAT, file, line, function);
|
|
assertTrue(newLineLen >= 0, "Line formatting failed");
|
|
char_t *newLine = (char_t *)memoryAllocate(newLineLen + 1);
|
|
snprintf(newLine, newLineLen + 1, ERROR_LINE_FORMAT, file, line, function);
|
|
|
|
// Resize the existing lines to accommodate the new line
|
|
size_t existingLen = strlen(retval.state->lines);
|
|
memoryResize(
|
|
(void**)&retval.state->lines,
|
|
existingLen,
|
|
existingLen + newLineLen + 1
|
|
);
|
|
|
|
// Now append the new line to the existing lines
|
|
memoryCopy(
|
|
retval.state->lines + existingLen,
|
|
newLine,
|
|
newLineLen + 1
|
|
);
|
|
|
|
// Cleanup the temporary new line
|
|
memoryFree(newLine);
|
|
return retval;
|
|
}
|
|
|
|
void errorCatch(const errorret_t retval) {
|
|
if (retval.code == ERROR_OK) return;
|
|
|
|
assertNotNull(retval.state, "Error state cannot be NULL");
|
|
assertNotNull(retval.state->message, "Message cannot be NULL");
|
|
|
|
memoryFree((void*)retval.state->message);
|
|
}
|
|
|
|
errorret_t errorPrint(const errorret_t retval) {
|
|
if (retval.code == ERROR_OK) return retval;
|
|
|
|
assertNotNull(retval.state, "Error state cannot be NULL");
|
|
assertNotNull(retval.state->message, "Message cannot be NULL");
|
|
|
|
printf(
|
|
ERROR_PRINT_FORMAT,
|
|
retval.state->code,
|
|
retval.state->message,
|
|
retval.state->lines
|
|
);
|
|
return retval;
|
|
} |