error_private.h 6.0 KB

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