src/error.h
changeset 3 cc94ae754e2a
child 4 a3ca0f97a075
equal deleted inserted replaced
2:a834f0559939 3:cc94ae754e2a
       
     1 #ifndef ERROR_H
       
     2 #define ERROR_H
       
     3 
       
     4 /*
       
     5  * Error-handling functions
       
     6  */
       
     7 #include <errno.h>
       
     8 
       
     9 /*
       
    10  * Type used for error codes is an explicitly *unsigned* int, meaning that error codes themselves are positive.
       
    11  * Negative error codes also exist in some places, and they are just a negative err_t.
       
    12  */
       
    13 typedef unsigned int err_t;
       
    14 
       
    15 /*
       
    16  * List of defined error codes, organized mostly by function name
       
    17  */
       
    18 enum error_code {
       
    19     ERR_CALLOC                  = 0x000100,
       
    20     
       
    21     // network resolver errors
       
    22     ERR_GETADDRINFO             = 0x000200,
       
    23     ERR_GETADDRINFO_EMPTY       = 0x000201,     /* No valid results */
       
    24 
       
    25     // low-level network errors
       
    26     ERR_SOCKET                  = 0x000301,
       
    27     ERR_CONNECT                 = 0x000302,
       
    28 
       
    29     // low-level IO errors
       
    30     ERR_READ                    = 0x000401,
       
    31     ERR_WRITE                   = 0x000402,
       
    32 };
       
    33 
       
    34 /*
       
    35  * An error code and associated extra infos
       
    36  */
       
    37 struct error_info {
       
    38     /* The base error code */
       
    39     err_t code;
       
    40 
       
    41     /* Additional detail info, usually some third-part error code */
       
    42     unsigned int extra;
       
    43 };
       
    44 
       
    45 /** No error, evaulates as logical false */
       
    46 #define SUCCESS (0)
       
    47 
       
    48 /* Evaulates to error_info.code as lvalue */
       
    49 #define ERROR_CODE(err_info) ((err_info).code)
       
    50 
       
    51 /* Evaulates to error_info.extra as lvalue */
       
    52 #define ERROR_EXTRA(err_info) ((err_info).extra)
       
    53 
       
    54 /* Set error_info.code to SUCCESS, evaulates as zero */
       
    55 #define RESET_ERROR(err_info) ((err_info).code = SUCCESS)
       
    56 
       
    57 /* Compare error_info.code != 0 */
       
    58 #define IS_ERROR(err_info) (!!(err_info).code)
       
    59 
       
    60 /* Set error_info.code, but leave err_extra as-is. Evaluates to err_code */
       
    61 #define SET_ERROR(err_info, err_code) ((err_info).code = (err_code))
       
    62 
       
    63 /* Set error_info.code/extra. XXX: should evaluate to err_code */
       
    64 #define _SET_ERROR_EXTRA(err_info, err_code, err_extra) (err_info).code = (err_code); err_info.extra = (err_extra)
       
    65 #define SET_ERROR_EXTRA(err_info, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info, err_code, err_extra); } while (0)
       
    66 
       
    67 /* Set error.info.code to err_code, and .extra to errno. XXX: should evaulate to err_code */
       
    68 #define _SET_ERROR_ERRNO(err_info, err_code) _SET_ERROR_EXTRA(err_info, err_code, errno);
       
    69 #define SET_ERROR_ERRNO(err_info, err_code) SET_ERROR_EXTRA(err_info, err_code, errno);
       
    70 
       
    71 /* Ss above, but also return err_code from func. XXX: use 'return SET_ERROR...' instead */
       
    72 #define RETURN_SET_ERROR(err_info, err_code) do { _SET_ERROR(err_info, err_code); return (err_code); } while (0)
       
    73 #define RETURN_SET_ERROR_EXTRA(err_info, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info, err_code, err_extra); return (err_code); } while (0)
       
    74 #define RETURN_SET_ERROR_ERRNO(err_info, err_code) do { _SET_ERROR_ERRNO(err_info, err_code); return (err_code); } while (0)
       
    75 
       
    76 #endif