/xbmc/visualizations/Vortex/angelscript/add_on/scriptdictionary/scriptdictionary.cpp
http://github.com/xbmc/xbmc · C++ · 467 lines · 342 code · 75 blank · 50 comment · 39 complexity · 55e318b3c708a72c2655688f9e4308ce MD5 · raw file
- #include <assert.h>
- #include <string.h>
- #include "scriptdictionary.h"
- BEGIN_AS_NAMESPACE
- using namespace std;
- //--------------------------------------------------------------------------
- // CScriptDictionary implementation
- CScriptDictionary::CScriptDictionary(asIScriptEngine *engine)
- {
- // We start with one reference
- refCount = 1;
- // 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.
- this->engine = engine;
- // Notify the garbage collector of this object
- // TODO: The type id should be cached
- engine->NotifyGarbageCollectorOfNewObject(this, engine->GetTypeIdByDecl("dictionary"));
- }
- CScriptDictionary::~CScriptDictionary()
- {
- // Delete all keys and values
- DeleteAll();
- }
- void CScriptDictionary::AddRef()
- {
- // We need to clear the GC flag
- refCount = (refCount & 0x7FFFFFFF) + 1;
- }
- void CScriptDictionary::Release()
- {
- // We need to clear the GC flag
- refCount = (refCount & 0x7FFFFFFF) - 1;
- if( refCount == 0 )
- delete this;
- }
- int CScriptDictionary::GetRefCount()
- {
- return refCount & 0x7FFFFFFF;
- }
- void CScriptDictionary::SetGCFlag()
- {
- refCount |= 0x80000000;
- }
- bool CScriptDictionary::GetGCFlag()
- {
- return (refCount & 0x80000000) ? true : false;
- }
- void CScriptDictionary::EnumReferences(asIScriptEngine *engine)
- {
- // Call the gc enum callback for each of the objects
- map<string, valueStruct>::iterator it;
- for( it = dict.begin(); it != dict.end(); it++ )
- {
- if( it->second.typeId & asTYPEID_MASK_OBJECT )
- engine->GCEnumCallback(it->second.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*/)
- {
- // Do nothing
- // TODO: Should do a shallow copy of the dictionary
- return *this;
- }
- void CScriptDictionary::Set(const string &key, void *value, int typeId)
- {
- valueStruct valStruct = {{0},0};
- valStruct.typeId = typeId;
- if( typeId & asTYPEID_OBJHANDLE )
- {
- // We're receiving a reference to the handle, so we need to dereference it
- valStruct.valueObj = *(void**)value;
- engine->AddRefScriptObject(valStruct.valueObj, typeId);
- }
- else if( typeId & asTYPEID_MASK_OBJECT )
- {
- // Create a copy of the object
- valStruct.valueObj = engine->CreateScriptObjectCopy(value, typeId);
- }
- else
- {
- // Copy the primitive value
- // We receive a pointer to the value.
- int size = engine->GetSizeOfPrimitiveType(typeId);
- memcpy(&valStruct.valueInt, value, size);
- }
- map<string, valueStruct>::iterator it;
- it = dict.find(key);
- if( it != dict.end() )
- {
- FreeValue(it->second);
- // Insert the new value
- it->second = valStruct;
- }
- else
- {
- dict.insert(map<string, valueStruct>::value_type(key, valStruct));
- }
- }
- // 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 string &key, asINT64 &value)
- {
- Set(key, &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 string &key, double &value)
- {
- Set(key, &value, asTYPEID_DOUBLE);
- }
- // Returns true if the value was successfully retrieved
- bool CScriptDictionary::Get(const string &key, void *value, int typeId) const
- {
- map<string, valueStruct>::const_iterator it;
- it = dict.find(key);
- if( it != dict.end() )
- {
- // 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( (it->second.typeId & asTYPEID_MASK_OBJECT) &&
- engine->IsHandleCompatibleWithObject(it->second.valueObj, it->second.typeId, typeId) )
- {
- engine->AddRefScriptObject(it->second.valueObj, it->second.typeId);
- *(void**)value = it->second.valueObj;
- return true;
- }
- }
- else if( typeId & asTYPEID_MASK_OBJECT )
- {
- // Verify that the copy can be made
- bool isCompatible = false;
- if( it->second.typeId == typeId )
- isCompatible = true;
- // Copy the object into the given reference
- if( isCompatible )
- {
- engine->CopyScriptObject(value, it->second.valueObj, typeId);
- return true;
- }
- }
- else
- {
- if( it->second.typeId == typeId )
- {
- int size = engine->GetSizeOfPrimitiveType(typeId);
- memcpy(value, &it->second.valueInt, size);
- return true;
- }
- // We know all numbers are stored as either int64 or double, since we register overloaded functions for those
- if( it->second.typeId == asTYPEID_INT64 && typeId == asTYPEID_DOUBLE )
- {
- *(double*)value = double(it->second.valueInt);
- return true;
- }
- else if( it->second.typeId == asTYPEID_DOUBLE && typeId == asTYPEID_INT64 )
- {
- *(asINT64*)value = asINT64(it->second.valueFlt);
- return true;
- }
- }
- }
- // 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;
- }
- bool CScriptDictionary::Get(const string &key, asINT64 &value) const
- {
- return Get(key, &value, asTYPEID_INT64);
- }
- bool CScriptDictionary::Get(const string &key, double &value) const
- {
- return Get(key, &value, asTYPEID_DOUBLE);
- }
- bool CScriptDictionary::Exists(const string &key) const
- {
- map<string, valueStruct>::const_iterator it;
- it = dict.find(key);
- if( it != dict.end() )
- {
- return true;
- }
- return false;
- }
- void CScriptDictionary::Delete(const string &key)
- {
- map<string, valueStruct>::iterator it;
- it = dict.find(key);
- if( it != dict.end() )
- {
- FreeValue(it->second);
- dict.erase(it);
- }
- }
- void CScriptDictionary::DeleteAll()
- {
- map<string, valueStruct>::iterator it;
- for( it = dict.begin(); it != dict.end(); it++ )
- {
- FreeValue(it->second);
- }
- dict.clear();
- }
- void CScriptDictionary::FreeValue(valueStruct &value)
- {
- // If it is a handle or a ref counted object, call release
- if( value.typeId & asTYPEID_MASK_OBJECT )
- {
- // Let the engine release the object
- engine->ReleaseScriptObject(value.valueObj, value.typeId);
- value.valueObj = 0;
- value.typeId = 0;
- }
- // For primitives, there's nothing to do
- }
- //--------------------------------------------------------------------------
- // Generic wrappers
- void ScriptDictionaryFactory_Generic(asIScriptGeneric *gen)
- {
- *(CScriptDictionary**)gen->GetAddressOfReturnLocation() = new CScriptDictionary(gen->GetEngine());
- }
- 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 ScriptDictionarySet_Generic(asIScriptGeneric *gen)
- {
- CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject();
- string *key = *(string**)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();
- string *key = *(string**)gen->GetAddressOfArg(0);
- void *ref = *(void**)gen->GetAddressOfArg(1);
- dict->Set(*key, *(asINT64*)ref);
- }
- void ScriptDictionarySetFlt_Generic(asIScriptGeneric *gen)
- {
- CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject();
- string *key = *(string**)gen->GetAddressOfArg(0);
- void *ref = *(void**)gen->GetAddressOfArg(1);
- dict->Set(*key, *(double*)ref);
- }
- void ScriptDictionaryGet_Generic(asIScriptGeneric *gen)
- {
- CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject();
- string *key = *(string**)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();
- string *key = *(string**)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();
- string *key = *(string**)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();
- string *key = *(string**)gen->GetAddressOfArg(0);
- bool ret = dict->Exists(*key);
- *(bool*)gen->GetAddressOfReturnLocation() = ret;
- }
- void ScriptDictionaryDelete_Generic(asIScriptGeneric *gen)
- {
- CScriptDictionary *dict = (CScriptDictionary*)gen->GetObject();
- string *key = *(string**)gen->GetAddressOfArg(0);
- 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);
- }
- //--------------------------------------------------------------------------
- // 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;
- 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_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", "void set(const string &in, ?&in)", asMETHODPR(CScriptDictionary,Set,(const string&,void*,int),void), asCALL_THISCALL); assert( r >= 0 );
- r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, ?&out) const", asMETHODPR(CScriptDictionary,Get,(const string&,void*,int) const,bool), asCALL_THISCALL); assert( r >= 0 );
- r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, int64&in)", asMETHODPR(CScriptDictionary,Set,(const string&,asINT64&),void), asCALL_THISCALL); assert( r >= 0 );
- r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, int64&out) const", asMETHODPR(CScriptDictionary,Get,(const string&,asINT64&) const,bool), asCALL_THISCALL); assert( r >= 0 );
- r = engine->RegisterObjectMethod("dictionary", "void set(const string &in, double&in)", asMETHODPR(CScriptDictionary,Set,(const string&,double&),void), asCALL_THISCALL); assert( r >= 0 );
- r = engine->RegisterObjectMethod("dictionary", "bool get(const string &in, double&out) const", asMETHODPR(CScriptDictionary,Get,(const string&,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", "void 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 );
- // 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 );
- }
- void RegisterScriptDictionary_Generic(asIScriptEngine *engine)
- {
- int r;
- 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_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", "void set(const string &in, ?&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, 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, 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", "void 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 );
- // 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 );
- }
- END_AS_NAMESPACE