Home | History | Annotate | Line # | Download | only in common
      1  1.1  christos /*
      2  1.1  christos  * Copyright (c) Meta Platforms, Inc. and affiliates.
      3  1.1  christos  * All rights reserved.
      4  1.1  christos  *
      5  1.1  christos  * This source code is licensed under both the BSD-style license (found in the
      6  1.1  christos  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
      7  1.1  christos  * in the COPYING file in the root directory of this source tree).
      8  1.1  christos  * You may select, at your option, one of the above-listed licenses.
      9  1.1  christos  */
     10  1.1  christos 
     11  1.1  christos /* Note : this module is expected to remain private, do not expose it */
     12  1.1  christos 
     13  1.1  christos #ifndef ERROR_H_MODULE
     14  1.1  christos #define ERROR_H_MODULE
     15  1.1  christos 
     16  1.1  christos /* ****************************************
     17  1.1  christos *  Dependencies
     18  1.1  christos ******************************************/
     19  1.1  christos #include "../zstd_errors.h"  /* enum list */
     20  1.1  christos #include "compiler.h"
     21  1.1  christos #include "debug.h"
     22  1.1  christos #include "zstd_deps.h"       /* size_t */
     23  1.1  christos 
     24  1.1  christos /* ****************************************
     25  1.1  christos *  Compiler-specific
     26  1.1  christos ******************************************/
     27  1.1  christos #if defined(__GNUC__)
     28  1.1  christos #  define ERR_STATIC static __attribute__((unused))
     29  1.1  christos #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
     30  1.1  christos #  define ERR_STATIC static inline
     31  1.1  christos #elif defined(_MSC_VER)
     32  1.1  christos #  define ERR_STATIC static __inline
     33  1.1  christos #else
     34  1.1  christos #  define ERR_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */
     35  1.1  christos #endif
     36  1.1  christos 
     37  1.1  christos 
     38  1.1  christos /*-****************************************
     39  1.1  christos *  Customization (error_public.h)
     40  1.1  christos ******************************************/
     41  1.1  christos typedef ZSTD_ErrorCode ERR_enum;
     42  1.1  christos #define PREFIX(name) ZSTD_error_##name
     43  1.1  christos 
     44  1.1  christos 
     45  1.1  christos /*-****************************************
     46  1.1  christos *  Error codes handling
     47  1.1  christos ******************************************/
     48  1.1  christos #undef ERROR   /* already defined on Visual Studio */
     49  1.1  christos #define ERROR(name) ZSTD_ERROR(name)
     50  1.1  christos #define ZSTD_ERROR(name) ((size_t)-PREFIX(name))
     51  1.1  christos 
     52  1.1  christos ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
     53  1.1  christos 
     54  1.1  christos ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
     55  1.1  christos 
     56  1.1  christos /* check and forward error code */
     57  1.1  christos #define CHECK_V_F(e, f)     \
     58  1.1  christos     size_t const e = f;     \
     59  1.1  christos     do {                    \
     60  1.1  christos         if (ERR_isError(e)) \
     61  1.1  christos             return e;       \
     62  1.1  christos     } while (0)
     63  1.1  christos #define CHECK_F(f)   do { CHECK_V_F(_var_err__, f); } while (0)
     64  1.1  christos 
     65  1.1  christos 
     66  1.1  christos /*-****************************************
     67  1.1  christos *  Error Strings
     68  1.1  christos ******************************************/
     69  1.1  christos 
     70  1.1  christos const char* ERR_getErrorString(ERR_enum code);   /* error_private.c */
     71  1.1  christos 
     72  1.1  christos ERR_STATIC const char* ERR_getErrorName(size_t code)
     73  1.1  christos {
     74  1.1  christos     return ERR_getErrorString(ERR_getErrorCode(code));
     75  1.1  christos }
     76  1.1  christos 
     77  1.1  christos /**
     78  1.1  christos  * Ignore: this is an internal helper.
     79  1.1  christos  *
     80  1.1  christos  * This is a helper function to help force C99-correctness during compilation.
     81  1.1  christos  * Under strict compilation modes, variadic macro arguments can't be empty.
     82  1.1  christos  * However, variadic function arguments can be. Using a function therefore lets
     83  1.1  christos  * us statically check that at least one (string) argument was passed,
     84  1.1  christos  * independent of the compilation flags.
     85  1.1  christos  */
     86  1.1  christos static INLINE_KEYWORD UNUSED_ATTR
     87  1.1  christos void _force_has_format_string(const char *format, ...) {
     88  1.1  christos   (void)format;
     89  1.1  christos }
     90  1.1  christos 
     91  1.1  christos /**
     92  1.1  christos  * Ignore: this is an internal helper.
     93  1.1  christos  *
     94  1.1  christos  * We want to force this function invocation to be syntactically correct, but
     95  1.1  christos  * we don't want to force runtime evaluation of its arguments.
     96  1.1  christos  */
     97  1.1  christos #define _FORCE_HAS_FORMAT_STRING(...)              \
     98  1.1  christos     do {                                           \
     99  1.1  christos         if (0) {                                   \
    100  1.1  christos             _force_has_format_string(__VA_ARGS__); \
    101  1.1  christos         }                                          \
    102  1.1  christos     } while (0)
    103  1.1  christos 
    104  1.1  christos #define ERR_QUOTE(str) #str
    105  1.1  christos 
    106  1.1  christos /**
    107  1.1  christos  * Return the specified error if the condition evaluates to true.
    108  1.1  christos  *
    109  1.1  christos  * In debug modes, prints additional information.
    110  1.1  christos  * In order to do that (particularly, printing the conditional that failed),
    111  1.1  christos  * this can't just wrap RETURN_ERROR().
    112  1.1  christos  */
    113  1.1  christos #define RETURN_ERROR_IF(cond, err, ...)                                        \
    114  1.1  christos     do {                                                                       \
    115  1.1  christos         if (cond) {                                                            \
    116  1.1  christos             RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s",          \
    117  1.1  christos                   __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
    118  1.1  christos             _FORCE_HAS_FORMAT_STRING(__VA_ARGS__);                             \
    119  1.1  christos             RAWLOG(3, ": " __VA_ARGS__);                                       \
    120  1.1  christos             RAWLOG(3, "\n");                                                   \
    121  1.1  christos             return ERROR(err);                                                 \
    122  1.1  christos         }                                                                      \
    123  1.1  christos     } while (0)
    124  1.1  christos 
    125  1.1  christos /**
    126  1.1  christos  * Unconditionally return the specified error.
    127  1.1  christos  *
    128  1.1  christos  * In debug modes, prints additional information.
    129  1.1  christos  */
    130  1.1  christos #define RETURN_ERROR(err, ...)                                               \
    131  1.1  christos     do {                                                                     \
    132  1.1  christos         RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
    133  1.1  christos               __FILE__, __LINE__, ERR_QUOTE(ERROR(err)));                    \
    134  1.1  christos         _FORCE_HAS_FORMAT_STRING(__VA_ARGS__);                               \
    135  1.1  christos         RAWLOG(3, ": " __VA_ARGS__);                                         \
    136  1.1  christos         RAWLOG(3, "\n");                                                     \
    137  1.1  christos         return ERROR(err);                                                   \
    138  1.1  christos     } while(0)
    139  1.1  christos 
    140  1.1  christos /**
    141  1.1  christos  * If the provided expression evaluates to an error code, returns that error code.
    142  1.1  christos  *
    143  1.1  christos  * In debug modes, prints additional information.
    144  1.1  christos  */
    145  1.1  christos #define FORWARD_IF_ERROR(err, ...)                                                 \
    146  1.1  christos     do {                                                                           \
    147  1.1  christos         size_t const err_code = (err);                                             \
    148  1.1  christos         if (ERR_isError(err_code)) {                                               \
    149  1.1  christos             RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s",                 \
    150  1.1  christos                   __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
    151  1.1  christos             _FORCE_HAS_FORMAT_STRING(__VA_ARGS__);                                 \
    152  1.1  christos             RAWLOG(3, ": " __VA_ARGS__);                                           \
    153  1.1  christos             RAWLOG(3, "\n");                                                       \
    154  1.1  christos             return err_code;                                                       \
    155  1.1  christos         }                                                                          \
    156  1.1  christos     } while(0)
    157  1.1  christos 
    158  1.1  christos #endif /* ERROR_H_MODULE */
    159