Magic.h
// Magic.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2011
#pragma once
#ifndef Ceda_cxUtils_Magic_H
#define Ceda_cxUtils_Magic_H
#include <cstdint>
#ifdef _MSC_VER
// 'this' in base argument list
#pragma warning(disable: 4355)
#endif
namespace ceda
{
// Map address p to a magic value derived from the value of p
inline uint32 GetMagic1(const void* p)
{
return (uint32)(intptr_t)p ^ 0xAAAAAAAA;
}
inline uint32 GetMagic2(const void* p)
{
return (uint32)(intptr_t)p ^ 0x55555555;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// MagicTestDestructed
#ifdef CEDA_CHECK_ASSERTIONS
class MagicTestDestructed
{
public:
MagicTestDestructed() : v(GetMagic1(this)) {}
~MagicTestDestructed() { v = 0; }
void Check() const
{
cxAssert(v == GetMagic1(this));
}
private:
uint32 v;
};
#else
class MagicTestDestructed
{
public:
void Check() const
{
}
};
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
// TwoStateMagic
/*
In debug builds, employs magic values to ensure that the status toggles between states called
'set' and 'reset'. Checks that the status has returned to 'reset' before it destructs.
The purpose of the magic values is to verify object type in cases where reinterpret casts
are performed.
*/
#ifdef CEDA_CHECK_ASSERTIONS
struct TwoStateMagic
{
TwoStateMagic() : v(GetMagic1(this)) {}
void Reset()
{
cxAssert(v == GetMagic2(this));
v = GetMagic1(this);
}
void Set()
{
cxAssert(v == GetMagic1(this));
v = GetMagic2(this);
}
uint32 v;
};
#else
struct TwoStateMagic
{
void Reset() {}
void Set() {}
};
#endif
} // namespace ceda
#endif // include guard