src/bytestream.cpp

changeset 6
67b6ef6917ba
child 10
bc1414343e19
equal deleted inserted replaced
5:3c04e05ab24f 6:67b6ef6917ba
1 #include "bytestream.h"
2 #include "misc.h"
3 #include <string.h>
4
5 union {
6 uint32 i;
7 float f;
8 } g_floatunion;
9
10 Bytestream::Bytestream( ulong len ) {
11 m_data = null;
12 resize( len );
13 clear();
14 }
15
16 Bytestream::Bytestream( const char* data, ulong len ) {
17 m_data = null;
18 init( data, len );
19 }
20
21 void Bytestream::resize( ulong newsize ) {
22 char* olddata = null;
23 ulong oldsize;
24
25 if( m_data ) {
26 oldsize = m_size;
27 olddata = new char[oldsize];
28 memcpy( olddata, m_data, oldsize );
29 }
30
31 delete[] m_data;
32 m_data = new uint8[newsize];
33 m_size = newsize;
34
35 if( olddata )
36 memcpy( m_data, olddata, min<ulong> ( oldsize, newsize ));
37 }
38
39 void Bytestream::init( const char* data, ulong len ) {
40 resize( len );
41 memcpy( m_data, data, len );
42 m_ptr = &m_data[0];
43 m_len = len;
44 }
45
46 size_t Bytestream::len() const {
47 return m_len;
48 }
49
50 void Bytestream::clear() {
51 m_ptr = &m_data[0];
52 m_len = 0;
53 }
54
55 uint8& Bytestream::subscript( ulong idx ) {
56 return m_data[idx];
57 }
58
59 const uint8& Bytestream::const_subscript( ulong idx ) const {
60 return m_data[idx];
61 }
62
63 void Bytestream::seek( ulong pos ) {
64 m_ptr = m_data + pos;
65 }
66
67 // =============================================================================
68 void Bytestream::rewind() {
69 m_ptr = m_data;
70 }
71
72 ulong Bytestream::bytesLeft() const {
73 return ( m_len - ( m_ptr - &m_data[0] ));
74 }
75
76 ulong Bytestream::spaceLeft() const {
77 return ( m_size - m_len );
78 }
79
80 // =============================================================================
81 bool Bytestream::readByte( uint8& val ) {
82 if( bytesLeft() < 1 )
83 return false;
84
85 val = *m_ptr++;
86 return true;
87 }
88
89 // =============================================================================
90 bool Bytestream::readShort( uint16& val ) {
91 if( bytesLeft() < 2 )
92 return false;
93
94 val = 0;
95
96 for( int i = 0; i < 2; ++i )
97 val |= *m_ptr++ << ( i * 8 );
98
99 return true;
100 }
101
102 // =============================================================================
103 bool Bytestream::readLong( uint32& val ) {
104 if( bytesLeft() < 4 )
105 return false;
106
107 val = 0;
108
109 for( int i = 0; i < 4; ++i )
110 val |= *m_ptr++ << ( i * 8 );
111
112 return true;
113 }
114
115 // =============================================================================
116 bool Bytestream::readFloat( float& val ) {
117 if( !readLong( g_floatunion.i ))
118 return false;
119
120 val = g_floatunion.f;
121 return true;
122 }
123
124 // =============================================================================
125 bool Bytestream::readString( str& val ) {
126 if( bytesLeft() < 1 ) // need at least the null terminator
127 return false;
128
129 uint8_t c;
130
131 while( readByte( c ) && c != '\0' )
132 val += ( char ) c;
133
134 return true;
135 }
136
137 // =============================================================================
138 void Bytestream::doWrite( uint8_t val ) {
139 *m_ptr++ = val;
140 m_len++;
141 }
142
143 void Bytestream::growToFit( ulong bytes ) {
144 if( spaceLeft() < bytes )
145 resize( m_size + bytes + 128 );
146 }
147
148 bool Bytestream::readBytes( uint8 numbytes, uint8* val ) {
149 while( numbytes-- )
150 if( !readByte( *val++ ))
151 return false;
152
153 return true;
154 }
155
156 void Bytestream::writeBytes( uint8 numbytes, const uint8* val ) {
157 growToFit( numbytes );
158
159 while( numbytes-- )
160 writeByte( *val++ );
161 }
162
163 // =============================================================================
164 void Bytestream::writeByte( uint8 val ) {
165 growToFit( 1 );
166 doWrite( val );
167 }
168
169 // =============================================================================
170 void Bytestream::writeShort( uint16 val ) {
171 growToFit( 2 );
172
173 for( int i = 0; i < 2; ++i )
174 doWrite(( val >> ( i * 8 )) & 0xFF );
175 }
176
177 // =============================================================================
178 void Bytestream::writeLong( uint32 val ) {
179 growToFit( 4 );
180
181 for( int i = 0; i < 4; ++i )
182 doWrite(( val >> ( i * 8 )) & 0xFF );
183 }
184
185 // =============================================================================
186 void Bytestream::writeFloat( float val ) {
187 g_floatunion.f = val;
188 writeLong( g_floatunion.i );
189 }
190
191 // =============================================================================
192 void Bytestream::writeString( str val ) {
193 growToFit( val.length() + 1 );
194
195 for( qchar c : val )
196 doWrite( c.toAscii() );
197
198 doWrite( '\0' );
199 }
200
201 // =============================================================================
202 bool Bytestream::tryMerge( const Bytestream& other ) {
203 if( spaceLeft() < other.len() )
204 return false;
205
206 for( ulong i = 0; i < other.len(); ++i )
207 writeByte( other[i] );
208
209 return true;
210 }
211
212 void Bytestream::merge( const Bytestream& other ) {
213 growToFit( other.len() );
214
215 if( !tryMerge( other )) {
216 // Shouldn't happen
217 fprint( stderr, "ByteStream: Not enough space for merge (%1 bytes left, need %2)",
218 spaceLeft(), other.len() );
219 abort();
220 }
221 }
222
223 const uint8* Bytestream::data() const {
224 return m_data;
225 }

mercurial