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