00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef NL_MEM_STREAM_H
00025 #define NL_MEM_STREAM_H
00026
00027 #include "types_nl.h"
00028 #include "stream.h"
00029 #include "object_vector.h"
00030 #include "fast_mem.h"
00031 #include "smart_ptr.h"
00032
00033 #include <algorithm>
00034
00035 namespace NLMISC
00036 {
00037
00039 struct EMemStream : public NLMISC::EStream
00040 {
00041 EMemStream( const std::string& str ) : EStream( str ) {}
00042 };
00043
00044
00056 class CMemStreamBuffer
00057 {
00058 public:
00059 typedef CObjectVector<uint8, false> TBuffer;
00060 private:
00061 struct TMemStreamBuffer : public CRefCount
00062 {
00063
00064 TBuffer _Buffer;
00065 };
00066
00067 typedef CSmartPtr<TMemStreamBuffer> TMemStreamBufferPtr;
00068
00069 TMemStreamBufferPtr _SharedBuffer;
00070
00071 public:
00072
00073 mutable uint32 Pos;
00074
00076 CMemStreamBuffer()
00077 {
00078 _SharedBuffer = new TMemStreamBuffer;
00079 Pos = 0;
00080 }
00081
00082
00084 const TBuffer &getBuffer() const
00085 {
00086 return _SharedBuffer->_Buffer;
00087 }
00088
00092 TBuffer &getBufferWrite()
00093 {
00094 if (_SharedBuffer->getRefCount() > 1)
00095 {
00096
00097 _SharedBuffer = new TMemStreamBuffer(*_SharedBuffer);
00098 }
00099 return _SharedBuffer->_Buffer;
00100 }
00101
00103 void swap(CMemStreamBuffer &other)
00104 {
00105 std::swap(_SharedBuffer, other._SharedBuffer);
00106 std::swap(Pos, other.Pos);
00107 }
00108
00109 };
00110
00111
00140 class CMemStream : public NLMISC::IStream
00141 {
00142 public:
00143
00145 CMemStream( bool inputStream=false, bool stringmode=false, uint32 defaultcapacity=0 ) :
00146 NLMISC::IStream( inputStream ), _StringMode( stringmode )
00147 {
00148 _DefaultCapacity = std::max( (uint32)defaultcapacity, (uint32)16 );
00149 _Buffer.getBufferWrite().resize (_DefaultCapacity);
00150 _Buffer.Pos = 0;
00151 }
00152
00154 CMemStream( const CMemStream& other ) :
00155 IStream (other)
00156 {
00157 operator=( other );
00158 }
00159
00161 CMemStream& operator=( const CMemStream& other )
00162 {
00163 IStream::operator= (other);
00164 _Buffer = other._Buffer;
00165 _StringMode = other._StringMode;
00166 _DefaultCapacity = other._DefaultCapacity;
00167 return *this;
00168 }
00169
00171 void swap(CMemStream &other);
00172
00174 void setStringMode( bool stringmode ) { _StringMode = stringmode; }
00175
00177 bool stringMode() const { return _StringMode; }
00178
00183 std::string toString( bool hexFormat=false ) const;
00184
00186 virtual void serialBuffer(uint8 *buf, uint len);
00187
00189 virtual void serialBit(bool &bit);
00190
00207 virtual bool seek (sint32 offset, TSeekOrigin origin) const throw(EStream);
00208
00220 virtual sint32 getPos () const throw(EStream)
00221 {
00222 return sint32(_Buffer.Pos);
00223 }
00224
00229 sint32 reserve( uint len )
00230 {
00231 sint32 pos = sint32(_Buffer.Pos);
00232 if ( ! isReading() )
00233 {
00234 increaseBufferIfNecessary( len );
00235 _Buffer.Pos += len;
00236 }
00237 return pos;
00238 }
00239
00250 template <class T>
00251 void poke( T value, sint32 pos )
00252 {
00253 if ( ! isReading() )
00254 {
00255 uint8 *pokeBufPos = _Buffer.getBufferWrite().getPtr() + pos;
00256 nlassert( pokeBufPos + sizeof(T) <= pokeBufPos+_Buffer.Pos );
00257 *(T*)pokeBufPos = value;
00258 }
00259 }
00260
00262 virtual void clear()
00263 {
00264 resetPtrTable();
00265 _Buffer.getBufferWrite().clear();
00266 if (!isReading())
00267 {
00268 _Buffer.getBufferWrite().resize (_DefaultCapacity);
00269 }
00270 _Buffer.Pos = 0;
00271 }
00272
00278 virtual uint32 length() const
00279 {
00280 if ( isReading() )
00281 {
00282 return lengthR();
00283 }
00284 else
00285 {
00286 return lengthS();
00287 }
00288 }
00289
00291 uint32 size() const
00292 {
00293 return _Buffer.getBuffer().size();
00294 }
00295
00299 virtual const uint8 *buffer() const
00300 {
00301 return _Buffer.getBuffer().getPtr();
00302 }
00303
00304
00311 void resetBufPos() { _Buffer.Pos = 0; }
00312
00318 void fill( const uint8 *srcbuf, uint32 len )
00319 {
00320 if (len == 0) return;
00321
00322 _Buffer.getBufferWrite().resize( len );
00323 CFastMem::memcpy( _Buffer.getBufferWrite().getPtr(), srcbuf, len );
00324 if (isReading())
00325 {
00326 _Buffer.Pos = 0;
00327 }
00328 else
00329 {
00330 _Buffer.Pos = _Buffer.getBuffer().size();
00331 }
00332 }
00333
00338 void resize (uint32 size);
00339
00350 uint8 *bufferToFill( uint32 msgsize )
00351 {
00352 #ifdef NL_DEBUG
00353 nlassert( isReading() );
00354 #endif
00355 if ( msgsize == 0 )
00356 return NULL;
00357
00358 _Buffer.getBufferWrite().resize( msgsize );
00359 _Buffer.Pos = 0;
00360 return _Buffer.getBufferWrite().getPtr();
00361 }
00362
00373 virtual void invert()
00374 {
00375 if ( isReading() )
00376 {
00377
00378 uint32 sizeOfReadStream = lengthR();
00379 resetPtrTable();
00380 setInOut( false );
00381 _Buffer.Pos = sizeOfReadStream;
00382 }
00383 else
00384 {
00385
00386 resetPtrTable();
00387 setInOut( true );
00388
00389 _Buffer.getBufferWrite().resize (_Buffer.Pos);
00390 _Buffer.Pos = 0;
00391 }
00392 }
00393
00395 void resetPtrTable() { IStream::resetPtrTable() ; }
00396
00398 #ifdef NL_OS_WINDOWS
00399 __forceinline
00400 #endif
00401 void increaseBufferIfNecessary(uint32 len)
00402 {
00403 uint32 oldBufferSize = _Buffer.getBuffer().size();
00404 if (_Buffer.Pos + len > oldBufferSize)
00405 {
00406
00407 _Buffer.getBufferWrite().resize(oldBufferSize*2 + len);
00408 }
00409 }
00410
00411
00412 template <class T> void fastSerial (T &val)
00413 {
00414 #ifdef NL_LITTLE_ENDIAN
00415 if(isReading())
00416 {
00417
00418 if ( lengthS()+sizeof(T) > length() )
00419 throw EStreamOverflow();
00420
00421 val = *(T*)(_Buffer.getBuffer().getPtr() + _Buffer.Pos);
00422 }
00423 else
00424 {
00425 increaseBufferIfNecessary (sizeof(T));
00426 *(T*)(_Buffer.getBufferWrite().getPtr() + _Buffer.Pos) = val;
00427 }
00428 _Buffer.Pos += sizeof (T);
00429 #else // NL_LITTLE_ENDIAN
00430 IStream::serial( val );
00431 #endif // NL_LITTLE_ENDIAN
00432 }
00433
00434 template <class T>
00435 void fastWrite( const T& value )
00436 {
00437
00438 increaseBufferIfNecessary (sizeof(T));
00439 *(T*)(_Buffer.getBufferWrite().getPtr() + _Buffer.Pos) = value;
00440
00441 _Buffer.Pos += sizeof (T);
00442 }
00443
00444 template <class T>
00445 void fastRead( T& value )
00446 {
00447
00448
00449 if ( lengthS()+sizeof(value) > length() )
00450 {
00451 throw EStreamOverflow();
00452 }
00453
00454 value = *(T*)(_Buffer.getBuffer().getPtr() + _Buffer.Pos);
00455 _Buffer.Pos += sizeof(value);
00456 }
00457
00458
00460 template<class T>
00461 void serial(T &obj) { obj.serial(*this); }
00462
00463
00464 template<class T>
00465 void serialCont(std::vector<T> &cont) {IStream::serialCont(cont);}
00466 template<class T>
00467 void serialCont(std::list<T> &cont) {IStream::serialCont(cont);}
00468 template<class T>
00469 void serialCont(std::deque<T> &cont) {IStream::serialCont(cont);}
00470 template<class T>
00471 void serialCont(std::set<T> &cont) {IStream::serialCont(cont);}
00472 template<class T>
00473 void serialCont(std::multiset<T> &cont) {IStream::serialCont(cont);}
00474 template<class K, class T>
00475 void serialCont(std::map<K, T> &cont) {IStream::serialCont(cont);}
00476 template<class K, class T>
00477 void serialCont(std::multimap<K, T> &cont) {IStream::serialCont(cont);}
00479 virtual void serialCont(std::vector<uint8> &cont) {IStream::serialCont(cont);}
00481 virtual void serialCont(std::vector<sint8> &cont) {IStream::serialCont(cont);}
00483 virtual void serialCont(std::vector<bool> &cont) {IStream::serialCont(cont);}
00484
00485
00486
00487 template<class T0,class T1>
00488 void serial(T0 &a, T1 &b)
00489 { serial(a); serial(b);}
00490 template<class T0,class T1,class T2>
00491 void serial(T0 &a, T1 &b, T2 &c)
00492 { serial(a); serial(b); serial(c);}
00493 template<class T0,class T1,class T2,class T3>
00494 void serial(T0 &a, T1 &b, T2 &c, T3 &d)
00495 { serial(a); serial(b); serial(c); serial(d);}
00496 template<class T0,class T1,class T2,class T3,class T4>
00497 void serial(T0 &a, T1 &b, T2 &c, T3 &d, T4 &e)
00498 { serial(a); serial(b); serial(c); serial(d); serial(e);}
00499 template<class T0,class T1,class T2,class T3,class T4,class T5>
00500 void serial(T0 &a, T1 &b, T2 &c, T3 &d, T4 &e, T5 &f)
00501 { serial(a); serial(b); serial(c); serial(d); serial(e); serial(f);}
00502
00507 virtual void serial(uint8 &b) ;
00508 virtual void serial(sint8 &b) ;
00509 virtual void serial(uint16 &b) ;
00510 virtual void serial(sint16 &b) ;
00511 virtual void serial(uint32 &b) ;
00512 virtual void serial(sint32 &b) ;
00513 virtual void serial(uint64 &b) ;
00514 virtual void serial(sint64 &b) ;
00515 virtual void serial(float &b) ;
00516 virtual void serial(double &b) ;
00517 virtual void serial(bool &b) ;
00518 #ifndef NL_OS_CYGWIN
00519 virtual void serial(char &b) ;
00520 #endif
00521 virtual void serial(std::string &b) ;
00522 virtual void serial(ucstring &b) ;
00524
00525
00527
00528
00530 uint serialSeparatedBufferIn( uint8 *buf, uint len );
00531
00533 void serialSeparatedBufferOut( uint8 *buf, uint len );
00534
00536 virtual void serialHex(uint32 &b);
00537
00539
00540 protected:
00541
00543 virtual uint32 lengthS() const
00544 {
00545 return _Buffer.Pos;
00546 }
00547
00552 uint32 lengthR() const
00553 {
00554 return size();
00555 }
00556
00560 virtual uint getDbgStreamSize() const;
00561
00562 CMemStreamBuffer _Buffer;
00563
00564 mutable bool _StringMode;
00565
00566 uint32 _DefaultCapacity;
00567 };
00568
00569
00570 #define readnumber(dest,thetype,digits,convfunc) \
00571 char number_as_cstring [digits+1]; \
00572 uint realdigits = serialSeparatedBufferIn( (uint8*)number_as_cstring, digits ); \
00573 number_as_cstring[realdigits] = '\0'; \
00574 dest = (thetype)convfunc( number_as_cstring );
00575
00576
00577 #define writenumber(src,format,digits) \
00578 char number_as_cstring [digits+1]; \
00579 sprintf( number_as_cstring, format, src ); \
00580 serialSeparatedBufferOut( (uint8*)number_as_cstring, strlen(number_as_cstring) );
00581
00582
00583
00584
00585 inline uint32 atoihex( const char* ident )
00586 {
00587 uint32 number;
00588 sscanf( ident, "%x", &number );
00589 return number;
00590 }
00591
00592 inline uint32 atoui( const char *ident)
00593 {
00594 return (uint32) strtoul (ident, NULL, 10);
00595 }
00596
00597 static const char SEPARATOR = ' ';
00598 static const int SEP_SIZE = 1;
00599
00600
00601
00602
00603
00604
00605
00606 inline void CMemStream::serial(uint8 &b)
00607 {
00608 if ( _StringMode )
00609 {
00610 if ( isReading() )
00611 {
00612 readnumber( b, uint8, 3, atoi );
00613 }
00614 else
00615 {
00616 writenumber( (uint16)b,"%hu", 3 );
00617 }
00618 }
00619 else
00620 {
00621 fastSerial (b);
00622 }
00623 }
00624
00625
00626 inline void CMemStream::serial(sint8 &b)
00627 {
00628 if ( _StringMode )
00629 {
00630 if ( isReading() )
00631 {
00632 readnumber( b, sint8, 4, atoi );
00633 }
00634 else
00635 {
00636 writenumber( (sint16)b, "%hd", 4 );
00637 }
00638 }
00639 else
00640 {
00641 fastSerial (b);
00642 }
00643 }
00644
00645
00646 inline void CMemStream::serial(uint16 &b)
00647 {
00648 if ( _StringMode )
00649 {
00650
00651 if ( isReading() )
00652 {
00653 readnumber( b, uint16, 5, atoi );
00654 }
00655 else
00656 {
00657 writenumber( b, "%hu", 5 );
00658 }
00659 }
00660 else
00661 {
00662 fastSerial (b);
00663 }
00664 }
00665
00666
00667 inline void CMemStream::serial(sint16 &b)
00668 {
00669 if ( _StringMode )
00670 {
00671 if ( isReading() )
00672 {
00673 readnumber( b, sint16, 6, atoi );
00674 }
00675 else
00676 {
00677 writenumber( b, "%hd", 6 );
00678 }
00679 }
00680 else
00681 {
00682 fastSerial (b);
00683 }
00684 }
00685
00686
00687 inline void CMemStream::serial(uint32 &b)
00688 {
00689 if ( _StringMode )
00690 {
00691 if ( isReading() )
00692 {
00693 readnumber( b, uint32, 10, atoui );
00694 }
00695 else
00696 {
00697 writenumber( b, "%u", 10 );
00698 }
00699 }
00700 else
00701 {
00702 fastSerial (b);
00703 }
00704 }
00705
00706
00707
00708 inline void CMemStream::serial(sint32 &b)
00709 {
00710 if ( _StringMode )
00711 {
00712 if ( isReading() )
00713 {
00714 readnumber( b, sint32, 11, atoi );
00715 }
00716 else
00717 {
00718 writenumber( b, "%d", 11 );
00719 }
00720 }
00721 else
00722 {
00723 fastSerial (b);
00724 }
00725 }
00726
00727
00728 inline void CMemStream::serial(uint64 &b)
00729 {
00730 if ( _StringMode )
00731 {
00732 if ( isReading() )
00733 {
00734 readnumber( b, uint64, 20, atoiInt64 );
00735 }
00736 else
00737 {
00738 writenumber( b, "%"NL_I64"u", 20 );
00739 }
00740 }
00741 else
00742 {
00743 fastSerial (b);
00744 }
00745 }
00746
00747
00748 inline void CMemStream::serial(sint64 &b)
00749 {
00750 if ( _StringMode )
00751 {
00752 if ( isReading() )
00753 {
00754 readnumber( b, sint64, 20, atoiInt64 );
00755 }
00756 else
00757 {
00758 writenumber( b, "%"NL_I64"d", 20 );
00759 }
00760 }
00761 else
00762 {
00763 fastSerial (b);
00764 }
00765 }
00766
00767
00768 inline void CMemStream::serial(float &b)
00769 {
00770 if ( _StringMode )
00771 {
00772 if ( isReading() )
00773 {
00774 readnumber( b, float, 128, atof );
00775 }
00776 else
00777 {
00778 writenumber( (double)b, "%f", 128 );
00779 }
00780 }
00781 else
00782 {
00783 fastSerial (b);
00784 }
00785 }
00786
00787
00788 inline void CMemStream::serial(double &b)
00789 {
00790 if ( _StringMode )
00791 {
00792 if ( isReading() )
00793 {
00794 readnumber( b, double, 128, atof );
00795 }
00796 else
00797 {
00798 writenumber( b, "%f", 128 );
00799 }
00800 }
00801 else
00802 {
00803 fastSerial (b);
00804 }
00805 }
00806
00807
00808 inline void CMemStream::serial(bool &b)
00809 {
00810 if ( _StringMode )
00811 {
00812 serialBit(b);
00813 }
00814 else
00815 {
00816 fastSerial (b);
00817 }
00818 }
00819
00820
00821 #ifndef NL_OS_CYGWIN
00822
00823 inline void CMemStream::serial(char &b)
00824 {
00825 if ( _StringMode )
00826 {
00827 char buff [2];
00828 if ( isReading() )
00829 {
00830 serialBuffer( (uint8*)buff, 2 );
00831 b = buff[0];
00832 }
00833 else
00834 {
00835 buff[0] = b;
00836 buff[1] = SEPARATOR;
00837 serialBuffer( (uint8*)buff, 2 );
00838 }
00839 }
00840 else
00841 {
00842 fastSerial (b);
00843 }
00844 }
00845 #endif
00846
00847
00848 inline void CMemStream::serial(std::string &b)
00849 {
00850 if ( _StringMode )
00851 {
00852 uint32 len=0;
00853
00854 if(isReading())
00855 {
00856 serial(len);
00857 checkStreamSize((uint)len);
00858
00859
00860
00861 b.resize(len);
00862 }
00863 else
00864 {
00865 len= (uint32)b.size();
00866 if (len>1000000)
00867 throw NLMISC::EInvalidDataStream( "CMemStream/str: Trying to write a string of %u bytes", len );
00868 serial(len);
00869 }
00870
00871
00872 for(uint i=0;i!=len;++i)
00873 serialBuffer( (uint8*)&(b[i]), sizeof(b[i]) );
00874
00875 char sep = SEPARATOR;
00876 serialBuffer( (uint8*)&sep, 1 );
00877 }
00878 else
00879 {
00880 if (isReading())
00881 {
00882 if (!isXML())
00883 {
00884 uint32 len=0;
00885 fastSerial(len);
00886 checkStreamSize((uint)len);
00887
00888
00889
00890
00891 b.resize(len);
00892 if (len > 0)
00893 {
00894
00895 serialBuffer((uint8 *) &b[0], len);
00896 }
00897 }
00898 else
00899 {
00900 IStream::serial( b );
00901 }
00902 }
00903 else
00904 {
00905 IStream::serial( b );
00906 }
00907 }
00908 }
00909
00910
00911
00912 inline void CMemStream::serial(ucstring &b)
00913 {
00914 if ( _StringMode )
00915 {
00916 uint32 len=0;
00917
00918 if(isReading())
00919 {
00920 serial(len);
00921 checkStreamSize((uint)len);
00922
00923
00924
00925
00926 b.resize(len);
00927 }
00928 else
00929 {
00930 len= (uint32)b.size();
00931 if (len>1000000)
00932 throw NLMISC::EInvalidDataStream( "CMemStream/str: Trying to write an ucstring of %u bytes", len );
00933 serial(len);
00934 }
00935
00936 for(uint i=0;i!=len;++i)
00937 serialBuffer( (uint8*)&b[i], sizeof(b[i]) );
00938
00939 char sep = SEPARATOR;
00940 serialBuffer( (uint8*)&sep, 1 );
00941 }
00942 else
00943 {
00944 IStream::serial( b );
00945 }
00946 }
00947
00948
00949
00950
00951
00952
00953 inline void CMemStream::serialHex(uint32 &b)
00954 {
00955 if ( _StringMode )
00956 {
00957 if ( isReading() )
00958 {
00959 readnumber( b, uint32, 10, atoihex );
00960 }
00961 else
00962 {
00963 writenumber( b, "%x", 10 );
00964 }
00965 }
00966 else
00967 {
00968 IStream::serial( b );
00969 }
00970 }
00971
00972 }
00973
00974 #endif // NL_MEM_STREAM_H
00975
00976