Result Library 0.1
Elegant error handling in C
Loading...
Searching...
No Matches
result.h File Reference

A header-only C library to handle errors elegantly. More...

Macros

#define RESULT_VERSION   0
 Returns the major version number of this library.
 
#define RESULT_TAG(success_type_name, failure_type_name)
 Returns the struct tag for results with the supplied success and failure type names.
 
#define RESULT_STRUCT_TAG(success_type, failure_type, struct_tag)
 Declares a result struct with the supplied success and failure types.
 
#define RESULT_STRUCT(success_type, failure_type)
 Declares a result struct with a default tag and the supplied success and failure types.
 
#define RESULT(success_type_name, failure_type_name)
 Returns the type specifier for results with the supplied success and failure type names.
 
#define RESULT_SUCCESS(success)
 Initializes a new successful result containing the supplied value.
 
#define RESULT_FAILURE(failure)
 Initializes a new failed result containing the supplied value.
 
#define RESULT_HAS_SUCCESS(result)
 Checks if a result contains a success value.
 
#define RESULT_HAS_FAILURE(result)
 Checks if a result contains a failure value.
 
#define RESULT_USE_SUCCESS(result)
 Returns a result's success value.
 
#define RESULT_USE_FAILURE(result)
 Returns a result's failure value.
 
#define RESULT_GET_SUCCESS(result)
 Returns a result's success value as a possibly-null pointer.
 
#define RESULT_GET_FAILURE(result)
 Returns a result's failure value as a possibly-null pointer.
 
#define RESULT_OR_ELSE(result, other)
 Returns a result's success value, or the supplied one.
 
#define RESULT_OR_ELSE_MAP(result, failure_mapper)
 Returns a result's success value, or maps its failure value.
 
#define RESULT_IF_SUCCESS(result, action)
 Performs the supplied action with a successful result's value.
 
#define RESULT_IF_FAILURE(result, action)
 Performs the supplied action with a failed result's value.
 
#define RESULT_IF_SUCCESS_OR_ELSE(result, success_action, failure_action)
 Performs either of the supplied actions with a result's value.
 
#define RESULT_FILTER(result, is_acceptable, failure)
 Conditionally transforms a successful result into a failed one.
 
#define RESULT_FILTER_MAP(result, is_acceptable, success_mapper)
 Conditionally transforms a successful result into a failed one, mapping its success value.
 
#define RESULT_RECOVER(result, is_recoverable, success)
 Conditionally transforms a failed result into a successful one.
 
#define RESULT_RECOVER_MAP(result, is_recoverable, failure_mapper)
 Conditionally transforms a failed result into a successful one, mapping its failure value.
 
#define RESULT_MAP_SUCCESS(result, success_mapper, result_type)
 Transforms the value of a successful result.
 
#define RESULT_MAP_FAILURE(result, failure_mapper, result_type)
 Transforms the value of a failed result.
 
#define RESULT_MAP(result, success_mapper, failure_mapper, result_type)
 Transforms either the success or the failure value of a result.
 
#define RESULT_FLAT_MAP_SUCCESS(result, success_mapper)
 Transforms a successful result into a different one.
 
#define RESULT_FLAT_MAP_FAILURE(result, failure_mapper)
 Transforms a failed result into a different one.
 
#define RESULT_FLAT_MAP(result, success_mapper, failure_mapper)
 Transforms a result into a different one.
 
#define RESULT_DEBUG_FUNC(result)
 Returns the function name where a result was created.
 
#define RESULT_DEBUG_FILE(result)
 Returns the source file name where a result was created.
 
#define RESULT_DEBUG_LINE(result)
 Returns the source line number where a result was created.
 

Detailed Description

A header-only C library to handle errors elegantly.

This library consists of one header file only. All you need to do is copy result.h into your project, and include it.

#include <result.h>
A header-only C library to handle errors elegantly.

Since it's a header-only library, there is no library code to link against.

Version
0.1.0
Author
Guillermo Calvo
See also
For more information, visit the project on GitHub

Macro Definition Documentation

◆ RESULT_VERSION

#define RESULT_VERSION   0

Returns the major version number of this library.

◆ RESULT_TAG

#define RESULT_TAG ( success_type_name,
failure_type_name )
Value:
result_of_ ## success_type_name ## _and_ ## failure_type_name

Returns the struct tag for results with the supplied success and failure type names.

For example, a result that can hold either an int success value, or a char failure value, has a struct tag: result_of_int_and_char.

Parameters
success_type_namethe success type name.
failure_type_namethe failure type name.
Returns
the result struct tag.
See also
RESULT_STRUCT_TAG

◆ RESULT_STRUCT_TAG

#define RESULT_STRUCT_TAG ( success_type,
failure_type,
struct_tag )
Value:
struct struct_tag { \
bool _failed; \
union { \
success_type _success; \
failure_type _failure; \
} _value; \
struct { \
const char * _func; \
const char * _file; \
int _line; \
} _debug; \
}

Declares a result struct with the supplied success and failure types.

Precondition
struct_tag SHOULD be generated via RESULT_TAG.
Warning
The exact sequence of members that make up a result struct MUST be considered part of the implementation details. Results SHOULD only be created and accessed using the macros provided in this header file.
Remarks
This macro is useful to declare result structs.
Parameters
success_typethe success type.
failure_typethe failure type.
struct_tagthe struct tag.
Returns
the struct declaration.
See also
RESULT_STRUCT
RESULT_TAG

◆ RESULT_STRUCT

#define RESULT_STRUCT ( success_type,
failure_type )
Value:
success_type, \
failure_type, \
RESULT_TAG(success_type, failure_type) \
)
#define RESULT_STRUCT_TAG(success_type, failure_type, struct_tag)
Declares a result struct with the supplied success and failure types.
Definition result.h:88
#define RESULT_TAG(success_type_name, failure_type_name)
Returns the struct tag for results with the supplied success and failure type names.
Definition result.h:65

Declares a result struct with a default tag and the supplied success and failure types.

Note
The struct tag will be generated via RESULT_TAG.
Remarks
This macro is useful to declare result structs with a default tag.
Parameters
success_typethe success type.
failure_typethe failure type.
Returns
the type definition.
See also
RESULT

◆ RESULT

#define RESULT ( success_type_name,
failure_type_name )
Value:
struct RESULT_TAG(success_type_name, failure_type_name)

Returns the type specifier for results with the supplied success and failure type names.

For example, a result that can hold either an int success value, or a char failure value, has a type specifier: struct result_of_int_and_char.

Note
The struct tag will be generated via RESULT_TAG.
Remarks
This macro is useful to define a variable of that specific type of results.
Parameters
success_type_namethe success type name.
failure_type_namethe failure type name.
Returns
the result type specifier.
See also
RESULT_STRUCT

◆ RESULT_SUCCESS

#define RESULT_SUCCESS ( success)
Value:
{ \
._failed = false, \
._value = { \
._success = success \
}, \
._debug = { \
._func = __func__, \
._file = __FILE__, \
._line = __LINE__ \
} \
}

Initializes a new successful result containing the supplied value.

Parameters
successthe success value.
Returns
the initializer for a successful result holding success.
See also
RESULT_FAILURE

◆ RESULT_FAILURE

#define RESULT_FAILURE ( failure)
Value:
{ \
._failed = true, \
._value = { \
._failure = failure \
}, \
._debug = { \
._func = __func__, \
._file = __FILE__, \
._line = __LINE__ \
} \
}

Initializes a new failed result containing the supplied value.

Parameters
failurethe failure value.
Returns
the initializer for a failed result holding failure.
See also
RESULT_SUCCESS

◆ RESULT_HAS_SUCCESS

#define RESULT_HAS_SUCCESS ( result)
Value:
( !(result)._failed )

Checks if a result contains a success value.

Parameters
resultthe result to check for success.
Returns
true if result is successful; otherwise false.
See also
RESULT_HAS_FAILURE

◆ RESULT_HAS_FAILURE

#define RESULT_HAS_FAILURE ( result)
Value:
( (result)._failed )

Checks if a result contains a failure value.

Parameters
resultthe result to check for failure.
Returns
true if result is failed; otherwise false.
See also
RESULT_HAS_SUCCESS

◆ RESULT_USE_SUCCESS

#define RESULT_USE_SUCCESS ( result)
Value:
( (result)._value._success )

Returns a result's success value.

Precondition
result MUST be successful.
Warning
If result is failed, the appropriate part of the object representation of the failure value is reinterpreted as a success value (a process sometimes called "type punning"), which may be a trap representation.
Parameters
resultthe result to retrieve the success value from.
Returns
result's success value.
See also
RESULT_USE_FAILURE

◆ RESULT_USE_FAILURE

#define RESULT_USE_FAILURE ( result)
Value:
( (result)._value._failure )

Returns a result's failure value.

Precondition
result MUST be failed.
Warning
If result is successful, the appropriate part of the object representation of the success value is reinterpreted as a failure value (a process sometimes called "type punning"), which may be a trap representation.
Parameters
resultthe result to retrieve the failure value from.
Returns
result's failure value.
See also
RESULT_USE_FAILURE

◆ RESULT_GET_SUCCESS

#define RESULT_GET_SUCCESS ( result)
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? NULL \
: &RESULT_USE_SUCCESS(result) \
)
#define RESULT_USE_SUCCESS(result)
Returns a result's success value.
Definition result.h:223

Returns a result's success value as a possibly-null pointer.

Precondition
result MUST be an lvalue.
Parameters
resultthe result to retrieve the success value from.
Returns
a pointer to result's success value if successful; otherwise NULL.
See also
RESULT_GET_FAILURE

◆ RESULT_GET_FAILURE

#define RESULT_GET_FAILURE ( result)
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? &RESULT_USE_FAILURE(result) \
: NULL \
)
#define RESULT_USE_FAILURE(result)
Returns a result's failure value.
Definition result.h:240

Returns a result's failure value as a possibly-null pointer.

Precondition
result MUST be an lvalue.
Parameters
resultthe result to retrieve the failure value from.
Returns
a pointer to result's failure value if failed; otherwise NULL.
See also
RESULT_GET_SUCCESS

◆ RESULT_OR_ELSE

#define RESULT_OR_ELSE ( result,
other )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? (other) \
: RESULT_USE_SUCCESS(result) \
)

Returns a result's success value, or the supplied one.

Precondition
result MUST be an lvalue.
Parameters
resultthe result to retrieve the success value from.
otherthe alternative success value.
Returns
result's success value if successful; otherwise other.
See also
RESULT_OR_ELSE_MAP

◆ RESULT_OR_ELSE_MAP

#define RESULT_OR_ELSE_MAP ( result,
failure_mapper )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? failure_mapper(RESULT_USE_FAILURE(result)) \
: RESULT_USE_SUCCESS(result) \
)

Returns a result's success value, or maps its failure value.

Precondition
result MUST be an lvalue.
Parameters
resultthe result to retrieve the success value from.
failure_mapperthe mapping function or macro that produces the alternative success value.
Returns
result's success value if successful; otherwise the value produced by failure_mapper.
See also
RESULT_OR_ELSE

◆ RESULT_IF_SUCCESS

#define RESULT_IF_SUCCESS ( result,
action )
Value:
do { \
typeof(result) _result = (result); \
if (RESULT_HAS_SUCCESS(_result)) { \
(void) (action(RESULT_USE_SUCCESS(_result))); \
} \
} while(false)
#define RESULT_HAS_SUCCESS(result)
Checks if a result contains a success value.
Definition result.h:195

Performs the supplied action with a successful result's value.

Parameters
resultthe result whose success value will be used.
actionthe function or macro to be applied to result's success value.
See also
RESULT_IF_FAILURE
RESULT_IF_SUCCESS_OR_ELSE

◆ RESULT_IF_FAILURE

#define RESULT_IF_FAILURE ( result,
action )
Value:
do { \
typeof(result) _result = (result); \
if (RESULT_HAS_FAILURE(_result)) { \
(void) (action(RESULT_USE_FAILURE(_result))); \
} \
} while(false)
#define RESULT_HAS_FAILURE(result)
Checks if a result contains a failure value.
Definition result.h:206

Performs the supplied action with a failed result's value.

Parameters
resultthe result whose failure value will be used.
actionthe function or macro to be applied to result's failure value.
See also
RESULT_IF_SUCCESS
RESULT_IF_SUCCESS_OR_ELSE

◆ RESULT_IF_SUCCESS_OR_ELSE

#define RESULT_IF_SUCCESS_OR_ELSE ( result,
success_action,
failure_action )
Value:
do { \
typeof(result) _result = (result); \
if (RESULT_HAS_FAILURE(_result)) { \
(void) (failure_action(RESULT_USE_FAILURE(_result))); \
} else { \
(void) (success_action(RESULT_USE_SUCCESS(_result))); \
} \
} while(false)

Performs either of the supplied actions with a result's value.

Parameters
resultthe result whose value will be used.
success_actionthe function or macro to be applied to result's success value.
failure_actionthe function or macro to be applied to result's failure value.
See also
RESULT_IF_SUCCESS
RESULT_IF_FAILURE

◆ RESULT_FILTER

#define RESULT_FILTER ( result,
is_acceptable,
failure )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
|| is_acceptable(RESULT_USE_SUCCESS(result)) \
? (result) \
: (typeof(result)) RESULT_FAILURE(failure) \
)
#define RESULT_FAILURE(failure)
Initializes a new failed result containing the supplied value.
Definition result.h:174

Conditionally transforms a successful result into a failed one.

Precondition
result MUST be an lvalue.
Parameters
resultthe result to map the success value from.
is_acceptablethe predicate function or macro to apply to the success value.
failurethe failure value if not acceptable.
Returns
if result is successful and its success value is deemed not acceptable, a new failed result holding failure; otherwise, the supplied result.
See also
RESULT_FILTER_MAP

◆ RESULT_FILTER_MAP

#define RESULT_FILTER_MAP ( result,
is_acceptable,
success_mapper )
Value:
result, \
is_acceptable, \
success_mapper(RESULT_USE_SUCCESS(result)) \
)
#define RESULT_FILTER(result, is_acceptable, failure)
Conditionally transforms a successful result into a failed one.
Definition result.h:387

Conditionally transforms a successful result into a failed one, mapping its success value.

Precondition
result MUST be an lvalue.
Parameters
resultthe result to map the success value from.
is_acceptablethe predicate function or macro to apply to the success value.
success_mapperthe mapping function or macro that produces the failure value.
Returns
if result is successful and its value is deemed not acceptable, a new failed result holding the value produced by success_mapper; otherwise, the supplied result.
See also
RESULT_FILTER

◆ RESULT_RECOVER

#define RESULT_RECOVER ( result,
is_recoverable,
success )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
&& is_recoverable(RESULT_USE_FAILURE(result)) \
? (typeof(result)) RESULT_SUCCESS(success) \
: (result) \
)
#define RESULT_SUCCESS(success)
Initializes a new successful result containing the supplied value.
Definition result.h:154

Conditionally transforms a failed result into a successful one.

Precondition
result MUST be an lvalue.
Parameters
resultthe result to map the failure value from.
is_recoverablethe predicate function or macro to apply to the failure value.
successthe success value if recoverable.
Returns
if result is failed and its value is deemed recoverable, a new successful result holding success; otherwise, the supplied result.
See also
RESULT_RECOVER_MAP

◆ RESULT_RECOVER_MAP

#define RESULT_RECOVER_MAP ( result,
is_recoverable,
failure_mapper )
Value:
result, \
is_recoverable, \
failure_mapper(RESULT_USE_FAILURE(result)) \
)
#define RESULT_RECOVER(result, is_recoverable, success)
Conditionally transforms a failed result into a successful one.
Definition result.h:434

Conditionally transforms a failed result into a successful one, mapping its failure value.

Precondition
result MUST be an lvalue.
Parameters
resultthe result to map the failure value from.
is_recoverablethe predicate function or macro to apply to the failure value.
failure_mapperthe mapping function or macro that produces the success value.
Returns
if result is failed and its value is deemed recoverable, a new successful result holding the value produced by failure_mapper; otherwise, the supplied result.
See also
RESULT_RECOVER

◆ RESULT_MAP_SUCCESS

#define RESULT_MAP_SUCCESS ( result,
success_mapper,
result_type )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? (result_type) \
: (result_type) \
RESULT_SUCCESS(success_mapper(RESULT_USE_SUCCESS(result))) \
)

Transforms the value of a successful result.

Precondition
result MUST be an lvalue.
Parameters
resultthe result whose success value will be transformed.
success_mapperthe mapping function or macro that produces the new success value.
result_typethe type of transformed result type.
Returns
if result is successful, a new successful result holding the value produced by success_mapper; otherwise, the supplied result.

◆ RESULT_MAP_FAILURE

#define RESULT_MAP_FAILURE ( result,
failure_mapper,
result_type )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? (result_type) \
RESULT_FAILURE(failure_mapper(RESULT_USE_FAILURE(result))) \
: (result_type) \
)

Transforms the value of a failed result.

Precondition
result MUST be an lvalue.
Parameters
resultthe result whose failure value will be transformed.
failure_mapperthe mapping function or macro that produces the new failure value.
result_typethe type of transformed result type.
Returns
if result is failed, a new failed result holding the value produced by failure_mapper; otherwise, the supplied result.

◆ RESULT_MAP

#define RESULT_MAP ( result,
success_mapper,
failure_mapper,
result_type )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? (result_type) \
RESULT_FAILURE(failure_mapper(RESULT_USE_FAILURE(result))) \
: (result_type) \
RESULT_SUCCESS(success_mapper(RESULT_USE_SUCCESS(result))) \
)

Transforms either the success or the failure value of a result.

Precondition
result MUST be an lvalue.
Parameters
resultthe result whose value will be transformed.
success_mapperthe mapping function or macro that produces the new success value.
failure_mapperthe mapping function or macro that produces the new failure value.
result_typethe type of transformed result type.
Returns
if result is successful, a new successful result holding the value produced by success_mapper; otherwise, a new failed result holding the value produced by failure_mapper.

◆ RESULT_FLAT_MAP_SUCCESS

#define RESULT_FLAT_MAP_SUCCESS ( result,
success_mapper )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? (typeof(success_mapper(RESULT_USE_SUCCESS(result)))) \
: success_mapper(RESULT_USE_SUCCESS(result)) \
)

Transforms a successful result into a different one.

Precondition
result MUST be an lvalue.
Parameters
resultthe result that will be transformed.
success_mapperthe mapping function or macro that produces the new result if the given result is successful.
Returns
if result is successful, a new result produced by success_mapper; otherwise, the supplied result.

◆ RESULT_FLAT_MAP_FAILURE

#define RESULT_FLAT_MAP_FAILURE ( result,
failure_mapper )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? failure_mapper(RESULT_USE_FAILURE(result)) \
: (typeof(failure_mapper(RESULT_USE_FAILURE(result)))) \
)

Transforms a failed result into a different one.

Precondition
result MUST be an lvalue.
Parameters
resultthe result that will be transformed.
failure_mapperthe mapping function or macro that produces the new result if the given result is failed.
Returns
if result is failed, a new result produced by failure_mapper; otherwise, the supplied result.

◆ RESULT_FLAT_MAP

#define RESULT_FLAT_MAP ( result,
success_mapper,
failure_mapper )
Value:
( \
(void) &(result), \
RESULT_HAS_FAILURE(result) \
? failure_mapper(RESULT_USE_FAILURE(result)) \
: success_mapper(RESULT_USE_SUCCESS(result)) \
)

Transforms a result into a different one.

Precondition
result MUST be an lvalue.
Parameters
resultthe result that will be transformed.
success_mapperthe mapping function or macro that produces the new result if the given result is successful.
failure_mapperthe mapping function or macro that produces the new result if the given result is failed.
Returns
the result produced by either success_mapper or failure_mapper.

◆ RESULT_DEBUG_FUNC

#define RESULT_DEBUG_FUNC ( result)
Value:
( (result)._debug._func )

Returns the function name where a result was created.

Precondition
This macro is only available if NDEBUG is not defined.
Parameters
resultthe result to retrieve the debug information from.
Returns
the function name where result was created.
See also
RESULT_DEBUG_FILE
RESULT_DEBUG_LINE

◆ RESULT_DEBUG_FILE

#define RESULT_DEBUG_FILE ( result)
Value:
( (result)._debug._file )

Returns the source file name where a result was created.

Precondition
This macro is only available if NDEBUG is not defined.
Parameters
resultthe result to retrieve the debug information from.
Returns
the source file name where result was created.
See also
RESULT_DEBUG_FUNC
RESULT_DEBUG_LINE

◆ RESULT_DEBUG_LINE

#define RESULT_DEBUG_LINE ( result)
Value:
( (result)._debug._line )

Returns the source line number where a result was created.

Precondition
This macro is only available if NDEBUG is not defined.
Parameters
resultthe result to retrieve the debug information from.
Returns
the source line number where result was created.
See also
RESULT_DEBUG_FUNC
RESULT_DEBUG_FILE