Files
2026-02-02 04:50:13 +01:00

339 lines
15 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#ifndef HPL_SERIALIZE_CLASS_H
#define HPL_SERIALIZE_CLASS_H
#include "hpl1/engine/system/MemoryManager.h"
#include "hpl1/engine/system/SystemTypes.h"
#include "hpl1/static_string.h"
#include "common/stablemap.h"
class TiXmlElement;
namespace hpl {
/////////////////////////////////////////////////
//// ENGINE VALUE TYPES ///////////////////////////////
/////////////////////////////////////////////////
typedef unsigned int eSerializeType;
#define eSerializeType_Bool (1)
#define eSerializeType_Int32 (2)
#define eSerializeType_Float32 (3)
#define eSerializeType_String (4)
#define eSerializeType_Vector2l (5)
#define eSerializeType_Vector2f (6)
#define eSerializeType_Vector3l (7)
#define eSerializeType_Vector3f (8)
#define eSerializeType_Matrixf (9)
#define eSerializeType_Color (10)
#define eSerializeType_Rect2l (11)
#define eSerializeType_Rect2f (12)
#define eSerializeType_Planef (13)
#define eSerializeType_WString (14)
#define eSerializeType_Class (100)
// Important with this type is that it will only be created
// if the member variable is NULL. Else it is assume that it is
// already created.
// Also, for the class to be a class pointer it has to have a
// constructor without any parameters.
// NULL Values are NOT allowed!
#define eSerializeType_ClassPointer (101)
// User defined types must be after this
#define eSerializeType_Last (200)
#define eSerializeType_NULL (0xFFFF)
/////////////////////////////////////////////////
//// ENGINE MAIN TYPES //////////////////////////
/////////////////////////////////////////////////
typedef unsigned int eSerializeMainType;
#define eSerializeMainType_Variable (1)
#define eSerializeMainType_Array (2)
#define eSerializeMainType_Container (3)
#define eSerializeMainType_NULL (0xFFFF)
/////////////////////////////////////////////////
//// HELPER DEFINES /////////////////////////////
/////////////////////////////////////////////////
#define ClassMemberOffset(aClass, aMember) (size_t(&(((aClass *)1)->aMember)) - 1)
#define ClassMemberSize(aClass, aMember) (sizeof(((aClass *)1)->aMember))
/**
* This inits a class and must be first in a serializable class
*/
#define kSerializableClassInit(aClass) \
public: \
const static char *msSerialize_Name; \
const static char *msSerialize_ParentName; \
static cSerializeMemberField *mpSerialize_MemberFields; \
virtual ~aClass() = default; \
virtual tString Serialize_GetTopClass() { return #aClass; }
#define kSerializableClassInit_nodestructor(aClass) \
public: \
const static char *msSerialize_Name; \
const static char *msSerialize_ParentName; \
static cSerializeMemberField *mpSerialize_MemberFields; \
virtual tString Serialize_GetTopClass() { return #aClass; }
/**
* Declared in the cpp-file of the class to be serialized. Class must have parent!
*/
#define kBeginSerialize(aClass, aParent) \
namespace SerializeNamespace_##aClass { \
extern cSerializeMemberField mvTempMemberFields[]; \
} \
const char *aClass::msSerialize_Name = #aClass; \
const char *aClass::msSerialize_ParentName = #aParent; \
cSerializeMemberField *aClass::mpSerialize_MemberFields = SerializeNamespace_##aClass::mvTempMemberFields; \
namespace SerializeNamespace_##aClass { \
typedef aClass tVarClass; \
cSerializeMemberField mvTempMemberFields[] = {
#define kBeginSerializeBase(aClass) \
namespace SerializeNamespace_##aClass { \
extern cSerializeMemberField mvTempMemberFields[]; \
} \
const char *aClass::msSerialize_Name = #aClass; \
const char *aClass::msSerialize_ParentName = ""; \
cSerializeMemberField *aClass::mpSerialize_MemberFields = SerializeNamespace_##aClass::mvTempMemberFields; \
namespace SerializeNamespace_##aClass { \
typedef aClass tVarClass; \
cSerializeMemberField mvTempMemberFields[] = {
#define kBeginSerializeVirtual(aClass, aParent) \
namespace SerializeNamespace_##aClass { \
extern cSerializeMemberField mvTempMemberFields[]; \
} \
const char *aClass::msSerialize_Name = #aClass; \
const char *aClass::msSerialize_ParentName = #aParent; \
cSerializeMemberField *aClass::mpSerialize_MemberFields = SerializeNamespace_##aClass::mvTempMemberFields; \
namespace SerializeNamespace_##aClass { \
typedef aClass tVarClass; \
cSerializeMemberField mvTempMemberFields[] = {
#define kBeginSerializeBaseVirtual(aClass) \
namespace SerializeNamespace_##aClass { \
extern cSerializeMemberField mvTempMemberFields[]; \
} \
const char *aClass::msSerialize_Name = #aClass; \
const char *aClass::msSerialize_ParentName = ""; \
cSerializeMemberField *aClass::mpSerialize_MemberFields = SerializeNamespace_##aClass::mvTempMemberFields; \
namespace SerializeNamespace_##aClass { \
typedef aClass tVarClass; \
cSerializeMemberField mvTempMemberFields[] = {
/**
*Declared when all variable declarations are over.
*/
#define kEndSerialize() \
cSerializeMemberField("", 0, 0, eSerializeType_NULL, 0) \
} \
; \
}
/**
* Declared after begin, adds a variable or class.
*/
#define kSerializeVar(aVar, aType) \
cSerializeMemberField(#aVar, ClassMemberOffset(tVarClass, aVar), ClassMemberSize(tVarClass, aVar), aType, eSerializeMainType_Variable),
/**
* Declared after begin, adds an array of variables.
*/
#define kSerializeVarArray(aVar, aType, aArraySize) \
cSerializeMemberField(#aVar, ClassMemberOffset(tVarClass, aVar), ClassMemberSize(tVarClass, aVar), aType, eSerializeMainType_Array, aArraySize),
/**
* Declared after begin, adds an container of variables.
*/
#define kSerializeVarContainer(aVar, aType) \
cSerializeMemberField(#aVar, ClassMemberOffset(tVarClass, aVar), ClassMemberSize(tVarClass, aVar), aType, eSerializeMainType_Container),
/**
* Declared after begin, adds an container of classes.
*/
#define kSerializeClassContainer(aVar, aClass, aType) \
cSerializeMemberField(#aVar, ClassMemberOffset(tVarClass, aVar), ClassMemberSize(tVarClass, aVar), aType, eSerializeMainType_Container, #aClass),
/////////////////////////////////////////////////
//// CLASSES ////////////////////////////////////
/////////////////////////////////////////////////
//-------------------------------------------------
class cSerializeMemberField {
public:
constexpr cSerializeMemberField(Hpl1::StaticString asName, size_t alOffset, size_t alSize, eSerializeType alType,
eSerializeMainType aMainType) : msName(asName), msClassName(""), mlOffset(alOffset), mlSize(alSize), mType(alType), mMainType(aMainType), mlArraySize(0) {
}
constexpr cSerializeMemberField(Hpl1::StaticString asName, size_t alOffset, size_t alSize, eSerializeType alType,
eSerializeMainType aMainType, size_t alArraySize) : msName(asName), msClassName(""), mlOffset(alOffset), mlSize(alSize), mType(alType), mMainType(aMainType), mlArraySize(alArraySize) {
}
constexpr cSerializeMemberField(Hpl1::StaticString asName, size_t alOffset, size_t alSize, eSerializeType alType,
eSerializeMainType aMainType, Hpl1::StaticString asClassName) : msName(asName), msClassName(asClassName), mlOffset(alOffset), mlSize(alSize), mType(alType), mMainType(aMainType), mlArraySize(0) {
}
Hpl1::StaticString msName;
Hpl1::StaticString msClassName;
size_t mlOffset;
size_t mlSize;
eSerializeType mType;
eSerializeMainType mMainType;
size_t mlArraySize;
};
//-------------------------------------------------
class iSerializable {
public:
virtual ~iSerializable() = default;
virtual tString Serialize_GetTopClass() { return ""; }
};
//-------------------------------------------------
class iSerializableType {
public:
virtual ~iSerializableType() = default;
virtual char *ValueToString(void *apVal) = 0;
virtual void ValueFromString(char *apString, void *apVal) = 0;
};
//-------------------------------------------------
struct cSerializeSavedClass {
public:
constexpr cSerializeSavedClass() = default;
constexpr cSerializeSavedClass(const char *asName, const char *asParent,
cSerializeMemberField *apMemberFields, size_t alSize,
iSerializable *(*apCreateFunc)()) : msName(asName), msParentName(asParent), mpMemberFields(apMemberFields),
mlSize(alSize), mpCreateFunc(apCreateFunc) {}
const char *msName = "";
const char *msParentName = "";
cSerializeMemberField *mpMemberFields = nullptr;
size_t mlSize = 0;
iSerializable *(*mpCreateFunc)() = nullptr;
};
//-------------------------------------------------
class cSerializeMemberFieldIterator {
public:
cSerializeMemberFieldIterator(cSerializeSavedClass *apTopClass);
bool HasNext();
cSerializeMemberField *GetNext();
private:
cSerializeSavedClass *mpSavedClass;
int mlFieldNum;
};
//-------------------------------------------------
typedef Common::StableMap<Hpl1::StaticString, cSerializeSavedClass> tSerializeSavedClassMap;
typedef tSerializeSavedClassMap::iterator tSerializeSavedClassMapIt;
typedef Common::List<cSerializeSavedClass *> tSerializeSavedClassList;
typedef tSerializeSavedClassList::iterator tSerializeSavedClassListIt;
class cSerializeClass {
public:
static void initSaveClassesMap();
static void finalizeSaveClassesMap();
static void SetLog(bool abX);
static bool GetLog();
static void PrintMembers(iSerializable *apData);
static bool SaveToFile(iSerializable *apData, const tWString &asFile, const tString &asRoot);
static void SaveToElement(iSerializable *apData, const tString &asName, TiXmlElement *apParent, bool abIsPointer = false);
static bool LoadFromFile(iSerializable *apData, const tWString &asFile);
static void LoadFromElement(iSerializable *apData, TiXmlElement *apElement, bool abIsPointer = false);
static cSerializeSavedClass *GetClass(const tString &asName);
static cSerializeMemberFieldIterator GetMemberFieldIterator(iSerializable *apData);
static tString ValueToString(void *apData, size_t alOffset, eSerializeType aType);
static void StringToValue(void *apData, size_t alOffset, eSerializeType aType,
const char *asVal);
private:
static void SaveVariable(TiXmlElement *apElement, cSerializeMemberField *apField, iSerializable *apData);
static void SaveArray(TiXmlElement *apElement, cSerializeMemberField *apField, iSerializable *apData);
static void SaveContainer(TiXmlElement *apElement, cSerializeMemberField *apField, iSerializable *apData);
static void LoadVariable(TiXmlElement *apElement, iSerializable *apData, cSerializeSavedClass *apClass);
static void LoadArray(TiXmlElement *apElement, iSerializable *apData, cSerializeSavedClass *apClass);
static void LoadClass(TiXmlElement *apElement, iSerializable *apData, cSerializeSavedClass *apClass);
static void LoadClassPointer(TiXmlElement *apElement, iSerializable *apData, cSerializeSavedClass *apClass);
static void LoadContainer(TiXmlElement *apElement, iSerializable *apData, cSerializeSavedClass *apClass);
static void FillSaveClassMembersList(tSerializeSavedClassList *apList, cSerializeSavedClass *apClass);
static void SaveSavedClassMembers(cSerializeSavedClass *apClass, iSerializable *apData);
static cSerializeMemberField *GetMemberField(const tString &asName, cSerializeSavedClass *apClass);
static size_t SizeOfType(eSerializeType aType);
static void SetUpData();
static char msTempCharArray[2048];
static bool mbDataSetup;
static tSerializeSavedClassMap *m_mapSavedClasses;
static Common::Array<iSerializableType *> mvValueTypes;
};
//-------------------------------------------------
}
#endif // HPL_SERIALIZE_CLASS_H