error_private.h 6.3 KB

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