Skip to content

Commit

Permalink
CHANGE: not using HostileFork's CPP casting macros
Browse files Browse the repository at this point in the history
  • Loading branch information
Oldes committed Jun 8, 2023
1 parent 8cfcc7a commit 58b6043
Showing 1 changed file with 8 additions and 100 deletions.
108 changes: 8 additions & 100 deletions src/include/reb-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@
**
***********************************************************************/

#if defined(__cplusplus) && __cplusplus >= 201103L
#include <type_traits> // used in CASTING MACROS
#endif

#ifdef __OBJC__
#define HAS_BOOL // don't redefine BOOL in objective-c code
#endif
Expand Down Expand Up @@ -427,103 +423,15 @@ typedef void(*CFUNC)(void *);
#define REB_NORETURN
#endif

//
// CASTING MACROS
//
// The following code and explanation is from "Casts for the Masses (in C)":
//
// http://blog.hostilefork.com/c-casts-for-the-masses/
//
// But debug builds don't inline functions--not even no-op ones whose sole
// purpose is static analysis. This means the cast macros add a headache when
// stepping through the debugger, and also they consume a measurable amount
// of runtime. Hence we sacrifice cast checking in the debug builds...and the
// release C++ builds on Travis are relied upon to do the proper optimizations
// as well as report any static analysis errors.
//

#if !defined(__cplusplus) || !defined(NDEBUG)
/* These macros are easier-to-spot variants of the parentheses cast.
* The 'm_cast' is when getting [M]utablity on a const is okay (RARELY!)
* Plain 'cast' can do everything else (except remove volatile)
* The 'c_cast' helper ensures you're ONLY adding [C]onst to a value
*/
#define m_cast(t,v) ((t)(v))
#define cast(t,v) ((t)(v))
#define c_cast(t,v) ((t)(v))
/*
* Q: Why divide roles? A: Frequently, input to cast is const but you
* "just forget" to include const in the result type, gaining mutable
* access. Stray writes to that can cause even time-traveling bugs, with
* effects *before* that write is made...due to "undefined behavior".
*/
#elif defined(__cplusplus) /* for gcc -Wundef */ && (__cplusplus < 201103L)
/* Well-intentioned macros aside, C has no way to enforce that you can't
* cast away a const without m_cast. C++98 builds can do that, at least:
*/
#define m_cast(t,v) const_cast<t>(v)
#define cast(t,v) ((t)(v))
#define c_cast(t,v) const_cast<t>(v)
#else
/* __cplusplus >= 201103L has C++11's type_traits, where we get some
* actual power. cast becomes a reinterpret_cast for pointers and a
* static_cast otherwise. We ensure c_cast added a const and m_cast
* removed one, and that neither affected volatility.
*/
template<typename T, typename V>
T m_cast_helper(V v) {
static_assert(!std::is_const<T>::value,
"invalid m_cast() - requested a const type for output result");
static_assert(std::is_volatile<T>::value == std::is_volatile<V>::value,
"invalid m_cast() - input and output have mismatched volatility");
return const_cast<T>(v);
}
/* reinterpret_cast for pointer to pointer casting (non-class source)*/
template<typename T, typename V,
typename std::enable_if<
!std::is_class<V>::value
&& (std::is_pointer<V>::value || std::is_pointer<T>::value)
>::type* = nullptr>
T cast_helper(V v) { return reinterpret_cast<T>(v); }
/* static_cast for non-pointer to non-pointer casting (non-class source) */
template<typename T, typename V,
typename std::enable_if<
!std::is_class<V>::value
&& (!std::is_pointer<V>::value && !std::is_pointer<T>::value)
>::type* = nullptr>
T cast_helper(V v) { return static_cast<T>(v); }
/* use static_cast on all classes, to go through their cast operators */
template<typename T, typename V,
typename std::enable_if<
std::is_class<V>::value
>::type* = nullptr>
T cast_helper(V v) { return static_cast<T>(v); }
template<typename T, typename V>
T c_cast_helper(V v) {
static_assert(!std::is_const<T>::value,
"invalid c_cast() - did not request const type for output result");
static_assert(std::is_volatile<T>::value == std::is_volatile<V>::value,
"invalid c_cast() - input and output have mismatched volatility");
return const_cast<T>(v);
}
#define m_cast(t, v) m_cast_helper<t>(v)
#define cast(t, v) cast_helper<t>(v)
#define c_cast(t, v) c_cast_helper<t>(v)
#endif

/* These macros are easier-to-spot variants of the parentheses cast.
* The 'm_cast' is when getting [M]utablity on a const is okay (RARELY!)
* Plain 'cast' can do everything else (except remove volatile)
* The 'c_cast' helper ensures you're ONLY adding [C]onst to a value
*/
#define m_cast(t,v) ((t)(v))
#define cast(t,v) ((t)(v))
#define c_cast(t,v) ((t)(v))

//=//// BYTE STRINGS VS UNENCODED CHARACTER STRINGS ///////////////////////=//
//
// Use these when you semantically are talking about unsigned characters as
// bytes. For instance: if you want to count unencoded chars in 'char *' us
// strlen(), and the reader will know that is a count of letters. If you have
// something like UTF-8 with more than one byte per character, use LEN_BYTES.
// The casting macros are derived from "Casts for the Masses (in C)":
//
// http://blog.hostilefork.com/c-casts-for-the-masses/
//
// For APPEND_BYTES_LIMIT, m is the max-size allocated for d (dest)
//
#include <string.h> // for strlen() etc, but also defines `size_t`
#define strsize strlen
#if defined(NDEBUG)
Expand Down

0 comments on commit 58b6043

Please sign in to comment.