diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 1597494d9..609fed8c1 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -419,6 +419,16 @@ void PType::SetDefaultValue(void *base, unsigned offset, TArray { } +//========================================================================== +// +// PType :: SetDefaultValue +// +//========================================================================== + +void PType::SetPointer(void *base, unsigned offset, TArray *stroffs) const +{ +} + //========================================================================== // // PType :: InitializeValue @@ -1550,6 +1560,21 @@ void PPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = 0; } +//========================================================================== +// +// PPointer :: SetDefaultValue +// +//========================================================================== + +void PPointer::SetPointer(void *base, unsigned offset, TArray *special) const +{ + if (PointedType != nullptr && PointedType->IsKindOf(RUNTIME_CLASS(PClass))) + { + // Add to the list of pointers for this class. + special->Push(offset); + } +} + //========================================================================== // // PPointer :: WriteValue @@ -1869,6 +1894,20 @@ void PArray::SetDefaultValue(void *base, unsigned offset, TArray } } +//========================================================================== +// +// PArray :: SetDefaultValue +// +//========================================================================== + +void PArray::SetPointer(void *base, unsigned offset, TArray *special) const +{ + for (unsigned i = 0; i < ElementCount; ++i) + { + ElementType->SetPointer(base, offset + i*ElementSize, special); + } +} + //========================================================================== // // NewArray @@ -2104,6 +2143,23 @@ void PStruct::SetDefaultValue(void *base, unsigned offset, TArray *special) const +{ + for (const PField *field : Fields) + { + if (!(field->Flags & VARF_Native)) + { + field->Type->SetPointer(base, unsigned(offset + field->Offset), special); + } + } +} + //========================================================================== // // PStruct :: WriteValue @@ -3045,14 +3101,9 @@ void PClass::InitializeDefaults() assert(ParentClass != NULL); ParentClass->InitializeSpecials(Defaults); - // and initialize our own special values. - auto it = Symbols.GetIterator(); - PSymbolTable::MapType::Pair *pair; - - while (it.NextPair(pair)) + for (const PField *field : Fields) { - auto field = dyn_cast(pair->Value); - if (field != nullptr && !(field->Flags & VARF_Native)) + if (!(field->Flags & VARF_Native)) { field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } @@ -3270,7 +3321,7 @@ void PClass::BuildFlatPointers () return; } else if (ParentClass == NULL) - { // No parent: FlatPointers is the same as Pointers. + { // No parent (i.e. DObject: FlatPointers is the same as Pointers. if (Pointers == NULL) { // No pointers: Make FlatPointers a harmless non-NULL. FlatPointers = &TheEnd; @@ -3283,7 +3334,19 @@ void PClass::BuildFlatPointers () else { ParentClass->BuildFlatPointers (); - if (Pointers == NULL) + + TArray ScriptPointers; + + // Collect all pointers in scripted fields. These are not part of the Pointers list. + for (auto field : Fields) + { + if (!(field->Flags & VARF_Native)) + { + field->Type->SetPointer(Defaults, unsigned(field->Offset), &ScriptPointers); + } + } + + if (Pointers == nullptr && ScriptPointers.Size() == 0) { // No new pointers: Just use the same FlatPointers as the parent. FlatPointers = ParentClass->FlatPointers; } @@ -3291,20 +3354,34 @@ void PClass::BuildFlatPointers () { // New pointers: Create a new FlatPointers array and add them. int numPointers, numSuperPointers; - // Count pointers defined by this class. - for (numPointers = 0; Pointers[numPointers] != ~(size_t)0; numPointers++) - { } + if (Pointers != nullptr) + { + // Count pointers defined by this class. + for (numPointers = 0; Pointers[numPointers] != ~(size_t)0; numPointers++) + { + } + } + else numPointers = 0; + // Count pointers defined by superclasses. for (numSuperPointers = 0; ParentClass->FlatPointers[numSuperPointers] != ~(size_t)0; numSuperPointers++) { } // Concatenate them into a new array - size_t *flat = new size_t[numPointers + numSuperPointers + 1]; + size_t *flat = new size_t[numPointers + numSuperPointers + ScriptPointers.Size() + 1]; if (numSuperPointers > 0) { memcpy (flat, ParentClass->FlatPointers, sizeof(size_t)*numSuperPointers); } - memcpy (flat + numSuperPointers, Pointers, sizeof(size_t)*(numPointers+1)); + if (numPointers > 0) + { + memcpy(flat + numSuperPointers, Pointers, sizeof(size_t)*numPointers); + } + if (ScriptPointers.Size() > 0) + { + memcpy(flat + numSuperPointers + numPointers, &ScriptPointers[0], sizeof(size_t) * ScriptPointers.Size()); + } + flat[numSuperPointers + numPointers + ScriptPointers.Size()] = ~(size_t)0; FlatPointers = flat; } } diff --git a/src/dobjtype.h b/src/dobjtype.h index 0062c56ab..bf4608c7b 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -252,6 +252,7 @@ public: // initialization when the object is created and destruction when the // object is destroyed. virtual void SetDefaultValue(void *base, unsigned offset, TArray *special=NULL) const; + virtual void SetPointer(void *base, unsigned offset, TArray *ptrofs = NULL) const; // Initialize the value, if needed (e.g. strings) virtual void InitializeValue(void *addr, const void *def) const; @@ -552,6 +553,7 @@ public: virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; + void SetPointer(void *base, unsigned offset, TArray *special = NULL) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; @@ -569,6 +571,9 @@ public: class PClass *ClassRestriction; + // this is only here to block PPointer's implementation + void SetPointer(void *base, unsigned offset, TArray *special = NULL) const override {} + virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; protected: @@ -626,6 +631,7 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *special) const override; + void SetPointer(void *base, unsigned offset, TArray *special) const override; protected: PArray(); @@ -679,6 +685,7 @@ public: void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *specials) const override; + void SetPointer(void *base, unsigned offset, TArray *specials) const override; static void WriteFields(FSerializer &ar, const void *addr, const TArray &fields); bool ReadFields(FSerializer &ar, void *addr) const;