Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / ryzom / common / src / game_share / persistent_data_inline.h
blob8541404dc048e7a062af807abc27d5d2597ca6e4
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/>.
17 //-----------------------------------------------------------------------------
18 // inlines CPersistentDataRecord
19 //-----------------------------------------------------------------------------
21 inline void CPersistentDataRecord::addString(const std::string& name,uint16 &result)
23 // check whether the value of 'result' is already correct
24 if (result<_StringTable.size())
25 if (_StringTable[result]==name)
26 return;
28 // no luck so do the full work...
29 result= addString(name);
32 inline void CPersistentDataRecord::addString(const char* name,uint16 &result)
34 // check whether the value of 'result' is already correct
35 if (result<_StringTable.size())
36 if (strcmp(_StringTable[result].c_str(),name)==0)
37 return;
39 // no luck so do the full work...
40 result= addString(name);
43 inline void CPersistentDataRecord::push(TToken token,const CArg& arg)
45 arg.push(token,_TokenTable,_ArgTable);
48 inline void CPersistentDataRecord::push(TToken token,bool val)
50 // make sure the token is valid
51 #ifdef NL_DEBUG
52 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
53 #endif
55 // store the token and value to the relavent data buffers
56 _TokenTable.push_back((token<<3)+CArg::SINT_TOKEN);
57 _ArgTable.push_back((sint32)val);
60 inline void CPersistentDataRecord::push(TToken token,sint8 val)
62 // make sure the token is valid
63 #ifdef NL_DEBUG
64 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
65 #endif
67 // store the token and value to the relavent data buffers
68 _TokenTable.push_back((token<<3)+CArg::SINT_TOKEN);
69 _ArgTable.push_back((sint32)val);
72 inline void CPersistentDataRecord::push(TToken token,sint16 val)
74 // make sure the token is valid
75 #ifdef NL_DEBUG
76 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
77 #endif
79 // store the token and value to the relavent data buffers
80 _TokenTable.push_back((token<<3)+CArg::SINT_TOKEN);
81 _ArgTable.push_back((sint32)val);
84 inline void CPersistentDataRecord::push(TToken token,sint32 val)
86 // make sure the token is valid
87 #ifdef NL_DEBUG
88 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
89 #endif
91 // store the token and value to the relavent data buffers
92 _TokenTable.push_back((token<<3)+CArg::SINT_TOKEN);
93 _ArgTable.push_back(val);
96 inline void CPersistentDataRecord::push(TToken token,sint64 val)
98 // create a union for splitting the i64 value into 2 32bit parts and map the union onto the input value
99 NLMISC::C64BitsParts valueInBits;
100 valueInBits.i64[0] = val;
102 // make sure the token is valid
103 #ifdef NL_DEBUG
104 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
105 #endif
107 // store the token and value to the relavent data buffers
108 _TokenTable.push_back((token<<3)+CArg::EXTEND_TOKEN);
109 _ArgTable.push_back(valueInBits.u32[0]);
110 _TokenTable.push_back((token<<3)+CArg::SINT_TOKEN);
111 _ArgTable.push_back(valueInBits.u32[0]);
114 inline void CPersistentDataRecord::push(TToken token,uint8 val)
116 // make sure the token is valid
117 #ifdef NL_DEBUG
118 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
119 #endif
121 // store the token and value to the relavent data buffers
122 _TokenTable.push_back((token<<3)+CArg::UINT_TOKEN);
123 _ArgTable.push_back(val);
126 inline void CPersistentDataRecord::push(TToken token,uint16 val)
128 // make sure the token is valid
129 #ifdef NL_DEBUG
130 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
131 #endif
133 // store the token and value to the relavent data buffers
134 _TokenTable.push_back((token<<3)+CArg::UINT_TOKEN);
135 _ArgTable.push_back(val);
138 inline void CPersistentDataRecord::push(TToken token,uint32 val)
140 // make sure the token is valid
141 #ifdef NL_DEBUG
142 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
143 #endif
145 // store the token and value to the relavent data buffers
146 _TokenTable.push_back((token<<3)+CArg::UINT_TOKEN);
147 _ArgTable.push_back(val);
150 inline void CPersistentDataRecord::push(TToken token,uint64 val)
152 // create a union for splitting the i64 value into 2 32bit parts and map the union onto the input value
153 NLMISC::C64BitsParts valueInBits;
154 valueInBits.u64[0] = val;
156 // make sure the token is valid
157 #ifdef NL_DEBUG
158 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
159 #endif
161 // store the token and value to the relavent data buffers
162 _TokenTable.push_back((token<<3)+CArg::EXTEND_TOKEN);
163 _ArgTable.push_back(valueInBits.u32[0]);
164 _TokenTable.push_back((token<<3)+CArg::UINT_TOKEN);
165 _ArgTable.push_back(valueInBits.u32[1]);
168 inline void CPersistentDataRecord::push(TToken token,float val)
170 NLMISC::C64BitsParts valueInBits;
171 valueInBits.f[0] = val;
173 // make sure the token is valid
174 #ifdef NL_DEBUG
175 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
176 #endif
178 // store the token and value to the relavent data buffers
179 _TokenTable.push_back((token<<3)+CArg::FLOAT_TOKEN);
180 _ArgTable.push_back(valueInBits.u32[0]);
183 inline void CPersistentDataRecord::push(TToken token,double val)
185 // create a union for splitting the i64 value into 2 32bit parts and map the union onto the input value
186 NLMISC::C64BitsParts valueInBits;
187 valueInBits.d[0] = val;
189 // make sure the token is valid
190 #ifdef NL_DEBUG
191 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
192 #endif
194 // store the token and value to the relavent data buffers
195 _TokenTable.push_back((token<<3)+CArg::EXTEND_TOKEN);
196 _ArgTable.push_back(valueInBits.u32[0]);
197 _TokenTable.push_back((token<<3)+CArg::FLOAT_TOKEN);
198 _ArgTable.push_back(valueInBits.u32[1]);
201 inline void CPersistentDataRecord::push(TToken token,const std::string& val)
203 // make sure the token is valid
204 #ifdef NL_DEBUG
205 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
206 #endif
208 // store the token and value to the relavent data buffers
209 _TokenTable.push_back((token<<3)+CArg::STRING_TOKEN);
210 _ArgTable.push_back(addString(val));
213 inline void CPersistentDataRecord::push(TToken token,const ucstring& val)
215 // treat ucstrings as strings
216 push(token,val.toUtf8());
219 inline void CPersistentDataRecord::push(TToken token,NLMISC::CSheetId val)
221 // make sure the token is valid
222 #ifdef NL_DEBUG
223 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
224 #endif
226 // store the token and value to the relavent data buffers
227 _TokenTable.push_back((token<<3)+CArg::EXTEND_TOKEN);
228 _ArgTable.push_back(CArg::ET_SHEET_ID);
229 _TokenTable.push_back((token<<3)+CArg::STRING_TOKEN);
230 _ArgTable.push_back(val.asInt());
233 inline void CPersistentDataRecord::push(TToken token,const NLMISC::CEntityId& val)
235 // this one is a bit complictaed to unrole by hand - better leave it to standard CArg::push()
236 CArg::EntityId(val).push(token,_TokenTable,_ArgTable);
239 inline void CPersistentDataRecord::push(TToken token)
241 // make sure the token is valid
242 #ifdef NL_DEBUG
243 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
244 #endif
246 // store the token to the relavent data buffer
247 _TokenTable.push_back((token<<3)+CArg::FLAG_TOKEN);
250 inline void CPersistentDataRecord::pushStructBegin(TToken token)
252 // make sure the token is valid
253 #ifdef NL_DEBUG
254 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
255 #endif
257 _TokenTable.push_back(token<<3|CArg::STRUCT_BEGIN);
258 _WritingStructStack.push_back(token);
261 inline void CPersistentDataRecord::pushStructEnd(TToken token)
263 #ifdef NL_DEBUG
264 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
265 BOMB_IF(_WritingStructStack.empty(),"Trying to pop past end of stack",return);
266 BOMB_IF(_WritingStructStack.back()!=token,"Attempting to end a structure with the wrong delimiting token",return);
267 #endif
269 _WritingStructStack.pop_back();
270 _TokenTable.push_back(token<<3|CArg::STRUCT_END);
273 //-------------------------------------------------------------------------
274 // set of accessors for retrieving data from a CPersistentDataRecord
275 //-------------------------------------------------------------------------
277 inline bool CPersistentDataRecord::isEndOfData() const
279 DROP_IF( (_TokenOffset==_TokenTable.size()) && !(_ArgOffset==_ArgTable.size()),"Argument table and token table sizes don't match", return true);
280 DROP_IF( _TokenOffset>_TokenTable.size(),"Attempt to access beyond end of data...", return true);
281 return _TokenOffset==_TokenTable.size();
284 inline bool CPersistentDataRecord::isEndOfStruct() const
286 if (isEndOfData())
287 return true;
288 if (_ReadingStructStack.empty())
289 return false;
290 if (peekNextTokenType()!=CArg::STRUCT_END)
291 return false;
292 DROP_IF(_ReadingStructStack.back()!=peekNextToken(),"Opening and closing structure tokens don't match",return false)
293 return true;
296 inline bool CPersistentDataRecord::isStartOfStruct() const
298 // DROP_IF(isEndOfData(),"Attempt to read past end of input data",return 0);
299 return (peekNextTokenType()==CArg::STRUCT_BEGIN);
302 inline bool CPersistentDataRecord::isTokenWithNoData() const
304 // DROP_IF(isEndOfData(),"Attempt to read past end of input data",return 0);
305 return (peekNextTokenType()==CArg::FLAG);
308 inline CPersistentDataRecord::TToken CPersistentDataRecord::peekNextToken() const
310 DROP_IF(isEndOfData(),"Attempt to read past end of input data",return 0);
311 // the 3 low bits contain arg type information - uninteresting here
312 return _TokenTable[_TokenOffset]>>3;
315 inline const NLMISC::CSString& CPersistentDataRecord::peekNextTokenName() const
317 TToken t= peekNextToken();
318 return _StringTable[t];
321 inline CPersistentDataRecord::CArg::TType CPersistentDataRecord::peekNextTokenType() const
323 DROP_IF(isEndOfData(),"Attempt to read past end of input data",return CArg::TType(0));
324 uint32 tokenType= _TokenTable[_TokenOffset]&7;
325 if (tokenType==CArg::EXTEND_TOKEN)
327 DROP_IF(_TokenOffset+1>=_TokenTable.size(),"Attempt to read past end of input data",return CArg::TType(0));
328 return CArg::token2Type(_TokenTable[_TokenOffset+1]&7,true);
330 return CArg::token2Type(_TokenTable[_TokenOffset]&7,false);
333 inline const CPersistentDataRecord::CArg& CPersistentDataRecord::peekNextArg() const
335 CPersistentDataRecord::peekNextArg(TempArg);
336 return TempArg;
339 inline void CPersistentDataRecord::peekNextArg(CPersistentDataRecord::CArg& result) const
341 result.setType(peekNextTokenType());
342 if (result.isExtended())
344 BOMB_IF(_ArgOffset+1>=_ArgTable.size(),"Attempt to overrun end of input data",return);
345 DROP_IF((_TokenTable[_TokenOffset+0]&~7)!=(_TokenTable[_TokenOffset+1]&~7),"2 dwords of 64 bit have non-matching identifiers",return);
346 result._Value.i32_1 = _ArgTable[_ArgOffset+0];
347 result._Value.i32_2 = _ArgTable[_ArgOffset+1];
348 nlassert(result._Value.ExType == result._Value.i32_1);
349 nlassert(result._Value.i32_2 == result._Value.ex32_1);
350 nlassert(result._Value.ExData32 == result._Value.ex32_1);
352 if (result._Type == CArg::EXTEND_TYPE && result._Value.ExType >= CArg::ET_64_BIT_EXTENDED_TYPES)
354 // this is a 96 bit extended type, read one more value
355 BOMB_IF(_ArgOffset+2>=_ArgTable.size(),"Attempt to overrun end of input data",return);
356 BOMB_IF((_TokenTable[_TokenOffset+0]&~7)!=(_TokenTable[_TokenOffset+2]&~7),"3 dwords of 96 bit have non-matching identifiers",return);
357 result._Value.ex32_2 = _ArgTable[_ArgOffset+2];
359 nlassert((uint64(result._Value.ex32_2)<<32|result._Value.ex32_1) == result._Value.ExData64);
362 else if (!result.isFlag())
364 result._Value.i32_1 = _ArgTable[_ArgOffset];
366 if (result._Type==CArg::STRING)
368 result._String=lookupString(result._Value.i32_1);
370 return;
373 //inline CPersistentDataRecord::CArg CPersistentDataRecord::peekNextArg() const
375 // CArg arg;
376 // arg.setType(peekNextTokenType());
377 // if (arg.isExtended())
378 // {
379 // BOMB_IF(_ArgOffset+1>=_ArgTable.size(),"Attempt to overrun end of input data",return arg);
380 // DROP_IF((_TokenTable[_TokenOffset+0]&~7)!=(_TokenTable[_TokenOffset+1]&~7),"2 dwords of 64 bit have non-matching identifiers",return arg);
381 // arg._Value.i32_1 = _ArgTable[_ArgOffset+0];
382 // arg._Value.i32_2 = _ArgTable[_ArgOffset+1];
383 // nlassert(arg._Value.ExType == arg._Value.i32_1);
384 // nlassert(arg._Value.i32_2 == arg._Value.ex32_1);
385 // nlassert(arg._Value.ExData32 == arg._Value.ex32_1);
387 // if (arg._Type == CArg::EXTEND_TYPE && arg._Value.ExType >= CArg::ET_64_BIT_EXTENDED_TYPES)
388 // {
389 // // this is a 96 bit extended type, read one more value
390 // BOMB_IF(_ArgOffset+2>=_ArgTable.size(),"Attempt to overrun end of input data",return arg);
391 // BOMB_IF((_TokenTable[_TokenOffset+0]&~7)!=(_TokenTable[_TokenOffset+2]&~7),"3 dwords of 96 bit have non-matching identifiers",return arg);
392 // arg._Value.ex32_2 = _ArgTable[_ArgOffset+2];
394 // nlassert((uint64(arg._Value.ex32_2)<<32|arg._Value.ex32_1) == arg._Value.ExData64);
395 // }
396 // }
397 // else if (!arg.isFlag())
398 // {
399 // arg._Value.i32_1 = _ArgTable[_ArgOffset];
400 // }
401 // if (arg._Type==CArg::STRING)
402 // {
403 // arg._String=lookupString(arg._Value.i32_1);
404 // }
405 // return arg;
408 inline const CPersistentDataRecord::CArg& CPersistentDataRecord::popNextArg(TToken token)
410 CPersistentDataRecord::popNextArg(token,TempArg);
411 return TempArg;
414 inline void CPersistentDataRecord::popNextArg(TToken token,CPersistentDataRecord::CArg& result)
416 #ifdef NL_DEBUG
417 BOMB_IF(peekNextToken()!=token,"Error on read code - token requested doesn't match token found",return);
418 #else
419 nlunreferenced(token);
420 #endif
422 peekNextArg(result);
423 if (result.isFlag())
425 ++_TokenOffset;
427 else if (result.isExtended())
429 _ArgOffset+=2;
430 _TokenOffset+=2;
432 if (result._Type == CArg::EXTEND_TYPE && result._Value.ExType >= CArg::ET_64_BIT_EXTENDED_TYPES)
434 // this is a 96 bit extended type, skip another pair
435 _ArgOffset++;
436 _TokenOffset++;
439 else
441 ++_ArgOffset;
442 ++_TokenOffset;
446 //inline CPersistentDataRecord::CArg CPersistentDataRecord::popNextArg(TToken token)
448 // CArg arg;
449 // DROP_IF(peekNextToken()!=token,"Error on read code - token requested doesn't match token found",return arg);
450 // arg= peekNextArg();
451 // if (arg.isFlag())
452 // {
453 // ++_TokenOffset;
454 // }
455 // else if (arg.isExtended())
456 // {
457 // _ArgOffset+=2;
458 // _TokenOffset+=2;
460 // if (arg._Type == CArg::EXTEND_TYPE && arg._Value.ExType >= CArg::ET_64_BIT_EXTENDED_TYPES)
461 // {
462 // // this is a 96 bit extended type, skip another pair
463 // _ArgOffset++;
464 // _TokenOffset++;
465 // }
466 // }
467 // else
468 // {
469 // ++_ArgOffset;
470 // ++_TokenOffset;
471 // }
472 // return arg;
475 inline void CPersistentDataRecord::pop(TToken token,bool& result)
477 popNextArg(token,TempArg);
478 result= (TempArg.asSint()!=0);
481 inline void CPersistentDataRecord::pop(TToken token,sint8& result)
483 popNextArg(token,TempArg);
484 result= (sint8)TempArg.asSint();
486 inline void CPersistentDataRecord::pop(TToken token,sint16& result)
488 popNextArg(token,TempArg);
489 result= (sint16)TempArg.asSint();
491 inline void CPersistentDataRecord::pop(TToken token,sint32& result)
493 popNextArg(token,TempArg);
494 result= (sint32)TempArg.asSint();
496 inline void CPersistentDataRecord::pop(TToken token,sint64& result)
498 popNextArg(token,TempArg);
499 result= (sint64)TempArg.asSint();
502 inline void CPersistentDataRecord::pop(TToken token,uint8& result)
504 popNextArg(token,TempArg);
505 result= (uint8)TempArg.asUint();
508 inline void CPersistentDataRecord::pop(TToken token,uint16& result)
510 popNextArg(token,TempArg);
511 result= (uint16)TempArg.asUint();
513 inline void CPersistentDataRecord::pop(TToken token,uint32& result)
515 popNextArg(token,TempArg);
516 result= (uint32)TempArg.asUint();
518 inline void CPersistentDataRecord::pop(TToken token,uint64& result)
520 popNextArg(token,TempArg);
521 result= (uint64)TempArg.asUint();
524 inline void CPersistentDataRecord::pop(TToken token,float& result)
526 popNextArg(token,TempArg);
527 result= TempArg.asFloat();
529 inline void CPersistentDataRecord::pop(TToken token,double& result)
531 popNextArg(token,TempArg);
532 result= TempArg.asDouble();
534 inline void CPersistentDataRecord::pop(TToken token,std::string& result)
536 popNextArg(token,TempArg);
537 result= TempArg.asString();
539 inline void CPersistentDataRecord::pop(TToken token,ucstring& result)
541 popNextArg(token,TempArg);
542 result= TempArg.asUCString();
545 inline void CPersistentDataRecord::pop(TToken token,NLMISC::CSheetId& result)
547 popNextArg(token,TempArg);
548 result= TempArg.asSheetId();
550 inline void CPersistentDataRecord::pop(TToken token,NLMISC::CEntityId& result)
552 popNextArg(token,TempArg);
553 result= TempArg.asEntityId();
556 inline void CPersistentDataRecord::pop(TToken /* token */)
558 ++_TokenOffset;
561 inline void CPersistentDataRecord::popStructBegin(TToken token)
563 DROP_IF(peekNextToken()!=token,"Attempting to enter a structure with the wrong delimiting token",return);
564 DROP_IF(peekNextTokenType()!=CArg::STRUCT_BEGIN,"Attempting to enter a structure with the wrong delimiting token type",return);
565 _ReadingStructStack.push_back(token);
566 ++_TokenOffset;
569 inline void CPersistentDataRecord::popStructEnd(TToken token)
571 DROP_IF(_ReadingStructStack.empty(),"Attempting to pop end of a structure with nothing left in the open structure stack",return);
572 TToken nextToken=peekNextToken();
573 TToken topToken=_ReadingStructStack.back();
574 DROP_IF(topToken!=token,"Attempting to pop end of a structure with the wrong delimiting token",return);
575 DROP_IF(nextToken!=token,"Attempting to pop end of a structure with the wrong delimiting token",return);
576 DROP_IF(peekNextTokenType()!=CArg::STRUCT_END,"Attempting to leave a structure with the wrong delimiting token type",return);
577 _ReadingStructStack.pop_back();
578 ++_TokenOffset;
582 //-------------------------------------------------------------------------
583 // methods CPersistentDataRecord::CArg
584 //-------------------------------------------------------------------------
586 inline CPersistentDataRecord::CArg::CArg()
588 _Type= STRING;
589 _Value.i64= 0;
592 inline CPersistentDataRecord::CArg::CArg(const std::string& type,const std::string& value,CPersistentDataRecord& pdr)
594 if (setType(type)==false)
595 return;
596 switch (_Type)
598 case SINT32: _Value.i32=NLMISC::CSString(value).atoi(); break;
599 case UINT32: _Value.i32=NLMISC::CSString(value).atoi(); break;
600 case SINT64: _Value.i64=NLMISC::atoiInt64(value.c_str()); break;
601 case UINT64: _Value.i64=NLMISC::atoiInt64(value.c_str()); break;
602 case FLOAT32: NLMISC::fromString(value, _Value.f32); break;
603 case FLOAT64: NLMISC::fromString(value, _Value.f64); break;
604 case STRING: _Value.i32=pdr.addString(value); _String=value; break;
605 case EXTEND_TYPE:
606 switch(_Value.ExType)
608 case ET_SHEET_ID:
610 // Cf. CArg::asString()
611 if (value.size() != 0 && value[0] == '#')
613 _Value.ex32_1 = NLMISC::CSString(value.c_str()+1).atoi();
615 else
617 NLMISC::CSheetId sheetId(value);
618 STOP_IF( (sheetId == NLMISC::CSheetId::Unknown && value != "unknown.unknown"), "sheet_id.bin version does not match save game version" );
619 _Value.ExData32 = sheetId.asInt();
622 break;
623 case ET_ENTITY_ID:
625 NLMISC::CEntityId entityId(value);
626 _Value.ExData64 = entityId.getRawId();
628 break;
629 default: STOP("This should never happen!"); break;
631 break;
632 case FLAG: break;
633 default: STOP("This should never happen!"); break;
637 inline uint64 CPersistentDataRecord::CArg::asUint() const
639 switch (_Type)
641 case STRUCT_BEGIN:
642 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return 0);
643 case SINT32: return (uint64)(sint32)_Value.i32;
644 case UINT32: return (uint64)(uint32)_Value.i32; // 2 casts to ensure no sign extend
645 case SINT64: return (uint64)_Value.i64;
646 case UINT64: return (uint64)_Value.i64;
647 case FLOAT32: return (uint64)_Value.f32;
648 case FLOAT64: return (uint64)_Value.f64;
649 case STRING: return (uint64)NLMISC::atoiInt64(_String.c_str());
650 case FLAG: return 1;
651 case EXTEND_TYPE:
652 switch(_Value.ExType)
654 case ET_SHEET_ID: return _Value.ExData32;
655 case ET_ENTITY_ID: return _Value.ExData64;
656 default: break;
658 default: break;
660 STOP("This should never happen!");
661 return 0;
664 inline sint64 CPersistentDataRecord::CArg::asSint() const
666 switch (_Type)
668 case STRUCT_BEGIN:
669 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return 0);
670 case SINT32: return (sint64)(sint32)_Value.i32;
671 case UINT32: return (sint64)(uint32)_Value.i32;
672 case SINT64: return (sint64)_Value.i64;
673 case UINT64: return (sint64)_Value.i64;
674 case FLOAT32: return (sint64)_Value.f32;
675 case FLOAT64: return (sint64)_Value.f64;
676 case STRING: return (sint64)NLMISC::atoiInt64(_String.c_str());
677 case FLAG: return 1;
678 case EXTEND_TYPE:
679 switch(_Value.ExType)
681 case ET_SHEET_ID: return _Value.ExData32;
682 case ET_ENTITY_ID: return _Value.ExData64;
683 default: break;
685 default: break;
687 STOP("This should never happen!");
688 return 0;
691 inline float CPersistentDataRecord::CArg::asFloat() const
693 switch (_Type)
695 case STRUCT_BEGIN:
696 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return 0);
697 case SINT32: return (float)(sint32)_Value.i32;
698 case UINT32: return (float)(uint32)_Value.i32;
699 case SINT64: return (float)(sint64)_Value.i64;
700 case UINT64: return (float)(uint64)_Value.i64;
701 case FLOAT32: return (float)_Value.f32;
702 case FLOAT64: return (float)_Value.f64;
703 case STRING:
705 float val;
706 NLMISC::fromString(_String, val);
707 return val;
709 case FLAG: return 1.0f;
710 case EXTEND_TYPE:
711 switch(_Value.ExType)
713 case ET_SHEET_ID: return float(_Value.ExData32);
714 case ET_ENTITY_ID: return float(_Value.ExData64);
715 default: break;
717 default: break;
719 STOP("This should never happen!");
720 return 0.0f;
723 inline double CPersistentDataRecord::CArg::asDouble() const
725 switch (_Type)
727 case STRUCT_BEGIN:
728 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return 0);
729 case SINT32: return (double)(sint32)_Value.i32;
730 case UINT32: return (double)(uint32)_Value.i32;
731 case SINT64: return (double)(sint64)_Value.i64;
732 case UINT64: return (double)(uint64)_Value.i64;
733 case FLOAT32: return (double)_Value.f32;
734 case FLOAT64: return (double)_Value.f64;
735 case STRING:
737 double val;
738 NLMISC::fromString(_String, val);
739 return val;
741 case FLAG: return 1.0;
742 case EXTEND_TYPE:
743 switch(_Value.ExType)
745 case ET_SHEET_ID: return double(_Value.ExData32);
746 case ET_ENTITY_ID: return double(_Value.ExData64);
747 default: break;
749 default: break;
751 STOP("This should never happen!");
752 return 0.0;
755 inline NLMISC::CSString CPersistentDataRecord::CArg::asString() const
757 switch (_Type)
759 case STRUCT_BEGIN:
760 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return 0);
761 case SINT32: return NLMISC::toString((sint32)_Value.i32);
762 case UINT32: return NLMISC::toString((uint32)_Value.i32);
763 case SINT64: return NLMISC::toString((sint64)_Value.i64);
764 case UINT64: return NLMISC::toString((uint64)_Value.i64);
765 case FLOAT32: return NLMISC::toString(_Value.f32);
766 case FLOAT64: return NLMISC::toString(_Value.f64);
767 case STRING: return _String;
768 case FLAG: return "1";
769 case EXTEND_TYPE:
770 switch(_Value.ExType)
772 case ET_SHEET_ID:
774 NLMISC::CSheetId sheetId(_Value.ExData32);
775 return sheetId.toString(true);
777 case ET_ENTITY_ID:
779 NLMISC::CEntityId entityId(_Value.ExData64);
780 return entityId.toString();
782 default:
783 break;
785 default: break;
787 STOP("This should never happen!");
788 return "";
791 inline ucstring CPersistentDataRecord::CArg::asUCString() const
793 switch (_Type)
795 case STRUCT_BEGIN:
796 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return ucstring());
797 case SINT32: return (ucstring)NLMISC::toString((sint32)_Value.i32);
798 case UINT32: return (ucstring)NLMISC::toString((uint32)_Value.i32);
799 case SINT64: return (ucstring)NLMISC::toString((sint64)_Value.i64);
800 case UINT64: return (ucstring)NLMISC::toString((uint64)_Value.i64);
801 case FLOAT32: return (ucstring)NLMISC::toString(_Value.f32);
802 case FLOAT64: return (ucstring)NLMISC::toString(_Value.f64);
803 case STRING: { ucstring s; s.fromUtf8(_String); return s; }
804 case FLAG: return (ucstring)"1";
805 case EXTEND_TYPE:
806 switch(_Value.ExType)
808 case ET_SHEET_ID:
810 NLMISC::CSheetId sheetId(_Value.ExData32);
811 return sheetId.toString(true);
813 case ET_ENTITY_ID:
815 NLMISC::CEntityId entityId(_Value.ExData64);
816 return entityId.toString();
818 default:
819 break;
821 default: break;
823 STOP("This should never happen!");
824 return ucstring("");
827 inline NLMISC::CEntityId CPersistentDataRecord::CArg::asEntityId() const
829 switch (_Type)
831 case STRUCT_BEGIN:
832 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return NLMISC::CEntityId());
833 case SINT32: return NLMISC::CEntityId((uint64)_Value.i32);
834 case UINT32: return NLMISC::CEntityId((uint64)_Value.i32);
835 case SINT64: return NLMISC::CEntityId((uint64)_Value.i64);
836 case UINT64: return NLMISC::CEntityId((uint64)_Value.i64);
837 case FLOAT32: return NLMISC::CEntityId((uint64)_Value.f32);
838 case FLOAT64: return NLMISC::CEntityId((uint64)_Value.f64);
839 case STRING:
841 // try a convertion from '(0x000000000000000:00:00:00)' format
842 NLMISC::CEntityId result(_String);
844 // if the convertion returned '0' then check for decimal format
845 if (result.asUint64()==0)
847 result= asUint();
850 // return whatever we found
851 return result;
853 case FLAG: return NLMISC::CEntityId();
854 case EXTEND_TYPE:
855 switch(_Value.ExType)
857 case ET_SHEET_ID:
859 return NLMISC::CEntityId();
861 case ET_ENTITY_ID:
862 return NLMISC::CEntityId(_Value.ExData64);
863 default:
864 break;
866 default:
867 break;
869 STOP("This should never happen!");
870 return NLMISC::CEntityId();
875 inline NLMISC::CSheetId CPersistentDataRecord::CArg::asSheetId() const
877 switch (_Type)
879 case STRUCT_BEGIN:
880 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return NLMISC::CSheetId(0u));
881 case SINT32: return NLMISC::CSheetId((uint32)_Value.i32);
882 case UINT32: return NLMISC::CSheetId((uint32)_Value.i32);
883 case SINT64: return NLMISC::CSheetId((uint32)_Value.i64);
884 case UINT64: return NLMISC::CSheetId((uint32)_Value.i64);
885 case FLOAT32: return NLMISC::CSheetId((uint32)_Value.f32);
886 case FLOAT64: return NLMISC::CSheetId((uint32)_Value.f64);
887 case STRING: return NLMISC::CSheetId(_String);
888 case FLAG: return NLMISC::CSheetId();
889 case EXTEND_TYPE:
890 switch(_Value.ExType)
892 case ET_SHEET_ID:
894 return NLMISC::CSheetId (_Value.ExData32);
896 case ET_ENTITY_ID:
897 return NLMISC::CSheetId();
898 default:
899 break;
901 default: break;
903 STOP("This should never happen!");
904 return NLMISC::CSheetId();
907 inline NLMISC::CSString CPersistentDataRecord::CArg::typeName() const
909 switch (_Type)
911 case STRUCT_BEGIN:
912 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return 0);
913 case SINT32: return "SINT32";
914 case UINT32: return "UINT32";
915 case SINT64: return "SINT64";
916 case UINT64: return "UINT64";
917 case FLOAT32: return "FLOAT";
918 case FLOAT64: return "DOUBLE";
919 case STRING: return "STRING";;
920 case FLAG: return "FLAG";
921 case EXTEND_TYPE:
922 switch(_Value.ExType)
924 case ET_SHEET_ID: return "SHEET_ID";
925 case ET_ENTITY_ID: return "ENTITY_ID";
926 default: break;
928 default: break;
930 STOP("This should never happen!");
931 return "";
934 inline bool CPersistentDataRecord::CArg::setType(const std::string &name)
936 _Type=SINT32; if (typeName()==name) return true;
937 _Type=UINT32; if (typeName()==name) return true;
938 _Type=SINT64; if (typeName()==name) return true;
939 _Type=UINT64; if (typeName()==name) return true;
940 _Type=FLOAT32; if (typeName()==name) return true;
941 _Type=FLOAT64; if (typeName()==name) return true;
942 _Type=FLAG; if (typeName()==name) return true;
943 _Type=STRING; if (typeName()==name) return true;
944 // special case for extended types
945 _Type=EXTEND_TYPE;
947 _Value.ExType = ET_SHEET_ID; if (typeName()==name) return true;
948 _Value.ExType = ET_ENTITY_ID; if (typeName()==name) return true;
950 DROP(("Failed to find match for type name '"+name+"' => defaulting to string").c_str(),return false);
953 inline void CPersistentDataRecord::CArg::setType(CPersistentDataRecord::CArg::TType value)
955 BOMB_IF(value<0 || value>=CArg::NB_TYPE,"Invalid argument type",return);
956 _Type=value;
959 inline bool CPersistentDataRecord::CArg::isFlag() const
961 return _Type==FLAG;
964 inline bool CPersistentDataRecord::CArg::isExtended() const
966 return isTypeExtended(_Type);
969 inline void CPersistentDataRecord::CArg::push(TToken token, std::vector<TToken>& tokenTable, std::vector<uint32>& argTable) const
971 BOMB_IF( ((token<<3)>>3)!= token, "Invalid token - Insufficient numeric precision", return);
972 switch (_Type)
974 case FLAG:
975 tokenTable.push_back((token<<3)+CArg::type2Token(_Type));
976 break;
978 case STRING: // drop though to INT32
979 case FLOAT32: // drop though to INT32
980 case SINT32:
981 case UINT32:
982 tokenTable.push_back((token<<3)+CArg::type2Token(_Type));
983 argTable.push_back(_Value.i32);
984 break;
986 case FLOAT64: // drop though to INT64
987 case SINT64:
988 case UINT64:
989 case EXTEND_TYPE:
990 tokenTable.push_back((token<<3)+CArg::EXTEND_TOKEN);
991 argTable.push_back(_Value.i32_1);
992 tokenTable.push_back((token<<3)+CArg::type2Token(_Type));
993 argTable.push_back(_Value.i32_2);
994 if (_Type == EXTEND_TYPE && _Value.ExType >= ET_64_BIT_EXTENDED_TYPES)
996 // 96 bit extended type, add another 32 bit value
997 tokenTable.push_back((token<<3)+CArg::type2Token(_Type));
998 argTable.push_back(_Value.ex32_2);
1000 break;
1002 default:
1003 BOMB("This should never happen!!!",return);
1007 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::EntityId(NLMISC::CEntityId val)
1009 CArg arg;
1010 arg._Type= EXTEND_TYPE;
1011 arg._Value.ExType = ET_ENTITY_ID;
1012 arg._Value.ExData64 = val.getRawId();
1013 return arg;
1017 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::SheetId(NLMISC::CSheetId val)
1019 CArg arg;
1020 arg._Type= EXTEND_TYPE;
1021 arg._Value.ExType = ET_SHEET_ID;
1022 arg._Value.ExData32 = val.asInt();
1023 return arg;
1027 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::Int32(sint32 val)
1029 CArg arg;
1030 arg._Type= SINT32;
1031 arg._Value.i32= val;
1032 return arg;
1035 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::Int32(uint32 val)
1037 CArg arg;
1038 arg._Type= UINT32;
1039 arg._Value.i32= val;
1040 return arg;
1043 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::Int64(sint64 val)
1045 CArg arg;
1046 arg._Type= SINT64;
1047 arg._Value.i64= val;
1048 return arg;
1051 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::Int64(uint64 val)
1053 CArg arg;
1054 arg._Type= UINT64;
1055 arg._Value.i64= val;
1056 return arg;
1059 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::Float32(float val)
1061 CArg arg;
1062 arg._Type= FLOAT32;
1063 arg._Value.f32= val;
1064 return arg;
1067 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::Float64(double val)
1069 CArg arg;
1070 arg._Type= FLOAT64;
1071 arg._Value.f64= val;
1072 return arg;
1075 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::String(const std::string& value,CPersistentDataRecord& pdr)
1077 CArg arg;
1078 arg._Type= STRING;
1079 arg._Value.i32= pdr.addString(value);
1080 arg._String= value;
1081 return arg;
1084 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::UCString(const ucstring& value,CPersistentDataRecord& pdr)
1086 NLMISC::CSString s = value.toUtf8();
1087 CArg arg;
1088 arg._Type= STRING;
1089 arg._Value.i32= pdr.addString(s);
1090 arg._String= s;
1091 return arg;
1094 inline CPersistentDataRecord::CArg CPersistentDataRecord::CArg::Flag()
1096 CArg arg;
1097 arg._Type= FLAG;
1098 arg._Value.i32= 1;
1099 return arg;
1102 inline CPersistentDataRecord::CArg::TType CPersistentDataRecord::CArg::token2Type(uint32 token,bool extend)
1104 switch (token)
1106 case BEGIN_TOKEN: return STRUCT_BEGIN;
1107 case END_TOKEN: return STRUCT_END;
1108 case FLAG_TOKEN: return FLAG;
1109 case SINT_TOKEN: return extend? SINT64: SINT32;
1110 case UINT_TOKEN: return extend? UINT64: UINT32;
1111 case FLOAT_TOKEN: return extend? FLOAT64: FLOAT32;
1112 case STRING_TOKEN: return extend? EXTEND_TYPE: STRING;
1114 STOP("This should never happen!");
1115 return CArg::TType(0);
1118 inline CPersistentDataRecord::TToken CPersistentDataRecord::CArg::type2Token(uint32 type)
1120 switch (type)
1122 case STRUCT_BEGIN: return BEGIN_TOKEN;
1123 case STRUCT_END: return END_TOKEN;
1124 case FLAG: return FLAG_TOKEN;
1125 case SINT32: return SINT_TOKEN;
1126 case UINT32: return UINT_TOKEN;
1127 case FLOAT32: return FLOAT_TOKEN;
1128 case STRING: return STRING_TOKEN;
1129 case SINT64: return SINT_TOKEN;
1130 case UINT64: return UINT_TOKEN;
1131 case FLOAT64: return FLOAT_TOKEN;
1132 case EXTEND_TYPE: return STRING_TOKEN;
1134 STOP("This should never happen!");
1135 return 0;
1138 inline bool CPersistentDataRecord::CArg::isTypeExtended(uint32 type)
1140 switch (type)
1142 case STRUCT_BEGIN:
1143 case STRUCT_END: BOMB("Can't extract a value from a structure delimiter", return 0);
1144 case SINT32:
1145 case UINT32:
1146 case FLOAT32:
1147 case STRING:
1148 case FLAG: return false;
1149 case SINT64:
1150 case UINT64:
1151 case FLOAT64:
1152 case EXTEND_TYPE: return true;
1154 STOP("This should never happen!");
1155 return false;