Merge branch '138-toggle-free-look-with-hotkey' into 'main/atys-live'
[ryzomcore.git] / nel / src / misc / mem_stream.cpp
blobdd81334d1d66d760824e3b9d4a01656f417cc633
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/mem_stream.h"
21 #ifdef DEBUG_NEW
22 #define new DEBUG_NEW
23 #endif
25 namespace NLMISC
28 void CMemStream::swap(CMemStream &other)
30 IStream::swap(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);
45 if (len == 0)
46 return;
48 nlassert (buf != NULL);
50 if ( isReading() )
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 );
62 // Serialize in
63 CFastMem::memcpy( buf, _Buffer.getBuffer().getPtr()+_Buffer.Pos, len );
64 _Buffer.Pos += len;
66 else
68 // Serialize out
70 increaseBufferIfNecessary (len);
71 CFastMem::memcpy( _Buffer.getBufferWrite().getPtr()+_Buffer.Pos, buf, len );
72 _Buffer.Pos += len;
78 * serialBit (inherited from IStream)
80 void CMemStream::serialBit(bool &bit)
82 uint8 u;
83 if ( isReading() )
85 serial( u );
86 bit = (u!=0);
88 else
90 u = (uint8)bit;
91 serial( u );
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
112 switch (origin)
114 case begin:
115 if (offset > (sint)length())
116 return false;
117 if (offset < 0)
118 return false;
119 _Buffer.Pos = offset;
120 break;
121 case current:
122 if (getPos ()+offset > (sint)length())
123 return false;
124 if (getPos ()+offset < 0)
125 return false;
126 _Buffer.Pos += offset;
127 break;
128 case end:
129 if (offset < -(sint)length())
130 return false;
131 if (offset > 0)
132 return false;
133 _Buffer.Pos = _Buffer.getBuffer().size()+offset;
134 break;
136 return true;
141 * Resize the buffer.
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();
165 // Serialize in
166 uint32 i = 0;
167 const uint8 *pos = _Buffer.getBuffer().getPtr()+_Buffer.Pos;
168 while ( (i<len) && (*pos) != SEPARATOR )
170 *(buf+i) = *pos;
171 i++;
172 ++pos;
173 ++_Buffer.Pos;
175 // Exceeds len
176 if ( (*pos) != SEPARATOR )
178 throw EStreamOverflow();
180 _Buffer.Pos += SEP_SIZE;
182 return i;
187 * Output: writes len bytes from buf into the stream
189 void CMemStream::serialSeparatedBufferOut( uint8 *buf, uint len )
191 nlassert( _StringMode && (!isReading()) );
193 // Serialize out
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 );
202 _Buffer.Pos += 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
214 std::string s;
215 uint32 len = length();
216 if ( hexFormat )
218 for ( uint i=0; i!=len; ++i )
219 s += NLMISC::toString( "%2X ", buffer()[i] );
221 else
223 for ( uint i=0; i!=len; ++i )
224 s += NLMISC::toString( "%c", (buffer()[i]>31) ? buffer()[i] : '.' );
226 return s;
230 // ***************************************************************************
231 uint CMemStream::getDbgStreamSize() const
233 if(isReading())
234 return length();
235 else
236 return 0;