1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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);
28 Prototypes for these methods are also defined in the DECLARE_PERSISTENCE_METHODS macro in the persistent_data.h file.
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
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
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
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)
84 STRUCT2(name,write,read)
85 STRUCT3(name,logic,write,read)
87 STRUCT_MAP(keyType,valType,varName)
88 STRUCT_PTR_VECT(type,varName)
89 STRUCT_MAP2(name,keyType,logic,getKey,valWrite,read)
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')
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
124 #ifndef PERSISTENT_CLASS
125 #error PERSISTENT_CLASS not defined
128 #ifndef PERSISTENT_DATA
129 #error PERSISTENT_DATA not defined
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
;
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
;
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();
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())
229 // Convert UTC of the event to game cycle. Suppose that 1 second==10 tick
230 return CTickEventHandler::getGameCycle() + (second - NLMISC::CTime::getSecondsSince1970())*10;
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))
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)
277 #define _TOKENS_CLASSNAME _BUILD_TOKENS_CLASSNAME(PERSISTENT_CLASS)
278 #define _TOKENS_OBJNAME _BUILD_TOKENS_OBJNAME(PERSISTENT_CLASS)
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
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);
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;
323 static _TOKENS_CLASSNAME _TOKENS_OBJNAME
;
325 #undef _TOKENS_CLASSNAME
326 #undef _TOKENS_OBJNAME
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( " ")
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
342 #define _PERSISTENT_STORE_ARGS
346 void PERSISTENT_CLASS::store(CPersistentDataRecord
&pdr _PERSISTENT_STORE_ARGS
) const
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)
353 # define _PDR_TRACE(name)
356 #ifdef PERSISTENT_TOKEN_FAMILY
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()+"'",
367 #ifdef PERSISTENT_TOKEN_CLASS
368 #define _TOKEN(token) _BUILD_TOKENS_OBJNAME(PERSISTENT_TOKEN_CLASS).token
370 #define _TOKEN(token) _BUILD_TOKENS_OBJNAME(PERSISTENT_CLASS).token
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);
389 #define _TOKEN(token) token
392 // Add user-defined code
393 #ifdef PERSISTENT_PRE_STORE
397 // write the properties to the persistent data record
398 #define _PROP(token,name,type,logic,get,set)\
400 logic { type val=get; pdr.push(_TOKEN(token),val); }
402 #define _STRUCT(token,name,logic,write,read)\
404 logic { pdr.pushStructBegin(_TOKEN(token)); write; pdr.pushStructEnd(_TOKEN(token)); }
406 #define _PROP_MAP(token,name,keyType,valType,logic,getKey,getVal,set)\
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)\
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)\
424 logic { pdr.push(_TOKEN(token)); }
438 // Add user-defined code
439 #ifdef PERSISTENT_POST_STORE
440 PERSISTENT_POST_STORE
443 //nldebug("PDR:store:"NL_MACRO_TO_STR(PERSISTENT_CLASS)"(leave)");
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
453 #define _PERSISTENT_APPLY_ARGS
456 #ifndef PERSISTENT_NO_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
)
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)
472 # define _PDR_TRACE(name)
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);
491 // Add user-defined code at the start of the method
492 #ifdef PERSISTENT_PRE_APPLY
496 // apply the properties from the persistent data record
497 #define _PROP(token,name,type,logic,get,set)\
499 if (nextToken==token) { H_AUTO(token); type val; pdr.pop(token,val); set; continue; }
501 #define _STRUCT(token,name,logic,write,read)\
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)\
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)\
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)\
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
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());
548 pdr
.popNextArg(pdr
.peekNextToken());
551 while (!stack
.empty() && !pdr
.isEndOfData());
562 // Add user-defined code
563 #ifdef PERSISTENT_POST_APPLY
564 PERSISTENT_POST_APPLY
567 //nldebug("PDR:apply:"NL_MACRO_TO_STR(PERSISTENT_CLASS)"(leave)");
571 #endif // ndef PERSISTENT_NO_APPLY
574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
593 #undef STRUCT_PTR_VECT
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
617 #ifdef PERSISTENT_PRE_APPLY
618 #undef PERSISTENT_PRE_APPLY
621 #ifdef PERSISTENT_POST_APPLY
622 #undef PERSISTENT_POST_APPLY
625 #ifdef PERSISTENT_PRE_STORE
626 #undef PERSISTENT_PRE_STORE
629 #ifdef PERSISTENT_POST_STORE
630 #undef PERSISTENT_POST_STORE
633 #ifdef PERSISTENT_STORE_ARGS
634 #undef PERSISTENT_STORE_ARGS
637 #ifdef PERSISTENT_APPLY_ARGS
638 #undef PERSISTENT_APPLY_ARGS
641 #ifdef PERSISTENT_NO_STORE
642 #undef PERSISTENT_NO_STORE
645 #ifdef PERSISTENT_NO_APPLY
646 #undef PERSISTENT_NO_APPLY
651 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////