1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
#ifndef __CONDITION_MACROS_H__
#define __CONDITION_MACROS_H__
#include <assert.h>
#include <stdbool.h>
// This file contains macros to use for error checking, assertions,
// abort, return, etc. Each macro should have a comment about when to use it.
// The normal assert() macro should only be used to catch programmer mistakes,
// things which should never happen, even for weird file/network inputs.
// For example, a function which doesn't accept NULL pointer arguments,
// should assert that the parameter is not NULL.
// Used when you want to assert a precondtion (catch programmer mistake)
// but also want to handle the error if it ever happens in a release build.
// Useful if you are unsure if you need to handle the error, for example
// if you are adding assertions to older code. Also useful in cases where
// you know you want both, for example when network or file input can trigger
// the condition
#ifndef assert_or_return
#define assert_or_return(expr, val) { \
assert(expr); \
if (!(expr)) \
{ \
return val; \
} \
}
#endif
// Similar to assert_or_return, except you put it inside the if
// body which handles the error in release builds
#ifndef debug_abort_if_reached
#define debug_abort_if_reached() { \
assert(false); \
}
#endif
// libntech static assert (compile time check):
// has nt_ prefix to not be confused with static_assert
// Why not just static_assert?
// - It is already defined on some platforms (recent RHEL and Ubuntu),
// but in incompatible ways. On RHEL second arg (message) is required,
// on Ubuntu it is not.
// Why not redefine static_assert (undef + define)?
// - Hard to know which static_assert you are using. Include ordering becomes
// very important. Error messages are confusing if you end up using the wrong
// static_assert. Error message would only appear on some platforms, not others.
#ifdef _Static_assert
// Note: The message here is not really necessary,
// most compilers will include this information anyway.
#define nt_static_assert(x) _Static_assert(x, __FILE__ ":" TO_STRING(__LINE__) ": (" #x ") -> false")
#else
#define nt_static_assert(x) { \
switch (0) { \
case 0: /* Cause duplicate case if next is 0 as well */ \
break; \
case x: /* Error if 0 or if non-const expression */ \
break; \
} \
}
#endif
// Useful to assert that 2 string literals are the same, at compile time:
// #define nt_static_assert_string_equal(a,b) nt_static_assert(strcmp(a,b) == 0)
// This macro doesn't work everywhere, yet, because not all the compilers we
// use will optimize out the strcmp() call for string literals.
// TODO: Enable later :)
#endif
|