Library of Assembled Shared Sources
enforcer.h
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2023 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43/** @defgroup Enforcers Enforcers
44 * @brief enforcers are release-time counterpart of assertions to ease condition verifying
45 * @author [Bramz]
46 *
47 * Enforcers are a tool described by Alexandrescu [1]
48 * [1] ALEXANDRESCU A. & MARGINEAN P. (2003), Enforcements. June 2003, C++ Experts Forum,
49 * http://www.cuj.com/documents/s=8250/cujcexp2106alexandr/alexandr.htm
50 */
51
52#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_ENFORCER_H
53#define LASS_GUARDIAN_OF_INCLUSION_UTIL_ENFORCER_H
54
55#include "util_common.h"
56#include "impl/lass_errno.h"
57
58namespace lass
59{
60namespace util
61{
62
63/** Exception thrown by enforcers
64 * @ingroup Enforcers
65 */
66class EnforceFailure: public ExceptionMixin<EnforceFailure>
67{
68public:
69 EnforceFailure(std::string msg, std::string loc): ExceptionMixin<EnforceFailure>(std::move(msg), std::move(loc)) {}
70 ~EnforceFailure() noexcept {}
71};
72
73}
74}
75
76/** Enforces the expression to be "true", by using operator!.
77 * @ingroup Enforcers
78 *
79 * taken from:
80 * ALEXANDRESCU A. & MARGINEAN P. (2003), Enforcements. June 2003, C++ Experts Forum,
81 * http://www.cuj.com.
82 *
83 * http://www.cuj.com/documents/s=8250/cujcexp2106alexandr
84 */
85#define LASS_ENFORCE(expression)\
86 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
87 ::lass::util::impl::TruePredicate,\
88 ::lass::util::impl::DefaultRaiser,\
89 (expression), \
90 int(0), \
91 "Expression '" LASS_STRINGIFY(expression) "' failed in '" LASS_HERE "'.")
92
93
94
95/** Enforces a pointer to be different than the NULL pointer.
96 * @ingroup Enforcers
97 */
98#define LASS_ENFORCE_POINTER(pointer) \
99 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
100 ::lass::util::impl::TruePredicate,\
101 ::lass::util::impl::DefaultRaiser,\
102 (pointer), \
103 int(0), \
104 "Null pointer '" LASS_STRINGIFY(pointer) "' detected in '" LASS_HERE "'.")
105
106
107
108/** Enforces a stream to be in the good state.
109 * @ingroup Enforcers
110 */
111#define LASS_ENFORCE_STREAM(stream)\
112 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
113 ::lass::util::impl::StreamPredicate,\
114 ::lass::util::impl::DefaultRaiser,\
115 (stream),\
116 int(0), \
117 "Failing stream '" LASS_STRINGIFY(stream) "' detected in '" LASS_HERE "'.")
118
119
120
121/** Enforces the result of the expression to be zero.
122 * @ingroup Enforcers
123 */
124#define LASS_ENFORCE_ZERO(expression) \
125 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
126 ::lass::util::impl::EqualPredicate,\
127 ::lass::util::impl::ZeroRaiser>(\
128 (expression), \
129 int(0), \
130 "'" LASS_STRINGIFY(expression) "' in '" LASS_HERE "'.")
131
132
133
134/** Enforces the return code of a CLIB function call to be different than -1.
135 * @ingroup Enforcers
136 * Some CLIB functions return -1 on failure. An error code indicating the failure
137 * can be found using errno. LASS_ENFORCE_CLIB will enforce that the return
138 * value of the function call is not -1. If it is -1, it will rais a runtime
139 * exception with the error code errno and its string message translated by strerror().
140 */
141#define LASS_ENFORCE_CLIB(functionCall)\
142 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
143 ::lass::util::impl::UnequalPredicate,\
144 ::lass::util::impl::ClibRaiser,\
145 (functionCall), \
146 int(-1), \
147 "'" LASS_STRINGIFY(functionCall) "' in '" LASS_HERE "'")
148
149#define LASS_ENFORCE_CLIB_EX(functionCall, errorValue)\
150 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
151 ::lass::util::impl::UnequalPredicate,\
152 ::lass::util::impl::ClibRaiser,\
153 (functionCall), \
154 (errorValue), \
155 "'" LASS_STRINGIFY(functionCall) "' in '" LASS_HERE "'")
156
157#define LASS_WARN_CLIB(functionCall)\
158 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
159 ::lass::util::impl::UnequalPredicate,\
160 ::lass::util::impl::ClibWarner,\
161 (functionCall), \
162 int(-1), \
163 "'" LASS_STRINGIFY(functionCall) "' in '" LASS_HERE "'")
164
165
166/** Enforces the return code of a CLIB function call to be zero.
167 * @ingroup Enforcers
168 * Some CLIB functions return zero on success and an error code on failure.
169 * This error code can be translated to a string message with strerror().
170 * LASS_ENFORCE_CLIB_RC will enforce that the return code of the function call
171 * is zero. If it's not, it will raise a runtime exception with the translated
172 * error code.
173 */
174#define LASS_ENFORCE_CLIB_RC(errorCode)\
175 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
176 ::lass::util::impl::EqualPredicate,\
177 ::lass::util::impl::ClibRcRaiser,\
178 (errorCode), \
179 int(0), \
180 "'" LASS_STRINGIFY(errorCode) "' in '" LASS_HERE "'")
181
182
183/** Enforces the return code of a CLIB function call to be zero.
184 * @ingroup Enforcers
185 * Some CLIB functions return zero on success and an error code on failure.
186 * This error code can be translated to a string message with strerror().
187 * LASS_ENFORCE_CLIB_RC will enforce that the return code of the function call
188 * is zero. If it's not, it will raise a runtime exception with the translated
189 * error code.
190 */
191#define LASS_WARN_CLIB_RC(errorCode)\
192 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
193 ::lass::util::impl::EqualPredicate,\
194 ::lass::util::impl::ClibRcWarner,\
195 (errorCode), \
196 int(0), \
197 "'" LASS_STRINGIFY(errorCode) "' in '" LASS_HERE "'")
198
199
200
201/** Enforces the HRESULT of a COM call to be 0 or more.
202 * @ingroup Enforcers
203 */
204#define LASS_ENFORCE_COM(comResult) \
205 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
206 ::lass::util::impl::GreaterEqualPredicate,\
207 ::lass::util::impl::ComRaiser,\
208 (comResult), \
209 int(0), \
210 "'" LASS_STRINGIFY(comResult) "' in '" LASS_HERE "'.")
211
212
213
214#ifdef LASS_HAS_GETLASTERROR
215
216/** Enforces a Win API call to return non-zero and uses GetLastError() to retrieve error code.
217 * @ingroup Enforcers
218 */
219#define LASS_ENFORCE_WINAPI(functionCall)\
220 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
221 ::lass::util::impl::WinAPIPredicate,\
222 ::lass::util::impl::LastErrorRaiser,\
223 (functionCall), \
224 int(0), \
225 "'" LASS_STRINGIFY(functionCall) "' in '" LASS_HERE "'")
226
227#define LASS_WARN_WINAPI(functionCall)\
228 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
229 ::lass::util::impl::WinAPIPredicate,\
230 ::lass::util::impl::LastErrorWarner,\
231 (functionCall), \
232 int(0), \
233 "'" LASS_STRINGIFY(functionCall) "' in '" LASS_HERE "'")
234
235
236/** Enforces the handle to be different than INVALID_HANDLE_VALUE and uses GetLastError() to retrieve error code.
237 * @ingroup Enforcers
238 */
239#define LASS_ENFORCE_HANDLE(handle) \
240 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
241 ::lass::util::impl::UnequalPredicate,\
242 ::lass::util::impl::LastErrorRaiser,\
243 (handle),\
244 INVALID_HANDLE_VALUE, \
245 "Invalid handle '" LASS_STRINGIFY(handle) "' in '" LASS_HERE "'.")
246
247#endif
248
249
250
251/** Enforces an index to be in the half open range [0, iSize).
252 * @ingroup Enforcers
253 */
254#define LASS_ENFORCE_INDEX(index, size)\
255 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
256 ::lass::util::impl::IndexPredicate,\
257 ::lass::util::impl::IndexRaiser,\
258 (index), (size), LASS_HERE)
259
260
261
262/** Enforces a pointer to an object to be dynamic casted to related type.
263 * @ingroup Enforcers
264 * @param t_DestPointer
265 * the type of the pointer to be casted to.
266 * @param v_pointer
267 * a pointer to be casted (note that we don't cast references, use
268 * LASS_ENFORCE_DYNAMIC_REF_CAST for that)
269 */
270#define LASS_ENFORCE_DYNAMIC_CAST(t_DestPointer, v_pointer)\
271 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
272 ::lass::util::impl::TruePredicate,\
273 ::lass::util::impl::DefaultRaiser,\
274 (dynamic_cast<t_DestPointer>(v_pointer)),\
275 int(0), \
276 "Unable to cast to '" LASS_STRINGIFY(t_DestPointer) "': '" LASS_STRINGIFY(v_pointer)\
277 "' is a null pointer or is not of the correct type, '" LASS_HERE "'.")
278
279
280
281/** Enforces a python shared pointer to be dynamic casted to a related python shared pointer.
282 * @ingroup Enforcers
283 * @param t_DestPyObjectPtr
284 * the type of python shared pointer to be casted to.
285 * So if you want to cast to @c PyObjectPtr<Foo>::Type, @a t_DestPyObjectPtr should
286 * be @c PyObjectPtr<Foo>::Type.
287 * @param v_pyObjectPtr
288 * a python shared pointer to be casted.
289 */
290#define LASS_ENFORCE_DYNAMIC_PY_CAST(t_DestPyObjectPtr, v_pyObjectPtr)\
291 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
292 ::lass::util::impl::TruePredicate,\
293 ::lass::util::impl::DefaultRaiser,\
294 ::lass::python::dynamicPyCast<t_DestPyObjectPtr>(v_pyObjectPtr),\
295 int(0), \
296 "Unable to cast to '" LASS_STRINGIFY(t_DestPyObjectPtr) "': '" LASS_STRINGIFY(v_pyObjectPtr)\
297 "' is a null pointer or is not of the correct type, '" LASS_HERE "'.")
298
299
300
301/** always-failing enforcer to block unreachable code paths
302 */
303#define LASS_ENFORCE_UNREACHABLE\
304 *LASS_UTIL_IMPL_MAKE_ENFORCER(\
305 ::lass::util::impl::TruePredicate,\
306 ::lass::util::impl::DefaultRaiser,\
307 (false),\
308 int(0), \
309 "You have reached unreachable code in '" LASS_HERE "'.")
310
311#include "impl/enforcer_impl.h"
312#include <string>
313#include <sstream>
314
315#endif
general utility, debug facilities, ...
Library for Assembled Shared Sources.
Definition config.h:53