xref: /linux-6.15/lib/zstd/common/error_private.h (revision 65d1f550)
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