00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef NL_MEM_STREAM_H
00027 #define NL_MEM_STREAM_H
00028
00029 #include "nel/misc/types_nl.h"
00030 #include "nel/misc/stream.h"
00031 #include "nel/misc/object_vector.h"
00032 #include "nel/misc/fast_mem.h"
00033
00034 namespace NLMISC
00035 {
00036
00038 struct EMemStream : public NLMISC::EStream
00039 {
00040 EMemStream( const std::string& str ) : EStream( str ) {}
00041 };
00042
00044 struct EStreamOverflow : public EMemStream
00045 {
00046 EStreamOverflow() : EMemStream( "Stream Overflow Error" ) {}
00047 };
00048
00049
00051
00052
00054
00055
00056
00057
00064 class CMemStream : public NLMISC::IStream
00065 {
00066 public:
00067
00069 CMemStream( bool inputStream=false, bool stringmode=false, uint32 defaultcapacity=0 ) :
00070 NLMISC::IStream( inputStream ), _StringMode( stringmode )
00071 {
00072 _DefaultCapacity = std::max( defaultcapacity, (uint32)16 );
00073 _Buffer.resize (_DefaultCapacity);
00074 _BufPos = _Buffer.getPtr();
00075 }
00076
00078 CMemStream( const CMemStream& other ) :
00079 IStream (other)
00080 {
00081 operator=( other );
00082 }
00083
00085 CMemStream& operator=( const CMemStream& other )
00086 {
00087 IStream::operator= (other);
00088 _Buffer = other._Buffer;
00089 _BufPos = _Buffer.getPtr() + other.lengthS();
00090 _StringMode = other._StringMode;
00091 _DefaultCapacity = other._DefaultCapacity;
00092 return *this;
00093 }
00094
00096 void setStringMode( bool stringmode ) { _StringMode = stringmode; }
00097
00099 bool stringMode() const { return _StringMode; }
00100
00102 virtual void serialBuffer(uint8 *buf, uint len);
00103
00105 virtual void serialBit(bool &bit);
00106
00118 virtual bool seek (sint32 offset, TSeekOrigin origin) throw(EStream);
00119
00131 virtual sint32 getPos () throw(EStream)
00132 {
00133 return _BufPos - _Buffer.getPtr();
00134 }
00135
00137 virtual void clear()
00138 {
00139 resetPtrTable();
00140 _Buffer.clear();
00141 if (!isReading())
00142 {
00143 _Buffer.resize (_DefaultCapacity);
00144 }
00145 _BufPos = _Buffer.getPtr();
00146 }
00147
00152 virtual uint32 length() const
00153 {
00154 if ( isReading() )
00155 {
00156 return lengthR();
00157 }
00158 else
00159 {
00160 return lengthS();
00161 }
00162 }
00163
00167 const uint8 *buffer() const
00168 {
00169 return _Buffer.getPtr();
00170
00171
00172
00173
00174
00175
00176
00177
00178 }
00179
00180
00181
00182
00183
00184
00185
00187
00188
00189
00190
00191
00192
00193 void resetBufPos() { _BufPos = _Buffer.getPtr(); }
00194
00196 void fill( const uint8 *srcbuf, uint32 len )
00197 {
00198 if (len == 0) return;
00199
00200 _Buffer.resize( len );
00201 CFastMem::memcpy( _Buffer.getPtr(), srcbuf, len );
00202 if (isReading())
00203 {
00204 _BufPos = _Buffer.getPtr();
00205 }
00206 else
00207 {
00208 _BufPos = _Buffer.getPtr() + _Buffer.size();
00209 }
00210 }
00211
00212 void resize (uint32 size);
00213
00218 uint8 *bufferToFill( uint32 msgsize )
00219 {
00220 if (msgsize == 0) return NULL;
00221
00222
00223 _Buffer.resize( msgsize );
00224 _BufPos = _Buffer.getPtr() + msgsize;
00225 return _Buffer.getPtr();
00226 }
00227
00229 virtual void invert()
00230 {
00231 if ( isReading() )
00232 {
00233
00234 resetPtrTable();
00235 setInOut( false );
00236 _BufPos = _Buffer.getPtr()+_Buffer.size();
00237 }
00238 else
00239 {
00240
00241 resetPtrTable();
00242 setInOut( true );
00243 _Buffer.resize (_BufPos - _Buffer.getPtr());
00244 _BufPos = _Buffer.getPtr();
00245 }
00246 }
00247
00249 void resetPtrTable() { IStream::resetPtrTable() ; }
00250
00252 #ifdef NL_OS_WINDOWS
00253 __forceinline
00254 #endif
00255 void increaseBufferIfNecessary(uint32 len)
00256 {
00257 uint32 oldBufferSize = _Buffer.size();
00258 if (_BufPos - _Buffer.getPtr() + len > oldBufferSize)
00259 {
00260
00261 uint32 pos = _BufPos - _Buffer.getPtr();
00262 _Buffer.resize(oldBufferSize*2 + len);
00263 _BufPos = _Buffer.getPtr() + pos;
00264 }
00265 }
00266
00267
00268 template <class T> void fastSerial (T &val)
00269 {
00270 #ifdef NL_LITTLE_ENDIAN
00271 if(isReading())
00272 {
00273
00274
00275 if ( lengthS()+sizeof(T) > lengthR() )
00276 throw EStreamOverflow();
00277
00278 val = *(T*)_BufPos;
00279 }
00280 else
00281 {
00282 increaseBufferIfNecessary (sizeof(T));
00283 *(T*)_BufPos = val;
00284 }
00285 _BufPos += sizeof (T);
00286 #else // NL_LITTLE_ENDIAN
00287 IStream::serial( val );
00288 #endif // NL_LITTLE_ENDIAN
00289 }
00290
00291 template <class T>
00292 void fastWrite( T& value )
00293 {
00294
00295 increaseBufferIfNecessary (sizeof(T));
00296 *(T*)_BufPos = value;
00297 _BufPos += sizeof (T);
00298 }
00299
00300 template <class T>
00301 void fastRead( T& value )
00302 {
00303
00304
00305 if ( lengthS()+sizeof(value) > lengthR() )
00306 {
00307 throw EStreamOverflow();
00308 }
00309
00310 value = *(T*)_BufPos;
00311 _BufPos += sizeof(value);
00312 }
00313
00314
00316 template<class T>
00317 void serial(T &obj) { obj.serial(*this); }
00318
00319 template<class T>
00320 void serialCont(std::vector<T> &cont) {IStream::serialCont(cont);}
00321 template<class T>
00322 void serialCont(std::list<T> &cont) {IStream::serialCont(cont);}
00323 template<class T>
00324 void serialCont(std::deque<T> &cont) {IStream::serialCont(cont);}
00325 template<class T>
00326 void serialCont(std::set<T> &cont) {IStream::serialCont(cont);}
00327 template<class T>
00328 void serialCont(std::multiset<T> &cont) {IStream::serialCont(cont);}
00329 template<class K, class T>
00330 void serialCont(std::map<K, T> &cont) {IStream::serialCont(cont);}
00331 template<class K, class T>
00332 void serialCont(std::multimap<K, T> &cont) {IStream::serialCont(cont);}
00333
00335 virtual void serialCont(std::vector<uint8> &cont) {IStream::serialCont(cont);}
00337 virtual void serialCont(std::vector<sint8> &cont) {IStream::serialCont(cont);}
00339 virtual void serialCont(std::vector<bool> &cont) {IStream::serialCont(cont);}
00340
00341
00342
00343 template<class T0,class T1>
00344 void serial(T0 &a, T1 &b)
00345 { serial(a); serial(b);}
00346 template<class T0,class T1,class T2>
00347 void serial(T0 &a, T1 &b, T2 &c)
00348 { serial(a); serial(b); serial(c);}
00349 template<class T0,class T1,class T2,class T3>
00350 void serial(T0 &a, T1 &b, T2 &c, T3 &d)
00351 { serial(a); serial(b); serial(c); serial(d);}
00352 template<class T0,class T1,class T2,class T3,class T4>
00353 void serial(T0 &a, T1 &b, T2 &c, T3 &d, T4 &e)
00354 { serial(a); serial(b); serial(c); serial(d); serial(e);}
00355 template<class T0,class T1,class T2,class T3,class T4,class T5>
00356 void serial(T0 &a, T1 &b, T2 &c, T3 &d, T4 &e, T5 &f)
00357 { serial(a); serial(b); serial(c); serial(d); serial(e); serial(f);}
00358
00363 virtual void serial(uint8 &b) ;
00364 virtual void serial(sint8 &b) ;
00365 virtual void serial(uint16 &b) ;
00366 virtual void serial(sint16 &b) ;
00367 virtual void serial(uint32 &b) ;
00368 virtual void serial(sint32 &b) ;
00369 virtual void serial(uint64 &b) ;
00370 virtual void serial(sint64 &b) ;
00371 virtual void serial(float &b) ;
00372 virtual void serial(double &b) ;
00373 virtual void serial(bool &b) ;
00374 #ifndef NL_OS_CYGWIN
00375 virtual void serial(char &b) ;
00376 #endif
00377 virtual void serial(std::string &b) ;
00378 virtual void serial(ucstring &b) ;
00380
00381
00383
00384
00386 uint serialSeparatedBufferIn( uint8 *buf, uint len );
00387
00389 void serialSeparatedBufferOut( uint8 *buf, uint len );
00390
00392 virtual void serialHex(uint32 &b);
00393
00395
00396 protected:
00397
00399 uint32 lengthS() const
00400 {
00401 return _BufPos-_Buffer.getPtr();
00402 }
00403
00405 uint32 lengthR() const
00406 {
00407
00408 return _Buffer.size();
00409 }
00410
00411 CObjectVector<uint8, false> _Buffer;
00412 uint8 *_BufPos;
00413
00414
00415
00416 bool _StringMode;
00417
00418 uint32 _DefaultCapacity;
00419 };
00420
00421
00422 #define readnumber(dest,thetype,digits,convfunc) \
00423 char number_as_cstring [digits+1]; \
00424 uint realdigits = serialSeparatedBufferIn( (uint8*)&number_as_cstring, digits ); \
00425 number_as_cstring[realdigits] = '\0'; \
00426 dest = (thetype)convfunc( number_as_cstring );
00427
00428
00429 #define writenumber(src,format,digits) \
00430 char number_as_cstring [digits+1]; \
00431 sprintf( number_as_cstring, format, src ); \
00432 serialSeparatedBufferOut( (uint8*)&number_as_cstring, strlen(number_as_cstring) );
00433
00434
00435
00436
00437 inline int atoihex( const char* ident )
00438 {
00439 int number;
00440 sscanf( ident, "%x", &number );
00441 return number;
00442 }
00443
00444 inline uint32 atoui( const char *ident)
00445 {
00446 return (uint32) strtoul (ident, NULL, 10);
00447 }
00448
00449 const char SEPARATOR = ' ';
00450 const int SEP_SIZE = 1;
00451
00452
00453
00454
00455
00456
00457
00458 inline void CMemStream::serial(uint8 &b)
00459 {
00460 if ( _StringMode )
00461 {
00462 if ( isReading() )
00463 {
00464 readnumber( b, uint8, 3, atoi );
00465 }
00466 else
00467 {
00468 writenumber( (uint16)b,"%hu", 3 );
00469 }
00470 }
00471 else
00472 {
00473 fastSerial (b);
00474 }
00475 }
00476
00477
00478 inline void CMemStream::serial(sint8 &b)
00479 {
00480 if ( _StringMode )
00481 {
00482 if ( isReading() )
00483 {
00484 readnumber( b, sint8, 4, atoi );
00485 }
00486 else
00487 {
00488 writenumber( (sint16)b, "%hd", 4 );
00489 }
00490 }
00491 else
00492 {
00493 fastSerial (b);
00494 }
00495 }
00496
00497
00498 inline void CMemStream::serial(uint16 &b)
00499 {
00500 if ( _StringMode )
00501 {
00502
00503 if ( isReading() )
00504 {
00505 readnumber( b, uint16, 5, atoi );
00506 }
00507 else
00508 {
00509 writenumber( b, "%hu", 5 );
00510 }
00511 }
00512 else
00513 {
00514 fastSerial (b);
00515 }
00516 }
00517
00518
00519 inline void CMemStream::serial(sint16 &b)
00520 {
00521 if ( _StringMode )
00522 {
00523 if ( isReading() )
00524 {
00525 readnumber( b, sint16, 6, atoi );
00526 }
00527 else
00528 {
00529 writenumber( b, "%hd", 6 );
00530 }
00531 }
00532 else
00533 {
00534 fastSerial (b);
00535 }
00536 }
00537
00538
00539 inline void CMemStream::serial(uint32 &b)
00540 {
00541 if ( _StringMode )
00542 {
00543 if ( isReading() )
00544 {
00545 readnumber( b, uint32, 10, atoui );
00546 }
00547 else
00548 {
00549 writenumber( b, "%u", 10 );
00550 }
00551 }
00552 else
00553 {
00554 fastSerial (b);
00555 }
00556 }
00557
00558
00559
00560 inline void CMemStream::serial(sint32 &b)
00561 {
00562 if ( _StringMode )
00563 {
00564 if ( isReading() )
00565 {
00566 readnumber( b, sint32, 11, atoi );
00567 }
00568 else
00569 {
00570 writenumber( b, "%d", 11 );
00571 }
00572 }
00573 else
00574 {
00575 fastSerial (b);
00576 }
00577 }
00578
00579
00580 inline void CMemStream::serial(uint64 &b)
00581 {
00582 if ( _StringMode )
00583 {
00584 if ( isReading() )
00585 {
00586 readnumber( b, uint64, 20, atoiInt64 );
00587 }
00588 else
00589 {
00590 writenumber( b, "%"NL_I64"u", 20 );
00591 }
00592 }
00593 else
00594 {
00595 fastSerial (b);
00596 }
00597 }
00598
00599
00600 inline void CMemStream::serial(sint64 &b)
00601 {
00602 if ( _StringMode )
00603 {
00604 if ( isReading() )
00605 {
00606 readnumber( b, sint64, 20, atoiInt64 );
00607 }
00608 else
00609 {
00610 writenumber( b, "%"NL_I64"d", 20 );
00611 }
00612 }
00613 else
00614 {
00615 fastSerial (b);
00616 }
00617 }
00618
00619
00620 inline void CMemStream::serial(float &b)
00621 {
00622 if ( _StringMode )
00623 {
00624 if ( isReading() )
00625 {
00626 readnumber( b, float, 128, atof );
00627 }
00628 else
00629 {
00630 writenumber( (double)b, "%f", 128 );
00631 }
00632 }
00633 else
00634 {
00635 fastSerial (b);
00636 }
00637 }
00638
00639
00640 inline void CMemStream::serial(double &b)
00641 {
00642 if ( _StringMode )
00643 {
00644 if ( isReading() )
00645 {
00646 readnumber( b, double, 128, atof );
00647 }
00648 else
00649 {
00650 writenumber( b, "%f", 128 );
00651 }
00652 }
00653 else
00654 {
00655 fastSerial (b);
00656 }
00657 }
00658
00659
00660 inline void CMemStream::serial(bool &b)
00661 {
00662 if ( _StringMode )
00663 {
00664 serialBit(b);
00665 }
00666 else
00667 {
00668 fastSerial (b);
00669 }
00670 }
00671
00672
00673 #ifndef NL_OS_CYGWIN
00674
00675 inline void CMemStream::serial(char &b)
00676 {
00677 if ( _StringMode )
00678 {
00679 char buff [2];
00680 if ( isReading() )
00681 {
00682 serialBuffer( (uint8*)buff, 2 );
00683 b = buff[0];
00684 }
00685 else
00686 {
00687 buff[0] = b;
00688 buff[1] = SEPARATOR;
00689 serialBuffer( (uint8*)buff, 2 );
00690 }
00691 }
00692 else
00693 {
00694 fastSerial (b);
00695 }
00696 }
00697 #endif
00698
00699
00700 inline void CMemStream::serial(std::string &b)
00701 {
00702 if ( _StringMode )
00703 {
00704 sint32 len=0;
00705
00706 if(isReading())
00707 {
00708 serial(len);
00709 nlassert( len<1000000 );
00710 b.resize(len);
00711 }
00712 else
00713 {
00714 len= b.size();
00715 serial(len);
00716 }
00717
00718
00719 for(sint i=0;i<len;i++)
00720 serialBuffer( (uint8*)&(b[i]), sizeof(b[i]) );
00721
00722 char sep = SEPARATOR;
00723 serialBuffer( (uint8*)&sep, 1 );
00724 }
00725 else
00726 {
00727 IStream::serial( b );
00728 }
00729 }
00730
00731
00732
00733 inline void CMemStream::serial(ucstring &b)
00734 {
00735 if ( _StringMode )
00736 {
00737 sint32 len=0;
00738
00739 if(isReading())
00740 {
00741 serial(len);
00742 b.resize(len);
00743 }
00744 else
00745 {
00746 len= b.size();
00747 serial(len);
00748 }
00749
00750 for(sint i=0;i<len;i++)
00751 serialBuffer( (uint8*)&b[i], sizeof( sizeof(b[i]) ) );
00752
00753 char sep = SEPARATOR;
00754 serialBuffer( (uint8*)&sep, 1 );
00755 }
00756 else
00757 {
00758 IStream::serial( b );
00759 }
00760 }
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 inline void CMemStream::serialHex(uint32 &b)
00800 {
00801 if ( _StringMode )
00802 {
00803 if ( isReading() )
00804 {
00805 readnumber( b, uint32, 10, atoihex );
00806 }
00807 else
00808 {
00809 writenumber( b, "%x", 10 );
00810 }
00811 }
00812 else
00813 {
00814 IStream::serial( b );
00815 }
00816 }
00817
00818
00819
00820
00821
00822
00823
00824
00825 }
00826
00827 #endif // NL_MEM_STREAM_H
00828
00829