Completely removed references from the engine, changed array semantics to not copy automatically, implemented postfix ++/-- correctly

stable-5.1
Peter Wortmann 2010-04-08 02:47:45 +02:00
parent efb5925129
commit edb4a4a0b2
19 changed files with 218 additions and 684 deletions

View File

@ -686,13 +686,13 @@ void C4Def::Draw(C4Facet &cgo, bool fSelected, DWORD iColor, C4Object *pObj, int
if (pObj)
{
instance = pObj->pMeshInstance;
pObj->GetPropertyVal(P_PictureTransformation, value);
pObj->GetPropertyVal(P_PictureTransformation, &value);
}
else
{
dummy.reset(new StdMeshInstance(*graphics->Mesh));
instance = dummy.get();
GetPropertyVal(P_PictureTransformation, value);
GetPropertyVal(P_PictureTransformation, &value);
}
@ -1394,9 +1394,9 @@ C4PropList *C4Def::GetActionByName(C4String *actname)
// If we get the null string or ActIdle by name, return NULL action
if (!actname || actname == Strings.P[P_Idle]) return NULL;
// otherwise, query actmap
C4Value ActMap; GetPropertyVal(P_ActMap, ActMap);
C4Value ActMap; GetPropertyVal(P_ActMap, &ActMap);
if (!ActMap.getPropList()) return false;
C4Value Action; ActMap.getPropList()->GetPropertyVal(actname, Action);
C4Value Action; ActMap.getPropList()->GetPropertyVal(actname, &Action);
if (!Action.getPropList()) return false;
return Action.getPropList();
}

View File

@ -733,12 +733,12 @@ void C4GraphicsOverlay::UpdateFacet()
return;
C4Value v;
pDef->GetPropertyVal(P_ActMap, v);
pDef->GetPropertyVal(P_ActMap, &v);
C4PropList *actmap = v.getPropList();
if (!actmap)
return;
actmap->GetPropertyVal(::Strings.RegString(Action), v);
actmap->GetPropertyVal(::Strings.RegString(Action), &v);
C4PropList *action = v.getPropList();
if (!action)
return;
@ -1093,7 +1093,7 @@ void C4GraphicsOverlay::Draw(C4TargetFacet &cgo, C4Object *pForObj, int32_t iByP
}
C4Value value;
pDef->GetPropertyVal(P_PictureTransformation, value);
pDef->GetPropertyVal(P_PictureTransformation, &value);
StdMeshMatrix matrix;
if (C4ValueToMatrix(value, &matrix))
lpDDraw->SetMeshTransform(&matrix);
@ -1170,7 +1170,7 @@ void C4GraphicsOverlay::DrawPicture(C4Facet &cgo, C4Object *pForObj)
C4Def *pDef = pSourceGfx->pDef;
C4Value value;
pDef->GetPropertyVal(P_PictureTransformation, value);
pDef->GetPropertyVal(P_PictureTransformation, &value);
StdMeshMatrix matrix;
if (C4ValueToMatrix(value, &matrix))
lpDDraw->SetMeshTransform(&matrix);

View File

@ -212,10 +212,10 @@ void C4PhysicalInfo::PromotionUpdate(int32_t iRank, bool fUpdateTrainablePhysica
for (int32_t iPhysIdx=0; (szPhysName = GetNameByIndex(iPhysIdx, &PhysOff)); ++iPhysIdx)
{
C4Value PhysVal(this->*PhysOff);
C4AulParSet Pars(C4VString(szPhysName), C4VInt(iRank), C4VRef(&PhysVal));
if (!!pTrainDef->Script.Call(PSF_GetFairCrewPhysical, 0, &Pars))
C4AulParSet Pars(C4VString(szPhysName), C4VInt(iRank), PhysVal);
if (C4Value NewVal = pTrainDef->Script.Call(PSF_GetFairCrewPhysical, 0, &Pars))
{
this->*PhysOff = PhysVal.getInt();
this->*PhysOff = NewVal.getInt();
}
}
}

View File

@ -555,7 +555,7 @@ void C4Object::DrawFaceImpl(C4TargetFacet &cgo, bool action, float fx, float fy,
break;
case C4DefGraphics::TYPE_Mesh:
C4Value value;
GetPropertyVal(P_MeshTransformation, value);
GetPropertyVal(P_MeshTransformation, &value);
StdMeshMatrix matrix;
if (C4ValueToMatrix(value, &matrix))
lpDDraw->SetMeshTransform(&matrix);
@ -2671,7 +2671,7 @@ void C4Object::DrawLine(C4TargetFacet &cgo)
// additive mode?
PrepareDrawing();
// Draw line segments
C4Value colorsV; GetPropertyVal(P_LineColors, colorsV);
C4Value colorsV; GetPropertyVal(P_LineColors, &colorsV);
C4ValueArray *colors = colorsV.getArray();
int32_t color0 = 0xFFFF00FF, color1 = 0xFFFF00FF; // use bright colors so author notices
if (colors)
@ -3343,7 +3343,7 @@ void C4Object::Resort()
C4PropList* C4Object::GetAction()
{
C4Value value;
GetPropertyVal(P_Action, value);
GetPropertyVal(P_Action, &value);
return value.getPropList();
}
@ -3474,9 +3474,9 @@ bool C4Object::SetActionByName(C4String *ActName,
// If we get the null string or ActIdle by name, set ActIdle
if (!ActName || ActName == Strings.P[P_Idle])
return SetAction(0,0,0,iCalls,fForce);
C4Value ActMap; GetPropertyVal(P_ActMap, ActMap);
C4Value ActMap; GetPropertyVal(P_ActMap, &ActMap);
if (!ActMap.getPropList()) return false;
C4Value Action; ActMap.getPropList()->GetPropertyVal(ActName, Action);
C4Value Action; ActMap.getPropList()->GetPropertyVal(ActName, &Action);
if (!Action.getPropList()) return false;
return SetAction(Action.getPropList(),pTarget,pTarget2,iCalls,fForce);
}
@ -4595,7 +4595,7 @@ void C4Object::ExecAction()
int32_t attachVertex0,attachVertex1;
attachVertex0=attachVertex1=0;
{
C4Value lineAttachV; GetPropertyVal(P_LineAttach, lineAttachV);
C4Value lineAttachV; GetPropertyVal(P_LineAttach, &lineAttachV);
C4ValueArray *lineAttach = lineAttachV.getArray();
if (lineAttach)
{
@ -4839,7 +4839,7 @@ bool C4Object::IsVisible(int32_t iForPlr, bool fAsOverlay)
{
bool fDraw;
C4Value vis;
if (!GetPropertyVal(P_Visibility, vis))
if (!GetPropertyVal(P_Visibility, &vis))
return true;
int32_t Visibility;
@ -5064,7 +5064,7 @@ void C4Object::GetParallaxity(int32_t *parX, int32_t *parY)
assert(parX); assert(parY);
*parX = 100; *parY = 100;
if (!(Category & C4D_Parallax)) return;
C4Value parV; GetPropertyVal(P_Parallaxity, parV);
C4Value parV; GetPropertyVal(P_Parallaxity, &parV);
C4ValueArray *par = parV.getArray();
if (!par) return;
*parX = par->GetItem(0).getInt();
@ -5074,7 +5074,7 @@ void C4Object::GetParallaxity(int32_t *parX, int32_t *parY)
bool C4Object::GetDragImage(C4Object **drag_object, C4ID *drag_id)
{
// drag is possible if MouseDragImage is assigned
C4Value parV; GetPropertyVal(P_MouseDragImage, parV);
C4Value parV; GetPropertyVal(P_MouseDragImage, &parV);
if (!parV) return false;
// determine drag object/id
C4Object *obj=NULL; C4ID id;

View File

@ -638,7 +638,7 @@ bool C4FindObjectActionTarget::Check(C4Object *pObj)
bool C4FindObjectProcedure::Check(C4Object *pObj)
{
C4Value v;
pObj->GetAction()->GetPropertyVal(P_Procedure, v);
pObj->GetAction()->GetPropertyVal(P_Procedure, &v);
return v != C4VNull && v.getInt() == procedure;
}

View File

@ -194,7 +194,6 @@ typedef bool t_bool;
typedef C4ID t_id;
typedef C4Object *t_object;
typedef C4String *t_string;
typedef C4Value &t_ref;
typedef C4Value t_any;
typedef C4ValueArray *t_array;
@ -203,8 +202,7 @@ inline t_bool getPar_bool(C4Value *pVal) { return pVal->getBool(); }
inline t_id getPar_id(C4Value *pVal) { return pVal->getC4ID(); }
inline t_object getPar_object(C4Value *pVal) { return pVal->getObj(); }
inline t_string getPar_string(C4Value *pVal) { return pVal->getStr(); }
//inline t_ref getPar_ref(C4Value *pVal) { return pVal->GetRefVal(); }
inline t_any getPar_any(C4Value *pVal) { return pVal->GetRefValConst(); }
inline t_any getPar_any(C4Value *pVal) { return *pVal; }
inline t_array getPar_array(C4Value *pVal) { return pVal->getArray(); }
#define PAR(type, name) t_##type name = getPar_##type(pPars++)
@ -1011,7 +1009,7 @@ static C4Value FnGetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value
C4String * key = key_C4V->_getStr();
if (!key) return C4VNull;
C4Value r;
pObj->GetPropertyRef(key, r);
pObj->GetPropertyVal(key, &r);
return r;
}
@ -1924,26 +1922,25 @@ static C4Object *FnComposeContents(C4AulObjectContext *cthr, C4ID c_id)
return cthr->Obj->ComposeContents(c_id);
}
static bool FnFindConstructionSite(C4AulContext *cthr, C4PropList * PropList, C4Value * VarX, C4Value * VarY)
static C4ValueArray *FnFindConstructionSite(C4AulContext *cthr, C4PropList * PropList, int32_t v1, int32_t v2)
{
// Get def Old-style implementation (fixed)...
// Get def
C4Def *pDef;
if (!(pDef=PropList->GetDef())) return false;
// Get thread vars
if (!cthr->Caller) return false;
C4Value V1 = VarX->GetRefValConst();
C4Value V2 = VarY->GetRefValConst();
// Construction check at starting position
if (ConstructionCheck(PropList,V1.getInt(),V2.getInt()))
return true;
if (ConstructionCheck(PropList,v1,v2))
return NULL;
// Search for real
int32_t v1 = V1.getInt(), v2 = V2.getInt();
bool result = !!FindConSiteSpot(v1, v2,
pDef->Shape.Wdt,pDef->Shape.Hgt,
pDef->Category,
20);
*VarX = C4VInt(v1); *VarY = C4VInt(v2);
return result;
C4ValueArray *pArray = new C4ValueArray(2);
pArray->SetItem(0, C4VInt(v1));
pArray->SetItem(1, C4VInt(v2));
return pArray;
}
C4FindObject *CreateCriterionsFromPars(C4Value *pPars, C4FindObject **pFOs, C4SortObject **pSOs)
@ -2919,18 +2916,19 @@ static bool FnPathFree(C4AulContext *cthr, long X1, long Y1, long X2, long Y2)
return !!PathFree(X1, Y1, X2, Y2);
}
static C4Value FnPathFree2_C4V(C4AulContext *cthr, C4Value * X1, C4Value * Y1, C4Value * X2, C4Value * Y2)
static C4Value FnPathFree2(C4AulContext *cthr, int32_t x1, int32_t y1, int32_t x2, int32_t y2)
{
int32_t x = -1, y = -1;
C4Value x1 = X1->GetRefValConst(), y1 = Y1->GetRefValConst();
// Do not use getInt on the references, because it destroys them.
bool r = !!PathFree(x1.getInt(), y1.getInt(), X2->getInt(), Y2->getInt(), &x, &y);
bool r = !!PathFree(x1, y1, x2, y2, &x, &y);
if (!r)
{
*X1 = C4VInt(x);
*Y1 = C4VInt(y);
C4ValueArray *pArray = new C4ValueArray(2);
pArray->SetItem(0, C4VInt(x));
pArray->SetItem(1, C4VInt(y));
return C4VArray(pArray);
}
return C4VBool(r);
return C4VBool(true);
}
static long FnSetTransferZone(C4AulObjectContext *cthr, long iX, long iY, long iWdt, long iHgt)
@ -3353,11 +3351,6 @@ static C4String *FnGetProcedure(C4AulObjectContext *cthr)
return String(ProcedureName[iProc]);
}
static C4Value FnIsRef(C4AulContext *cthr, C4Value* Value)
{
return C4VBool(Value->IsRef());
}
static C4Value FnGetType(C4AulContext *cthr, C4Value* Value)
{
return C4VInt(Value->GetType());
@ -3403,14 +3396,14 @@ static C4Value FnGetIndexOf(C4AulContext *cthr, C4Value *pPars)
return C4VInt(-1);
}
static C4Void FnSetLength(C4AulContext *cthr, C4Value *pArrayRef, int iNewSize)
static C4Void FnSetLength(C4AulContext *cthr, C4ValueArray *pArray, int iNewSize)
{
// safety
if (iNewSize<0 || iNewSize > C4ValueArray::MaxSize)
throw new C4AulExecError(cthr->Obj, FormatString("SetLength: invalid array size (%d)", iNewSize).getData());
// set new size
pArrayRef->SetArrayLength(iNewSize, cthr);
pArray->SetSize(iNewSize);
return C4VNull;
}
@ -4025,8 +4018,8 @@ static C4Value FnVarN(C4AulContext *cthr, C4Value *strName_C4V)
if (iID < 0)
return C4VNull;
// return reference on variable
return cthr->Caller->Vars[iID].GetRef();
// return variable value
return cthr->Caller->Vars[iID];
}
static C4Value FnLocalN(C4AulContext* cthr, C4Value* strName_C4V)
@ -4037,10 +4030,9 @@ static C4Value FnLocalN(C4AulContext* cthr, C4Value* strName_C4V)
C4String * key = strName_C4V->getStr();
if (!key) return C4VNull;
// get reference on variable
// get variable
C4Value r;
cthr->Obj->GetPropertyRef(key, r);
cthr->Obj->GetPropertyVal(key, &r);
return r;
}
@ -4053,8 +4045,8 @@ static C4Value FnGlobalN(C4AulContext* cthr, C4Value* strName_C4V)
if (!pVarN) return C4Value();
// return reference on variable
return pVarN->GetRef();
// return variable value
return *pVarN;
}
static bool FnSetSkyAdjust(C4AulContext* cthr, long dwAdjust, long dwBackClr)
@ -4724,11 +4716,13 @@ static C4Value FnSimFlight(C4AulContext *ctx, C4Value *pvrX, C4Value *pvrY, C4Va
if (!SimFlight(x, y, xdir, ydir, iDensityMin, iDensityMax, iIter))
return C4VFalse;
// write results back
*pvrX = C4VInt(fixtoi(x)); *pvrY = C4VInt(fixtoi(y));
*pvrXDir = C4VInt(fixtoi(xdir * iPrec)); *pvrYDir = C4VInt(fixtoi(ydir * iPrec));
return C4VTrue;
// write results to array
C4ValueArray *pResults = new C4ValueArray(4);
pResults->SetItem(0, C4VInt(fixtoi(x)));
pResults->SetItem(1, C4VInt(fixtoi(y)));
pResults->SetItem(2, C4VInt(fixtoi(xdir * iPrec)));
pResults->SetItem(3, C4VInt(fixtoi(ydir * iPrec)));
return C4VArray(pResults);
}
#undef COPY_C4V_PAR
static bool FnSetPortrait(C4AulObjectContext *ctx, C4String *pstrPortrait, C4ID idSourceDef, bool fPermanent, bool fCopyGfx)
@ -6382,6 +6376,7 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "ExecuteCommand", FnExecuteCommand);
AddFunc(pEngine, "LocateFunc", FnLocateFunc);
AddFunc(pEngine, "PathFree", FnPathFree);
AddFunc(pEngine, "PathFree2", FnPathFree2);
AddFunc(pEngine, "SetNextMission", FnSetNextMission);
AddFunc(pEngine, "GetPlayerControlState", FnGetPlayerControlState);
AddFunc(pEngine, "SetPlayerControlEnabled", FnSetPlayerControlEnabled);
@ -6791,7 +6786,6 @@ C4ScriptFnDef C4ScriptFnMap[]=
{ "AddCommand", 1 ,C4V_Bool ,{ C4V_String ,C4V_C4Object,C4V_Any ,C4V_Int ,C4V_C4Object,C4V_Int ,C4V_Any ,C4V_Int ,C4V_Int ,C4V_Any} ,0 , FnAddCommand },
{ "AppendCommand", 1 ,C4V_Bool ,{ C4V_String ,C4V_C4Object,C4V_Any ,C4V_Int ,C4V_C4Object,C4V_Int ,C4V_Any ,C4V_Int ,C4V_Int ,C4V_Any} ,0 , FnAppendCommand },
{ "GetCommand", 1 ,C4V_Any ,{ C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnGetCommand },
{ "PathFree2", 1 ,C4V_Bool ,{ C4V_Ref ,C4V_Ref ,C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnPathFree2_C4V , 0 },
{ "FindObject", 1 ,C4V_C4Object ,{ C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnFindObject },
{ "FindObjects", 1 ,C4V_Array ,{ C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnFindObjects },
{ "ObjectCount", 1 ,C4V_Int ,{ C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnObjectCount },
@ -6816,7 +6810,6 @@ C4ScriptFnDef C4ScriptFnMap[]=
{ "GetHomebaseMaterial", 1 ,C4V_Int ,{ C4V_Int ,C4V_PropList,C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetHomebaseMaterial_C4V , 0 },
{ "GetHomebaseProduction",1 ,C4V_Int ,{ C4V_Int ,C4V_PropList,C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetHomebaseProduction_C4V , 0 },
{ "IsRef", 1 ,C4V_Bool ,{ C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnIsRef, 0 },
{ "GetType", 1 ,C4V_Int ,{ C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetType, 0 },
{ "CreateArray", 1 ,C4V_Array ,{ C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0, FnCreateArray },
@ -6835,7 +6828,7 @@ C4ScriptFnDef C4ScriptFnMap[]=
{ "GetPlrExtraData", 1 ,C4V_Any ,{ C4V_Int ,C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetPlrExtraData, 0 },
{ "SetCrewExtraData", 1 ,C4V_Any ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnSetCrewExtraData, 0 },
{ "GetCrewExtraData", 1 ,C4V_Any ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetCrewExtraData, 0 },
{ "SimFlight", 1 ,C4V_Bool ,{ C4V_Ref ,C4V_Ref ,C4V_Ref ,C4V_Ref ,C4V_Int ,C4V_Int ,C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any} ,MkFnC4V FnSimFlight, 0 },
{ "SimFlight", 1 ,C4V_Bool ,{ C4V_Int ,C4V_Int ,C4V_Int ,C4V_Int ,C4V_Int ,C4V_Int ,C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any} ,MkFnC4V FnSimFlight, 0 },
{ "GetPortrait", 1 ,C4V_Any ,{ C4V_C4Object,C4V_Bool ,C4V_Bool ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetPortrait, 0 },
{ "AddEffect", 1 ,C4V_Int ,{ C4V_String ,C4V_C4Object,C4V_Int ,C4V_Int ,C4V_C4Object,C4V_PropList,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnAddEffect_C4V, 0 },
{ "GetEffect", 1 ,C4V_Any ,{ C4V_String ,C4V_C4Object,C4V_Int ,C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetEffect_C4V, 0 },

View File

@ -29,8 +29,8 @@ class C4AulScriptEngine;
class StdMeshMatrix;
const int C4SCR_Access_Public = 0,
C4SCR_Access_Protected = 1,
C4SCR_Access_Private = 2;
C4SCR_Access_Protected = 1,
C4SCR_Access_Private = 2;
#define C4SCR_Public "public"
#define C4SCR_Protected "protected"
@ -57,7 +57,7 @@ struct C4ScriptFnDef
bool Public;
C4V_Type RetType; // type returned. ignored when C4V
C4V_Type ParType[10];// type of the parameters. error when wrong parameter type.
C4Value (*FunctionC4V)(C4AulContext *cthr, C4Value*, C4Value*, C4Value*, C4Value*, C4Value*,
C4Value (*FunctionC4V)(struct C4AulContext *cthr, C4Value*, C4Value*, C4Value*, C4Value*, C4Value*,
C4Value*, C4Value*, C4Value*, C4Value*, C4Value*);
C4Value (*FunctionC4V2)(struct C4AulContext *, C4Value *);
};

View File

@ -413,7 +413,6 @@ void C4AulScriptFunc::CopyBody(C4AulScriptFunc &FromFunc)
Script = FromFunc.Script;
VarNamed = FromFunc.VarNamed;
ParNamed = FromFunc.ParNamed;
bReturnRef = FromFunc.bReturnRef;
pOrgScript = FromFunc.pOrgScript;
for (int i = 0; i < C4AUL_MAX_Par; i++)
ParType[i] = FromFunc.ParType[i];

View File

@ -206,6 +206,7 @@ struct C4ScriptOpDef
unsigned short Priority;
const char* Identifier;
C4AulBCCType Code;
C4AulBCCType ResultModifier; // code to apply to result after it was calculated
bool Postfix;
bool Changer; // changes first operand to result, rewrite to "a = a (op) b"
bool NoSecondStatement; // no second statement expected (++/-- postfix)
@ -316,12 +317,11 @@ public:
C4ValueMapNames VarNamed; // list of named vars in this function
C4ValueMapNames ParNamed; // list of named pars in this function
C4V_Type ParType[C4AUL_MAX_Par]; // parameter types
bool bReturnRef; // return reference
C4AulScript *pOrgScript; // the orginal script (!= Owner if included or appended)
C4AulScriptFunc(C4AulScript *pOwner, const char *pName, bool bAtEnd = true) : C4AulFunc(pOwner, pName, bAtEnd),
OwnerOverloaded(NULL), idImage (C4ID::None), iImagePhase(0), Condition(NULL), ControlMethod(C4AUL_ControlMethod_All),
bReturnRef(false), tProfileTime(0)
tProfileTime(0)
{
for (int i = 0; i < C4AUL_MAX_Par; i++) ParType[i] = C4V_Any;
} // constructor
@ -330,7 +330,7 @@ public:
virtual bool GetPublic() { return true; }
virtual C4V_Type *GetParType() { return ParType; }
virtual C4V_Type GetRetType() { return bReturnRef ? C4V_Ref : C4V_Any; }
virtual C4V_Type GetRetType() { return C4V_Any; }
virtual C4Value Exec(C4AulContext *pCallerCtx, C4Value pPars[], bool fPassErrors=false); // execute func (script call, should not happen)
virtual C4Value Exec(C4Object *pObj=NULL, C4AulParSet *pPars = NULL, bool fPassErrors=false); // execute func (engine call)

View File

@ -217,7 +217,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
if (!pCurCtx->Obj)
throw new C4AulExecError(pCurCtx->Obj, "can't access local variables in a definition call!");
PushNullVals(1);
pCurCtx->Obj->GetPropertyVal(pCPos->Par.s, pCurVal[0]);
pCurCtx->Obj->GetPropertyVal(pCPos->Par.s, pCurVal);
break;
case AB_LOCALN_SET:
if (!pCurCtx->Obj)
@ -439,13 +439,13 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
// Typcheck to determine whether it's an array or a proplist
if(CheckArrayAccess(pStruct, pIndex) == C4V_Array)
{
pStruct->GetArrayElement(pIndex->_getInt(), *pResult, pCurCtx, true);
*pResult = pStruct->_getArray()->GetItem(pIndex->_getInt());
}
else
{
C4PropList *pPropList = pStruct->getPropList();
assert(pPropList);
if (!pPropList->GetPropertyVal(pIndex->_getStr(), *pResult))
assert(pStruct->GetType() == C4V_PropList || pStruct->GetType() == C4V_C4Object);
C4PropList *pPropList = pStruct->_getPropList();
if (!pPropList->GetPropertyVal(pIndex->_getStr(), pResult))
pResult->Set0();
}
// Remove index
@ -458,15 +458,12 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
// Typcheck to determine whether it's an array or a proplist
if(CheckArrayAccess(pStruct, pIndex) == C4V_Array)
{
// TODO: Does not work, because array gets copied here!
C4Value Ref;
pStruct->GetArrayElement(pIndex->_getInt(), Ref, pCurCtx, false);
Ref.getRef()->Set(*pValue);
pStruct->_getArray()->SetItem(pIndex->_getInt(), *pValue);
}
else
{
C4PropList *pPropList = pStruct->getPropList();
assert(pPropList);
assert(pStruct->GetType() == C4V_PropList || pStruct->GetType() == C4V_C4Object);
C4PropList *pPropList = pStruct->_getPropList();
pPropList->SetProperty(pIndex->_getStr(), *pValue);
}
// Set result, remove array and index from stack
@ -551,10 +548,6 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
case AB_RETURN:
{
// Resolve reference
if (!pCurCtx->Func->SFunc()->bReturnRef)
pCurVal->Deref();
// Trace
if (iTraceStart >= 0)
{

View File

@ -73,12 +73,6 @@ private:
(++pCurVal)->Set(rVal);
}
void PushValueRef(C4Value &rVal)
{
CheckOverflow(1);
(++pCurVal)->SetRef(&rVal);
}
void PushNullVals(int iCnt)
{
CheckOverflow(iCnt);

View File

@ -419,54 +419,54 @@ bool C4AulParseState::AdvanceSpaces()
C4ScriptOpDef C4ScriptOpMap[] =
{
// priority postfix
// | identifier | changer
// | | Bytecode | | no second id
// | | | | | | RetType ParType1 ParType2
// priority postfix
// | identifier | changer
// | | Bytecode Result | | no second id
// | | | Modifier | | | RetType ParType1 ParType2
// prefix
{ 15, "++", AB_Inc, 0, 1, 0, C4V_Int, C4V_Int, C4V_Any},
{ 15, "--", AB_Dec, 0, 1, 0, C4V_Int, C4V_Int, C4V_Any},
{ 15, "~", AB_BitNot, 0, 0, 0, C4V_Int, C4V_Int, C4V_Any},
{ 15, "!", AB_Not, 0, 0, 0, C4V_Bool, C4V_Bool, C4V_Any},
{ 15, "+", AB_ERR, 0, 0, 0, C4V_Int, C4V_Int, C4V_Any},
{ 15, "-", AB_Neg, 0, 0, 0, C4V_Int, C4V_Int, C4V_Any},
{ 15, "++", AB_Inc, AB_ERR, 0, 1, 0, C4V_Int, C4V_Int, C4V_Any},
{ 15, "--", AB_Dec, AB_ERR, 0, 1, 0, C4V_Int, C4V_Int, C4V_Any},
{ 15, "~", AB_BitNot, AB_ERR, 0, 0, 0, C4V_Int, C4V_Int, C4V_Any},
{ 15, "!", AB_Not, AB_ERR, 0, 0, 0, C4V_Bool, C4V_Bool, C4V_Any},
{ 15, "+", AB_ERR, AB_ERR, 0, 0, 0, C4V_Int, C4V_Int, C4V_Any},
{ 15, "-", AB_Neg, AB_ERR, 0, 0, 0, C4V_Int, C4V_Int, C4V_Any},
// postfix (whithout second statement)
{ 16, "++", AB_Inc, 1, 1, 1, C4V_Int, C4V_Int, C4V_Any},
{ 16, "--", AB_Dec, 1, 1, 1, C4V_Int, C4V_Int, C4V_Any},
{ 16, "++", AB_Inc, AB_Dec, 1, 1, 1, C4V_Int, C4V_Int, C4V_Any},
{ 16, "--", AB_Dec, AB_Inc, 1, 1, 1, C4V_Int, C4V_Int, C4V_Any},
// postfix
{ 14, "**", AB_Pow, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 13, "/", AB_Div, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 13, "*", AB_Mul, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 13, "%", AB_Mod, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 12, "-", AB_Sub, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 12, "+", AB_Sum, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 11, "<<", AB_LeftShift, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 11, ">>", AB_RightShift, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 10, "<", AB_LessThan, AB_ERR, 1, 0, 0, C4V_Bool, C4V_Int, C4V_Int},
{ 10, "<=", AB_LessThanEqual, AB_ERR, 1, 0, 0, C4V_Bool, C4V_Int, C4V_Int},
{ 10, ">", AB_GreaterThan, AB_ERR, 1, 0, 0, C4V_Bool, C4V_Int, C4V_Int},
{ 10, ">=", AB_GreaterThanEqual,AB_ERR, 1, 0, 0, C4V_Bool, C4V_Int, C4V_Int},
{ 9, "==", AB_Equal, AB_ERR, 1, 0, 0, C4V_Bool, C4V_Any, C4V_Any},
{ 9, "!=", AB_NotEqual, AB_ERR, 1, 0, 0, C4V_Bool, C4V_Any, C4V_Any},
{ 8, "&", AB_BitAnd, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 6, "^", AB_BitXOr, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 6, "|", AB_BitOr, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 5, "&&", AB_JUMPAND, AB_ERR, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
{ 4, "||", AB_JUMPOR, AB_ERR, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
// postfix
{ 14, "**", AB_Pow, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 13, "/", AB_Div, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 13, "*", AB_Mul, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 13, "%", AB_Mod, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 12, "-", AB_Sub, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 12, "+", AB_Sum, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 11, "<<", AB_LeftShift, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 11, ">>", AB_RightShift, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 10, "<", AB_LessThan, 1, 0, 0, C4V_Bool, C4V_Int, C4V_Int},
{ 10, "<=", AB_LessThanEqual, 1, 0, 0, C4V_Bool, C4V_Int, C4V_Int},
{ 10, ">", AB_GreaterThan, 1, 0, 0, C4V_Bool, C4V_Int, C4V_Int},
{ 10, ">=", AB_GreaterThanEqual,1, 0, 0, C4V_Bool, C4V_Int, C4V_Int},
{ 9, "==", AB_Equal, 1, 0, 0, C4V_Bool, C4V_Any, C4V_Any},
{ 9, "!=", AB_NotEqual, 1, 0, 0, C4V_Bool, C4V_Any, C4V_Any},
{ 8, "&", AB_BitAnd, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 6, "^", AB_BitXOr, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 6, "|", AB_BitOr, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 5, "&&", AB_JUMPAND, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
{ 4, "||", AB_JUMPOR, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
// changers
{ 2, "*=", AB_Mul, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "/=", AB_Div, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "%=", AB_Mod, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "+=", AB_Sum, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "-=", AB_Sub, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "&=", AB_BitAnd, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "|=", AB_BitOr, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "^=", AB_BitXOr, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 0, NULL, AB_ERR, 0, 0, 0, C4V_Any, C4V_Any, C4V_Any}
{ 2, "*=", AB_Mul, AB_ERR, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "/=", AB_Div, AB_ERR, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "%=", AB_Mod, AB_ERR, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "+=", AB_Sum, AB_ERR, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "-=", AB_Sub, AB_ERR, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "&=", AB_BitAnd, AB_ERR, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "|=", AB_BitOr, AB_ERR, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 2, "^=", AB_BitXOr, AB_ERR, 1, 1, 0, C4V_Int, C4V_Int, C4V_Int},
{ 0, NULL, AB_ERR, AB_ERR, 0, 0, 0, C4V_Any, C4V_Any, C4V_Any}
};
int C4AulParseState::GetOperator(const char* pScript)
@ -1128,6 +1128,22 @@ void C4AulParseState::AddBCC(C4AulBCCType eType, intptr_t X)
return;
}
// Prune unneeded Incs / Decs
if(eType == AB_STACK && X < 0 && (pCPos1->bccType == AB_Inc || pCPos1->bccType == AB_Dec))
if(C4ScriptOpMap[pCPos1->Par.i].ResultModifier != pCPos1->bccType)
{
pCPos1->bccType = eType;
pCPos1->Par.i = X;
return;
}
else
{
// If it was a result modifier, we can safely remove it knowing that it was neither
// the first chunk nor a jump target. We can therefore apply additional optimizations.
a->RemoveLastBCC();
pCPos1--;
}
// Join VARN_SET + STACK -1 to IVARN (equivalent)
if(eType == AB_STACK && X == -1 && pCPos1->bccType == AB_VARN_SET)
{
@ -1544,13 +1560,7 @@ void C4AulParseState::Parse_FuncHead()
if (SEqual(Idtf, C4AUL_Func))
{
Shift(Discard, false);
bool bReturnRef = false;
// get next token, must be func name or "&"
if (TokenType == ATT_AMP)
{
bReturnRef = true;
Shift(Discard, false);
}
// get next token, must be func name
if (TokenType != ATT_IDTF)
UnexpectedToken("function name");
// check: symbol already in use?
@ -1587,7 +1597,6 @@ void C4AulParseState::Parse_FuncHead()
// set up func (in the case we got an error)
Fn->Script = SPos; // temporary
Fn->Access = Acc; Fn->pOrgScript = a;
Fn->bReturnRef = bReturnRef;
Shift(Discard,false);
// expect an opening bracket now
if (TokenType != ATT_BOPEN)
@ -1623,7 +1632,6 @@ void C4AulParseState::Parse_FuncHead()
else if (SEqual(Idtf, C4AUL_TypeString)) { Fn->ParType[cpar] = C4V_String; Shift(Discard,false); }
else if (SEqual(Idtf, C4AUL_TypeArray)) { Fn->ParType[cpar] = C4V_Array; Shift(Discard,false); }
// ampersand?
if (TokenType == ATT_AMP) { Fn->ParType[cpar] = C4V_Ref; Shift(Discard,false); }
if (TokenType != ATT_IDTF)
{
UnexpectedToken("parameter name");
@ -2654,9 +2662,13 @@ void C4AulParseState::Parse_Expression2(int iParentPrio)
Parse_Expression(C4ScriptOpMap[OpID].Priority);
// write byte code
AddBCC(C4ScriptOpMap[OpID].Code, OpID);
// write setter
// write setter and mofidier
if (C4ScriptOpMap[OpID].Changer)
{
AddBCC(Setter.bccType, Setter.Par.i);
if(C4ScriptOpMap[OpID].ResultModifier != AB_ERR)
AddBCC(C4ScriptOpMap[OpID].ResultModifier, OpID);
}
}
break;
}

View File

@ -42,19 +42,6 @@ void C4PropList::DelRef(const C4Value * pRef, C4Value * pNextRef)
pVal->NextRef = pNextRef;
}
if (FirstRef) return;
if (iElementReferences) return;
// These classes have their own memory management
if (dynamic_cast<C4Object *>(this)) return;
if (dynamic_cast<C4Def *>(this)) return;
delete this;
}
void C4PropList::DecElementRef()
{
assert(iElementReferences > 0);
--iElementReferences;
if (iElementReferences) return;
if (FirstRef) return;
// These classes have their own memory management
if (dynamic_cast<C4Object *>(this)) return;
if (dynamic_cast<C4Def *>(this)) return;
@ -110,7 +97,7 @@ C4PropListNumbered::~C4PropListNumbered()
C4PropList::C4PropList(C4PropList * prototype):
Status(1),
FirstRef(NULL), iElementReferences(0), prototype(prototype)
FirstRef(NULL), prototype(prototype)
{
if (prototype)
SetProperty(Strings.P[P_Prototype], C4VPropList(prototype));
@ -125,8 +112,8 @@ void C4PropList::DenumeratePointers()
p = Properties.Next(p);
}
C4Value v;
GetPropertyVal(Strings.P[P_Prototype], v);
prototype = v.getPropList();
if(GetPropertyVal(Strings.P[P_Prototype], &v))
prototype = v.getPropList();
}
C4PropList::~C4PropList()
@ -139,7 +126,6 @@ C4PropList::~C4PropList()
FirstRef = FirstRef->NextRef;
ref->NextRef = NULL;
}
assert(!iElementReferences);
assert(!::Objects.ObjectNumber(this));
}
@ -288,67 +274,17 @@ bool C4PropList::HasProperty(C4String * k) const
return false;
}
void C4PropList::GetPropertyRef(C4String * k, C4Value & to)
{
// The prototype is special
if (k == Strings.P[P_Prototype])
{
to.SetPropList(prototype);
return;
}
to.SetPropListRef(this, k);
}
C4Value * C4PropList::GetRefToProperty(C4String * k)
{
// The prototype is special
if (k == Strings.P[P_Prototype])
{
return 0;
}
if (Properties.Has(k))
{
return &Properties.Get(k).Value;
}
if (prototype)
{
C4Property p(k, *(prototype->GetRefToProperty(k)));
return &(Properties.Add(p)->Value);
}
C4Property p(k, C4VNull);
return &(Properties.Add(p)->Value);
}
const C4Value * C4PropList::GetRefToPropertyConst(C4String * k) const
{
// The prototype is special
if (k == Strings.P[P_Prototype])
{
return 0;
}
if (Properties.Has(k))
{
return &Properties.Get(k).Value;
}
if (prototype)
{
return prototype->GetRefToPropertyConst(k);
}
return 0;
}
bool C4PropList::GetPropertyVal(C4String * k, C4Value & to)
bool C4PropList::GetPropertyVal(C4String * k, C4Value *pResult)
{
if (Properties.Has(k))
{
to.Set(Properties.Get(k).Value);
*pResult = Properties.Get(k).Value;
return true;
}
if (prototype)
{
return prototype->GetPropertyVal(k, to);
}
return false;
else if(prototype)
return prototype->GetPropertyVal(k, pResult);
else
return false;
}
C4String * C4PropList::GetPropertyStr(C4PropertyName n)
@ -403,8 +339,6 @@ void C4PropList::ResetProperty(C4String * k)
Properties.Remove(k);
}
template<> template<>
unsigned int C4Set<C4PropListNumbered *>::Hash<int>(int e)
{

View File

@ -49,8 +49,6 @@ public:
int32_t Status;
void AddRef(C4Value *pRef);
void DelRef(const C4Value *pRef, C4Value * pNextRef);
void IncElementRef() { ++iElementReferences; }
void DecElementRef();
void AssignRemoval();
const char *GetName();
virtual void SetName (const char *NewName = 0);
@ -60,12 +58,9 @@ public:
virtual C4PropListNumbered * GetPropListNumbered();
C4PropList * GetPrototype() { return prototype; }
void GetPropertyRef(C4String * k, C4Value & to);
bool HasProperty(C4String * k) const;
C4Value * GetRefToProperty(C4String * k);
const C4Value * GetRefToPropertyConst(C4String * k) const;
bool GetPropertyVal(C4String * k, C4Value & to);
bool GetPropertyVal(C4PropertyName k, C4Value & to) { return GetPropertyVal(Strings.P[k], to); }
bool GetPropertyVal(C4String *k, C4Value *pResult);
bool GetPropertyVal(C4PropertyName k, C4Value *pResult) { return GetPropertyVal(Strings.P[k], pResult); }
C4String * GetPropertyStr(C4PropertyName k);
int32_t GetPropertyInt(C4PropertyName k);
void SetProperty(C4String * k, const C4Value & to);
@ -85,7 +80,6 @@ protected:
private:
C4Value *FirstRef; // No-Save
bool constant; // if true, this proplist is neither saved nor changeable FIXME: implement
unsigned int iElementReferences;
C4PropList * prototype;
friend void CompileNewFunc<C4PropList>(C4PropList *&pStruct, StdCompiler *pComp);

View File

@ -33,32 +33,12 @@ const C4NullValue C4VNull = C4NullValue();
const C4Value C4VTrue = C4VBool(true);
const C4Value C4VFalse = C4VBool(false);
C4Value::~C4Value()
{
// resolve all C4Values referencing this Value
while (FirstRef)
FirstRef->Set(*this);
// delete contents
DelDataRef(Data, Type, GetNextRef(), GetBaseArray(), Type == C4V_PropListRef ? PropListRefKey : NULL);
}
C4Value &C4Value::operator = (const C4Value &nValue)
{
// set referenced value
GetRefVal().Set(nValue.GetRefVal());
return *this;
}
void C4Value::AddDataRef()
{
assert(Type != C4V_Any || !Data);
switch (Type)
{
case C4V_Ref: Data.Ref->AddRef(this); break;
case C4V_PropListRef: Data.PropList->IncElementRef(); PropListRefKey->IncRef(); break;
case C4V_Array: Data.Array = Data.Array->IncRef(); break;
case C4V_Array: Data.Array->IncRef(); break;
case C4V_String: Data.Str->IncRef(); break;
case C4V_C4Object:
case C4V_PropList:
@ -75,17 +55,11 @@ void C4Value::AddDataRef()
}
}
void C4Value::DelDataRef(C4V_Data Data, C4V_Type Type, C4Value * pNextRef, C4ValueArray * pBaseArray, C4String * Key)
void C4Value::DelDataRef(C4V_Data Data, C4V_Type Type, C4Value *pNextRef)
{
// clean up
switch (Type)
{
case C4V_Ref:
// Save because AddDataRef does not set this flag
HasBaseArray = false;
Data.Ref->DelRef(this, pNextRef, pBaseArray);
break;
case C4V_PropListRef: Data.PropList->DecElementRef(); Key->DecRef(); break;
case C4V_C4Object: case C4V_PropList: Data.PropList->DelRef(this, pNextRef); break;
case C4V_Array: Data.Array->DecRef(); break;
case C4V_String: Data.Str->DecRef(); break;
@ -93,33 +67,23 @@ void C4Value::DelDataRef(C4V_Data Data, C4V_Type Type, C4Value * pNextRef, C4Val
}
}
void C4Value::Set(C4V_Data nData, C4V_Type nType, C4String * nPropListRefKey)
void C4Value::Set(C4V_Data nData, C4V_Type nType)
{
assert(nType != C4V_Any || !nData);
assert(nType != C4V_PropListRef || nPropListRefKey);
// Do not add this to the same linked list twice.
if (Data == nData && Type == nType) return;
C4V_Data oData = Data;
C4V_Type oType = Type;
C4Value * oNextRef = NextRef;
C4ValueArray * oBaseArray = BaseArray;
C4String * oKey = PropListRefKey;
bool oHasBaseArray = HasBaseArray;
// change
PropListRefKey = nPropListRefKey; // This will be overwritten if the union is needed for something else
Data = nData;
Type = nData || IsNullableType(nType) ? nType : C4V_Any;
// hold
// hold new data & clean up old
AddDataRef();
// clean up
DelDataRef(oData, oType,
oHasBaseArray ? NULL : oNextRef,
oHasBaseArray ? oBaseArray : NULL,
oType == C4V_PropListRef ? oKey : NULL);
DelDataRef(oData, oType, oNextRef);
}
void C4Value::Set0()
@ -128,152 +92,11 @@ void C4Value::Set0()
C4V_Type oType = Type;
// change
Data = 0;
Data.Obj = 0;
Type = C4V_Any;
// clean up (save even if Data was 0 before)
DelDataRef(oData, oType,
HasBaseArray ? NULL : NextRef,
HasBaseArray ? BaseArray : NULL,
oType == C4V_PropListRef ? PropListRefKey : NULL);
}
void C4Value::SetPropListRef(C4PropList * PropList, C4String * Key)
{
assert(PropList);
assert(Key);
C4V_Data d; d.PropList = PropList;
Set(d, C4V_PropListRef, Key);
}
void C4Value::Move(C4Value *nValue)
{
nValue->Set(*this);
// change references
for (C4Value *pVal = FirstRef; pVal; pVal = pVal->GetNextRef())
pVal->Data.Ref = nValue;
// copy ref list
assert(!nValue->FirstRef);
nValue->FirstRef = FirstRef;
// delete usself
FirstRef = NULL;
Set0();
}
void C4Value::GetArrayElement(int32_t Index, C4Value & target, C4AulContext *pctx, bool noref)
{
if (noref)
{
const C4Value & Ref = GetRefValConst();
// No array (and no nullpointer because Data==0 => Type==any)
if (Ref.Type != C4V_Array)
throw new C4AulExecError(pctx->Obj, "Array access: array expected");
// Get the item, but do not resize the array - it might be used more than once
if (Index < Ref.Data.Array->GetSize())
target.Set(Ref.Data.Array->GetItem(Index));
else
target.Set0();
}
else
{
C4Value & Ref = GetRefVal();
// No array (and no nullpointer because Data==0 => Type==any)
if (Ref.Type != C4V_Array)
throw new C4AulExecError(pctx->Obj, "Array access: array expected");
// Is target the first ref?
if (Index >= Ref.Data.Array->GetSize() || !Ref.Data.Array->GetItem(Index).FirstRef)
{
Ref.Data.Array = Ref.Data.Array->IncElementRef();
target.SetRef(&Ref.Data.Array->GetItem(Index));
if (target.Type == C4V_Ref)
{
assert(!target.NextRef);
target.BaseArray = Ref.Data.Array;
target.HasBaseArray = true;
}
// else target apparently owned the last reference to the array
}
else
{
target.SetRef(&Ref.Data.Array->GetItem(Index));
}
}
}
void C4Value::SetArrayLength(int32_t size, C4AulContext *cthr)
{
C4Value & Ref = GetRefVal();
// No array
if (Ref.Type != C4V_Array)
throw new C4AulExecError(cthr->Obj, "SetLength: array expected");
Ref.Data.Array = Ref.Data.Array->SetLength(size);
}
const C4Value & C4Value::GetRefVal() const
{
const C4Value* pVal = this;
while (1)
{
if (pVal->Type == C4V_Ref)
pVal = pVal->Data.Ref;
else if (pVal->Type == C4V_PropListRef)
{
pVal = pVal->Data.PropList->GetRefToPropertyConst(pVal->PropListRefKey);
if (!pVal) return C4VNull;
}
else
return *pVal;
}
}
C4Value &C4Value::GetRefVal()
{
C4Value* pVal = this;
while (1)
{
if (pVal->Type == C4V_Ref)
pVal = pVal->Data.Ref;
else if (pVal->Type == C4V_PropListRef)
pVal = pVal->Data.PropList->GetRefToProperty(pVal->PropListRefKey);
else
return *pVal;
}
}
void C4Value::AddRef(C4Value *pRef)
{
pRef->NextRef = FirstRef;
FirstRef = pRef;
}
void C4Value::DelRef(const C4Value *pRef, C4Value * pNextRef, C4ValueArray * pBaseArray)
{
if (pRef == FirstRef)
FirstRef = pNextRef;
else
{
C4Value* pVal = FirstRef;
while (pVal->NextRef != pRef)
{
// assert that pRef really was in the list
assert(pVal->NextRef && !pVal->HasBaseArray);
pVal = pVal->NextRef;
}
pVal->NextRef = pNextRef;
if (pBaseArray)
{
pVal->HasBaseArray = true;
pVal->BaseArray = pBaseArray;
}
}
// Was pRef the last ref to an array element?
if (pBaseArray && !FirstRef)
{
pBaseArray->DecElementRef();
}
DelDataRef(oData, oType, NextRef);
}
const char* GetC4VName(const C4V_Type Type)
@ -294,8 +117,6 @@ const char* GetC4VName(const C4V_Type Type)
return "array";
case C4V_PropList:
return "proplist";
case C4V_Ref:
return "&";
default:
return "!Fehler!";
}
@ -324,7 +145,6 @@ char GetC4VID(const C4V_Type Type)
case C4V_PropList:
return 'p';
default:
assert(Type != C4V_Ref && Type != C4V_PropListRef);
assert(false);
}
return ' ';
@ -344,8 +164,6 @@ C4V_Type GetC4VFromID(const char C4VID)
return C4V_C4Object;
case 's':
return C4V_String;
case 'V':
return C4V_Ref;
case 'O':
return C4V_C4ObjectEnum;
case 'D':
@ -371,22 +189,6 @@ static bool FnCnvError(C4Value *Val, C4V_Type toType)
return false;
}
static bool FnCnvDeref(C4Value *Val, C4V_Type toType)
{
// resolve reference of Value
Val->Deref();
// retry to check convert
return Val->ConvertTo(toType);
}
bool C4Value::FnCnvPLR(C4Value *Val, C4V_Type toType)
{
// resolve reference of Value
Val->SetRef(Val->Data.PropList->GetRefToProperty(Val->PropListRefKey));
// retry to check convert
return Val->ConvertTo(toType);
}
static bool FnOk0(C4Value *Val, C4V_Type toType)
{
// 0 can be treated as nil, but every other integer can't
@ -404,8 +206,6 @@ bool C4Value::FnCnvObject(C4Value *Val, C4V_Type toType)
#define CnvOK 0, false // allow conversion by same value
#define CnvOK0 FnOk0, true
#define CnvError FnCnvError, true
#define CnvDeref FnCnvDeref, false
#define CnvPLR FnCnvPLR, false
#define CnvObject FnCnvObject, false
C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
@ -418,8 +218,6 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
{ CnvOK }, // C4Object
{ CnvOK }, // String
{ CnvOK }, // Array
{ CnvError }, // Ref
{ CnvError }, // PropListRef
},
{ // C4V_Int
{ CnvOK }, // any
@ -429,8 +227,6 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
{ CnvOK0 }, // C4Object only if 0
{ CnvOK0 }, // String only if 0
{ CnvOK0 }, // Array only if 0
{ CnvError }, // Ref
{ CnvError }, // PropListRef
},
{ // C4V_Bool
{ CnvOK }, // any
@ -440,8 +236,6 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
{ CnvError }, // C4Object NEVER!
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
{ CnvError }, // Ref
{ CnvError }, // PropListRef
},
{ // C4V_PropList
{ CnvOK }, // any
@ -451,8 +245,6 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
{ CnvObject }, // C4Object
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
{ CnvError }, // Ref NEVER!
{ CnvError }, // PropListRef
},
{ // C4V_Object
{ CnvOK }, // any
@ -462,8 +254,6 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
{ CnvOK }, // C4Object same
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
{ CnvError }, // Ref NEVER!
{ CnvError }, // PropListRef
},
{ // C4V_String
{ CnvOK }, // any
@ -473,8 +263,6 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
{ CnvError }, // C4Object NEVER!
{ CnvOK }, // String same
{ CnvError }, // Array NEVER!
{ CnvError }, // Ref NEVER!
{ CnvError }, // PropListRef
},
{ // C4V_Array
{ CnvOK }, // any
@ -484,45 +272,17 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
{ CnvError }, // C4Object NEVER!
{ CnvError }, // String NEVER!
{ CnvOK }, // Array same
{ CnvError }, // Ref NEVER!
{ CnvError }, // PropListRef
},
{ // C4V_Ref - resolve reference and retry type check
{ CnvDeref }, // any
{ CnvDeref }, // int
{ CnvDeref }, // Bool
{ CnvDeref }, // PropList
{ CnvDeref }, // C4Object
{ CnvDeref }, // String
{ CnvDeref }, // Array
{ CnvOK }, // Ref same
{ CnvError }, // PropListRef
},
{ // C4V_Ref - resolve reference and retry type check
{ CnvPLR }, // any
{ CnvPLR }, // int
{ CnvPLR }, // Bool
{ CnvPLR }, // PropList
{ CnvPLR }, // C4Object
{ CnvPLR }, // String
{ CnvPLR }, // Array
{ CnvPLR }, // Ref
{ CnvOK }, // PropListRef same
},
}
};
#undef CnvOK
#undef CnvOK0
#undef CnvError
#undef CnvDeref
#undef CnvPLR
#undef CnvObject
// Humanreadable debug output
StdStrBuf C4Value::GetDataString()
{
if (Type == C4V_Ref)
return GetRefVal().GetDataString() + "*";
// ouput by type info
switch (GetType())
@ -736,7 +496,7 @@ void C4Value::CompileFunc(StdCompiler *pComp)
case C4V_Array:
pComp->Separator(StdCompiler::SEP_START2);
pComp->Value(mkPtrAdapt(Data.Array, false));
if (fCompiler) Data.Array = Data.Array->IncRef();
if (fCompiler) Data.Array->IncRef();
pComp->Separator(StdCompiler::SEP_END2);
break;
@ -746,7 +506,6 @@ void C4Value::CompileFunc(StdCompiler *pComp)
break;
// shouldn't happen
case C4V_Ref:
default:
assert(false);
break;
@ -785,7 +544,6 @@ bool C4Value::operator == (const C4Value& Value2) const
case C4V_Array:
return Type == Value2.Type && *(Data.Array) == *(Value2.Data.Array);
default:
// C4AulExec should have dereferenced both values, no need to implement comparison here
return Data == Value2.Data;
}
return GetData() == Value2.GetData();

View File

@ -39,14 +39,12 @@ enum C4V_Type
C4V_C4Object=4,
C4V_String=5,
C4V_Array=6,
C4V_Ref=7, // reference to a value (variable)
C4V_PropListRef=8, // reference to an entry in a proplist
C4V_C4ObjectEnum=9, // enumerated object
C4V_C4DefEnum=10 // enumerated object
};
#define C4V_Last (int) C4V_PropListRef
#define C4V_Last (int) C4V_Array
const char* GetC4VName(const C4V_Type Type);
char GetC4VID(const C4V_Type Type);
@ -58,13 +56,12 @@ union C4V_Data
C4Object * Obj;
C4PropList * PropList;
C4String * Str;
C4Value * Ref;
C4ValueArray * Array;
// cheat a little - assume that all members have the same length
operator void * () { return Ref; }
operator const void * () const { return Ref; }
bool operator== (C4V_Data b) { return Ref == b.Ref; }
C4V_Data& operator= (C4Value * p) { Ref = p; return *this; }
operator void * () { return Obj; }
operator const void * () const { return Obj; }
bool operator== (C4V_Data b) { return Obj == b.Obj; }
C4V_Data &operator = (void *p) { Obj = reinterpret_cast<C4Object *>(p); return *this; }
};
// converter function, used in converter table
@ -80,29 +77,27 @@ class C4Value
{
public:
C4Value() : NextRef(NULL), FirstRef(NULL), Type(C4V_Any), HasBaseArray(false) { Data.Ref = 0; }
C4Value() : NextRef(NULL), Type(C4V_Any) { Data.Obj = 0; }
C4Value(const C4Value &nValue) : Data(nValue.Data), PropListRefKey(nValue.PropListRefKey), FirstRef(NULL), Type(nValue.Type), HasBaseArray(false)
C4Value(const C4Value &nValue) : Data(nValue.Data), NextRef(NULL), Type(nValue.Type)
{ AddDataRef(); }
explicit C4Value(bool data): NextRef(NULL), FirstRef(NULL), Type(C4V_Bool), HasBaseArray(false)
{ Data.Int = data; AddDataRef(); }
explicit C4Value(int32_t data): NextRef(NULL), FirstRef(NULL), Type(C4V_Int), HasBaseArray(false)
{ Data.Int = data; AddDataRef(); }
explicit C4Value(C4Object *pObj): NextRef(NULL), FirstRef(NULL), Type(pObj ? C4V_C4Object : C4V_Any), HasBaseArray(false)
explicit C4Value(bool data): NextRef(NULL), Type(C4V_Bool)
{ Data.Int = data; }
explicit C4Value(int32_t data): NextRef(NULL), Type(C4V_Int)
{ Data.Int = data; }
explicit C4Value(C4Object *pObj): NextRef(NULL), Type(pObj ? C4V_C4Object : C4V_Any)
{ Data.Obj = pObj; AddDataRef(); }
explicit C4Value(C4String *pStr): NextRef(NULL), FirstRef(NULL), Type(pStr ? C4V_String : C4V_Any), HasBaseArray(false)
explicit C4Value(C4String *pStr): NextRef(NULL), Type(pStr ? C4V_String : C4V_Any)
{ Data.Str = pStr; AddDataRef(); }
explicit C4Value(C4ValueArray *pArray): NextRef(NULL), FirstRef(NULL), Type(pArray ? C4V_Array : C4V_Any), HasBaseArray(false)
explicit C4Value(C4ValueArray *pArray): NextRef(NULL), Type(pArray ? C4V_Array : C4V_Any)
{ Data.Array = pArray; AddDataRef(); }
explicit C4Value(C4PropList *p): NextRef(NULL), FirstRef(NULL), Type(p ? C4V_PropList : C4V_Any), HasBaseArray(false)
explicit C4Value(C4PropList *p): NextRef(NULL), Type(p ? C4V_PropList : C4V_Any)
{ Data.PropList = p; AddDataRef(); }
explicit C4Value(C4Value *pVal): NextRef(NULL), FirstRef(NULL), Type(pVal ? C4V_Ref : C4V_Any), HasBaseArray(false)
{ Data.Ref = pVal; AddDataRef(); }
C4Value& operator = (const C4Value& nValue);
C4Value& operator = (const C4Value& nValue) { Set(nValue); return *this; }
~C4Value();
~C4Value() { DelDataRef(Data, Type, NextRef); }
// Checked getters
int32_t getInt() { return ConvertTo(C4V_Int) ? Data.Int : 0; }
@ -112,7 +107,6 @@ public:
C4PropList * getPropList() { return ConvertTo(C4V_PropList) ? Data.PropList : NULL; }
C4String * getStr() { return ConvertTo(C4V_String) ? Data.Str : NULL; }
C4ValueArray * getArray() { return ConvertTo(C4V_Array) ? Data.Array : NULL; }
C4Value * getRef() { return ConvertTo(C4V_Ref) ? Data.Ref : NULL; }
// Unchecked getters
int32_t _getInt() const { return Data.Int; }
@ -121,7 +115,6 @@ public:
C4String *_getStr() const { return Data.Str; }
C4ValueArray *_getArray() const { return Data.Array; }
C4PropList *_getPropList() const { return Data.PropList; }
C4Value *_getRef() { return Data.Ref; }
// Template versions
template <typename T> inline T Get() { return C4ValueConv<T>::FromC4V(*this); }
@ -130,68 +123,37 @@ public:
bool operator ! () const { return !GetData(); }
inline operator const void* () const { return GetData()?this:0; } // To allow use of C4Value in conditions
void Set(const C4Value &nValue) { if (this != &nValue) Set(nValue.Data, nValue.Type, nValue.PropListRefKey); }
void Set(const C4Value &nValue) { if (this != &nValue) Set(nValue.Data, nValue.Type); }
void SetInt(int i) { C4V_Data d; d.Int = i; Set(d, C4V_Int); }
void SetBool(bool b) { C4V_Data d; d.Int = b; Set(d, C4V_Bool); }
void SetObject(C4Object * Obj) { C4V_Data d; d.Obj = Obj; Set(d, C4V_C4Object); }
void SetString(C4String * Str) { C4V_Data d; d.Str = Str; Set(d, C4V_String); }
void SetArray(C4ValueArray * Array) { C4V_Data d; d.Array = Array; Set(d, C4V_Array); }
void SetPropList(C4PropList * PropList) { C4V_Data d; d.PropList = PropList; Set(d, C4V_PropList); }
void SetRef(C4Value* nValue) { C4V_Data d; d.Ref = nValue; Set(d, C4V_Ref); }
void SetPropListRef(C4PropList * PropList, C4String * Key);
void Set0();
bool operator == (const C4Value& Value2) const;
bool operator != (const C4Value& Value2) const;
// Change and set Type to int in case it was any before (avoids GuessType())
C4Value & operator += (int32_t by) { GetData().Int += by; GetRefVal().Type=C4V_Int; return *this; }
C4Value & operator -= (int32_t by) { GetData().Int -= by; GetRefVal().Type=C4V_Int; return *this; }
C4Value & operator *= (int32_t by) { GetData().Int *= by; GetRefVal().Type=C4V_Int; return *this; }
C4Value & operator /= (int32_t by) { GetData().Int /= by; GetRefVal().Type=C4V_Int; return *this; }
C4Value & operator %= (int32_t by) { GetData().Int %= by; GetRefVal().Type=C4V_Int; return *this; }
C4Value & operator &= (int32_t by) { GetData().Int &= by; GetRefVal().Type=C4V_Int; return *this; }
C4Value & operator ^= (int32_t by) { GetData().Int ^= by; GetRefVal().Type=C4V_Int; return *this; }
C4Value & operator |= (int32_t by) { GetData().Int |= by; GetRefVal().Type=C4V_Int; return *this; }
C4Value & operator ++ () { GetData().Int ++; GetRefVal().Type=C4V_Int; return *this; }
C4Value operator ++ (int) { C4Value alt = GetRefValConst(); GetData().Int ++; GetRefVal().Type=C4V_Int; return alt; }
C4Value & operator -- () { GetData().Int --; GetRefVal().Type=C4V_Int; return *this; }
C4Value operator -- (int) { C4Value alt = GetRefValConst(); GetData().Int --; GetRefVal().Type=C4V_Int; return alt; }
C4Value & operator += (int32_t by) { Data.Int += by; Type=C4V_Int; return *this; }
C4Value & operator -= (int32_t by) { Data.Int -= by; Type=C4V_Int; return *this; }
C4Value & operator *= (int32_t by) { Data.Int *= by; Type=C4V_Int; return *this; }
C4Value & operator /= (int32_t by) { Data.Int /= by; Type=C4V_Int; return *this; }
C4Value & operator %= (int32_t by) { Data.Int %= by; Type=C4V_Int; return *this; }
C4Value & operator &= (int32_t by) { Data.Int &= by; Type=C4V_Int; return *this; }
C4Value & operator ^= (int32_t by) { Data.Int ^= by; Type=C4V_Int; return *this; }
C4Value & operator |= (int32_t by) { Data.Int |= by; Type=C4V_Int; return *this; }
C4Value & operator ++ () { Data.Int++; Type=C4V_Int; return *this; }
C4Value operator ++ (int) { C4Value old = *this; ++(*this); return old; }
C4Value & operator -- () { Data.Int--; Type=C4V_Int; return *this; }
C4Value operator -- (int) { C4Value old = *this; --(*this); return old; }
void Move(C4Value *nValue);
C4Value GetRef() { return C4Value(this); }
void Deref() { Set(GetRefValConst()); }
bool IsRef() { return Type == C4V_Ref; }
// get data of referenced value
C4V_Data GetData() const { return GetRefVal().Data; }
C4V_Data & GetData() { return GetRefVal().Data; }
// get type of referenced value
C4V_Type GetType() const { return GetRefVal().Type; }
// return referenced value
const C4Value & GetRefVal() const;
const C4Value & GetRefValConst() const { return GetRefVal(); }
protected:
// This also creates a new entry in a proplist if the referenced value was previously only in the prototype
C4Value & GetRefVal();
public:
// Get the Value at the index. Throws C4AulExecError if not an array
void GetArrayElement(int32_t index, C4Value & to, struct C4AulContext *pctx, bool noref);
// Set the length of the array. Throws C4AulExecError if not an array
void SetArrayLength(int32_t size, C4AulContext *cthr);
// getters
C4V_Data GetData() const { return Data; }
C4V_Data & GetData() { return Data; }
C4V_Type GetType() const { return Type; }
const char *GetTypeName() const { return GetC4VName(GetType()); }
const char *GetTypeInfo();
@ -222,40 +184,19 @@ protected:
// data
C4V_Data Data;
// reference-list
union
{
C4Value * NextRef;
C4ValueArray * BaseArray;
C4String * PropListRefKey;
};
C4Value * FirstRef;
// data type
C4V_Type Type:8;
bool HasBaseArray:8;
// All referenzes to a C4Value form a linked list, so that they can be updated if the C4Value
// has to move, (array is resized), or goes out of scope (func & f() { var r; return r; })
// If the reference is in an array, the last c4value in the list has HasBaseArray set, and
// BaseArray points to the array. This is used to count the references to elements that an
// array has, and maintain the invariant that an array can only have multiple references to
// the array OR its elements, but not both. For example, a[0] = a; has to copy the entire
// old array into its first element. But a[0]=42; GetLength(a); should not copy the array,
// so the element reference count has to be reset after a[0] is removed from the stack.
C4V_Type Type;
C4Value * GetNextRef() { if (HasBaseArray) return 0; else return NextRef; }
C4ValueArray * GetBaseArray() { if (HasBaseArray) return BaseArray; else return 0; }
// proplist reference list
C4Value * NextRef;
C4Value(C4V_Data nData, C4V_Type nType): Data(nData), NextRef(NULL), FirstRef(NULL), HasBaseArray(false)
{ Type = nData || IsNullableType(nType) ? nType : C4V_Any; AddDataRef(); }
C4Value(C4V_Data nData, C4V_Type nType): Data(nData), NextRef(NULL)
{ Type = (nData || IsNullableType(nType) ? nType : C4V_Any); AddDataRef(); }
void Set(C4V_Data nData, C4V_Type nType, C4String * PropListRefKey = 0);
void AddRef(C4Value *pRef);
void DelRef(const C4Value *pRef, C4Value * pNextRef, C4ValueArray * pBaseArray);
void Set(C4V_Data nData, C4V_Type nType);
void AddDataRef();
void DelDataRef(C4V_Data Data, C4V_Type Type, C4Value * pNextRef, C4ValueArray * pBaseArray, C4String * Key);
void DelDataRef(C4V_Data Data, C4V_Type Type, C4Value *pNextRef);
static C4VCnvFn C4ScriptCnvMap[C4V_Last+1][C4V_Last+1];
static bool FnCnvObject(C4Value *Val, C4V_Type toType);
@ -276,7 +217,6 @@ inline C4Value C4VObj(C4Object *pObj) { return C4Value(pObj); }
inline C4Value C4VPropList(C4PropList * p) { return C4Value(p); }
inline C4Value C4VString(C4String *pStr) { return C4Value(pStr); }
inline C4Value C4VArray(C4ValueArray *pArray) { return C4Value(pArray); }
inline C4Value C4VRef(C4Value *pVal) { return pVal->GetRef(); }
C4Value C4VString(StdStrBuf strString);
C4Value C4VString(const char *strString);
@ -331,13 +271,6 @@ template <> struct C4ValueConv<C4PropList *>
inline static C4PropList *_FromC4V(C4Value &v) { return v._getPropList(); }
inline static C4Value ToC4V(C4PropList *v) { return C4VPropList(v); }
};
template <> struct C4ValueConv<C4Value *>
{
inline static C4V_Type Type() { return C4V_Ref; }
inline static C4Value *FromC4V(C4Value &v) { return v.getRef(); }
inline static C4Value *_FromC4V(C4Value &v) { return v._getRef(); }
inline static C4Value ToC4V(C4Value *v) { return C4VRef(v); }
};
template <> struct C4ValueConv<const C4Value &>
{
inline static C4V_Type Type() { return C4V_Any; }

View File

@ -109,23 +109,23 @@ C4Value &C4ValueList::GetItem(int32_t iElem)
else if (iElem < 0)
iElem = iSize + iElem;
else if (iElem >= iSize && iElem < MaxSize) this->SetSize(iElem + 1);
// out-of-memory? This might not be catched, but it's better than a segfault
// out-of-memory? This might not get caught, but it's better than a segfault
if (iElem >= iSize)
throw new C4AulExecError(NULL,"out of memory");
// return
return pData[iElem];
}
void C4ValueList::SetItem(int32_t iElemNr, C4Value iValue)
void C4ValueList::SetItem(int32_t iElemNr, const C4Value &Value)
{
// enlarge
if (iElemNr < 0) iElemNr = 0;
if (iElemNr >= iSize && iElemNr < MaxSize) this->SetSize(iElemNr + 1);
// out-of-memory? This might not be catched, but it's better than a segfault
// out-of-memory? This might not get caught, but it's better than a segfault
if (iElemNr >= iSize)
throw new C4AulExecError(NULL,"out of memory");
// set
pData[iElemNr]=iValue;
pData[iElemNr]=Value;
}
void C4ValueList::SetSize(int32_t inSize)
@ -142,14 +142,14 @@ void C4ValueList::SetSize(int32_t inSize)
// bounds check
if (inSize > MaxSize) return;
// create new array (initialises)
// create new array
C4Value* pnData = new C4Value [inSize];
if (!pnData) return;
// move existing values
int32_t i;
for (i=0; i<iSize; i++)
pData[i].Move(&pnData[i]);
pnData[i] = pData[i];
// replace
delete[] pData;
@ -195,17 +195,12 @@ void C4ValueList::CompileFunc(class StdCompiler *pComp)
}
C4ValueArray::C4ValueArray()
: C4ValueList(), iRefCnt(0), iElementReferences(0)
: C4ValueList(), iRefCnt(0)
{
}
C4ValueArray::C4ValueArray(int32_t inSize)
: C4ValueList(inSize), iRefCnt(0), iElementReferences(0)
{
}
C4ValueArray::C4ValueArray(const C4ValueArray &Array2)
: C4ValueList(Array2), iRefCnt(1), iElementReferences(0)
: C4ValueList(inSize), iRefCnt(0)
{
}
@ -215,44 +210,6 @@ C4ValueArray::~C4ValueArray()
enum { C4VALUEARRAY_DEBUG = 0 };
C4ValueArray * C4ValueArray::IncElementRef()
{
if (iRefCnt > 1)
{
C4ValueArray * pNew = new C4ValueArray(*this);
pNew->iElementReferences = 1;
if (C4VALUEARRAY_DEBUG) printf("%p IncElementRef at %d, %d - Copying %p\n", static_cast<void*>(this), iRefCnt, iElementReferences, static_cast<void*>(pNew));
--iRefCnt;
return pNew;
}
else
{
if (C4VALUEARRAY_DEBUG) printf("%p IncElementRef at %d, %d\n", static_cast<void*>(this), iRefCnt, iElementReferences);
++iElementReferences;
return this;
}
}
void C4ValueArray::DecElementRef()
{
if (C4VALUEARRAY_DEBUG) printf("%p DecElementRef at %d, %d\n", static_cast<void*>(this), iRefCnt, iElementReferences);
assert(iElementReferences > 0);
--iElementReferences;
}
C4ValueArray * C4ValueArray::IncRef()
{
if (iRefCnt >= 1 && iElementReferences)
{
C4ValueArray * pNew = new C4ValueArray(*this);
if (C4VALUEARRAY_DEBUG) printf("%p IncRef from %d, %d - Copying %p\n", static_cast<void*>(this), iRefCnt, iElementReferences, static_cast<void*>(pNew));
return pNew;
}
if (C4VALUEARRAY_DEBUG) printf("%p IncRef from %d, %d\n", static_cast<void*>(this), iRefCnt, iElementReferences);
iRefCnt++;
return this;
}
C4ValueArray * C4ValueArray::GetSlice(int32_t startIndex, int32_t endIndex)
{
// adjust indices so that the default end index works and that negative numbers count backwards from the end of the string
@ -265,9 +222,7 @@ C4ValueArray * C4ValueArray::GetSlice(int32_t startIndex, int32_t endIndex)
else if (endIndex < 0) endIndex += iSize;
if (startIndex == 0 && endIndex == iSize)
{
return IncRef();
}
return this;
else
{
C4ValueArray* NewArray = new C4ValueArray(std::max(0, endIndex - startIndex));
@ -277,31 +232,3 @@ C4ValueArray * C4ValueArray::GetSlice(int32_t startIndex, int32_t endIndex)
}
}
C4ValueArray * C4ValueArray::SetLength(int32_t size)
{
if (iRefCnt > 1)
{
C4ValueArray * pNew = (new C4ValueArray(size))->IncRef();
for (int32_t i = 0; i < size; i++)
pNew->pData[i].Set(pData[i]);
if (C4VALUEARRAY_DEBUG) printf("%p SetLength at %d, %d - Copying %p\n", static_cast<void*>(this), iRefCnt, iElementReferences, static_cast<void*>(pNew));
--iRefCnt;
return pNew;
}
else
{
if (C4VALUEARRAY_DEBUG) printf("%p SetLength at %d, %d\n", static_cast<void*>(this), iRefCnt, iElementReferences);
SetSize(size);
return this;
}
}
void C4ValueArray::DecRef()
{
if (C4VALUEARRAY_DEBUG) printf("%p DecRef from %d, %d%s\n", static_cast<void*>(this), iRefCnt, iElementReferences, iRefCnt == 1 ? " - Deleting" : "");
assert(iRefCnt);
if (!--iRefCnt)
{
delete this;
}
}

View File

@ -57,7 +57,7 @@ public:
C4Value &operator[](int32_t iElem) { return GetItem(iElem); }
void Reset();
void SetItem(int32_t iElemNr, C4Value iValue);
void SetItem(int32_t iElemNr, const C4Value &Value);
void SetSize(int32_t inSize); // (enlarge only!)
void DenumeratePointers();
@ -78,23 +78,20 @@ public:
~C4ValueArray();
// Add Reference, return self or new copy if necessary
C4ValueArray * IncRef();
C4ValueArray * IncElementRef();
// Add/Remove Reference
void IncRef() { iRefCnt++; }
void DecRef() { if (!--iRefCnt) delete this; }
// Return sub-array [startIndex, endIndex), or reference for [0, iSize)
C4ValueArray * GetSlice(int32_t startIndex, int32_t endIndex);
// Change length, return self or new copy if necessary
C4ValueArray * SetLength(int32_t size);
void DecRef();
void DecElementRef();
// Change length
void SetLength(int32_t size);
void Sort(class C4SortObject &rSort);
private:
// Only for IncRef/AddElementRef
C4ValueArray(const C4ValueArray &Array2);
// Reference counter
unsigned int iRefCnt;
unsigned int iElementReferences;
};
#endif

View File

@ -211,16 +211,16 @@ void C4ValueMapData::OnNameListChanged(const char **pOldNames, int32_t iOldSize)
//FIXME: This optimization is ugly.
if (i < pNames->iSize && SEqual(pNames->pNames[i], pOldNames[i]))
{
pOldData[i].Move(&pData[i]);
pData[i] = pOldData[i];
}
else for (j = 0; j < pNames->iSize; j++)
{
if (SEqual(pNames->pNames[j], pOldNames[i]))
{
if (SEqual(pNames->pNames[j], pOldNames[i]))
{
pOldData[i].Move(&pData[j]);
break;
}
pData[j] = pOldData[i];
break;
}
}
}
// delete old data array
delete[] pOldData;