Show bonus/malus timer text if available
[ryzomcore.git] / nel / src / misc / stream.cpp
blobc652d6fe9530829d1b99690f63949d2046f116c7
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
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 #include "stdmisc.h"
19 #include "nel/misc/stream.h"
20 #include "nel/misc/mem_stream.h"
22 using namespace std;
24 #ifdef DEBUG_NEW
25 #define new DEBUG_NEW
26 #endif
28 namespace NLMISC
32 // ======================================================================================================
33 // ======================================================================================================
34 // EStream.
35 // ======================================================================================================
36 // ======================================================================================================
39 // ======================================================================================================
40 EStream::EStream( const IStream &f ) : Exception( "In Stream: " + f.getStreamName() + string(": Stream Error") )
42 StreamName= f.getStreamName();
45 EStream::EStream( const IStream &f, const std::string& str )
46 : Exception( "In Stream: " + f.getStreamName() + ": " + str )
48 StreamName= f.getStreamName();
51 EInvalidDataStream::EInvalidDataStream(const char *msg, uint size)
52 : EStream( NLMISC::toString( msg, size ) )
56 EStreamOverflow::EStreamOverflow( const char *msg, uint size )
57 : EStream( NLMISC::toString( msg, size ) )
61 // ======================================================================================================
62 // ======================================================================================================
63 // IStream.
64 // ======================================================================================================
65 // ======================================================================================================
68 // ======================================================================================================
69 bool IStream::_ThrowOnOlder=false;
70 bool IStream::_ThrowOnNewer=true;
73 // ======================================================================================================
74 void IStream::setVersionException(bool throwOnOlder, bool throwOnNewer)
76 _ThrowOnOlder=throwOnOlder;
77 _ThrowOnNewer=throwOnNewer;
80 // ======================================================================================================
81 void IStream::getVersionException(bool &throwOnOlder, bool &throwOnNewer)
83 throwOnOlder=_ThrowOnOlder;
84 throwOnNewer=_ThrowOnNewer;
90 * Copy constructor
92 IStream::IStream( const IStream& other )
94 operator=( other );
96 // By default, mode _XML is off
97 _XML = false;
102 * Assignment operator
104 IStream& IStream::operator=( const IStream& other )
106 _InputStream = other._InputStream;
107 resetPtrTable();
108 return *this;
111 void IStream::swap(IStream &other)
113 std::swap(_InputStream, other._InputStream);
114 std::swap(_NextSerialPtrId, other._NextSerialPtrId);
115 _IdMap.swap(other._IdMap);
116 std::swap(_XML, other._XML);
120 // ======================================================================================================
121 // ======================================================================================================
122 // ======================================================================================================
125 // ======================================================================================================
126 void IStream::serialIStreamable(IStreamable* &ptr)
128 uint64 node=0;
130 // Open a node
131 xmlPushBegin ("POLYPTR");
133 if(isReading())
135 // First attribute name
136 xmlSetAttrib ("id");
138 serial(node);
140 if(node==0)
142 ptr=NULL;
144 // Close the node header
145 xmlPushEnd ();
147 else
149 ItIdMap it;
150 it= _IdMap.find(node);
152 // Test if object already created/read.
153 if( it==_IdMap.end() )
155 // Read the class name.
156 string className;
158 // Second attribute name
159 xmlSetAttrib ("class");
161 serial(className);
163 // Close the node header
164 xmlPushEnd ();
166 // Construct object.
167 ptr= dynamic_cast<IStreamable*> (CClassRegistry::create(className));
168 if(ptr==NULL)
169 #ifdef NL_DEBUG
170 throw EUnregisteredClass(className);
171 #else
172 throw EUnregisteredClass();
173 #endif
176 #ifdef NL_DEBUG
177 nlassert(CClassRegistry::checkObject(ptr));
178 #endif
180 // Insert the node.
181 _IdMap.insert( ValueIdMap(node, ptr) );
183 // Read the object!
184 ptr->serial(*this);
186 else
188 ptr= static_cast<IStreamable*>(it->second);
190 // Close the node header
191 xmlPushEnd ();
195 else
197 if(ptr==NULL)
199 node= 0;
201 // First attribute name
202 xmlSetAttrib ("id");
204 serial(node);
206 // Close the node header
207 xmlPushEnd ();
209 else
211 // Assume that prt size is an int size
212 //#ifdef NL_DEBUG
213 // nlassert(sizeof(uint) == sizeof(void *));
214 //#endif
216 ItIdMap it;
217 it = _IdMap.find((uint64)/*(uint)*/ptr);
219 // Test if object has been already written
220 if( it==_IdMap.end() )
222 // Not yet written
224 // Get the next available ID
225 node = _NextSerialPtrId++;
227 // Serial the id
228 xmlSetAttrib ("id");
229 serial(node);
231 // Insert the pointer in the map with the id
232 _IdMap.insert( ValueIdMap((uint64)/*(uint)*/ptr, (void*)/*(uint)*/node) );
234 #ifdef NL_DEBUG
235 nlassert(CClassRegistry::checkObject(ptr));
236 #endif
238 // Write the class name.
239 string className=ptr->getClassName();
241 // Second attribute name
242 xmlSetAttrib ("class");
243 serial(className);
245 // Close the node header
246 xmlPushEnd ();
248 // Write the object!
249 ptr->serial(*this);
251 else
253 // Write only the object id
254 xmlSetAttrib ("id");
255 node = (uint64)/*(uint)*/(it->second);
256 serial(node);
257 xmlPushEnd ();
262 // Close the node
263 xmlPop ();
265 // ======================================================================================================
266 void IStream::resetPtrTable()
268 _IdMap.clear();
269 _NextSerialPtrId = 1; // Start at 1 because 0 is the NULL pointer
273 // ======================================================================================================
274 // ======================================================================================================
275 // ======================================================================================================
278 // ======================================================================================================
279 uint IStream::serialVersion(uint currentVersion)
281 uint8 b=0;
282 uint32 v=0;
283 uint streamVersion;
285 // Open the node
286 xmlPush ("VERSION");
288 if(isReading())
290 serial(b);
291 if(b==0xFF)
292 serial(v);
293 else
294 v=b;
295 streamVersion=v;
297 // Exception test.
298 if(_ThrowOnOlder && streamVersion < currentVersion)
299 throw EOlderStream(*this);
300 if(_ThrowOnNewer && streamVersion > currentVersion)
301 throw ENewerStream(*this);
303 else
305 v= streamVersion=currentVersion;
306 if(v>=0xFF)
308 b=0xFF;
309 serial(b);
310 serial(v);
312 else
314 b= (uint8)v;
315 serial(b);
319 // Close the node
320 xmlPop ();
322 return streamVersion;
326 // ======================================================================================================
327 // ======================================================================================================
328 // ======================================================================================================
330 // ======================================================================================================
331 void IStream::serialCont(vector<uint8> &cont)
333 sint32 len=0;
334 if(isReading())
336 serial(len);
338 // check stream holds enough bytes (avoid STL to crash on resize)
339 checkStreamSize(len);
341 // one block serial
342 cont.resize(len);
343 if (len != 0)
344 serialBuffer( (uint8*)&(*cont.begin()) , len);
346 else
348 len= (sint32)cont.size();
349 serial(len);
350 if (len != 0)
351 serialBuffer( (uint8*)&(*cont.begin()) , len);
354 // ======================================================================================================
355 void IStream::serialCont(vector<sint8> &cont)
357 sint32 len=0;
358 if(isReading())
360 serial(len);
362 // check stream holds enough bytes (avoid STL to crash on resize)
363 checkStreamSize(len);
365 // one block serial
366 cont.resize(len);
367 if (len != 0)
368 serialBuffer( (uint8*)&(*cont.begin()) , len);
370 else
372 len= (sint32)cont.size();
373 serial(len);
374 if (len != 0)
375 serialBuffer( (uint8*)&(*cont.begin()) , len);
378 // ======================================================================================================
379 void IStream::serialCont(vector<bool> &cont)
381 sint32 len=0;
382 vector<uint8> vec;
384 if(isReading())
386 serial(len);
388 // check stream holds enough bytes (avoid STL to crash on resize)
389 checkStreamSize(len/8);
391 // One Block Serial
392 cont.resize(len);
394 if (len != 0)
396 // read as uint8*.
397 sint lb= (len+7)/8;
398 vec.resize(lb);
399 serialBuffer( (uint8*)&(*vec.begin()) , lb);
400 for(sint i=0;i<len;i++)
402 uint bit= (vec[i>>3]>>(i&7)) & 1;
403 cont[i]= bit?true:false;
407 else
409 len= (sint32)cont.size();
410 serial(len);
412 if (len != 0)
414 // write as uint8*.
415 sint lb= (len+7)/8;
416 vec.resize(lb);
417 fill_n(vec.begin(), lb, 0);
418 for(sint i=0;i<len;i++)
420 uint bit= cont[i]?1:0;
421 vec[i>>3]|= bit<<(i&7);
423 serialBuffer( (uint8*)&(*vec.begin()) , lb);
428 // ======================================================================================================
429 bool IStream::seek (sint32 offset, TSeekOrigin origin) const
431 throw ESeekNotSupported(*this);
433 // ======================================================================================================
434 sint32 IStream::getPos () const
436 throw ESeekNotSupported(*this);
439 // ======================================================================================================
440 void IStream::setInOut(bool inputStream)
442 _InputStream= inputStream;
446 // ======================================================================================================
447 string IStream::getStreamName() const
449 return "";
453 // ======================================================================================================
454 void IStream::setXMLMode (bool on)
456 _XML = on;
461 * Serial memstream, bitmemstream...
463 void IStream::serialMemStream( CMemStream &b )
465 uint32 len=0;
467 // Serialize length
468 if ( isReading() )
470 // fill b with data from this
471 serial (len);
472 serialBuffer (b.bufferToFill (len), len);
473 b.resetBufPos ();
475 else
477 // fill this with data from b
478 len = b.length();
480 serial( len );
481 serialBuffer( (uint8*) b.buffer (), len );