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 const 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 const 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 int v1, const int v2, const CheckContext& ctx);
69 CV_EXPORTS void CV_NORETURN check_failed_auto(const size_t v1, const size_t v2, const CheckContext& ctx);
70 CV_EXPORTS void CV_NORETURN check_failed_auto(const float v1, const float v2, const CheckContext& ctx);
71 CV_EXPORTS void CV_NORETURN check_failed_auto(const double v1, const double v2, const CheckContext& ctx);
72 CV_EXPORTS void CV_NORETURN check_failed_auto(const Size_<int> v1, const Size_<int> v2, const CheckContext& ctx);
73 CV_EXPORTS void CV_NORETURN check_failed_MatDepth(const int v1, const int v2, const CheckContext& ctx);
74 CV_EXPORTS void CV_NORETURN check_failed_MatType(const int v1, const int v2, const CheckContext& ctx);
75 CV_EXPORTS void CV_NORETURN check_failed_MatChannels(const int v1, const int v2, const CheckContext& ctx);
76 
77 CV_EXPORTS void CV_NORETURN check_failed_auto(const int v, const CheckContext& ctx);
78 CV_EXPORTS void CV_NORETURN check_failed_auto(const size_t v, const CheckContext& ctx);
79 CV_EXPORTS void CV_NORETURN check_failed_auto(const float v, const CheckContext& ctx);
80 CV_EXPORTS void CV_NORETURN check_failed_auto(const double v, const CheckContext& ctx);
81 CV_EXPORTS void CV_NORETURN check_failed_auto(const Size_<int> v, const CheckContext& ctx);
82 CV_EXPORTS void CV_NORETURN check_failed_auto(const std::string& v1, const CheckContext& ctx);
83 CV_EXPORTS void CV_NORETURN check_failed_MatDepth(const int v, const CheckContext& ctx);
84 CV_EXPORTS void CV_NORETURN check_failed_MatType(const int v, const CheckContext& ctx);
85 CV_EXPORTS void CV_NORETURN check_failed_MatChannels(const int v, const CheckContext& ctx);
86 
87 
88 #define CV__TEST_EQ(v1, v2) ((v1) == (v2))
89 #define CV__TEST_NE(v1, v2) ((v1) != (v2))
90 #define CV__TEST_LE(v1, v2) ((v1) <= (v2))
91 #define CV__TEST_LT(v1, v2) ((v1) < (v2))
92 #define CV__TEST_GE(v1, v2) ((v1) >= (v2))
93 #define CV__TEST_GT(v1, v2) ((v1) > (v2))
94 
95 #define CV__CHECK(id, op, type, v1, v2, v1_str, v2_str, msg_str) do { \
96     if(CV__TEST_##op((v1), (v2))) ; else { \
97         CV__DEFINE_CHECK_CONTEXT(id, msg_str, cv::detail::TEST_ ## op, v1_str, v2_str); \
98         cv::detail::check_failed_ ## type((v1), (v2), CV__CHECK_LOCATION_VARNAME(id)); \
99     } \
100 } while (0)
101 
102 #define CV__CHECK_CUSTOM_TEST(id, type, v, test_expr, v_str, test_expr_str, msg_str) do { \
103     if(!!(test_expr)) ; else { \
104         CV__DEFINE_CHECK_CONTEXT(id, msg_str, cv::detail::TEST_CUSTOM, v_str, test_expr_str); \
105         cv::detail::check_failed_ ## type((v), CV__CHECK_LOCATION_VARNAME(id)); \
106     } \
107 } while (0)
108 
109 } // namespace
110 //! @endcond
111 
112 
113 /// Supported values of these types: int, float, double
114 #define CV_CheckEQ(v1, v2, msg)  CV__CHECK(_, EQ, auto, v1, v2, #v1, #v2, msg)
115 #define CV_CheckNE(v1, v2, msg)  CV__CHECK(_, NE, auto, v1, v2, #v1, #v2, msg)
116 #define CV_CheckLE(v1, v2, msg)  CV__CHECK(_, LE, auto, v1, v2, #v1, #v2, msg)
117 #define CV_CheckLT(v1, v2, msg)  CV__CHECK(_, LT, auto, v1, v2, #v1, #v2, msg)
118 #define CV_CheckGE(v1, v2, msg)  CV__CHECK(_, GE, auto, v1, v2, #v1, #v2, msg)
119 #define CV_CheckGT(v1, v2, msg)  CV__CHECK(_, GT, auto, v1, v2, #v1, #v2, msg)
120 
121 /// Check with additional "decoding" of type values in error message
122 #define CV_CheckTypeEQ(t1, t2, msg)  CV__CHECK(_, EQ, MatType, t1, t2, #t1, #t2, msg)
123 /// Check with additional "decoding" of depth values in error message
124 #define CV_CheckDepthEQ(d1, d2, msg)  CV__CHECK(_, EQ, MatDepth, d1, d2, #d1, #d2, msg)
125 
126 #define CV_CheckChannelsEQ(c1, c2, msg)  CV__CHECK(_, EQ, MatChannels, c1, c2, #c1, #c2, msg)
127 
128 /// Example: type == CV_8UC1 || type == CV_8UC3
129 #define CV_CheckType(t, test_expr, msg)  CV__CHECK_CUSTOM_TEST(_, MatType, t, (test_expr), #t, #test_expr, msg)
130 
131 /// Example: depth == CV_32F || depth == CV_64F
132 #define CV_CheckDepth(t, test_expr, msg)  CV__CHECK_CUSTOM_TEST(_, MatDepth, t, (test_expr), #t, #test_expr, msg)
133 
134 /// Example: v == A || v == B
135 #define CV_Check(v, test_expr, msg)  CV__CHECK_CUSTOM_TEST(_, auto, v, (test_expr), #v, #test_expr, msg)
136 
137 /// Some complex conditions: CV_Check(src2, src2.empty() || (src2.type() == src1.type() && src2.size() == src1.size()), "src2 should have same size/type as src1")
138 // TODO define pretty-printers
139 
140 #ifndef NDEBUG
141 #define CV_DbgCheck(v, test_expr, msg)  CV__CHECK_CUSTOM_TEST(_, auto, v, (test_expr), #v, #test_expr, msg)
142 #define CV_DbgCheckEQ(v1, v2, msg)  CV__CHECK(_, EQ, auto, v1, v2, #v1, #v2, msg)
143 #define CV_DbgCheckNE(v1, v2, msg)  CV__CHECK(_, NE, auto, v1, v2, #v1, #v2, msg)
144 #define CV_DbgCheckLE(v1, v2, msg)  CV__CHECK(_, LE, auto, v1, v2, #v1, #v2, msg)
145 #define CV_DbgCheckLT(v1, v2, msg)  CV__CHECK(_, LT, auto, v1, v2, #v1, #v2, msg)
146 #define CV_DbgCheckGE(v1, v2, msg)  CV__CHECK(_, GE, auto, v1, v2, #v1, #v2, msg)
147 #define CV_DbgCheckGT(v1, v2, msg)  CV__CHECK(_, GT, auto, v1, v2, #v1, #v2, msg)
148 #else
149 #define CV_DbgCheck(v, test_expr, msg)  do { } while (0)
150 #define CV_DbgCheckEQ(v1, v2, msg)  do { } while (0)
151 #define CV_DbgCheckNE(v1, v2, msg)  do { } while (0)
152 #define CV_DbgCheckLE(v1, v2, msg)  do { } while (0)
153 #define CV_DbgCheckLT(v1, v2, msg)  do { } while (0)
154 #define CV_DbgCheckGE(v1, v2, msg)  do { } while (0)
155 #define CV_DbgCheckGT(v1, v2, msg)  do { } while (0)
156 #endif
157 
158 } // namespace
159 
160 #endif // OPENCV_CORE_CHECK_HPP
161