openclonk/src/script/C4Aul.cpp

622 lines
14 KiB
C++
Raw Normal View History

2009-05-08 13:28:41 +00:00
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001, 2004, 2007-2008 Sven Eberhardt
2011-09-01 14:58:52 +00:00
* Copyright (c) 2001, 2009 Peter Wortmann
* Copyright (c) 2006-2009, 2011 Günther Brammer
* Copyright (c) 2007 Matthes Bender
* Copyright (c) 2009 Nicolas Hake
* Copyright (c) 2010 Benjamin Herr
* Copyright (c) 2010 Martin Plicht
2009-05-08 13:28:41 +00:00
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* 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.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
// C4Aul script engine CP conversion
#include <C4Include.h>
#include <C4Aul.h>
2009-04-21 21:44:56 +00:00
#include <C4AulExec.h>
#include <C4AulDebug.h>
2009-05-08 13:28:41 +00:00
#include <C4Config.h>
#include <C4Def.h>
#include <C4Log.h>
#include <C4Components.h>
2010-01-13 17:07:58 +00:00
#include <C4Application.h>
#include <C4LangStringTable.h>
2009-05-08 13:28:41 +00:00
C4AulError::C4AulError(): shown(false) {}
2009-05-08 13:28:41 +00:00
void C4AulError::show()
2010-03-28 18:58:01 +00:00
{
shown = true;
2009-05-08 13:28:41 +00:00
// simply log error message
2010-03-28 18:58:01 +00:00
if (sMessage)
2009-05-08 13:28:41 +00:00
DebugLog(sMessage.getData());
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc::C4AulFunc(C4AulScript *pOwner, const char *pName, bool bAtEnd):
2011-09-25 19:09:16 +00:00
Name(pName ? Strings.RegString(pName) : 0),
2010-03-28 18:58:01 +00:00
MapNext(NULL),
LinkedTo (NULL),
OverloadedBy (NULL)
{
2009-05-08 13:28:41 +00:00
// reg2list (at end or at the beginning)
Owner = pOwner;
2010-03-28 18:58:01 +00:00
if (bAtEnd)
2009-05-08 13:28:41 +00:00
{
2010-01-25 04:00:59 +00:00
if ((Prev = Owner->FuncL))
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Prev->Next = this;
Owner->FuncL = this;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Owner->Func0 = this;
Owner->FuncL = this;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
Next = NULL;
}
else
{
2010-01-25 04:00:59 +00:00
if ((Next = Owner->Func0))
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Next->Prev = this;
Owner->Func0 = this;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Owner->Func0 = this;
Owner->FuncL = this;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
Prev = NULL;
}
// add to global lookuptable with this name
if (GetName())
Owner->Engine->FuncLookUp.Add(this, bAtEnd);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc::~C4AulFunc()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// if it's a global: remove the global link!
if (LinkedTo && Owner)
if (LinkedTo->Owner == Owner->Engine)
delete LinkedTo;
// unlink func
if (LinkedTo)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// find prev
C4AulFunc* pAkt = this;
2010-03-28 18:58:01 +00:00
while (pAkt->LinkedTo != this) pAkt = pAkt->LinkedTo;
if (pAkt == LinkedTo)
2009-05-08 13:28:41 +00:00
pAkt->LinkedTo = NULL;
else
pAkt->LinkedTo = LinkedTo;
LinkedTo = NULL;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// remove from list
if (Prev) Prev->Next = Next;
if (Next) Next->Prev = Prev;
if (Owner)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (Owner->Func0 == this) Owner->Func0 = Next;
if (Owner->FuncL == this) Owner->FuncL = Prev;
if (GetName())
Owner->Engine->FuncLookUp.Remove(this);
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulFunc::DestroyLinked()
{
// delete all functions linked to this one.
2010-03-28 18:58:01 +00:00
while (LinkedTo)
2009-05-08 13:28:41 +00:00
delete LinkedTo;
}
StdStrBuf C4AulScriptFunc::GetFullName()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// "lost" function?
StdStrBuf sOwner;
if (!Owner)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
sOwner.Ref("(unknown) ");
2010-03-28 18:58:01 +00:00
}
else if (Owner->GetPropList() && Owner->GetPropList()->GetDef())
2010-03-28 18:58:01 +00:00
{
sOwner.Format("%s.", Owner->GetPropList()->GetDef()->id.ToString());
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else if (Owner->Engine == Owner)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
sOwner.Ref("global ");
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
sOwner.Ref("game ");
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
StdStrBuf sResult;
sResult.Format("%s%s", sOwner.getData(), GetName());
2009-05-08 13:28:41 +00:00
return sResult;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulScript::C4AulScript()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// not compiled
State = ASS_NONE;
IncludesResolved = false;
// defaults
Strict = MAXSTRICT;
Resolving=false;
2009-05-08 13:28:41 +00:00
Temporary = false;
LocalNamed.Reset();
// prepare lists
Child0 = ChildL = Prev = Next = NULL;
Owner = Engine = NULL;
Func0 = FuncL = NULL;
// prepare include list
2011-02-25 23:48:19 +00:00
Includes.clear();
Appends.clear();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulScript::~C4AulScript()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// clear
Clear();
// unreg
Unreg();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScript::Unreg()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// remove from list
if (Prev) Prev->Next = Next; else if (Owner) Owner->Child0 = Next;
if (Next) Next->Prev = Prev; else if (Owner) Owner->ChildL = Prev;
Prev = Next = Owner = NULL;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScript::Clear()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// remove includes
2011-02-25 23:48:19 +00:00
Includes.clear();
Appends.clear();
2009-05-08 13:28:41 +00:00
// delete child scripts + funcs
while (Child0) // Child0->Unreg();
2010-03-28 18:58:01 +00:00
if (Child0->Delete()) delete Child0; else Child0->Unreg();
2009-05-08 13:28:41 +00:00
while (Func0) delete Func0;
// reset flags
2009-05-08 13:28:41 +00:00
State = ASS_NONE;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScript::Reg2List(C4AulScriptEngine *pEngine, C4AulScript *pOwner)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// already regged? (def reloaded)
if (Owner) return;
// reg to list
Engine = pEngine;
2010-01-25 04:00:59 +00:00
if ((Owner = pOwner))
2010-03-28 18:58:01 +00:00
{
2010-01-25 04:00:59 +00:00
if ((Prev = Owner->ChildL))
2009-05-08 13:28:41 +00:00
Prev->Next = this;
else
Owner->Child0 = this;
Owner->ChildL = this;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
Prev = NULL;
Next = NULL;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc *C4AulScript::GetOverloadedFunc(C4AulFunc *ByFunc)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert(ByFunc);
// search local list
C4AulFunc *f = ByFunc;
if (f) f = f->Prev; else f = FuncL;
while (f)
2010-03-28 18:58:01 +00:00
{
if (SEqual(ByFunc->GetName(), f->GetName())) break;
2009-05-08 13:28:41 +00:00
f = f->Prev;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
#ifdef _DEBUG
C4AulFunc * f2 = Engine ? Engine->GetFunc(ByFunc->GetName(), this, ByFunc) : NULL;
2009-05-08 13:28:41 +00:00
assert (f == f2);
#endif
// nothing found? then search owner, if existant
if (!f && Owner)
2010-03-28 18:58:01 +00:00
{
if ((f = Owner->GetFuncRecursive(ByFunc->GetName())))
2009-05-08 13:28:41 +00:00
// just found the global link?
if (ByFunc && f->LinkedTo == ByFunc)
f = Owner->GetOverloadedFunc(f);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// return found fn
return f;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc *C4AulScript::GetFuncRecursive(const char *pIdtf)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// search local list
C4AulFunc *f = GetFunc(pIdtf);
if (f) return f;
// nothing found? then search owner, if existant
else if (Owner) return Owner->GetFuncRecursive(pIdtf);
return NULL;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc *C4AulScript::GetFunc(const char *pIdtf)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4AulFunc * f = Engine ? Engine->GetFunc(pIdtf, this, NULL) : NULL;
#if 0
// search func list
C4AulFunc *f2 = FuncL;
while (f2)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (SEqual(pIdtf, f2->Name)) break;
f2 = f2->Prev;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
assert (f == f2);
#endif
return f;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulScriptFunc *C4AulScript::GetSFuncWarn(const char *pIdtf, C4AulAccess AccNeeded, const char *WarnStr)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// no identifier
if (!pIdtf || !pIdtf[0]) return NULL;
// get func?
C4AulScriptFunc *pFn = GetSFunc(pIdtf, AccNeeded, true);
2009-05-08 13:28:41 +00:00
if (!pFn)
Warn(FormatString("Error getting %s function '%s'", WarnStr, pIdtf).getData(), NULL);
return pFn;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulScriptFunc *C4AulScript::GetSFunc(const char *pIdtf, C4AulAccess AccNeeded, bool fFailsafe)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// failsafe call
if (*pIdtf=='~') { fFailsafe=true; pIdtf++; }
2009-05-08 13:28:41 +00:00
// get function reference from table
C4AulScriptFunc *pFn = GetSFunc(pIdtf);
// undefined function
if (!pFn)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// not failsafe?
if (!fFailsafe)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// show error
C4AulParseError err(this, "Undefined function: ", pIdtf);
err.show();
}
2010-03-28 18:58:01 +00:00
return NULL;
}
2009-05-08 13:28:41 +00:00
// check access
if (pFn->Access < AccNeeded)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// no access? show error
C4AulParseError err(this, "insufficient access level");
err.show();
// don't even break in strict execution, because the caller might be non-strict
//if (Strict) return NULL;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// return found function
return pFn;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulScriptFunc *C4AulScript::GetSFunc(const char *pIdtf)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get func by name; return script func
if (!pIdtf) return NULL;
if (!pIdtf[0]) return NULL;
if (pIdtf[0] == '~') pIdtf++;
C4AulFunc *f = GetFunc(pIdtf);
if (!f) return NULL;
return f->SFunc();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
std::string C4AulScript::Translate(const std::string &text) const
{
const C4AulScript *cursor = this;
while (cursor)
{
try
{
if (cursor->stringTable)
return cursor->stringTable->Translate(text);
}
catch (C4LangStringTable::NoSuchTranslation &)
{
// Ignore, soldier on
}
// Walk tree structure upwards
cursor = cursor->Owner;
}
throw C4LangStringTable::NoSuchTranslation(text);
}
2009-05-08 13:28:41 +00:00
void C4AulScriptFunc::CopyBody(C4AulScriptFunc &FromFunc)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// copy some members, that are set before linking
Access = FromFunc.Access;
Script = FromFunc.Script;
VarNamed = FromFunc.VarNamed;
ParNamed = FromFunc.ParNamed;
ParCount = FromFunc.ParCount;
2009-05-08 13:28:41 +00:00
pOrgScript = FromFunc.pOrgScript;
2010-03-28 18:58:01 +00:00
for (int i = 0; i < C4AUL_MAX_Par; i++)
2009-05-08 13:28:41 +00:00
ParType[i] = FromFunc.ParType[i];
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScript::AddFunc(const char *pIdtf, C4ScriptFnDef* Def)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// create def func
new C4AulDefFunc(this, pIdtf, Def);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
/*--- C4AulScriptEngine ---*/
C4AulScriptEngine::C4AulScriptEngine():
2010-03-28 18:58:01 +00:00
warnCnt(0), errCnt(0), nonStrictCnt(0), lineCnt(0)
{
2009-05-08 13:28:41 +00:00
// /me r b engine
Engine = this;
ScriptName.Ref(C4CFN_System);
Strict = MAXSTRICT;
GlobalNamedNames.Reset();
GlobalNamed.Reset();
GlobalNamed.SetNameList(&GlobalNamedNames);
GlobalConstNames.Reset();
GlobalConsts.Reset();
GlobalConsts.SetNameList(&GlobalConstNames);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulScriptEngine::~C4AulScriptEngine() { Clear(); }
void C4AulScriptEngine::Clear()
2010-03-28 18:58:01 +00:00
{
#ifndef NOAULDEBUG
2009-04-21 21:44:56 +00:00
// stop debugger
delete C4AulDebug::GetDebugger();
#endif
2009-05-08 13:28:41 +00:00
// clear inherited
C4AulScript::Clear();
// clear own stuff
// reset values
warnCnt = errCnt = nonStrictCnt = lineCnt = 0;
// resetting name lists will reset all data lists, too
// except not...
GlobalNamedNames.Reset();
GlobalConstNames.Reset();
GlobalConsts.Reset();
GlobalConsts.SetNameList(&GlobalConstNames);
GlobalNamed.Reset();
GlobalNamed.SetNameList(&GlobalNamedNames);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScriptEngine::UnLink()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// unlink scripts
C4AulScript::UnLink();
// Do not clear global variables and constants, because they are registered by the
// preparser or other parts. Note that keeping those fields means that you cannot delete a global
2009-05-08 13:28:41 +00:00
// variable or constant at runtime by removing it from the script.
//GlobalNamedNames.Reset();
//GlobalConstNames.Reset();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScriptEngine::RegisterGlobalConstant(const char *szName, const C4Value &rValue)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Register name and set value.
// AddName returns the index of existing element if the name is assigned already.
// That is OK, since it will only change the value of the global ("overload" it).
// A warning would be nice here. However, this warning would show up whenever a script
// containing globals constants is recompiled.
GlobalConsts[GlobalConstNames.AddName(szName)] = rValue;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4AulScriptEngine::GetGlobalConstant(const char *szName, C4Value *pTargetValue)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get index of global by name
int32_t iConstIndex = GlobalConstNames.GetItemNr(szName);
// not found?
if (iConstIndex<0) return false;
// if it's found, assign the value if desired
if (pTargetValue) *pTargetValue = GlobalConsts[iConstIndex];
// constant exists
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4AulScriptEngine::Denumerate(C4ValueNumbers * numbers)
2010-03-28 18:58:01 +00:00
{
GlobalNamed.Denumerate(numbers);
2009-05-08 13:28:41 +00:00
// runtime data only: don't denumerate consts
GameScript.ScenPropList->Denumerate(numbers);
return true;
2010-03-28 18:58:01 +00:00
}
2009-04-21 21:44:56 +00:00
void C4AulScriptEngine::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4ValueMapData GlobalNamedDefault;
GlobalNamedDefault.SetNameList(&GlobalNamedNames);
pComp->Value(mkNamingAdapt(mkParAdapt(GlobalNamed, numbers), "StaticVariables", GlobalNamedDefault));
pComp->Value(mkNamingAdapt(mkParAdapt(*GameScript.ScenPropList, numbers), "Scenario"));
2010-03-28 18:58:01 +00:00
}
2009-04-21 21:44:56 +00:00
std::list<const char*> C4AulScriptEngine::GetFunctionNames(C4AulScript * script)
{
std::list<const char*> functions;
for (C4AulFunc *pFn = Func0; pFn; pFn = pFn->Next)
{
if (pFn->GetPublic())
{
functions.push_back(pFn->GetName());
}
}
// Add object or scenario script functions
if (script)
{
bool divider = false;
C4AulFunc *f = script->FuncL;
C4AulScriptFunc *pRef;
// Scan all functions
while (f)
{
if ((pRef = f->SFunc()))
{
// Public functions only
if (pRef->Access == AA_PUBLIC)
{
// Insert divider if necessary
if (!divider)
functions.push_back(0);
divider = true;
// Add function
functions.push_back(pRef->GetName());
}
}
f = f->Prev;
}
}
return functions;
}
2009-05-08 13:28:41 +00:00
/*--- C4AulFuncMap ---*/
static const size_t CapacityInc = 1024;
2010-01-25 04:00:59 +00:00
C4AulFuncMap::C4AulFuncMap(): Funcs(new C4AulFunc*[CapacityInc]), FuncCnt(0), Capacity(CapacityInc)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
memset(Funcs, 0, sizeof (C4AulFunc *) * Capacity);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFuncMap::~C4AulFuncMap()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
delete[] Funcs;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
unsigned int C4AulFuncMap::Hash(const char * name)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Fowler/Noll/Vo hash
unsigned int h = 2166136261u;
while (*name)
h = (h ^ *(name++)) * 16777619;
return h;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc * C4AulFuncMap::GetFirstFunc(const char * Name)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (!Name) return NULL;
C4AulFunc * Func = Funcs[Hash(Name) % Capacity];
while (Func && !SEqual(Name, Func->GetName()))
2009-05-08 13:28:41 +00:00
Func = Func->MapNext;
return Func;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc * C4AulFuncMap::GetNextSNFunc(const C4AulFunc * After)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4AulFunc * Func = After->MapNext;
while (Func && !SEqual(After->GetName(), Func->GetName()))
2009-05-08 13:28:41 +00:00
Func = Func->MapNext;
return Func;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc * C4AulFuncMap::GetFunc(const char * Name, const C4AulScript * Owner, const C4AulFunc * After)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (!Name) return NULL;
C4AulFunc * Func = Funcs[Hash(Name) % Capacity];
if (After)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
while (Func && Func != After)
Func = Func->MapNext;
if (Func)
Func = Func->MapNext;
2010-03-28 18:58:01 +00:00
}
while (Func && (Func->Owner != Owner || !SEqual(Name, Func->GetName())))
2009-05-08 13:28:41 +00:00
Func = Func->MapNext;
return Func;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulFuncMap::Add(C4AulFunc * func, bool bAtStart)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (++FuncCnt > Capacity)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int NCapacity = Capacity + CapacityInc;
C4AulFunc ** NFuncs = new C4AulFunc*[NCapacity];
memset(NFuncs, 0, sizeof (C4AulFunc *) * NCapacity);
for (int i = 0; i < Capacity; ++i)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
while (Funcs[i])
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Get a pointer to the bucket
C4AulFunc ** pNFunc = &(NFuncs[Hash(Funcs[i]->GetName()) % NCapacity]);
2009-05-08 13:28:41 +00:00
// get a pointer to the end of the linked list
while (*pNFunc) pNFunc = &((*pNFunc)->MapNext);
// Move the func over
*pNFunc = Funcs[i];
// proceed with the next list member
Funcs[i] = Funcs[i]->MapNext;
// Terminate the linked list
(*pNFunc)->MapNext = 0;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
Capacity = NCapacity;
delete [] Funcs;
Funcs = NFuncs;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Get a pointer to the bucket
C4AulFunc ** pFunc = &(Funcs[Hash(func->GetName()) % Capacity]);
2009-05-08 13:28:41 +00:00
if (bAtStart)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// move the current first to the second position
func->MapNext = *pFunc;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get a pointer to the end of the linked list
while (*pFunc)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pFunc = &((*pFunc)->MapNext);
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Add the func
*pFunc = func;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulFuncMap::Remove(C4AulFunc * func)
2010-03-28 18:58:01 +00:00
{
C4AulFunc ** pFunc = &Funcs[Hash(func->GetName()) % Capacity];
2009-05-08 13:28:41 +00:00
while (*pFunc != func)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pFunc = &((*pFunc)->MapNext);
assert(*pFunc); // crash on remove of a not contained func
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
*pFunc = (*pFunc)->MapNext;
--FuncCnt;
2010-03-28 18:58:01 +00:00
}
C4AulScriptEngine ScriptEngine;