Update some AS stuff

This commit is contained in:
Aang23 2025-08-12 19:30:15 +02:00
parent 4f600e3d6f
commit 26d514baea
8 changed files with 598 additions and 112 deletions

View file

@ -78,6 +78,7 @@ void CScriptDictionary::Init(asIScriptEngine *e)
// We start with one reference
refCount = 1;
gcFlag = false;
iterGuard = 0;
// Keep a reference to the engine for as long as we live
// We don't increment the reference counter, because the
@ -310,8 +311,11 @@ void CScriptDictionary::Set(const dictKey_t &key, void *value, int typeId)
{
dictMap_t::iterator it;
it = dict.find(key);
if( it == dict.end() )
if (it == dict.end())
{
it = dict.insert(dictMap_t::value_type(key, CScriptDictValue())).first;
iterGuard++;
}
it->second.Set(engine, value, typeId);
}
@ -402,6 +406,7 @@ bool CScriptDictionary::Delete(const dictKey_t &key)
{
it->second.FreeValue(engine);
dict.erase(it);
iterGuard++;
return true;
}
@ -415,6 +420,7 @@ void CScriptDictionary::DeleteAll()
it->second.FreeValue(engine);
dict.clear();
iterGuard++;
}
CScriptArray* CScriptDictionary::GetKeys() const
@ -1055,6 +1061,192 @@ static void CScriptDictValue_FreeValue_Generic(asIScriptGeneric *gen)
self->FreeValue(gen->GetEngine());
}
//----------------------------------------------------------------------------
// Foreach support
CScriptDictionary::CScriptDictIter::CScriptDictIter(const CScriptDictionary* dict) : iter(dict->begin()), refCount(1), iterGuard(dict->iterGuard) {}
CScriptDictionary::CScriptDictIter::~CScriptDictIter() {}
void CScriptDictionary::CScriptDictIter::AddRef() const
{
asAtomicInc(refCount);
}
void CScriptDictionary::CScriptDictIter::Release() const
{
if (asAtomicDec(refCount) == 0)
{
this->~CScriptDictIter();
asFreeMem(const_cast<CScriptDictIter*>(this));
}
}
CScriptDictionary::CScriptDictIter* CScriptDictionary::opForBegin() const
{
// Use the custom memory routine from AngelScript to allow application to better control how much memory is used
CScriptDictionary::CScriptDictIter* iter = (CScriptDictionary::CScriptDictIter*)asAllocMem(sizeof(CScriptDictionary::CScriptDictIter));
new(iter) CScriptDictionary::CScriptDictIter(this);
return iter;
}
bool CScriptDictionary::opForEnd(const CScriptDictionary::CScriptDictIter& iter) const
{
if (iter.iterGuard != iterGuard)
return true;
if (iter.iter == end())
return true;
return false;
}
CScriptDictionary::CScriptDictIter* CScriptDictionary::opForNext(CScriptDictionary::CScriptDictIter& iter) const
{
if (iter.iterGuard != iterGuard)
iter.iter = end();
else
++iter.iter;
return &iter;
}
const CScriptDictValue& CScriptDictionary::opForValue0(const CScriptDictionary::CScriptDictIter& iter) const
{
return iter.iter.m_it->second;
}
const dictKey_t& CScriptDictionary::opForValue1(const CScriptDictionary::CScriptDictIter& iter) const
{
return iter.iter.m_it->first;
}
void ScriptDictIterAddRef_Generic(asIScriptGeneric* gen)
{
CScriptDictionary::CScriptDictIter* iter = (CScriptDictionary::CScriptDictIter*)gen->GetObject();
iter->AddRef();
}
void ScriptDictIterRelease_Generic(asIScriptGeneric* gen)
{
CScriptDictionary::CScriptDictIter* iter = (CScriptDictionary::CScriptDictIter*)gen->GetObject();
iter->Release();
}
void ScriptDictionary_opForBegin_Generic(asIScriptGeneric* gen)
{
CScriptDictionary* dict = (CScriptDictionary*)gen->GetObject();
*(CScriptDictionary::CScriptDictIter**)gen->GetAddressOfReturnLocation() = dict->opForBegin();
}
void ScriptDictionary_opForEnd_Generic(asIScriptGeneric* gen)
{
CScriptDictionary* dict = (CScriptDictionary*)gen->GetObject();
CScriptDictionary::CScriptDictIter* iter = *(CScriptDictionary::CScriptDictIter**)gen->GetAddressOfArg(0);
*(bool*)gen->GetAddressOfReturnLocation() = dict->opForEnd(*iter);
}
void ScriptDictionary_opForNext_Generic(asIScriptGeneric* gen)
{
CScriptDictionary* dict = (CScriptDictionary*)gen->GetObject();
CScriptDictionary::CScriptDictIter* iter = *(CScriptDictionary::CScriptDictIter**)gen->GetAddressOfArg(0);
*(CScriptDictionary::CScriptDictIter**)gen->GetAddressOfReturnLocation() = dict->opForNext(*iter);
}
void ScriptDictionary_opForValue0_Generic(asIScriptGeneric* gen)
{
CScriptDictionary* dict = (CScriptDictionary*)gen->GetObject();
CScriptDictionary::CScriptDictIter* iter = *(CScriptDictionary::CScriptDictIter**)gen->GetAddressOfArg(0);
*reinterpret_cast<const CScriptDictValue**>(gen->GetAddressOfReturnLocation()) = &dict->opForValue0(*iter);
}
void ScriptDictionary_opForValue1_Generic(asIScriptGeneric* gen)
{
CScriptDictionary* dict = (CScriptDictionary*)gen->GetObject();
CScriptDictionary::CScriptDictIter* iter = *(CScriptDictionary::CScriptDictIter**)gen->GetAddressOfArg(0);
*reinterpret_cast<const dictKey_t**>(gen->GetAddressOfReturnLocation()) = &dict->opForValue1(*iter);
}
//------------------------------------------------------------------
// 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();
}
//--------------------------------------------------------------------------
// Register the type
@ -1130,6 +1322,19 @@ void RegisterScriptDictionary_Native(asIScriptEngine *engine)
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 );
// Support foreach
r = engine->RegisterObjectType("dictionaryIter", 0, asOBJ_REF); assert(r >= 0);
r = engine->RegisterObjectBehaviour("dictionaryIter", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptDictionary::CScriptDictIter, AddRef), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectBehaviour("dictionaryIter", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptDictionary::CScriptDictIter, Release), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "dictionaryIter @opForBegin() const", asMETHODPR(CScriptDictionary, opForBegin, () const, CScriptDictionary::CScriptDictIter *), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "bool opForEnd(dictionaryIter @+) const", asMETHODPR(CScriptDictionary, opForEnd, (const CScriptDictionary::CScriptDictIter&) const, bool), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "dictionaryIter @+ opForNext(dictionaryIter @+) const", asMETHODPR(CScriptDictionary, opForNext, (CScriptDictionary::CScriptDictIter&) const, CScriptDictionary::CScriptDictIter*), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "const dictionaryValue &opForValue0(dictionaryIter @+) const", asMETHODPR(CScriptDictionary, opForValue0, (const CScriptDictionary::CScriptDictIter&) const, const CScriptDictValue &), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "const string &opForValue1(dictionaryIter @+) const", asMETHODPR(CScriptDictionary, opForValue1, (const CScriptDictionary::CScriptDictIter&) const, const dictKey_t&), 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 );
@ -1208,92 +1413,21 @@ void RegisterScriptDictionary_Generic(asIScriptEngine *engine)
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 );
// Support foreach
r = engine->RegisterObjectType("dictionaryIter", 0, asOBJ_REF); assert(r >= 0);
r = engine->RegisterObjectBehaviour("dictionaryIter", asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptDictIterAddRef_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectBehaviour("dictionaryIter", asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptDictIterRelease_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "dictionaryIter @opForBegin() const", asFUNCTION(ScriptDictionary_opForBegin_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "bool opForEnd(dictionaryIter @+) const", asFUNCTION(ScriptDictionary_opForEnd_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "dictionaryIter @+ opForNext(dictionaryIter @+) const", asFUNCTION(ScriptDictionary_opForNext_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "const dictionaryValue &opForValue0(dictionaryIter @+) const", asFUNCTION(ScriptDictionary_opForValue0_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("dictionary", "const string &opForValue1(dictionaryIter @+) const", asFUNCTION(ScriptDictionary_opForValue1_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