10c16b537SWarner Losh /*
2*5ff13fbcSAllan Jude * Copyright (c) Yann Collet, Facebook, Inc.
30c16b537SWarner Losh * All rights reserved.
40c16b537SWarner Losh *
50c16b537SWarner Losh * This source code is licensed under both the BSD-style license (found in the
60c16b537SWarner Losh * LICENSE file in the root directory of this source tree) and the GPLv2 (found
70c16b537SWarner Losh * in the COPYING file in the root directory of this source tree).
80c16b537SWarner Losh * You may select, at your option, one of the above-listed licenses.
90c16b537SWarner Losh */
100c16b537SWarner Losh
110c16b537SWarner Losh /* Note : this module is expected to remain private, do not expose it */
120c16b537SWarner Losh
130c16b537SWarner Losh #ifndef ERROR_H_MODULE
140c16b537SWarner Losh #define ERROR_H_MODULE
150c16b537SWarner Losh
160c16b537SWarner Losh #if defined (__cplusplus)
170c16b537SWarner Losh extern "C" {
180c16b537SWarner Losh #endif
190c16b537SWarner Losh
200c16b537SWarner Losh
210c16b537SWarner Losh /* ****************************************
220c16b537SWarner Losh * Dependencies
230c16b537SWarner Losh ******************************************/
24*5ff13fbcSAllan Jude #include "../zstd_errors.h" /* enum list */
25*5ff13fbcSAllan Jude #include "compiler.h"
26*5ff13fbcSAllan Jude #include "debug.h"
27f7cd7fe5SConrad Meyer #include "zstd_deps.h" /* size_t */
280c16b537SWarner Losh
290c16b537SWarner Losh
300c16b537SWarner Losh /* ****************************************
310c16b537SWarner Losh * Compiler-specific
320c16b537SWarner Losh ******************************************/
330c16b537SWarner Losh #if defined(__GNUC__)
340c16b537SWarner Losh # define ERR_STATIC static __attribute__((unused))
350c16b537SWarner Losh #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
360c16b537SWarner Losh # define ERR_STATIC static inline
370c16b537SWarner Losh #elif defined(_MSC_VER)
380c16b537SWarner Losh # define ERR_STATIC static __inline
390c16b537SWarner Losh #else
400c16b537SWarner Losh # define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
410c16b537SWarner Losh #endif
420c16b537SWarner Losh
430c16b537SWarner Losh
440c16b537SWarner Losh /*-****************************************
450c16b537SWarner Losh * Customization (error_public.h)
460c16b537SWarner Losh ******************************************/
470c16b537SWarner Losh typedef ZSTD_ErrorCode ERR_enum;
480c16b537SWarner Losh #define PREFIX(name) ZSTD_error_##name
490c16b537SWarner Losh
500c16b537SWarner Losh
510c16b537SWarner Losh /*-****************************************
520c16b537SWarner Losh * Error codes handling
530c16b537SWarner Losh ******************************************/
5437f1f268SConrad Meyer #undef ERROR /* already defined on Visual Studio */
550c16b537SWarner Losh #define ERROR(name) ZSTD_ERROR(name)
560c16b537SWarner Losh #define ZSTD_ERROR(name) ((size_t)-PREFIX(name))
570c16b537SWarner Losh
ERR_isError(size_t code)580c16b537SWarner Losh ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
590c16b537SWarner Losh
ERR_getErrorCode(size_t code)600c16b537SWarner Losh ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
610c16b537SWarner Losh
6237f1f268SConrad Meyer /* check and forward error code */
6337f1f268SConrad Meyer #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
6437f1f268SConrad Meyer #define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
6537f1f268SConrad Meyer
660c16b537SWarner Losh
670c16b537SWarner Losh /*-****************************************
680c16b537SWarner Losh * Error Strings
690c16b537SWarner Losh ******************************************/
700c16b537SWarner Losh
710c16b537SWarner Losh const char* ERR_getErrorString(ERR_enum code); /* error_private.c */
720c16b537SWarner Losh
ERR_getErrorName(size_t code)730c16b537SWarner Losh ERR_STATIC const char* ERR_getErrorName(size_t code)
740c16b537SWarner Losh {
750c16b537SWarner Losh return ERR_getErrorString(ERR_getErrorCode(code));
760c16b537SWarner Losh }
770c16b537SWarner Losh
78*5ff13fbcSAllan Jude /**
79*5ff13fbcSAllan Jude * Ignore: this is an internal helper.
80*5ff13fbcSAllan Jude *
81*5ff13fbcSAllan Jude * This is a helper function to help force C99-correctness during compilation.
82*5ff13fbcSAllan Jude * Under strict compilation modes, variadic macro arguments can't be empty.
83*5ff13fbcSAllan Jude * However, variadic function arguments can be. Using a function therefore lets
84*5ff13fbcSAllan Jude * us statically check that at least one (string) argument was passed,
85*5ff13fbcSAllan Jude * independent of the compilation flags.
86*5ff13fbcSAllan Jude */
87*5ff13fbcSAllan Jude static INLINE_KEYWORD UNUSED_ATTR
_force_has_format_string(const char * format,...)88*5ff13fbcSAllan Jude void _force_has_format_string(const char *format, ...) {
89*5ff13fbcSAllan Jude (void)format;
90*5ff13fbcSAllan Jude }
91*5ff13fbcSAllan Jude
92*5ff13fbcSAllan Jude /**
93*5ff13fbcSAllan Jude * Ignore: this is an internal helper.
94*5ff13fbcSAllan Jude *
95*5ff13fbcSAllan Jude * We want to force this function invocation to be syntactically correct, but
96*5ff13fbcSAllan Jude * we don't want to force runtime evaluation of its arguments.
97*5ff13fbcSAllan Jude */
98*5ff13fbcSAllan Jude #define _FORCE_HAS_FORMAT_STRING(...) \
99*5ff13fbcSAllan Jude if (0) { \
100*5ff13fbcSAllan Jude _force_has_format_string(__VA_ARGS__); \
101*5ff13fbcSAllan Jude }
102*5ff13fbcSAllan Jude
103*5ff13fbcSAllan Jude #define ERR_QUOTE(str) #str
104*5ff13fbcSAllan Jude
105*5ff13fbcSAllan Jude /**
106*5ff13fbcSAllan Jude * Return the specified error if the condition evaluates to true.
107*5ff13fbcSAllan Jude *
108*5ff13fbcSAllan Jude * In debug modes, prints additional information.
109*5ff13fbcSAllan Jude * In order to do that (particularly, printing the conditional that failed),
110*5ff13fbcSAllan Jude * this can't just wrap RETURN_ERROR().
111*5ff13fbcSAllan Jude */
112*5ff13fbcSAllan Jude #define RETURN_ERROR_IF(cond, err, ...) \
113*5ff13fbcSAllan Jude if (cond) { \
114*5ff13fbcSAllan Jude RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
115*5ff13fbcSAllan Jude __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
116*5ff13fbcSAllan Jude _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
117*5ff13fbcSAllan Jude RAWLOG(3, ": " __VA_ARGS__); \
118*5ff13fbcSAllan Jude RAWLOG(3, "\n"); \
119*5ff13fbcSAllan Jude return ERROR(err); \
120*5ff13fbcSAllan Jude }
121*5ff13fbcSAllan Jude
122*5ff13fbcSAllan Jude /**
123*5ff13fbcSAllan Jude * Unconditionally return the specified error.
124*5ff13fbcSAllan Jude *
125*5ff13fbcSAllan Jude * In debug modes, prints additional information.
126*5ff13fbcSAllan Jude */
127*5ff13fbcSAllan Jude #define RETURN_ERROR(err, ...) \
128*5ff13fbcSAllan Jude do { \
129*5ff13fbcSAllan Jude RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
130*5ff13fbcSAllan Jude __FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \
131*5ff13fbcSAllan Jude _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
132*5ff13fbcSAllan Jude RAWLOG(3, ": " __VA_ARGS__); \
133*5ff13fbcSAllan Jude RAWLOG(3, "\n"); \
134*5ff13fbcSAllan Jude return ERROR(err); \
135*5ff13fbcSAllan Jude } while(0);
136*5ff13fbcSAllan Jude
137*5ff13fbcSAllan Jude /**
138*5ff13fbcSAllan Jude * If the provided expression evaluates to an error code, returns that error code.
139*5ff13fbcSAllan Jude *
140*5ff13fbcSAllan Jude * In debug modes, prints additional information.
141*5ff13fbcSAllan Jude */
142*5ff13fbcSAllan Jude #define FORWARD_IF_ERROR(err, ...) \
143*5ff13fbcSAllan Jude do { \
144*5ff13fbcSAllan Jude size_t const err_code = (err); \
145*5ff13fbcSAllan Jude if (ERR_isError(err_code)) { \
146*5ff13fbcSAllan Jude RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \
147*5ff13fbcSAllan Jude __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
148*5ff13fbcSAllan Jude _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
149*5ff13fbcSAllan Jude RAWLOG(3, ": " __VA_ARGS__); \
150*5ff13fbcSAllan Jude RAWLOG(3, "\n"); \
151*5ff13fbcSAllan Jude return err_code; \
152*5ff13fbcSAllan Jude } \
153*5ff13fbcSAllan Jude } while(0);
154*5ff13fbcSAllan Jude
1550c16b537SWarner Losh #if defined (__cplusplus)
1560c16b537SWarner Losh }
1570c16b537SWarner Losh #endif
1580c16b537SWarner Losh
1590c16b537SWarner Losh #endif /* ERROR_H_MODULE */
160