1*65d1f550SNick Terrell /* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
2e0c1b49fSNick Terrell /*
3*65d1f550SNick Terrell * Copyright (c) Meta Platforms, Inc. and affiliates.
4e0c1b49fSNick Terrell * All rights reserved.
5e0c1b49fSNick Terrell *
6e0c1b49fSNick Terrell * This source code is licensed under both the BSD-style license (found in the
7e0c1b49fSNick Terrell * LICENSE file in the root directory of this source tree) and the GPLv2 (found
8e0c1b49fSNick Terrell * in the COPYING file in the root directory of this source tree).
9e0c1b49fSNick Terrell * You may select, at your option, one of the above-listed licenses.
10e0c1b49fSNick Terrell */
11e0c1b49fSNick Terrell
12e0c1b49fSNick Terrell /* Note : this module is expected to remain private, do not expose it */
13e0c1b49fSNick Terrell
14e0c1b49fSNick Terrell #ifndef ERROR_H_MODULE
15e0c1b49fSNick Terrell #define ERROR_H_MODULE
16e0c1b49fSNick Terrell
17e0c1b49fSNick Terrell /* ****************************************
18e0c1b49fSNick Terrell * Dependencies
19e0c1b49fSNick Terrell ******************************************/
20e0c1b49fSNick Terrell #include <linux/zstd_errors.h> /* enum list */
212aa14b1aSNick Terrell #include "compiler.h"
222aa14b1aSNick Terrell #include "debug.h"
232aa14b1aSNick Terrell #include "zstd_deps.h" /* size_t */
24e0c1b49fSNick Terrell
25e0c1b49fSNick Terrell /* ****************************************
26e0c1b49fSNick Terrell * Compiler-specific
27e0c1b49fSNick Terrell ******************************************/
28e0c1b49fSNick Terrell #define ERR_STATIC static __attribute__((unused))
29e0c1b49fSNick Terrell
30e0c1b49fSNick Terrell
31e0c1b49fSNick Terrell /*-****************************************
32e0c1b49fSNick Terrell * Customization (error_public.h)
33e0c1b49fSNick Terrell ******************************************/
34e0c1b49fSNick Terrell typedef ZSTD_ErrorCode ERR_enum;
35e0c1b49fSNick Terrell #define PREFIX(name) ZSTD_error_##name
36e0c1b49fSNick Terrell
37e0c1b49fSNick Terrell
38e0c1b49fSNick Terrell /*-****************************************
39e0c1b49fSNick Terrell * Error codes handling
40e0c1b49fSNick Terrell ******************************************/
41e0c1b49fSNick Terrell #undef ERROR /* already defined on Visual Studio */
42e0c1b49fSNick Terrell #define ERROR(name) ZSTD_ERROR(name)
43e0c1b49fSNick Terrell #define ZSTD_ERROR(name) ((size_t)-PREFIX(name))
44e0c1b49fSNick Terrell
ERR_isError(size_t code)45e0c1b49fSNick Terrell ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
46e0c1b49fSNick Terrell
ERR_getErrorCode(size_t code)47e0c1b49fSNick Terrell ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
48e0c1b49fSNick Terrell
49e0c1b49fSNick Terrell /* check and forward error code */
50*65d1f550SNick Terrell #define CHECK_V_F(e, f) \
51*65d1f550SNick Terrell size_t const e = f; \
52*65d1f550SNick Terrell do { \
53*65d1f550SNick Terrell if (ERR_isError(e)) \
54*65d1f550SNick Terrell return e; \
55*65d1f550SNick Terrell } while (0)
56*65d1f550SNick Terrell #define CHECK_F(f) do { CHECK_V_F(_var_err__, f); } while (0)
57e0c1b49fSNick Terrell
58e0c1b49fSNick Terrell
59e0c1b49fSNick Terrell /*-****************************************
60e0c1b49fSNick Terrell * Error Strings
61e0c1b49fSNick Terrell ******************************************/
62e0c1b49fSNick Terrell
63e0c1b49fSNick Terrell const char* ERR_getErrorString(ERR_enum code); /* error_private.c */
64e0c1b49fSNick Terrell
ERR_getErrorName(size_t code)65e0c1b49fSNick Terrell ERR_STATIC const char* ERR_getErrorName(size_t code)
66e0c1b49fSNick Terrell {
67e0c1b49fSNick Terrell return ERR_getErrorString(ERR_getErrorCode(code));
68e0c1b49fSNick Terrell }
69e0c1b49fSNick Terrell
702aa14b1aSNick Terrell /*
712aa14b1aSNick Terrell * Ignore: this is an internal helper.
722aa14b1aSNick Terrell *
732aa14b1aSNick Terrell * This is a helper function to help force C99-correctness during compilation.
742aa14b1aSNick Terrell * Under strict compilation modes, variadic macro arguments can't be empty.
752aa14b1aSNick Terrell * However, variadic function arguments can be. Using a function therefore lets
762aa14b1aSNick Terrell * us statically check that at least one (string) argument was passed,
772aa14b1aSNick Terrell * independent of the compilation flags.
782aa14b1aSNick Terrell */
792aa14b1aSNick Terrell static INLINE_KEYWORD UNUSED_ATTR
_force_has_format_string(const char * format,...)802aa14b1aSNick Terrell void _force_has_format_string(const char *format, ...) {
812aa14b1aSNick Terrell (void)format;
822aa14b1aSNick Terrell }
832aa14b1aSNick Terrell
842aa14b1aSNick Terrell /*
852aa14b1aSNick Terrell * Ignore: this is an internal helper.
862aa14b1aSNick Terrell *
872aa14b1aSNick Terrell * We want to force this function invocation to be syntactically correct, but
882aa14b1aSNick Terrell * we don't want to force runtime evaluation of its arguments.
892aa14b1aSNick Terrell */
902aa14b1aSNick Terrell #define _FORCE_HAS_FORMAT_STRING(...) \
91*65d1f550SNick Terrell do { \
922aa14b1aSNick Terrell if (0) { \
932aa14b1aSNick Terrell _force_has_format_string(__VA_ARGS__); \
94*65d1f550SNick Terrell } \
95*65d1f550SNick Terrell } while (0)
962aa14b1aSNick Terrell
972aa14b1aSNick Terrell #define ERR_QUOTE(str) #str
982aa14b1aSNick Terrell
992aa14b1aSNick Terrell /*
1002aa14b1aSNick Terrell * Return the specified error if the condition evaluates to true.
1012aa14b1aSNick Terrell *
1022aa14b1aSNick Terrell * In debug modes, prints additional information.
1032aa14b1aSNick Terrell * In order to do that (particularly, printing the conditional that failed),
1042aa14b1aSNick Terrell * this can't just wrap RETURN_ERROR().
1052aa14b1aSNick Terrell */
1062aa14b1aSNick Terrell #define RETURN_ERROR_IF(cond, err, ...) \
107*65d1f550SNick Terrell do { \
1082aa14b1aSNick Terrell if (cond) { \
1092aa14b1aSNick Terrell RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
1102aa14b1aSNick Terrell __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
1112aa14b1aSNick Terrell _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
1122aa14b1aSNick Terrell RAWLOG(3, ": " __VA_ARGS__); \
1132aa14b1aSNick Terrell RAWLOG(3, "\n"); \
1142aa14b1aSNick Terrell return ERROR(err); \
115*65d1f550SNick Terrell } \
116*65d1f550SNick Terrell } while (0)
1172aa14b1aSNick Terrell
1182aa14b1aSNick Terrell /*
1192aa14b1aSNick Terrell * Unconditionally return the specified error.
1202aa14b1aSNick Terrell *
1212aa14b1aSNick Terrell * In debug modes, prints additional information.
1222aa14b1aSNick Terrell */
1232aa14b1aSNick Terrell #define RETURN_ERROR(err, ...) \
1242aa14b1aSNick Terrell do { \
1252aa14b1aSNick Terrell RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
1262aa14b1aSNick Terrell __FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \
1272aa14b1aSNick Terrell _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
1282aa14b1aSNick Terrell RAWLOG(3, ": " __VA_ARGS__); \
1292aa14b1aSNick Terrell RAWLOG(3, "\n"); \
1302aa14b1aSNick Terrell return ERROR(err); \
131*65d1f550SNick Terrell } while(0)
1322aa14b1aSNick Terrell
1332aa14b1aSNick Terrell /*
1342aa14b1aSNick Terrell * If the provided expression evaluates to an error code, returns that error code.
1352aa14b1aSNick Terrell *
1362aa14b1aSNick Terrell * In debug modes, prints additional information.
1372aa14b1aSNick Terrell */
1382aa14b1aSNick Terrell #define FORWARD_IF_ERROR(err, ...) \
1392aa14b1aSNick Terrell do { \
1402aa14b1aSNick Terrell size_t const err_code = (err); \
1412aa14b1aSNick Terrell if (ERR_isError(err_code)) { \
1422aa14b1aSNick Terrell RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \
1432aa14b1aSNick Terrell __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
1442aa14b1aSNick Terrell _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
1452aa14b1aSNick Terrell RAWLOG(3, ": " __VA_ARGS__); \
1462aa14b1aSNick Terrell RAWLOG(3, "\n"); \
1472aa14b1aSNick Terrell return err_code; \
1482aa14b1aSNick Terrell } \
149*65d1f550SNick Terrell } while(0)
150e0c1b49fSNick Terrell
151e0c1b49fSNick Terrell #endif /* ERROR_H_MODULE */
152