Welcome to mirror list, hosted at ThFree Co, Russian Federation.

serializer.h « serializer « add_on « angelscript « Scripting « Source - github.com/WolfireGames/overgrowth.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2d91cbe81959e90fa30dbdd4db0456820efbf470 (plain)
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