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/>.
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
)
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)
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
52 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
64 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
76 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
88 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
104 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
118 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
130 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
142 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
158 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
175 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
191 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
205 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
223 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
243 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
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
254 BOMB_IF( ((token
<<3)>>3)!= token
, "Invalid token - Insufficient numeric precision", return);
257 _TokenTable
.push_back(token
<<3|CArg::STRUCT_BEGIN
);
258 _WritingStructStack
.push_back(token
);
261 inline void CPersistentDataRecord::pushStructEnd(TToken token
)
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);
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
288 if (_ReadingStructStack
.empty())
290 if (peekNextTokenType()!=CArg::STRUCT_END
)
292 DROP_IF(_ReadingStructStack
.back()!=peekNextToken(),"Opening and closing structure tokens don't match",return false)
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
);
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
);
373 //inline CPersistentDataRecord::CArg CPersistentDataRecord::peekNextArg() const
376 // arg.setType(peekNextTokenType());
377 // if (arg.isExtended())
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)
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);
397 // else if (!arg.isFlag())
399 // arg._Value.i32_1 = _ArgTable[_ArgOffset];
401 // if (arg._Type==CArg::STRING)
403 // arg._String=lookupString(arg._Value.i32_1);
408 inline const CPersistentDataRecord::CArg
& CPersistentDataRecord::popNextArg(TToken token
)
410 CPersistentDataRecord::popNextArg(token
,TempArg
);
414 inline void CPersistentDataRecord::popNextArg(TToken token
,CPersistentDataRecord::CArg
& result
)
417 BOMB_IF(peekNextToken()!=token
,"Error on read code - token requested doesn't match token found",return);
419 nlunreferenced(token
);
427 else if (result
.isExtended())
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
446 //inline CPersistentDataRecord::CArg CPersistentDataRecord::popNextArg(TToken token)
449 // DROP_IF(peekNextToken()!=token,"Error on read code - token requested doesn't match token found",return arg);
450 // arg= peekNextArg();
455 // else if (arg.isExtended())
460 // if (arg._Type == CArg::EXTEND_TYPE && arg._Value.ExType >= CArg::ET_64_BIT_EXTENDED_TYPES)
462 // // this is a 96 bit extended type, skip another pair
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 */)
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
);
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();
582 //-------------------------------------------------------------------------
583 // methods CPersistentDataRecord::CArg
584 //-------------------------------------------------------------------------
586 inline CPersistentDataRecord::CArg::CArg()
592 inline CPersistentDataRecord::CArg::CArg(const std::string
& type
,const std::string
& value
,CPersistentDataRecord
& pdr
)
594 if (setType(type
)==false)
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;
606 switch(_Value
.ExType
)
610 // Cf. CArg::asString()
611 if (value
.size() != 0 && value
[0] == '#')
613 _Value
.ex32_1
= NLMISC::CSString(value
.c_str()+1).atoi();
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();
625 NLMISC::CEntityId
entityId(value
);
626 _Value
.ExData64
= entityId
.getRawId();
629 default: STOP("This should never happen!"); break;
633 default: STOP("This should never happen!"); break;
637 inline uint64
CPersistentDataRecord::CArg::asUint() const
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());
652 switch(_Value
.ExType
)
654 case ET_SHEET_ID
: return _Value
.ExData32
;
655 case ET_ENTITY_ID
: return _Value
.ExData64
;
660 STOP("This should never happen!");
664 inline sint64
CPersistentDataRecord::CArg::asSint() const
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());
679 switch(_Value
.ExType
)
681 case ET_SHEET_ID
: return _Value
.ExData32
;
682 case ET_ENTITY_ID
: return _Value
.ExData64
;
687 STOP("This should never happen!");
691 inline float CPersistentDataRecord::CArg::asFloat() const
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
;
706 NLMISC::fromString(_String
, val
);
709 case FLAG
: return 1.0f
;
711 switch(_Value
.ExType
)
713 case ET_SHEET_ID
: return float(_Value
.ExData32
);
714 case ET_ENTITY_ID
: return float(_Value
.ExData64
);
719 STOP("This should never happen!");
723 inline double CPersistentDataRecord::CArg::asDouble() const
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
;
738 NLMISC::fromString(_String
, val
);
741 case FLAG
: return 1.0;
743 switch(_Value
.ExType
)
745 case ET_SHEET_ID
: return double(_Value
.ExData32
);
746 case ET_ENTITY_ID
: return double(_Value
.ExData64
);
751 STOP("This should never happen!");
755 inline NLMISC::CSString
CPersistentDataRecord::CArg::asString() const
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";
770 switch(_Value
.ExType
)
774 NLMISC::CSheetId
sheetId(_Value
.ExData32
);
775 return sheetId
.toString(true);
779 NLMISC::CEntityId
entityId(_Value
.ExData64
);
780 return entityId
.toString();
787 STOP("This should never happen!");
791 inline ucstring
CPersistentDataRecord::CArg::asUCString() const
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";
806 switch(_Value
.ExType
)
810 NLMISC::CSheetId
sheetId(_Value
.ExData32
);
811 return sheetId
.toString(true);
815 NLMISC::CEntityId
entityId(_Value
.ExData64
);
816 return entityId
.toString();
823 STOP("This should never happen!");
827 inline NLMISC::CEntityId
CPersistentDataRecord::CArg::asEntityId() const
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
);
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)
850 // return whatever we found
853 case FLAG
: return NLMISC::CEntityId();
855 switch(_Value
.ExType
)
859 return NLMISC::CEntityId();
862 return NLMISC::CEntityId(_Value
.ExData64
);
869 STOP("This should never happen!");
870 return NLMISC::CEntityId();
875 inline NLMISC::CSheetId
CPersistentDataRecord::CArg::asSheetId() const
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();
890 switch(_Value
.ExType
)
894 return NLMISC::CSheetId (_Value
.ExData32
);
897 return NLMISC::CSheetId();
903 STOP("This should never happen!");
904 return NLMISC::CSheetId();
907 inline NLMISC::CSString
CPersistentDataRecord::CArg::typeName() const
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";
922 switch(_Value
.ExType
)
924 case ET_SHEET_ID
: return "SHEET_ID";
925 case ET_ENTITY_ID
: return "ENTITY_ID";
930 STOP("This should never happen!");
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
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);
959 inline bool CPersistentDataRecord::CArg::isFlag() const
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);
975 tokenTable
.push_back((token
<<3)+CArg::type2Token(_Type
));
978 case STRING
: // drop though to INT32
979 case FLOAT32
: // drop though to INT32
982 tokenTable
.push_back((token
<<3)+CArg::type2Token(_Type
));
983 argTable
.push_back(_Value
.i32
);
986 case FLOAT64
: // drop though to INT64
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
);
1003 BOMB("This should never happen!!!",return);
1007 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::EntityId(NLMISC::CEntityId val
)
1010 arg
._Type
= EXTEND_TYPE
;
1011 arg
._Value
.ExType
= ET_ENTITY_ID
;
1012 arg
._Value
.ExData64
= val
.getRawId();
1017 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::SheetId(NLMISC::CSheetId val
)
1020 arg
._Type
= EXTEND_TYPE
;
1021 arg
._Value
.ExType
= ET_SHEET_ID
;
1022 arg
._Value
.ExData32
= val
.asInt();
1027 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::Int32(sint32 val
)
1031 arg
._Value
.i32
= val
;
1035 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::Int32(uint32 val
)
1039 arg
._Value
.i32
= val
;
1043 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::Int64(sint64 val
)
1047 arg
._Value
.i64
= val
;
1051 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::Int64(uint64 val
)
1055 arg
._Value
.i64
= val
;
1059 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::Float32(float val
)
1063 arg
._Value
.f32
= val
;
1067 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::Float64(double val
)
1071 arg
._Value
.f64
= val
;
1075 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::String(const std::string
& value
,CPersistentDataRecord
& pdr
)
1079 arg
._Value
.i32
= pdr
.addString(value
);
1084 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::UCString(const ucstring
& value
,CPersistentDataRecord
& pdr
)
1086 NLMISC::CSString s
= value
.toUtf8();
1089 arg
._Value
.i32
= pdr
.addString(s
);
1094 inline CPersistentDataRecord::CArg
CPersistentDataRecord::CArg::Flag()
1102 inline CPersistentDataRecord::CArg::TType
CPersistentDataRecord::CArg::token2Type(uint32 token
,bool extend
)
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
)
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!");
1138 inline bool CPersistentDataRecord::CArg::isTypeExtended(uint32 type
)
1143 case STRUCT_END
: BOMB("Can't extract a value from a structure delimiter", return 0);
1148 case FLAG
: return false;
1152 case EXTEND_TYPE
: return true;
1154 STOP("This should never happen!");