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