openclonk/src/script/C4PropList.cpp

237 lines
4.9 KiB
C++

/*
* Copyright (c) 2009 Günther Brammer <gbrammer@gmx.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* "Clonk" is a registered trademark of Matthes Bender.
*/
#include <C4Include.h>
#include <C4PropList.h>
#include <C4GameObjects.h>
#include <C4Game.h>
#include <C4Object.h>
void C4PropList::AddRef(C4Value *pRef)
{
pRef->NextRef = FirstRef;
FirstRef = pRef;
}
void C4PropList::DelRef(const C4Value * pRef, C4Value * pNextRef)
{
// References to objects never have HasBaseArray set
if(pRef == FirstRef)
FirstRef = pNextRef;
else
{
C4Value *pVal = FirstRef;
while(pVal->NextRef && pVal->NextRef != pRef)
pVal = pVal->NextRef;
assert(pVal->NextRef);
pVal->NextRef = pNextRef;
}
if (FirstRef) return;
// These classes have their own memory management
if (dynamic_cast<C4Object *>(this)) return;
if (dynamic_cast<C4Def *>(this)) return;
delete this;
}
void C4PropList::AssignRemoval()
{
while(FirstRef) FirstRef->Set0();
Game.ClearPointers(this);
}
C4PropList::C4PropList(C4PropList * prototype):
Number(-1), Status(1),
FirstRef(NULL), prototype(prototype)
{
// Enumerate object
do
Number = ++Game.ObjectEnumerationIndex;
while (::Objects.PropLists.Get(Game.ObjectEnumerationIndex));
::Objects.PropLists.Add(this);
}
C4PropList::~C4PropList()
{
while (FirstRef)
{
// Manually kill references so DelRef doesn't destroy us again
FirstRef->Data = 0; FirstRef->Type = C4V_Any;
C4Value *ref = FirstRef;
FirstRef = FirstRef->NextRef;
ref->NextRef = NULL;
}
::Objects.PropLists.Remove(this);
assert(!::Objects.ObjectNumber(this));
}
const char * C4PropList::GetName()
{
C4String * s = GetPropertyStr(P_Name);
if (!s) return "";
return s->GetCStr();
}
void C4PropList::SetName(const char* NewName)
{
if(!NewName)
ResetProperty(Strings.P[P_Name]);
else
{
C4Value v = C4VString(NewName);
SetProperty(Strings.P[P_Name], v);
}
}
C4Object * C4PropList::GetObject()
{
if (prototype) return prototype->GetObject();
return 0;
}
C4Def * C4PropList::GetDef()
{
if (prototype) return prototype->GetDef();
return 0;
}
template<> template<>
unsigned int C4Set<C4Property>::Hash<C4String *>(C4String * e)
{
return e->Hash;
}
template<> template<>
bool C4Set<C4Property>::Equals<C4String *>(C4Property a, C4String * b)
{
return a.Key == b;
}
template<> template<>
unsigned int C4Set<C4Property>::Hash<C4Property>(C4Property p)
{
return p.Key->Hash;
}
bool C4PropList::GetProperty(C4String * k, C4Value & to)
{
// The prototype is special
if (k == Strings.P[P_Prototype])
{
to = C4VPropList(prototype);
return true;
}
if (Properties.Has(k))
{
to.SetRef(&Properties.Get(k).Value);
return true;
}
if (prototype)
{
return prototype->GetProperty(k, to);
}
return false;
}
C4String * C4PropList::GetPropertyStr(C4PropertyName n)
{
C4String * k = Strings.P[n];
if (Properties.Has(k))
{
return Properties.Get(k).Value.getStr();
}
if (prototype)
{
return prototype->GetPropertyStr(n);
}
return 0;
}
int32_t C4PropList::GetPropertyInt(C4PropertyName n)
{
C4String * k = Strings.P[n];
if (Properties.Has(k))
{
return Properties.Get(k).Value.getInt();
}
if (prototype)
{
return prototype->GetPropertyInt(n);
}
return 0;
}
void C4PropList::SetProperty(C4String * k, const C4Value & to)
{
assert(Strings.Set.Has(k));
if (k == Strings.P[P_Prototype] && to.GetType() == C4V_PropList)
{
prototype = to.GetData().PropList;
return;
}
if (Properties.Has(k))
{
Properties.Get(k).Value = to;
}
else
{
C4Property p(k, to);
Properties.Add(p);
}
}
void C4PropList::ResetProperty(C4String * k)
{
Properties.Remove(k);
}
template<> template<>
unsigned int C4Set<C4PropList *>::Hash<int>(int e)
{
unsigned int hash = 4, tmp;
hash += e >> 16;
tmp = ((e & 0xffff) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
hash += hash >> 11;
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
return hash;
}
template<> template<>
unsigned int C4Set<C4PropList *>::Hash<C4PropList *>(C4PropList * e)
{
return Hash(e->Number);
}
template<> template<>
bool C4Set<C4PropList *>::Equals<int>(C4PropList * a, int b)
{
return a->Number == b;
}