Banjo API 0.0.1
C99 game development API
Loading...
Searching...
No Matches
Error Management

Macros

#define bj_error_code_kind(code)
#define bj_error_code_is_user(code)

Enumerations

enum  bj_error_code {
  BJ_ERROR_NONE = 0x00000000 , BJ_ERROR = 0x00000001 , BJ_ERROR_UNSUPPORTED = 0x00000101 , BJ_ERROR_NOT_IMPLEMENTED = 0x00000201 ,
  BJ_ERROR_SYSTEM = 0x00000002 , BJ_ERROR_FILE_NOT_FOUND = 0x00000102 , BJ_ERROR_CANNOT_ALLOCATE = 0x00000202 , BJ_ERROR_INITIALIZE = 0x00000302 ,
  BJ_ERROR_DISPOSE = 0x00000402 , BJ_ERROR_IO = 0x00000003 , BJ_ERROR_CANNOT_READ = 0x00000103 , BJ_ERROR_CANNOT_WRITE = 0x00000203 ,
  BJ_ERROR_INVALID_DATA = 0x00000004 , BJ_ERROR_INVALID_FORMAT = 0x00000104 , BJ_ERROR_INCORRECT_VALUE = 0x00000204 , BJ_ERROR_VIDEO = 0x00000005 ,
  BJ_ERROR_AUDIO = 0x00000006
}

Functions

void bj_set_error (struct bj_error **error, uint32_t code, const char *message)
void bj_set_error_fmt (struct bj_error **error, uint32_t code, const char *format,...)
void bj_propagate_error (struct bj_error **dest, struct bj_error *src)
void bj_propagate_prefixed_error (struct bj_error **dest, struct bj_error *src, const char *format,...)
void bj_prefix_error (struct bj_error **error, const char *prefix)
void bj_prefix_error_fmt (struct bj_error **error, const char *format,...)
struct bj_errorbj_copy_error (const struct bj_error *error)
void bj_clear_error (struct bj_error **error)
bj_bool bj_error_matches (const struct bj_error *error, uint32_t code)
bj_bool bj_error_matches_kind (const struct bj_error *error, uint32_t kind)
uint32_t bj_error_code (const struct bj_error *error)
const char * bj_error_message (const struct bj_error *error)

Detailed Description

Recoverable error handling facilities.

This API provides a mechanism for communicating recoverable errors from callee to caller, inspired by GLib's GError system.

Basic Usage

Functions that may fail take a bj_error** as their last parameter. Pass a pointer to a NULL bj_error* to receive error details:

int main(int argc, char* argv[]) {
(void)argc;
(void)argv;
bj_info("=== Basic Error Handling ===");
// To receive error information, pass a pointer to a NULL bj_error*
bj_error* error = 0;
initialize_server("/etc/myapp.conf", 8080, &error);
if (error != 0) {
// The error message now includes context from the call chain
bj_err("Startup failed: %s", bj_error_message(error));
// Always clear errors when done to free memory
bj_clear_error(&error);
}
bj_info("\n=== Error Matching ===");
bj_info("\n=== Error Copying ===");
bj_info("\n=== Zero-Cost Path ===");
return 0;
}

Returning Errors

Use bj_set_error or bj_set_error_fmt from inside a function that may fail:

// Functions that can fail take a bj_error** as their last parameter.
// Use bj_set_error for literal messages.
void load_config_file(const char* path, bj_error** error) {
(void)path;
// Simulate a failure
int file_exists = 0;
if (!file_exists) {
bj_set_error(error, BJ_ERROR_FILE_NOT_FOUND, "configuration file missing");
return;
}
// ... normal processing ...
}
// Use bj_set_error_fmt for formatted messages with runtime values.
void open_network_port(int port, bj_error** error) {
// Simulate a failure
int port_available = 0;
if (!port_available) {
"port %d is already in use", port);
return;
}
// ... normal processing ...
}

Error Propagation

When calling a fallible function from another fallible function, use bj_propagate_error to forward errors up the call stack:

bj_error* local_err = NULL;
some_operation(&local_err);
if (local_err != NULL) {
bj_propagate_error(error, local_err);
return;
}
struct bj_error bj_error
Definition api.h:275
void bj_propagate_error(struct bj_error **dest, struct bj_error *src)
Propagates an error to the caller's error location.

Adding Context

Use bj_prefix_error to add context to an existing error:

if (local_err != NULL) {
bj_prefix_error(&local_err, "While loading config: ");
bj_propagate_error(error, local_err);
return;
}
void bj_prefix_error(struct bj_error **error, const char *prefix)
Adds a prefix to an existing error's message.

Zero-Cost When Unused

Passing NULL for the error parameter indicates you don't care about error details. In this case, no allocation occurs - just a pointer check.

Macro Definition Documentation

◆ bj_error_code_is_user

#define bj_error_code_is_user ( code)
Value:
(((code) >> 24) & 0xFFu)

Checks if an error code is user-defined (not from Banjo).

Banjo error codes have their most significant byte set to 0x00. User applications can use non-zero values in the MSB to define their own error codes without conflicting with Banjo.

Parameters
codeThe error code to check.
Returns
Non-zero if the error is user-defined, zero if it's a Banjo error.

◆ bj_error_code_kind

#define bj_error_code_kind ( code)
Value:
((code) & 0x000000FFu)

Extracts the kind (category) from an error code.

The kind is the least significant byte, shared by all errors in the same category. For example:

#define bj_error_code_kind(code)
Extracts the kind (category) from an error code.
Definition error.h:151
@ BJ_ERROR_CANNOT_ALLOCATE
Memory allocation failed.
Definition error.h:107
@ BJ_ERROR_SYSTEM
Generic operating system error.
Definition error.h:103
@ BJ_ERROR_INVALID_DATA
Generic invalid data error.
Definition error.h:123
@ BJ_ERROR_INVALID_FORMAT
Data format does not match expected format.
Definition error.h:125
Parameters
codeThe error code to extract the kind from.
Returns
The kind portion of the error code.

Enumeration Type Documentation

◆ bj_error_code

A numeric representation of an error in Banjo.

Error codes are 32-bit values with a hierarchical structure:

+----------+------------------+------------+
| Origin | Specific Code | Kind |
| (8 bits) | (16 bits) | (8 bits) |
+----------+------------------+------------+
MSB LSB
  • Origin (MSB): 0x00 for Banjo errors, non-zero for user-defined.
  • Specific Code: Unique identifier within the kind.
  • Kind (LSB): Category shared by related errors.

For example, BJ_ERROR_INCORRECT_VALUE is 0x00000204:

  • Origin: 0x00 (Banjo)
  • Specific: 0x0002
  • Kind: 0x04 (same as BJ_ERROR_INVALID_DATA)

Use bj_error_code_kind to extract the kind from any error code. Use bj_error_code_is_user to check if an error is user-defined.

Enumerator
BJ_ERROR_NONE 

No error occurred.

BJ_ERROR 

General unspecified error.

BJ_ERROR_UNSUPPORTED 

Operation not supported on this platform or configuration.

BJ_ERROR_NOT_IMPLEMENTED 

Feature not yet implemented.

BJ_ERROR_SYSTEM 

Generic operating system error.

BJ_ERROR_FILE_NOT_FOUND 

Requested file was not found.

BJ_ERROR_CANNOT_ALLOCATE 

Memory allocation failed.

BJ_ERROR_INITIALIZE 

System component initialization failed.

BJ_ERROR_DISPOSE 

System component cleanup failed.

BJ_ERROR_IO 

Generic I/O error.

BJ_ERROR_CANNOT_READ 

Error while reading from a file or stream.

BJ_ERROR_CANNOT_WRITE 

Error while writing to a file or stream.

BJ_ERROR_INVALID_DATA 

Generic invalid data error.

BJ_ERROR_INVALID_FORMAT 

Data format does not match expected format.

BJ_ERROR_INCORRECT_VALUE 

Value does not match expected value.

BJ_ERROR_VIDEO 

Error in video/graphics subsystem.

BJ_ERROR_AUDIO 

Error in audio subsystem.

Examples
handling_errors.c.

Function Documentation

◆ bj_clear_error()

void bj_clear_error ( struct bj_error ** error)

Frees an error and sets the pointer to NULL.

Safe to call with a NULL pointer or pointer to NULL.

bj_clear_error(&err); // err is now NULL
bj_clear_error(&err); // Safe, does nothing
void bj_clear_error(struct bj_error **error)
Frees an error and sets the pointer to NULL.
Parameters
errorPointer to error to free.
Examples
handling_errors.c.

◆ bj_copy_error()

struct bj_error * bj_copy_error ( const struct bj_error * error)

Creates a copy of an error.

Returns a newly allocated error with the same code and message. The caller owns the copy and must free it with bj_clear_error.

Parameters
errorThe error to copy. May be NULL.
Returns
A new error copy, or NULL if error was NULL.
Examples
handling_errors.c.

◆ bj_error_code()

uint32_t bj_error_code ( const struct bj_error * error)

Gets the error code from an error object.

Parameters
errorThe error to query. May be NULL.
Returns
The error code, or BJ_ERROR_NONE if error is NULL.

◆ bj_error_matches()

bj_bool bj_error_matches ( const struct bj_error * error,
uint32_t code )

Checks if an error matches a specific error code.

Returns true if error is non-NULL and has the specified code. Use this for exact matching of error codes.

// Handle missing file specifically
}
bj_bool bj_error_matches(const struct bj_error *error, uint32_t code)
Checks if an error matches a specific error code.
@ BJ_ERROR_FILE_NOT_FOUND
Requested file was not found.
Definition error.h:105
Parameters
errorThe error to check. May be NULL.
codeThe error code to match against.
Returns
BJ_TRUE if error matches the code, BJ_FALSE otherwise.
See also
bj_error_matches_kind For matching Error Management categories.
Examples
handling_errors.c.

◆ bj_error_matches_kind()

bj_bool bj_error_matches_kind ( const struct bj_error * error,
uint32_t kind )

Checks if an error belongs to a specific error kind (category).

Returns true if error is non-NULL and its kind matches the specified kind. Use this to handle categories of errors uniformly.

// Handle any I/O error (read, write, etc.)
}
bj_bool bj_error_matches_kind(const struct bj_error *error, uint32_t kind)
Checks if an error belongs to a specific error kind (category).
@ BJ_ERROR_IO
Generic I/O error.
Definition error.h:115
Parameters
errorThe error to check. May be NULL.
kindThe error kind to match (e.g., BJ_ERROR_IO, BJ_ERROR_SYSTEM).
Returns
BJ_TRUE if error's kind matches, BJ_FALSE otherwise.
Examples
handling_errors.c.

◆ bj_error_message()

const char * bj_error_message ( const struct bj_error * error)

Gets the error message from an error object.

The returned string is owned by the error object and remains valid until the error is freed or modified.

Parameters
errorThe error to query. May be NULL.
Returns
The error message, or NULL if error is NULL.
Examples
handling_errors.c.

◆ bj_prefix_error()

void bj_prefix_error ( struct bj_error ** error,
const char * prefix )

Adds a prefix to an existing error's message.

Prepends text to the error message to add context about where/why the error occurred.

if (err != NULL) {
bj_prefix_error(&err, "In function foo: ");
// Message is now "In function foo: original message"
}

If *error is NULL, this function does nothing.

Parameters
errorPointer to the error to modify.
prefixNull-terminated prefix string.
See also
bj_prefix_error_fmt For formatted prefixes.

◆ bj_prefix_error_fmt()

void bj_prefix_error_fmt ( struct bj_error ** error,
const char * format,
... )

Adds a formatted prefix to an existing error's message.

Like bj_prefix_error, but with printf-style formatting.

bj_prefix_error_fmt(&err, "While processing item %d: ", index);
void bj_prefix_error_fmt(struct bj_error **error, const char *format,...)
Adds a formatted prefix to an existing error's message.
Parameters
errorPointer to the error to modify.
formatPrintf-style format string for the prefix.
...Format arguments.
Examples
handling_errors.c.

◆ bj_propagate_error()

void bj_propagate_error ( struct bj_error ** dest,
struct bj_error * src )

Propagates an error to the caller's error location.

Transfers ownership of src to *dest. After this call, src is consumed and must not be used or freed.

If dest is NULL, the error is logged and freed (caller doesn't want it). If *dest is already non-NULL, src is logged and freed (first error wins).

Typical usage:

bj_error* local_err = NULL;
do_something(&local_err);
if (local_err != NULL) {
bj_propagate_error(error, local_err);
return FAILURE;
}
Parameters
destCaller's error location. May be NULL.
srcError to propagate. Consumed by this call.
See also
bj_propagate_prefixed_error To add context while propagating.
Examples
handling_errors.c.

◆ bj_propagate_prefixed_error()

void bj_propagate_prefixed_error ( struct bj_error ** dest,
struct bj_error * src,
const char * format,
... )

Propagates an error with an added prefix.

Combines bj_prefix_error_fmt and bj_propagate_error in one call. Adds context to the error message before propagating.

bj_propagate_prefixed_error(error, local_err,
"While loading '%s': ", filename);
void bj_propagate_prefixed_error(struct bj_error **dest, struct bj_error *src, const char *format,...)
Propagates an error with an added prefix.
Parameters
destCaller's error location. May be NULL.
srcError to propagate. Consumed by this call.
formatPrintf-style prefix format.
...Format arguments.
Examples
handling_errors.c.

◆ bj_set_error()

void bj_set_error ( struct bj_error ** error,
uint32_t code,
const char * message )

Creates a new error with a literal message.

Allocates and initializes a new error object. Use this when the error message is a compile-time constant or doesn't need formatting.

If *error is already non-NULL, the new error is logged but not stored, preserving the original error (first error wins).

If error is NULL, the error is logged in debug builds but no allocation occurs (zero cost).

Parameters
errorPointer to error location. May be NULL.
codeError code from bj_error_code or user-defined.
messageNull-terminated error message.
See also
bj_set_error_fmt For formatted messages.
bj_clear_error To free the Error Management.
Examples
handling_errors.c.

◆ bj_set_error_fmt()

void bj_set_error_fmt ( struct bj_error ** error,
uint32_t code,
const char * format,
... )

Creates a new error with a formatted message.

Like bj_set_error, but accepts printf-style format arguments.

"Cannot open '%s': %s", path, strerror(errno));
void bj_set_error_fmt(struct bj_error **error, uint32_t code, const char *format,...)
Creates a new error with a formatted message.
Parameters
errorPointer to error location. May be NULL.
codeError code.
formatPrintf-style format string.
...Format arguments.
See also
bj_set_error For literal messages (slightly more efficient).
Examples
handling_errors.c.