#pragma once #include #include #if defined(__clang__) || defined(__GNUC__) #define JVALIDATE_LIKELY(x) __builtin_expect(!!(x), 1) #define JVALIDATE_UNLIKELY(x) __builtin_expect(!!(x), 0) #else #define JVALIDATE_LIKELY(x) (x) #define JVALIDATE_UNLIKELY(x) (x) #endif #if defined(JVALIDATE_USE_EXCEPTIONS) /** * @brief Throw an exception after construcing the error message. * * @param extype A subtype of std::exception that can be constructed using a * std::string. * * @param message The error "message" to be emit - in the form of an iostream * output chain (e.g. `"unsupported index " << i << ", valid items " << items`). */ #define JVALIDATE_THROW(extype, message) \ do { \ std::stringstream ss; \ ss << message; \ throw extype(ss.str()); \ } while (false) #else /** * @brief Print an error message and then terminate execution * * @param extype[ignored] * * @param message The error "message" to be emit - in the form of an iostream * output chain (e.g. `"unsupported index " << i << ", valid items " << items`). */ #define JVALIDATE_THROW(extype, message) \ do { \ std::cerr << message << std::endl; \ std::terminate(); \ } while (false) #endif /** * @brief Assert a certain pre/post-condition is true, else emit an error of a * specified type and message. * * @param condition A boolean or boolean-like expression that should be TRUE. * If the condition is FALSE, then the other params are used to produce errors. * * @param extype A subtype of std::exception that can be constructed using a * std::string. If exceptions are enabled, and condition is FALSE - then this * is the type that will be thrown. * * @param message The error "message" to be emit - in the form of an iostream * output chain (e.g. `"unsupported index " << i << ", valid items " << items`). */ #define EXPECT_T(condition, extype, message) \ if (JVALIDATE_UNLIKELY(!(condition))) { \ JVALIDATE_THROW(extype, message); \ } /** * @brief Assert a certain pre/post-condition is true, else emit an error of a * specified message. * * @param condition A boolean or boolean-like expression that should be TRUE. * If the condition is FALSE, then the other params are used to produce errors. * * @param message The error "message" to be emit - in the form of an iostream * output chain (e.g. `"unsupported index " << i << ", valid items " << items`). */ #define EXPECT_M(condition, message) EXPECT_T(condition, std::runtime_error, message) /** * @brief Assert a certain pre/post-condition is true, else emit a generic error. * * @param condition A boolean or boolean-like expression that should be TRUE. * If the condition is FALSE, then the other params are used to produce errors. */ #define EXPECT(condition) EXPECT_M(condition, #condition " at " __FILE__ ":" << __LINE__) /** * @brief Assert a certain pre/post-condition is true, else return the default * expression (or void). * * @param condition A boolean or boolean-like expression that should be TRUE. * If the condition is FALSE, then the other params are used to produce errors. * * @param ... Zero or One arguments representing the return value if the * condition is FALSE. Zero arguments is equivalent to `return void();`, which * doesn't need to be explicitly stated. */ #define RETURN_UNLESS(condition, ...) \ if (JVALIDATE_UNLIKELY(!(condition))) { \ return __VA_ARGS__; \ }