src/bytestream.cpp

changeset 18
6bf57b4f42cd
parent 17
b41d74bacdea
child 19
c9b6dd9dd4cd
equal deleted inserted replaced
17:b41d74bacdea 18:6bf57b4f42cd
1 /*
2 * ZanDemo: Zandronum demo launcher
3 * Copyright (C) 2013 Santeri Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "bytestream.h"
20 #include "misc.h"
21 #include <string.h>
22
23 union {
24 uint32 i;
25 float f;
26 } g_floatunion;
27
28 Bytestream::Bytestream (ulong len) {
29 m_data = null;
30 resize (len);
31 clear();
32 }
33
34 Bytestream::Bytestream (const char* data, ulong len) {
35 m_data = null;
36 init (data, len);
37 }
38
39 void Bytestream::resize (ulong newsize) {
40 char* olddata = null;
41 ulong oldsize;
42
43 if (m_data) {
44 oldsize = m_size;
45 olddata = new char[oldsize];
46 memcpy (olddata, m_data, oldsize);
47 }
48
49 delete[] m_data;
50 m_data = new uint8[newsize];
51 m_size = newsize;
52
53 if (olddata)
54 memcpy (m_data, olddata, min<ulong> (oldsize, newsize));
55 }
56
57 void Bytestream::init (const char* data, ulong len) {
58 resize (len);
59 memcpy (m_data, data, len);
60 m_ptr = &m_data[0];
61 m_len = len;
62 }
63
64 size_t Bytestream::len() const {
65 return m_len;
66 }
67
68 void Bytestream::clear() {
69 m_ptr = &m_data[0];
70 m_len = 0;
71 }
72
73 uint8& Bytestream::subscript (ulong idx) {
74 return m_data[idx];
75 }
76
77 const uint8& Bytestream::const_subscript (ulong idx) const {
78 return m_data[idx];
79 }
80
81 void Bytestream::seek (ulong pos) {
82 m_ptr = m_data + pos;
83 }
84
85 // =============================================================================
86 void Bytestream::rewind() {
87 m_ptr = m_data;
88 }
89
90 ulong Bytestream::bytesLeft() const {
91 return (m_len - (m_ptr - &m_data[0]));
92 }
93
94 ulong Bytestream::spaceLeft() const {
95 return (m_size - m_len);
96 }
97
98 // =============================================================================
99 bool Bytestream::readByte (uint8& val) {
100 if (bytesLeft() < 1)
101 return false;
102
103 val = *m_ptr++;
104 return true;
105 }
106
107 // =============================================================================
108 bool Bytestream::readShort (uint16& val) {
109 if (bytesLeft() < 2)
110 return false;
111
112 val = 0;
113
114 for (int i = 0; i < 2; ++i)
115 val |= *m_ptr++ << (i * 8);
116
117 return true;
118 }
119
120 // =============================================================================
121 bool Bytestream::readLong (uint32& val) {
122 if (bytesLeft() < 4)
123 return false;
124
125 val = 0;
126
127 for (int i = 0; i < 4; ++i)
128 val |= *m_ptr++ << (i * 8);
129
130 return true;
131 }
132
133 // =============================================================================
134 bool Bytestream::readFloat (float& val) {
135 if (!readLong (g_floatunion.i))
136 return false;
137
138 val = g_floatunion.f;
139 return true;
140 }
141
142 // =============================================================================
143 bool Bytestream::readString (str& val) {
144 if (bytesLeft() < 1) // need at least the null terminator
145 return false;
146
147 uint8_t c;
148
149 while (readByte (c) && c != '\0')
150 val += (char) c;
151
152 return true;
153 }
154
155 // =============================================================================
156 void Bytestream::doWrite (uint8_t val) {
157 *m_ptr++ = val;
158 m_len++;
159 }
160
161 void Bytestream::growToFit (ulong bytes) {
162 if (spaceLeft() < bytes)
163 resize (m_size + bytes + 128);
164 }
165
166 bool Bytestream::readBytes (uint8 numbytes, uint8* val) {
167 while (numbytes--)
168 if (!readByte (*val++))
169 return false;
170
171 return true;
172 }
173
174 void Bytestream::writeBytes (uint8 numbytes, const uint8* val) {
175 growToFit (numbytes);
176
177 while (numbytes--)
178 writeByte (*val++);
179 }
180
181 // =============================================================================
182 void Bytestream::writeByte (uint8 val) {
183 growToFit (1);
184 doWrite (val);
185 }
186
187 // =============================================================================
188 void Bytestream::writeShort (uint16 val) {
189 growToFit (2);
190
191 for (int i = 0; i < 2; ++i)
192 doWrite ( (val >> (i * 8)) & 0xFF);
193 }
194
195 // =============================================================================
196 void Bytestream::writeLong (uint32 val) {
197 growToFit (4);
198
199 for (int i = 0; i < 4; ++i)
200 doWrite ( (val >> (i * 8)) & 0xFF);
201 }
202
203 // =============================================================================
204 void Bytestream::writeFloat (float val) {
205 g_floatunion.f = val;
206 writeLong (g_floatunion.i);
207 }
208
209 // =============================================================================
210 void Bytestream::writeString (str val) {
211 growToFit (val.length() + 1);
212
213 for (qchar c : val)
214 doWrite (c.toLatin1());
215
216 doWrite ('\0');
217 }
218
219 // =============================================================================
220 bool Bytestream::tryMerge (const Bytestream& other) {
221 if (spaceLeft() < other.len())
222 return false;
223
224 for (ulong i = 0; i < other.len(); ++i)
225 writeByte (other[i]);
226
227 return true;
228 }
229
230 void Bytestream::merge (const Bytestream& other) {
231 growToFit (other.len());
232
233 if (!tryMerge (other)) {
234 // Shouldn't happen
235 fprint (stderr, "ByteStream: Not enough space for merge (%1 bytes left, need %2)",
236 spaceLeft(), other.len());
237 abort();
238 }
239 }
240
241 const uint8* Bytestream::data() const {
242 return m_data;
243 }

mercurial