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