1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
//
// CSerializer
//
// This code was based on the CScriptReloader written by FDsagizi
// http://www.gamedev.net/topic/604890-dynamic-reloading-script/
//
#ifndef SERIALIZER_H
#define SERIALIZER_H
#ifndef ANGELSCRIPT_H
// Avoid having to inform include path if header is already include before
#include <angelscript.h>
#endif
#include <vector>
#include <string>
#include <map>
BEGIN_AS_NAMESPACE
class CSerializer;
class CSerializedValue;
// Need for register user types objects
// string, any, array... for all object
// user ref type.
struct CUserType
{
virtual ~CUserType() {};
virtual void Store(CSerializedValue *val, void *ptr) = 0;
virtual void Restore(CSerializedValue *val, void *ptr) = 0;
virtual void CleanupUserData(CSerializedValue * /*val*/) {}
};
class CSerializedValue
{
public:
CSerializedValue();
CSerializedValue(CSerializedValue *parent, const std::string &name, const std::string &nameSpace, void *ref, int typeId);
~CSerializedValue();
// Save the object and its children
void Store(void *ref, int refTypeId);
// Restore the object and its children
void Restore(void *ref, int refTypeId);
// Set type of this var
void SetType(int typeId);
// Returns the object type for non-primitives
asITypeInfo *GetType();
// Get child by name variable
CSerializedValue *FindByName(const std::string &name, const std::string &nameSpace);
// Find variable by ptr
CSerializedValue *FindByPtr(void *ptr);
// User data
void *GetUserData();
void SetUserData(void *data);
// Children, e.g. properties of a script class, or elements
// of an array, or object pointed to by a handle unless it
// is already a variable)
std::vector<CSerializedValue*> m_children;
protected:
friend class CSerializer;
void Init();
void Uninit();
// you first need to save all the objects before you can save references to objects
void ReplaceHandles();
// After the objects has been restored, the handles needs to
// be updated to point to the right objects
void RestoreHandles();
// Recursively get all ptrs of the children
void GetAllPointersOfChildren(std::vector<void*> *ptrs);
// may be that the two references refer to the same variable.
// But this variable is not available in the global list.
// According to this reference will be restores it.
// And so two links are not created 2 variables,
// it is necessary to cancel the creation of one of them.
void CancelDuplicates(CSerializedValue *from);
// Find variable by ptr but looking only at those in the references, which will create a new object
CSerializedValue *FindByPtrInHandles(void *ptr);
// ptr - is a handle to class
void *GetPointerToRestoredObject(void *ptr);
// Cleanup children
void ClearChildren();
// The serializer object
CSerializer *m_serializer;
// The user data can be used by CUserType to store extra information
void *m_userData;
// The type id of the stored value
int m_typeId;
// For non-primitives the typeId may change if the module is reloaded so
// it is necessary to store the type name to determine the new type id
std::string m_typeName;
// Name of variable or property
std::string m_name;
std::string m_nameSpace;
// Is initialized
bool m_isInit;
// 'this' pointer to variable.
// While storing, this points to the actual variable that was stored.
// While restoring, it is just a unique identifier.
void *m_originalPtr;
// where handle references
// While storing, this points to the actual object.
// While restoring, it is just a unique identifier.
void *m_handlePtr;
// new address object, ie address the restoration
// While storing this isn't used.
// While restoring it will point to the actual variable/object that is restored.
void *m_restorePtr;
// Serialized data for primitives
std::vector<char> m_mem;
};
// This class keeps a list of variables, then restores them after the script is rebuilt.
// But you have to be careful with the change of signature in classes, or
// changing the types of objects. You can remove or add variables, functions,
// methods, but you can not (yet) change the type of variables.
//
// You also need to understand that after a rebuild you should get
// new functions and typeids from the module.
class CSerializer
{
public:
CSerializer();
~CSerializer();
// Add implementation for serializing user types
void AddUserType(CUserType *ref, const std::string &name);
// Store all global variables in the module
int Store(asIScriptModule *mod);
// Restore all global variables after reloading script
int Restore(asIScriptModule *mod);
// Store extra objects that are not seen from the module's global variables
void AddExtraObjectToStore(asIScriptObject *object);
// Return new pointer to restored object
void *GetPointerToRestoredObject(void *originalObject);
protected:
friend class CSerializedValue;
CSerializedValue m_root;
asIScriptEngine *m_engine;
asIScriptModule *m_mod;
std::map<std::string, CUserType*> m_userTypes;
struct SExtraObject
{
asIScriptObject *originalObject;
std::string originalClassName;
int originalTypeId;
};
std::vector<SExtraObject> m_extraObjects;
};
END_AS_NAMESPACE
#endif
|