Added code to initialize and destroy string variables in classes

- Will require being able to add strings to non-native classes to actually
  test this.
This commit is contained in:
Randy Heit 2016-04-03 17:45:04 -05:00
parent 15208188de
commit 7c8cff64e6
5 changed files with 212 additions and 31 deletions

View file

@ -257,10 +257,12 @@ DObject::DObject (PClass *inClass)
DObject::~DObject () DObject::~DObject ()
{ {
if (!PClass::bShutdown)
{
PClass *type = GetClass();
if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown) if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
{ {
DObject **probe; DObject **probe;
PClass *type = GetClass();
if (!(ObjectFlags & OF_YesReallyDelete)) if (!(ObjectFlags & OF_YesReallyDelete))
{ {
@ -298,6 +300,8 @@ DObject::~DObject ()
} }
} }
} }
type->DestroySpecials(this);
}
} }
void DObject::Destroy () void DObject::Destroy ()

View file

@ -500,6 +500,36 @@ void PType::SkipValue(FArchive &ar, int tag)
} }
} }
//==========================================================================
//
// PType :: SetDefaultValue
//
//==========================================================================
void PType::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *stroffs) const
{
}
//==========================================================================
//
// PType :: InitializeValue
//
//==========================================================================
void PType::InitializeValue(void *addr, const void *def) const
{
}
//==========================================================================
//
// PType :: DestroyValue
//
//==========================================================================
void PType::DestroyValue(void *addr) const
{
}
//========================================================================== //==========================================================================
// //
// PType :: SetValue // PType :: SetValue
@ -1497,6 +1527,43 @@ bool PString::ReadValue(FArchive &ar, void *addr) const
return true; return true;
} }
//==========================================================================
//
// PString :: SetDefaultValue
//
//==========================================================================
void PString::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const
{
new((BYTE *)base + offset) FString;
if (special != NULL)
{
special->Push(std::make_pair(this, offset));
}
}
//==========================================================================
//
// PString :: InitializeValue
//
//==========================================================================
void PString::InitializeValue(void *addr, const void *def) const
{
new(addr) FString(*(FString *)def);
}
//==========================================================================
//
// PString :: DestroyValue
//
//==========================================================================
void PString::DestroyValue(void *addr) const
{
((FString *)addr)->~FString();
}
/* PName ******************************************************************/ /* PName ******************************************************************/
IMPLEMENT_CLASS(PName) IMPLEMENT_CLASS(PName)
@ -2328,6 +2395,20 @@ bool PArray::ReadValue(FArchive &ar, void *addr) const
return false; return false;
} }
//==========================================================================
//
// PArray :: SetDefaultValue
//
//==========================================================================
void PArray::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const
{
for (unsigned i = 0; i < ElementCount; ++i)
{
ElementType->SetDefaultValue(base, offset + i*ElementSize, special);
}
}
//========================================================================== //==========================================================================
// //
// NewArray // NewArray
@ -2581,6 +2662,23 @@ PStruct::PStruct(FName name, DObject *outer)
{ {
} }
//==========================================================================
//
// PStruct :: SetDefaultValue
//
//==========================================================================
void PStruct::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const
{
for (const PField *field : Fields)
{
if (!(field->Flags & VARF_Native))
{
field->Type->SetDefaultValue(base, offset + field->Offset, special);
}
}
}
//========================================================================== //==========================================================================
// //
// PStruct :: WriteValue // PStruct :: WriteValue
@ -3287,9 +3385,50 @@ DObject *PClass::CreateNew() const
ConstructNative (mem); ConstructNative (mem);
((DObject *)mem)->SetClass (const_cast<PClass *>(this)); ((DObject *)mem)->SetClass (const_cast<PClass *>(this));
if (Defaults != NULL)
{
InitializeSpecials(mem);
}
return (DObject *)mem; return (DObject *)mem;
} }
//==========================================================================
//
// PClass :: InitializeSpecials
//
// Initialize special fields of a newly-created instance (e.g. strings).
//
//==========================================================================
void PClass::InitializeSpecials(void *addr) const
{
if (ParentClass != NULL)
{
ParentClass->InitializeSpecials(addr);
}
for (auto tao : SpecialInits)
{
tao.first->InitializeValue((BYTE*)addr + tao.second, Defaults + tao.second);
}
}
//==========================================================================
//
// PClass :: DestroySpecials
//
//==========================================================================
void PClass::DestroySpecials(void *addr) const
{
if (ParentClass != NULL)
{
ParentClass->DestroySpecials(addr);
}
for (auto tao : SpecialInits)
{
tao.first->DestroyValue((BYTE *)addr + tao.second);
}
}
//========================================================================== //==========================================================================
// //
// PClass :: Derive // PClass :: Derive
@ -3388,6 +3527,11 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags)
{ {
Defaults = (BYTE *)M_Realloc(Defaults, Size); Defaults = (BYTE *)M_Realloc(Defaults, Size);
memset(Defaults + oldsize, 0, Size - oldsize); memset(Defaults + oldsize, 0, Size - oldsize);
// If this is a native class, then we must not initialize and
// destroy any of its members. We do, however, initialize the
// default instance since it's not a normal instance of the class.
type->SetDefaultValue(Defaults, field->Offset,
bRuntimeClass ? &SpecialInits : NULL);
} }
return field; return field;
} }

View file

@ -7,6 +7,8 @@
#include "vm.h" #include "vm.h"
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
// Variable/parameter/field flags ------------------------------------------- // Variable/parameter/field flags -------------------------------------------
// Making all these different storage types use a common set of flags seems // Making all these different storage types use a common set of flags seems
@ -200,6 +202,22 @@ public:
static void SkipValue(FArchive &ar); static void SkipValue(FArchive &ar);
static void SkipValue(FArchive &ar, int tag); static void SkipValue(FArchive &ar, int tag);
// Sets the default value for this type at (base + offset)
// If the default value is binary 0, then this function doesn't need
// to do anything, because PClass::Extend() takes care of that.
//
// The stroffs array is so that types that need special initialization
// and destruction (e.g. strings) can add their offsets to it for special
// initialization when the object is created and destruction when the
// object is destroyed.
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const;
// Initialize the value, if needed (e.g. strings)
virtual void InitializeValue(void *addr, const void *def) const;
// Destroy the value, if needed (e.g. strings)
virtual void DestroyValue(void *addr) const;
// Sets the value of a variable of this type at (addr) // Sets the value of a variable of this type at (addr)
virtual void SetValue(void *addr, int val); virtual void SetValue(void *addr, int val);
virtual void SetValue(void *addr, double val); virtual void SetValue(void *addr, double val);
@ -404,6 +422,9 @@ public:
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override; bool ReadValue(FArchive &ar, void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const override;
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
}; };
// Variations of integer types ---------------------------------------------- // Variations of integer types ----------------------------------------------
@ -577,6 +598,8 @@ public:
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override; bool ReadValue(FArchive &ar, void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override;
protected: protected:
PArray(); PArray();
}; };
@ -637,6 +660,7 @@ public:
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override; bool ReadValue(FArchive &ar, void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) const override;
static void WriteFields(FArchive &ar, const void *addr, const TArray<PField *> &fields); static void WriteFields(FArchive &ar, const void *addr, const TArray<PField *> &fields);
bool ReadFields(FArchive &ar, void *addr) const; bool ReadFields(FArchive &ar, void *addr) const;
@ -697,7 +721,9 @@ class PClass : public PStruct
protected: protected:
// We unravel _WITH_META here just as we did for PType. // We unravel _WITH_META here just as we did for PType.
enum { MetaClassNum = CLASSREG_PClassClass }; enum { MetaClassNum = CLASSREG_PClassClass };
TArray<FTypeAndOffset> SpecialInits;
virtual void Derive(PClass *newclass); virtual void Derive(PClass *newclass);
void InitializeSpecials(void *addr) const;
public: public:
typedef PClassClass MetaClass; typedef PClassClass MetaClass;
MetaClass *GetClass() const; MetaClass *GetClass() const;
@ -728,6 +754,7 @@ public:
PField *AddField(FName name, PType *type, DWORD flags=0) override; PField *AddField(FName name, PType *type, DWORD flags=0) override;
void InitializeActorInfo(); void InitializeActorInfo();
void BuildFlatPointers(); void BuildFlatPointers();
void DestroySpecials(void *addr) const;
const PClass *NativeClass() const; const PClass *NativeClass() const;
// Returns true if this type is an ancestor of (or same as) the passed type. // Returns true if this type is an ancestor of (or same as) the passed type.

View file

@ -94,17 +94,23 @@ public:
{ {
return &Array[0]; return &Array[0];
} }
const_iterator begin() const
iterator end()
{ {
return &Array[Count]; return &Array[0];
} }
const_iterator cbegin() const const_iterator cbegin() const
{ {
return &Array[0]; return &Array[0];
} }
iterator end()
{
return &Array[Count];
}
const_iterator end() const
{
return &Array[Count];
}
const_iterator cend() const const_iterator cend() const
{ {
return &Array[Count]; return &Array[Count];

View file

@ -3039,7 +3039,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
{ {
ExpEmit indexv(index->Emit(build)); ExpEmit indexv(index->Emit(build));
int shiftbits = 0; int shiftbits = 0;
while (1 << shiftbits < arraytype->ElementSize) while (1u << shiftbits < arraytype->ElementSize)
{ {
shiftbits++; shiftbits++;
} }