1 | /* Copyright 2019 Google LLC. All Rights Reserved. |
2 | |
3 | Licensed under the Apache License, Version 2.0 (the "License"); |
4 | you may not use this file except in compliance with the License. |
5 | You may obtain a copy of the License at |
6 | |
7 | http://www.apache.org/licenses/LICENSE-2.0 |
8 | |
9 | Unless required by applicable law or agreed to in writing, software |
10 | distributed under the License is distributed on an "AS IS" BASIS, |
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | See the License for the specific language governing permissions and |
13 | limitations under the License. |
14 | ==============================================================================*/ |
15 | |
16 | // self-contained, minimal, CHECK/DCHECK macros similar to glog. |
17 | |
18 | #ifndef RUY_RUY_CHECK_MACROS_H_ |
19 | #define RUY_RUY_CHECK_MACROS_H_ |
20 | |
21 | #include <cstdio> |
22 | #include <cstdlib> |
23 | #include <functional> |
24 | #include <type_traits> |
25 | |
26 | namespace ruy { |
27 | namespace check_macros { |
28 | |
29 | constexpr int kValueBufSize = 32; |
30 | |
31 | template <typename T, typename Enable = void> |
32 | struct ToString { |
33 | static void Run(const T&, char* buf) { snprintf(buf, kValueBufSize, "(?)" ); } |
34 | }; |
35 | |
36 | template <> |
37 | struct ToString<float, void> { |
38 | static void Run(float value, char* buf) { |
39 | snprintf(buf, kValueBufSize, "%.9g" , static_cast<double>(value)); |
40 | } |
41 | }; |
42 | |
43 | template <> |
44 | struct ToString<double, void> { |
45 | static void Run(double value, char* buf) { |
46 | snprintf(buf, kValueBufSize, "%.16g" , value); |
47 | } |
48 | }; |
49 | |
50 | template <typename T> |
51 | struct ToString<T, typename std::enable_if<std::is_integral<T>::value>::type> { |
52 | static void Run(const T& value, char* buf) { |
53 | snprintf(buf, kValueBufSize, "%lld" , static_cast<long long>(value)); |
54 | } |
55 | }; |
56 | |
57 | template <typename T> |
58 | struct ToString<T*, void> { |
59 | static void Run(T* value, char* buf) { |
60 | snprintf(buf, kValueBufSize, "%p" , value); |
61 | } |
62 | }; |
63 | |
64 | template <typename T> |
65 | struct ToString<T, typename std::enable_if<std::is_enum<T>::value>::type> { |
66 | static void Run(const T& value, char* buf) { |
67 | snprintf(buf, kValueBufSize, "(enum value %d)" , static_cast<int>(value)); |
68 | } |
69 | }; |
70 | |
71 | inline void CheckImpl(bool condition, const char* file, int line, |
72 | const char* macro, const char* condition_str) { |
73 | if (!condition) { |
74 | fprintf(stderr, "%s:%d: %s condition not satisfied: %s\n" , file, line, |
75 | macro, condition_str); |
76 | abort(); |
77 | } |
78 | } |
79 | |
80 | template <template <typename T> class Comparison, typename LhsType, |
81 | typename RhsType> |
82 | inline void CheckImpl(const char* file, int line, const char* macro, |
83 | const char* lhs, const LhsType& lhs_value, |
84 | const char* op_symbol, const char* rhs, |
85 | const RhsType& rhs_value) { |
86 | using CommonType = typename std::common_type<LhsType, RhsType>::type; |
87 | if (!Comparison<CommonType>()(lhs_value, rhs_value)) { |
88 | char lhs_value_buf[kValueBufSize]; |
89 | ToString<LhsType>::Run(lhs_value, lhs_value_buf); |
90 | char rhs_value_buf[kValueBufSize]; |
91 | ToString<RhsType>::Run(rhs_value, rhs_value_buf); |
92 | fprintf( |
93 | stderr, |
94 | "%s:%d: %s condition not satisfied: [ %s %s %s ] with values [ " |
95 | "%s %s %s ].\n" , |
96 | file, line, macro, lhs, op_symbol, rhs, lhs_value_buf, op_symbol, |
97 | rhs_value_buf); |
98 | abort(); |
99 | } |
100 | } |
101 | |
102 | #define RUY_CHECK_IMPL(macro, condition) \ |
103 | ruy::check_macros::CheckImpl(condition, __FILE__, __LINE__, #macro, \ |
104 | #condition) |
105 | |
106 | #define RUY_CHECK_OP_IMPL(macro, lhs, op_symbol, op_comparison, rhs) \ |
107 | ruy::check_macros::CheckImpl<op_comparison>( \ |
108 | __FILE__, __LINE__, #macro, #lhs, lhs, #op_symbol, #rhs, rhs) |
109 | |
110 | #define RUY_CHECK(condition) RUY_CHECK_IMPL(RUY_CHECK, condition) |
111 | #define RUY_CHECK_EQ(x, y) \ |
112 | RUY_CHECK_OP_IMPL(RUY_CHECK_EQ, x, ==, std::equal_to, y) |
113 | #define RUY_CHECK_NE(x, y) \ |
114 | RUY_CHECK_OP_IMPL(RUY_CHECK_NE, x, !=, std::not_equal_to, y) |
115 | #define RUY_CHECK_GE(x, y) \ |
116 | RUY_CHECK_OP_IMPL(RUY_CHECK_GE, x, >=, std::greater_equal, y) |
117 | #define RUY_CHECK_GT(x, y) \ |
118 | RUY_CHECK_OP_IMPL(RUY_CHECK_GT, x, >, std::greater, y) |
119 | #define RUY_CHECK_LE(x, y) \ |
120 | RUY_CHECK_OP_IMPL(RUY_CHECK_LE, x, <=, std::less_equal, y) |
121 | #define RUY_CHECK_LT(x, y) RUY_CHECK_OP_IMPL(RUY_CHECK_LT, x, <, std::less, y) |
122 | |
123 | #ifdef NDEBUG |
124 | #define RUY_DCHECK_IS_ENABLED false |
125 | #else |
126 | #define RUY_DCHECK_IS_ENABLED true |
127 | #endif |
128 | |
129 | #define RUY_DCHECK(condition) \ |
130 | if (RUY_DCHECK_IS_ENABLED) RUY_CHECK(condition) |
131 | #define RUY_DCHECK_EQ(x, y) \ |
132 | if (RUY_DCHECK_IS_ENABLED) RUY_CHECK_EQ(x, y) |
133 | #define RUY_DCHECK_NE(x, y) \ |
134 | if (RUY_DCHECK_IS_ENABLED) RUY_CHECK_NE(x, y) |
135 | #define RUY_DCHECK_GE(x, y) \ |
136 | if (RUY_DCHECK_IS_ENABLED) RUY_CHECK_GE(x, y) |
137 | #define RUY_DCHECK_GT(x, y) \ |
138 | if (RUY_DCHECK_IS_ENABLED) RUY_CHECK_GT(x, y) |
139 | #define RUY_DCHECK_LE(x, y) \ |
140 | if (RUY_DCHECK_IS_ENABLED) RUY_CHECK_LE(x, y) |
141 | #define RUY_DCHECK_LT(x, y) \ |
142 | if (RUY_DCHECK_IS_ENABLED) RUY_CHECK_LT(x, y) |
143 | |
144 | } // end namespace check_macros |
145 | } // end namespace ruy |
146 | |
147 | #endif // RUY_RUY_CHECK_MACROS_H_ |
148 | |