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