Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / ryzom / common / src / game_share / persistent_data_template.h
blob2587c3864f85de5512389b6ddb30c152b84a2c16
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 **************************************
19 NOTE: THIS IS NOT A NORMAL HEADER FILE
20 **************************************
22 This header file generates code for the following methods for a user-defined class
24 void <user_class>::store(CPersistentDataRecord &pdr) const;
25 void <user_class>::apply(CPersistentDataRecord &pdr);
27 Note:
28 Prototypes for these methods are also defined in the DECLARE_PERSISTENCE_METHODS macro in the persistent_data.h file.
30 Note:
31 This header may be included several times in the same cpp file in order to instantiate
32 store and apply methods for different classes
35 USAGE:
36 #define PERSISTENT_CLASS <class_name>
37 #define PERSISTENT_DATA <data_list>
39 #include "persistent_data_template.h"
41 #undef PERSISTENT_CLASS
42 #undef PERSISTENT_DATA
45 EXAMPLE USAGE:
46 ////////////////////////////////////////////////////////
48 #define PERSISTENT_CLASS CMyClass
49 #define PERSISTENT_DATA\
50 PROP(sint16, Title, getTitle(), setTitle(val))\
51 PROP(uint64, VisualPropertyA, getVisualPropertyA(), setVisualPropertyA(val))
53 #include "perstent_data_template.h"
55 #undef PERSISTENT_CLASS
56 #undef PERSISTENT_DATA
58 ////////////////////////////////////////////////////////
60 #define PERSISTENT_CLASS CAnotherClass
61 #define PERSISTENT_DATA\
62 PROP_VECT(ucstring,IsIgnoredBy,_IsIgnoredBy,_IsIgnoredBy[i],_IsIgnoredBy[i]=val)\
63 PROP_MAP(SP_TYPE,uint32,SkillPoints,_SpType,toString(key),val,setSp(fromString(key),val))\
64 STRUCT(EntityBase,CEntityBaseCharacter::store(pdr),CEntityBaseCharacter::apply(pdr))\
65 STRUCT_VECT(Pact,_Pact,_Pact[i].store(pdr),_Pact[i].apply(pdr))\
66 STRUCT_MAP(TAIAlias,TMissionHistory,MissionHistories,_MissionHistories,key,val.store(pdr),_MissionHistories[key].apply(pdr))
68 #include "persistent_data_template.h"
70 #undef PERSISTENT_CLASS
71 #undef PERSISTENT_DATA
73 ////////////////////////////////////////////////////////
75 MACROS FOR PERSISTENT_DATA DEFINITION
76 PROP(type,varName)
77 PROP2(name,type,get,set)
78 PROP3(name,type,logic,get,set)
79 PROP_SET(type,varName)
80 PROP_VECT(type,varName)
81 PROP_MAP(keyType,valType,varName)
82 PROP_MAP2(name,keyType,valType,logic,getKey,getVal,set)
83 STRUCT(varName)
84 STRUCT2(name,write,read)
85 STRUCT3(name,logic,write,read)
86 STRUCT_VECT(varName)
87 STRUCT_MAP(keyType,valType,varName)
88 STRUCT_PTR_VECT(type,varName)
89 STRUCT_MAP2(name,keyType,logic,getKey,valWrite,read)
91 Where:
92 name - the name stored in the persistent data record for this data element
93 varName - the name of a container (map or vector) to be iterated over
95 type - the data type of a variable
96 keyType - the data type of the key for a persistent map
97 valType - the data type of the value for a persistent map
99 get - code that returns a value to be stored in the persistent data
100 write - code to be executed for a structure at write time (equivalent to 'get' for a property)
101 getKey - code that returns a value for a map key to be stored in the persistent data
102 getVal - code that returns a value for a map value to be stored in the persistent data
103 valWrite - code to be executed for a map value structure at write time (equivalent to 'getVal' for a property)
105 set - code to store the value 'val' in persistent property at read time
106 read - code to be executed for a structure at read time (equivalent to 'get')
108 Context notes:
109 write - 'pdr' contains the persistent data record currently being processed
110 getKey - 'it' is the map iterator
111 getVal - 'it' is the map iterator
112 valWrite - 'pdr' contains the persistent data record currently being processed
113 set - 'val' contains the value to apply
114 read - 'pdr' contains the persistent data record currently being processed
115 read - for maps: 'key' contains the map key
116 read - for property maps: 'val' contains the map entry value
118 PROP_VECT - 'i' is the vector index during all read and write operations
119 STRUCT_VECT - 'i' is the vector index during all read and write operations
122 #include <limits>
124 #ifndef PERSISTENT_CLASS
125 #error PERSISTENT_CLASS not defined
126 #endif
128 #ifndef PERSISTENT_DATA
129 #error PERSISTENT_DATA not defined
130 #endif
132 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
134 #define MAP_LOGIC(keyType,valType,varName) for(std::map<keyType,valType>::const_iterator it=varName.begin();it!=varName.end();++it)
135 #define SET_LOGIC(type,varName) for(std::set<type>::const_iterator it=varName.begin();it!=varName.end();++it)
136 #define LIST_LOGIC(type,varName) for(std::list<type>::const_iterator it=varName.begin();it!=varName.end();++it)
137 #define VECT_LOGIC(varName) ARRAY_LOGIC(varName.size())
138 #define ARRAY_LOGIC(size) for(uint32 i=0;i<size;++i)
139 #define DEFAULT_LOGIC {}
141 #define PROP(type,varName) _PROP(__Tok##varName,#varName,type,DEFAULT_LOGIC,varName,varName=val)
142 #define NPROP(name,type,varName) _PROP(__Tok##name,#name,type,DEFAULT_LOGIC,varName,varName=val)
143 #define PROP2(name,type,get,set) _PROP(__Tok##name,#name,type,DEFAULT_LOGIC,get,set)
144 #define LPROP(type,varName,logic) _PROP(__Tok##varName,#varName,type,logic,varName,varName=val)
145 #define LPROP2(name,type,logic,get,set) _PROP(__Tok##name,#name,type,logic,get,set)
146 #define PROP_SET(type,varName) _PROP(__Tok##varName,#varName,type,SET_LOGIC(type,varName),(*it),varName.insert(val))
147 #define PROP_LIST(type,varName) _PROP(__Tok##varName,#varName,type,LIST_LOGIC(type,varName),(*it),varName.push_back(val))
148 #define PROP_VECT(type,varName) _PROP(__Tok##varName,#varName,type,VECT_LOGIC(varName),varName[i],varName.push_back(val))
149 #define LPROP_VECT(type,varName,logic) _PROP(__Tok##varName,#varName,type,logic,varName[i],varName.push_back(val))
150 #define LPROP_VECT2(name,type,logic,get,set) _PROP(__Tok##name,#name,type,logic,get,set)
151 #define PROP_MAP(keyType,valType,varName) _PROP_MAP(__Tok##varName,#varName,keyType,valType,MAP_LOGIC(keyType,valType,varName),it->first,it->second,varName[key]=val)
152 #define NPROP_MAP(name,keyType,valType,varName) _PROP_MAP(__Tok##name,#name,keyType,valType,MAP_LOGIC(keyType,valType,varName),it->first,it->second,varName[key]=val)
153 #define PROP_MAP2(name,keyType,valType,getKey,getVal,set) _PROP_MAP(__Tok##name,#name,keyType,valType,MAP_LOGIC(keyType,valType,varName),getKey,getVal,set)
154 #define PROP_ARRAY(type,varName,size) _PROP_MAP(__Tok##varName,#varName,uint32,type,ARRAY_LOGIC(size),i,varName[i],if (key<size) varName[key]=val)
155 #define LPROP_MAP2(name,keyType,valType,logic,getKey,getVal,set) _PROP_MAP(__Tok##name,#name,keyType,valType,logic,getKey,getVal,set)
156 #define STRUCT(varName) _STRUCT(__Tok##varName,#varName,DEFAULT_LOGIC,(varName).store(pdr),(varName).apply(pdr))
157 #define STRUCT2(name,write,read) _STRUCT(__Tok##name,#name,DEFAULT_LOGIC,write,read)
158 #define LSTRUCT(varName,logic) _STRUCT(__Tok##varName,#varName,logic,(varName).store(pdr),(varName).apply(pdr))
159 #define LSTRUCT2(name,logic,write,read) _STRUCT(__Tok##name,#name,logic,write,read)
160 #define STRUCT_LIST(type,varName) _STRUCT(__Tok##varName,#varName,LIST_LOGIC(type,varName),(*it).store(pdr),listAppend(varName).apply(pdr))
161 #define STRUCT_VECT(varName) _STRUCT(__Tok##varName,#varName,VECT_LOGIC(varName),varName[i].store(pdr),vectAppend(varName).apply(pdr))
162 #define LSTRUCT_VECT(varName,logic,write,read) _STRUCT(__Tok##varName,#varName,logic,write,read)
163 #define STRUCT_PTR_VECT(type,varName) _STRUCT(__Tok##varName,#varName,VECT_LOGIC(varName),if (varName[i]!=NULL)varName[i]->store(pdr),(varName.push_back(new type),varName.back())->apply(pdr))
164 #define STRUCT_SMRTPTR_VECT(type,varName) _STRUCT(__Tok##varName,#varName,VECT_LOGIC(varName),if (varName[i]!=NULL)varName[i]->store(pdr),(varName.push_back(NLMISC::CSmartPtr<type>(new type)),varName.back())->apply(pdr))
165 #define STRUCT_INDEXED_VECT(varName) _STRUCT_MAP(__Tok##varName,#varName,uint32,VECT_LOGIC(varName),i,varName[i].store(pdr),if (key>=varName.size()) varName.resize(key); varName[key].apply(pdr))
166 #define STRUCT_MAP(keyType,valType,varName) _STRUCT_MAP(__Tok##varName,#varName,keyType,MAP_LOGIC(keyType,valType,varName),it->first,it->second.store(pdr),varName[key].apply(pdr))
167 #define LSTRUCT_MAP2(name,keyType,logic,getKey,valWrite,read) _STRUCT_MAP(__Tok##name,#name,keyType,logic,getKey,valWrite,read)
168 #define STRUCT_ARRAY(varName,size) _STRUCT_MAP(__Tok##varName,#varName,uint32,ARRAY_LOGIC(size),i,varName[i].store(pdr),if (key<size) varName[key].apply(pdr))
169 #define FLAG(name,applyCode) _FLAG(__Tok##name,#name,DEFAULT_LOGIC,applyCode)
170 #define FLAG0(name,applyCode) _FLAG(__Tok##name,#name,if(false),applyCode)
171 #define LFLAG(name,logic,applyCode) _FLAG(__Tok##name,#name,logic,applyCode)
174 #ifndef PERSISTENT_GAME_CYCLE_INLINE_DEFINED
175 #define PERSISTENT_GAME_CYCLE_INLINE_DEFINED
176 #include "tick_event_handler.h"
177 #include "nel/misc/hierarchical_timer.h"
178 inline uint32 saveGameCycleToSecond(NLMISC::TGameCycle tick)
180 // Evaluate the UTC of this event (with the current date of save). Suppose that 1 second==10 tick
181 // NB: result should be positive since no event should have been launched before 1970!
182 if (tick < CTickEventHandler::getGameCycle())
184 NLMISC::TGameCycle tick_dt = CTickEventHandler::getGameCycle() - tick;
185 uint32 s_dt = tick_dt / 10;
186 return NLMISC::CTime::getSecondsSince1970() - s_dt;
188 else
190 NLMISC::TGameCycle tick_dt = tick - CTickEventHandler::getGameCycle();
191 uint32 s_dt = tick_dt / 10;
192 return NLMISC::CTime::getSecondsSince1970() + s_dt;
195 inline NLMISC::TGameCycle loadSecondToGameCycle(uint32 second)
197 if (second < NLMISC::CTime::getSecondsSince1970())
199 uint32 s_dt = NLMISC::CTime::getSecondsSince1970() - second;
200 NLMISC::TGameCycle tick_dt = s_dt * 10;
201 return CTickEventHandler::getGameCycle() - tick_dt;
203 else
205 uint32 s_dt = second - NLMISC::CTime::getSecondsSince1970();
206 NLMISC::TGameCycle tick_dt = s_dt * 10;
207 return CTickEventHandler::getGameCycle() + tick_dt;
211 /*inline uint32 saveGameCycleToSecond(NLMISC::TGameCycle tick)
213 sint32 dt = CTickEventHandler::getGameCycle() - tick;
216 // Evaluate the UTC of this event (with the current date of save). Suppose that 1 second==10 tick
217 if (tick < CTickEventHandler::getGameCycle())
218 return NLMISC::CTime::getSecondsSince1970();
219 else
220 return NLMISC::CTime::getSecondsSince1970() + (tick - CTickEventHandler::getGameCycle())/10;
221 // NB: result should be positive since no event should have been launched before 1970!
224 inline NLMISC::TGameCycle loadSecondToGameCycle(uint32 second)
226 if (second < NLMISC::CTime::getSecondsSince1970())
227 return 0;
229 // Convert UTC of the event to game cycle. Suppose that 1 second==10 tick
230 return CTickEventHandler::getGameCycle() + (second - NLMISC::CTime::getSecondsSince1970())*10;
232 #endif
234 // GameCycle property (saved as a UTC of the current game cycle, support server migration)
235 #define PROP_GAME_CYCLE(varName)\
236 /* read and write, in UTC seconds. if result is negative, clamp to 0 */ \
237 PROP2(UTC_##varName, uint32, saveGameCycleToSecond(varName), varName=loadSecondToGameCycle(val))
239 // GameCycle property with Backward compatibility (saved as a UTC of the current game cycle, support server migration)
240 #define PROP_GAME_CYCLE_COMP(varName)\
241 /* don't write (old variable name), but direct read if in pdr */ \
242 LPROP2(varName, NLMISC::TGameCycle, if(0), 0, varName=val) \
243 /* read and write, in UTC seconds. if result is negative, clamp to 0 */ \
244 PROP2(UTC_##varName, uint32, saveGameCycleToSecond(varName), varName=loadSecondToGameCycle(val))
246 // SideNotes:
247 // if the server where we load the game cycle is different from the one from where we saved, and if he is younger,
248 // then we can have situations where gamecycle<0. Since TGameCycle is actually a uint32, this will cause bugs.
249 // Hence we don't allow <0 values.
252 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
254 ///////////////////////////////////////////////////////////////////////////////////////////
256 // NOTE: This method is declared in DECLARE_PERSISTENCE_METHODS macro in persistent_data.h
258 ///////////////////////////////////////////////////////////////////////////////////////////
260 #ifndef PERSISTENT_NO_STORE
262 #ifdef PERSISTENT_TOKEN_FAMILY
264 //#pragma message( "Using token family "NL_MACRO_TO_STR(PERSISTENT_TOKEN_FAMILY)" for persistent data class " NL_MACRO_TO_STR(PERSISTENT_CLASS) )
266 // setup some macros for constructing the classname and object name that we need for
267 // the 'persistent token family' constants class
268 #define _EVAL(b,c) b##c
269 #define _BUILD_TOKENS_CLASSNAME(c) _EVAL(c,__constants__class)
270 #define _BUILD_TOKENS_OBJNAME(c) _EVAL(c,__constants__obj)
272 // setup the class name and object name for the 'persistent token family' constants class and its instance
273 #ifdef PERSISTENT_TOKEN_CLASS
274 #define _TOKENS_CLASSNAME _BUILD_TOKENS_CLASSNAME(PERSISTENT_TOKEN_CLASS)
275 #define _TOKENS_OBJNAME _BUILD_TOKENS_OBJNAME(PERSISTENT_TOKEN_CLASS)
276 #else
277 #define _TOKENS_CLASSNAME _BUILD_TOKENS_CLASSNAME(PERSISTENT_CLASS)
278 #define _TOKENS_OBJNAME _BUILD_TOKENS_OBJNAME(PERSISTENT_CLASS)
279 #endif
282 // define the set of tokens required by this class
283 // adding them to some pre-defined token family
284 struct _TOKENS_CLASSNAME
286 // the ctor is used to setup the values of the static tokens
287 _TOKENS_CLASSNAME()
289 #define _ADD_TOKEN(token) CPdrTokenRegistry::getInstance()->addToken(NL_MACRO_TO_STR(PERSISTENT_TOKEN_FAMILY),token)
291 __Tok__MapKey= _ADD_TOKEN("__Key__");
292 __Tok__MapVal= _ADD_TOKEN("__Val__");
293 #define _PROP(token,name,type,logic,get,set) token= _ADD_TOKEN(name);
294 #define _STRUCT(token,name,logic,write,read) token= _ADD_TOKEN(name);
295 #define _PROP_MAP(token,name,keyType,valType,logic,getKey,getVal,set) token= _ADD_TOKEN(name);
296 #define _STRUCT_MAP(token,name,keyType,logic,getKey,valWrite,read) token= _ADD_TOKEN(name);
297 #define _FLAG(token,name,logic,code) token= _ADD_TOKEN(name);
298 PERSISTENT_DATA
299 #undef _PROP
300 #undef _STRUCT
301 #undef _PROP_MAP
302 #undef _STRUCT_MAP
303 #undef _FLAG
305 #undef _ADD_TOKEN
308 // define the set of static variables to act as constants for stocking the set of tokens for this persistet data class
309 uint16 __Tok__MapKey;
310 uint16 __Tok__MapVal;
311 #define _PROP(token,name,type,logic,get,set) uint16 token;
312 #define _STRUCT(token,name,logic,write,read) uint16 token;
313 #define _PROP_MAP(token,name,keyType,valType,logic,getKey,getVal,set) uint16 token;
314 #define _STRUCT_MAP(token,name,keyType,logic,getKey,valWrite,read) uint16 token;
315 #define _FLAG(token,name,logic,code) uint16 token;
316 PERSISTENT_DATA
317 #undef _PROP
318 #undef _STRUCT
319 #undef _PROP_MAP
320 #undef _STRUCT_MAP
321 #undef _FLAG
323 static _TOKENS_CLASSNAME _TOKENS_OBJNAME;
325 #undef _TOKENS_CLASSNAME
326 #undef _TOKENS_OBJNAME
328 #else
330 #ifdef NL_OS_WINDOWS
331 #pragma message( " ")
332 #pragma message( "NON-OPTIMISED: Persistent data class " NL_MACRO_TO_STR(PERSISTENT_CLASS) " not using a token family")
333 #pragma message( " ")
334 #endif
336 #endif
338 // define _PERSISTENT_STORE_ARGS as either (<empty>) or (","<extra args>) for use in adding args to the store() function prototype
339 #ifdef PERSISTENT_STORE_ARGS
340 #define _PERSISTENT_STORE_ARGS ,PERSISTENT_STORE_ARGS
341 #else
342 #define _PERSISTENT_STORE_ARGS
343 #endif
345 // store()
346 void PERSISTENT_CLASS::store(CPersistentDataRecord &pdr _PERSISTENT_STORE_ARGS) const
348 // PDR debug helper
349 #ifdef NL_DEBUG
350 //nldebug("PDR:store:"NL_MACRO_TO_STR(PERSISTENT_CLASS)"(enter)");
351 # define _PDR_TRACE(name) //nldebug("PDR:store:" NL_MACRO_TO_STR(PERSISTENT_CLASS) "." #name)
352 #else
353 # define _PDR_TRACE(name)
354 #endif
356 #ifdef PERSISTENT_TOKEN_FAMILY
358 #ifdef NL_DEBUG
359 // this class has been configured to use a specific token family. This means that it is not possible
360 // to store the class to a pdr that is not using the same token family.
361 BOMB_IF(pdr.getTokenFamily()!=NL_MACRO_TO_STR(PERSISTENT_TOKEN_FAMILY),
362 NL_MACRO_TO_STR(PERSISTENT_CLASS) "::store() requires token family '" NL_MACRO_TO_STR(PERSISTENT_TOKEN_FAMILY) "'"
363 " but pdr is using token family '"+pdr.getTokenFamily()+"'",
364 return);
365 #endif
367 #ifdef PERSISTENT_TOKEN_CLASS
368 #define _TOKEN(token) _BUILD_TOKENS_OBJNAME(PERSISTENT_TOKEN_CLASS).token
369 #else
370 #define _TOKEN(token) _BUILD_TOKENS_OBJNAME(PERSISTENT_CLASS).token
371 #endif
373 #else
374 // define the set of tokens - this makes sure that the tokens exist in the map and that we only look them up the once
375 static uint16 __Tok__MapKey = std::numeric_limits<uint16>::max(); pdr.addString("__Key__",__Tok__MapKey);
376 static uint16 __Tok__MapVal = std::numeric_limits<uint16>::max(); pdr.addString("__Val__",__Tok__MapVal);
377 #define _PROP(token,name,type,logic,get,set) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
378 #define _STRUCT(token,name,logic,write,read) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
379 #define _PROP_MAP(token,name,keyType,valType,logic,getKey,getVal,set) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
380 #define _STRUCT_MAP(token,name,keyType,logic,getKey,valWrite,read) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
381 #define _FLAG(token,name,logic,code) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
382 PERSISTENT_DATA
383 #undef _PROP
384 #undef _STRUCT
385 #undef _PROP_MAP
386 #undef _STRUCT_MAP
387 #undef _FLAG
389 #define _TOKEN(token) token
390 #endif
392 // Add user-defined code
393 #ifdef PERSISTENT_PRE_STORE
394 PERSISTENT_PRE_STORE
395 #endif
397 // write the properties to the persistent data record
398 #define _PROP(token,name,type,logic,get,set)\
399 _PDR_TRACE(name);\
400 logic { type val=get; pdr.push(_TOKEN(token),val); }
402 #define _STRUCT(token,name,logic,write,read)\
403 _PDR_TRACE(name);\
404 logic { pdr.pushStructBegin(_TOKEN(token)); write; pdr.pushStructEnd(_TOKEN(token)); }
406 #define _PROP_MAP(token,name,keyType,valType,logic,getKey,getVal,set)\
407 _PDR_TRACE(name);\
409 pdr.pushStructBegin(_TOKEN(token));\
410 logic { keyType __k=getKey; valType __v=getVal; pdr.push(_TOKEN(__Tok__MapKey),__k); pdr.push(_TOKEN(__Tok__MapVal),__v); }\
411 pdr.pushStructEnd(_TOKEN(token)); \
414 #define _STRUCT_MAP(token,name,keyType,logic,getKey,valWrite,read)\
415 _PDR_TRACE(name);\
417 pdr.pushStructBegin(_TOKEN(token));\
418 logic { keyType __k=getKey; pdr.push(_TOKEN(__Tok__MapKey),__k); pdr.pushStructBegin(_TOKEN(__Tok__MapVal)); valWrite; pdr.pushStructEnd(_TOKEN(__Tok__MapVal)); }\
419 pdr.pushStructEnd(_TOKEN(token)); \
422 #define _FLAG(token,name,logic,code)\
423 _PDR_TRACE(name);\
424 logic { pdr.push(_TOKEN(token)); }
426 PERSISTENT_DATA
428 #undef _PROP
429 #undef _STRUCT
430 #undef _PROP_MAP
431 #undef _STRUCT_MAP
432 #undef _FLAG
433 #undef _PDR_TRACE
435 #undef _TOKEN
438 // Add user-defined code
439 #ifdef PERSISTENT_POST_STORE
440 PERSISTENT_POST_STORE
441 #endif
442 #ifdef NL_DEBUG
443 //nldebug("PDR:store:"NL_MACRO_TO_STR(PERSISTENT_CLASS)"(leave)");
444 #endif
447 #endif // ndef PERSISTENT_NO_STORE
449 // define _PERSISTENT_APPLY_ARGS as either (<empty>) or (","<extra args>) for use in adding args to the apply() function prototype
450 #ifdef PERSISTENT_APPLY_ARGS
451 #define _PERSISTENT_APPLY_ARGS ,PERSISTENT_APPLY_ARGS
452 #else
453 #define _PERSISTENT_APPLY_ARGS
454 #endif
456 #ifndef PERSISTENT_NO_APPLY
458 // apply()
459 void PERSISTENT_CLASS::apply(CPersistentDataRecord &pdr _PERSISTENT_APPLY_ARGS)
461 #define DECORATE(x) #x
462 #define MY_H_AUTO(name) static NLMISC::CHTimer _timer(DECORATE(name)"_Apply"); NLMISC::CAutoTimer _auto(&_timer);
463 MY_H_AUTO(PERSISTENT_CLASS)
464 #undef MY_H_AUTO
465 #undef DECORATE
467 // PDR debug helper
468 #ifdef NL_DEBUG
469 //nldebug("PDR:apply:"NL_MACRO_TO_STR(PERSISTENT_CLASS)"(enter)");
470 # define _PDR_TRACE(name) //nldebug("PDR:apply:" NL_MACRO_TO_STR(PERSISTENT_CLASS) "." #name)
471 #else
472 # define _PDR_TRACE(name)
473 #endif
475 // define the set of tokens - this makes sure that the tokens exist in the map and that we only look them up the once
476 static uint16 __Tok__MapKey = std::numeric_limits<uint16>::max(); pdr.addString("__Key__",__Tok__MapKey);
477 static uint16 __Tok__MapVal = std::numeric_limits<uint16>::max(); pdr.addString("__Val__",__Tok__MapVal);
478 #define _PROP(token,name,type,logic,get,set) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
479 #define _STRUCT(token,name,logic,write,read) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
480 #define _PROP_MAP(token,name,keyType,valType,logic,getKey,getVal,set) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
481 #define _STRUCT_MAP(token,name,keyType,logic,getKey,valWrite,read) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
482 #define _FLAG(token,name,logic,code) static uint16 token = std::numeric_limits<uint16>::max(); pdr.addString(name,token);
483 PERSISTENT_DATA
484 #undef _PROP
485 #undef _STRUCT
486 #undef _PROP_MAP
487 #undef _STRUCT_MAP
488 #undef _FLAG
491 // Add user-defined code at the start of the method
492 #ifdef PERSISTENT_PRE_APPLY
493 PERSISTENT_PRE_APPLY
494 #endif
496 // apply the properties from the persistent data record
497 #define _PROP(token,name,type,logic,get,set)\
498 _PDR_TRACE(name);\
499 if (nextToken==token) { H_AUTO(token); type val; pdr.pop(token,val); set; continue; }
501 #define _STRUCT(token,name,logic,write,read)\
502 _PDR_TRACE(name);\
503 if (nextToken==token) { H_AUTO(token##_STRUCT); pdr.popStructBegin(token); read; pdr.popStructEnd(token); continue; }
505 #define _PROP_MAP(token,name,keyType,valType,logic,getKey,getVal,set)\
506 _PDR_TRACE(name);\
507 if (nextToken==token) { H_AUTO(token##_Key); pdr.popStructBegin(token);\
508 while (!pdr.isEndOfStruct()) { H_AUTO(token##_Val); keyType key; pdr.pop(__Tok__MapKey,key); valType val; pdr.pop(__Tok__MapVal,val);set;}\
509 pdr.popStructEnd(token); continue; }
511 #define _STRUCT_MAP(token,name,keyType,logic,getKey,valWrite,read)\
512 _PDR_TRACE(name);\
513 if (nextToken==token) { H_AUTO(token##_Key); pdr.popStructBegin(token);\
514 while (!pdr.isEndOfStruct()) { H_AUTO(token##_Val_STRUCT); keyType key; pdr.pop(__Tok__MapKey,key);pdr.popStructBegin(__Tok__MapVal);read;pdr.popStructEnd(__Tok__MapVal);}\
515 pdr.popStructEnd(token); continue; }
517 #define _FLAG(token,name,logic,code)\
518 _PDR_TRACE(name);\
519 if (nextToken==token) { H_AUTO(token##_FLAG); pdr.pop(token); code; continue; }
521 while (!pdr.isEndOfStruct())
523 uint16 nextToken= pdr.peekNextToken();
525 // try to match the next token to one of the persistent data elements and 'continue' on success
526 PERSISTENT_DATA
527 // nlwarning("Skipping unrecognised token: %s",pdr.peekNextTokenName().c_str());
529 // if this is a structure then skip the whole thing
530 std::vector<uint16> stack;
533 H_AUTO(SkipUnknownStuff);
535 if (pdr.isStartOfStruct())
537 stack.push_back(pdr.peekNextToken());
538 pdr.popStructBegin(stack.back());
540 else if (pdr.isEndOfStruct())
542 pdr.popStructEnd(stack.back());
543 if (!stack.empty())
544 stack.pop_back();
546 else
548 pdr.popNextArg(pdr.peekNextToken());
551 while (!stack.empty() && !pdr.isEndOfData());
554 #undef _PROP
555 #undef _STRUCT
556 #undef _PROP_MAP
557 #undef _STRUCT_MAP
558 #undef _FLAG
559 #undef _PDR_TRACE
562 // Add user-defined code
563 #ifdef PERSISTENT_POST_APPLY
564 PERSISTENT_POST_APPLY
565 #endif
566 #ifdef NL_DEBUG
567 //nldebug("PDR:apply:"NL_MACRO_TO_STR(PERSISTENT_CLASS)"(leave)");
568 #endif
571 #endif // ndef PERSISTENT_NO_APPLY
574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
576 #undef PROP
577 #undef PROP2
578 #undef LPROP
579 #undef LPROP2
580 #undef PROP_SET
581 #undef PROP_VECT
582 #undef LPROP_VECT
583 #undef LPROP_VECT2
584 #undef PROP_MAP
585 #undef PROP_MAP2
586 #undef LPROP_MAP2
587 #undef STRUCT
588 #undef STRUCT2
589 #undef LSTRUCT
590 #undef LSTRUCT2
591 #undef STRUCT_VECT
592 #undef LSTRUCT_VECT
593 #undef STRUCT_PTR_VECT
594 #undef STRUCT_MAP
595 #undef LSTRUCT_MAP2
597 #undef MAP_LOGIC
598 #undef SET_LOGIC
599 #undef VECT_LOGIC
600 #undef ARRAY_LOGIC
601 #undef DEFAULT_LOGIC
603 #undef _PERSISTENT_STORE_ARGS
604 #undef _PERSISTENT_APPLY_ARGS
606 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
608 #ifdef PERSISTENT_MACROS_AUTO_UNDEF
610 #undef PERSISTENT_CLASS
611 #undef PERSISTENT_DATA
613 #ifdef PERSISTENT_TOKEN_CLASS
614 #undef PERSISTENT_TOKEN_CLASS
615 #endif
617 #ifdef PERSISTENT_PRE_APPLY
618 #undef PERSISTENT_PRE_APPLY
619 #endif
621 #ifdef PERSISTENT_POST_APPLY
622 #undef PERSISTENT_POST_APPLY
623 #endif
625 #ifdef PERSISTENT_PRE_STORE
626 #undef PERSISTENT_PRE_STORE
627 #endif
629 #ifdef PERSISTENT_POST_STORE
630 #undef PERSISTENT_POST_STORE
631 #endif
633 #ifdef PERSISTENT_STORE_ARGS
634 #undef PERSISTENT_STORE_ARGS
635 #endif
637 #ifdef PERSISTENT_APPLY_ARGS
638 #undef PERSISTENT_APPLY_ARGS
639 #endif
641 #ifdef PERSISTENT_NO_STORE
642 #undef PERSISTENT_NO_STORE
643 #endif
645 #ifdef PERSISTENT_NO_APPLY
646 #undef PERSISTENT_NO_APPLY
647 #endif
649 #endif
651 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////