123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #ifndef BASE_CHECK_OP_H_
- #define BASE_CHECK_OP_H_
- #include <cstddef>
- #include <type_traits>
- #include "base/check.h"
- #include "base/template_util.h"
- namespace logging {
- BASE_EXPORT char* CheckOpValueStr(int v);
- BASE_EXPORT char* CheckOpValueStr(unsigned v);
- BASE_EXPORT char* CheckOpValueStr(long v);
- BASE_EXPORT char* CheckOpValueStr(unsigned long v);
- BASE_EXPORT char* CheckOpValueStr(long long v);
- BASE_EXPORT char* CheckOpValueStr(unsigned long long v);
- BASE_EXPORT char* CheckOpValueStr(const void* v);
- BASE_EXPORT char* CheckOpValueStr(std::nullptr_t v);
- BASE_EXPORT char* CheckOpValueStr(double v);
- BASE_EXPORT char* StreamValToStr(const void* v,
- void (*stream_func)(std::ostream&,
- const void*));
- #ifdef __has_builtin
- #define SUPPORTS_BUILTIN_ADDRESSOF (__has_builtin(__builtin_addressof))
- #else
- #define SUPPORTS_BUILTIN_ADDRESSOF 0
- #endif
- template <typename T>
- inline typename std::enable_if<
- base::internal::SupportsOstreamOperator<const T&>::value &&
- !std::is_function<typename std::remove_pointer<T>::type>::value,
- char*>::type
- CheckOpValueStr(const T& v) {
- auto f = [](std::ostream& s, const void* p) {
- s << *reinterpret_cast<const T*>(p);
- };
-
-
-
- #if SUPPORTS_BUILTIN_ADDRESSOF
- const void* vp = const_cast<const void*>(
- reinterpret_cast<const volatile void*>(__builtin_addressof(v)));
- #else
- const void* vp = reinterpret_cast<const void*>(
- const_cast<const char*>(&reinterpret_cast<const volatile char&>(v)));
- #endif
- return StreamValToStr(vp, f);
- }
- #undef SUPPORTS_BUILTIN_ADDRESSOF
- template <typename T>
- inline typename std::enable_if<
- !base::internal::SupportsOstreamOperator<const T&>::value &&
- base::internal::SupportsToString<const T&>::value,
- char*>::type
- CheckOpValueStr(const T& v) {
-
- return CheckOpValueStr(v.ToString());
- }
- template <typename T>
- inline typename std::enable_if<
- std::is_function<typename std::remove_pointer<T>::type>::value,
- char*>::type
- CheckOpValueStr(const T& v) {
- return CheckOpValueStr(reinterpret_cast<const void*>(v));
- }
- template <typename T>
- inline typename std::enable_if<
- !base::internal::SupportsOstreamOperator<const T&>::value &&
- std::is_enum<T>::value,
- char*>::type
- CheckOpValueStr(const T& v) {
- return CheckOpValueStr(
- static_cast<typename std::underlying_type<T>::type>(v));
- }
- class CheckOpResult {
- public:
-
- constexpr CheckOpResult() {}
-
-
-
- BASE_EXPORT CheckOpResult(const char* expr_str, char* v1_str, char* v2_str);
-
- constexpr explicit operator bool() const { return !message_; }
- friend class CheckError;
- private:
- char* message_ = nullptr;
- };
- #if defined(OFFICIAL_BUILD) && defined(NDEBUG)
- #define CHECK_OP(name, op, val1, val2) CHECK((val1)op(val2))
- #else
- #define CHECK_OP(name, op, val1, val2) \
- switch (0) \
- case 0: \
- default: \
- if (::logging::CheckOpResult true_if_passed = \
- ::logging::Check##name##Impl((val1), (val2), \
- #val1 " " #op " " #val2)) \
- ; \
- else \
- ::logging::CheckError::CheckOp(__FILE__, __LINE__, &true_if_passed) \
- .stream()
- #endif
- #define DEFINE_CHECK_OP_IMPL(name, op) \
- template <typename T, typename U, \
- std::enable_if_t<!std::is_fundamental<T>::value || \
- !std::is_fundamental<U>::value, \
- int> = 0> \
- constexpr ::logging::CheckOpResult Check##name##Impl( \
- const T& v1, const U& v2, const char* expr_str) { \
- if (ANALYZER_ASSUME_TRUE(v1 op v2)) \
- return ::logging::CheckOpResult(); \
- return ::logging::CheckOpResult(expr_str, CheckOpValueStr(v1), \
- CheckOpValueStr(v2)); \
- } \
- template <typename T, typename U, \
- std::enable_if_t<std::is_fundamental<T>::value && \
- std::is_fundamental<U>::value, \
- int> = 0> \
- constexpr ::logging::CheckOpResult Check##name##Impl(T v1, U v2, \
- const char* expr_str) { \
- if (ANALYZER_ASSUME_TRUE(v1 op v2)) \
- return ::logging::CheckOpResult(); \
- return ::logging::CheckOpResult(expr_str, CheckOpValueStr(v1), \
- CheckOpValueStr(v2)); \
- }
- DEFINE_CHECK_OP_IMPL(EQ, ==)
- DEFINE_CHECK_OP_IMPL(NE, !=)
- DEFINE_CHECK_OP_IMPL(LE, <=)
- DEFINE_CHECK_OP_IMPL(LT, < )
- DEFINE_CHECK_OP_IMPL(GE, >=)
- DEFINE_CHECK_OP_IMPL(GT, > )
- #undef DEFINE_CHECK_OP_IMPL
- #define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2)
- #define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2)
- #define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2)
- #define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2)
- #define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
- #define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
- #if DCHECK_IS_ON()
- #define DCHECK_OP(name, op, val1, val2) \
- switch (0) \
- case 0: \
- default: \
- if (::logging::CheckOpResult true_if_passed = \
- ::logging::Check##name##Impl((val1), (val2), \
- #val1 " " #op " " #val2)) \
- ; \
- else \
- ::logging::CheckError::DCheckOp(__FILE__, __LINE__, &true_if_passed) \
- .stream()
- #else
- #define DCHECK_OP(name, op, val1, val2) \
- EAT_CHECK_STREAM_PARAMS((::logging::CheckOpValueStr(val1), \
- ::logging::CheckOpValueStr(val2), (val1)op(val2)))
- #endif
- #define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2)
- #define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2)
- #define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2)
- #define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2)
- #define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
- #define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2)
- }
- #endif
|