|
@@ -26,6 +26,7 @@
|
|
|
#include "StringBase.h"
|
|
#include "StringBase.h"
|
|
|
|
|
|
|
|
#include <cstring>
|
|
#include <cstring>
|
|
|
|
|
+#include <stdio.h>
|
|
|
|
|
|
|
|
// Adapted from Angelscript's scriptarray & scriptstdstring add-ons, but with garbage collection disabled
|
|
// Adapted from Angelscript's scriptarray & scriptstdstring add-ons, but with garbage collection disabled
|
|
|
|
|
|
|
@@ -33,17 +34,17 @@
|
|
|
struct SArrayBuffer
|
|
struct SArrayBuffer
|
|
|
{
|
|
{
|
|
|
asDWORD numElements;
|
|
asDWORD numElements;
|
|
|
- asBYTE data[1];
|
|
|
|
|
|
|
+ asBYTE data[1];
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-static CScriptArray* ScriptArrayFactory2(asIObjectType* ot, asUINT length)
|
|
|
|
|
|
|
+static CScriptArray* ScriptArrayFactory2(asIObjectType *ot, asUINT length)
|
|
|
{
|
|
{
|
|
|
- CScriptArray* a = new CScriptArray(length, ot);
|
|
|
|
|
|
|
+ CScriptArray *a = new CScriptArray(length, ot);
|
|
|
|
|
|
|
|
// It's possible the constructor raised a script exception, in which case we
|
|
// It's possible the constructor raised a script exception, in which case we
|
|
|
// need to free the memory and return null instead, else we get a memory leak.
|
|
// need to free the memory and return null instead, else we get a memory leak.
|
|
|
- asIScriptContext* context = asGetActiveContext();
|
|
|
|
|
- if (context && context->GetState() == asEXECUTION_EXCEPTION)
|
|
|
|
|
|
|
+ asIScriptContext *ctx = asGetActiveContext();
|
|
|
|
|
+ if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION )
|
|
|
{
|
|
{
|
|
|
delete a;
|
|
delete a;
|
|
|
return 0;
|
|
return 0;
|
|
@@ -52,14 +53,14 @@ static CScriptArray* ScriptArrayFactory2(asIObjectType* ot, asUINT length)
|
|
|
return a;
|
|
return a;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static CScriptArray* ScriptArrayFactoryDefVal(asIObjectType* ot, asUINT length, void* defVal)
|
|
|
|
|
|
|
+static CScriptArray* ScriptArrayFactoryDefVal(asIObjectType *ot, asUINT length, void *defVal)
|
|
|
{
|
|
{
|
|
|
- CScriptArray* a = new CScriptArray(length, defVal, ot);
|
|
|
|
|
|
|
+ CScriptArray *a = new CScriptArray(length, defVal, ot);
|
|
|
|
|
|
|
|
// It's possible the constructor raised a script exception, in which case we
|
|
// It's possible the constructor raised a script exception, in which case we
|
|
|
// need to free the memory and return null instead, else we get a memory leak.
|
|
// need to free the memory and return null instead, else we get a memory leak.
|
|
|
- asIScriptContext* context = asGetActiveContext();
|
|
|
|
|
- if (context && context->GetState() == asEXECUTION_EXCEPTION)
|
|
|
|
|
|
|
+ asIScriptContext *ctx = asGetActiveContext();
|
|
|
|
|
+ if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION )
|
|
|
{
|
|
{
|
|
|
delete a;
|
|
delete a;
|
|
|
return 0;
|
|
return 0;
|
|
@@ -68,7 +69,7 @@ static CScriptArray* ScriptArrayFactoryDefVal(asIObjectType* ot, asUINT length,
|
|
|
return a;
|
|
return a;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static CScriptArray* ScriptArrayFactory(asIObjectType* ot)
|
|
|
|
|
|
|
+static CScriptArray* ScriptArrayFactory(asIObjectType *ot)
|
|
|
{
|
|
{
|
|
|
return ScriptArrayFactory2(ot, 0);
|
|
return ScriptArrayFactory2(ot, 0);
|
|
|
}
|
|
}
|
|
@@ -76,28 +77,29 @@ static CScriptArray* ScriptArrayFactory(asIObjectType* ot)
|
|
|
// This optional callback is called when the template type is first used by the compiler.
|
|
// This optional callback is called when the template type is first used by the compiler.
|
|
|
// It allows the application to validate if the template can be instanciated for the requested
|
|
// It allows the application to validate if the template can be instanciated for the requested
|
|
|
// subtype at compile time, instead of at runtime.
|
|
// subtype at compile time, instead of at runtime.
|
|
|
-static bool ScriptArrayTemplateCallback(asIObjectType* ot)
|
|
|
|
|
|
|
+static bool ScriptArrayTemplateCallback(asIObjectType *ot)
|
|
|
{
|
|
{
|
|
|
// Make sure the subtype can be instanciated with a default factory/constructor,
|
|
// Make sure the subtype can be instanciated with a default factory/constructor,
|
|
|
// otherwise we won't be able to instanciate the elements. Script classes always
|
|
// otherwise we won't be able to instanciate the elements. Script classes always
|
|
|
// have default factories, so we don't have to worry about those.
|
|
// have default factories, so we don't have to worry about those.
|
|
|
int typeId = ot->GetSubTypeId();
|
|
int typeId = ot->GetSubTypeId();
|
|
|
- if ((typeId & asTYPEID_MASK_OBJECT) && !(typeId & asTYPEID_OBJHANDLE) && !(typeId & asTYPEID_SCRIPTOBJECT))
|
|
|
|
|
|
|
+ if( typeId == asTYPEID_VOID )
|
|
|
|
|
+ return false;
|
|
|
|
|
+ if( (typeId & asTYPEID_MASK_OBJECT) && !(typeId & asTYPEID_OBJHANDLE) && !(typeId & asTYPEID_SCRIPTOBJECT) )
|
|
|
{
|
|
{
|
|
|
asIObjectType *subtype = ot->GetEngine()->GetObjectTypeById(typeId);
|
|
asIObjectType *subtype = ot->GetEngine()->GetObjectTypeById(typeId);
|
|
|
asDWORD flags = subtype->GetFlags();
|
|
asDWORD flags = subtype->GetFlags();
|
|
|
- if ((flags & asOBJ_VALUE) && !(flags & asOBJ_POD))
|
|
|
|
|
|
|
+ if( (flags & asOBJ_VALUE) && !(flags & asOBJ_POD) )
|
|
|
{
|
|
{
|
|
|
// Verify that there is a default constructor
|
|
// Verify that there is a default constructor
|
|
|
- for (unsigned n = 0; n < subtype->GetBehaviourCount(); ++n)
|
|
|
|
|
|
|
+ for( asUINT n = 0; n < subtype->GetBehaviourCount(); n++ )
|
|
|
{
|
|
{
|
|
|
asEBehaviours beh;
|
|
asEBehaviours beh;
|
|
|
int funcId = subtype->GetBehaviourByIndex(n, &beh);
|
|
int funcId = subtype->GetBehaviourByIndex(n, &beh);
|
|
|
- if (beh != asBEHAVE_CONSTRUCT)
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
+ if( beh != asBEHAVE_CONSTRUCT ) continue;
|
|
|
|
|
|
|
|
- asIScriptFunction* func = ot->GetEngine()->GetFunctionById(funcId);
|
|
|
|
|
- if (func->GetParamCount() == 0)
|
|
|
|
|
|
|
+ asIScriptFunction *func = ot->GetEngine()->GetFunctionById(funcId);
|
|
|
|
|
+ if( func->GetParamCount() == 0 )
|
|
|
{
|
|
{
|
|
|
// Found the default constructor
|
|
// Found the default constructor
|
|
|
return true;
|
|
return true;
|
|
@@ -107,14 +109,14 @@ static bool ScriptArrayTemplateCallback(asIObjectType* ot)
|
|
|
// There is no default constructor
|
|
// There is no default constructor
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
- else if ((flags & asOBJ_REF))
|
|
|
|
|
|
|
+ else if( (flags & asOBJ_REF) )
|
|
|
{
|
|
{
|
|
|
// Verify that there is a default factory
|
|
// Verify that there is a default factory
|
|
|
- for (unsigned n = 0; n < subtype->GetFactoryCount(); ++n)
|
|
|
|
|
|
|
+ for( asUINT n = 0; n < subtype->GetFactoryCount(); n++ )
|
|
|
{
|
|
{
|
|
|
int funcId = subtype->GetFactoryIdByIndex(n);
|
|
int funcId = subtype->GetFactoryIdByIndex(n);
|
|
|
- asIScriptFunction* func = ot->GetEngine()->GetFunctionById(funcId);
|
|
|
|
|
- if (func->GetParamCount() == 0)
|
|
|
|
|
|
|
+ asIScriptFunction *func = ot->GetEngine()->GetFunctionById(funcId);
|
|
|
|
|
+ if( func->GetParamCount() == 0 )
|
|
|
{
|
|
{
|
|
|
// Found the default factory
|
|
// Found the default factory
|
|
|
return true;
|
|
return true;
|
|
@@ -130,12 +132,13 @@ static bool ScriptArrayTemplateCallback(asIObjectType* ot)
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-CScriptArray& CScriptArray::operator = (const CScriptArray &other)
|
|
|
|
|
|
|
+CScriptArray &CScriptArray::operator=(const CScriptArray &other)
|
|
|
{
|
|
{
|
|
|
// Only perform the copy if the array types are the same
|
|
// Only perform the copy if the array types are the same
|
|
|
- if (&other != this && other.GetArrayObjectType() == GetArrayObjectType())
|
|
|
|
|
|
|
+ if( &other != this &&
|
|
|
|
|
+ other.GetArrayObjectType() == GetArrayObjectType() )
|
|
|
{
|
|
{
|
|
|
- if (buffer)
|
|
|
|
|
|
|
+ if( buffer )
|
|
|
{
|
|
{
|
|
|
DeleteBuffer(buffer);
|
|
DeleteBuffer(buffer);
|
|
|
buffer = 0;
|
|
buffer = 0;
|
|
@@ -149,7 +152,7 @@ CScriptArray& CScriptArray::operator = (const CScriptArray &other)
|
|
|
return *this;
|
|
return *this;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-CScriptArray::CScriptArray(asUINT length, asIObjectType* ot)
|
|
|
|
|
|
|
+CScriptArray::CScriptArray(asUINT length, asIObjectType *ot)
|
|
|
{
|
|
{
|
|
|
refCount = 1;
|
|
refCount = 1;
|
|
|
gcFlag = false;
|
|
gcFlag = false;
|
|
@@ -157,18 +160,20 @@ CScriptArray::CScriptArray(asUINT length, asIObjectType* ot)
|
|
|
objType->AddRef();
|
|
objType->AddRef();
|
|
|
buffer = 0;
|
|
buffer = 0;
|
|
|
|
|
|
|
|
|
|
+ Precache();
|
|
|
|
|
+
|
|
|
// Determine element size
|
|
// Determine element size
|
|
|
- // TODO: Should probably store the template sub type id as well
|
|
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
- if (typeId & asTYPEID_MASK_OBJECT)
|
|
|
|
|
|
|
+ if( subTypeId & asTYPEID_MASK_OBJECT )
|
|
|
|
|
+ {
|
|
|
elementSize = sizeof(asPWORD);
|
|
elementSize = sizeof(asPWORD);
|
|
|
|
|
+ }
|
|
|
else
|
|
else
|
|
|
- elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(typeId);
|
|
|
|
|
-
|
|
|
|
|
- isArrayOfHandles = typeId & asTYPEID_OBJHANDLE ? true : false;
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(subTypeId);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Make sure the array size isn't too large for us to handle
|
|
// Make sure the array size isn't too large for us to handle
|
|
|
- if (!CheckMaxSize(length))
|
|
|
|
|
|
|
+ if( !CheckMaxSize(length) )
|
|
|
{
|
|
{
|
|
|
// Don't continue with the initialization
|
|
// Don't continue with the initialization
|
|
|
return;
|
|
return;
|
|
@@ -185,18 +190,20 @@ CScriptArray::CScriptArray(asUINT length, void *defVal, asIObjectType *ot)
|
|
|
objType->AddRef();
|
|
objType->AddRef();
|
|
|
buffer = 0;
|
|
buffer = 0;
|
|
|
|
|
|
|
|
|
|
+ Precache();
|
|
|
|
|
+
|
|
|
// Determine element size
|
|
// Determine element size
|
|
|
- // TODO: Should probably store the template sub type id as well
|
|
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
- if (typeId & asTYPEID_MASK_OBJECT)
|
|
|
|
|
|
|
+ if( subTypeId & asTYPEID_MASK_OBJECT )
|
|
|
|
|
+ {
|
|
|
elementSize = sizeof(asPWORD);
|
|
elementSize = sizeof(asPWORD);
|
|
|
|
|
+ }
|
|
|
else
|
|
else
|
|
|
- elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(typeId);
|
|
|
|
|
-
|
|
|
|
|
- isArrayOfHandles = typeId & asTYPEID_OBJHANDLE ? true : false;
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(subTypeId);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Make sure the array size isn't too large for us to handle
|
|
// Make sure the array size isn't too large for us to handle
|
|
|
- if (!CheckMaxSize(length))
|
|
|
|
|
|
|
+ if( !CheckMaxSize(length) )
|
|
|
{
|
|
{
|
|
|
// Don't continue with the initialization
|
|
// Don't continue with the initialization
|
|
|
return;
|
|
return;
|
|
@@ -205,41 +212,45 @@ CScriptArray::CScriptArray(asUINT length, void *defVal, asIObjectType *ot)
|
|
|
CreateBuffer(&buffer, length);
|
|
CreateBuffer(&buffer, length);
|
|
|
|
|
|
|
|
// Initialize the elements with the default value
|
|
// Initialize the elements with the default value
|
|
|
- for (asUINT n = 0; n < GetSize(); ++n)
|
|
|
|
|
|
|
+ for( asUINT n = 0; n < GetSize(); n++ )
|
|
|
SetValue(n, defVal);
|
|
SetValue(n, defVal);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Internal
|
|
// Internal
|
|
|
void CScriptArray::SetValue(asUINT index, void *value)
|
|
void CScriptArray::SetValue(asUINT index, void *value)
|
|
|
{
|
|
{
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
-
|
|
|
|
|
- if ((typeId & ~0x03FFFFFF) && !(typeId & asTYPEID_OBJHANDLE))
|
|
|
|
|
- objType->GetEngine()->CopyScriptObject(At(index), value, typeId);
|
|
|
|
|
- else if (typeId & asTYPEID_OBJHANDLE)
|
|
|
|
|
|
|
+ if( (subTypeId & ~0x03FFFFFF) && !(subTypeId & asTYPEID_OBJHANDLE) )
|
|
|
|
|
+ objType->GetEngine()->CopyScriptObject(At(index), value, subTypeId);
|
|
|
|
|
+ else if( subTypeId & asTYPEID_OBJHANDLE )
|
|
|
{
|
|
{
|
|
|
*(void**)At(index) = *(void**)value;
|
|
*(void**)At(index) = *(void**)value;
|
|
|
- objType->GetEngine()->AddRefScriptObject(*(void**)value, typeId);
|
|
|
|
|
|
|
+ objType->GetEngine()->AddRefScriptObject(*(void**)value, objType->GetSubType());
|
|
|
}
|
|
}
|
|
|
- else if (typeId == asTYPEID_BOOL || typeId == asTYPEID_INT8 || typeId == asTYPEID_UINT8)
|
|
|
|
|
|
|
+ else if( subTypeId == asTYPEID_BOOL ||
|
|
|
|
|
+ subTypeId == asTYPEID_INT8 ||
|
|
|
|
|
+ subTypeId == asTYPEID_UINT8 )
|
|
|
*(char*)At(index) = *(char*)value;
|
|
*(char*)At(index) = *(char*)value;
|
|
|
- else if (typeId == asTYPEID_INT16 || typeId == asTYPEID_UINT16)
|
|
|
|
|
|
|
+ else if( subTypeId == asTYPEID_INT16 ||
|
|
|
|
|
+ subTypeId == asTYPEID_UINT16 )
|
|
|
*(short*)At(index) = *(short*)value;
|
|
*(short*)At(index) = *(short*)value;
|
|
|
- else if (typeId == asTYPEID_INT32 || typeId == asTYPEID_UINT32 || typeId == asTYPEID_FLOAT)
|
|
|
|
|
|
|
+ else if( subTypeId == asTYPEID_INT32 ||
|
|
|
|
|
+ subTypeId == asTYPEID_UINT32 ||
|
|
|
|
|
+ subTypeId == asTYPEID_FLOAT )
|
|
|
*(int*)At(index) = *(int*)value;
|
|
*(int*)At(index) = *(int*)value;
|
|
|
- else if (typeId == asTYPEID_INT64 || typeId == asTYPEID_UINT64 || typeId == asTYPEID_DOUBLE)
|
|
|
|
|
|
|
+ else if( subTypeId == asTYPEID_INT64 ||
|
|
|
|
|
+ subTypeId == asTYPEID_UINT64 ||
|
|
|
|
|
+ subTypeId == asTYPEID_DOUBLE )
|
|
|
*(double*)At(index) = *(double*)value;
|
|
*(double*)At(index) = *(double*)value;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CScriptArray::~CScriptArray()
|
|
CScriptArray::~CScriptArray()
|
|
|
{
|
|
{
|
|
|
- if (buffer)
|
|
|
|
|
|
|
+ if( buffer )
|
|
|
{
|
|
{
|
|
|
DeleteBuffer(buffer);
|
|
DeleteBuffer(buffer);
|
|
|
buffer = 0;
|
|
buffer = 0;
|
|
|
}
|
|
}
|
|
|
- if (objType)
|
|
|
|
|
- objType->Release();
|
|
|
|
|
|
|
+ if( objType ) objType->Release();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
asUINT CScriptArray::GetSize() const
|
|
asUINT CScriptArray::GetSize() const
|
|
@@ -247,68 +258,55 @@ asUINT CScriptArray::GetSize() const
|
|
|
return buffer->numElements;
|
|
return buffer->numElements;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool CScriptArray::IsEmpty() const
|
|
|
|
|
-{
|
|
|
|
|
- return buffer->numElements == 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
void CScriptArray::Resize(asUINT numElements)
|
|
void CScriptArray::Resize(asUINT numElements)
|
|
|
{
|
|
{
|
|
|
- if (numElements & 0x80000000)
|
|
|
|
|
|
|
+ if( numElements & 0x80000000 )
|
|
|
{
|
|
{
|
|
|
CheckMaxSize(numElements);
|
|
CheckMaxSize(numElements);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- Resize((int)numElements - (int)buffer->numElements, -1);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void CScriptArray::Clear()
|
|
|
|
|
-{
|
|
|
|
|
- Resize(0);
|
|
|
|
|
|
|
+ Resize((int)numElements - (int)buffer->numElements, (asUINT)-1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Internal
|
|
// Internal
|
|
|
void CScriptArray::Resize(int delta, asUINT at)
|
|
void CScriptArray::Resize(int delta, asUINT at)
|
|
|
{
|
|
{
|
|
|
- if (delta < 0)
|
|
|
|
|
|
|
+ if( delta < 0 )
|
|
|
{
|
|
{
|
|
|
- if (-delta > (int)buffer->numElements)
|
|
|
|
|
|
|
+ if( -delta > (int)buffer->numElements )
|
|
|
delta = -(int)buffer->numElements;
|
|
delta = -(int)buffer->numElements;
|
|
|
- if (at > buffer->numElements + delta)
|
|
|
|
|
|
|
+ if( at > buffer->numElements + delta )
|
|
|
at = buffer->numElements + delta;
|
|
at = buffer->numElements + delta;
|
|
|
}
|
|
}
|
|
|
- else if (delta > 0)
|
|
|
|
|
|
|
+ else if( delta > 0 )
|
|
|
{
|
|
{
|
|
|
// Make sure the array size isn't too large for us to handle
|
|
// Make sure the array size isn't too large for us to handle
|
|
|
- if (delta > 0 && !CheckMaxSize(buffer->numElements + delta))
|
|
|
|
|
|
|
+ if( delta > 0 && !CheckMaxSize(buffer->numElements + delta) )
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
- if (at > buffer->numElements)
|
|
|
|
|
|
|
+ if( at > buffer->numElements )
|
|
|
at = buffer->numElements;
|
|
at = buffer->numElements;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (delta == 0)
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ if( delta == 0 ) return;
|
|
|
|
|
|
|
|
// Allocate memory for the buffer
|
|
// Allocate memory for the buffer
|
|
|
SArrayBuffer *newBuffer;
|
|
SArrayBuffer *newBuffer;
|
|
|
newBuffer = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1 + elementSize*(buffer->numElements + delta)];
|
|
newBuffer = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1 + elementSize*(buffer->numElements + delta)];
|
|
|
newBuffer->numElements = buffer->numElements + delta;
|
|
newBuffer->numElements = buffer->numElements + delta;
|
|
|
|
|
|
|
|
- int c = newBuffer->numElements > buffer->numElements ? buffer->numElements : newBuffer->numElements;
|
|
|
|
|
memcpy(newBuffer->data, buffer->data, at*elementSize);
|
|
memcpy(newBuffer->data, buffer->data, at*elementSize);
|
|
|
- if (delta > 0 && at < buffer->numElements)
|
|
|
|
|
|
|
+ if( delta > 0 && at < buffer->numElements )
|
|
|
memcpy(newBuffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements-at)*elementSize);
|
|
memcpy(newBuffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements-at)*elementSize);
|
|
|
- else if (delta < 0 && at < buffer->numElements)
|
|
|
|
|
|
|
+ else if( delta < 0 && at < buffer->numElements )
|
|
|
memcpy(newBuffer->data + at*elementSize, buffer->data + (at-delta)*elementSize, (buffer->numElements-at+delta)*elementSize);
|
|
memcpy(newBuffer->data + at*elementSize, buffer->data + (at-delta)*elementSize, (buffer->numElements-at+delta)*elementSize);
|
|
|
|
|
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
- if (typeId & asTYPEID_MASK_OBJECT)
|
|
|
|
|
|
|
+ if( subTypeId & asTYPEID_MASK_OBJECT )
|
|
|
{
|
|
{
|
|
|
- if (delta > 0)
|
|
|
|
|
|
|
+ if( delta > 0 )
|
|
|
Construct(newBuffer, at, at+delta);
|
|
Construct(newBuffer, at, at+delta);
|
|
|
- else if (delta < 0)
|
|
|
|
|
|
|
+ else if( delta < 0 )
|
|
|
Destruct(buffer, at, at-delta);
|
|
Destruct(buffer, at, at-delta);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -325,16 +323,20 @@ bool CScriptArray::CheckMaxSize(asUINT numElements)
|
|
|
// for the array doesn't overflow and becomes smaller than requested
|
|
// for the array doesn't overflow and becomes smaller than requested
|
|
|
|
|
|
|
|
asUINT maxSize = 0xFFFFFFFFul - sizeof(SArrayBuffer) + 1;
|
|
asUINT maxSize = 0xFFFFFFFFul - sizeof(SArrayBuffer) + 1;
|
|
|
- if (objType->GetSubTypeId() & asTYPEID_MASK_OBJECT)
|
|
|
|
|
|
|
+ if( subTypeId & asTYPEID_MASK_OBJECT )
|
|
|
maxSize /= sizeof(void*);
|
|
maxSize /= sizeof(void*);
|
|
|
- else
|
|
|
|
|
|
|
+ else if( elementSize > 0 )
|
|
|
maxSize /= elementSize;
|
|
maxSize /= elementSize;
|
|
|
|
|
|
|
|
- if (numElements > maxSize)
|
|
|
|
|
|
|
+ if( numElements > maxSize )
|
|
|
{
|
|
{
|
|
|
- asIScriptContext* context = asGetActiveContext();
|
|
|
|
|
- if (context)
|
|
|
|
|
- context->SetException("Too large array size");
|
|
|
|
|
|
|
+ asIScriptContext *ctx = asGetActiveContext();
|
|
|
|
|
+ if( ctx )
|
|
|
|
|
+ {
|
|
|
|
|
+ // Set a script exception
|
|
|
|
|
+ ctx->SetException("Too large array size");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -354,16 +356,17 @@ int CScriptArray::GetArrayTypeId() const
|
|
|
|
|
|
|
|
int CScriptArray::GetElementTypeId() const
|
|
int CScriptArray::GetElementTypeId() const
|
|
|
{
|
|
{
|
|
|
- return objType->GetSubTypeId();
|
|
|
|
|
|
|
+ return subTypeId;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CScriptArray::InsertAt(asUINT index, void *value)
|
|
void CScriptArray::InsertAt(asUINT index, void *value)
|
|
|
{
|
|
{
|
|
|
- if (index > buffer->numElements)
|
|
|
|
|
|
|
+ if( index > buffer->numElements )
|
|
|
{
|
|
{
|
|
|
- asIScriptContext* context = asGetActiveContext();
|
|
|
|
|
- if (context)
|
|
|
|
|
- context->SetException("Index out of bounds");
|
|
|
|
|
|
|
+ // If this is called from a script we raise a script exception
|
|
|
|
|
+ asIScriptContext *ctx = asGetActiveContext();
|
|
|
|
|
+ if( ctx )
|
|
|
|
|
+ ctx->SetException("Index out of bounds");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -381,11 +384,12 @@ void CScriptArray::InsertLast(void *value)
|
|
|
|
|
|
|
|
void CScriptArray::RemoveAt(asUINT index)
|
|
void CScriptArray::RemoveAt(asUINT index)
|
|
|
{
|
|
{
|
|
|
- if (index >= buffer->numElements)
|
|
|
|
|
|
|
+ if( index >= buffer->numElements )
|
|
|
{
|
|
{
|
|
|
- asIScriptContext* context = asGetActiveContext();
|
|
|
|
|
- if (context)
|
|
|
|
|
- context->SetException("Index out of bounds");
|
|
|
|
|
|
|
+ // If this is called from a script we raise a script exception
|
|
|
|
|
+ asIScriptContext *ctx = asGetActiveContext();
|
|
|
|
|
+ if( ctx )
|
|
|
|
|
+ ctx->SetException("Index out of bounds");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -401,17 +405,17 @@ void CScriptArray::RemoveLast()
|
|
|
// Return a pointer to the array element. Returns 0 if the index is out of bounds
|
|
// Return a pointer to the array element. Returns 0 if the index is out of bounds
|
|
|
void *CScriptArray::At(asUINT index)
|
|
void *CScriptArray::At(asUINT index)
|
|
|
{
|
|
{
|
|
|
- if (index >= buffer->numElements)
|
|
|
|
|
|
|
+ if( index >= buffer->numElements )
|
|
|
{
|
|
{
|
|
|
- asIScriptContext* context = asGetActiveContext();
|
|
|
|
|
- if (context)
|
|
|
|
|
- context->SetException("Index out of bounds");
|
|
|
|
|
|
|
+ // If this is called from a script we raise a script exception
|
|
|
|
|
+ asIScriptContext *ctx = asGetActiveContext();
|
|
|
|
|
+ if( ctx )
|
|
|
|
|
+ ctx->SetException("Index out of bounds");
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
- if ((typeId & asTYPEID_MASK_OBJECT) && !isArrayOfHandles)
|
|
|
|
|
|
|
+ if( (subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) )
|
|
|
return (void*)((size_t*)buffer->data)[index];
|
|
return (void*)((size_t*)buffer->data)[index];
|
|
|
else
|
|
else
|
|
|
return buffer->data + elementSize*index;
|
|
return buffer->data + elementSize*index;
|
|
@@ -421,8 +425,7 @@ void *CScriptArray::At(asUINT index)
|
|
|
// internal
|
|
// internal
|
|
|
void CScriptArray::CreateBuffer(SArrayBuffer **buf, asUINT numElements)
|
|
void CScriptArray::CreateBuffer(SArrayBuffer **buf, asUINT numElements)
|
|
|
{
|
|
{
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
- if (typeId & asTYPEID_MASK_OBJECT)
|
|
|
|
|
|
|
+ if( subTypeId & asTYPEID_MASK_OBJECT )
|
|
|
{
|
|
{
|
|
|
*buf = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1+sizeof(void*)*numElements];
|
|
*buf = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1+sizeof(void*)*numElements];
|
|
|
(*buf)->numElements = numElements;
|
|
(*buf)->numElements = numElements;
|
|
@@ -448,84 +451,396 @@ void CScriptArray::DeleteBuffer(SArrayBuffer *buf)
|
|
|
// internal
|
|
// internal
|
|
|
void CScriptArray::Construct(SArrayBuffer *buf, asUINT start, asUINT end)
|
|
void CScriptArray::Construct(SArrayBuffer *buf, asUINT start, asUINT end)
|
|
|
{
|
|
{
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
- if (isArrayOfHandles)
|
|
|
|
|
|
|
+ if( subTypeId & asTYPEID_OBJHANDLE )
|
|
|
{
|
|
{
|
|
|
// Set all object handles to null
|
|
// Set all object handles to null
|
|
|
- void* d = (void*)(buf->data + start * sizeof(void*));
|
|
|
|
|
|
|
+ void *d = (void*)(buf->data + start * sizeof(void*));
|
|
|
memset(d, 0, (end-start)*sizeof(void*));
|
|
memset(d, 0, (end-start)*sizeof(void*));
|
|
|
}
|
|
}
|
|
|
- else if (typeId & asTYPEID_MASK_OBJECT)
|
|
|
|
|
|
|
+ else if( subTypeId & asTYPEID_MASK_OBJECT )
|
|
|
{
|
|
{
|
|
|
- void** max = (void**)(buf->data + end * sizeof(void*));
|
|
|
|
|
- void** d = (void**)(buf->data + start * sizeof(void*));
|
|
|
|
|
|
|
+ void **max = (void**)(buf->data + end * sizeof(void*));
|
|
|
|
|
+ void **d = (void**)(buf->data + start * sizeof(void*));
|
|
|
|
|
|
|
|
- asIScriptEngine* engine = objType->GetEngine();
|
|
|
|
|
|
|
+ asIScriptEngine *engine = objType->GetEngine();
|
|
|
|
|
|
|
|
- for (; d < max; d++)
|
|
|
|
|
- *d = (void*)engine->CreateScriptObject(typeId);
|
|
|
|
|
|
|
+ for( ; d < max; d++ )
|
|
|
|
|
+ *d = (void*)engine->CreateScriptObject(subTypeId);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// internal
|
|
// internal
|
|
|
void CScriptArray::Destruct(SArrayBuffer *buf, asUINT start, asUINT end)
|
|
void CScriptArray::Destruct(SArrayBuffer *buf, asUINT start, asUINT end)
|
|
|
{
|
|
{
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
- if (typeId & asTYPEID_MASK_OBJECT)
|
|
|
|
|
|
|
+ if( subTypeId & asTYPEID_MASK_OBJECT )
|
|
|
{
|
|
{
|
|
|
- asIScriptEngine* engine = objType->GetEngine();
|
|
|
|
|
|
|
+ asIScriptEngine *engine = objType->GetEngine();
|
|
|
|
|
|
|
|
- void** max = (void**)(buf->data + end * sizeof(void*));
|
|
|
|
|
- void** d = (void**)(buf->data + start * sizeof(void*));
|
|
|
|
|
|
|
+ void **max = (void**)(buf->data + end * sizeof(void*));
|
|
|
|
|
+ void **d = (void**)(buf->data + start * sizeof(void*));
|
|
|
|
|
|
|
|
- for(; d < max; d++ )
|
|
|
|
|
|
|
+ for( ; d < max; d++ )
|
|
|
{
|
|
{
|
|
|
if( *d )
|
|
if( *d )
|
|
|
- engine->ReleaseScriptObject(*d, typeId);
|
|
|
|
|
|
|
+ engine->ReleaseScriptObject(*d, objType->GetSubType());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// internal
|
|
|
|
|
+bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext *ctx)
|
|
|
|
|
+{
|
|
|
|
|
+ if( !asc )
|
|
|
|
|
+ {
|
|
|
|
|
+ // Swap items
|
|
|
|
|
+ const void *TEMP = a;
|
|
|
|
|
+ a = b;
|
|
|
|
|
+ b = TEMP;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if( subTypeId <= asTYPEID_DOUBLE )
|
|
|
|
|
+ {
|
|
|
|
|
+ // Simple compare of values
|
|
|
|
|
+ switch( subTypeId )
|
|
|
|
|
+ {
|
|
|
|
|
+ #define COMPARE(T) *((T*)a) < *((T*)b)
|
|
|
|
|
+ case asTYPEID_BOOL: return COMPARE(bool);
|
|
|
|
|
+ case asTYPEID_INT8: return COMPARE(signed char);
|
|
|
|
|
+ case asTYPEID_UINT8: return COMPARE(unsigned char);
|
|
|
|
|
+ case asTYPEID_INT16: return COMPARE(signed short);
|
|
|
|
|
+ case asTYPEID_UINT16: return COMPARE(unsigned short);
|
|
|
|
|
+ case asTYPEID_INT32: return COMPARE(signed int);
|
|
|
|
|
+ case asTYPEID_UINT32: return COMPARE(unsigned int);
|
|
|
|
|
+ case asTYPEID_FLOAT: return COMPARE(float);
|
|
|
|
|
+ case asTYPEID_DOUBLE: return COMPARE(double);
|
|
|
|
|
+ #undef COMPARE
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ int r = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // Execute object opCmp
|
|
|
|
|
+ // TODO: Add proper error handling
|
|
|
|
|
+ r = ctx->Prepare(cmpFuncId); assert(r >= 0);
|
|
|
|
|
+ r = ctx->SetObject((void*)a); assert(r >= 0);
|
|
|
|
|
+ r = ctx->SetArgAddress(0, (void*)b); assert(r >= 0);
|
|
|
|
|
+ r = ctx->Execute();
|
|
|
|
|
+
|
|
|
|
|
+ if( r == asEXECUTION_FINISHED )
|
|
|
|
|
+ {
|
|
|
|
|
+ return (int)ctx->GetReturnDWord() < 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void CScriptArray::Reverse()
|
|
|
|
|
+{
|
|
|
|
|
+ asUINT size = GetSize();
|
|
|
|
|
+
|
|
|
|
|
+ if( size >= 2 )
|
|
|
|
|
+ {
|
|
|
|
|
+ asBYTE TEMP[16];
|
|
|
|
|
+
|
|
|
|
|
+ for( asUINT i = 0; i < size / 2; i++ )
|
|
|
|
|
+ {
|
|
|
|
|
+ Copy(TEMP, GetArrayItemPointer(i));
|
|
|
|
|
+ Copy(GetArrayItemPointer(i), GetArrayItemPointer(size - i - 1));
|
|
|
|
|
+ Copy(GetArrayItemPointer(size - i - 1), TEMP);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// internal
|
|
|
|
|
+bool CScriptArray::Equals(const void *a, const void *b, asIScriptContext *ctx)
|
|
|
|
|
+{
|
|
|
|
|
+ if( subTypeId <= asTYPEID_DOUBLE )
|
|
|
|
|
+ {
|
|
|
|
|
+ // Simple compare of values
|
|
|
|
|
+ switch( subTypeId )
|
|
|
|
|
+ {
|
|
|
|
|
+ #define COMPARE(T) *((T*)a) == *((T*)b)
|
|
|
|
|
+ case asTYPEID_BOOL: return COMPARE(bool);
|
|
|
|
|
+ case asTYPEID_INT8: return COMPARE(signed char);
|
|
|
|
|
+ case asTYPEID_UINT8: return COMPARE(unsigned char);
|
|
|
|
|
+ case asTYPEID_INT16: return COMPARE(signed short);
|
|
|
|
|
+ case asTYPEID_UINT16: return COMPARE(unsigned short);
|
|
|
|
|
+ case asTYPEID_INT32: return COMPARE(signed int);
|
|
|
|
|
+ case asTYPEID_UINT32: return COMPARE(unsigned int);
|
|
|
|
|
+ case asTYPEID_FLOAT: return COMPARE(float);
|
|
|
|
|
+ case asTYPEID_DOUBLE: return COMPARE(double);
|
|
|
|
|
+ #undef COMPARE
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ int r = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // Execute object opEquals if available
|
|
|
|
|
+ if( eqFuncId >= 0 )
|
|
|
|
|
+ {
|
|
|
|
|
+ // TODO: Add proper error handling
|
|
|
|
|
+ r = ctx->Prepare(eqFuncId); assert(r >= 0);
|
|
|
|
|
+ r = ctx->SetObject((void*)a); assert(r >= 0);
|
|
|
|
|
+ r = ctx->SetArgAddress(0, (void*)b); assert(r >= 0);
|
|
|
|
|
+ r = ctx->Execute();
|
|
|
|
|
+
|
|
|
|
|
+ if( r == asEXECUTION_FINISHED )
|
|
|
|
|
+ {
|
|
|
|
|
+ return ctx->GetReturnByte() != 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Execute object opCmp if available
|
|
|
|
|
+ if( cmpFuncId >= 0 )
|
|
|
|
|
+ {
|
|
|
|
|
+ // TODO: Add proper error handling
|
|
|
|
|
+ r = ctx->Prepare(cmpFuncId); assert(r >= 0);
|
|
|
|
|
+ r = ctx->SetObject((void*)a); assert(r >= 0);
|
|
|
|
|
+ r = ctx->SetArgAddress(0, (void*)b); assert(r >= 0);
|
|
|
|
|
+ r = ctx->Execute();
|
|
|
|
|
+
|
|
|
|
|
+ if( r == asEXECUTION_FINISHED )
|
|
|
|
|
+ {
|
|
|
|
|
+ return (int)ctx->GetReturnDWord() == 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int CScriptArray::Find(void *value)
|
|
|
|
|
+{
|
|
|
|
|
+ return Find(0, value);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int CScriptArray::Find(asUINT index, void *value)
|
|
|
|
|
+{
|
|
|
|
|
+ // Subtype isn't primitive and doesn't have opEquals / opCmp
|
|
|
|
|
+ if( subTypeId > asTYPEID_DOUBLE && (cmpFuncId <= 0 && eqFuncId <= 0) )
|
|
|
|
|
+ {
|
|
|
|
|
+ asIScriptContext *ctx = asGetActiveContext();
|
|
|
|
|
+ asIObjectType* subType = objType->GetEngine()->GetObjectTypeById(subTypeId);
|
|
|
|
|
+
|
|
|
|
|
+ // Throw an exception
|
|
|
|
|
+ if( ctx )
|
|
|
|
|
+ {
|
|
|
|
|
+ char tmp[512];
|
|
|
|
|
+#if defined(_MSC_VER) && _MSC_VER >= 1500
|
|
|
|
|
+ sprintf_s(tmp, 512, "Type '%s' does not have opEquals / opCmp", subType->GetName());
|
|
|
|
|
+#else
|
|
|
|
|
+ sprintf(tmp, "Type '%s' does not have opEquals / opCmp", subType->GetName());
|
|
|
|
|
+#endif
|
|
|
|
|
+ ctx->SetException(tmp);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ asIScriptContext *cmpContext = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if( subTypeId > asTYPEID_DOUBLE )
|
|
|
|
|
+ {
|
|
|
|
|
+ // TODO: Ideally this context would be retrieved from a pool, so we don't have to
|
|
|
|
|
+ // create a new one everytime. We could keep a context with the array object
|
|
|
|
|
+ // but that would consume a lot of resources as each context is quite heavy.
|
|
|
|
|
+ cmpContext = objType->GetEngine()->CreateContext();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int ret = -1;
|
|
|
|
|
+ asUINT size = GetSize();
|
|
|
|
|
+
|
|
|
|
|
+ if( index < size )
|
|
|
|
|
+ {
|
|
|
|
|
+ for( asUINT i = index; i < size; i++ )
|
|
|
|
|
+ {
|
|
|
|
|
+ // value passed by reference
|
|
|
|
|
+ if( Equals(At(i), (value), cmpContext) )
|
|
|
|
|
+ {
|
|
|
|
|
+ ret = (int)i;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if( cmpContext )
|
|
|
|
|
+ cmpContext->Release();
|
|
|
|
|
+
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// internal
|
|
|
|
|
+// Copy object handle or primitive value
|
|
|
|
|
+void CScriptArray::Copy(void *dst, void *src)
|
|
|
|
|
+{
|
|
|
|
|
+ memcpy(dst, src, elementSize);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// internal
|
|
|
|
|
+// Return pointer to array item (object handle or primitive value)
|
|
|
|
|
+void *CScriptArray::GetArrayItemPointer(int index)
|
|
|
|
|
+{
|
|
|
|
|
+ return buffer->data + index * elementSize;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// internal
|
|
|
|
|
+// Return pointer to data in buffer (object or primitive)
|
|
|
|
|
+void *CScriptArray::GetDataPointer(void *buffer)
|
|
|
|
|
+{
|
|
|
|
|
+ if ((subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) )
|
|
|
|
|
+ {
|
|
|
|
|
+ // Real address of object
|
|
|
|
|
+ return reinterpret_cast<void*>(*(size_t*)buffer);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Primitive is just a raw data
|
|
|
|
|
+ return buffer;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Sort ascending
|
|
|
|
|
+void CScriptArray::SortAsc()
|
|
|
|
|
+{
|
|
|
|
|
+ Sort(0, GetSize(), true);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Sort ascending
|
|
|
|
|
+void CScriptArray::SortAsc(asUINT index, asUINT count)
|
|
|
|
|
+{
|
|
|
|
|
+ Sort(index, count, true);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Sort descending
|
|
|
|
|
+void CScriptArray::SortDesc()
|
|
|
|
|
+{
|
|
|
|
|
+ Sort(0, GetSize(), false);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Sort descending
|
|
|
|
|
+void CScriptArray::SortDesc(asUINT index, asUINT count)
|
|
|
|
|
+{
|
|
|
|
|
+ Sort(index, count, false);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// internal
|
|
|
|
|
+void CScriptArray::Sort(asUINT index, asUINT count, bool asc)
|
|
|
|
|
+{
|
|
|
|
|
+ // Subtype isn't primitive and doesn't have opCmp
|
|
|
|
|
+ if( subTypeId > asTYPEID_DOUBLE && cmpFuncId <= 0 )
|
|
|
|
|
+ {
|
|
|
|
|
+ asIScriptContext *ctx = asGetActiveContext();
|
|
|
|
|
+ asIObjectType* subType = objType->GetEngine()->GetObjectTypeById(subTypeId);
|
|
|
|
|
+
|
|
|
|
|
+ // Throw an exception
|
|
|
|
|
+ if( ctx )
|
|
|
|
|
+ {
|
|
|
|
|
+ char tmp[512];
|
|
|
|
|
+#if defined(_MSC_VER) && _MSC_VER >= 1500
|
|
|
|
|
+ sprintf_s(tmp, 512, "Type '%s' does not have opCmp", subType->GetName());
|
|
|
|
|
+#else
|
|
|
|
|
+ sprintf(tmp, "Type '%s' does not have opCmp", subType->GetName());
|
|
|
|
|
+#endif
|
|
|
|
|
+ ctx->SetException(tmp);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // No need to sort
|
|
|
|
|
+ if( count < 2 )
|
|
|
|
|
+ {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int start = index;
|
|
|
|
|
+ int end = index + count;
|
|
|
|
|
+
|
|
|
|
|
+ // Check if we could access invalid item while sorting
|
|
|
|
|
+ if( start >= (int)buffer->numElements || end > (int)buffer->numElements )
|
|
|
|
|
+ {
|
|
|
|
|
+ asIScriptContext *ctx = asGetActiveContext();
|
|
|
|
|
+
|
|
|
|
|
+ // Throw an exception
|
|
|
|
|
+ if( ctx )
|
|
|
|
|
+ {
|
|
|
|
|
+ ctx->SetException("Index out of bounds");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ asBYTE tmp[16];
|
|
|
|
|
+ asIScriptContext *cmpContext = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if( subTypeId > asTYPEID_DOUBLE )
|
|
|
|
|
+ {
|
|
|
|
|
+ // TODO: Ideally this context would be retrieved from a pool, so we don't have to
|
|
|
|
|
+ // create a new one everytime. We could keep a context with the array object
|
|
|
|
|
+ // but that would consume a lot of resources as each context is quite heavy.
|
|
|
|
|
+ cmpContext = objType->GetEngine()->CreateContext();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Insertion sort
|
|
|
|
|
+ for( int i = start + 1; i < end; i++ )
|
|
|
|
|
+ {
|
|
|
|
|
+ Copy(tmp, GetArrayItemPointer(i));
|
|
|
|
|
+
|
|
|
|
|
+ int j = i - 1;
|
|
|
|
|
+
|
|
|
|
|
+ while( j >= start && Less(GetDataPointer(tmp), At(j), asc, cmpContext) )
|
|
|
|
|
+ {
|
|
|
|
|
+ Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j));
|
|
|
|
|
+ j--;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Copy(GetArrayItemPointer(j + 1), tmp);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if( cmpContext )
|
|
|
|
|
+ cmpContext->Release();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// internal
|
|
// internal
|
|
|
void CScriptArray::CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src)
|
|
void CScriptArray::CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src)
|
|
|
{
|
|
{
|
|
|
- asIScriptEngine* engine = objType->GetEngine();
|
|
|
|
|
- if(isArrayOfHandles)
|
|
|
|
|
|
|
+ asIScriptEngine *engine = objType->GetEngine();
|
|
|
|
|
+ if( subTypeId & asTYPEID_OBJHANDLE )
|
|
|
{
|
|
{
|
|
|
// Copy the references and increase the reference counters
|
|
// Copy the references and increase the reference counters
|
|
|
- if (dst->numElements > 0 && src->numElements > 0)
|
|
|
|
|
|
|
+ if( dst->numElements > 0 && src->numElements > 0 )
|
|
|
{
|
|
{
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
int count = dst->numElements > src->numElements ? src->numElements : dst->numElements;
|
|
int count = dst->numElements > src->numElements ? src->numElements : dst->numElements;
|
|
|
|
|
|
|
|
- void** max = (void**)(dst->data + count * sizeof(void*));
|
|
|
|
|
- void** d = (void**)dst->data;
|
|
|
|
|
- void** s = (void**)src->data;
|
|
|
|
|
|
|
+ void **max = (void**)(dst->data + count * sizeof(void*));
|
|
|
|
|
+ void **d = (void**)dst->data;
|
|
|
|
|
+ void **s = (void**)src->data;
|
|
|
|
|
|
|
|
- for (; d < max; d++, s++)
|
|
|
|
|
|
|
+ for( ; d < max; d++, s++ )
|
|
|
{
|
|
{
|
|
|
*d = *s;
|
|
*d = *s;
|
|
|
- if (*d)
|
|
|
|
|
- engine->AddRefScriptObject(*d, typeId);
|
|
|
|
|
|
|
+ if( *d )
|
|
|
|
|
+ engine->AddRefScriptObject(*d, objType->GetSubType());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- int typeId = objType->GetSubTypeId();
|
|
|
|
|
-
|
|
|
|
|
- if (dst->numElements > 0 && src->numElements > 0)
|
|
|
|
|
|
|
+ if( dst->numElements > 0 && src->numElements > 0 )
|
|
|
{
|
|
{
|
|
|
int count = dst->numElements > src->numElements ? src->numElements : dst->numElements;
|
|
int count = dst->numElements > src->numElements ? src->numElements : dst->numElements;
|
|
|
- if (typeId & asTYPEID_MASK_OBJECT)
|
|
|
|
|
|
|
+ if( subTypeId & asTYPEID_MASK_OBJECT )
|
|
|
{
|
|
{
|
|
|
// Call the assignment operator on all of the objects
|
|
// Call the assignment operator on all of the objects
|
|
|
- void** max = (void**)(dst->data + count * sizeof(void*));
|
|
|
|
|
- void** d = (void**)dst->data;
|
|
|
|
|
- void** s = (void**)src->data;
|
|
|
|
|
|
|
+ void **max = (void**)(dst->data + count * sizeof(void*));
|
|
|
|
|
+ void **d = (void**)dst->data;
|
|
|
|
|
+ void **s = (void**)src->data;
|
|
|
|
|
|
|
|
- for(; d < max; d++, s++)
|
|
|
|
|
- engine->CopyScriptObject(*d, *s, typeId);
|
|
|
|
|
|
|
+ for( ; d < max; d++, s++ )
|
|
|
|
|
+ engine->CopyScriptObject(*d, *s, subTypeId);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -536,6 +851,58 @@ void CScriptArray::CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// internal
|
|
|
|
|
+// Precache some info
|
|
|
|
|
+void CScriptArray::Precache()
|
|
|
|
|
+{
|
|
|
|
|
+ // TODO: optimize: This information could be stored in the object type as user data,
|
|
|
|
|
+ // then it wouldn't be necessary to look for this for each array initialization
|
|
|
|
|
+
|
|
|
|
|
+ subTypeId = objType->GetSubTypeId();
|
|
|
|
|
+
|
|
|
|
|
+ cmpFuncId = -1;
|
|
|
|
|
+ eqFuncId = -1;
|
|
|
|
|
+
|
|
|
|
|
+ // Object - search for opCmp / opEquals
|
|
|
|
|
+ if( subTypeId > asTYPEID_DOUBLE )
|
|
|
|
|
+ {
|
|
|
|
|
+ asIObjectType *subType = objType->GetEngine()->GetObjectTypeById(subTypeId);
|
|
|
|
|
+
|
|
|
|
|
+ if( subType )
|
|
|
|
|
+ {
|
|
|
|
|
+ for( asUINT i = 0; i < subType->GetMethodCount(); i++ )
|
|
|
|
|
+ {
|
|
|
|
|
+ asIScriptFunction *func = subType->GetMethodByIndex(i);
|
|
|
|
|
+
|
|
|
|
|
+ if( func->GetParamCount() == 1 /* && func->IsReadOnly() */ )
|
|
|
|
|
+ {
|
|
|
|
|
+ asDWORD flags = 0;
|
|
|
|
|
+ int returnTypeId = func->GetReturnTypeId();
|
|
|
|
|
+ int paramTypeId = func->GetParamTypeId(0, &flags);
|
|
|
|
|
+
|
|
|
|
|
+ if( flags == asTM_INREF && paramTypeId == subTypeId )
|
|
|
|
|
+ {
|
|
|
|
|
+ if( returnTypeId == asTYPEID_INT32 && strcmp(func->GetName(), "opCmp") == 0 )
|
|
|
|
|
+ {
|
|
|
|
|
+ cmpFuncId = subType->GetMethodIdByIndex(i);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if( returnTypeId == asTYPEID_BOOL && strcmp(func->GetName(), "opEquals") == 0 )
|
|
|
|
|
+ {
|
|
|
|
|
+ eqFuncId = subType->GetMethodIdByIndex(i);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if( cmpFuncId >= 0 && eqFuncId >= 0 )
|
|
|
|
|
+ {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void CScriptArray::AddRef() const
|
|
void CScriptArray::AddRef() const
|
|
|
{
|
|
{
|
|
|
// Clear the GC flag then increase the counter
|
|
// Clear the GC flag then increase the counter
|
|
@@ -547,8 +914,20 @@ void CScriptArray::Release() const
|
|
|
{
|
|
{
|
|
|
// Now do the actual releasing (clearing the flag set by GC)
|
|
// Now do the actual releasing (clearing the flag set by GC)
|
|
|
gcFlag = false;
|
|
gcFlag = false;
|
|
|
- if (--refCount == 0)
|
|
|
|
|
|
|
+ if( --refCount == 0 )
|
|
|
|
|
+ {
|
|
|
delete this;
|
|
delete this;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void ScriptArrayClear(CScriptArray* ptr)
|
|
|
|
|
+{
|
|
|
|
|
+ ptr->Resize(0);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static bool ScriptArrayIsEmpty(CScriptArray* ptr)
|
|
|
|
|
+{
|
|
|
|
|
+ return ptr->GetSize() == 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RegisterArray(asIScriptEngine* engine)
|
|
void RegisterArray(asIScriptEngine* engine)
|
|
@@ -569,9 +948,17 @@ void RegisterArray(asIScriptEngine* engine)
|
|
|
engine->RegisterObjectMethod("Array<T>", "void Push(const T& in)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL);
|
|
engine->RegisterObjectMethod("Array<T>", "void Push(const T& in)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL);
|
|
|
engine->RegisterObjectMethod("Array<T>", "void Pop()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL);
|
|
engine->RegisterObjectMethod("Array<T>", "void Pop()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL);
|
|
|
engine->RegisterObjectMethod("Array<T>", "void Resize(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL);
|
|
engine->RegisterObjectMethod("Array<T>", "void Resize(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL);
|
|
|
- engine->RegisterObjectMethod("Array<T>", "void Clear()", asMETHOD(CScriptArray, Clear), asCALL_THISCALL);
|
|
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "void Clear()", asFUNCTION(ScriptArrayClear), asCALL_CDECL_OBJLAST);
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "void Sort()", asMETHODPR(CScriptArray, SortAsc, (), void), asCALL_THISCALL);
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "void Sort(uint, uint)", asMETHODPR(CScriptArray, SortAsc, (asUINT, asUINT), void), asCALL_THISCALL);
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "void SortReverse()", asMETHODPR(CScriptArray, SortDesc, (), void), asCALL_THISCALL);
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "void SortReverse(uint, uint)", asMETHODPR(CScriptArray, SortDesc, (asUINT, asUINT), void), asCALL_THISCALL);
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "void Reverse()", asMETHOD(CScriptArray, Reverse), asCALL_THISCALL);
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "int Find(const T&in) const", asMETHODPR(CScriptArray, Find, (void*), int), asCALL_THISCALL);
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "int Find(uint, const T&in) const", asMETHODPR(CScriptArray, Find, (asUINT, void*), int), asCALL_THISCALL);
|
|
|
engine->RegisterObjectMethod("Array<T>", "uint get_length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL);
|
|
engine->RegisterObjectMethod("Array<T>", "uint get_length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL);
|
|
|
- engine->RegisterObjectMethod("Array<T>", "bool get_empty() const", asMETHOD(CScriptArray, IsEmpty), asCALL_THISCALL);
|
|
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "void set_length(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL);
|
|
|
|
|
+ engine->RegisterObjectMethod("Array<T>", "bool get_empty() const", asFUNCTION(ScriptArrayIsEmpty), asCALL_CDECL_OBJLAST);
|
|
|
engine->RegisterDefaultArrayType("Array<T>");
|
|
engine->RegisterDefaultArrayType("Array<T>");
|
|
|
}
|
|
}
|
|
|
|
|
|