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

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

#include <stddef.h>

Macros

#define RESULT_VERSION   1
 Returns the major version number of this library.
 
#define RESULT(success_type_name, failure_type_name)
 Returns the type specifier for results with the supplied success and failure type names.
 
#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(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.
 
#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.
 

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
1.0.0
Author
Guillermo Calvo
See also
For more information, visit the project on GitHub

Macro Definition Documentation

◆ RESULT_VERSION

#define RESULT_VERSION   1

Returns the major version number of this library.

◆ RESULT

#define RESULT ( success_type_name,
failure_type_name )
Value:
struct RESULT_TAG(success_type_name, failure_type_name)
#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:835

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.

Example:

RESULT(pet_status, pet_error) result;
Parameters
success_type_nameThe success type name.
failure_type_nameThe failure type name.
Returns
The result type specifier.
See also
RESULT_STRUCT

◆ 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:864

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.

Example:

RESULT_STRUCT(pet_status, pet_error);
Parameters
success_typeThe success type.
failure_typeThe failure type.
Returns
The type definition.
See also
RESULT

◆ 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.

Example:

RESULT(pet_status, pet_error) result = RESULT_SUCCESS(AVAILABLE);
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.

Example:

RESULT(pet_status, pet_error) result = RESULT_FAILURE(PET_NOT_FOUND);
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.

Example:

RESULT(pet_status, pet_error) result = RESULT_SUCCESS(AVAILABLE);
bool has_success = RESULT_HAS_SUCCESS(result);
assert(has_success == true);
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.

Example:

RESULT(pet_status, pet_error) result = RESULT_FAILURE(PET_NOT_FOUND);
bool has_failure = RESULT_HAS_FAILURE(result);
assert(has_failure == true);
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.

Example:

RESULT(pet_status, pet_error) result = RESULT_SUCCESS(AVAILABLE);
pet_status value = RESULT_USE_SUCCESS(result);
assert(value == AVAILABLE);
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.

Example:

RESULT(pet_status, pet_error) result = RESULT_FAILURE(PET_NOT_FOUND);
pet_error value = RESULT_USE_FAILURE(result);
assert(value == PET_NOT_FOUND);
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:253

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

Precondition
result MUST be an value.

Example:

RESULT(pet_status, pet_error) result = RESULT_SUCCESS(AVAILABLE);
const pet_status *value = RESULT_GET_SUCCESS(result);
assert(*value == AVAILABLE);
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:274

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

Precondition
result MUST be an lvalue.

Example:

RESULT(pet_status, pet_error) result = RESULT_FAILURE(PET_NOT_FOUND);
const pet_error *value = RESULT_GET_FAILURE(result);
assert(*value == PET_NOT_FOUND);
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.

Example:

RESULT(pet_status, pet_error) result = RESULT_FAILURE(PET_ALREADY_SOLD);
pet_status value = RESULT_OR_ELSE(result, PENDING);
assert(value == PENDING);
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.

Example:

#define ERROR_TO_STATUS(x) x == PET_ALREADY_SOLD ? SOLD : PENDING
RESULT(pet_status, pet_error) result = RESULT_FAILURE(PET_ALREADY_SOLD);
pet_status value = RESULT_OR_ELSE_MAP(result, ERROR_TO_STATUS);
assert(value == SOLD);
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:218

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

Example:

RESULT(int, pet_error) result = RESULT_SUCCESS(123);
side_effect = 0;
RESULT_IF_SUCCESS(result, set_side_effect);
assert(side_effect == 123);
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:232

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

Example:

RESULT(int, pet_error) result = RESULT_FAILURE(PET_NOT_FOUND);
last_error = OK;
RESULT_IF_FAILURE(result, log_error);
assert(last_error == PET_NOT_FOUND);
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.

Example:

RESULT(int, pet_error) result = RESULT_FAILURE(PET_NOT_FOUND);
side_effect = 0;
last_error = OK;
RESULT_IF_SUCCESS_OR_ELSE(result, set_side_effect, log_error);
assert(side_effect == 0);
assert(last_error == PET_NOT_FOUND);
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:171

Conditionally transforms a successful result into a failed one.

Precondition
result MUST be an lvalue.

Example:

struct pet sold = {.status = SOLD};
RESULT(Pet, pet_error) result = RESULT_SUCCESS(&sold);
RESULT(Pet, pet_error) filtered = RESULT_FILTER(result, is_available, PET_NOT_AVAILABLE);
assert(RESULT_USE_FAILURE(filtered) == PET_NOT_AVAILABLE);
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:451

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

Precondition
result MUST be an lvalue.

Example:

#define PET_TO_ERROR(pet) (PET_STATUS(pet) == SOLD ? PET_ALREADY_SOLD : PET_NOT_AVAILABLE)
struct pet sold = {.status = SOLD};
RESULT(Pet, pet_error) result = RESULT_SUCCESS(&sold);
RESULT(Pet, pet_error) filtered = RESULT_FILTER_MAP(result, is_available, PET_TO_ERROR);
assert(RESULT_USE_FAILURE(filtered) == PET_ALREADY_SOLD);
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:122

Conditionally transforms a failed result into a successful one.

Precondition
result MUST be an lvalue.

Example:

RESULT(pet_status, pet_error) result = RESULT_FAILURE(PET_NOT_AVAILABLE);
RESULT(pet_status, pet_error) recovered = RESULT_RECOVER(result, is_not_available, SOLD);
assert(RESULT_USE_SUCCESS(recovered) == SOLD);
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:504

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

Precondition
result MUST be an lvalue.

Example:

#define ERROR_TO_STATUS(x) x == PET_ALREADY_SOLD ? SOLD : PENDING
RESULT(pet_status, pet_error) result = RESULT_FAILURE(PET_NOT_AVAILABLE);
RESULT(pet_status, pet_error) recovered = RESULT_RECOVER_MAP(result, is_not_available, ERROR_TO_STATUS);
assert(RESULT_USE_SUCCESS(recovered) == PENDING);
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.

Example:

struct pet sold = {.status = SOLD};
RESULT(Pet, pet_error) result = RESULT_SUCCESS(&sold);
RESULT(pet_status, pet_error) mapped = RESULT_MAP_SUCCESS(result, PET_STATUS, typeof(mapped));
assert(RESULT_USE_SUCCESS(mapped) == SOLD);
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.
See also
RESULT_MAP_FAILURE
RESULT_MAP

◆ 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.

Example:

RESULT(Pet, pet_error) result = RESULT_FAILURE(PET_NOT_AVAILABLE);
RESULT(Pet, msg) mapped = RESULT_MAP_FAILURE(result, pet_error_message, typeof(mapped));
assert(strcmp(RESULT_USE_FAILURE(mapped), "Pet not available") == 0);
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.
See also
RESULT_MAP_SUCCESS
RESULT_MAP

◆ 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.

Example:

struct pet sold = {.status = SOLD};
RESULT(Pet, pet_error) result = RESULT_SUCCESS(&sold);
RESULT(pet_status, msg) mapped = RESULT_MAP(result, PET_STATUS, pet_error_message, typeof(mapped));
assert(RESULT_USE_SUCCESS(mapped) == SOLD);
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.
See also
RESULT_MAP_SUCCESS
RESULT_MAP_FAILURE

◆ 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.

Example:

struct pet sold = {.status = SOLD};
RESULT(Pet, pet_error) result = RESULT_SUCCESS(&sold);
RESULT(Pet, pet_error) mapped = RESULT_FLAT_MAP_SUCCESS(result, buy_pet);
assert(RESULT_USE_FAILURE(mapped) == PET_NOT_AVAILABLE);
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.
See also
RESULT_FLAT_MAP_FAILURE
RESULT_FLAT_MAP

◆ 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.

Example:

RESULT(Pet, pet_error) result = RESULT_FAILURE(PET_NOT_FOUND);
RESULT(Pet, pet_error) mapped = RESULT_FLAT_MAP_FAILURE(result, pet_get_default);
assert(strcmp(PET_NAME(RESULT_USE_SUCCESS(mapped)), "Default pet") == 0);
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.
See also
RESULT_FLAT_MAP_SUCCESS
RESULT_FLAT_MAP

◆ 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.

Example:

struct pet available = {.status = AVAILABLE};
RESULT(Pet, pet_error) result = RESULT_SUCCESS(&available);
RESULT(Pet, pet_error) mapped = RESULT_FLAT_MAP(result, buy_pet, pet_get_default);
assert(RESULT_USE_SUCCESS(mapped) == &available);
assert(PET_STATUS(RESULT_USE_SUCCESS(mapped)) == SOLD);
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.
See also
RESULT_FLAT_MAP_SUCCESS
RESULT_FLAT_MAP_FAILURE

◆ RESULT_DEBUG_FUNC

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

Returns the function name where a result was created.

Example:

RESULT(Pet, pet_error) failure = RESULT_FAILURE(PET_NOT_FOUND);
const char *func = RESULT_DEBUG_FUNC(failure);
const char *file = RESULT_DEBUG_FILE(failure);
const int line = RESULT_DEBUG_LINE(failure);
fprintf(stderr, "Failure at %s (%s:%d)\n",
func ? func : "unknown function", file ? file : "unknown file", line);
Parameters
resultThe result to retrieve the debug information from.
Returns
The function name where result was created if NDEBUG is undefined; otherwise NULL.
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.

Example:

RESULT(Pet, pet_error) failure = RESULT_FAILURE(PET_NOT_FOUND);
const char *func = RESULT_DEBUG_FUNC(failure);
const char *file = RESULT_DEBUG_FILE(failure);
const int line = RESULT_DEBUG_LINE(failure);
fprintf(stderr, "Failure at %s (%s:%d)\n",
func ? func : "unknown function", file ? file : "unknown file", line);
Parameters
resultThe result to retrieve the debug information from.
Returns
The source file name where result was created if NDEBUG is undefined; otherwise NULL.
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.

Example:

RESULT(Pet, pet_error) failure = RESULT_FAILURE(PET_NOT_FOUND);
const char *func = RESULT_DEBUG_FUNC(failure);
const char *file = RESULT_DEBUG_FILE(failure);
const int line = RESULT_DEBUG_LINE(failure);
fprintf(stderr, "Failure at %s (%s:%d)\n",
func ? func : "unknown function", file ? file : "unknown file", line);
Parameters
resultThe result to retrieve the debug information from.
Returns
The source line number where @ result was created if NDEBUG is undefined; otherwise zero.
See also
RESULT_DEBUG_FUNC
RESULT_DEBUG_FILE

◆ 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.

Example:

RESULT_STRUCT_TAG(Pet, const char *, RESULT_TAG(Pet, error_message));
RESULT(Pet, error_message) result = RESULT_FAILURE("Oops");
assert(strcmp(RESULT_USE_FAILURE(result), "Oops") == 0);
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.

Example:

RESULT_STRUCT_TAG(Pet, const char *, RESULT_TAG(Pet, error_message));
RESULT(Pet, error_message) result = RESULT_FAILURE("Oops");
assert(strcmp(RESULT_USE_FAILURE(result), "Oops") == 0);
Parameters
success_typeThe success type.
failure_typeThe failure type.
struct_tagThe struct tag.
Returns
The struct declaration.
See also
RESULT_STRUCT
RESULT_TAG