From e748f6e96fc19c1e93c7cc7aea76073fa364f00b Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sat, 27 Mar 2021 22:39:25 +0100 Subject: [PATCH] Updates Angelscript addons, adds angelscript dictionary addon. --- .../scriptarray/scriptarray.cpp | 141 +- .../scriptarray/scriptarray.h | 2 +- .../scriptbuilder/scriptbuilder.h | 7 +- .../scriptdictionary/scriptdictionary.cpp | 1299 +++++++++++++++++ .../scriptdictionary/scriptdictionary.h | 240 +++ .../scripthandle/scripthandle.cpp | 527 ++++--- .../scripthelper/scripthelper.cpp | 3 +- .../scriptstdstring/scriptstdstring.cpp | 71 +- .../scriptstdstring/scriptstdstring_utils.cpp | 3 +- .../AngelScript/AngelScriptResolver.cpp | 4 +- 10 files changed, 1921 insertions(+), 376 deletions(-) create mode 100644 extern/angelscript_addons/scriptdictionary/scriptdictionary.cpp create mode 100644 extern/angelscript_addons/scriptdictionary/scriptdictionary.h diff --git a/extern/angelscript_addons/scriptarray/scriptarray.cpp b/extern/angelscript_addons/scriptarray/scriptarray.cpp index d7ccda3..58512f3 100644 --- a/extern/angelscript_addons/scriptarray/scriptarray.cpp +++ b/extern/angelscript_addons/scriptarray/scriptarray.cpp @@ -4,6 +4,7 @@ #include #include // sprintf #include +#include // std::sort #include "scriptarray.h" @@ -998,7 +999,7 @@ void CScriptArray::Destruct(SArrayBuffer *buf, asUINT start, asUINT end) // internal -bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache) +bool CScriptArray::Less(const void *a, const void *b, bool asc) { if( !asc ) { @@ -1027,42 +1028,6 @@ bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext #undef COMPARE } } - else - { - int r = 0; - - if( subTypeId & asTYPEID_OBJHANDLE ) - { - // Allow sort to work even if the array contains null handles - if( *(void**)a == 0 ) return true; - if( *(void**)b == 0 ) return false; - } - - // Execute object opCmp - if( cache && cache->cmpFunc ) - { - // TODO: Add proper error handling - r = ctx->Prepare(cache->cmpFunc); assert(r >= 0); - - if( subTypeId & asTYPEID_OBJHANDLE ) - { - r = ctx->SetObject(*((void**)a)); assert(r >= 0); - r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); - } - else - { - r = ctx->SetObject((void*)a); assert(r >= 0); - r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); - } - - r = ctx->Execute(); - - if( r == asEXECUTION_FINISHED ) - { - return (int)ctx->GetReturnDWord() < 0; - } - } - } return false; } @@ -1475,12 +1440,11 @@ void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc) return; } - asBYTE tmp[16]; - asIScriptContext *cmpContext = 0; - bool isNested = false; - if( subTypeId & ~asTYPEID_MASK_SEQNBR ) { + asIScriptContext *cmpContext = 0; + bool isNested = false; + // Try to reuse the active context cmpContext = asGetActiveContext(); if( cmpContext ) @@ -1491,38 +1455,83 @@ void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc) cmpContext = 0; } if( cmpContext == 0 ) - { cmpContext = objType->GetEngine()->RequestContext(); + + // Do the sorting + struct { + bool asc; + asIScriptContext *cmpContext; + asIScriptFunction *cmpFunc; + bool operator()(void *a, void *b) const + { + if( !asc ) + { + // Swap items + void *TEMP = a; + a = b; + b = TEMP; + } + + int r = 0; + + // Allow sort to work even if the array contains null handles + if( a == 0 ) return true; + if( b == 0 ) return false; + + // Execute object opCmp + if( cmpFunc ) + { + // TODO: Add proper error handling + r = cmpContext->Prepare(cmpFunc); assert(r >= 0); + r = cmpContext->SetObject(a); assert(r >= 0); + r = cmpContext->SetArgObject(0, b); assert(r >= 0); + r = cmpContext->Execute(); + + if( r == asEXECUTION_FINISHED ) + { + return (int)cmpContext->GetReturnDWord() < 0; + } + } + + return false; + } + } customLess = {asc, cmpContext, cache ? cache->cmpFunc : 0}; + std::sort((void**)GetArrayItemPointer(start), (void**)GetArrayItemPointer(end), customLess); + + // Clean up + if( cmpContext ) + { + if( isNested ) + { + asEContextState state = cmpContext->GetState(); + cmpContext->PopState(); + if( state == asEXECUTION_ABORTED ) + cmpContext->Abort(); + } + else + objType->GetEngine()->ReturnContext(cmpContext); } } - - // Insertion sort - for( int i = start + 1; i < end; i++ ) + else { - Copy(tmp, GetArrayItemPointer(i)); - - int j = i - 1; - - while( j >= start && Less(GetDataPointer(tmp), At(j), asc, cmpContext, cache) ) + // TODO: Use std::sort for primitive types too + + // Insertion sort + asBYTE tmp[16]; + for( int i = start + 1; i < end; i++ ) { - Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j)); - j--; - } + Copy(tmp, GetArrayItemPointer(i)); - Copy(GetArrayItemPointer(j + 1), tmp); - } + int j = i - 1; - if( cmpContext ) - { - if( isNested ) - { - asEContextState state = cmpContext->GetState(); - cmpContext->PopState(); - if( state == asEXECUTION_ABORTED ) - cmpContext->Abort(); + while( j >= start && Less(GetDataPointer(tmp), At(j), asc) ) + { + Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j)); + j--; + } + + Copy(GetArrayItemPointer(j + 1), tmp); } - else - objType->GetEngine()->ReturnContext(cmpContext); } } @@ -1550,7 +1559,6 @@ void CScriptArray::Sort(asIScriptFunction *func, asUINT startAt, asUINT count) return; } - asBYTE tmp[16]; asIScriptContext *cmpContext = 0; bool isNested = false; @@ -1567,6 +1575,7 @@ void CScriptArray::Sort(asIScriptFunction *func, asUINT startAt, asUINT count) cmpContext = objType->GetEngine()->RequestContext(); // Insertion sort + asBYTE tmp[16]; for (asUINT i = start + 1; i < end; i++) { Copy(tmp, GetArrayItemPointer(i)); diff --git a/extern/angelscript_addons/scriptarray/scriptarray.h b/extern/angelscript_addons/scriptarray/scriptarray.h index 41b34dd..4903a97 100644 --- a/extern/angelscript_addons/scriptarray/scriptarray.h +++ b/extern/angelscript_addons/scriptarray/scriptarray.h @@ -120,7 +120,7 @@ protected: CScriptArray(const CScriptArray &other); virtual ~CScriptArray(); - bool Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache); + bool Less(const void *a, const void *b, bool asc); void *GetArrayItemPointer(int index); void *GetDataPointer(void *buffer); void Copy(void *dst, void *src); diff --git a/extern/angelscript_addons/scriptbuilder/scriptbuilder.h b/extern/angelscript_addons/scriptbuilder/scriptbuilder.h index 4326f7c..c11f1b9 100644 --- a/extern/angelscript_addons/scriptbuilder/scriptbuilder.h +++ b/extern/angelscript_addons/scriptbuilder/scriptbuilder.h @@ -14,6 +14,8 @@ // TODO: Implement flags for turning on/off include directives and conditional programming + + //--------------------------- // Declaration // @@ -23,9 +25,10 @@ #include #endif + #if defined(_MSC_VER) && _MSC_VER <= 1200 // disable the annoying warnings on MSVC 6 -#pragma warning(disable : 4786) +#pragma warning (disable:4786) #endif #include @@ -197,7 +200,7 @@ protected: { bool operator()(const std::string &a, const std::string &b) const { - return _strcmpi(a.c_str(), b.c_str()) < 0; + return _stricmp(a.c_str(), b.c_str()) < 0; } }; std::set includedScripts; diff --git a/extern/angelscript_addons/scriptdictionary/scriptdictionary.cpp b/extern/angelscript_addons/scriptdictionary/scriptdictionary.cpp new file mode 100644 index 0000000..2ae5305 --- /dev/null +++ b/extern/angelscript_addons/scriptdictionary/scriptdictionary.cpp @@ -0,0 +1,1299 @@ +#include +#include +#include "scriptdictionary.h" +#include "../scriptarray/scriptarray.h" + +BEGIN_AS_NAMESPACE + +using namespace std; + +//------------------------------------------------------------------------ +// Object types are cached as user data to avoid costly runtime lookups + +// We just define a number here that we assume nobody else is using for +// object type user data. The add-ons have reserved the numbers 1000 +// through 1999 for this purpose, so we should be fine. +const asPWORD DICTIONARY_CACHE = 1003; + +// This cache holds the object type of the dictionary type and array type +// so it isn't necessary to look this up each time the dictionary or array +// is created. +struct SDictionaryCache +{ + asITypeInfo *dictType; + asITypeInfo *arrayType; + asITypeInfo *keyType; + + // This is called from RegisterScriptDictionary + static void Setup(asIScriptEngine *engine) + { + SDictionaryCache *cache = reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + if( cache == 0 ) + { + cache = new SDictionaryCache; + engine->SetUserData(cache, DICTIONARY_CACHE); + engine->SetEngineUserDataCleanupCallback(SDictionaryCache::Cleanup, DICTIONARY_CACHE); + + cache->dictType = engine->GetTypeInfoByName("dictionary"); + cache->arrayType = engine->GetTypeInfoByDecl("array"); + cache->keyType = engine->GetTypeInfoByDecl("string"); + } + } + + // This is called from the engine when shutting down + static void Cleanup(asIScriptEngine *engine) + { + SDictionaryCache *cache = reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + if( cache ) + delete cache; + } +}; + +//-------------------------------------------------------------------------- +// CScriptDictionary implementation + +CScriptDictionary *CScriptDictionary::Create(asIScriptEngine *engine) +{ + // Use the custom memory routine from AngelScript to allow application to better control how much memory is used + CScriptDictionary *obj = (CScriptDictionary*)asAllocMem(sizeof(CScriptDictionary)); + new(obj) CScriptDictionary(engine); + return obj; +} + +CScriptDictionary *CScriptDictionary::Create(asBYTE *buffer) +{ + // Use the custom memory routine from AngelScript to allow application to better control how much memory is used + CScriptDictionary *obj = (CScriptDictionary*)asAllocMem(sizeof(CScriptDictionary)); + new(obj) CScriptDictionary(buffer); + return obj; +} + +CScriptDictionary::CScriptDictionary(asIScriptEngine *engine) +{ + Init(engine); +} + +void CScriptDictionary::Init(asIScriptEngine *e) +{ + // We start with one reference + refCount = 1; + gcFlag = false; + + // Keep a reference to the engine for as long as we live + // We don't increment the reference counter, because the + // engine will hold a pointer to the object in the GC. + engine = e; + + // The dictionary object type is cached to avoid dynamically parsing it each time + SDictionaryCache *cache = reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + + // Notify the garbage collector of this object + engine->NotifyGarbageCollectorOfNewObject(this, cache->dictType); +} + +CScriptDictionary::CScriptDictionary(asBYTE *buffer) +{ + // This constructor will always be called from a script + // so we can get the engine from the active context + asIScriptContext *ctx = asGetActiveContext(); + Init(ctx->GetEngine()); + + // Determine if the dictionary key type is registered as reference type or value type + SDictionaryCache& cache = *reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + bool keyAsRef = cache.keyType->GetFlags() & asOBJ_REF ? true : false; + + // Initialize the dictionary from the buffer + asUINT length = *(asUINT*)buffer; + buffer += 4; + + while( length-- ) + { + // Align the buffer pointer on a 4 byte boundary in + // case previous value was smaller than 4 bytes + if( asPWORD(buffer) & 0x3 ) + buffer += 4 - (asPWORD(buffer) & 0x3); + + // Get the name value pair from the buffer and insert it in the dictionary + dictKey_t name; + if (keyAsRef) + { + name = **(dictKey_t**)buffer; + buffer += sizeof(dictKey_t*); + } + else + { + name = *(dictKey_t*)buffer; + buffer += sizeof(dictKey_t); + } + + // Get the type id of the value + int typeId = *(int*)buffer; + buffer += sizeof(int); + + // Depending on the type id, the value will inline in the buffer or a pointer + void *ref = (void*)buffer; + + if( typeId >= asTYPEID_INT8 && typeId <= asTYPEID_DOUBLE ) + { + // Convert primitive values to either int64 or double, so we can use the overloaded Set methods + asINT64 i64; + double d; + switch( typeId ) + { + case asTYPEID_INT8: i64 = *(char*) ref; break; + case asTYPEID_INT16: i64 = *(short*) ref; break; + case asTYPEID_INT32: i64 = *(int*) ref; break; + case asTYPEID_INT64: i64 = *(asINT64*) ref; break; + case asTYPEID_UINT8: i64 = *(unsigned char*) ref; break; + case asTYPEID_UINT16: i64 = *(unsigned short*)ref; break; + case asTYPEID_UINT32: i64 = *(unsigned int*) ref; break; + case asTYPEID_UINT64: i64 = *(asINT64*) ref; break; + case asTYPEID_FLOAT: d = *(float*) ref; break; + case asTYPEID_DOUBLE: d = *(double*) ref; break; + } + + if( typeId >= asTYPEID_FLOAT ) + Set(name, d); + else + Set(name, i64); + } + else + { + if( (typeId & asTYPEID_MASK_OBJECT) && + !(typeId & asTYPEID_OBJHANDLE) && + (engine->GetTypeInfoById(typeId)->GetFlags() & asOBJ_REF) ) + { + // Dereference the pointer to get the reference to the actual object + ref = *(void**)ref; + } + + Set(name, ref, typeId); + } + + // Advance the buffer pointer with the size of the value + if( typeId & asTYPEID_MASK_OBJECT ) + { + asITypeInfo *ti = engine->GetTypeInfoById(typeId); + if( ti->GetFlags() & asOBJ_VALUE ) + buffer += ti->GetSize(); + else + buffer += sizeof(void*); + } + else if( typeId == 0 ) + { + // null pointer + buffer += sizeof(void*); + } + else + { + buffer += engine->GetSizeOfPrimitiveType(typeId); + } + } +} + +CScriptDictionary::~CScriptDictionary() +{ + // Delete all keys and values + DeleteAll(); +} + +void CScriptDictionary::AddRef() const +{ + // We need to clear the GC flag + gcFlag = false; + asAtomicInc(refCount); +} + +void CScriptDictionary::Release() const +{ + // We need to clear the GC flag + gcFlag = false; + if( asAtomicDec(refCount) == 0 ) + { + this->~CScriptDictionary(); + asFreeMem(const_cast(this)); + } +} + +int CScriptDictionary::GetRefCount() +{ + return refCount; +} + +void CScriptDictionary::SetGCFlag() +{ + gcFlag = true; +} + +bool CScriptDictionary::GetGCFlag() +{ + return gcFlag; +} + +void CScriptDictionary::EnumReferences(asIScriptEngine *inEngine) +{ + // TODO: If garbage collection can be done from a separate thread, then this method must be + // protected so that it doesn't get lost during the iteration if the dictionary is modified + + // Call the gc enum callback for each of the objects + dictMap_t::iterator it; + for( it = dict.begin(); it != dict.end(); it++ ) + { + if (it->second.m_typeId & asTYPEID_MASK_OBJECT) + { + asITypeInfo *subType = engine->GetTypeInfoById(it->second.m_typeId); + if ((subType->GetFlags() & asOBJ_VALUE) && (subType->GetFlags() & asOBJ_GC)) + { + // For value types we need to forward the enum callback + // to the object so it can decide what to do + engine->ForwardGCEnumReferences(it->second.m_valueObj, subType); + } + else + { + // For others, simply notify the GC about the reference + inEngine->GCEnumCallback(it->second.m_valueObj); + } + } + } +} + +void CScriptDictionary::ReleaseAllReferences(asIScriptEngine * /*engine*/) +{ + // We're being told to release all references in + // order to break circular references for dead objects + DeleteAll(); +} + +CScriptDictionary &CScriptDictionary::operator =(const CScriptDictionary &other) +{ + // Clear everything we had before + DeleteAll(); + + // Do a shallow copy of the dictionary + dictMap_t::const_iterator it; + for( it = other.dict.begin(); it != other.dict.end(); it++ ) + { + if( it->second.m_typeId & asTYPEID_OBJHANDLE ) + Set(it->first, (void*)&it->second.m_valueObj, it->second.m_typeId); + else if( it->second.m_typeId & asTYPEID_MASK_OBJECT ) + Set(it->first, (void*)it->second.m_valueObj, it->second.m_typeId); + else + Set(it->first, (void*)&it->second.m_valueInt, it->second.m_typeId); + } + + return *this; +} + +CScriptDictValue *CScriptDictionary::operator[](const dictKey_t &key) +{ + // Return the existing value if it exists, else insert an empty value + return &dict[key]; +} + +const CScriptDictValue *CScriptDictionary::operator[](const dictKey_t &key) const +{ + // Return the existing value if it exists + dictMap_t::const_iterator it; + it = dict.find(key); + if( it != dict.end() ) + return &it->second; + + // Else raise an exception + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Invalid access to non-existing value"); + + return 0; +} + +void CScriptDictionary::Set(const dictKey_t &key, void *value, int typeId) +{ + dictMap_t::iterator it; + it = dict.find(key); + if( it == dict.end() ) + it = dict.insert(dictMap_t::value_type(key, CScriptDictValue())).first; + + it->second.Set(engine, value, typeId); +} + +// This overloaded method is implemented so that all integer and +// unsigned integers types will be stored in the dictionary as int64 +// through implicit conversions. This simplifies the management of the +// numeric types when the script retrieves the stored value using a +// different type. +void CScriptDictionary::Set(const dictKey_t &key, const asINT64 &value) +{ + Set(key, const_cast(&value), asTYPEID_INT64); +} + +// This overloaded method is implemented so that all floating point types +// will be stored in the dictionary as double through implicit conversions. +// This simplifies the management of the numeric types when the script +// retrieves the stored value using a different type. +void CScriptDictionary::Set(const dictKey_t &key, const double &value) +{ + Set(key, const_cast(&value), asTYPEID_DOUBLE); +} + +// Returns true if the value was successfully retrieved +bool CScriptDictionary::Get(const dictKey_t &key, void *value, int typeId) const +{ + dictMap_t::const_iterator it; + it = dict.find(key); + if( it != dict.end() ) + return it->second.Get(engine, value, typeId); + + // AngelScript has already initialized the value with a default value, + // so we don't have to do anything if we don't find the element, or if + // the element is incompatible with the requested type. + + return false; +} + +// Returns the type id of the stored value +int CScriptDictionary::GetTypeId(const dictKey_t &key) const +{ + dictMap_t::const_iterator it; + it = dict.find(key); + if( it != dict.end() ) + return it->second.m_typeId; + + return -1; +} + +bool CScriptDictionary::Get(const dictKey_t &key, asINT64 &value) const +{ + return Get(key, &value, asTYPEID_INT64); +} + +bool CScriptDictionary::Get(const dictKey_t &key, double &value) const +{ + return Get(key, &value, asTYPEID_DOUBLE); +} + +bool CScriptDictionary::Exists(const dictKey_t &key) const +{ + dictMap_t::const_iterator it; + it = dict.find(key); + if( it != dict.end() ) + return true; + + return false; +} + +bool CScriptDictionary::IsEmpty() const +{ + if( dict.size() == 0 ) + return true; + + return false; +} + +asUINT CScriptDictionary::GetSize() const +{ + return asUINT(dict.size()); +} + +bool CScriptDictionary::Delete(const dictKey_t &key) +{ + dictMap_t::iterator it; + it = dict.find(key); + if( it != dict.end() ) + { + it->second.FreeValue(engine); + dict.erase(it); + return true; + } + + return false; +} + +void CScriptDictionary::DeleteAll() +{ + dictMap_t::iterator it; + for( it = dict.begin(); it != dict.end(); it++ ) + it->second.FreeValue(engine); + + dict.clear(); +} + +CScriptArray* CScriptDictionary::GetKeys() const +{ + // Retrieve the object type for the array from the cache + SDictionaryCache *cache = reinterpret_cast(engine->GetUserData(DICTIONARY_CACHE)); + asITypeInfo *ti = cache->arrayType; + + // Create the array object + CScriptArray *array = CScriptArray::Create(ti, asUINT(dict.size())); + long current = -1; + dictMap_t::const_iterator it; + for( it = dict.begin(); it != dict.end(); it++ ) + { + current++; + *(dictKey_t*)array->At(current) = it->first; + } + + return array; +} + +//-------------------------------------------------------------------------- +// Generic wrappers + +void ScriptDictionaryFactory_Generic(asIScriptGeneric *gen) +{ + *(CScriptDictionary**)gen->GetAddressOfReturnLocation() = CScriptDictionary::Create(gen->GetEngine()); +} + +void ScriptDictionaryListFactory_Generic(asIScriptGeneric *gen) +{ + asBYTE *buffer = (asBYTE*)gen->GetArgAddress(0); + *(CScriptDictionary**)gen->GetAddressOfReturnLocation() = CScriptDictionary::Create(buffer); +} + +void ScriptDictionaryAddRef_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dict->AddRef(); +} + +void ScriptDictionaryRelease_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dict->Release(); +} + +void ScriptDictionaryAssign_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + CScriptDictionary *other = *(CScriptDictionary**)gen->GetAddressOfArg(0); + *dict = *other; + *(CScriptDictionary**)gen->GetAddressOfReturnLocation() = dict; +} + +void ScriptDictionarySet_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + int typeId = gen->GetArgTypeId(1); + dict->Set(*key, ref, typeId); +} + +void ScriptDictionarySetInt_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + dict->Set(*key, *(asINT64*)ref); +} + +void ScriptDictionarySetFlt_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + dict->Set(*key, *(double*)ref); +} + +void ScriptDictionaryGet_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + int typeId = gen->GetArgTypeId(1); + *(bool*)gen->GetAddressOfReturnLocation() = dict->Get(*key, ref, typeId); +} + +void ScriptDictionaryGetInt_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + *(bool*)gen->GetAddressOfReturnLocation() = dict->Get(*key, *(asINT64*)ref); +} + +void ScriptDictionaryGetFlt_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + void *ref = *(void**)gen->GetAddressOfArg(1); + *(bool*)gen->GetAddressOfReturnLocation() = dict->Get(*key, *(double*)ref); +} + +void ScriptDictionaryExists_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + bool ret = dict->Exists(*key); + *(bool*)gen->GetAddressOfReturnLocation() = ret; +} + +void ScriptDictionaryIsEmpty_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + bool ret = dict->IsEmpty(); + *(bool*)gen->GetAddressOfReturnLocation() = ret; +} + +void ScriptDictionaryGetSize_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + asUINT ret = dict->GetSize(); + *(asUINT*)gen->GetAddressOfReturnLocation() = ret; +} + +void ScriptDictionaryDelete_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + *(bool*)gen->GetAddressOfReturnLocation() = dict->Delete(*key); +} + +void ScriptDictionaryDeleteAll_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject(); + dict->DeleteAll(); +} + +static void ScriptDictionaryGetRefCount_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + *(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount(); +} + +static void ScriptDictionarySetGCFlag_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + self->SetGCFlag(); +} + +static void ScriptDictionaryGetGCFlag_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + *(bool*)gen->GetAddressOfReturnLocation() = self->GetGCFlag(); +} + +static void ScriptDictionaryEnumReferences_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); + self->EnumReferences(engine); +} + +static void ScriptDictionaryReleaseAllReferences_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); + self->ReleaseAllReferences(engine); +} + +static void CScriptDictionaryGetKeys_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + *(CScriptArray**)gen->GetAddressOfReturnLocation() = self->GetKeys(); +} + +static void CScriptDictionary_opIndex_Generic(asIScriptGeneric *gen) +{ + CScriptDictionary *self = (CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = self->operator[](*key); +} + +static void CScriptDictionary_opIndex_const_Generic(asIScriptGeneric *gen) +{ + const CScriptDictionary *self = (const CScriptDictionary*)gen->GetObject(); + dictKey_t *key = *(dictKey_t**)gen->GetAddressOfArg(0); + *(const CScriptDictValue**)gen->GetAddressOfReturnLocation() = self->operator[](*key); +} + + +//------------------------------------------------------------------------- +// CScriptDictValue + +CScriptDictValue::CScriptDictValue() +{ + m_valueObj = 0; + m_typeId = 0; +} + +CScriptDictValue::CScriptDictValue(asIScriptEngine *engine, void *value, int typeId) +{ + m_valueObj = 0; + m_typeId = 0; + Set(engine, value, typeId); +} + +CScriptDictValue::~CScriptDictValue() +{ + if (m_valueObj && m_typeId) + { + asIScriptContext *ctx = asGetActiveContext(); + if (ctx) + FreeValue(ctx->GetEngine()); + else + { + // Must not hold an object when destroyed, as then the object will never be freed + assert((m_typeId & asTYPEID_MASK_OBJECT) == 0); + } + } +} + +void CScriptDictValue::FreeValue(asIScriptEngine *engine) +{ + // If it is a handle or a ref counted object, call release + if( m_typeId & asTYPEID_MASK_OBJECT ) + { + // Let the engine release the object + engine->ReleaseScriptObject(m_valueObj, engine->GetTypeInfoById(m_typeId)); + m_valueObj = 0; + m_typeId = 0; + } + + // For primitives, there's nothing to do +} + +void CScriptDictValue::EnumReferences(asIScriptEngine *inEngine) +{ + // If we're holding a reference, we'll notify the garbage collector of it + if (m_valueObj) + inEngine->GCEnumCallback(m_valueObj); + + // The object type itself is also garbage collected + if (m_typeId) + inEngine->GCEnumCallback(inEngine->GetTypeInfoById(m_typeId)); +} + +void CScriptDictValue::Set(asIScriptEngine *engine, void *value, int typeId) +{ + FreeValue(engine); + + m_typeId = typeId; + if( typeId & asTYPEID_OBJHANDLE ) + { + // We're receiving a reference to the handle, so we need to dereference it + m_valueObj = *(void**)value; + engine->AddRefScriptObject(m_valueObj, engine->GetTypeInfoById(typeId)); + } + else if( typeId & asTYPEID_MASK_OBJECT ) + { + // Create a copy of the object + m_valueObj = engine->CreateScriptObjectCopy(value, engine->GetTypeInfoById(typeId)); + if( m_valueObj == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Cannot create copy of object"); + } + } + else + { + // Copy the primitive value + // We receive a pointer to the value. + int size = engine->GetSizeOfPrimitiveType(typeId); + memcpy(&m_valueInt, value, size); + } +} + +void CScriptDictValue::Set(asIScriptEngine *engine, CScriptDictValue &value) +{ + if( value.m_typeId & asTYPEID_OBJHANDLE ) + Set(engine, (void*)&value.m_valueObj, value.m_typeId); + else if( value.m_typeId & asTYPEID_MASK_OBJECT ) + Set(engine, (void*)value.m_valueObj, value.m_typeId); + else + Set(engine, (void*)&value.m_valueInt, value.m_typeId); +} + +// This overloaded method is implemented so that all integer and +// unsigned integers types will be stored in the dictionary as int64 +// through implicit conversions. This simplifies the management of the +// numeric types when the script retrieves the stored value using a +// different type. +void CScriptDictValue::Set(asIScriptEngine *engine, const asINT64 &value) +{ + Set(engine, const_cast(&value), asTYPEID_INT64); +} + +// This overloaded method is implemented so that all floating point types +// will be stored in the dictionary as double through implicit conversions. +// This simplifies the management of the numeric types when the script +// retrieves the stored value using a different type. +void CScriptDictValue::Set(asIScriptEngine *engine, const double &value) +{ + Set(engine, const_cast(&value), asTYPEID_DOUBLE); +} + +bool CScriptDictValue::Get(asIScriptEngine *engine, void *value, int typeId) const +{ + // Return the value + if( typeId & asTYPEID_OBJHANDLE ) + { + // A handle can be retrieved if the stored type is a handle of same or compatible type + // or if the stored type is an object that implements the interface that the handle refer to. + if( (m_typeId & asTYPEID_MASK_OBJECT) ) + { + // Don't allow the get if the stored handle is to a const, but the desired handle is not + if( (m_typeId & asTYPEID_HANDLETOCONST) && !(typeId & asTYPEID_HANDLETOCONST) ) + return false; + + // RefCastObject will increment the refcount if successful + engine->RefCastObject(m_valueObj, engine->GetTypeInfoById(m_typeId), engine->GetTypeInfoById(typeId), reinterpret_cast(value)); + + return true; + } + } + else if( typeId & asTYPEID_MASK_OBJECT ) + { + // Verify that the copy can be made + bool isCompatible = false; + + // Allow a handle to be value assigned if the wanted type is not a handle + if( (m_typeId & ~(asTYPEID_OBJHANDLE | asTYPEID_HANDLETOCONST) ) == typeId && m_valueObj != 0 ) + isCompatible = true; + + // Copy the object into the given reference + if( isCompatible ) + { + engine->AssignScriptObject(value, m_valueObj, engine->GetTypeInfoById(typeId)); + + return true; + } + } + else + { + if( m_typeId == typeId ) + { + int size = engine->GetSizeOfPrimitiveType(typeId); + memcpy(value, &m_valueInt, size); + return true; + } + + // We know all numbers are stored as either int64 or double, since we register overloaded functions for those + // Only bool and enums needs to be treated separately + if( typeId == asTYPEID_DOUBLE ) + { + if( m_typeId == asTYPEID_INT64 ) + *(double*)value = double(m_valueInt); + else if (m_typeId == asTYPEID_BOOL) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + char localValue; + memcpy(&localValue, &m_valueInt, sizeof(char)); + *(double*)value = localValue ? 1.0 : 0.0; + } + else if (m_typeId > asTYPEID_DOUBLE && (m_typeId & asTYPEID_MASK_OBJECT) == 0) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + int localValue; + memcpy(&localValue, &m_valueInt, sizeof(int)); + *(double*)value = double(localValue); // enums are 32bit + } + else + { + // The stored type is an object + // TODO: Check if the object has a conversion operator to a primitive value + *(double*)value = 0; + return false; + } + return true; + } + else if( typeId == asTYPEID_INT64 ) + { + if( m_typeId == asTYPEID_DOUBLE ) + *(asINT64*)value = asINT64(m_valueFlt); + else if (m_typeId == asTYPEID_BOOL) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + char localValue; + memcpy(&localValue, &m_valueInt, sizeof(char)); + *(asINT64*)value = localValue ? 1 : 0; + } + else if (m_typeId > asTYPEID_DOUBLE && (m_typeId & asTYPEID_MASK_OBJECT) == 0) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + int localValue; + memcpy(&localValue, &m_valueInt, sizeof(int)); + *(asINT64*)value = localValue; // enums are 32bit + } + else + { + // The stored type is an object + // TODO: Check if the object has a conversion operator to a primitive value + *(asINT64*)value = 0; + return false; + } + return true; + } + else if( typeId > asTYPEID_DOUBLE && (m_typeId & asTYPEID_MASK_OBJECT) == 0 ) + { + // The desired type is an enum. These are always 32bit integers + if( m_typeId == asTYPEID_DOUBLE ) + *(int*)value = int(m_valueFlt); + else if( m_typeId == asTYPEID_INT64 ) + *(int*)value = int(m_valueInt); + else if (m_typeId == asTYPEID_BOOL) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + char localValue; + memcpy(&localValue, &m_valueInt, sizeof(char)); + *(int*)value = localValue ? 1 : 0; + } + else if (m_typeId > asTYPEID_DOUBLE && (m_typeId & asTYPEID_MASK_OBJECT) == 0) + { + // Use memcpy instead of type cast to make sure the code is endianess agnostic + int localValue; + memcpy(&localValue, &m_valueInt, sizeof(int)); + *(int*)value = localValue; // enums are 32bit + } + else + { + // The stored type is an object + // TODO: Check if the object has a conversion operator to a primitive value + *(int*)value = 0; + return false; + } + return true; + } + else if( typeId == asTYPEID_BOOL ) + { + if (m_typeId & asTYPEID_OBJHANDLE) + { + // TODO: Check if the object has a conversion operator to a primitive value + *(bool*)value = m_valueObj ? true : false; + } + else if( m_typeId & asTYPEID_MASK_OBJECT ) + { + // TODO: Check if the object has a conversion operator to a primitive value + *(bool*)value = true; + } + else + { + // Compare only the bytes that were actually set + asQWORD zero = 0; + int size = engine->GetSizeOfPrimitiveType(m_typeId); + *(bool*)value = memcmp(&m_valueInt, &zero, size) == 0 ? false : true; + } + return true; + } + } + + // It was not possible to retrieve the value using the desired typeId + return false; +} + +const void * CScriptDictValue::GetAddressOfValue() const +{ + if( (m_typeId & asTYPEID_MASK_OBJECT) && !(m_typeId & asTYPEID_OBJHANDLE) ) + { + // Return the address to the object directly + return m_valueObj; + } + + // Return the address of the primitive or the pointer to the object + return reinterpret_cast(&m_valueObj); +} + +bool CScriptDictValue::Get(asIScriptEngine *engine, asINT64 &value) const +{ + return Get(engine, &value, asTYPEID_INT64); +} + +bool CScriptDictValue::Get(asIScriptEngine *engine, double &value) const +{ + return Get(engine, &value, asTYPEID_DOUBLE); +} + +int CScriptDictValue::GetTypeId() const +{ + return m_typeId; +} + +static void CScriptDictValue_Construct(void *mem) +{ + new(mem) CScriptDictValue(); +} + +static void CScriptDictValue_Destruct(CScriptDictValue *obj) +{ + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + { + asIScriptEngine *engine = ctx->GetEngine(); + obj->FreeValue(engine); + } + obj->~CScriptDictValue(); +} + +static CScriptDictValue &CScriptDictValue_opAssign(void *ref, int typeId, CScriptDictValue *obj) +{ + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + { + asIScriptEngine *engine = ctx->GetEngine(); + obj->Set(engine, ref, typeId); + } + return *obj; +} + +static CScriptDictValue &CScriptDictValue_opAssign(const CScriptDictValue &other, CScriptDictValue *obj) +{ + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + { + asIScriptEngine *engine = ctx->GetEngine(); + obj->Set(engine, const_cast(other)); + } + + return *obj; +} + +static CScriptDictValue &CScriptDictValue_opAssign(double val, CScriptDictValue *obj) +{ + return CScriptDictValue_opAssign(&val, asTYPEID_DOUBLE, obj); +} + +static CScriptDictValue &CScriptDictValue_opAssign(asINT64 val, CScriptDictValue *obj) +{ + return CScriptDictValue_opAssign(&val, asTYPEID_INT64, obj); +} + +static void CScriptDictValue_opCast(void *ref, int typeId, CScriptDictValue *obj) +{ + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + { + asIScriptEngine *engine = ctx->GetEngine(); + obj->Get(engine, ref, typeId); + } +} + +static asINT64 CScriptDictValue_opConvInt(CScriptDictValue *obj) +{ + asINT64 value; + CScriptDictValue_opCast(&value, asTYPEID_INT64, obj); + return value; +} + +static double CScriptDictValue_opConvDouble(CScriptDictValue *obj) +{ + double value; + CScriptDictValue_opCast(&value, asTYPEID_DOUBLE, obj); + return value; +} + +//------------------------------------------------------------------- +// generic wrapper for CScriptDictValue + +static void CScriptDictValue_opConvDouble_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + double value; + self->Get(gen->GetEngine(), value); + *(double*)gen->GetAddressOfReturnLocation() = value; +} + +static void CScriptDictValue_opConvInt_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + asINT64 value; + self->Get(gen->GetEngine(), value); + *(asINT64*)gen->GetAddressOfReturnLocation() = value; +} + +static void CScriptDictValue_opCast_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + self->Get(gen->GetEngine(), gen->GetArgAddress(0), gen->GetArgTypeId(0)); +} + +static void CScriptDictValue_opAssign_int64_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = &CScriptDictValue_opAssign((asINT64)gen->GetArgQWord(0), self); +} + +static void CScriptDictValue_opAssign_double_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = &CScriptDictValue_opAssign(gen->GetArgDouble(0), self); +} + +static void CScriptDictValue_opAssign_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = &CScriptDictValue_opAssign(gen->GetArgAddress(0), gen->GetArgTypeId(0), self); +} + +static void CScriptDictValue_opCopyAssign_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + *(CScriptDictValue**)gen->GetAddressOfReturnLocation() = &CScriptDictValue_opAssign(*reinterpret_cast(gen->GetArgAddress(0)), self); +} + +static void CScriptDictValue_Construct_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + CScriptDictValue_Construct(self); +} + +static void CScriptDictValue_Destruct_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + CScriptDictValue_Destruct(self); +} + +static void CScriptDictValue_EnumReferences_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + self->EnumReferences(gen->GetEngine()); +} + +static void CScriptDictValue_FreeValue_Generic(asIScriptGeneric *gen) +{ + CScriptDictValue *self = (CScriptDictValue*)gen->GetObject(); + self->FreeValue(gen->GetEngine()); +} + +//-------------------------------------------------------------------------- +// Register the type + +void RegisterScriptDictionary(asIScriptEngine *engine) +{ + if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) + RegisterScriptDictionary_Generic(engine); + else + RegisterScriptDictionary_Native(engine); +} + +void RegisterScriptDictionary_Native(asIScriptEngine *engine) +{ + int r; + + // The array type must be available + assert( engine->GetTypeInfoByDecl("array") ); + +#if AS_CAN_USE_CPP11 + // With C++11 it is possible to use asGetTypeTraits to automatically determine the correct flags that represents the C++ class + r = engine->RegisterObjectType("dictionaryValue", sizeof(CScriptDictValue), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits()); assert( r >= 0 ); +#else + r = engine->RegisterObjectType("dictionaryValue", sizeof(CScriptDictValue), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CD); assert( r >= 0 ); +#endif + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(CScriptDictValue_Construct), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(CScriptDictValue_Destruct), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptDictValue, EnumReferences), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptDictValue, FreeValue), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(const dictionaryValue &in)", asFUNCTIONPR(CScriptDictValue_opAssign, (const CScriptDictValue &, CScriptDictValue *), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opHndlAssign(const ?&in)", asFUNCTIONPR(CScriptDictValue_opAssign, (void *, int, CScriptDictValue*), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opHndlAssign(const dictionaryValue &in)", asFUNCTIONPR(CScriptDictValue_opAssign, (const CScriptDictValue &, CScriptDictValue *), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(const ?&in)", asFUNCTIONPR(CScriptDictValue_opAssign, (void *, int, CScriptDictValue*), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(double)", asFUNCTIONPR(CScriptDictValue_opAssign, (double, CScriptDictValue*), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(int64)", asFUNCTIONPR(CScriptDictValue_opAssign, (asINT64, CScriptDictValue*), CScriptDictValue &), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "void opCast(?&out)", asFUNCTIONPR(CScriptDictValue_opCast, (void *, int, CScriptDictValue*), void), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "void opConv(?&out)", asFUNCTIONPR(CScriptDictValue_opCast, (void *, int, CScriptDictValue*), void), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "int64 opConv()", asFUNCTIONPR(CScriptDictValue_opConvInt, (CScriptDictValue*), asINT64), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "double opConv()", asFUNCTIONPR(CScriptDictValue_opConvDouble, (CScriptDictValue*), double), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + r = engine->RegisterObjectType("dictionary", sizeof(CScriptDictionary), asOBJ_REF | asOBJ_GC); assert( r >= 0 ); + // Use the generic interface to construct the object since we need the engine pointer, we could also have retrieved the engine pointer from the active context + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_FACTORY, "dictionary@ f()", asFUNCTION(ScriptDictionaryFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_LIST_FACTORY, "dictionary @f(int &in) {repeat {string, ?}}", asFUNCTION(ScriptDictionaryListFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptDictionary,AddRef), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptDictionary,Release), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "dictionary &opAssign(const dictionary &in)", asMETHODPR(CScriptDictionary, operator=, (const CScriptDictionary &), CScriptDictionary&), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const ?&in)", asMETHODPR(CScriptDictionary,Set,(const dictKey_t&,void*,int),void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, ?&out) const", asMETHODPR(CScriptDictionary,Get,(const dictKey_t&,void*,int) const,bool), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const int64&in)", asMETHODPR(CScriptDictionary,Set,(const dictKey_t&,const asINT64&),void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, int64&out) const", asMETHODPR(CScriptDictionary,Get,(const dictKey_t&,asINT64&) const,bool), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const double&in)", asMETHODPR(CScriptDictionary,Set,(const dictKey_t&,const double&),void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, double&out) const", asMETHODPR(CScriptDictionary,Get,(const dictKey_t&,double&) const,bool), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "bool exists(const string &in) const", asMETHOD(CScriptDictionary,Exists), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool isEmpty() const", asMETHOD(CScriptDictionary, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "uint getSize() const", asMETHOD(CScriptDictionary, GetSize), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool delete(const string &in)", asMETHOD(CScriptDictionary,Delete), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "void deleteAll()", asMETHOD(CScriptDictionary,DeleteAll), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "array @getKeys() const", asMETHOD(CScriptDictionary,GetKeys), asCALL_THISCALL); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "dictionaryValue &opIndex(const string &in)", asMETHODPR(CScriptDictionary, operator[], (const dictKey_t &), CScriptDictValue*), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "const dictionaryValue &opIndex(const string &in) const", asMETHODPR(CScriptDictionary, operator[], (const dictKey_t &) const, const CScriptDictValue*), asCALL_THISCALL); assert( r >= 0 ); + + // Register GC behaviours + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(CScriptDictionary,GetRefCount), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_SETGCFLAG, "void f()", asMETHOD(CScriptDictionary,SetGCFlag), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(CScriptDictionary,GetGCFlag), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptDictionary,EnumReferences), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptDictionary,ReleaseAllReferences), asCALL_THISCALL); assert( r >= 0 ); + +#if AS_USE_STLNAMES == 1 + // Same as isEmpty + r = engine->RegisterObjectMethod("dictionary", "bool empty() const", asMETHOD(CScriptDictionary, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); + // Same as getSize + r = engine->RegisterObjectMethod("dictionary", "uint size() const", asMETHOD(CScriptDictionary, GetSize), asCALL_THISCALL); assert( r >= 0 ); + // Same as delete + r = engine->RegisterObjectMethod("dictionary", "void erase(const string &in)", asMETHOD(CScriptDictionary,Delete), asCALL_THISCALL); assert( r >= 0 ); + // Same as deleteAll + r = engine->RegisterObjectMethod("dictionary", "void clear()", asMETHOD(CScriptDictionary,DeleteAll), asCALL_THISCALL); assert( r >= 0 ); +#endif + + // Cache some things the dictionary will need at runtime + SDictionaryCache::Setup(engine); +} + +void RegisterScriptDictionary_Generic(asIScriptEngine *engine) +{ + int r; + + // Register the cleanup callback for the object type cache + engine->SetEngineUserDataCleanupCallback(SDictionaryCache::Cleanup, DICTIONARY_CACHE); + +#if AS_CAN_USE_CPP11 + // With C++11 it is possible to use asGetTypeTraits to automatically determine the correct flags that represents the C++ class + r = engine->RegisterObjectType("dictionaryValue", sizeof(CScriptDictValue), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits()); assert( r >= 0 ); +#else + r = engine->RegisterObjectType("dictionaryValue", sizeof(CScriptDictValue), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CD); assert( r >= 0 ); +#endif + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(CScriptDictValue_Construct_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(CScriptDictValue_Destruct_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(CScriptDictValue_EnumReferences_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectBehaviour("dictionaryValue", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(CScriptDictValue_FreeValue_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(const dictionaryValue &in)", asFUNCTION(CScriptDictValue_opCopyAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opHndlAssign(const ?&in)", asFUNCTION(CScriptDictValue_opAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opHndlAssign(const dictionaryValue &in)", asFUNCTION(CScriptDictValue_opCopyAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(const ?&in)", asFUNCTION(CScriptDictValue_opAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(double)", asFUNCTION(CScriptDictValue_opAssign_double_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "dictionaryValue &opAssign(int64)", asFUNCTION(CScriptDictValue_opAssign_int64_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "void opCast(?&out)", asFUNCTION(CScriptDictValue_opCast_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "void opConv(?&out)", asFUNCTION(CScriptDictValue_opCast_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "int64 opConv()", asFUNCTION(CScriptDictValue_opConvInt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionaryValue", "double opConv()", asFUNCTION(CScriptDictValue_opConvDouble_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectType("dictionary", sizeof(CScriptDictionary), asOBJ_REF | asOBJ_GC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_FACTORY, "dictionary@ f()", asFUNCTION(ScriptDictionaryFactory_Generic), asCALL_GENERIC); assert( r>= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_LIST_FACTORY, "dictionary @f(int &in) {repeat {string, ?}}", asFUNCTION(ScriptDictionaryListFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptDictionaryAddRef_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptDictionaryRelease_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "dictionary &opAssign(const dictionary &in)", asFUNCTION(ScriptDictionaryAssign_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const ?&in)", asFUNCTION(ScriptDictionarySet_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, ?&out) const", asFUNCTION(ScriptDictionaryGet_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const int64&in)", asFUNCTION(ScriptDictionarySetInt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, int64&out) const", asFUNCTION(ScriptDictionaryGetInt_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, const double&in)", asFUNCTION(ScriptDictionarySetFlt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, double&out) const", asFUNCTION(ScriptDictionaryGetFlt_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "bool exists(const string &in) const", asFUNCTION(ScriptDictionaryExists_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool isEmpty() const", asFUNCTION(ScriptDictionaryIsEmpty_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "uint getSize() const", asFUNCTION(ScriptDictionaryGetSize_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "bool delete(const string &in)", asFUNCTION(ScriptDictionaryDelete_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "void deleteAll()", asFUNCTION(ScriptDictionaryDeleteAll_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "array @getKeys() const", asFUNCTION(CScriptDictionaryGetKeys_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("dictionary", "dictionaryValue &opIndex(const string &in)", asFUNCTION(CScriptDictionary_opIndex_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("dictionary", "const dictionaryValue &opIndex(const string &in) const", asFUNCTION(CScriptDictionary_opIndex_const_Generic), asCALL_GENERIC); assert( r >= 0 ); + + // Register GC behaviours + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptDictionaryGetRefCount_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptDictionarySetGCFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptDictionaryGetGCFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptDictionaryEnumReferences_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("dictionary", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptDictionaryReleaseAllReferences_Generic), asCALL_GENERIC); assert( r >= 0 ); + + // Cache some things the dictionary will need at runtime + SDictionaryCache::Setup(engine); +} + +//------------------------------------------------------------------ +// Iterator implementation + +CScriptDictionary::CIterator CScriptDictionary::begin() const +{ + return CIterator(*this, dict.begin()); +} + +CScriptDictionary::CIterator CScriptDictionary::end() const +{ + return CIterator(*this, dict.end()); +} + +CScriptDictionary::CIterator CScriptDictionary::find(const dictKey_t &key) const +{ + return CIterator(*this, dict.find(key)); +} + +CScriptDictionary::CIterator::CIterator( + const CScriptDictionary &dict, + dictMap_t::const_iterator it) + : m_it(it), m_dict(dict) +{} + +void CScriptDictionary::CIterator::operator++() +{ + ++m_it; +} + +void CScriptDictionary::CIterator::operator++(int) +{ + ++m_it; + + // Normally the post increment would return a copy of the object with the original state, + // but it is rarely used so we skip this extra copy to avoid unnecessary overhead +} + +CScriptDictionary::CIterator &CScriptDictionary::CIterator::operator*() +{ + return *this; +} + +bool CScriptDictionary::CIterator::operator==(const CIterator &other) const +{ + return m_it == other.m_it; +} + +bool CScriptDictionary::CIterator::operator!=(const CIterator &other) const +{ + return m_it != other.m_it; +} + +const dictKey_t &CScriptDictionary::CIterator::GetKey() const +{ + return m_it->first; +} + +int CScriptDictionary::CIterator::GetTypeId() const +{ + return m_it->second.m_typeId; +} + +bool CScriptDictionary::CIterator::GetValue(asINT64 &value) const +{ + return m_it->second.Get(m_dict.engine, &value, asTYPEID_INT64); +} + +bool CScriptDictionary::CIterator::GetValue(double &value) const +{ + return m_it->second.Get(m_dict.engine, &value, asTYPEID_DOUBLE); +} + +bool CScriptDictionary::CIterator::GetValue(void *value, int typeId) const +{ + return m_it->second.Get(m_dict.engine, value, typeId); +} + +const void *CScriptDictionary::CIterator::GetAddressOfValue() const +{ + return m_it->second.GetAddressOfValue(); +} + +END_AS_NAMESPACE + + diff --git a/extern/angelscript_addons/scriptdictionary/scriptdictionary.h b/extern/angelscript_addons/scriptdictionary/scriptdictionary.h new file mode 100644 index 0000000..062bb15 --- /dev/null +++ b/extern/angelscript_addons/scriptdictionary/scriptdictionary.h @@ -0,0 +1,240 @@ +#ifndef SCRIPTDICTIONARY_H +#define SCRIPTDICTIONARY_H + +// The dictionary class relies on the script string object, thus the script +// string type must be registered with the engine before registering the +// dictionary type + +#ifndef ANGELSCRIPT_H +// Avoid having to inform include path if header is already include before +#include +#endif + +// By default the CScriptDictionary use the std::string for the keys. +// If the application uses a custom string type, then this typedef +// can be changed accordingly. +#include +typedef std::string dictKey_t; + +// Forward declare CScriptDictValue so we can typedef the internal map type +BEGIN_AS_NAMESPACE +class CScriptDictValue; +END_AS_NAMESPACE + +// C++11 introduced the std::unordered_map which is a hash map which is +// is generally more performatic for lookups than the std::map which is a +// binary tree. +// TODO: memory: The map allocator should use the asAllocMem and asFreeMem +#if AS_CAN_USE_CPP11 +#include +typedef std::unordered_map dictMap_t; +#else +#include +typedef std::map dictMap_t; +#endif + + +#ifdef _MSC_VER +// Turn off annoying warnings about truncated symbol names +#pragma warning (disable:4786) +#endif + + + + +// Sometimes it may be desired to use the same method names as used by C++ STL. +// This may for example reduce time when converting code from script to C++ or +// back. +// +// 0 = off +// 1 = on + +#ifndef AS_USE_STLNAMES +#define AS_USE_STLNAMES 0 +#endif + + +BEGIN_AS_NAMESPACE + +class CScriptArray; +class CScriptDictionary; + +class CScriptDictValue +{ +public: + // This class must not be declared as local variable in C++, because it needs + // to receive the script engine pointer in all operations. The engine pointer + // is not kept as member in order to keep the size down + CScriptDictValue(); + CScriptDictValue(asIScriptEngine *engine, void *value, int typeId); + + // Destructor must not be called without first calling FreeValue, otherwise a memory leak will occur + ~CScriptDictValue(); + + // Replace the stored value + void Set(asIScriptEngine *engine, void *value, int typeId); + void Set(asIScriptEngine *engine, const asINT64 &value); + void Set(asIScriptEngine *engine, const double &value); + void Set(asIScriptEngine *engine, CScriptDictValue &value); + + // Gets the stored value. Returns false if the value isn't compatible with the informed typeId + bool Get(asIScriptEngine *engine, void *value, int typeId) const; + bool Get(asIScriptEngine *engine, asINT64 &value) const; + bool Get(asIScriptEngine *engine, double &value) const; + + // Returns the address of the stored value for inspection + const void *GetAddressOfValue() const; + + // Returns the type id of the stored value + int GetTypeId() const; + + // Free the stored value + void FreeValue(asIScriptEngine *engine); + + // GC callback + void EnumReferences(asIScriptEngine *engine); + +protected: + friend class CScriptDictionary; + + union + { + asINT64 m_valueInt; + double m_valueFlt; + void *m_valueObj; + }; + int m_typeId; +}; + +class CScriptDictionary +{ +public: + // Factory functions + static CScriptDictionary *Create(asIScriptEngine *engine); + + // Called from the script to instantiate a dictionary from an initialization list + static CScriptDictionary *Create(asBYTE *buffer); + + // Reference counting + void AddRef() const; + void Release() const; + + // Reassign the dictionary + CScriptDictionary &operator =(const CScriptDictionary &other); + + // Sets a key/value pair + void Set(const dictKey_t &key, void *value, int typeId); + void Set(const dictKey_t &key, const asINT64 &value); + void Set(const dictKey_t &key, const double &value); + + // Gets the stored value. Returns false if the value isn't compatible with the informed typeId + bool Get(const dictKey_t &key, void *value, int typeId) const; + bool Get(const dictKey_t &key, asINT64 &value) const; + bool Get(const dictKey_t &key, double &value) const; + + // Index accessors. If the dictionary is not const it inserts the value if it doesn't already exist + // If the dictionary is const then a script exception is set if it doesn't exist and a null pointer is returned + CScriptDictValue *operator[](const dictKey_t &key); + const CScriptDictValue *operator[](const dictKey_t &key) const; + + // Returns the type id of the stored value, or negative if it doesn't exist + int GetTypeId(const dictKey_t &key) const; + + // Returns true if the key is set + bool Exists(const dictKey_t &key) const; + + // Returns true if there are no key/value pairs in the dictionary + bool IsEmpty() const; + + // Returns the number of key/value pairs in the dictionary + asUINT GetSize() const; + + // Deletes the key + bool Delete(const dictKey_t &key); + + // Deletes all keys + void DeleteAll(); + + // Get an array of all keys + CScriptArray *GetKeys() const; + + // STL style iterator + class CIterator + { + public: + void operator++(); // Pre-increment + void operator++(int); // Post-increment + + // This is needed to support C++11 range-for + CIterator &operator*(); + + bool operator==(const CIterator &other) const; + bool operator!=(const CIterator &other) const; + + // Accessors + const dictKey_t &GetKey() const; + int GetTypeId() const; + bool GetValue(asINT64 &value) const; + bool GetValue(double &value) const; + bool GetValue(void *value, int typeId) const; + const void * GetAddressOfValue() const; + + protected: + friend class CScriptDictionary; + + CIterator(); + CIterator(const CScriptDictionary &dict, + dictMap_t::const_iterator it); + + CIterator &operator=(const CIterator &) {return *this;} // Not used + + dictMap_t::const_iterator m_it; + const CScriptDictionary &m_dict; + }; + + CIterator begin() const; + CIterator end() const; + CIterator find(const dictKey_t &key) const; + + // Garbage collections behaviours + int GetRefCount(); + void SetGCFlag(); + bool GetGCFlag(); + void EnumReferences(asIScriptEngine *engine); + void ReleaseAllReferences(asIScriptEngine *engine); + +protected: + // Since the dictionary uses the asAllocMem and asFreeMem functions to allocate memory + // the constructors are made protected so that the application cannot allocate it + // manually in a different way + CScriptDictionary(asIScriptEngine *engine); + CScriptDictionary(asBYTE *buffer); + + // We don't want anyone to call the destructor directly, it should be called through the Release method + virtual ~CScriptDictionary(); + + // Cache the object types needed + void Init(asIScriptEngine *engine); + + // Our properties + asIScriptEngine *engine; + mutable int refCount; + mutable bool gcFlag; + dictMap_t dict; +}; + +// This function will determine the configuration of the engine +// and use one of the two functions below to register the dictionary object +void RegisterScriptDictionary(asIScriptEngine *engine); + +// Call this function to register the math functions +// using native calling conventions +void RegisterScriptDictionary_Native(asIScriptEngine *engine); + +// Use this one instead if native calling conventions +// are not supported on the target platform +void RegisterScriptDictionary_Generic(asIScriptEngine *engine); + +END_AS_NAMESPACE + +#endif diff --git a/extern/angelscript_addons/scripthandle/scripthandle.cpp b/extern/angelscript_addons/scripthandle/scripthandle.cpp index f4de29a..df6cbbe 100644 --- a/extern/angelscript_addons/scripthandle/scripthandle.cpp +++ b/extern/angelscript_addons/scripthandle/scripthandle.cpp @@ -1,367 +1,360 @@ #include "scripthandle.h" -#include #include +#include #include BEGIN_AS_NAMESPACE -static void Construct(CScriptHandle* self) { new (self) CScriptHandle(); } -static void Construct(CScriptHandle* self, const CScriptHandle& o) { new (self) CScriptHandle(o); } +static void Construct(CScriptHandle *self) { new(self) CScriptHandle(); } +static void Construct(CScriptHandle *self, const CScriptHandle &o) { new(self) CScriptHandle(o); } // This one is not static because it needs to be friend with the CScriptHandle class -void Construct(CScriptHandle* self, void* ref, int typeId) { new (self) CScriptHandle(ref, typeId); } -static void Destruct(CScriptHandle* self) { self->~CScriptHandle(); } +void Construct(CScriptHandle *self, void *ref, int typeId) { new(self) CScriptHandle(ref, typeId); } +static void Destruct(CScriptHandle *self) { self->~CScriptHandle(); } -CScriptHandle::CScriptHandle() { - m_ref = 0; - m_type = 0; +CScriptHandle::CScriptHandle() +{ + m_ref = 0; + m_type = 0; } -CScriptHandle::CScriptHandle(const CScriptHandle& other) { - m_ref = other.m_ref; - m_type = other.m_type; +CScriptHandle::CScriptHandle(const CScriptHandle &other) +{ + m_ref = other.m_ref; + m_type = other.m_type; - AddRefHandle(); + AddRefHandle(); } -CScriptHandle::CScriptHandle(void* ref, asITypeInfo* type) { - m_ref = ref; - m_type = type; +CScriptHandle::CScriptHandle(void *ref, asITypeInfo *type) +{ + m_ref = ref; + m_type = type; - AddRefHandle(); + AddRefHandle(); } -// This constructor shouldn't be called from the application +// This constructor shouldn't be called from the application // directly as it requires an active script context -CScriptHandle::CScriptHandle(void* ref, int typeId) { - m_ref = 0; - m_type = 0; +CScriptHandle::CScriptHandle(void *ref, int typeId) +{ + m_ref = 0; + m_type = 0; - Assign(ref, typeId); + Assign(ref, typeId); } -CScriptHandle::~CScriptHandle() { ReleaseHandle(); } - -void CScriptHandle::ReleaseHandle() { - if (m_ref && m_type) { - asIScriptEngine* engine = m_type->GetEngine(); - engine->ReleaseScriptObject(m_ref, m_type); - - engine->Release(); - - m_ref = 0; - m_type = 0; - } +CScriptHandle::~CScriptHandle() +{ + ReleaseHandle(); } -void CScriptHandle::AddRefHandle() { - if (m_ref && m_type) { - asIScriptEngine* engine = m_type->GetEngine(); - engine->AddRefScriptObject(m_ref, m_type); +void CScriptHandle::ReleaseHandle() +{ + if( m_ref && m_type ) + { + asIScriptEngine *engine = m_type->GetEngine(); + engine->ReleaseScriptObject(m_ref, m_type); - // Hold on to the engine so it isn't destroyed while - // a reference to a script object is still held - engine->AddRef(); - } + engine->Release(); + + m_ref = 0; + m_type = 0; + } } -CScriptHandle& CScriptHandle::operator=(const CScriptHandle& other) { - Set(other.m_ref, other.m_type); +void CScriptHandle::AddRefHandle() +{ + if( m_ref && m_type ) + { + asIScriptEngine *engine = m_type->GetEngine(); + engine->AddRefScriptObject(m_ref, m_type); - return *this; + // Hold on to the engine so it isn't destroyed while + // a reference to a script object is still held + engine->AddRef(); + } } -void CScriptHandle::Set(void* ref, asITypeInfo* type) { - if (m_ref == ref) - return; +CScriptHandle &CScriptHandle::operator =(const CScriptHandle &other) +{ + Set(other.m_ref, other.m_type); - ReleaseHandle(); - - m_ref = ref; - m_type = type; - - AddRefHandle(); + return *this; } -void* CScriptHandle::GetRef() { return m_ref; } +void CScriptHandle::Set(void *ref, asITypeInfo *type) +{ + if( m_ref == ref ) return; -asITypeInfo* CScriptHandle::GetType() const { return m_type; } + ReleaseHandle(); -int CScriptHandle::GetTypeId() const { - if (m_type == 0) - return 0; + m_ref = ref; + m_type = type; - return m_type->GetTypeId() | asTYPEID_OBJHANDLE; + AddRefHandle(); } -// This method shouldn't be called from the application +void *CScriptHandle::GetRef() +{ + return m_ref; +} + +asITypeInfo *CScriptHandle::GetType() const +{ + return m_type; +} + +int CScriptHandle::GetTypeId() const +{ + if( m_type == 0 ) return 0; + + return m_type->GetTypeId() | asTYPEID_OBJHANDLE; +} + +// This method shouldn't be called from the application // directly as it requires an active script context -CScriptHandle& CScriptHandle::Assign(void* ref, int typeId) { - // When receiving a null handle we just clear our memory - if (typeId == 0) { - Set(0, 0); - return *this; - } +CScriptHandle &CScriptHandle::Assign(void *ref, int typeId) +{ + // When receiving a null handle we just clear our memory + if( typeId == 0 ) + { + Set(0, 0); + return *this; + } - // Dereference received handles to get the object - if (typeId & asTYPEID_OBJHANDLE) { - // Store the actual reference - ref = *(void**)ref; - typeId &= ~asTYPEID_OBJHANDLE; - } + // Dereference received handles to get the object + if( typeId & asTYPEID_OBJHANDLE ) + { + // Store the actual reference + ref = *(void**)ref; + typeId &= ~asTYPEID_OBJHANDLE; + } - // Get the object type - asIScriptContext* ctx = asGetActiveContext(); - asIScriptEngine* engine = ctx->GetEngine(); - asITypeInfo* type = engine->GetTypeInfoById(typeId); + // Get the object type + asIScriptContext *ctx = asGetActiveContext(); + asIScriptEngine *engine = ctx->GetEngine(); + asITypeInfo *type = engine->GetTypeInfoById(typeId); - // If the argument is another CScriptHandle, we should copy the content instead - if (type && strcmp(type->GetName(), "ref") == 0) { - CScriptHandle* r = (CScriptHandle*)ref; - ref = r->m_ref; - type = r->m_type; - } + // If the argument is another CScriptHandle, we should copy the content instead + if( type && strcmp(type->GetName(), "ref") == 0 ) + { + CScriptHandle *r = (CScriptHandle*)ref; + ref = r->m_ref; + type = r->m_type; + } - Set(ref, type); + Set(ref, type); - return *this; + return *this; } -bool CScriptHandle::operator==(const CScriptHandle& o) const { - if (m_ref == o.m_ref && m_type == o.m_type) - return true; +bool CScriptHandle::operator==(const CScriptHandle &o) const +{ + if( m_ref == o.m_ref && + m_type == o.m_type ) + return true; - // TODO: If type is not the same, we should attempt to do a dynamic cast, - // which may change the pointer for application registered classes + // TODO: If type is not the same, we should attempt to do a dynamic cast, + // which may change the pointer for application registered classes - return false; + return false; } -bool CScriptHandle::operator!=(const CScriptHandle& o) const { return !(*this == o); } +bool CScriptHandle::operator!=(const CScriptHandle &o) const +{ + return !(*this == o); +} -bool CScriptHandle::Equals(void* ref, int typeId) const { - // Null handles are received as reference to a null handle - if (typeId == 0) - ref = 0; +bool CScriptHandle::Equals(void *ref, int typeId) const +{ + // Null handles are received as reference to a null handle + if( typeId == 0 ) + ref = 0; - // Dereference handles to get the object - if (typeId & asTYPEID_OBJHANDLE) { - // Compare the actual reference - ref = *(void**)ref; - typeId &= ~asTYPEID_OBJHANDLE; - } + // Dereference handles to get the object + if( typeId & asTYPEID_OBJHANDLE ) + { + // Compare the actual reference + ref = *(void**)ref; + typeId &= ~asTYPEID_OBJHANDLE; + } - // TODO: If typeId is not the same, we should attempt to do a dynamic cast, - // which may change the pointer for application registered classes + // TODO: If typeId is not the same, we should attempt to do a dynamic cast, + // which may change the pointer for application registered classes - if (ref == m_ref) - return true; + if( ref == m_ref ) return true; - return false; + return false; } // AngelScript: used as '@obj = cast(ref);' -void CScriptHandle::Cast(void** outRef, int typeId) { - // If we hold a null handle, then just return null - if (m_type == 0) { - *outRef = 0; - return; - } +void CScriptHandle::Cast(void **outRef, int typeId) +{ + // If we hold a null handle, then just return null + if( m_type == 0 ) + { + *outRef = 0; + return; + } + + // It is expected that the outRef is always a handle + assert( typeId & asTYPEID_OBJHANDLE ); - // It is expected that the outRef is always a handle - assert(typeId & asTYPEID_OBJHANDLE); + // Compare the type id of the actual object + typeId &= ~asTYPEID_OBJHANDLE; + asIScriptEngine *engine = m_type->GetEngine(); + asITypeInfo *type = engine->GetTypeInfoById(typeId); - // Compare the type id of the actual object - typeId &= ~asTYPEID_OBJHANDLE; - asIScriptEngine* engine = m_type->GetEngine(); - asITypeInfo* type = engine->GetTypeInfoById(typeId); + *outRef = 0; - *outRef = 0; - - // RefCastObject will increment the refCount of the returned object if successful - engine->RefCastObject(m_ref, m_type, type, outRef); + // RefCastObject will increment the refCount of the returned object if successful + engine->RefCastObject(m_ref, m_type, type, outRef); } -void CScriptHandle::EnumReferences(asIScriptEngine* inEngine) { - // If we're holding a reference, we'll notify the garbage collector of it - if (m_ref) - inEngine->GCEnumCallback(m_ref); +void CScriptHandle::EnumReferences(asIScriptEngine *inEngine) +{ + // If we're holding a reference, we'll notify the garbage collector of it + if (m_ref) + inEngine->GCEnumCallback(m_ref); - // The object type itself is also garbage collected - if (m_type) - inEngine->GCEnumCallback(m_type); + // The object type itself is also garbage collected + if( m_type) + inEngine->GCEnumCallback(m_type); } -void CScriptHandle::ReleaseReferences(asIScriptEngine*) { - // Simply clear the content to release the references - Set(0, 0); +void CScriptHandle::ReleaseReferences(asIScriptEngine *inEngine) +{ + // Simply clear the content to release the references + Set(0, 0); } -void RegisterScriptHandle_Native(asIScriptEngine* engine) { - [[maybe_unused]] int r; +void RegisterScriptHandle_Native(asIScriptEngine *engine) +{ + int r; #if AS_CAN_USE_CPP11 - // With C++11 it is possible to use asGetTypeTraits to automatically determine the flags that represent the C++ - // class - r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), - asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits()); - assert(r >= 0); + // With C++11 it is possible to use asGetTypeTraits to automatically determine the flags that represent the C++ class + r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits()); assert( r >= 0 ); #else - r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), - asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); - assert(r >= 0); + r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); #endif - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", - asFUNCTIONPR(Construct, (CScriptHandle*), void), asCALL_CDECL_OBJFIRST); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", - asFUNCTIONPR(Construct, (CScriptHandle*, const CScriptHandle&), void), - asCALL_CDECL_OBJFIRST); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", - asFUNCTIONPR(Construct, (CScriptHandle*, void*, int), void), - asCALL_CDECL_OBJFIRST); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", - asFUNCTIONPR(Destruct, (CScriptHandle*), void), asCALL_CDECL_OBJFIRST); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", - asMETHOD(CScriptHandle, EnumReferences), asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", - asMETHOD(CScriptHandle, ReleaseReferences), asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asMETHODPR(CScriptHandle, Cast, (void**, int), void), - asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asMETHOD(CScriptHandle, operator=), - asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asMETHOD(CScriptHandle, Assign), - asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", - asMETHODPR(CScriptHandle, operator==,(const CScriptHandle&) const, bool), - asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", - asMETHODPR(CScriptHandle, Equals, (void*, int)const, bool), asCALL_THISCALL); - assert(r >= 0); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", asFUNCTIONPR(Construct, (CScriptHandle *), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", asFUNCTIONPR(Construct, (CScriptHandle *, const CScriptHandle &), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", asFUNCTIONPR(Construct, (CScriptHandle *, void *, int), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", asFUNCTIONPR(Destruct, (CScriptHandle *), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptHandle,EnumReferences), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptHandle, ReleaseReferences), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asMETHODPR(CScriptHandle, Cast, (void **, int), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asMETHOD(CScriptHandle, operator=), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asMETHOD(CScriptHandle, Assign), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", asMETHODPR(CScriptHandle, operator==, (const CScriptHandle &) const, bool), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", asMETHODPR(CScriptHandle, Equals, (void*, int) const, bool), asCALL_THISCALL); assert( r >= 0 ); } -void CScriptHandle_Construct_Generic(asIScriptGeneric* gen) { - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - new (self) CScriptHandle(); +void CScriptHandle_Construct_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + new(self) CScriptHandle(); } -void CScriptHandle_ConstructCopy_Generic(asIScriptGeneric* gen) { - CScriptHandle* other = reinterpret_cast(gen->GetArgAddress(0)); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - new (self) CScriptHandle(*other); +void CScriptHandle_ConstructCopy_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *other = reinterpret_cast(gen->GetArgAddress(0)); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + new(self) CScriptHandle(*other); } -void CScriptHandle_ConstructVar_Generic(asIScriptGeneric* gen) { - void* ref = gen->GetArgAddress(0); - int typeId = gen->GetArgTypeId(0); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - Construct(self, ref, typeId); +void CScriptHandle_ConstructVar_Generic(asIScriptGeneric *gen) +{ + void *ref = gen->GetArgAddress(0); + int typeId = gen->GetArgTypeId(0); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + Construct(self, ref, typeId); } -void CScriptHandle_Destruct_Generic(asIScriptGeneric* gen) { - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->~CScriptHandle(); +void CScriptHandle_Destruct_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->~CScriptHandle(); } -void CScriptHandle_Cast_Generic(asIScriptGeneric* gen) { - void** ref = reinterpret_cast(gen->GetArgAddress(0)); - int typeId = gen->GetArgTypeId(0); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->Cast(ref, typeId); +void CScriptHandle_Cast_Generic(asIScriptGeneric *gen) +{ + void **ref = reinterpret_cast(gen->GetArgAddress(0)); + int typeId = gen->GetArgTypeId(0); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->Cast(ref, typeId); } -void CScriptHandle_Assign_Generic(asIScriptGeneric* gen) { - CScriptHandle* other = reinterpret_cast(gen->GetArgAddress(0)); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - *self = *other; - gen->SetReturnAddress(self); +void CScriptHandle_Assign_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *other = reinterpret_cast(gen->GetArgAddress(0)); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + *self = *other; + gen->SetReturnAddress(self); } -void CScriptHandle_AssignVar_Generic(asIScriptGeneric* gen) { - void* ref = gen->GetArgAddress(0); - int typeId = gen->GetArgTypeId(0); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->Assign(ref, typeId); - gen->SetReturnAddress(self); +void CScriptHandle_AssignVar_Generic(asIScriptGeneric *gen) +{ + void *ref = gen->GetArgAddress(0); + int typeId = gen->GetArgTypeId(0); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->Assign(ref, typeId); + gen->SetReturnAddress(self); } -void CScriptHandle_Equals_Generic(asIScriptGeneric* gen) { - CScriptHandle* other = reinterpret_cast(gen->GetArgAddress(0)); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - gen->SetReturnByte(*self == *other); +void CScriptHandle_Equals_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *other = reinterpret_cast(gen->GetArgAddress(0)); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + gen->SetReturnByte(*self == *other); } -void CScriptHandle_EqualsVar_Generic(asIScriptGeneric* gen) { - void* ref = gen->GetArgAddress(0); - int typeId = gen->GetArgTypeId(0); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - gen->SetReturnByte(self->Equals(ref, typeId)); +void CScriptHandle_EqualsVar_Generic(asIScriptGeneric *gen) +{ + void *ref = gen->GetArgAddress(0); + int typeId = gen->GetArgTypeId(0); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + gen->SetReturnByte(self->Equals(ref, typeId)); } -void CScriptHandle_EnumReferences_Generic(asIScriptGeneric* gen) { - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->EnumReferences(gen->GetEngine()); +void CScriptHandle_EnumReferences_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->EnumReferences(gen->GetEngine()); } -void CScriptHandle_ReleaseReferences_Generic(asIScriptGeneric* gen) { - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->ReleaseReferences(gen->GetEngine()); +void CScriptHandle_ReleaseReferences_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->ReleaseReferences(gen->GetEngine()); } -void RegisterScriptHandle_Generic(asIScriptEngine* engine) { - [[maybe_unused]] int r; +void RegisterScriptHandle_Generic(asIScriptEngine *engine) +{ + int r; - r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), - asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", - asFUNCTION(CScriptHandle_Construct_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", - asFUNCTION(CScriptHandle_ConstructCopy_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", - asFUNCTION(CScriptHandle_ConstructVar_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", - asFUNCTION(CScriptHandle_Destruct_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", - asFUNCTION(CScriptHandle_EnumReferences_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", - asFUNCTION(CScriptHandle_ReleaseReferences_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asFUNCTION(CScriptHandle_Cast_Generic), - asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", - asFUNCTION(CScriptHandle_Assign_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", - asFUNCTION(CScriptHandle_AssignVar_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", - asFUNCTION(CScriptHandle_Equals_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", - asFUNCTION(CScriptHandle_EqualsVar_Generic), asCALL_GENERIC); - assert(r >= 0); + r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(CScriptHandle_Construct_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", asFUNCTION(CScriptHandle_ConstructCopy_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", asFUNCTION(CScriptHandle_ConstructVar_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(CScriptHandle_Destruct_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(CScriptHandle_EnumReferences_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(CScriptHandle_ReleaseReferences_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asFUNCTION(CScriptHandle_Cast_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asFUNCTION(CScriptHandle_Assign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asFUNCTION(CScriptHandle_AssignVar_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", asFUNCTION(CScriptHandle_Equals_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", asFUNCTION(CScriptHandle_EqualsVar_Generic), asCALL_GENERIC); assert( r >= 0 ); } -void RegisterScriptHandle(asIScriptEngine* engine) { - if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) - RegisterScriptHandle_Generic(engine); - else - RegisterScriptHandle_Native(engine); +void RegisterScriptHandle(asIScriptEngine *engine) +{ + if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) + RegisterScriptHandle_Generic(engine); + else + RegisterScriptHandle_Native(engine); } + END_AS_NAMESPACE diff --git a/extern/angelscript_addons/scripthelper/scripthelper.cpp b/extern/angelscript_addons/scripthelper/scripthelper.cpp index e70f075..4af4fde 100644 --- a/extern/angelscript_addons/scripthelper/scripthelper.cpp +++ b/extern/angelscript_addons/scripthelper/scripthelper.cpp @@ -975,8 +975,7 @@ string ScriptGetExceptionInfo() void RegisterExceptionRoutines(asIScriptEngine *engine) { - [[maybe_unused]] - int r; + int r; // The string type must be available assert(engine->GetTypeInfoByDecl("string")); diff --git a/extern/angelscript_addons/scriptstdstring/scriptstdstring.cpp b/extern/angelscript_addons/scriptstdstring/scriptstdstring.cpp index 2b1a175..2a96ad4 100644 --- a/extern/angelscript_addons/scriptstdstring/scriptstdstring.cpp +++ b/extern/angelscript_addons/scriptstdstring/scriptstdstring.cpp @@ -28,25 +28,26 @@ typedef map map_t; END_AS_NAMESPACE #endif +BEGIN_AS_NAMESPACE class CStdStringFactory : public asIStringFactory { public: - CStdStringFactory() = default; - ~CStdStringFactory() override + CStdStringFactory() {} + ~CStdStringFactory() { // The script engine must release each string // constant that it has requested - assert(stringCache.empty()); + assert(stringCache.size() == 0); } - const void *GetStringConstant(const char *data, asUINT length) override + const void *GetStringConstant(const char *data, asUINT length) { // The string factory might be modified from multiple // threads, so it is necessary to use a mutex. asAcquireExclusiveLock(); string str(data, length); - auto it = stringCache.find(str); + map_t::iterator it = stringCache.find(str); if (it != stringCache.end()) it->second++; else @@ -57,9 +58,9 @@ public: return reinterpret_cast(&it->first); } - int ReleaseStringConstant(const void *str) override + int ReleaseStringConstant(const void *str) { - if (str == nullptr) + if (str == 0) return asERROR; int ret = asSUCCESS; @@ -68,7 +69,7 @@ public: // threads, so it is necessary to use a mutex. asAcquireExclusiveLock(); - auto it = stringCache.find(*reinterpret_cast(str)); + map_t::iterator it = stringCache.find(*reinterpret_cast(str)); if (it == stringCache.end()) ret = asERROR; else @@ -83,9 +84,9 @@ public: return ret; } - int GetRawStringData(const void *str, char *data, asUINT *length) const override + int GetRawStringData(const void *str, char *data, asUINT *length) const { - if (str == nullptr) + if (str == 0) return asERROR; if (length) @@ -98,17 +99,17 @@ public: } // THe access to the string cache is protected with the common mutex provided by AngelScript - map_t stringCache = {}; + map_t stringCache; }; -static CStdStringFactory *stringFactory = nullptr; +static CStdStringFactory *stringFactory = 0; // TODO: Make this public so the application can also use the string // factory and share the string constants if so desired, or to // monitor the size of the string factory cache. CStdStringFactory *GetStdStringFactorySingleton() { - if( stringFactory == nullptr ) + if( stringFactory == 0 ) { // The following instance will be destroyed by the global // CStdStringFactoryCleaner instance upon application shutdown @@ -122,7 +123,7 @@ class CStdStringFactoryCleaner public: ~CStdStringFactoryCleaner() { - if (stringFactory != nullptr) + if (stringFactory) { // Only delete the string factory if the stringCache is empty // If it is not empty, it means that someone might still attempt @@ -133,13 +134,13 @@ public: if (stringFactory->stringCache.empty()) { delete stringFactory; - stringFactory = nullptr; + stringFactory = 0; } } } }; -static CStdStringFactoryCleaner cleaner = {}; +static CStdStringFactoryCleaner cleaner; static void ConstructString(string *thisPointer) @@ -461,12 +462,12 @@ static void StringResize(asUINT l, string &str) // string formatInt(int64 val, const string &in options, uint width) static string formatInt(asINT64 value, const string &options, asUINT width) { - bool leftJustify = options.find('l') != string::npos; - bool padWithZero = options.find('0') != string::npos; - bool alwaysSign = options.find('+') != string::npos; - bool spaceOnSign = options.find(' ') != string::npos; - bool hexSmall = options.find('h') != string::npos; - bool hexLarge = options.find('H') != string::npos; + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool hexSmall = options.find("h") != string::npos; + bool hexLarge = options.find("H") != string::npos; string fmt = "%"; if( leftJustify ) fmt += "-"; @@ -505,12 +506,12 @@ static string formatInt(asINT64 value, const string &options, asUINT width) // string formatUInt(uint64 val, const string &in options, uint width) static string formatUInt(asQWORD value, const string &options, asUINT width) { - bool leftJustify = options.find('l') != string::npos; - bool padWithZero = options.find('0') != string::npos; - bool alwaysSign = options.find('+') != string::npos; - bool spaceOnSign = options.find(' ') != string::npos; - bool hexSmall = options.find('h') != string::npos; - bool hexLarge = options.find('H') != string::npos; + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool hexSmall = options.find("h") != string::npos; + bool hexLarge = options.find("H") != string::npos; string fmt = "%"; if( leftJustify ) fmt += "-"; @@ -549,12 +550,12 @@ static string formatUInt(asQWORD value, const string &options, asUINT width) // string formatFloat(double val, const string &in options, uint width, uint precision) static string formatFloat(double value, const string &options, asUINT width, asUINT precision) { - bool leftJustify = options.find('l') != string::npos; - bool padWithZero = options.find('0') != string::npos; - bool alwaysSign = options.find('+') != string::npos; - bool spaceOnSign = options.find(' ') != string::npos; - bool expSmall = options.find('e') != string::npos; - bool expLarge = options.find('E') != string::npos; + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool expSmall = options.find("e") != string::npos; + bool expLarge = options.find("E") != string::npos; string fmt = "%"; if( leftJustify ) fmt += "-"; @@ -734,7 +735,7 @@ static string StringSubString(asUINT start, int count, const string &str) // makro, so this wrapper was introduced as work around. static bool StringEquals(const std::string& lhs, const std::string& rhs) { - return lhs == rhs; + return lhs == rhs; } void RegisterStdString_Native(asIScriptEngine *engine) diff --git a/extern/angelscript_addons/scriptstdstring/scriptstdstring_utils.cpp b/extern/angelscript_addons/scriptstdstring/scriptstdstring_utils.cpp index 9b11243..54662aa 100644 --- a/extern/angelscript_addons/scriptstdstring/scriptstdstring_utils.cpp +++ b/extern/angelscript_addons/scriptstdstring/scriptstdstring_utils.cpp @@ -112,8 +112,7 @@ static void StringJoin_Generic(asIScriptGeneric *gen) // The string type must have been registered first. void RegisterStdStringUtils(asIScriptEngine *engine) { - [[maybe_unused]] - int r; + int r; if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { diff --git a/src/ScriptResolving/AngelScript/AngelScriptResolver.cpp b/src/ScriptResolving/AngelScript/AngelScriptResolver.cpp index 7cf6ac6..c3400ff 100644 --- a/src/ScriptResolving/AngelScript/AngelScriptResolver.cpp +++ b/src/ScriptResolving/AngelScript/AngelScriptResolver.cpp @@ -1,6 +1,7 @@ #include "AngelScriptResolver.hpp" #include #include +#include "../../../extern/angelscript_addons/scriptdictionary/scriptdictionary.h" #include "../../../extern/angelscript_addons/scripthandle/scripthandle.h" #include "../../../extern/angelscript_addons/scripthelper/scripthelper.h" #include "../../../extern/angelscript_addons/scriptstdstring/scriptstdstring.h" @@ -35,7 +36,7 @@ static void TranslateException(asIScriptContext* ctx, void* /*userParam*/) { } catch (ArbUt::Exception& e) { // Tell the VM the type of exception that occurred ctx->SetException(e.what()); - }catch (std::exception& e) { + } catch (std::exception& e) { // Tell the VM the type of exception that occurred ctx->SetException(e.what()); } catch (...) { @@ -76,6 +77,7 @@ void AngelScriptResolver::Initialize(CreatureLib::Battling::BattleLibrary* arg, // Register Script Array type RegisterScriptArray(_engine, true); RegisterScriptHandle(_engine); + RegisterScriptDictionary(_engine); r = _engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(Print), asCALL_CDECL); if (r < 0) throw ArbUt::Exception("Registering print function failed.");