1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
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/>.
19 #include "nel/misc/mem_stream.h"
28 void CMemStream::swap(CMemStream
&other
)
31 _Buffer
.swap(other
._Buffer
);
32 std::swap(_StringMode
, other
._StringMode
);
33 std::swap(_DefaultCapacity
, other
._DefaultCapacity
);
38 * serial (inherited from IStream)
40 void CMemStream::serialBuffer(uint8
*buf
, uint len
)
42 // commented for optimum performance
43 // nlassert (len > 0);
48 nlassert (buf
!= NULL
);
52 // Check that we don't read more than there is to read
53 //checkStreamSize(len);
55 uint32 pos
= lengthS();
56 uint32 total
= length();
57 if ( pos
+len
> total
) // calls virtual length (cf. sub messages)
59 throw EStreamOverflow( "CMemStream serialBuffer overflow: Read past %u bytes", total
);
63 CFastMem::memcpy( buf
, _Buffer
.getBuffer().getPtr()+_Buffer
.Pos
, len
);
70 increaseBufferIfNecessary (len
);
71 CFastMem::memcpy( _Buffer
.getBufferWrite().getPtr()+_Buffer
.Pos
, buf
, len
);
78 * serialBit (inherited from IStream)
80 void CMemStream::serialBit(bool &bit
)
97 * seek (inherited from IStream)
99 * Warning: in output mode, seek(end) does not point to the end of the serialized data,
100 * but on the end of the whole allocated buffer (see size()).
101 * If you seek back and want to return to the end of the serialized data, you have to
102 * store the position (a better way is to use reserve()/poke()).
104 * Possible enhancement:
105 * In output mode, keep another pointer to track the end of serialized data.
106 * When serializing, increment the pointer if its value exceeds its previous value
107 * (to prevent from an "inside serial" to increment it).
108 * Then a seek(end) would get back to the pointer.
110 bool CMemStream::seek (sint32 offset
, TSeekOrigin origin
) const
115 if (offset
> (sint
)length())
119 _Buffer
.Pos
= offset
;
122 if (getPos ()+offset
> (sint
)length())
124 if (getPos ()+offset
< 0)
126 _Buffer
.Pos
+= offset
;
129 if (offset
< -(sint
)length())
133 _Buffer
.Pos
= _Buffer
.getBuffer().size()+offset
;
142 * Warning: the position is unchanged, only the size is changed.
144 void CMemStream::resize (uint32 size
)
146 if (size
== length()) return;
147 // need to increase the buffer size
148 _Buffer
.getBufferWrite().resize(size
);
153 * Input: read from the stream until the next separator, and return the number of bytes read. The separator is then skipped.
155 uint
CMemStream::serialSeparatedBufferIn( uint8
*buf
, uint len
)
157 nlassert( _StringMode
&& isReading() );
159 // Check that we don't read more than there is to read
160 if ( ( _Buffer
.Pos
== _Buffer
.getBuffer().size() ) || // we are at the end
161 ( ( lengthS()+len
+SEP_SIZE
> length() ) && (_Buffer
.getBuffer()[_Buffer
.getBuffer().size()-1] != SEPARATOR
) ) ) // we are before the end // calls virtual length (cf. sub messages)
163 throw EStreamOverflow();
167 const uint8
*pos
= _Buffer
.getBuffer().getPtr()+_Buffer
.Pos
;
168 while ( (i
<len
) && (*pos
) != SEPARATOR
)
176 if ( (*pos
) != SEPARATOR
)
178 throw EStreamOverflow();
180 _Buffer
.Pos
+= SEP_SIZE
;
187 * Output: writes len bytes from buf into the stream
189 void CMemStream::serialSeparatedBufferOut( uint8
*buf
, uint len
)
191 nlassert( _StringMode
&& (!isReading()) );
194 uint32 oldBufferSize
= _Buffer
.getBuffer().size();
195 if (_Buffer
.Pos
+ (len
+ SEP_SIZE
) > oldBufferSize
)
197 // need to increase the buffer size
198 _Buffer
.getBufferWrite().resize(oldBufferSize
*2 + len
+ SEP_SIZE
);
201 CFastMem::memcpy( _Buffer
.getBufferWrite().getPtr()+_Buffer
.Pos
, buf
, len
);
203 *(_Buffer
.getBufferWrite().getPtr()+_Buffer
.Pos
) = SEPARATOR
;
204 _Buffer
.Pos
+= SEP_SIZE
;
208 /* Returns a readable string to display it to the screen. It's only for debugging purpose!
209 * Don't use it for anything else than to debugging, the string format could change in the future.
210 * \param hexFormat If true, display all bytes in hexadecimal, else display as chars (above 31, otherwise '.')
212 std::string
CMemStream::toString( bool hexFormat
) const
215 uint32 len
= length();
218 for ( uint i
=0; i
!=len
; ++i
)
219 s
+= NLMISC::toString( "%2X ", buffer()[i
] );
223 for ( uint i
=0; i
!=len
; ++i
)
224 s
+= NLMISC::toString( "%c", (buffer()[i
]>31) ? buffer()[i
] : '.' );
230 // ***************************************************************************
231 uint
CMemStream::getDbgStreamSize() const