mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-12-19 17:37:42 -05:00
643 lines
20 KiB
C++
643 lines
20 KiB
C++
#include <new>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include "scriptarray.h"
|
|
|
|
BEGIN_AS_NAMESPACE
|
|
|
|
struct SArrayBuffer
|
|
{
|
|
asDWORD numElements;
|
|
asBYTE data[1];
|
|
};
|
|
|
|
static CScriptArray* ScriptArrayFactory2(asIObjectType *ot, asUINT length)
|
|
{
|
|
CScriptArray *a = new CScriptArray(length, ot);
|
|
|
|
// 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.
|
|
asIScriptContext *ctx = asGetActiveContext();
|
|
if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION )
|
|
{
|
|
delete a;
|
|
return 0;
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
static CScriptArray* ScriptArrayFactory(asIObjectType *ot)
|
|
{
|
|
return ScriptArrayFactory2(ot, 0);
|
|
}
|
|
|
|
// 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
|
|
// subtype at compile time, instead of at runtime.
|
|
static bool ScriptArrayTemplateCallback(asIObjectType *ot)
|
|
{
|
|
// Make sure the subtype can be instanciated with a default factory/constructor,
|
|
// otherwise we won't be able to instanciate the elements
|
|
int typeId = ot->GetSubTypeId();
|
|
if( (typeId & asTYPEID_MASK_OBJECT) && !(typeId & asTYPEID_OBJHANDLE) )
|
|
{
|
|
asIObjectType *subtype = ot->GetEngine()->GetObjectTypeById(typeId);
|
|
asDWORD flags = subtype->GetFlags();
|
|
if( (flags & asOBJ_VALUE) && !(flags & asOBJ_POD) )
|
|
{
|
|
// Verify that there is a default constructor
|
|
for( int n = 0; n < subtype->GetBehaviourCount(); n++ )
|
|
{
|
|
asEBehaviours beh;
|
|
int funcId = subtype->GetBehaviourByIndex(n, &beh);
|
|
if( beh != asBEHAVE_CONSTRUCT ) continue;
|
|
|
|
asIScriptFunction *func = ot->GetEngine()->GetFunctionDescriptorById(funcId);
|
|
if( func->GetParamCount() == 0 )
|
|
{
|
|
// Found the default constructor
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// There is no default constructor
|
|
return false;
|
|
}
|
|
else if( (flags & asOBJ_REF) )
|
|
{
|
|
// Verify that there is a default factory
|
|
for( int n = 0; n < subtype->GetFactoryCount(); n++ )
|
|
{
|
|
int funcId = subtype->GetFactoryIdByIndex(n);
|
|
asIScriptFunction *func = ot->GetEngine()->GetFunctionDescriptorById(funcId);
|
|
if( func->GetParamCount() == 0 )
|
|
{
|
|
// Found the default factory
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// No default factory
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// The type is ok
|
|
return true;
|
|
}
|
|
|
|
// Registers the template array type
|
|
void RegisterScriptArray(asIScriptEngine *engine)
|
|
{
|
|
if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") == 0 )
|
|
RegisterScriptArray_Native(engine);
|
|
else
|
|
RegisterScriptArray_Generic(engine);
|
|
}
|
|
|
|
void RegisterScriptArray_Native(asIScriptEngine *engine)
|
|
{
|
|
int r;
|
|
|
|
// Register the array type as a template
|
|
r = engine->RegisterObjectType("array<class T>", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 );
|
|
|
|
// Register a callback for validating the subtype before it is used
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in)", asFUNCTION(ScriptArrayTemplateCallback), asCALL_CDECL); assert( r >= 0 );
|
|
|
|
// Templates receive the object type as the first parameter. To the script writer this is hidden
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in)", asFUNCTIONPR(ScriptArrayFactory, (asIObjectType*), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint)", asFUNCTIONPR(ScriptArrayFactory2, (asIObjectType*, asUINT), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
|
|
|
|
// The memory management methods
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptArray,AddRef), asCALL_THISCALL); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptArray,Release), asCALL_THISCALL); assert( r >= 0 );
|
|
|
|
// The index operator returns the template subtype
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_INDEX, "T &f(uint)", asMETHOD(CScriptArray, At), asCALL_THISCALL); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_INDEX, "const T &f(uint) const", asMETHOD(CScriptArray, At), asCALL_THISCALL); assert( r >= 0 );
|
|
|
|
// The assignment operator
|
|
r = engine->RegisterObjectMethod("array<T>", "array<T> &opAssign(const array<T>&in)", asMETHOD(CScriptArray, operator=), asCALL_THISCALL); assert( r >= 0 );
|
|
|
|
// Other methods
|
|
r = engine->RegisterObjectMethod("array<T>", "uint length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 );
|
|
r = engine->RegisterObjectMethod("array<T>", "void resize(uint)", asMETHOD(CScriptArray, Resize), asCALL_THISCALL); assert( r >= 0 );
|
|
|
|
// Register GC behaviours in case the array needs to be garbage collected
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(CScriptArray, GetRefCount), asCALL_THISCALL); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_SETGCFLAG, "void f()", asMETHOD(CScriptArray, SetFlag), asCALL_THISCALL); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(CScriptArray, GetFlag), asCALL_THISCALL); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptArray, EnumReferences), asCALL_THISCALL); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptArray, ReleaseAllHandles), asCALL_THISCALL); assert( r >= 0 );
|
|
}
|
|
|
|
CScriptArray &CScriptArray::operator=(const CScriptArray &other)
|
|
{
|
|
// Only perform the copy if the array types are the same
|
|
if( &other != this &&
|
|
other.GetArrayObjectType() == GetArrayObjectType() )
|
|
{
|
|
if( buffer )
|
|
{
|
|
DeleteBuffer(buffer);
|
|
buffer = 0;
|
|
}
|
|
|
|
// Copy all elements from the other array
|
|
CreateBuffer(&buffer, other.buffer->numElements);
|
|
CopyBuffer(buffer, other.buffer);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
CScriptArray::CScriptArray(asUINT length, asIObjectType *ot)
|
|
{
|
|
refCount = 1;
|
|
gcFlag = false;
|
|
objType = ot;
|
|
objType->AddRef();
|
|
buffer = 0;
|
|
|
|
// Determine element size
|
|
// TODO: Should probably store the template sub type id as well
|
|
int typeId = objType->GetSubTypeId();
|
|
if( typeId & asTYPEID_MASK_OBJECT )
|
|
{
|
|
elementSize = sizeof(asPWORD);
|
|
}
|
|
else
|
|
{
|
|
elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(typeId);
|
|
}
|
|
|
|
isArrayOfHandles = typeId & asTYPEID_OBJHANDLE ? true : false;
|
|
|
|
// Make sure the array size isn't too large for us to handle
|
|
if( !CheckMaxSize(length) )
|
|
{
|
|
// Don't continue with the initialization
|
|
return;
|
|
}
|
|
|
|
CreateBuffer(&buffer, length);
|
|
|
|
// Notify the GC of the successful creation
|
|
if( objType->GetFlags() & asOBJ_GC )
|
|
objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType->GetTypeId());
|
|
}
|
|
|
|
CScriptArray::~CScriptArray()
|
|
{
|
|
if( buffer )
|
|
{
|
|
DeleteBuffer(buffer);
|
|
buffer = 0;
|
|
}
|
|
if( objType ) objType->Release();
|
|
}
|
|
|
|
asUINT CScriptArray::GetSize()
|
|
{
|
|
return buffer->numElements;
|
|
}
|
|
|
|
void CScriptArray::Resize(asUINT numElements)
|
|
{
|
|
// Don't do anything if the size is already correct
|
|
if( numElements == buffer->numElements )
|
|
return;
|
|
|
|
// Make sure the array size isn't too large for us to handle
|
|
if( !CheckMaxSize(numElements) )
|
|
{
|
|
// Don't resize the array
|
|
return;
|
|
}
|
|
|
|
SArrayBuffer *newBuffer;
|
|
int typeId = objType->GetSubTypeId();
|
|
if( typeId & asTYPEID_MASK_OBJECT )
|
|
{
|
|
// Allocate memory for the buffer
|
|
newBuffer = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1+sizeof(void*)*numElements];
|
|
newBuffer->numElements = numElements;
|
|
|
|
// Copy the elements from the old buffer
|
|
int c = numElements > buffer->numElements ? buffer->numElements : numElements;
|
|
asDWORD **d = (asDWORD**)newBuffer->data;
|
|
asDWORD **s = (asDWORD**)buffer->data;
|
|
for( int n = 0; n < c; n++ )
|
|
d[n] = s[n];
|
|
|
|
if( numElements > buffer->numElements )
|
|
{
|
|
Construct(newBuffer, buffer->numElements, numElements);
|
|
}
|
|
else if( numElements < buffer->numElements )
|
|
{
|
|
Destruct(buffer, numElements, buffer->numElements);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Allocate memory for the buffer
|
|
newBuffer = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1+elementSize*numElements];
|
|
newBuffer->numElements = numElements;
|
|
|
|
int c = numElements > buffer->numElements ? buffer->numElements : numElements;
|
|
memcpy(newBuffer->data, buffer->data, c*elementSize);
|
|
}
|
|
|
|
// Release the old buffer
|
|
delete[] (asBYTE*)buffer;
|
|
|
|
buffer = newBuffer;
|
|
}
|
|
|
|
// internal
|
|
bool CScriptArray::CheckMaxSize(asUINT numElements)
|
|
{
|
|
// This code makes sure the size of the buffer that is allocated
|
|
// for the array doesn't overflow and becomes smaller than requested
|
|
|
|
asUINT maxSize = 0xFFFFFFFFul - sizeof(SArrayBuffer) + 1;
|
|
if( objType->GetSubTypeId() & asTYPEID_MASK_OBJECT )
|
|
{
|
|
maxSize /= sizeof(void*);
|
|
}
|
|
else
|
|
{
|
|
maxSize /= elementSize;
|
|
}
|
|
|
|
if( numElements > maxSize )
|
|
{
|
|
asIScriptContext *ctx = asGetActiveContext();
|
|
if( ctx )
|
|
{
|
|
// Set a script exception
|
|
ctx->SetException("Too large array size");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// OK
|
|
return true;
|
|
}
|
|
|
|
asIObjectType *CScriptArray::GetArrayObjectType() const
|
|
{
|
|
return objType;
|
|
}
|
|
|
|
int CScriptArray::GetArrayTypeId() const
|
|
{
|
|
return objType->GetTypeId();
|
|
}
|
|
|
|
int CScriptArray::GetElementTypeId() const
|
|
{
|
|
return objType->GetSubTypeId();
|
|
}
|
|
|
|
// Return a pointer to the array element. Returns 0 if the index is out of bounds
|
|
void *CScriptArray::At(asUINT index)
|
|
{
|
|
if( index >= buffer->numElements )
|
|
{
|
|
// 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;
|
|
}
|
|
else
|
|
{
|
|
int typeId = objType->GetSubTypeId();
|
|
if( (typeId & asTYPEID_MASK_OBJECT) && !isArrayOfHandles )
|
|
return (void*)((size_t*)buffer->data)[index];
|
|
else
|
|
return buffer->data + elementSize*index;
|
|
}
|
|
}
|
|
|
|
// internal
|
|
void CScriptArray::CreateBuffer(SArrayBuffer **buf, asUINT numElements)
|
|
{
|
|
int typeId = objType->GetSubTypeId();
|
|
if( typeId & asTYPEID_MASK_OBJECT )
|
|
{
|
|
*buf = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1+sizeof(void*)*numElements];
|
|
(*buf)->numElements = numElements;
|
|
}
|
|
else
|
|
{
|
|
*buf = (SArrayBuffer*)new asBYTE[sizeof(SArrayBuffer)-1+elementSize*numElements];
|
|
(*buf)->numElements = numElements;
|
|
}
|
|
|
|
Construct(*buf, 0, numElements);
|
|
}
|
|
|
|
// internal
|
|
void CScriptArray::DeleteBuffer(SArrayBuffer *buf)
|
|
{
|
|
Destruct(buf, 0, buf->numElements);
|
|
|
|
// Free the buffer
|
|
delete[] (asBYTE*)buf;
|
|
}
|
|
|
|
// internal
|
|
void CScriptArray::Construct(SArrayBuffer *buf, asUINT start, asUINT end)
|
|
{
|
|
int typeId = objType->GetSubTypeId();
|
|
if( isArrayOfHandles )
|
|
{
|
|
// Set all object handles to null
|
|
asDWORD *d = (asDWORD*)(buf->data + start * sizeof(void*));
|
|
memset(d, 0, (end-start)*sizeof(void*));
|
|
}
|
|
else if( typeId & asTYPEID_MASK_OBJECT )
|
|
{
|
|
asDWORD **max = (asDWORD**)(buf->data + end * sizeof(void*));
|
|
asDWORD **d = (asDWORD**)(buf->data + start * sizeof(void*));
|
|
|
|
asIScriptEngine *engine = objType->GetEngine();
|
|
|
|
for( ; d < max; d++ )
|
|
*d = (asDWORD*)engine->CreateScriptObject(typeId);
|
|
}
|
|
}
|
|
|
|
// internal
|
|
void CScriptArray::Destruct(SArrayBuffer *buf, asUINT start, asUINT end)
|
|
{
|
|
int typeId = objType->GetSubTypeId();
|
|
if( typeId & asTYPEID_MASK_OBJECT )
|
|
{
|
|
asIScriptEngine *engine = objType->GetEngine();
|
|
|
|
asDWORD **max = (asDWORD**)(buf->data + end * sizeof(void*));
|
|
asDWORD **d = (asDWORD**)(buf->data + start * sizeof(void*));
|
|
|
|
for( ; d < max; d++ )
|
|
{
|
|
if( *d )
|
|
engine->ReleaseScriptObject(*d, typeId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// internal
|
|
void CScriptArray::CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src)
|
|
{
|
|
asIScriptEngine *engine = objType->GetEngine();
|
|
if( isArrayOfHandles )
|
|
{
|
|
// Copy the references and increase the reference counters
|
|
if( dst->numElements > 0 && src->numElements > 0 )
|
|
{
|
|
int typeId = objType->GetSubTypeId();
|
|
int count = dst->numElements > src->numElements ? src->numElements : dst->numElements;
|
|
|
|
asDWORD **max = (asDWORD**)(dst->data + count * sizeof(void*));
|
|
asDWORD **d = (asDWORD**)dst->data;
|
|
asDWORD **s = (asDWORD**)src->data;
|
|
|
|
for( ; d < max; d++, s++ )
|
|
{
|
|
*d = *s;
|
|
if( *d )
|
|
engine->AddRefScriptObject(*d, typeId);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int typeId = objType->GetSubTypeId();
|
|
|
|
if( dst->numElements > 0 && src->numElements > 0 )
|
|
{
|
|
int count = dst->numElements > src->numElements ? src->numElements : dst->numElements;
|
|
if( typeId & asTYPEID_MASK_OBJECT )
|
|
{
|
|
// Call the assignment operator on all of the objects
|
|
asDWORD **max = (asDWORD**)(dst->data + count * sizeof(void*));
|
|
asDWORD **d = (asDWORD**)dst->data;
|
|
asDWORD **s = (asDWORD**)src->data;
|
|
|
|
for( ; d < max; d++, s++ )
|
|
engine->CopyScriptObject(*d, *s, typeId);
|
|
}
|
|
else
|
|
{
|
|
// Primitives are copied byte for byte
|
|
memcpy(dst->data, src->data, count*elementSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// GC behaviour
|
|
void CScriptArray::EnumReferences(asIScriptEngine *engine)
|
|
{
|
|
// If the array is holding handles, then we need to notify the GC of them
|
|
int typeId = objType->GetSubTypeId();
|
|
if( typeId & asTYPEID_MASK_OBJECT )
|
|
{
|
|
void **d = (void**)buffer->data;
|
|
for( asUINT n = 0; n < buffer->numElements; n++ )
|
|
{
|
|
if( d[n] )
|
|
engine->GCEnumCallback(d[n]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// GC behaviour
|
|
void CScriptArray::ReleaseAllHandles(asIScriptEngine *engine)
|
|
{
|
|
int subTypeId = objType->GetSubTypeId();
|
|
asIObjectType *subType = engine->GetObjectTypeById(subTypeId);
|
|
if( subType && subType->GetFlags() & asOBJ_GC )
|
|
{
|
|
void **d = (void**)buffer->data;
|
|
for( asUINT n = 0; n < buffer->numElements; n++ )
|
|
{
|
|
if( d[n] )
|
|
{
|
|
engine->ReleaseScriptObject(d[n], subTypeId);
|
|
d[n] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CScriptArray::AddRef()
|
|
{
|
|
// Clear the GC flag then increase the counter
|
|
gcFlag = false;
|
|
refCount++;
|
|
}
|
|
|
|
void CScriptArray::Release()
|
|
{
|
|
// Now do the actual releasing (clearing the flag set by GC)
|
|
gcFlag = false;
|
|
if( --refCount == 0 )
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
// GC behaviour
|
|
int CScriptArray::GetRefCount()
|
|
{
|
|
return refCount;
|
|
}
|
|
|
|
// GC behaviour
|
|
void CScriptArray::SetFlag()
|
|
{
|
|
gcFlag = true;
|
|
}
|
|
|
|
// GC behaviour
|
|
bool CScriptArray::GetFlag()
|
|
{
|
|
return gcFlag;
|
|
}
|
|
|
|
//--------------------------------------------
|
|
// Generic calling conventions
|
|
|
|
static void ScriptArrayFactory_Generic(asIScriptGeneric *gen)
|
|
{
|
|
asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
|
|
|
|
*(CScriptArray**)gen->GetAddressOfReturnLocation() = ScriptArrayFactory(ot);
|
|
}
|
|
|
|
static void ScriptArrayFactory2_Generic(asIScriptGeneric *gen)
|
|
{
|
|
asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
|
|
asUINT length = gen->GetArgDWord(1);
|
|
|
|
*(CScriptArray**)gen->GetAddressOfReturnLocation() = ScriptArrayFactory2(ot, length);
|
|
}
|
|
|
|
static void ScriptArrayTemplateCallback_Generic(asIScriptGeneric *gen)
|
|
{
|
|
asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
|
|
*(bool*)gen->GetAddressOfReturnLocation() = ScriptArrayTemplateCallback(ot);
|
|
}
|
|
|
|
static void ScriptArrayAssignment_Generic(asIScriptGeneric *gen)
|
|
{
|
|
CScriptArray *other = (CScriptArray*)gen->GetArgObject(0);
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
|
|
*self = *other;
|
|
|
|
gen->SetReturnObject(self);
|
|
}
|
|
|
|
static void ScriptArrayAt_Generic(asIScriptGeneric *gen)
|
|
{
|
|
asUINT index = gen->GetArgDWord(0);
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
|
|
gen->SetReturnAddress(self->At(index));
|
|
}
|
|
|
|
static void ScriptArrayLength_Generic(asIScriptGeneric *gen)
|
|
{
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
|
|
gen->SetReturnDWord(self->GetSize());
|
|
}
|
|
|
|
static void ScriptArrayResize_Generic(asIScriptGeneric *gen)
|
|
{
|
|
asUINT size = gen->GetArgDWord(0);
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
|
|
self->Resize(size);
|
|
}
|
|
|
|
static void ScriptArrayAddRef_Generic(asIScriptGeneric *gen)
|
|
{
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
self->AddRef();
|
|
}
|
|
|
|
static void ScriptArrayRelease_Generic(asIScriptGeneric *gen)
|
|
{
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
self->Release();
|
|
}
|
|
|
|
static void ScriptArrayGetRefCount_Generic(asIScriptGeneric *gen)
|
|
{
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
*(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount();
|
|
}
|
|
|
|
static void ScriptArraySetFlag_Generic(asIScriptGeneric *gen)
|
|
{
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
self->SetFlag();
|
|
}
|
|
|
|
static void ScriptArrayGetFlag_Generic(asIScriptGeneric *gen)
|
|
{
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
*(bool*)gen->GetAddressOfReturnLocation() = self->GetFlag();
|
|
}
|
|
|
|
static void ScriptArrayEnumReferences_Generic(asIScriptGeneric *gen)
|
|
{
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
|
|
self->EnumReferences(engine);
|
|
}
|
|
|
|
static void ScriptArrayReleaseAllHandles_Generic(asIScriptGeneric *gen)
|
|
{
|
|
CScriptArray *self = (CScriptArray*)gen->GetObject();
|
|
asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
|
|
self->ReleaseAllHandles(engine);
|
|
}
|
|
|
|
void RegisterScriptArray_Generic(asIScriptEngine *engine)
|
|
{
|
|
int r;
|
|
|
|
r = engine->RegisterObjectType("array<class T>", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 );
|
|
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in)", asFUNCTION(ScriptArrayFactory_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in)", asFUNCTION(ScriptArrayTemplateCallback_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint)", asFUNCTION(ScriptArrayFactory2_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptArrayAddRef_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptArrayRelease_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_INDEX, "T &f(uint)", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_INDEX, "const T &f(uint) const", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectMethod("array<T>", "array<T> &opAssign(const array<T>&in)", asFUNCTION(ScriptArrayAssignment_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectMethod("array<T>", "uint length() const", asFUNCTION(ScriptArrayLength_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectMethod("array<T>", "void resize(uint)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptArrayGetRefCount_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptArraySetFlag_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptArrayGetFlag_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptArrayEnumReferences_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptArrayReleaseAllHandles_Generic), asCALL_GENERIC); assert( r >= 0 );
|
|
}
|
|
|
|
END_AS_NAMESPACE
|