/* bits/errno-return.h: A convenient way of setting errno after a syscall. */

#ifndef _BITS_ERRNO_RETURN_H
#define _BITS_ERRNO_RETURN_H

#include <errno.h>

// Set errno after a failed system call, otherwise extract the successful value.
#define __errno_return(value, type)                                                                                    \
    do {                                                                                                               \
        if (value < 0)                                                                                                 \
        {                                                                                                              \
            errno = (int)(-value);                                                                                     \
            return (type)-1;                                                                                           \
        }                                                                                                              \
        return (type)value;                                                                                            \
    } while (0)

// If expr has a value, evaluates to that value. Otherwise, short-circuits, sets errno to expr's error, and returns
// failval (casted to rtype) from the calling function. Similar to TRY() in luna/Result.h, but used for transforming
// errors from luna functions to libc functions.
#define TRY_OR_SET_ERRNO(expr, rtype, failval)                                                                         \
    ({                                                                                                                 \
        auto _expr_rc = (expr);                                                                                        \
        if (!_expr_rc.has_value())                                                                                     \
        {                                                                                                              \
            errno = _expr_rc.error();                                                                                  \
            return (rtype)failval;                                                                                     \
        }                                                                                                              \
        _expr_rc.release_value();                                                                                      \
    })

#endif