| 1 | // This file is part of OpenCV project. |
| 2 | // It is subject to the license terms in the LICENSE file found in the top-level directory |
| 3 | // of this distribution and at http://opencv.org/license.html. |
| 4 | |
| 5 | #ifndef OPENCV_CORE_CHECK_HPP |
| 6 | #define OPENCV_CORE_CHECK_HPP |
| 7 | |
| 8 | #include <opencv2/core/base.hpp> |
| 9 | |
| 10 | namespace cv { |
| 11 | |
| 12 | /** Returns string of cv::Mat depth value: CV_8U -> "CV_8U" or "<invalid depth>" */ |
| 13 | CV_EXPORTS const char* depthToString(int depth); |
| 14 | |
| 15 | /** Returns string of cv::Mat depth value: CV_8UC3 -> "CV_8UC3" or "<invalid type>" */ |
| 16 | CV_EXPORTS String typeToString(int type); |
| 17 | |
| 18 | |
| 19 | //! @cond IGNORED |
| 20 | namespace detail { |
| 21 | |
| 22 | /** Returns string of cv::Mat depth value: CV_8U -> "CV_8U" or NULL */ |
| 23 | CV_EXPORTS const char* depthToString_(int depth); |
| 24 | |
| 25 | /** Returns string of cv::Mat depth value: CV_8UC3 -> "CV_8UC3" or cv::String() */ |
| 26 | CV_EXPORTS cv::String typeToString_(int type); |
| 27 | |
| 28 | enum TestOp { |
| 29 | TEST_CUSTOM = 0, |
| 30 | TEST_EQ = 1, |
| 31 | TEST_NE = 2, |
| 32 | TEST_LE = 3, |
| 33 | TEST_LT = 4, |
| 34 | TEST_GE = 5, |
| 35 | TEST_GT = 6, |
| 36 | CV__LAST_TEST_OP |
| 37 | }; |
| 38 | |
| 39 | struct CheckContext { |
| 40 | const char* func; |
| 41 | const char* file; |
| 42 | int line; |
| 43 | enum TestOp testOp; |
| 44 | const char* message; |
| 45 | const char* p1_str; |
| 46 | const char* p2_str; |
| 47 | }; |
| 48 | |
| 49 | #ifndef CV__CHECK_FILENAME |
| 50 | # define CV__CHECK_FILENAME __FILE__ |
| 51 | #endif |
| 52 | |
| 53 | #ifndef CV__CHECK_FUNCTION |
| 54 | # if defined _MSC_VER |
| 55 | # define CV__CHECK_FUNCTION __FUNCSIG__ |
| 56 | # elif defined __GNUC__ |
| 57 | # define CV__CHECK_FUNCTION __PRETTY_FUNCTION__ |
| 58 | # else |
| 59 | # define CV__CHECK_FUNCTION "<unknown>" |
| 60 | # endif |
| 61 | #endif |
| 62 | |
| 63 | #define CV__CHECK_LOCATION_VARNAME(id) CVAUX_CONCAT(CVAUX_CONCAT(__cv_check_, id), __LINE__) |
| 64 | #define CV__DEFINE_CHECK_CONTEXT(id, message, testOp, p1_str, p2_str) \ |
| 65 | static const cv::detail::CheckContext CV__CHECK_LOCATION_VARNAME(id) = \ |
| 66 | { CV__CHECK_FUNCTION, CV__CHECK_FILENAME, __LINE__, testOp, "" message, "" p1_str, "" p2_str } |
| 67 | |
| 68 | CV_EXPORTS void CV_NORETURN check_failed_auto(const bool v1, const bool v2, const CheckContext& ctx); |
| 69 | CV_EXPORTS void CV_NORETURN check_failed_auto(const int v1, const int v2, const CheckContext& ctx); |
| 70 | CV_EXPORTS void CV_NORETURN check_failed_auto(const size_t v1, const size_t v2, const CheckContext& ctx); |
| 71 | CV_EXPORTS void CV_NORETURN check_failed_auto(const float v1, const float v2, const CheckContext& ctx); |
| 72 | CV_EXPORTS void CV_NORETURN check_failed_auto(const double v1, const double v2, const CheckContext& ctx); |
| 73 | CV_EXPORTS void CV_NORETURN check_failed_auto(const Size_<int> v1, const Size_<int> v2, const CheckContext& ctx); |
| 74 | CV_EXPORTS void CV_NORETURN check_failed_MatDepth(const int v1, const int v2, const CheckContext& ctx); |
| 75 | CV_EXPORTS void CV_NORETURN check_failed_MatType(const int v1, const int v2, const CheckContext& ctx); |
| 76 | CV_EXPORTS void CV_NORETURN check_failed_MatChannels(const int v1, const int v2, const CheckContext& ctx); |
| 77 | |
| 78 | CV_EXPORTS void CV_NORETURN check_failed_true(const bool v, const CheckContext& ctx); |
| 79 | CV_EXPORTS void CV_NORETURN check_failed_false(const bool v, const CheckContext& ctx); |
| 80 | |
| 81 | CV_EXPORTS void CV_NORETURN check_failed_auto(const int v, const CheckContext& ctx); |
| 82 | CV_EXPORTS void CV_NORETURN check_failed_auto(const size_t v, const CheckContext& ctx); |
| 83 | CV_EXPORTS void CV_NORETURN check_failed_auto(const float v, const CheckContext& ctx); |
| 84 | CV_EXPORTS void CV_NORETURN check_failed_auto(const double v, const CheckContext& ctx); |
| 85 | CV_EXPORTS void CV_NORETURN check_failed_auto(const Size_<int> v, const CheckContext& ctx); |
| 86 | CV_EXPORTS void CV_NORETURN check_failed_auto(const std::string& v1, const CheckContext& ctx); |
| 87 | CV_EXPORTS void CV_NORETURN check_failed_MatDepth(const int v, const CheckContext& ctx); |
| 88 | CV_EXPORTS void CV_NORETURN check_failed_MatType(const int v, const CheckContext& ctx); |
| 89 | CV_EXPORTS void CV_NORETURN check_failed_MatChannels(const int v, const CheckContext& ctx); |
| 90 | |
| 91 | |
| 92 | #define CV__TEST_EQ(v1, v2) ((v1) == (v2)) |
| 93 | #define CV__TEST_NE(v1, v2) ((v1) != (v2)) |
| 94 | #define CV__TEST_LE(v1, v2) ((v1) <= (v2)) |
| 95 | #define CV__TEST_LT(v1, v2) ((v1) < (v2)) |
| 96 | #define CV__TEST_GE(v1, v2) ((v1) >= (v2)) |
| 97 | #define CV__TEST_GT(v1, v2) ((v1) > (v2)) |
| 98 | |
| 99 | #define CV__CHECK(id, op, type, v1, v2, v1_str, v2_str, msg_str) do { \ |
| 100 | if(CV__TEST_##op((v1), (v2))) ; else { \ |
| 101 | CV__DEFINE_CHECK_CONTEXT(id, msg_str, cv::detail::TEST_ ## op, v1_str, v2_str); \ |
| 102 | cv::detail::check_failed_ ## type((v1), (v2), CV__CHECK_LOCATION_VARNAME(id)); \ |
| 103 | } \ |
| 104 | } while (0) |
| 105 | |
| 106 | #define CV__CHECK_CUSTOM_TEST(id, type, v, test_expr, v_str, test_expr_str, msg_str) do { \ |
| 107 | if(!!(test_expr)) ; else { \ |
| 108 | CV__DEFINE_CHECK_CONTEXT(id, msg_str, cv::detail::TEST_CUSTOM, v_str, test_expr_str); \ |
| 109 | cv::detail::check_failed_ ## type((v), CV__CHECK_LOCATION_VARNAME(id)); \ |
| 110 | } \ |
| 111 | } while (0) |
| 112 | |
| 113 | } // namespace |
| 114 | //! @endcond |
| 115 | |
| 116 | |
| 117 | /// Supported values of these types: int, float, double |
| 118 | #define CV_CheckEQ(v1, v2, msg) CV__CHECK(_, EQ, auto, v1, v2, #v1, #v2, msg) |
| 119 | #define CV_CheckNE(v1, v2, msg) CV__CHECK(_, NE, auto, v1, v2, #v1, #v2, msg) |
| 120 | #define CV_CheckLE(v1, v2, msg) CV__CHECK(_, LE, auto, v1, v2, #v1, #v2, msg) |
| 121 | #define CV_CheckLT(v1, v2, msg) CV__CHECK(_, LT, auto, v1, v2, #v1, #v2, msg) |
| 122 | #define CV_CheckGE(v1, v2, msg) CV__CHECK(_, GE, auto, v1, v2, #v1, #v2, msg) |
| 123 | #define CV_CheckGT(v1, v2, msg) CV__CHECK(_, GT, auto, v1, v2, #v1, #v2, msg) |
| 124 | |
| 125 | /// Check with additional "decoding" of type values in error message |
| 126 | #define CV_CheckTypeEQ(t1, t2, msg) CV__CHECK(_, EQ, MatType, t1, t2, #t1, #t2, msg) |
| 127 | /// Check with additional "decoding" of depth values in error message |
| 128 | #define CV_CheckDepthEQ(d1, d2, msg) CV__CHECK(_, EQ, MatDepth, d1, d2, #d1, #d2, msg) |
| 129 | |
| 130 | #define CV_CheckChannelsEQ(c1, c2, msg) CV__CHECK(_, EQ, MatChannels, c1, c2, #c1, #c2, msg) |
| 131 | |
| 132 | /// Example: type == CV_8UC1 || type == CV_8UC3 |
| 133 | #define CV_CheckType(t, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, MatType, t, (test_expr), #t, #test_expr, msg) |
| 134 | |
| 135 | /// Example: depth == CV_32F || depth == CV_64F |
| 136 | #define CV_CheckDepth(t, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, MatDepth, t, (test_expr), #t, #test_expr, msg) |
| 137 | |
| 138 | /// Example: channel == 1 || channel == 3 |
| 139 | #define CV_CheckChannels(t, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, MatChannels, t, (test_expr), #t, #test_expr, msg) |
| 140 | |
| 141 | /// Example: v == A || v == B |
| 142 | #define CV_Check(v, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, auto, v, (test_expr), #v, #test_expr, msg) |
| 143 | |
| 144 | /// Example: v == true |
| 145 | #define CV_CheckTrue(v, msg) CV__CHECK_CUSTOM_TEST(_, true, v, v, #v, "", msg) |
| 146 | |
| 147 | /// Example: v == false |
| 148 | #define CV_CheckFalse(v, msg) CV__CHECK_CUSTOM_TEST(_, false, v, (!(v)), #v, "", msg) |
| 149 | |
| 150 | /// Some complex conditions: CV_Check(src2, src2.empty() || (src2.type() == src1.type() && src2.size() == src1.size()), "src2 should have same size/type as src1") |
| 151 | // TODO define pretty-printers |
| 152 | |
| 153 | #ifndef NDEBUG |
| 154 | #define CV_DbgCheck(v, test_expr, msg) CV__CHECK_CUSTOM_TEST(_, auto, v, (test_expr), #v, #test_expr, msg) |
| 155 | #define CV_DbgCheckEQ(v1, v2, msg) CV__CHECK(_, EQ, auto, v1, v2, #v1, #v2, msg) |
| 156 | #define CV_DbgCheckNE(v1, v2, msg) CV__CHECK(_, NE, auto, v1, v2, #v1, #v2, msg) |
| 157 | #define CV_DbgCheckLE(v1, v2, msg) CV__CHECK(_, LE, auto, v1, v2, #v1, #v2, msg) |
| 158 | #define CV_DbgCheckLT(v1, v2, msg) CV__CHECK(_, LT, auto, v1, v2, #v1, #v2, msg) |
| 159 | #define CV_DbgCheckGE(v1, v2, msg) CV__CHECK(_, GE, auto, v1, v2, #v1, #v2, msg) |
| 160 | #define CV_DbgCheckGT(v1, v2, msg) CV__CHECK(_, GT, auto, v1, v2, #v1, #v2, msg) |
| 161 | #else |
| 162 | #define CV_DbgCheck(v, test_expr, msg) do { } while (0) |
| 163 | #define CV_DbgCheckEQ(v1, v2, msg) do { } while (0) |
| 164 | #define CV_DbgCheckNE(v1, v2, msg) do { } while (0) |
| 165 | #define CV_DbgCheckLE(v1, v2, msg) do { } while (0) |
| 166 | #define CV_DbgCheckLT(v1, v2, msg) do { } while (0) |
| 167 | #define CV_DbgCheckGE(v1, v2, msg) do { } while (0) |
| 168 | #define CV_DbgCheckGT(v1, v2, msg) do { } while (0) |
| 169 | #endif |
| 170 | |
| 171 | } // namespace |
| 172 | |
| 173 | #endif // OPENCV_CORE_CHECK_HPP |
| 174 | |