mirror of
https://github.com/fairyglade/ly
synced 2024-11-08 01:10:41 +00:00
78 lines
3.0 KiB
Markdown
78 lines
3.0 KiB
Markdown
# Dragonfail
|
|
Dragonfail is a simple library providing basic error handling functionnalities.
|
|
It was designed to be as lightweight as possible, and can be completely disabled
|
|
with only one `#define` (more on that later).
|
|
|
|
Dragonfail was designed to be fast and uses inline functions exclusively. These
|
|
calls modify a global context which is not directly accessible by the programmer.
|
|
|
|
All the error codes must be written in an enum in **your** `dragonfail_error.h` file.
|
|
Because of this rather unusual architecture, the file must be found by the compiler
|
|
when it is processing `dragonfail.c` (in addition to your own source code of course).
|
|
|
|
## Testing
|
|
Run `make` to compile an example, and `make run` to execute it.
|
|
|
|
## Defines
|
|
This header can also contain some `#define` to modify dragonfail's behaviour:
|
|
- `DRAGONFAIL_SKIP` completely disables the whole library, making it completely
|
|
disappear from the binary (unless your compiler is a massive douche).
|
|
- `DRAGONFAIL_BASIC_LOG` enables the `dgn_basic_log()` function calls
|
|
- `DRAGONFAIL_THROW_BASIC_LOG` makes `dgn_throw()` call `dgn_basic_log()` automatically
|
|
- `DRAGONFAIL_THROW_DEBUG_LOG` also prints the file and line in which
|
|
`dgn_throw()` is called (you don't even need to compile with symbols
|
|
because this is achieved the smart way using simple C99 macros)
|
|
- `DRAGONFAIL_ABORT` makes `dgn_throw()` call `abort()`
|
|
|
|
Again, these `#define` must be placed in **your** `dragonfail_error.h` file.
|
|
|
|
## Using
|
|
### TL;DR
|
|
see the `example` folder :)
|
|
|
|
### Documentation
|
|
```
|
|
char** dgn_init();
|
|
```
|
|
This intializes the context to `DGN_OK` (no error) and returns the array of strings
|
|
you can fill with log messages corresponding to the errors you added in the enum.
|
|
|
|
```
|
|
void dgn_reset();
|
|
```
|
|
This resets the context to `DGN_OK`.
|
|
|
|
```
|
|
void dgn_basic_log();
|
|
```
|
|
This prints the message corresponding to the current error to stderr.
|
|
|
|
```
|
|
void dgn_throw(enum dgn_error new_code);
|
|
```
|
|
This sets the error to the given code.
|
|
|
|
```
|
|
char dgn_catch();
|
|
```
|
|
This returns true if the context currently holds an error
|
|
|
|
## Why is the architecture so strange?
|
|
The dragonfail context is global (extern) but really *implemented* in `dragonfail.c`.
|
|
Its type depends on the size of the enum so it is *declared* in `dragonfail_private.h`:
|
|
this way we can include the user's `dragonfail_error.h` and get `DGN_SIZE`.
|
|
|
|
The inline functions need to access this context and **we want it private**, so we can't
|
|
*implement* them directly in the header as a lot of people seem to appreciate. Instead,
|
|
we will *declare* them here, and put the *implementations* in `dragonfail.c`: this way
|
|
we can access the global context without including its declaration, because it is
|
|
implemented here as well.
|
|
|
|
When you include `dragonfail.h`, you get access to the inline functions declarations
|
|
and thanks to this design any compiler will do the rest of the job automatically. Yes,
|
|
this whole thing is useless and over-engineered. And yes, I had fun doing it...
|
|
|
|
## Greetings
|
|
Jinjer for the cool music \m/
|
|
Haiku developers for indirectly giving me the idea
|