- dictionary can also go to 'common'.
This commit is contained in:
parent
f6bd2e4f76
commit
1ce11ff02a
4 changed files with 50 additions and 46 deletions
218
src/common/scripting/core/dictionary.cpp
Normal file
218
src/common/scripting/core/dictionary.cpp
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
#include "dictionary.h"
|
||||
|
||||
#include "vm.h"
|
||||
#include "serializer.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
//=====================================================================================
|
||||
//
|
||||
// DObject implementations for Dictionary and DictionaryIterator
|
||||
//
|
||||
//=====================================================================================
|
||||
|
||||
IMPLEMENT_CLASS(Dictionary, false, false);
|
||||
|
||||
IMPLEMENT_CLASS(DictionaryIterator, false, true);
|
||||
|
||||
IMPLEMENT_POINTERS_START(DictionaryIterator)
|
||||
IMPLEMENT_POINTER(Dict)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
//=====================================================================================
|
||||
//
|
||||
// Dictionary functions
|
||||
//
|
||||
//=====================================================================================
|
||||
|
||||
void Dictionary::Serialize(FSerializer &arc)
|
||||
{
|
||||
Super::Serialize(arc);
|
||||
|
||||
constexpr char key[] { "dictionary" };
|
||||
|
||||
if (arc.isWriting())
|
||||
{
|
||||
// Pass this instance to serializer.
|
||||
Dictionary *pointerToThis = this;
|
||||
arc(key, pointerToThis);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Receive new Dictionary, copy contents, clean up.
|
||||
Dictionary *pointerToDeserializedDictionary;
|
||||
arc(key, pointerToDeserializedDictionary);
|
||||
Map.TransferFrom(pointerToDeserializedDictionary->Map);
|
||||
delete pointerToDeserializedDictionary;
|
||||
}
|
||||
}
|
||||
|
||||
static Dictionary *DictCreate()
|
||||
{
|
||||
Dictionary *dict { Create<Dictionary>() };
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
static void DictInsert(Dictionary *dict, const FString &key, const FString &value)
|
||||
{
|
||||
dict->Map.Insert(key, value);
|
||||
}
|
||||
|
||||
static void DictAt(const Dictionary *dict, const FString &key, FString *result)
|
||||
{
|
||||
const FString *value = dict->Map.CheckKey(key);
|
||||
*result = value ? *value : "";
|
||||
}
|
||||
|
||||
static void DictToString(const Dictionary *dict, FString *result)
|
||||
{
|
||||
*result = DictionaryToString(*dict);
|
||||
}
|
||||
|
||||
static void DictRemove(Dictionary *dict, const FString &key)
|
||||
{
|
||||
dict->Map.Remove(key);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
//
|
||||
// Dictionary exports
|
||||
//
|
||||
//=====================================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Create, DictCreate)
|
||||
{
|
||||
ACTION_RETURN_POINTER(DictCreate());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Insert, DictInsert)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(Dictionary);
|
||||
PARAM_STRING(key);
|
||||
PARAM_STRING(value);
|
||||
DictInsert(self, key, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, At, DictAt)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(Dictionary);
|
||||
PARAM_STRING(key);
|
||||
FString result;
|
||||
DictAt(self, key, &result);
|
||||
ACTION_RETURN_STRING(result);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, ToString, DictToString)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(Dictionary);
|
||||
FString result;
|
||||
DictToString(self, &result);
|
||||
ACTION_RETURN_STRING(result);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, FromString, DictionaryFromString)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(string);
|
||||
ACTION_RETURN_POINTER(DictionaryFromString(string));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Remove, DictRemove)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(Dictionary);
|
||||
PARAM_STRING(key);
|
||||
DictRemove(self, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
//
|
||||
// DictionaryIterator functions
|
||||
//
|
||||
//=====================================================================================
|
||||
|
||||
DictionaryIterator::DictionaryIterator()
|
||||
: Iterator(nullptr)
|
||||
, Pair(nullptr)
|
||||
, Dict(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void DictionaryIterator::Serialize(FSerializer &arc)
|
||||
{
|
||||
if (arc.isWriting())
|
||||
{
|
||||
I_Error("Attempt to save pointer to unhandled type DictionaryIterator");
|
||||
}
|
||||
}
|
||||
|
||||
void DictionaryIterator::init(Dictionary *dict)
|
||||
{
|
||||
Iterator = std::make_unique<Dictionary::ConstIterator>(dict->Map);
|
||||
Dict = dict;
|
||||
|
||||
GC::WriteBarrier(this, Dict);
|
||||
}
|
||||
|
||||
static DictionaryIterator *DictIteratorCreate(Dictionary *dict)
|
||||
{
|
||||
DictionaryIterator *iterator = Create<DictionaryIterator>();
|
||||
iterator->init(dict);
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
static int DictIteratorNext(DictionaryIterator *self)
|
||||
{
|
||||
assert(self->Iterator != nullptr);
|
||||
|
||||
const bool hasNext { self->Iterator->NextPair(self->Pair) };
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
static void DictIteratorKey(const DictionaryIterator *self, FString *result)
|
||||
{
|
||||
*result = self->Pair ? self->Pair->Key : FString {};
|
||||
}
|
||||
|
||||
static void DictIteratorValue(const DictionaryIterator *self, FString *result)
|
||||
{
|
||||
*result = self->Pair ? self->Pair->Value : FString {};
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
//
|
||||
// DictionaryIterator exports
|
||||
//
|
||||
//=====================================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Create, DictIteratorCreate)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_POINTER(dict, Dictionary);
|
||||
ACTION_RETURN_POINTER(DictIteratorCreate(dict));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Next, DictIteratorNext)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(DictionaryIterator);
|
||||
ACTION_RETURN_BOOL(DictIteratorNext(self));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Key, DictIteratorKey)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(DictionaryIterator);
|
||||
FString result;
|
||||
DictIteratorKey(self, &result);
|
||||
ACTION_RETURN_STRING(result);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Value, DictIteratorValue)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(DictionaryIterator);
|
||||
FString result;
|
||||
DictIteratorValue(self, &result);
|
||||
ACTION_RETURN_STRING(result);
|
||||
}
|
||||
70
src/common/scripting/core/dictionary.h
Normal file
70
src/common/scripting/core/dictionary.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
#include "zstring.h"
|
||||
#include "dobject.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* @brief The Dictionary class exists to be exported to ZScript.
|
||||
*
|
||||
* It is a string-to-string map.
|
||||
*
|
||||
* It is derived from DObject to be a part of normal GC process.
|
||||
*/
|
||||
class Dictionary final : public DObject
|
||||
{
|
||||
DECLARE_CLASS(Dictionary, DObject)
|
||||
|
||||
public:
|
||||
|
||||
using StringMap = TMap<FString, FString>;
|
||||
using ConstIterator = StringMap::ConstIterator;
|
||||
using ConstPair = StringMap::ConstPair;
|
||||
|
||||
void Serialize(FSerializer &arc) override;
|
||||
|
||||
StringMap Map;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The DictionaryIterator class exists to be exported to ZScript.
|
||||
*
|
||||
* It provides iterating over a Dictionary. The order is not specified.
|
||||
*
|
||||
* It is derived from DObject to be a part of normal GC process.
|
||||
*/
|
||||
class DictionaryIterator final : public DObject
|
||||
{
|
||||
DECLARE_CLASS(DictionaryIterator, DObject)
|
||||
HAS_OBJECT_POINTERS
|
||||
|
||||
public:
|
||||
|
||||
~DictionaryIterator() override = default;
|
||||
|
||||
/**
|
||||
* IMPLEMENT_CLASS macro needs a constructor without parameters.
|
||||
*
|
||||
* @see init().
|
||||
*/
|
||||
DictionaryIterator();
|
||||
|
||||
void Serialize(FSerializer &arc) override;
|
||||
|
||||
/**
|
||||
* @brief init function complements constructor.
|
||||
* @attention always call init after constructing DictionaryIterator.
|
||||
*/
|
||||
void init(Dictionary *dict);
|
||||
|
||||
std::unique_ptr<Dictionary::ConstIterator> Iterator;
|
||||
Dictionary::ConstPair *Pair;
|
||||
|
||||
/**
|
||||
* @brief Dictionary attribute exists for holding a pointer to iterated
|
||||
* dictionary, so it is known by GC.
|
||||
*/
|
||||
Dictionary *Dict;
|
||||
};
|
||||
|
|
@ -39,8 +39,6 @@
|
|||
#include "printf.h"
|
||||
#include "textureid.h"
|
||||
#include "version.h"
|
||||
#include "info.h"
|
||||
#include "serializer_doom.h"
|
||||
|
||||
|
||||
FTypeTable TypeTable;
|
||||
|
|
@ -1439,49 +1437,6 @@ PPointer *NewPointer(PClass *cls, bool isconst)
|
|||
return static_cast<PPointer *>(ptype);
|
||||
}
|
||||
|
||||
/* PStatePointer **********************************************************/
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer Default Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PStatePointer::PStatePointer()
|
||||
{
|
||||
mDescriptiveName = "Pointer<State>";
|
||||
PointedType = NewStruct(NAME_State, nullptr, true);
|
||||
IsConst = true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer :: WriteValue
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PStatePointer::WriteValue(FSerializer &ar, const char *key, const void *addr) const
|
||||
{
|
||||
#ifdef GZDOOM
|
||||
ar(key, *(FState **)addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer :: ReadValue
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) const
|
||||
{
|
||||
bool res = false;
|
||||
#ifdef GZDOOM
|
||||
::Serialize(ar, key, *(FState **)addr, nullptr, &res);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* PClassPointer **********************************************************/
|
||||
|
|
@ -2569,3 +2524,52 @@ CCMD(typetable)
|
|||
DumpTypeTable();
|
||||
}
|
||||
|
||||
// fixme: The VM depends on this but it's engine specific. Needs a better solution.
|
||||
|
||||
/* PStatePointer **********************************************************/
|
||||
#ifdef GZDOOM
|
||||
#include "info.h"
|
||||
#include "serializer_doom.h"
|
||||
#endif
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer Default Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PStatePointer::PStatePointer()
|
||||
{
|
||||
mDescriptiveName = "Pointer<State>";
|
||||
PointedType = NewStruct(NAME_State, nullptr, true);
|
||||
IsConst = true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer :: WriteValue
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PStatePointer::WriteValue(FSerializer& ar, const char* key, const void* addr) const
|
||||
{
|
||||
#ifdef GZDOOM
|
||||
ar(key, *(FState**)addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer :: ReadValue
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PStatePointer::ReadValue(FSerializer& ar, const char* key, void* addr) const
|
||||
{
|
||||
bool res = false;
|
||||
#ifdef GZDOOM
|
||||
::Serialize(ar, key, *(FState**)addr, nullptr, &res);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue