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
Günther Brammer 2010-09-20 19:49:00 +02:00
parent aa235b8836
commit 7d3811fc76
6 changed files with 34 additions and 52 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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];
}

View File

@ -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);