mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-12-19 17:37:42 -05:00
Initial import
This commit is contained in:
630
AngelScript/source/as_arrayobject.cpp
Normal file
630
AngelScript/source/as_arrayobject.cpp
Normal file
@@ -0,0 +1,630 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2009 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
The original version of this library can be located at:
|
||||
http://www.angelcode.com/angelscript/
|
||||
|
||||
Andreas Jonsson
|
||||
andreas@angelcode.com
|
||||
*/
|
||||
|
||||
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "as_config.h"
|
||||
#include "as_arrayobject.h"
|
||||
#include "as_texts.h"
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
struct sArrayBuffer
|
||||
{
|
||||
asDWORD numElements;
|
||||
asBYTE data[1];
|
||||
};
|
||||
|
||||
static asCArrayObject* ArrayObjectFactory2(asIObjectType *ot, asUINT length)
|
||||
{
|
||||
asCArrayObject *a = asNEW(asCArrayObject)(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 )
|
||||
{
|
||||
asDELETE(a, asCArrayObject);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
asCArrayObject* ArrayObjectFactory(asIObjectType *ot)
|
||||
{
|
||||
return ArrayObjectFactory2(ot, 0);
|
||||
}
|
||||
|
||||
#ifndef AS_MAX_PORTABILITY
|
||||
|
||||
static asCArrayObject &ArrayObjectAssignment(asCArrayObject *other, asCArrayObject *self)
|
||||
{
|
||||
return *self = *other;
|
||||
}
|
||||
|
||||
static void *ArrayObjectAt(asUINT index, asCArrayObject *self)
|
||||
{
|
||||
return self->at(index);
|
||||
}
|
||||
|
||||
static asUINT ArrayObjectLength(asCArrayObject *self)
|
||||
{
|
||||
return self->GetElementCount();
|
||||
}
|
||||
static void ArrayObjectResize(asUINT size, asCArrayObject *self)
|
||||
{
|
||||
self->Resize(size);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void ArrayObjectFactory_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
|
||||
|
||||
*(asCArrayObject**)gen->GetAddressOfReturnLocation() = ArrayObjectFactory(ot);
|
||||
}
|
||||
|
||||
static void ArrayObjectFactory2_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
|
||||
asUINT length = gen->GetArgDWord(1);
|
||||
|
||||
*(asCArrayObject**)gen->GetAddressOfReturnLocation() = ArrayObjectFactory2(ot, length);
|
||||
}
|
||||
|
||||
static void ArrayObjectAssignment_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCArrayObject *other = (asCArrayObject*)gen->GetArgObject(0);
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
|
||||
*self = *other;
|
||||
|
||||
gen->SetReturnObject(self);
|
||||
}
|
||||
|
||||
static void ArrayObjectAt_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asUINT index = gen->GetArgDWord(0);
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
|
||||
gen->SetReturnAddress(self->at(index));
|
||||
}
|
||||
|
||||
static void ArrayObjectLength_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
|
||||
gen->SetReturnDWord(self->GetElementCount());
|
||||
}
|
||||
|
||||
static void ArrayObjectResize_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asUINT size = gen->GetArgDWord(0);
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
|
||||
self->Resize(size);
|
||||
}
|
||||
|
||||
static void ArrayObject_AddRef_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
self->AddRef();
|
||||
}
|
||||
|
||||
static void ArrayObject_Release_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
self->Release();
|
||||
}
|
||||
|
||||
static void ArrayObject_GetRefCount_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
*(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount();
|
||||
}
|
||||
|
||||
static void ArrayObject_SetFlag_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
self->SetFlag();
|
||||
}
|
||||
|
||||
static void ArrayObject_GetFlag_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
*(bool*)gen->GetAddressOfReturnLocation() = self->GetFlag();
|
||||
}
|
||||
|
||||
static void ArrayObject_EnumReferences_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
|
||||
self->EnumReferences(engine);
|
||||
}
|
||||
|
||||
static void ArrayObject_ReleaseAllHandles_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCArrayObject *self = (asCArrayObject*)gen->GetObject();
|
||||
asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
|
||||
self->ReleaseAllHandles(engine);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void RegisterArrayObject(asIScriptEngine *engine)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = engine->RegisterObjectType("_builtin_array_<class T>", sizeof(asCArrayObject), asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); asASSERT( r >= 0 );
|
||||
#ifndef AS_MAX_PORTABILITY
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_FACTORY, "_builtin_array_<T>@ f(int&in)", asFUNCTIONPR(ArrayObjectFactory, (asIObjectType*), asCArrayObject*), asCALL_CDECL); asASSERT( r >= 0 );
|
||||
// TODO: initlist: Need a special behaviour for this
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_FACTORY, "_builtin_array_<T>@ f(int&in, uint)", asFUNCTIONPR(ArrayObjectFactory2, (asIObjectType*, asUINT), asCArrayObject*), asCALL_CDECL); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_ADDREF, "void f()", asMETHOD(asCArrayObject,AddRef), asCALL_THISCALL); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_RELEASE, "void f()", asMETHOD(asCArrayObject,Release), asCALL_THISCALL); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("_builtin_array_<T>", "_builtin_array_<T> &opAssign(const _builtin_array_<T>&in)", asFUNCTION(ArrayObjectAssignment), asCALL_CDECL_OBJLAST); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_INDEX, "T &f(uint)", asFUNCTION(ArrayObjectAt), asCALL_CDECL_OBJLAST); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_INDEX, "const T &f(uint) const", asFUNCTION(ArrayObjectAt), asCALL_CDECL_OBJLAST); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("_builtin_array_<T>", "uint length() const", asFUNCTION(ArrayObjectLength), asCALL_CDECL_OBJLAST); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("_builtin_array_<T>", "void resize(uint)", asFUNCTION(ArrayObjectResize), asCALL_CDECL_OBJLAST); asASSERT( r >= 0 );
|
||||
|
||||
// Register GC behaviours
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCArrayObject,GetRefCount), asCALL_THISCALL); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCArrayObject,SetFlag), asCALL_THISCALL); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCArrayObject,GetFlag), asCALL_THISCALL); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCArrayObject,EnumReferences), asCALL_THISCALL); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCArrayObject,ReleaseAllHandles), asCALL_THISCALL); asASSERT( r >= 0 );
|
||||
#else
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_FACTORY, "_builtin_array_<T>@ f(int&in)", asFUNCTION(ArrayObjectFactory_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
// TODO: initlist: Need a special behaviour for this
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_FACTORY, "_builtin_array_<T>@ f(int&in, uint)", asFUNCTION(ArrayObjectFactory2_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_ADDREF, "void f()", asFUNCTION(ArrayObject_AddRef_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_RELEASE, "void f()", asFUNCTION(ArrayObject_Release_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("_builtin_array_<T>", "_builtin_array_<T> &opAssign(const _builtin_array_<T>&in)", asFUNCTION(ArrayObjectAssignment_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_INDEX, "T &f(uint)", asFUNCTION(ArrayObjectAt_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_INDEX, "const T &f(uint) const", asFUNCTION(ArrayObjectAt_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("_builtin_array_<T>", "uint length() const", asFUNCTION(ArrayObjectLength_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectMethod("_builtin_array_<T>", "void resize(uint)", asFUNCTION(ArrayObjectResize_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
|
||||
// Register GC behaviours
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ArrayObject_GetRefCount_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ArrayObject_SetFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ArrayObject_GetFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ArrayObject_EnumReferences_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
r = engine->RegisterObjectBehaviour("_builtin_array_<T>", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ArrayObject_ReleaseAllHandles_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
asCArrayObject &asCArrayObject::operator=(asCArrayObject &other)
|
||||
{
|
||||
if( &other != this )
|
||||
{
|
||||
if( buffer )
|
||||
{
|
||||
DeleteBuffer(buffer);
|
||||
buffer = 0;
|
||||
}
|
||||
|
||||
// Copy all elements from the other array
|
||||
CreateBuffer(&buffer, other.buffer->numElements);
|
||||
CopyBuffer(buffer, other.buffer);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
int asCArrayObject::CopyFrom(asIScriptArray *other)
|
||||
{
|
||||
if( other == 0 ) return asINVALID_ARG;
|
||||
|
||||
// Verify that the types are equal
|
||||
if( GetArrayTypeId() != other->GetArrayTypeId() )
|
||||
return asINVALID_TYPE;
|
||||
|
||||
*this = *(asCArrayObject*)other;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
asCArrayObject::asCArrayObject(asUINT length, asIObjectType *ot)
|
||||
{
|
||||
refCount.set(1);
|
||||
gcFlag = false;
|
||||
objType = ot;
|
||||
objType->AddRef();
|
||||
buffer = 0;
|
||||
|
||||
// Determine element size
|
||||
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());
|
||||
}
|
||||
|
||||
asCArrayObject::~asCArrayObject()
|
||||
{
|
||||
if( buffer )
|
||||
{
|
||||
DeleteBuffer(buffer);
|
||||
buffer = 0;
|
||||
}
|
||||
if( objType ) objType->Release();
|
||||
}
|
||||
|
||||
asIScriptEngine *asCArrayObject::GetEngine() const
|
||||
{
|
||||
return objType->GetEngine();
|
||||
}
|
||||
|
||||
asUINT asCArrayObject::GetElementCount()
|
||||
{
|
||||
return buffer->numElements;
|
||||
}
|
||||
|
||||
void asCArrayObject::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*)asNEWARRAY(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*)asNEWARRAY(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
|
||||
userFree(buffer);
|
||||
|
||||
buffer = newBuffer;
|
||||
}
|
||||
|
||||
// internal
|
||||
bool asCArrayObject::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;
|
||||
}
|
||||
|
||||
int asCArrayObject::GetArrayTypeId()
|
||||
{
|
||||
return objType->GetTypeId();
|
||||
}
|
||||
|
||||
int asCArrayObject::GetElementTypeId()
|
||||
{
|
||||
return objType->GetSubTypeId();
|
||||
}
|
||||
|
||||
void *asCArrayObject::GetElementPointer(asUINT index)
|
||||
{
|
||||
if( index >= buffer->numElements ) return 0;
|
||||
|
||||
int typeId = objType->GetSubTypeId();
|
||||
if( (typeId & asTYPEID_MASK_OBJECT) && !isArrayOfHandles )
|
||||
return (void*)((size_t*)buffer->data)[index];
|
||||
else
|
||||
return buffer->data + elementSize*index;
|
||||
}
|
||||
|
||||
void *asCArrayObject::at(asUINT index)
|
||||
{
|
||||
if( index >= buffer->numElements )
|
||||
{
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
if( ctx )
|
||||
ctx->SetException(TXT_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;
|
||||
}
|
||||
}
|
||||
|
||||
void asCArrayObject::CreateBuffer(sArrayBuffer **buf, asUINT numElements)
|
||||
{
|
||||
int typeId = objType->GetSubTypeId();
|
||||
if( typeId & asTYPEID_MASK_OBJECT )
|
||||
{
|
||||
*buf = (sArrayBuffer*)asNEWARRAY(asBYTE, sizeof(sArrayBuffer)-1+sizeof(void*)*numElements);
|
||||
(*buf)->numElements = numElements;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buf = (sArrayBuffer*)asNEWARRAY(asBYTE, sizeof(sArrayBuffer)-1+elementSize*numElements);
|
||||
(*buf)->numElements = numElements;
|
||||
}
|
||||
|
||||
Construct(*buf, 0, numElements);
|
||||
}
|
||||
|
||||
void asCArrayObject::DeleteBuffer(sArrayBuffer *buf)
|
||||
{
|
||||
Destruct(buf, 0, buf->numElements);
|
||||
|
||||
// Free the buffer
|
||||
asDELETEARRAY(buf);
|
||||
}
|
||||
|
||||
void asCArrayObject::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);
|
||||
}
|
||||
}
|
||||
|
||||
void asCArrayObject::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void asCArrayObject::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void asCArrayObject::Destruct()
|
||||
{
|
||||
// Call destructor and free the memory
|
||||
asDELETE(this, asCArrayObject);
|
||||
}
|
||||
|
||||
void asCArrayObject::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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void asCArrayObject::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int asCArrayObject::AddRef()
|
||||
{
|
||||
// Clear the GC flag then increase the counter
|
||||
gcFlag = false;
|
||||
return refCount.atomicInc();
|
||||
}
|
||||
|
||||
int asCArrayObject::Release()
|
||||
{
|
||||
// Now do the actual releasing (clearing the flag set by GC)
|
||||
gcFlag = false;
|
||||
int r = refCount.atomicDec();
|
||||
if( r == 0 )
|
||||
{
|
||||
Destruct();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int asCArrayObject::GetRefCount()
|
||||
{
|
||||
return refCount.get();
|
||||
}
|
||||
|
||||
void asCArrayObject::SetFlag()
|
||||
{
|
||||
gcFlag = true;
|
||||
}
|
||||
|
||||
bool asCArrayObject::GetFlag()
|
||||
{
|
||||
return gcFlag;
|
||||
}
|
||||
|
||||
END_AS_NAMESPACE
|
||||
Reference in New Issue
Block a user