mirror of
https://github.com/OpenMW/openmw.git
synced 2025-11-30 22:04:31 +00:00
Check Nif::RecordPtrT in debug builds
To verify class invariant.
This commit is contained in:
parent
0c2164330b
commit
434f450778
1 changed files with 69 additions and 10 deletions
|
|
@ -19,6 +19,16 @@ namespace Nif
|
||||||
template <class X>
|
template <class X>
|
||||||
class RecordPtrT
|
class RecordPtrT
|
||||||
{
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
enum class State
|
||||||
|
{
|
||||||
|
Index,
|
||||||
|
Ptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
State mState;
|
||||||
|
#endif
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
intptr_t mIndex;
|
intptr_t mIndex;
|
||||||
|
|
@ -27,12 +37,22 @@ namespace Nif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RecordPtrT()
|
RecordPtrT()
|
||||||
: mIndex(-2)
|
:
|
||||||
|
#ifndef NDEBUG
|
||||||
|
mState(State::Index)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
mIndex(-2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordPtrT(X* ptr)
|
RecordPtrT(X* ptr)
|
||||||
: mPtr(ptr)
|
:
|
||||||
|
#ifndef NDEBUG
|
||||||
|
mState(State::Ptr)
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
mPtr(ptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,6 +60,9 @@ namespace Nif
|
||||||
void read(NIFStream* nif)
|
void read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
// Can only read the index once
|
// Can only read the index once
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(mState == State::Index);
|
||||||
|
#endif
|
||||||
assert(mIndex == -2);
|
assert(mIndex == -2);
|
||||||
|
|
||||||
// Store the index for later
|
// Store the index for later
|
||||||
|
|
@ -53,6 +76,10 @@ namespace Nif
|
||||||
/// Resolve index to pointer
|
/// Resolve index to pointer
|
||||||
void post(Reader& nif)
|
void post(Reader& nif)
|
||||||
{
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(mState == State::Index);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mIndex < 0)
|
if (mIndex < 0)
|
||||||
mPtr = nullptr;
|
mPtr = nullptr;
|
||||||
else
|
else
|
||||||
|
|
@ -61,34 +88,66 @@ namespace Nif
|
||||||
if (r == nullptr)
|
if (r == nullptr)
|
||||||
throw std::runtime_error(std::format("Record at {} is nullptr", mIndex));
|
throw std::runtime_error(std::format("Record at {} is nullptr", mIndex));
|
||||||
|
|
||||||
// And cast it
|
X* const ptr = dynamic_cast<X*>(r);
|
||||||
mPtr = dynamic_cast<X*>(r);
|
if (ptr == nullptr)
|
||||||
if (mPtr == nullptr)
|
|
||||||
throw std::runtime_error(std::format("Failed to cast record pointer to {}", typeid(X).name()));
|
throw std::runtime_error(std::format("Failed to cast record pointer to {}", typeid(X).name()));
|
||||||
|
|
||||||
|
mPtr = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
mState = State::Ptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Look up the actual object from the index
|
/// Look up the actual object from the index
|
||||||
const X* getPtr() const
|
const X* getPtr() const
|
||||||
{
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(mState == State::Ptr);
|
||||||
|
#endif
|
||||||
assert(mPtr != nullptr);
|
assert(mPtr != nullptr);
|
||||||
return mPtr;
|
return mPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
X* getPtr()
|
X* getPtr()
|
||||||
{
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(mState == State::Ptr);
|
||||||
|
#endif
|
||||||
assert(mPtr != nullptr);
|
assert(mPtr != nullptr);
|
||||||
return mPtr;
|
return mPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const X& get() const { return *getPtr(); }
|
const X& get() const
|
||||||
X& get() { return *getPtr(); }
|
{
|
||||||
|
return *getPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
X& get()
|
||||||
|
{
|
||||||
|
return *getPtr();
|
||||||
|
}
|
||||||
|
|
||||||
/// Syntactic sugar
|
/// Syntactic sugar
|
||||||
const X* operator->() const { return getPtr(); }
|
const X* operator->() const
|
||||||
X* operator->() { return getPtr(); }
|
{
|
||||||
|
return getPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
X* operator->()
|
||||||
|
{
|
||||||
|
return getPtr();
|
||||||
|
}
|
||||||
|
|
||||||
/// Pointers are allowed to be empty
|
/// Pointers are allowed to be empty
|
||||||
bool empty() const { return mPtr == nullptr; }
|
bool empty() const
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(mState == State::Ptr);
|
||||||
|
#endif
|
||||||
|
return mPtr == nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A list of references to other records. These are read as a list,
|
/** A list of references to other records. These are read as a list,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue