mirror of
https://github.com/ZDoom/Raze.git
synced 2025-05-30 00:41:24 +00:00
- backend update from GZDoom.
This commit is contained in:
parent
4666c4a4b5
commit
1061e3e2ca
31 changed files with 2760 additions and 116 deletions
483
source/common/scripting/core/maps.cpp
Normal file
483
source/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
source/common/scripting/core/maps.h
Normal file
110
source/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 "s_soundinternal.h"
|
||||
#include "types.h"
|
||||
#include "printf.h"
|
||||
#include "textureid.h"
|
||||
#include "maps.h"
|
||||
|
||||
|
||||
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
|
||||
|
@ -1862,7 +1869,7 @@ void PArray::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
|
|||
|
||||
void PArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *special)
|
||||
{
|
||||
if (ElementType->isStruct())
|
||||
if (ElementType->isStruct() || ElementType->isDynArray())
|
||||
{
|
||||
for (unsigned int i = 0; i < ElementCount; ++i)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -2202,12 +2226,89 @@ PDynArray *NewDynArray(PType *type)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PMap::PMap(PType *keytype, PType *valtype)
|
||||
: KeyType(keytype), ValueType(valtype)
|
||||
enum OverrideFunctionRetType {
|
||||
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());
|
||||
Size = sizeof(FMap);
|
||||
Align = alignof(FMap);
|
||||
Size = sizeof(ZSFMap);
|
||||
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;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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
|
||||
|
@ -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;
|
||||
PType *maptype = TypeTable.FindType(NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, &bucket);
|
||||
if (maptype == nullptr)
|
||||
PType *mapType = TypeTable.FindType(NAME_Map, (intptr_t)keyType, (intptr_t)valueType, &bucket);
|
||||
if (mapType == nullptr)
|
||||
{
|
||||
maptype = new PMap(keytype, valuetype);
|
||||
TypeTable.AddType(maptype, NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, bucket);
|
||||
FString backingName = "Map_";
|
||||
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 ****************************************************************/
|
||||
|
@ -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
|
||||
|
|
|
@ -129,6 +129,7 @@ public:
|
|||
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 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)
|
||||
virtual void InitializeValue(void *addr, const void *def) const;
|
||||
|
@ -200,6 +201,8 @@ public:
|
|||
bool isArray() const { return !!(Flags & TYPE_Array); }
|
||||
bool isStaticArray() const { return TypeTableType == NAME_StaticArray; }
|
||||
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 isClass() const { return TypeTableType == NAME_Object; }
|
||||
bool isPrototype() const { return TypeTableType == NAME_Prototype; }
|
||||
|
@ -489,6 +492,7 @@ public:
|
|||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *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 SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs = NULL) override;
|
||||
};
|
||||
|
||||
class PStaticArray : public PArray
|
||||
|
@ -521,14 +525,72 @@ public:
|
|||
|
||||
class PMap : public PCompoundType
|
||||
{
|
||||
void Construct(void * addr) const;
|
||||
public:
|
||||
PMap(PType *keytype, PType *valtype);
|
||||
PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class);
|
||||
|
||||
PType *KeyType;
|
||||
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 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
|
||||
|
@ -550,6 +612,7 @@ public:
|
|||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *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 SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs) override;
|
||||
};
|
||||
|
||||
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.
|
||||
PMap *NewMap(PType *keytype, PType *valuetype);
|
||||
PMapIterator *NewMapIterator(PType *keytype, PType *valuetype);
|
||||
PArray *NewArray(PType *type, unsigned int count);
|
||||
PStaticArray *NewStaticArray(PType *type);
|
||||
PDynArray *NewDynArray(PType *type);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue