error_private.h 6.4 KB

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