mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 06:42:12 +00:00
Map<K,V> and MapIterator<K,V> for ZScript
This commit is contained in:
parent
1e5e65546d
commit
8b6a714d41
23 changed files with 2355 additions and 29 deletions
|
@ -1153,6 +1153,7 @@ set (PCH_SOURCES
|
||||||
common/rendering/gl/gl_samplers.cpp
|
common/rendering/gl/gl_samplers.cpp
|
||||||
common/rendering/gl/gl_shader.cpp
|
common/rendering/gl/gl_shader.cpp
|
||||||
common/rendering/gl/gl_shaderprogram.cpp
|
common/rendering/gl/gl_shaderprogram.cpp
|
||||||
|
common/scripting/core/maps.cpp
|
||||||
common/scripting/core/dictionary.cpp
|
common/scripting/core/dictionary.cpp
|
||||||
common/scripting/core/dynarrays.cpp
|
common/scripting/core/dynarrays.cpp
|
||||||
common/scripting/core/symbols.cpp
|
common/scripting/core/symbols.cpp
|
||||||
|
|
|
@ -117,6 +117,7 @@ xx(Double)
|
||||||
xx(String)
|
xx(String)
|
||||||
xx(Vector)
|
xx(Vector)
|
||||||
xx(Map)
|
xx(Map)
|
||||||
|
xx(MapIterator)
|
||||||
xx(Array)
|
xx(Array)
|
||||||
xx(Include)
|
xx(Include)
|
||||||
xx(Sound)
|
xx(Sound)
|
||||||
|
@ -162,6 +163,14 @@ xx(ToVector)
|
||||||
xx(Size)
|
xx(Size)
|
||||||
xx(Push)
|
xx(Push)
|
||||||
xx(Insert)
|
xx(Insert)
|
||||||
|
xx(InsertNew)
|
||||||
|
xx(Remove)
|
||||||
|
xx(Get)
|
||||||
|
xx(GetValue)
|
||||||
|
xx(GetKey)
|
||||||
|
xx(SetValue)
|
||||||
|
xx(CheckKey)
|
||||||
|
xx(Value)
|
||||||
xx(Copy)
|
xx(Copy)
|
||||||
xx(Move)
|
xx(Move)
|
||||||
xx(Voidptr)
|
xx(Voidptr)
|
||||||
|
|
|
@ -88,7 +88,7 @@ int Printf (const char *format, ...) ATTRIBUTE((format(printf,1,2)));
|
||||||
int DPrintf (int level, const char *format, ...) ATTRIBUTE((format(printf,2,3)));
|
int DPrintf (int level, const char *format, ...) ATTRIBUTE((format(printf,2,3)));
|
||||||
|
|
||||||
void I_DebugPrint(const char* cp);
|
void I_DebugPrint(const char* cp);
|
||||||
void debugprintf(const char* f, ...); // Prints to the debugger's log.
|
void I_DebugPrintf(const char* fmt, ...); // Prints to the debugger's log.
|
||||||
|
|
||||||
// flag to silence non-error output
|
// flag to silence non-error output
|
||||||
extern bool batchrun;
|
extern bool batchrun;
|
||||||
|
|
|
@ -167,6 +167,7 @@ std2:
|
||||||
'vector2' { RET(TK_Vector2); }
|
'vector2' { RET(TK_Vector2); }
|
||||||
'vector3' { RET(TK_Vector3); }
|
'vector3' { RET(TK_Vector3); }
|
||||||
'map' { RET(TK_Map); }
|
'map' { RET(TK_Map); }
|
||||||
|
'mapiterator' { RET(TK_MapIterator); }
|
||||||
'array' { RET(TK_Array); }
|
'array' { RET(TK_Array); }
|
||||||
'in' { RET(TK_In); }
|
'in' { RET(TK_In); }
|
||||||
'sizeof' { RET(TK_SizeOf); }
|
'sizeof' { RET(TK_SizeOf); }
|
||||||
|
|
|
@ -128,6 +128,7 @@ xx(TK_Replaces, "'replaces'")
|
||||||
xx(TK_Vector2, "'vector2'")
|
xx(TK_Vector2, "'vector2'")
|
||||||
xx(TK_Vector3, "'vector3'")
|
xx(TK_Vector3, "'vector3'")
|
||||||
xx(TK_Map, "'map'")
|
xx(TK_Map, "'map'")
|
||||||
|
xx(TK_MapIterator, "'mapiterator'")
|
||||||
xx(TK_Array, "'array'")
|
xx(TK_Array, "'array'")
|
||||||
xx(TK_In, "'in'")
|
xx(TK_In, "'in'")
|
||||||
xx(TK_SizeOf, "'sizeof'")
|
xx(TK_SizeOf, "'sizeof'")
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "i_time.h"
|
#include "i_time.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
#include "maps.h"
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -342,6 +343,17 @@ DEFINE_ACTION_FUNCTION(DObject, Destroy)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
template<typename M>
|
||||||
|
static void PropagateMarkMap(M *map)
|
||||||
|
{
|
||||||
|
TMapIterator<typename M::KeyType,DObject*> it(*map);
|
||||||
|
typename M::Pair * p;
|
||||||
|
while(it.NextPair(p))
|
||||||
|
{
|
||||||
|
GC::Mark(&p->Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t DObject::PropagateMark()
|
size_t DObject::PropagateMark()
|
||||||
{
|
{
|
||||||
const PClass *info = GetClass();
|
const PClass *info = GetClass();
|
||||||
|
@ -375,6 +387,27 @@ size_t DObject::PropagateMark()
|
||||||
offsets++;
|
offsets++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::pair<size_t,PType *> *maps = info->MapPointers;
|
||||||
|
if (maps == NULL)
|
||||||
|
{
|
||||||
|
const_cast<PClass *>(info)->BuildMapPointers();
|
||||||
|
maps = info->MapPointers;
|
||||||
|
}
|
||||||
|
while (maps->first != ~(size_t)0)
|
||||||
|
{
|
||||||
|
if(maps->second->RegType == REGT_STRING)
|
||||||
|
{ // FString,DObject*
|
||||||
|
PropagateMarkMap((ZSMap<FString,DObject*>*)((uint8_t *)this + maps->first));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // uint32_t,DObject*
|
||||||
|
PropagateMarkMap((ZSMap<uint32_t,DObject*>*)((uint8_t *)this + maps->first));
|
||||||
|
}
|
||||||
|
maps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return info->Size;
|
return info->Size;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -82,6 +82,8 @@ DEFINE_GLOBAL(WP_NOCHANGE);
|
||||||
// A harmless non-nullptr FlatPointer for classes without pointers.
|
// A harmless non-nullptr FlatPointer for classes without pointers.
|
||||||
static const size_t TheEnd = ~(size_t)0;
|
static const size_t TheEnd = ~(size_t)0;
|
||||||
|
|
||||||
|
static const std::pair<size_t,PType *> TheMapEnd = {~(size_t)0 , nullptr};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PClass :: WriteValue
|
// PClass :: WriteValue
|
||||||
|
@ -877,6 +879,68 @@ void PClass::BuildArrayPointers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PClass :: BuildMapPointers
|
||||||
|
//
|
||||||
|
// same as above, but creates a list to dynamic object arrays
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PClass::BuildMapPointers()
|
||||||
|
{
|
||||||
|
if (MapPointers != nullptr)
|
||||||
|
{ // Already built: Do nothing.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (ParentClass == nullptr)
|
||||||
|
{ // No parent (i.e. DObject: FlatPointers is the same as Pointers.
|
||||||
|
MapPointers = &TheMapEnd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ParentClass->BuildMapPointers();
|
||||||
|
|
||||||
|
TArray<std::pair<size_t,PType *>> ScriptPointers;
|
||||||
|
|
||||||
|
// Collect all arrays to pointers in scripted fields.
|
||||||
|
for (auto field : Fields)
|
||||||
|
{
|
||||||
|
if (!(field->Flags & VARF_Native))
|
||||||
|
{
|
||||||
|
field->Type->SetPointerMap(Defaults, unsigned(field->Offset), &ScriptPointers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ScriptPointers.Size() == 0)
|
||||||
|
{ // No new pointers: Just use the same ArrayPointers as the parent.
|
||||||
|
MapPointers = ParentClass->MapPointers;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // New pointers: Create a new FlatPointers array and add them.
|
||||||
|
int numSuperPointers;
|
||||||
|
|
||||||
|
// Count pointers defined by superclasses.
|
||||||
|
for (numSuperPointers = 0; ParentClass->MapPointers[numSuperPointers].first != ~(size_t)0; numSuperPointers++)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Concatenate them into a new array
|
||||||
|
std::pair<size_t,PType *> *flat = (std::pair<size_t,PType *>*)ClassDataAllocator.Alloc(sizeof(std::pair<size_t,PType *>) * (numSuperPointers + ScriptPointers.Size() + 1));
|
||||||
|
if (numSuperPointers > 0)
|
||||||
|
{
|
||||||
|
memcpy(flat, ParentClass->MapPointers, sizeof(std::pair<size_t,PType *>)*numSuperPointers);
|
||||||
|
}
|
||||||
|
if (ScriptPointers.Size() > 0)
|
||||||
|
{
|
||||||
|
memcpy(flat + numSuperPointers, &ScriptPointers[0], sizeof(std::pair<size_t,PType *>) * ScriptPointers.Size());
|
||||||
|
}
|
||||||
|
flat[numSuperPointers + ScriptPointers.Size()] = TheMapEnd;
|
||||||
|
MapPointers = flat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PClass :: NativeClass
|
// PClass :: NativeClass
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
const size_t *Pointers = nullptr; // object pointers defined by this class *only*
|
const size_t *Pointers = nullptr; // object pointers defined by this class *only*
|
||||||
const size_t *FlatPointers = nullptr; // object pointers defined by this class and all its superclasses; not initialized by default
|
const size_t *FlatPointers = nullptr; // object pointers defined by this class and all its superclasses; not initialized by default
|
||||||
const size_t *ArrayPointers = nullptr; // dynamic arrays containing object pointers.
|
const size_t *ArrayPointers = nullptr; // dynamic arrays containing object pointers.
|
||||||
|
const std::pair<size_t,PType *> *MapPointers = nullptr; // maps containing object pointers.
|
||||||
uint8_t *Defaults = nullptr;
|
uint8_t *Defaults = nullptr;
|
||||||
uint8_t *Meta = nullptr; // Per-class static script data
|
uint8_t *Meta = nullptr; // Per-class static script data
|
||||||
unsigned Size = sizeof(DObject);
|
unsigned Size = sizeof(DObject);
|
||||||
|
@ -84,6 +85,7 @@ public:
|
||||||
void InitializeActorInfo();
|
void InitializeActorInfo();
|
||||||
void BuildFlatPointers();
|
void BuildFlatPointers();
|
||||||
void BuildArrayPointers();
|
void BuildArrayPointers();
|
||||||
|
void BuildMapPointers();
|
||||||
void DestroySpecials(void *addr);
|
void DestroySpecials(void *addr);
|
||||||
void DestroyMeta(void *addr);
|
void DestroyMeta(void *addr);
|
||||||
const PClass *NativeClass() const;
|
const PClass *NativeClass() const;
|
||||||
|
|
|
@ -8205,6 +8205,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
PContainerType *ccls = nullptr;
|
PContainerType *ccls = nullptr;
|
||||||
|
|
||||||
|
PFunction * afd_override = nullptr;
|
||||||
|
|
||||||
if (ctx.Class == nullptr)
|
if (ctx.Class == nullptr)
|
||||||
{
|
{
|
||||||
// There's no way that a member function call can resolve to a constant so abort right away.
|
// There's no way that a member function call can resolve to a constant so abort right away.
|
||||||
|
@ -8278,7 +8280,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
if (Self->ValueType->isRealPointer())
|
if (Self->ValueType->isRealPointer())
|
||||||
{
|
{
|
||||||
auto pointedType = Self->ValueType->toPointer()->PointedType;
|
auto pointedType = Self->ValueType->toPointer()->PointedType;
|
||||||
if (pointedType && pointedType->isDynArray())
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
{
|
{
|
||||||
Self = new FxOutVarDereference(Self, Self->ScriptPosition);
|
Self = new FxOutVarDereference(Self, Self->ScriptPosition);
|
||||||
SAFE_RESOLVE(Self, ctx);
|
SAFE_RESOLVE(Self, ctx);
|
||||||
|
@ -8454,7 +8456,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
if (a->ValueType->isRealPointer())
|
if (a->ValueType->isRealPointer())
|
||||||
{
|
{
|
||||||
auto pointedType = a->ValueType->toPointer()->PointedType;
|
auto pointedType = a->ValueType->toPointer()->PointedType;
|
||||||
if (pointedType && pointedType->isDynArray())
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
{
|
{
|
||||||
a = new FxOutVarDereference(a, a->ScriptPosition);
|
a = new FxOutVarDereference(a, a->ScriptPosition);
|
||||||
SAFE_RESOLVE(a, ctx);
|
SAFE_RESOLVE(a, ctx);
|
||||||
|
@ -8561,6 +8563,193 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(Self->IsMap())
|
||||||
|
{
|
||||||
|
PMap * m = static_cast<PMap*>(Self->ValueType);
|
||||||
|
Self->ValueType = m->BackingType;
|
||||||
|
|
||||||
|
auto mapKeyType = m->KeyType;
|
||||||
|
auto mapValueType = m->ValueType;
|
||||||
|
|
||||||
|
bool isObjMap = mapValueType->isObjectPointer();
|
||||||
|
|
||||||
|
if (PFunction **Override; (Override = m->FnOverrides.CheckKey(MethodName)))
|
||||||
|
{
|
||||||
|
afd_override = *Override;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapted from DynArray codegen
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (auto &a : ArgList)
|
||||||
|
{
|
||||||
|
a = a->Resolve(ctx);
|
||||||
|
if (a == nullptr)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (a->ValueType->isRealPointer())
|
||||||
|
{
|
||||||
|
auto pointedType = a->ValueType->toPointer()->PointedType;
|
||||||
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
|
{
|
||||||
|
a = new FxOutVarDereference(a, a->ScriptPosition);
|
||||||
|
SAFE_RESOLVE(a, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isObjMap && (MethodName == NAME_Insert && idx == 1))
|
||||||
|
{
|
||||||
|
// Null pointers are always valid.
|
||||||
|
if (!a->isConstant() || static_cast<FxConstant*>(a)->GetValue().GetPointer() != nullptr)
|
||||||
|
{
|
||||||
|
if (!a->ValueType->isObjectPointer() ||
|
||||||
|
!static_cast<PObjectPointer*>(mapValueType)->PointedClass()->IsAncestorOf(static_cast<PObjectPointer*>(a->ValueType)->PointedClass()))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->IsMap())
|
||||||
|
{
|
||||||
|
// Copy and Move must turn their parameter into a pointer to the backing struct type.
|
||||||
|
auto o = static_cast<PMap*>(a->ValueType);
|
||||||
|
auto backingtype = o->BackingType;
|
||||||
|
if (mapKeyType != o->KeyType || mapValueType != o->ValueType)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
bool writable;
|
||||||
|
if (!a->RequestAddress(ctx, &writable))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Unable to dereference map variable");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
a->ValueType = NewPointer(backingtype);
|
||||||
|
|
||||||
|
// Also change the field's type so the code generator can work with this (actually this requires swapping out the entire field.)
|
||||||
|
if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_StackVariable)
|
||||||
|
{
|
||||||
|
auto member = static_cast<FxMemberBase*>(Self);
|
||||||
|
auto newfield = Create<PField>(NAME_None, backingtype, 0, member->membervar->Offset);
|
||||||
|
member->membervar = newfield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (a->IsPointer() && Self->ValueType->isPointer())
|
||||||
|
{
|
||||||
|
// the only case which must be checked up front is for pointer arrays receiving a new element.
|
||||||
|
// Since there is only one native backing class it uses a neutral void pointer as its argument,
|
||||||
|
// meaning that FxMemberFunctionCall is unable to do a proper check. So we have to do it here.
|
||||||
|
if (a->ValueType != mapValueType)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument. Got %s, expected %s", a->ValueType->DescriptiveName(), mapValueType->DescriptiveName());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Self->IsMapIterator())
|
||||||
|
{
|
||||||
|
PMapIterator * mi = static_cast<PMapIterator*>(Self->ValueType);
|
||||||
|
Self->ValueType = mi->BackingType;
|
||||||
|
|
||||||
|
auto mapKeyType = mi->KeyType;
|
||||||
|
auto mapValueType = mi->ValueType;
|
||||||
|
|
||||||
|
bool isObjMap = mapValueType->isObjectPointer();
|
||||||
|
|
||||||
|
if (PFunction **Override; (Override = mi->FnOverrides.CheckKey(MethodName)))
|
||||||
|
{
|
||||||
|
afd_override = *Override;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapted from DynArray codegen
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (auto &a : ArgList)
|
||||||
|
{
|
||||||
|
a = a->Resolve(ctx);
|
||||||
|
if (a == nullptr)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (a->ValueType->isRealPointer())
|
||||||
|
{
|
||||||
|
auto pointedType = a->ValueType->toPointer()->PointedType;
|
||||||
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
|
{
|
||||||
|
a = new FxOutVarDereference(a, a->ScriptPosition);
|
||||||
|
SAFE_RESOLVE(a, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isObjMap && (MethodName == NAME_SetValue && idx == 0))
|
||||||
|
{
|
||||||
|
// Null pointers are always valid.
|
||||||
|
if (!a->isConstant() || static_cast<FxConstant*>(a)->GetValue().GetPointer() != nullptr)
|
||||||
|
{
|
||||||
|
if (!a->ValueType->isObjectPointer() ||
|
||||||
|
!static_cast<PObjectPointer*>(mapValueType)->PointedClass()->IsAncestorOf(static_cast<PObjectPointer*>(a->ValueType)->PointedClass()))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->IsMap())
|
||||||
|
{
|
||||||
|
// Copy and Move must turn their parameter into a pointer to the backing struct type.
|
||||||
|
auto o = static_cast<PMapIterator*>(a->ValueType);
|
||||||
|
auto backingtype = o->BackingType;
|
||||||
|
if (mapKeyType != o->KeyType || mapValueType != o->ValueType)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
bool writable;
|
||||||
|
if (!a->RequestAddress(ctx, &writable))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Unable to dereference map variable");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
a->ValueType = NewPointer(backingtype);
|
||||||
|
|
||||||
|
// Also change the field's type so the code generator can work with this (actually this requires swapping out the entire field.)
|
||||||
|
if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_StackVariable)
|
||||||
|
{
|
||||||
|
auto member = static_cast<FxMemberBase*>(Self);
|
||||||
|
auto newfield = Create<PField>(NAME_None, backingtype, 0, member->membervar->Offset);
|
||||||
|
member->membervar = newfield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (a->IsPointer() && Self->ValueType->isPointer())
|
||||||
|
{
|
||||||
|
// the only case which must be checked up front is for pointer arrays receiving a new element.
|
||||||
|
// Since there is only one native backing class it uses a neutral void pointer as its argument,
|
||||||
|
// meaning that FxMemberFunctionCall is unable to do a proper check. So we have to do it here.
|
||||||
|
if (a->ValueType != mapValueType)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument. Got %s, expected %s", a->ValueType->DescriptiveName(), mapValueType->DescriptiveName());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (MethodName == NAME_GetParentClass &&
|
if (MethodName == NAME_GetParentClass &&
|
||||||
|
@ -8635,7 +8824,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
isresolved:
|
isresolved:
|
||||||
bool error = false;
|
bool error = false;
|
||||||
PFunction *afd = FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error, ctx.Version, !ctx.FromDecorate);
|
PFunction *afd = afd_override ? afd_override : FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error, ctx.Version, !ctx.FromDecorate);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -9034,7 +9223,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
if (ArgList[i] && ArgList[i]->ValueType->isRealPointer())
|
if (ArgList[i] && ArgList[i]->ValueType->isRealPointer())
|
||||||
{
|
{
|
||||||
auto pointedType = ArgList[i]->ValueType->toPointer()->PointedType;
|
auto pointedType = ArgList[i]->ValueType->toPointer()->PointedType;
|
||||||
if (pointedType && pointedType->isDynArray())
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
{
|
{
|
||||||
ArgList[i] = new FxOutVarDereference(ArgList[i], ArgList[i]->ScriptPosition);
|
ArgList[i] = new FxOutVarDereference(ArgList[i], ArgList[i]->ScriptPosition);
|
||||||
SAFE_RESOLVE(ArgList[i], ctx);
|
SAFE_RESOLVE(ArgList[i], ctx);
|
||||||
|
@ -11806,7 +11995,7 @@ FxExpression *FxOutVarDereference::Resolve(FCompileContext &ctx)
|
||||||
SelfType = Self->ValueType->toPointer()->PointedType;
|
SelfType = Self->ValueType->toPointer()->PointedType;
|
||||||
ValueType = SelfType;
|
ValueType = SelfType;
|
||||||
|
|
||||||
if (SelfType->GetRegType() == REGT_NIL && !SelfType->isRealPointer() && !SelfType->isDynArray())
|
if (SelfType->GetRegType() == REGT_NIL && !SelfType->isRealPointer() && !SelfType->isDynArray() && !SelfType->isMap() && !SelfType->isMapIterator())
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Cannot dereference pointer");
|
ScriptPosition.Message(MSG_ERROR, "Cannot dereference pointer");
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -11835,7 +12024,7 @@ ExpEmit FxOutVarDereference::Emit(VMFunctionBuilder *build)
|
||||||
regType = REGT_POINTER;
|
regType = REGT_POINTER;
|
||||||
loadOp = OP_LP;
|
loadOp = OP_LP;
|
||||||
}
|
}
|
||||||
else if (SelfType->isDynArray())
|
else if (SelfType->isDynArray() || SelfType->isMap() || SelfType->isMapIterator())
|
||||||
{
|
{
|
||||||
regType = REGT_POINTER;
|
regType = REGT_POINTER;
|
||||||
loadOp = OP_MOVEA;
|
loadOp = OP_MOVEA;
|
||||||
|
|
|
@ -350,6 +350,8 @@ public:
|
||||||
bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); }
|
bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); }
|
||||||
bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form.
|
bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form.
|
||||||
bool IsDynamicArray() const { return (ValueType->isDynArray()); }
|
bool IsDynamicArray() const { return (ValueType->isDynArray()); }
|
||||||
|
bool IsMap() const { return ValueType->isMap(); }
|
||||||
|
bool IsMapIterator() const { return ValueType->isMapIterator(); }
|
||||||
bool IsStruct() const { return ValueType->isStruct(); }
|
bool IsStruct() const { return ValueType->isStruct(); }
|
||||||
bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast<PStruct*>(ValueType)->isNative); }
|
bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast<PStruct*>(ValueType)->isNative); }
|
||||||
|
|
||||||
|
|
483
src/common/scripting/core/maps.cpp
Normal file
483
src/common/scripting/core/maps.cpp
Normal file
|
@ -0,0 +1,483 @@
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "dobject.h"
|
||||||
|
#include "zstring.h"
|
||||||
|
#include "vm.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "v_draw.h"
|
||||||
|
#include "maps.h"
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MAP_GC_WRITE_BARRIER
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
#define MAP_GC_WRITE_BARRIER(x) { \
|
||||||
|
TMapIterator<typename M::KeyType, DObject*> it(*x);\
|
||||||
|
typename M::Pair * p;\
|
||||||
|
while(it.NextPair(p)){\
|
||||||
|
GC::WriteBarrier(p->Value);\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapCopy
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapCopy(M * self, M * other)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType,DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(other);
|
||||||
|
}
|
||||||
|
*self = *other; // how does this handle self->info? TODO double check.
|
||||||
|
self->info->rev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapMove
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapMove(M * self, M * other)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType,DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(other);
|
||||||
|
}
|
||||||
|
self->TransferFrom(*other);
|
||||||
|
self->info->rev++;
|
||||||
|
other->info->rev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapSwap
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapSwap(M * self, M * other)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType,DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(other);
|
||||||
|
}
|
||||||
|
self->Swap(*other);
|
||||||
|
self->info->rev++;
|
||||||
|
other->info->rev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapClear
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapClear(M * self)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType,DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(self);
|
||||||
|
}
|
||||||
|
self->Clear();
|
||||||
|
self->info->rev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using expand_types_vm =
|
||||||
|
std::conditional_t<std::is_same_v<T, uint8_t> || std::is_same_v<T, uint16_t>, uint32_t , /* expand 8/16-bit to 32-bit */
|
||||||
|
std::conditional_t<std::is_same_v<T, float> , double , /* expand float to double */
|
||||||
|
std::conditional_t<std::is_same_v<T, FString> , const FString & , T>>>; /* change String to String ref */
|
||||||
|
|
||||||
|
template<typename M> unsigned int MapCountUsed(M * self)
|
||||||
|
{
|
||||||
|
return self->CountUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename M> expand_types_vm<typename M::ValueType> MapGet(M * self,expand_types_vm<typename M::KeyType> key)
|
||||||
|
{
|
||||||
|
typename M::ValueType * v = self->CheckKey(key);
|
||||||
|
if (v) {
|
||||||
|
return *v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
typename M::ValueType n {};
|
||||||
|
self->Insert(key,n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename M> void MapGetString(M * self,expand_types_vm<typename M::KeyType> key, FString &out)
|
||||||
|
{
|
||||||
|
FString * v = self->CheckKey(key);
|
||||||
|
if (v) {
|
||||||
|
out = *v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out = FString();
|
||||||
|
self->Insert(key,out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename M> int MapCheckKey(M * self, expand_types_vm<typename M::KeyType> key)
|
||||||
|
{
|
||||||
|
return self->CheckKey(key) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapInsert
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapInsert(M * self, expand_types_vm<typename M::KeyType> key, expand_types_vm<typename M::ValueType> value)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType, DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(self);
|
||||||
|
GC::WriteBarrier(value);
|
||||||
|
}
|
||||||
|
self->Insert(key, value);
|
||||||
|
self->info->rev++; // invalidate iterators
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapInsertNew(M * self, expand_types_vm<typename M::KeyType> key)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType, DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(self);
|
||||||
|
}
|
||||||
|
self->Insert(key,{});
|
||||||
|
self->info->rev++; // invalidate iterators
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename M> void MapRemove(M * self, expand_types_vm<typename M::KeyType> key)
|
||||||
|
{
|
||||||
|
self->Remove(key);
|
||||||
|
self->info->rev++; // invalidate iterators
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename I, typename M> int MapIteratorInit(I * self, M * other)
|
||||||
|
{
|
||||||
|
return self->Init(*other);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> int MapIteratorReInit(I * self)
|
||||||
|
{
|
||||||
|
return self->ReInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> int MapIteratorValid(I * self)
|
||||||
|
{
|
||||||
|
return self->Valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> int MapIteratorNext(I * self)
|
||||||
|
{
|
||||||
|
return self->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> expand_types_vm<typename I::KeyType> MapIteratorGetKey(I * self)
|
||||||
|
{
|
||||||
|
return self->GetKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> void MapIteratorGetKeyString(I * self, FString &out)
|
||||||
|
{
|
||||||
|
out = self->GetKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> expand_types_vm<typename I::ValueType> MapIteratorGetValue(I * self)
|
||||||
|
{
|
||||||
|
return self->GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> void MapIteratorGetValueString(I * self, FString &out)
|
||||||
|
{
|
||||||
|
out = self->GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> void MapIteratorSetValue(I * self, expand_types_vm<typename I::ValueType> value)
|
||||||
|
{
|
||||||
|
auto & val = self->GetValue();
|
||||||
|
if constexpr(std::is_same_v<typename I::ValueType, DObject*>)
|
||||||
|
{
|
||||||
|
GC::WriteBarrier(val);
|
||||||
|
GC::WriteBarrier(value);
|
||||||
|
}
|
||||||
|
val = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
#define PARAM_VOIDPOINTER(X) PARAM_POINTER( X , void )
|
||||||
|
#define PARAM_OBJPOINTER(X) PARAM_OBJECT( X , DObject )
|
||||||
|
|
||||||
|
#define _DEF_MAP( name, key_type, value_type, PARAM_KEY, PARAM_VALUE ) \
|
||||||
|
typedef ZSMap<key_type , value_type> name;\
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Copy , MapCopy< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_POINTER( other, name ); \
|
||||||
|
MapCopy(self , other); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Move , MapMove< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_POINTER( other, name ); \
|
||||||
|
MapMove(self , other); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Swap , MapSwap< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_POINTER( other, name ); \
|
||||||
|
MapSwap(self , other); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Clear , MapClear< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
MapClear(self); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, CountUsed, MapCountUsed< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_INT( MapCountUsed(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, CheckKey, MapCheckKey< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
ACTION_RETURN_BOOL( MapCheckKey(self, key) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, Insert, MapInsert< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
PARAM_VALUE( value ); \
|
||||||
|
MapInsert(self, key, value); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, InsertNew, MapInsertNew< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
MapInsertNew(self, key); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, Remove, MapRemove< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
MapRemove(self, key); \
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_X_X( name, key_type, value_type, PARAM_KEY, PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
_DEF_MAP( name , key_type , value_type , PARAM_KEY , PARAM_VALUE ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, Get, MapGet< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
ACTION_RETURN_VALUE( MapGet(self, key) ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_X_S( name, key_type, PARAM_KEY ) \
|
||||||
|
_DEF_MAP( name , key_type , FString , PARAM_KEY , PARAM_STRING ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, Get, MapGetString< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
FString out; \
|
||||||
|
MapGetString(self, key, out); \
|
||||||
|
ACTION_RETURN_STRING( out ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define COMMA ,
|
||||||
|
|
||||||
|
#define _DEF_MAP_IT( map_name , name, key_type, value_type, PARAM_VALUE ) \
|
||||||
|
typedef ZSMapIterator<key_type , value_type> name; \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Init , MapIteratorInit< name COMMA map_name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_POINTER( other, map_name ); \
|
||||||
|
ACTION_RETURN_BOOL( MapIteratorInit(self , other) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , ReInit , MapIteratorReInit< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_BOOL( MapIteratorReInit(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Valid , MapIteratorValid< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_BOOL( MapIteratorValid(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Next , MapIteratorNext< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_BOOL( MapIteratorNext(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , SetValue , MapIteratorSetValue< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_VALUE( value ); \
|
||||||
|
MapIteratorSetValue(self, value); \
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetKey , MapIteratorGetKey< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_KEY( MapIteratorGetKey(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetValue , MapIteratorGetValue< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_VALUE( MapIteratorGetValue(self) ); \
|
||||||
|
} \
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEF_MAP_IT_I_X( map_name , name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
_DEF_MAP_IT( map_name , name , uint32_t , value_type , PARAM_VALUE ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetKey , MapIteratorGetKey< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_INT( MapIteratorGetKey(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetValue , MapIteratorGetValue< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_VALUE( MapIteratorGetValue(self) ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_IT_S_X( map_name , name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
_DEF_MAP_IT( map_name , name , FString , value_type , PARAM_VALUE ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetKey , MapIteratorGetKeyString< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
FString out; \
|
||||||
|
MapIteratorGetKeyString(self , out); \
|
||||||
|
ACTION_RETURN_STRING( out ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetValue , MapIteratorGetValue< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_VALUE( MapIteratorGetValue(self) ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_IT_I_S() \
|
||||||
|
_DEF_MAP_IT( FMap_I32_Str , FMapIterator_I32_Str , uint32_t , FString , PARAM_STRING ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_I32_Str , GetKey , MapIteratorGetKey< FMapIterator_I32_Str > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_I32_Str ); \
|
||||||
|
ACTION_RETURN_INT( MapIteratorGetKey(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_I32_Str , GetValue , MapIteratorGetValue< FMapIterator_I32_Str > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_I32_Str ); \
|
||||||
|
ACTION_RETURN_STRING( MapIteratorGetValue(self) ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_IT_S_S() \
|
||||||
|
_DEF_MAP_IT( FMap_Str_Str , FMapIterator_Str_Str , FString , FString , PARAM_STRING ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_Str_Str , GetKey , MapIteratorGetKeyString< FMapIterator_Str_Str > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_Str_Str ); \
|
||||||
|
FString out; \
|
||||||
|
MapIteratorGetKeyString(self , out); \
|
||||||
|
ACTION_RETURN_STRING( out ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_Str_Str , GetValue , MapIteratorGetValueString< FMapIterator_Str_Str > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_Str_Str ); \
|
||||||
|
FString out; \
|
||||||
|
MapIteratorGetValueString(self , out); \
|
||||||
|
ACTION_RETURN_STRING( out ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFINE_MAP_AND_IT_I_X( name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
DEF_MAP_X_X( FMap_ ## name , uint32_t , value_type , PARAM_INT , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
DEF_MAP_IT_I_X( FMap_ ## name , FMapIterator_ ## name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE )
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFINE_MAP_AND_IT_S_X( name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
DEF_MAP_X_X( FMap_ ## name , FString , value_type , PARAM_STRING , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
DEF_MAP_IT_S_X( FMap_ ## name , FMapIterator_ ## name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE )
|
||||||
|
|
||||||
|
#define DEFINE_MAP_AND_IT_I_S() \
|
||||||
|
DEF_MAP_X_S( FMap_I32_Str , uint32_t , PARAM_INT ) \
|
||||||
|
DEF_MAP_IT_I_S()
|
||||||
|
|
||||||
|
#define DEFINE_MAP_AND_IT_S_S() \
|
||||||
|
DEF_MAP_X_S( FMap_Str_Str , FString , PARAM_STRING ) \
|
||||||
|
DEF_MAP_IT_S_S()
|
||||||
|
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_I8 , uint8_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_I16 , uint16_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_I32 , uint32_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_F32 , float , PARAM_FLOAT , ACTION_RETURN_FLOAT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_F64 , double , PARAM_FLOAT , ACTION_RETURN_FLOAT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_Obj , DObject* , PARAM_OBJPOINTER , ACTION_RETURN_OBJECT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_Ptr , void* , PARAM_VOIDPOINTER , ACTION_RETURN_POINTER);
|
||||||
|
DEFINE_MAP_AND_IT_I_S();
|
||||||
|
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_I8 , uint8_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_I16 , uint16_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_I32 , uint32_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_F32 , float , PARAM_FLOAT , ACTION_RETURN_FLOAT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_F64 , double , PARAM_FLOAT , ACTION_RETURN_FLOAT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_Obj , DObject* , PARAM_OBJPOINTER , ACTION_RETURN_OBJECT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_Ptr , void* , PARAM_VOIDPOINTER , ACTION_RETURN_POINTER);
|
||||||
|
DEFINE_MAP_AND_IT_S_S();
|
110
src/common/scripting/core/maps.h
Normal file
110
src/common/scripting/core/maps.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "refcounted.h"
|
||||||
|
|
||||||
|
class ZSMapInfo : public RefCountedBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void * self = nullptr;
|
||||||
|
int rev = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZSFMap : FMap {
|
||||||
|
RefCountedPtr<RefCountedBase> info;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class KT, class VT>
|
||||||
|
class ZSMap : public TMap<KT,VT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RefCountedPtr<ZSMapInfo> info;
|
||||||
|
ZSMap() :
|
||||||
|
TMap<KT,VT>(), info(new ZSMapInfo)
|
||||||
|
{
|
||||||
|
info->self = this;
|
||||||
|
}
|
||||||
|
~ZSMap()
|
||||||
|
{
|
||||||
|
info->self = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class KT, class VT>
|
||||||
|
struct ZSMapIterator
|
||||||
|
{
|
||||||
|
RefCountedPtr<ZSMapInfo> info;
|
||||||
|
TMapIterator<KT,VT> *it = nullptr;
|
||||||
|
typename ZSMap<KT,VT>::Pair *p = nullptr;
|
||||||
|
|
||||||
|
typedef KT KeyType;
|
||||||
|
typedef VT ValueType;
|
||||||
|
|
||||||
|
int rev = 0;
|
||||||
|
|
||||||
|
~ZSMapIterator()
|
||||||
|
{
|
||||||
|
if(it) delete it;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Valid()
|
||||||
|
{
|
||||||
|
return it && p && info.get() && info->self && info->rev == rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReInit()
|
||||||
|
{
|
||||||
|
if(info.get() && info->self) {
|
||||||
|
if(it) delete it;
|
||||||
|
it = new TMapIterator<KT,VT>(*static_cast<ZSMap<KT,VT>*>(info->self));
|
||||||
|
rev = info->rev;
|
||||||
|
p = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Init(ZSMap<KT,VT> &m)
|
||||||
|
{
|
||||||
|
info = m.info;
|
||||||
|
return ReInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Next()
|
||||||
|
{
|
||||||
|
if(it && info.get() && info->self && info->rev == rev)
|
||||||
|
{
|
||||||
|
p = nullptr;
|
||||||
|
return it->NextPair(p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThrowAbortException(X_FORMAT_ERROR,"MapIterator::Next called from invalid iterator");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VT& GetValue()
|
||||||
|
{
|
||||||
|
if(p && info.get() && info->self && info->rev == rev)
|
||||||
|
{
|
||||||
|
return p->Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThrowAbortException(X_FORMAT_ERROR,p ? "MapIterator::GetValue called from invalid iterator" : "MapIterator::GetValue called from invalid position");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const KT& GetKey()
|
||||||
|
{
|
||||||
|
if(p && info.get() && info->self && info->rev == rev)
|
||||||
|
{
|
||||||
|
return p->Key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThrowAbortException(X_FORMAT_ERROR,p ? "MapIterator::GetKey called from invalid iterator" : "MapIterator::GetKey called from invalid position");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -33,11 +33,14 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
#include "vmintern.h"
|
#include "vmintern.h"
|
||||||
#include "s_soundinternal.h"
|
#include "s_soundinternal.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "textureid.h"
|
#include "textureid.h"
|
||||||
|
#include "maps.h"
|
||||||
|
|
||||||
|
|
||||||
FTypeTable TypeTable;
|
FTypeTable TypeTable;
|
||||||
|
@ -183,7 +186,7 @@ void PType::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset>
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PType :: SetDefaultValue
|
// PType :: SetPointer*
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
@ -195,6 +198,10 @@ void PType::SetPointerArray(void *base, unsigned offset, TArray<size_t> *stroffs
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PType::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PType :: InitializeValue
|
// PType :: InitializeValue
|
||||||
|
@ -1871,6 +1878,23 @@ void PArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *specia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PArray :: SetPointerMap
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PArray::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *special)
|
||||||
|
{
|
||||||
|
if(ElementType->isStruct() || ElementType->isMap())
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < ElementCount; ++i)
|
||||||
|
{
|
||||||
|
ElementType->SetPointerMap(base, offset + ElementSize * i, special);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// NewArray
|
// NewArray
|
||||||
|
@ -2202,12 +2226,89 @@ PDynArray *NewDynArray(PType *type)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PMap::PMap(PType *keytype, PType *valtype)
|
enum OverrideFunctionRetType {
|
||||||
: KeyType(keytype), ValueType(valtype)
|
OFN_RET_VOID,
|
||||||
|
OFN_RET_VAL,
|
||||||
|
OFN_RET_KEY,
|
||||||
|
OFN_RET_BOOL,
|
||||||
|
};
|
||||||
|
enum OverrideFunctionArgType {
|
||||||
|
OFN_ARG_VOID,
|
||||||
|
OFN_ARG_KEY,
|
||||||
|
OFN_ARG_VAL,
|
||||||
|
OFN_ARG_KEY_VAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class MT, OverrideFunctionRetType RetType, OverrideFunctionArgType ArgType >
|
||||||
|
void CreateOverrideFunction(MT *self, FName name)
|
||||||
|
{
|
||||||
|
auto Fn = Create<PFunction>(self->BackingType, name);
|
||||||
|
auto NativeFn = FindFunction(self->BackingType, name.GetChars());
|
||||||
|
|
||||||
|
assert(NativeFn);
|
||||||
|
assert(NativeFn->VMPointer);
|
||||||
|
|
||||||
|
|
||||||
|
TArray<PType*> ret;
|
||||||
|
TArray<PType*> args;
|
||||||
|
TArray<uint32_t> argflags;
|
||||||
|
TArray<FName> argnames;
|
||||||
|
|
||||||
|
if constexpr(RetType == OFN_RET_VAL)
|
||||||
|
{
|
||||||
|
ret.Push(self->ValueType);
|
||||||
|
}
|
||||||
|
else if constexpr(RetType == OFN_RET_KEY)
|
||||||
|
{
|
||||||
|
ret.Push(self->KeyType);
|
||||||
|
}
|
||||||
|
else if constexpr(RetType == OFN_RET_BOOL)
|
||||||
|
{
|
||||||
|
ret.Push(TypeBool);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Push(NewPointer(self->BackingType));
|
||||||
|
argnames.Push(NAME_self);
|
||||||
|
argflags.Push(VARF_Implicit | VARF_ReadOnly);
|
||||||
|
|
||||||
|
if constexpr(ArgType == OFN_ARG_KEY)
|
||||||
|
{
|
||||||
|
args.Push(self->KeyType);
|
||||||
|
argflags.Push(0);
|
||||||
|
argnames.Push(NAME_Key);
|
||||||
|
}
|
||||||
|
else if constexpr(ArgType == OFN_ARG_VAL)
|
||||||
|
{
|
||||||
|
|
||||||
|
args.Push(self->ValueType);
|
||||||
|
argflags.Push(0);
|
||||||
|
argnames.Push(NAME_Value);
|
||||||
|
}
|
||||||
|
else if constexpr(ArgType == OFN_ARG_KEY_VAL)
|
||||||
|
{
|
||||||
|
args.Push(self->KeyType);
|
||||||
|
args.Push(self->ValueType);
|
||||||
|
argflags.Push(0);
|
||||||
|
argflags.Push(0);
|
||||||
|
argnames.Push(NAME_Key);
|
||||||
|
argnames.Push(NAME_Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Fn->AddVariant(NewPrototype(ret, args), argflags, argnames, *NativeFn->VMPointer, VARF_Method | VARF_Native,SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM);
|
||||||
|
self->FnOverrides.Insert(name, Fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
PMap::PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class)
|
||||||
|
: KeyType(keytype), ValueType(valtype), BackingType(backing), BackingClass((decltype(BackingClass)) backing_class)
|
||||||
{
|
{
|
||||||
mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName());
|
mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName());
|
||||||
Size = sizeof(FMap);
|
Size = sizeof(ZSFMap);
|
||||||
Align = alignof(FMap);
|
Align = alignof(ZSFMap);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_VAL, OFN_ARG_KEY>(this, NAME_Get);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_BOOL, OFN_ARG_KEY>(this, NAME_CheckKey);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_VOID, OFN_ARG_KEY_VAL>(this, NAME_Insert);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_VOID, OFN_ARG_KEY>(this, NAME_InsertNew);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_VOID, OFN_ARG_KEY>(this, NAME_Remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2236,6 +2337,345 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
id2 = (intptr_t)ValueType;
|
id2 = (intptr_t)ValueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: InitializeValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMap::Construct(void * addr) const {
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case MAP_I32_I8:
|
||||||
|
new(addr) ZSMap<uint32_t, uint8_t>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_I16:
|
||||||
|
new(addr) ZSMap<uint32_t, uint16_t>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_I32:
|
||||||
|
new(addr) ZSMap<uint32_t, uint32_t>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_F32:
|
||||||
|
new(addr) ZSMap<uint32_t, float>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_F64:
|
||||||
|
new(addr) ZSMap<uint32_t, double>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_OBJ:
|
||||||
|
new(addr) ZSMap<uint32_t, DObject*>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_PTR:
|
||||||
|
new(addr) ZSMap<uint32_t, void*>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_STR:
|
||||||
|
new(addr) ZSMap<uint32_t, FString>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I8:
|
||||||
|
new(addr) ZSMap<FString, uint8_t>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I16:
|
||||||
|
new(addr) ZSMap<FString, uint16_t>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I32:
|
||||||
|
new(addr) ZSMap<FString, uint32_t>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_F32:
|
||||||
|
new(addr) ZSMap<FString, float>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_F64:
|
||||||
|
new(addr) ZSMap<FString, double>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_OBJ:
|
||||||
|
new(addr) ZSMap<FString, DObject*>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_PTR:
|
||||||
|
new(addr) ZSMap<FString, void*>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_STR:
|
||||||
|
new(addr) ZSMap<FString, FString>();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PMap::InitializeValue(void *addr, const void *def) const
|
||||||
|
{
|
||||||
|
if (def != nullptr)
|
||||||
|
{
|
||||||
|
I_Error("Map cannot have default values");
|
||||||
|
}
|
||||||
|
Construct(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: DestroyValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMap::DestroyValue(void *addr) const
|
||||||
|
{
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case MAP_I32_I8:
|
||||||
|
static_cast<ZSMap<uint32_t, uint8_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_I16:
|
||||||
|
static_cast<ZSMap<uint32_t, uint16_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_I32:
|
||||||
|
static_cast<ZSMap<uint32_t, uint32_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_F32:
|
||||||
|
static_cast<ZSMap<uint32_t, float>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_F64:
|
||||||
|
static_cast<ZSMap<uint32_t, double>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_OBJ:
|
||||||
|
static_cast<ZSMap<uint32_t, DObject*>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_PTR:
|
||||||
|
static_cast<ZSMap<uint32_t, void*>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_STR:
|
||||||
|
static_cast<ZSMap<uint32_t, FString>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I8:
|
||||||
|
static_cast<ZSMap<FString, uint8_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I16:
|
||||||
|
static_cast<ZSMap<FString, uint16_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I32:
|
||||||
|
static_cast<ZSMap<FString, uint32_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_F32:
|
||||||
|
static_cast<ZSMap<FString, float>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_F64:
|
||||||
|
static_cast<ZSMap<FString, double>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_OBJ:
|
||||||
|
static_cast<ZSMap<FString, DObject*>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_PTR:
|
||||||
|
static_cast<ZSMap<FString, void*>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_STR:
|
||||||
|
static_cast<ZSMap<FString, FString>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: SetDefaultValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMap::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special)
|
||||||
|
{
|
||||||
|
assert(!(base && special));
|
||||||
|
if (base != nullptr)
|
||||||
|
{
|
||||||
|
Construct(((uint8_t*)base)+offset); // is this needed? string/dynarray do this initialization if base != nullptr, but their initialization doesn't need to allocate
|
||||||
|
// it might lead to double allocations (and memory leakage) for Map if both base and special != nullptr
|
||||||
|
}
|
||||||
|
if (special != nullptr)
|
||||||
|
{
|
||||||
|
special->Push(std::make_pair(this, offset));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I_Error("null special");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: SetPointer
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMap::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *special)
|
||||||
|
{
|
||||||
|
if (ValueType->isObjectPointer())
|
||||||
|
{
|
||||||
|
// Add to the list of pointer arrays for this class.
|
||||||
|
special->Push(std::make_pair(offset,KeyType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: WriteValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
template<typename M>
|
||||||
|
static void PMapValueWriter(FSerializer &ar, const M *map, const PMap *m)
|
||||||
|
{
|
||||||
|
TMapConstIterator<typename M::KeyType, typename M::ValueType> it(*map);
|
||||||
|
const typename M::Pair * p;
|
||||||
|
while(it.NextPair(p))
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::KeyType,FString>)
|
||||||
|
{
|
||||||
|
m->ValueType->WriteValue(ar,p->Key.GetChars(),static_cast<const void *>(&p->Value));
|
||||||
|
}
|
||||||
|
else if constexpr(std::is_same_v<typename M::KeyType,uint32_t>)
|
||||||
|
{
|
||||||
|
FString key;
|
||||||
|
key.Format("%u",p->Key);
|
||||||
|
m->ValueType->WriteValue(ar,key.GetChars(),static_cast<const void *>(&p->Value));
|
||||||
|
}
|
||||||
|
//else unknown key type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PMap::WriteValue(FSerializer &ar, const char *key, const void *addr) const
|
||||||
|
{
|
||||||
|
if(ar.BeginObject(key))
|
||||||
|
{
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case MAP_I32_I8:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, uint8_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_I16:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, uint16_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_I32:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, uint32_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_F32:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, float>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_F64:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, double>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_OBJ:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, DObject*>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_PTR:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, void*>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_STR:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, FString>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_I8:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, uint8_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_I16:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, uint16_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_I32:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, uint32_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_F32:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, float>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_F64:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, double>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_OBJ:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, DObject*>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_PTR:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, void*>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_STR:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, FString>*>(addr), this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ar.EndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: ReadValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M>
|
||||||
|
static bool PMapValueReader(FSerializer &ar, M *map, const PMap *m)
|
||||||
|
{
|
||||||
|
const char * k;
|
||||||
|
while(k = ar.GetKey())
|
||||||
|
{
|
||||||
|
typename M::ValueType * val;
|
||||||
|
if constexpr(std::is_same_v<typename M::KeyType,FString>)
|
||||||
|
{
|
||||||
|
val = &map->InsertNew(k);
|
||||||
|
}
|
||||||
|
else if constexpr(std::is_same_v<typename M::KeyType,uint32_t>)
|
||||||
|
{
|
||||||
|
FString s(k);
|
||||||
|
if(!s.IsInt())
|
||||||
|
{
|
||||||
|
ar.EndObject();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
val = &map->InsertNew(static_cast<uint32_t>(s.ToULong()));
|
||||||
|
}
|
||||||
|
if (!m->ValueType->ReadValue(ar,nullptr,static_cast<void*>(val)))
|
||||||
|
{
|
||||||
|
ar.EndObject();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ar.EndObject();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PMap::ReadValue(FSerializer &ar, const char *key, void *addr) const
|
||||||
|
{
|
||||||
|
DestroyValue(addr);
|
||||||
|
InitializeValue(addr, nullptr);
|
||||||
|
if(ar.BeginObject(key))
|
||||||
|
{
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case MAP_I32_I8:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, uint8_t>*>(addr), this);
|
||||||
|
case MAP_I32_I16:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, uint16_t>*>(addr), this);
|
||||||
|
case MAP_I32_I32:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, uint32_t>*>(addr), this);
|
||||||
|
case MAP_I32_F32:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, float>*>(addr), this);
|
||||||
|
case MAP_I32_F64:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, double>*>(addr), this);
|
||||||
|
case MAP_I32_OBJ:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, DObject*>*>(addr), this);
|
||||||
|
case MAP_I32_PTR:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, void*>*>(addr), this);
|
||||||
|
case MAP_I32_STR:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, FString>*>(addr), this);
|
||||||
|
case MAP_STR_I8:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, uint8_t>*>(addr), this);
|
||||||
|
case MAP_STR_I16:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, uint16_t>*>(addr), this);
|
||||||
|
case MAP_STR_I32:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, uint32_t>*>(addr), this);
|
||||||
|
case MAP_STR_F32:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, float>*>(addr), this);
|
||||||
|
case MAP_STR_F64:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, double>*>(addr), this);
|
||||||
|
case MAP_STR_OBJ:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, DObject*>*>(addr), this);
|
||||||
|
case MAP_STR_PTR:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, void*>*>(addr), this);
|
||||||
|
case MAP_STR_STR:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, FString>*>(addr), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// NewMap
|
// NewMap
|
||||||
|
@ -2245,16 +2685,330 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PMap *NewMap(PType *keytype, PType *valuetype)
|
int PMapBackingClass(PType *keytype, PType *valuetype, FString &backingName) {
|
||||||
|
int backingClass;
|
||||||
|
auto key_rtype = keytype->GetRegType();
|
||||||
|
auto value_rtype = valuetype->GetRegType();
|
||||||
|
if (key_rtype == REGT_INT)
|
||||||
|
{
|
||||||
|
if(keytype->Size != 4)
|
||||||
|
{
|
||||||
|
I_Error("Unsupported map requested");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backingName += "I32_";
|
||||||
|
backingClass = PMap::MAP_I32_I8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key_rtype == REGT_STRING)
|
||||||
|
{
|
||||||
|
backingName += "Str_";
|
||||||
|
backingClass = PMap::MAP_STR_I8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I_Error("Unsupported map requested");
|
||||||
|
}
|
||||||
|
switch (valuetype->GetRegType())
|
||||||
|
{
|
||||||
|
case REGT_INT:
|
||||||
|
backingName.AppendFormat("I%d", valuetype->Size * 8);
|
||||||
|
backingClass += (valuetype->Size >> 1);
|
||||||
|
break;
|
||||||
|
case REGT_FLOAT:
|
||||||
|
backingName.AppendFormat("F%d", valuetype->Size * 8);
|
||||||
|
backingClass += PMap::MAP_I32_F32 + (valuetype->Size == 8);
|
||||||
|
break;
|
||||||
|
case REGT_STRING:
|
||||||
|
backingName += "Str";
|
||||||
|
backingClass += PMap::MAP_I32_STR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGT_POINTER:
|
||||||
|
if (valuetype->isObjectPointer())
|
||||||
|
{
|
||||||
|
backingName += "Obj";
|
||||||
|
backingClass += PMap::MAP_I32_OBJ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backingName += "Ptr";
|
||||||
|
backingClass += PMap::MAP_I32_PTR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
I_Error("Unsupported map requested");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return backingClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
PMap *NewMap(PType *keyType, PType *valueType)
|
||||||
{
|
{
|
||||||
size_t bucket;
|
size_t bucket;
|
||||||
PType *maptype = TypeTable.FindType(NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, &bucket);
|
PType *mapType = TypeTable.FindType(NAME_Map, (intptr_t)keyType, (intptr_t)valueType, &bucket);
|
||||||
if (maptype == nullptr)
|
if (mapType == nullptr)
|
||||||
{
|
{
|
||||||
maptype = new PMap(keytype, valuetype);
|
FString backingName = "Map_";
|
||||||
TypeTable.AddType(maptype, NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, bucket);
|
int backingClass = PMapBackingClass(keyType, valueType, backingName);
|
||||||
|
|
||||||
|
auto backing = NewStruct(backingName, nullptr, true);
|
||||||
|
mapType = new PMap(keyType, valueType, backing, backingClass);
|
||||||
|
TypeTable.AddType(mapType, NAME_Map, (intptr_t)keyType, (intptr_t)valueType, bucket);
|
||||||
|
|
||||||
}
|
}
|
||||||
return (PMap *)maptype;
|
return (PMap *)mapType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PMap *******************************************************************/
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap - Parameterized Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PMapIterator::PMapIterator(PType *keytype, PType *valtype, PStruct *backing, int backing_class)
|
||||||
|
: KeyType(keytype), ValueType(valtype), BackingType(backing), BackingClass((decltype(BackingClass)) backing_class)
|
||||||
|
{
|
||||||
|
mDescriptiveName.Format("MapIterator<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName());
|
||||||
|
Size = sizeof(ZSFMap);
|
||||||
|
Align = alignof(ZSFMap);
|
||||||
|
CreateOverrideFunction<PMapIterator, OFN_RET_KEY, OFN_ARG_VOID>(this, NAME_GetKey);
|
||||||
|
CreateOverrideFunction<PMapIterator, OFN_RET_VAL, OFN_ARG_VOID>(this, NAME_GetValue);
|
||||||
|
CreateOverrideFunction<PMapIterator, OFN_RET_VOID, OFN_ARG_VAL>(this, NAME_SetValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: IsMatch
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool PMapIterator::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
|
{
|
||||||
|
const PType *keyty = (const PType *)id1;
|
||||||
|
const PType *valty = (const PType *)id2;
|
||||||
|
|
||||||
|
return keyty == KeyType && valty == ValueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: GetTypeIDs
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
|
{
|
||||||
|
id1 = (intptr_t)KeyType;
|
||||||
|
id2 = (intptr_t)ValueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: InitializeValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::Construct(void * addr) const {
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case PMap::MAP_I32_I8:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, uint8_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_I16:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, uint16_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_I32:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, uint32_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_F32:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, float>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_F64:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, double>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_OBJ:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, DObject*>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_PTR:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, void*>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_STR:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, FString>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I8:
|
||||||
|
new(addr) ZSMapIterator<FString, uint8_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I16:
|
||||||
|
new(addr) ZSMapIterator<FString, uint16_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I32:
|
||||||
|
new(addr) ZSMapIterator<FString, uint32_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_F32:
|
||||||
|
new(addr) ZSMapIterator<FString, float>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_F64:
|
||||||
|
new(addr) ZSMapIterator<FString, double>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_OBJ:
|
||||||
|
new(addr) ZSMapIterator<FString, DObject*>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_PTR:
|
||||||
|
new(addr) ZSMapIterator<FString, void*>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_STR:
|
||||||
|
new(addr) ZSMapIterator<FString, FString>();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PMapIterator::InitializeValue(void *addr, const void *def) const
|
||||||
|
{
|
||||||
|
if (def != nullptr)
|
||||||
|
{
|
||||||
|
I_Error("Map cannot have default values");
|
||||||
|
}
|
||||||
|
Construct(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: DestroyValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::DestroyValue(void *addr) const
|
||||||
|
{
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case PMap::MAP_I32_I8:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, uint8_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_I16:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, uint16_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_I32:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, uint32_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_F32:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, float>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_F64:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, double>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_OBJ:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, DObject*>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_PTR:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, void*>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_STR:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, FString>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I8:
|
||||||
|
static_cast<ZSMapIterator<FString, uint8_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I16:
|
||||||
|
static_cast<ZSMapIterator<FString, uint16_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I32:
|
||||||
|
static_cast<ZSMapIterator<FString, uint32_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_F32:
|
||||||
|
static_cast<ZSMapIterator<FString, float>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_F64:
|
||||||
|
static_cast<ZSMapIterator<FString, double>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_OBJ:
|
||||||
|
static_cast<ZSMapIterator<FString, DObject*>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_PTR:
|
||||||
|
static_cast<ZSMapIterator<FString, void*>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_STR:
|
||||||
|
static_cast<ZSMapIterator<FString, FString>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: SetDefaultValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special)
|
||||||
|
{
|
||||||
|
assert(!(base && special));
|
||||||
|
if (base != nullptr)
|
||||||
|
{
|
||||||
|
Construct(((uint8_t*)base)+offset);
|
||||||
|
}
|
||||||
|
if (special != nullptr)
|
||||||
|
{
|
||||||
|
special->Push(std::make_pair(this, offset));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I_Error("null special");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: WriteValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::WriteValue(FSerializer &ar, const char *key, const void *addr) const
|
||||||
|
{
|
||||||
|
ar.BeginObject(key);
|
||||||
|
ar.EndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: ReadValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool PMapIterator::ReadValue(FSerializer &ar, const char *key, void *addr) const
|
||||||
|
{
|
||||||
|
DestroyValue(addr);
|
||||||
|
InitializeValue(addr, nullptr);
|
||||||
|
ar.BeginObject(key);
|
||||||
|
ar.EndObject();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// NewMapIterator
|
||||||
|
//
|
||||||
|
// Returns a PMapIterator for the given key and value types, ensuring not to create
|
||||||
|
// duplicates.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PMapIterator *NewMapIterator(PType *keyType, PType *valueType)
|
||||||
|
{
|
||||||
|
size_t bucket;
|
||||||
|
PType *mapIteratorType = TypeTable.FindType(NAME_MapIterator, (intptr_t)keyType, (intptr_t)valueType, &bucket);
|
||||||
|
if (mapIteratorType == nullptr)
|
||||||
|
{
|
||||||
|
FString backingName = "MapIterator_";
|
||||||
|
int backingClass = PMapBackingClass(keyType, valueType, backingName);
|
||||||
|
|
||||||
|
auto backing = NewStruct(backingName, nullptr, true);
|
||||||
|
mapIteratorType = new PMapIterator(keyType, valueType, backing, backingClass);
|
||||||
|
TypeTable.AddType(mapIteratorType, NAME_MapIterator, (intptr_t)keyType, (intptr_t)valueType, bucket);
|
||||||
|
}
|
||||||
|
return (PMapIterator *)mapIteratorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PStruct ****************************************************************/
|
/* PStruct ****************************************************************/
|
||||||
|
@ -2333,6 +3087,26 @@ void PStruct::SetPointerArray(void *base, unsigned offset, TArray<size_t> *speci
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PStruct :: SetPointerMap
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PStruct::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *special)
|
||||||
|
{
|
||||||
|
auto it = Symbols.GetIterator();
|
||||||
|
PSymbolTable::MapType::Pair *pair;
|
||||||
|
while (it.NextPair(pair))
|
||||||
|
{
|
||||||
|
auto field = dyn_cast<PField>(pair->Value);
|
||||||
|
if (field && !(field->Flags & VARF_Transient))
|
||||||
|
{
|
||||||
|
field->Type->SetPointerMap(base, unsigned(offset + field->Offset), special);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PStruct :: WriteValue
|
// PStruct :: WriteValue
|
||||||
|
|
|
@ -129,6 +129,7 @@ public:
|
||||||
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL);
|
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL);
|
||||||
virtual void SetPointer(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
virtual void SetPointer(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
||||||
virtual void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
virtual void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
||||||
|
virtual void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs = NULL);
|
||||||
|
|
||||||
// Initialize the value, if needed (e.g. strings)
|
// Initialize the value, if needed (e.g. strings)
|
||||||
virtual void InitializeValue(void *addr, const void *def) const;
|
virtual void InitializeValue(void *addr, const void *def) const;
|
||||||
|
@ -200,6 +201,8 @@ public:
|
||||||
bool isArray() const { return !!(Flags & TYPE_Array); }
|
bool isArray() const { return !!(Flags & TYPE_Array); }
|
||||||
bool isStaticArray() const { return TypeTableType == NAME_StaticArray; }
|
bool isStaticArray() const { return TypeTableType == NAME_StaticArray; }
|
||||||
bool isDynArray() const { return TypeTableType == NAME_DynArray; }
|
bool isDynArray() const { return TypeTableType == NAME_DynArray; }
|
||||||
|
bool isMap() const { return TypeTableType == NAME_Map; }
|
||||||
|
bool isMapIterator() const { return TypeTableType == NAME_MapIterator; }
|
||||||
bool isStruct() const { return TypeTableType == NAME_Struct; }
|
bool isStruct() const { return TypeTableType == NAME_Struct; }
|
||||||
bool isClass() const { return TypeTableType == NAME_Object; }
|
bool isClass() const { return TypeTableType == NAME_Object; }
|
||||||
bool isPrototype() const { return TypeTableType == NAME_Prototype; }
|
bool isPrototype() const { return TypeTableType == NAME_Prototype; }
|
||||||
|
@ -489,6 +492,7 @@ public:
|
||||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) override;
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) override;
|
||||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) override;
|
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) override;
|
||||||
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) override;
|
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) override;
|
||||||
|
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs = NULL) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PStaticArray : public PArray
|
class PStaticArray : public PArray
|
||||||
|
@ -521,14 +525,72 @@ public:
|
||||||
|
|
||||||
class PMap : public PCompoundType
|
class PMap : public PCompoundType
|
||||||
{
|
{
|
||||||
|
void Construct(void * addr) const;
|
||||||
public:
|
public:
|
||||||
PMap(PType *keytype, PType *valtype);
|
PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class);
|
||||||
|
|
||||||
PType *KeyType;
|
PType *KeyType;
|
||||||
PType *ValueType;
|
PType *ValueType;
|
||||||
|
|
||||||
|
TMap<FName,PFunction*> FnOverrides;
|
||||||
|
|
||||||
|
PStruct *BackingType;
|
||||||
|
|
||||||
|
enum EBackingClass {
|
||||||
|
MAP_I32_I8,
|
||||||
|
MAP_I32_I16,
|
||||||
|
MAP_I32_I32,
|
||||||
|
MAP_I32_F32,
|
||||||
|
MAP_I32_F64,
|
||||||
|
MAP_I32_OBJ,
|
||||||
|
MAP_I32_PTR,
|
||||||
|
MAP_I32_STR,
|
||||||
|
|
||||||
|
MAP_STR_I8,
|
||||||
|
MAP_STR_I16,
|
||||||
|
MAP_STR_I32,
|
||||||
|
MAP_STR_F32,
|
||||||
|
MAP_STR_F64,
|
||||||
|
MAP_STR_OBJ,
|
||||||
|
MAP_STR_PTR,
|
||||||
|
MAP_STR_STR,
|
||||||
|
} BackingClass;
|
||||||
|
|
||||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
||||||
|
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
|
||||||
|
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
||||||
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
||||||
|
void InitializeValue(void *addr, const void *def) const override;
|
||||||
|
void DestroyValue(void *addr) const override;
|
||||||
|
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PMapIterator : public PCompoundType
|
||||||
|
{
|
||||||
|
void Construct(void * addr) const;
|
||||||
|
public:
|
||||||
|
PMapIterator(PType *keytype, PType *valtype, PStruct *backing, int backing_class);
|
||||||
|
|
||||||
|
PType *KeyType;
|
||||||
|
PType *ValueType;
|
||||||
|
|
||||||
|
TMap<FName,PFunction*> FnOverrides;
|
||||||
|
|
||||||
|
PStruct *BackingType;
|
||||||
|
|
||||||
|
PMap::EBackingClass BackingClass;
|
||||||
|
|
||||||
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
||||||
|
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
|
||||||
|
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
||||||
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
||||||
|
void InitializeValue(void *addr, const void *def) const override;
|
||||||
|
void DestroyValue(void *addr) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PStruct : public PContainerType
|
class PStruct : public PContainerType
|
||||||
|
@ -550,6 +612,7 @@ public:
|
||||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
||||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override;
|
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override;
|
||||||
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *special) override;
|
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *special) override;
|
||||||
|
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPrototype : public PCompoundType
|
class PPrototype : public PCompoundType
|
||||||
|
@ -586,6 +649,7 @@ inline PClass *PObjectPointer::PointedClass() const
|
||||||
|
|
||||||
// Returns a type from the TypeTable. Will create one if it isn't present.
|
// Returns a type from the TypeTable. Will create one if it isn't present.
|
||||||
PMap *NewMap(PType *keytype, PType *valuetype);
|
PMap *NewMap(PType *keytype, PType *valuetype);
|
||||||
|
PMapIterator *NewMapIterator(PType *keytype, PType *valuetype);
|
||||||
PArray *NewArray(PType *type, unsigned int count);
|
PArray *NewArray(PType *type, unsigned int count);
|
||||||
PStaticArray *NewStaticArray(PType *type);
|
PStaticArray *NewStaticArray(PType *type);
|
||||||
PDynArray *NewDynArray(PType *type);
|
PDynArray *NewDynArray(PType *type);
|
||||||
|
|
|
@ -502,6 +502,16 @@ static void PrintMapType(FLispString &out, const ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PrintMapIteratorType(FLispString &out, const ZCC_TreeNode *node)
|
||||||
|
{
|
||||||
|
ZCC_MapIteratorType *tnode = (ZCC_MapIteratorType *)node;
|
||||||
|
out.Open("map-iterator-type");
|
||||||
|
PrintNodes(out, tnode->ArraySize);
|
||||||
|
PrintNodes(out, tnode->KeyType);
|
||||||
|
PrintNodes(out, tnode->ValueType);
|
||||||
|
out.Close();
|
||||||
|
}
|
||||||
|
|
||||||
static void PrintDynArrayType(FLispString &out, const ZCC_TreeNode *node)
|
static void PrintDynArrayType(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_DynArrayType *tnode = (ZCC_DynArrayType *)node;
|
ZCC_DynArrayType *tnode = (ZCC_DynArrayType *)node;
|
||||||
|
@ -955,6 +965,7 @@ static const NodePrinterFunc TreeNodePrinter[] =
|
||||||
PrintType,
|
PrintType,
|
||||||
PrintBasicType,
|
PrintBasicType,
|
||||||
PrintMapType,
|
PrintMapType,
|
||||||
|
PrintMapIteratorType,
|
||||||
PrintDynArrayType,
|
PrintDynArrayType,
|
||||||
PrintClassType,
|
PrintClassType,
|
||||||
PrintExpression,
|
PrintExpression,
|
||||||
|
|
|
@ -932,7 +932,7 @@ type_name(X) ::= DOT dottable_id(A).
|
||||||
/* Type names can also be used as identifiers in contexts where type names
|
/* Type names can also be used as identifiers in contexts where type names
|
||||||
* are not normally allowed. */
|
* are not normally allowed. */
|
||||||
%fallback IDENTIFIER
|
%fallback IDENTIFIER
|
||||||
SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 VECTOR4 NAME MAP ARRAY VOID STATE COLOR SOUND UINT8 INT8 UINT16 INT16 PROPERTY.
|
SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 VECTOR4 NAME MAP MAPITERATOR ARRAY VOID STATE COLOR SOUND UINT8 INT8 UINT16 INT16 PROPERTY.
|
||||||
|
|
||||||
/* Aggregate types */
|
/* Aggregate types */
|
||||||
%type aggregate_type {ZCC_Type *}
|
%type aggregate_type {ZCC_Type *}
|
||||||
|
@ -944,7 +944,7 @@ type_name(X) ::= DOT dottable_id(A).
|
||||||
%type array_size{ZCC_Expression *}
|
%type array_size{ZCC_Expression *}
|
||||||
%type array_size_expr{ZCC_Expression *}
|
%type array_size_expr{ZCC_Expression *}
|
||||||
|
|
||||||
aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* Hash table */
|
aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMap<K, V> */
|
||||||
{
|
{
|
||||||
NEW_AST_NODE(MapType,map,T);
|
NEW_AST_NODE(MapType,map,T);
|
||||||
map->KeyType = A;
|
map->KeyType = A;
|
||||||
|
@ -952,6 +952,14 @@ aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* H
|
||||||
X = map;
|
X = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aggregate_type(X) ::= MAPITERATOR(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMapIterator<K, V> */
|
||||||
|
{
|
||||||
|
NEW_AST_NODE(MapIteratorType,map_it,T);
|
||||||
|
map_it->KeyType = A;
|
||||||
|
map_it->ValueType = B;
|
||||||
|
X = map_it;
|
||||||
|
}
|
||||||
|
|
||||||
aggregate_type(X) ::= ARRAY(T) LT type_or_array(A) GT. /* TArray<type> */
|
aggregate_type(X) ::= ARRAY(T) LT type_or_array(A) GT. /* TArray<type> */
|
||||||
{
|
{
|
||||||
NEW_AST_NODE(DynArrayType,arr,T);
|
NEW_AST_NODE(DynArrayType,arr,T);
|
||||||
|
|
|
@ -1853,16 +1853,96 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
||||||
}
|
}
|
||||||
|
|
||||||
case AST_MapType:
|
case AST_MapType:
|
||||||
if (allowarraytypes)
|
{
|
||||||
|
if(AST.ParseVersion < MakeVersion(4, 10, 0))
|
||||||
{
|
{
|
||||||
Error(field, "%s: Map types not implemented yet", name.GetChars());
|
Error(field, "Map not accessible to ZScript version %d.%d.%d", AST.ParseVersion.major, AST.ParseVersion.minor, AST.ParseVersion.revision);
|
||||||
// Todo: Decide what we allow here and if it makes sense to allow more complex constructs.
|
|
||||||
auto mtype = static_cast<ZCC_MapType *>(ztype);
|
|
||||||
retval = NewMap(DetermineType(outertype, field, name, mtype->KeyType, false, false), DetermineType(outertype, field, name, mtype->ValueType, false, false));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
|
// Todo: Decide what we allow here and if it makes sense to allow more complex constructs.
|
||||||
|
auto mtype = static_cast<ZCC_MapType *>(ztype);
|
||||||
|
|
||||||
|
auto keytype = DetermineType(outertype, field, name, mtype->KeyType, false, false);
|
||||||
|
auto valuetype = DetermineType(outertype, field, name, mtype->ValueType, false, false);
|
||||||
|
|
||||||
|
if (keytype->GetRegType() == REGT_INT)
|
||||||
|
{
|
||||||
|
if (keytype->Size != 4)
|
||||||
|
{
|
||||||
|
Error(field, "Map<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (keytype->GetRegType() != REGT_STRING)
|
||||||
|
{
|
||||||
|
Error(field, "Map<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(valuetype->GetRegType())
|
||||||
|
{
|
||||||
|
case REGT_FLOAT:
|
||||||
|
case REGT_INT:
|
||||||
|
case REGT_STRING:
|
||||||
|
case REGT_POINTER:
|
||||||
|
if (valuetype->GetRegCount() > 1)
|
||||||
|
{
|
||||||
|
Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = NewMap(keytype, valuetype);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error(field, "%s: Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AST_MapIteratorType:
|
||||||
|
{
|
||||||
|
if(AST.ParseVersion < MakeVersion(4, 10, 0))
|
||||||
|
{
|
||||||
|
Error(field, "MapIterator not accessible to ZScript version %d.%d.%d", AST.ParseVersion.major, AST.ParseVersion.minor, AST.ParseVersion.revision);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Todo: Decide what we allow here and if it makes sense to allow more complex constructs.
|
||||||
|
auto mtype = static_cast<ZCC_MapIteratorType *>(ztype);
|
||||||
|
|
||||||
|
auto keytype = DetermineType(outertype, field, name, mtype->KeyType, false, false);
|
||||||
|
auto valuetype = DetermineType(outertype, field, name, mtype->ValueType, false, false);
|
||||||
|
|
||||||
|
if (keytype->GetRegType() == REGT_INT)
|
||||||
|
{
|
||||||
|
if (keytype->Size != 4)
|
||||||
|
{
|
||||||
|
Error(field, "MapIterator<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (keytype->GetRegType() != REGT_STRING)
|
||||||
|
{
|
||||||
|
Error(field, "MapIterator<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(valuetype->GetRegType())
|
||||||
|
{
|
||||||
|
case REGT_FLOAT:
|
||||||
|
case REGT_INT:
|
||||||
|
case REGT_STRING:
|
||||||
|
case REGT_POINTER:
|
||||||
|
if (valuetype->GetRegCount() > 1)
|
||||||
|
{
|
||||||
|
Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
retval = NewMapIterator(keytype, valuetype);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error(field, "%s: Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case AST_DynArrayType:
|
case AST_DynArrayType:
|
||||||
{
|
{
|
||||||
auto atype = static_cast<ZCC_DynArrayType *>(ztype);
|
auto atype = static_cast<ZCC_DynArrayType *>(ztype);
|
||||||
|
@ -2357,7 +2437,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
{
|
{
|
||||||
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if ((type->isStruct() && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) || type->isDynArray())
|
if ((type->isStruct() && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) || type->isDynArray() || type->isMap() || type->isMapIterator())
|
||||||
{
|
{
|
||||||
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
|
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
|
||||||
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
|
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
|
||||||
|
|
|
@ -220,6 +220,7 @@ static void InitTokenMap()
|
||||||
TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3);
|
TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3);
|
||||||
TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name);
|
TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name);
|
||||||
TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map);
|
TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map);
|
||||||
|
TOKENDEF2(TK_MapIterator, ZCC_MAPITERATOR,NAME_MapIterator);
|
||||||
TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array);
|
TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array);
|
||||||
TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include);
|
TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include);
|
||||||
TOKENDEF (TK_Void, ZCC_VOID);
|
TOKENDEF (TK_Void, ZCC_VOID);
|
||||||
|
@ -896,6 +897,19 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AST_MapIteratorType:
|
||||||
|
{
|
||||||
|
TreeNodeDeepCopy_Start(MapIteratorType);
|
||||||
|
|
||||||
|
// ZCC_Type
|
||||||
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
||||||
|
// AST_MapIteratorType
|
||||||
|
copy->KeyType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->KeyType, true, copiedNodesList));
|
||||||
|
copy->ValueType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->ValueType, true, copiedNodesList));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AST_DynArrayType:
|
case AST_DynArrayType:
|
||||||
{
|
{
|
||||||
TreeNodeDeepCopy_Start(DynArrayType);
|
TreeNodeDeepCopy_Start(DynArrayType);
|
||||||
|
|
|
@ -98,6 +98,7 @@ enum EZCCTreeNodeType
|
||||||
AST_Type,
|
AST_Type,
|
||||||
AST_BasicType,
|
AST_BasicType,
|
||||||
AST_MapType,
|
AST_MapType,
|
||||||
|
AST_MapIteratorType,
|
||||||
AST_DynArrayType,
|
AST_DynArrayType,
|
||||||
AST_ClassType,
|
AST_ClassType,
|
||||||
AST_Expression,
|
AST_Expression,
|
||||||
|
@ -367,6 +368,12 @@ struct ZCC_MapType : ZCC_Type
|
||||||
ZCC_Type *ValueType;
|
ZCC_Type *ValueType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ZCC_MapIteratorType : ZCC_Type
|
||||||
|
{
|
||||||
|
ZCC_Type *KeyType;
|
||||||
|
ZCC_Type *ValueType;
|
||||||
|
};
|
||||||
|
|
||||||
struct ZCC_DynArrayType : ZCC_Type
|
struct ZCC_DynArrayType : ZCC_Type
|
||||||
{
|
{
|
||||||
ZCC_Type *ElementType;
|
ZCC_Type *ElementType;
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
bool gameisdead;
|
bool gameisdead;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include <cstdarg>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "zstring.h"
|
#include "zstring.h"
|
||||||
void I_DebugPrint(const char *cp)
|
void I_DebugPrint(const char *cp)
|
||||||
|
@ -46,10 +47,31 @@ void I_DebugPrint(const char *cp)
|
||||||
OutputDebugStringW(wstr.c_str());
|
OutputDebugStringW(wstr.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_DebugPrintf(const char *fmt,...)
|
||||||
|
{
|
||||||
|
if (IsDebuggerPresent())
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
FString s;
|
||||||
|
s.VFormat(fmt, args);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
auto wstr = WideString(s);
|
||||||
|
OutputDebugStringW(wstr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
void I_DebugPrint(const char *cp)
|
void I_DebugPrint(const char *cp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_DebugPrintf(const char *fmt,...)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "engineerrors.h"
|
#include "engineerrors.h"
|
||||||
|
|
|
@ -916,6 +916,9 @@ public:
|
||||||
typedef struct { const KT Key; VT Value; } Pair;
|
typedef struct { const KT Key; VT Value; } Pair;
|
||||||
typedef const Pair ConstPair;
|
typedef const Pair ConstPair;
|
||||||
|
|
||||||
|
typedef KT KeyType;
|
||||||
|
typedef VT ValueType;
|
||||||
|
|
||||||
TMap() { NumUsed = 0; SetNodeVector(1); }
|
TMap() { NumUsed = 0; SetNodeVector(1); }
|
||||||
TMap(hash_t size) { NumUsed = 0; SetNodeVector(size); }
|
TMap(hash_t size) { NumUsed = 0; SetNodeVector(size); }
|
||||||
~TMap() { ClearNodeVector(); }
|
~TMap() { ClearNodeVector(); }
|
||||||
|
|
|
@ -3,6 +3,7 @@ version "4.10"
|
||||||
// Generic engine code
|
// Generic engine code
|
||||||
#include "zscript/engine/base.zs"
|
#include "zscript/engine/base.zs"
|
||||||
#include "zscript/engine/dynarrays.zs"
|
#include "zscript/engine/dynarrays.zs"
|
||||||
|
#include "zscript/engine/maps.zs"
|
||||||
#include "zscript/engine/dictionary.zs"
|
#include "zscript/engine/dictionary.zs"
|
||||||
#include "zscript/engine/inputevents.zs"
|
#include "zscript/engine/inputevents.zs"
|
||||||
#include "zscript/engine/service.zs"
|
#include "zscript/engine/service.zs"
|
||||||
|
|
447
wadsrc/static/zscript/engine/maps.zs
Normal file
447
wadsrc/static/zscript/engine/maps.zs
Normal file
|
@ -0,0 +1,447 @@
|
||||||
|
|
||||||
|
struct Map_I32_I8 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_I8 other);
|
||||||
|
native void Move(Map_I32_I8 other);
|
||||||
|
native void Swap(Map_I32_I8 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,int value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_I8 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_I8 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_I16 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_I16 other);
|
||||||
|
native void Move(Map_I32_I16 other);
|
||||||
|
native void Swap(Map_I32_I16 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,int value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_I16 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_I16 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_I32 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_I32 other);
|
||||||
|
native void Move(Map_I32_I32 other);
|
||||||
|
native void Swap(Map_I32_I32 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,int value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_I32 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_I32 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_F32 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_F32 other);
|
||||||
|
native void Move(Map_I32_F32 other);
|
||||||
|
native void Swap(Map_I32_F32 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native double Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,double value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_F32 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_F32 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native double GetValue();
|
||||||
|
native void SetValue(double value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_F64 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_F64 other);
|
||||||
|
native void Move(Map_I32_F64 other);
|
||||||
|
native void Swap(Map_I32_F64 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native double Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,double value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_F64 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_F64 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native double GetValue();
|
||||||
|
native void SetValue(double value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_Obj native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_Obj other);
|
||||||
|
native void Move(Map_I32_Obj other);
|
||||||
|
native void Swap(Map_I32_Obj other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native Object Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,Object value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_Obj native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_Obj other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native Object GetValue();
|
||||||
|
native void SetValue(Object value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_Ptr native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_Ptr other);
|
||||||
|
native void Move(Map_I32_Ptr other);
|
||||||
|
native void Swap(Map_I32_Ptr other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native voidptr Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,voidptr value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_Ptr native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_Ptr other);
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native voidptr GetValue();
|
||||||
|
native void SetValue(voidptr value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_Str native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_Str other);
|
||||||
|
native void Move(Map_I32_Str other);
|
||||||
|
native void Swap(Map_I32_Str other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native String Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,String value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_Str native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_Str other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native String GetValue();
|
||||||
|
native void SetValue(String value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
struct Map_Str_I8 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_I8 other);
|
||||||
|
native void Move(Map_Str_I8 other);
|
||||||
|
native void Swap(Map_Str_I8 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,int value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_I8 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_I8 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_I16 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_I16 other);
|
||||||
|
native void Move(Map_Str_I16 other);
|
||||||
|
native void Swap(Map_Str_I16 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,int value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_I16 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_I16 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_I32 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_I32 other);
|
||||||
|
native void Move(Map_Str_I32 other);
|
||||||
|
native void Swap(Map_Str_I32 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,int value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_I32 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_I32 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_F32 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_F32 other);
|
||||||
|
native void Move(Map_Str_F32 other);
|
||||||
|
native void Swap(Map_Str_F32 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native double Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,double value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_F32 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_F32 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native double GetValue();
|
||||||
|
native void SetValue(double value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_F64 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_F64 other);
|
||||||
|
native void Move(Map_Str_F64 other);
|
||||||
|
native void Swap(Map_Str_F64 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native double Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,double value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_F64 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_F64 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native double GetValue();
|
||||||
|
native void SetValue(double value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_Obj native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_Obj other);
|
||||||
|
native void Move(Map_Str_Obj other);
|
||||||
|
native void Swap(Map_Str_Obj other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native Object Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,Object value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_Obj native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_Obj other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native Object GetValue();
|
||||||
|
native void SetValue(Object value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_Ptr native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_Ptr other);
|
||||||
|
native void Move(Map_Str_Ptr other);
|
||||||
|
native void Swap(Map_Str_Ptr other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native voidptr Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,voidptr value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_Ptr native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_Ptr other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native voidptr GetValue();
|
||||||
|
native void SetValue(voidptr value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_Str native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_Str other);
|
||||||
|
native void Move(Map_Str_Str other);
|
||||||
|
native void Swap(Map_Str_Str other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native String Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,String value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_Str native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_Str other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native String GetValue();
|
||||||
|
native void SetValue(String value);
|
||||||
|
}
|
Loading…
Reference in a new issue