forked from Mirrors/openclonk
Script: Arrays do not autoextend when accessed
Done by constifying the C4ValueList interface. To avoid rewriting some code that uses that interface, also constify some C4Value functions. While at it, replace the dynamic function call for C4Value conversion with a switch. This makes C4Value conversion not actually convert anything, but the only case left is conversion to bool, which already occurs when the value is read.floating-point
parent
aa235b8836
commit
7d3811fc76
|
@ -396,7 +396,7 @@ void C4FindObject::CheckObjectStatus(C4ValueArray *pArray)
|
|||
int32_t j = i; i++;
|
||||
for (; i < pArray->GetSize(); i++)
|
||||
if (pArray->GetItem(i).getObj()->Status)
|
||||
pArray->GetItem(j++) = pArray->GetItem(i);
|
||||
(*pArray)[j++] = pArray->GetItem(i);
|
||||
// Set new size
|
||||
pArray->SetSize(j);
|
||||
break;
|
||||
|
|
|
@ -432,7 +432,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
|
||||
// Pop values from stack
|
||||
for (int i = 0; i < pCPos->Par.i; i++)
|
||||
pArray->GetItem(i) = pCurVal[i - pCPos->Par.i + 1];
|
||||
(*pArray)[i] = pCurVal[i - pCPos->Par.i + 1];
|
||||
|
||||
// Push array
|
||||
if (pCPos->Par.i > 0)
|
||||
|
|
|
@ -180,32 +180,17 @@ const char* C4Value::GetTypeInfo()
|
|||
return GetC4VName(GetType());
|
||||
}
|
||||
|
||||
// converter functions ----------------
|
||||
|
||||
static bool FnCnvError(C4Value *Val, C4V_Type toType)
|
||||
{
|
||||
// deny convert
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool FnOk0(C4Value *Val, C4V_Type toType)
|
||||
{
|
||||
// 0 can be treated as nil, but every other integer can't
|
||||
return !*Val;
|
||||
}
|
||||
|
||||
bool C4Value::FnCnvObject(C4Value *Val, C4V_Type toType)
|
||||
bool C4Value::FnCnvObject() const
|
||||
{
|
||||
// try casting
|
||||
if (dynamic_cast<C4Object *>(Val->Data.PropList)) return true;
|
||||
if (dynamic_cast<C4Object *>(Data.PropList)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Type conversion table
|
||||
#define CnvOK 0, false // allow conversion by same value
|
||||
#define CnvOK0 FnOk0, true
|
||||
#define CnvError FnCnvError, true
|
||||
#define CnvObject FnCnvObject, false
|
||||
#define CnvOK C4VCnvFn::CnvOK, false // allow conversion by same value
|
||||
#define CnvOK0 C4VCnvFn::CnvOK0, true
|
||||
#define CnvError C4VCnvFn::CnvError, true
|
||||
#define CnvObject C4VCnvFn::CnvObject, false
|
||||
|
||||
C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
|
||||
{
|
||||
|
@ -280,7 +265,7 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] =
|
|||
#undef CnvObject
|
||||
|
||||
// Humanreadable debug output
|
||||
StdStrBuf C4Value::GetDataString()
|
||||
StdStrBuf C4Value::GetDataString() const
|
||||
{
|
||||
|
||||
// ouput by type info
|
||||
|
@ -552,7 +537,7 @@ bool C4Value::operator != (const C4Value& Value2) const
|
|||
}
|
||||
|
||||
C4Value C4VID(C4ID iVal) { return C4Value(::Definitions.ID2Def(iVal)); }
|
||||
C4ID C4Value::getC4ID()
|
||||
C4ID C4Value::getC4ID() const
|
||||
{
|
||||
C4PropList * p = getPropList();
|
||||
if (!p) return C4ID::None;
|
||||
|
|
|
@ -66,7 +66,7 @@ union C4V_Data
|
|||
// converter function, used in converter table
|
||||
struct C4VCnvFn
|
||||
{
|
||||
bool (*Function) (C4Value*, C4V_Type); // function to be called; returns whether possible
|
||||
enum { CnvOK, CnvOK0, CnvError, CnvObject } Function;
|
||||
bool Warn;
|
||||
};
|
||||
|
||||
|
@ -99,13 +99,13 @@ public:
|
|||
~C4Value() { DelDataRef(Data, Type, NextRef); }
|
||||
|
||||
// Checked getters
|
||||
int32_t getInt() { return ConvertTo(C4V_Int) ? Data.Int : 0; }
|
||||
bool getBool() { return ConvertTo(C4V_Bool) ? !! Data : 0; }
|
||||
C4ID getC4ID();
|
||||
C4Object * getObj() { return ConvertTo(C4V_C4Object) ? Data.Obj : NULL; }
|
||||
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; }
|
||||
int32_t getInt() const { return ConvertTo(C4V_Int) ? Data.Int : 0; }
|
||||
bool getBool() const { return ConvertTo(C4V_Bool) ? !! Data : 0; }
|
||||
C4ID getC4ID() const;
|
||||
C4Object * getObj() const { return ConvertTo(C4V_C4Object) ? Data.Obj : NULL; }
|
||||
C4PropList * getPropList() const { return ConvertTo(C4V_PropList) ? Data.PropList : NULL; }
|
||||
C4String * getStr() const { return ConvertTo(C4V_String) ? Data.Str : NULL; }
|
||||
C4ValueArray * getArray() const { return ConvertTo(C4V_Array) ? Data.Array : NULL; }
|
||||
|
||||
// Unchecked getters
|
||||
int32_t _getInt() const { return Data.Int; }
|
||||
|
@ -151,7 +151,6 @@ public:
|
|||
|
||||
// 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()); }
|
||||
|
@ -159,14 +158,17 @@ public:
|
|||
|
||||
void DenumeratePointer();
|
||||
|
||||
StdStrBuf GetDataString();
|
||||
StdStrBuf GetDataString() const;
|
||||
|
||||
inline bool ConvertTo(C4V_Type vtToType) // convert to dest type
|
||||
inline bool ConvertTo(C4V_Type vtToType) const // convert to dest type
|
||||
{
|
||||
C4VCnvFn Fn = C4ScriptCnvMap[Type][vtToType];
|
||||
if (Fn.Function)
|
||||
return (*Fn.Function)(this, vtToType);
|
||||
return true;
|
||||
switch (C4ScriptCnvMap[Type][vtToType].Function)
|
||||
{
|
||||
case C4VCnvFn::CnvOK: return true;
|
||||
case C4VCnvFn::CnvOK0: return !*this;
|
||||
case C4VCnvFn::CnvError: return false;
|
||||
case C4VCnvFn::CnvObject: return FnCnvObject();
|
||||
}
|
||||
}
|
||||
inline static bool WarnAboutConversion(C4V_Type vtFromType, C4V_Type vtToType)
|
||||
{
|
||||
|
@ -198,8 +200,7 @@ protected:
|
|||
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);
|
||||
static bool FnCnvPLR(C4Value *Val, C4V_Type toType);
|
||||
bool FnCnvObject() const;
|
||||
|
||||
friend class C4PropList;
|
||||
friend class C4AulDefFunc;
|
||||
|
|
|
@ -102,16 +102,13 @@ void C4ValueArray::Sort(class C4SortObject &rSort)
|
|||
std::stable_sort(pData, pData+iSize, C4SortObjectSTL(rSort));
|
||||
}
|
||||
|
||||
C4Value &C4ValueList::GetItem(int32_t iElem)
|
||||
C4Value &C4ValueList::operator[](int32_t iElem)
|
||||
{
|
||||
if (iElem < -iSize)
|
||||
throw new C4AulExecError(NULL,"array access: index out of range");
|
||||
else if (iElem < 0)
|
||||
iElem = iSize + iElem;
|
||||
else if (iElem >= iSize && iElem < MaxSize) this->SetSize(iElem + 1);
|
||||
assert(iElem < MaxSize);
|
||||
assert(iElem >= 0);
|
||||
if (iElem >= iSize && iElem < MaxSize) this->SetSize(iElem + 1);
|
||||
// out-of-memory? This might not get caught, but it's better than a segfault
|
||||
if (iElem >= iSize)
|
||||
throw new C4AulExecError(NULL,"array access: index too large");
|
||||
assert(iElem < iSize);
|
||||
// return
|
||||
return pData[iElem];
|
||||
}
|
||||
|
|
|
@ -51,10 +51,9 @@ public:
|
|||
else
|
||||
return C4VNull;
|
||||
}
|
||||
C4Value &GetItem(int32_t iElem);
|
||||
|
||||
C4Value operator[](int32_t iElem) const { return GetItem(iElem); }
|
||||
C4Value &operator[](int32_t iElem) { return GetItem(iElem); }
|
||||
C4Value &operator[](int32_t iElem);
|
||||
|
||||
void Reset();
|
||||
void SetItem(int32_t iElemNr, const C4Value &Value);
|
||||
|
|
Loading…
Reference in New Issue