xref: /haiku/src/libs/icon/flat_icon/LittleEndianBuffer.cpp (revision 0562493379cd52eb7103531f895f10bb8e77c085)
1 /*
2  * Copyright 2006-2007, Haiku. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  */
8 
9 
10 #include "LittleEndianBuffer.h"
11 
12 #include <ByteOrder.h>
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 
18 using namespace BPrivate::Icon;
19 
20 #define CHUNK_SIZE 256
21 
22 
23 // constructor
24 LittleEndianBuffer::LittleEndianBuffer()
25 	: fBuffer((uint8*)malloc(CHUNK_SIZE)),
26 	  fHandle(fBuffer),
27 	  fBufferEnd(fBuffer + CHUNK_SIZE),
28 	  fSize(CHUNK_SIZE),
29 	  fOwnsBuffer(true)
30 {
31 }
32 
33 // constructor
34 LittleEndianBuffer::LittleEndianBuffer(size_t size)
35 	: fBuffer((uint8*)malloc(size)),
36 	  fHandle(fBuffer),
37 	  fBufferEnd(fBuffer + size),
38 	  fSize(size),
39 	  fOwnsBuffer(true)
40 {
41 }
42 
43 // constructor
44 LittleEndianBuffer::LittleEndianBuffer(uint8* buffer, size_t size)
45 	: fBuffer(buffer),
46 	  fHandle(fBuffer),
47 	  fBufferEnd(fBuffer + size),
48 	  fSize(size),
49 	  fOwnsBuffer(false)
50 {
51 }
52 
53 // destructor
54 LittleEndianBuffer::~LittleEndianBuffer()
55 {
56 	if (fOwnsBuffer)
57 		free(fBuffer);
58 }
59 
60 // Write 8
61 bool
62 LittleEndianBuffer::Write(uint8 value)
63 {
64 	if (fHandle == fBufferEnd)
65 		_SetSize(fSize + CHUNK_SIZE);
66 
67 	if (!fBuffer)
68 		return false;
69 
70 	*fHandle = value;
71 	fHandle++;
72 
73 	return true;
74 }
75 
76 // Write 16
77 bool
78 LittleEndianBuffer::Write(uint16 value)
79 {
80 	if ((fHandle + 1) >= fBufferEnd)
81 		_SetSize(fSize + CHUNK_SIZE);
82 
83 	if (!fBuffer)
84 		return false;
85 
86 	*(uint16*)fHandle = B_HOST_TO_LENDIAN_INT16(value);
87 	fHandle += 2;
88 
89 	return true;
90 }
91 
92 // Write 32
93 bool
94 LittleEndianBuffer::Write(uint32 value)
95 {
96 	if ((fHandle + 3) >= fBufferEnd)
97 		_SetSize(fSize + CHUNK_SIZE);
98 
99 	if (!fBuffer)
100 		return false;
101 
102 	*(uint32*)fHandle = B_HOST_TO_LENDIAN_INT32(value);
103 	fHandle += 4;
104 
105 	return true;
106 }
107 
108 // Write double
109 bool
110 LittleEndianBuffer::Write(float value)
111 {
112 	if ((fHandle + sizeof(float) - 1) >= fBufferEnd)
113 		_SetSize(fSize + CHUNK_SIZE);
114 
115 	if (!fBuffer)
116 		return false;
117 
118 	*(float*)fHandle = B_HOST_TO_LENDIAN_FLOAT(value);
119 	fHandle += sizeof(float);
120 
121 	return true;
122 }
123 
124 // Write double
125 bool
126 LittleEndianBuffer::Write(double value)
127 {
128 	if ((fHandle + sizeof(double) - 1) >= fBufferEnd)
129 		_SetSize(fSize + CHUNK_SIZE);
130 
131 	if (!fBuffer)
132 		return false;
133 
134 	*(double*)fHandle = B_HOST_TO_LENDIAN_DOUBLE(value);
135 	fHandle += sizeof(double);
136 
137 	return true;
138 }
139 
140 // Write LittleEndianBuffer
141 bool
142 LittleEndianBuffer::Write(const LittleEndianBuffer& other)
143 {
144 	return Write(other.Buffer(), other.SizeUsed());
145 }
146 
147 // Write buffer
148 bool
149 LittleEndianBuffer::Write(const uint8* buffer, size_t bytes)
150 {
151 	if (bytes == 0)
152 		return true;
153 
154 	// figure out needed size and suitable new size
155 	size_t neededSize = SizeUsed() + bytes;
156 	size_t newSize = fSize;
157 	while (newSize < neededSize)
158 		newSize += CHUNK_SIZE;
159 
160 	// resize if necessary
161 	if (newSize > fSize)
162 		_SetSize(newSize);
163 
164 	if (!fBuffer)
165 		return false;
166 
167 	// paste buffer
168 	memcpy(fHandle, buffer, bytes);
169 	fHandle += bytes;
170 
171 	return true;
172 }
173 
174 // #pragma mark -
175 
176 // Read 8
177 bool
178 LittleEndianBuffer::Read(uint8& value)
179 {
180 	if (fHandle >= fBufferEnd)
181 		return false;
182 
183 	value = *fHandle++;
184 
185 	return true;
186 }
187 
188 // Read 16
189 bool
190 LittleEndianBuffer::Read(uint16& value)
191 {
192 	if ((fHandle + 1) >= fBufferEnd)
193 		return false;
194 
195 	value = B_LENDIAN_TO_HOST_INT16(*(uint16*)fHandle);
196 	fHandle += 2;
197 
198 	return true;
199 }
200 
201 // Read 32
202 bool
203 LittleEndianBuffer::Read(uint32& value)
204 {
205 	if ((fHandle + 3) >= fBufferEnd)
206 		return false;
207 
208 	value = B_LENDIAN_TO_HOST_INT32(*(uint32*)fHandle);
209 	fHandle += 4;
210 
211 	return true;
212 }
213 
214 // Read float
215 bool
216 LittleEndianBuffer::Read(float& value)
217 {
218 	if ((fHandle + sizeof(float) - 1) >= fBufferEnd)
219 		return false;
220 
221 	value = B_LENDIAN_TO_HOST_FLOAT(*(float*)fHandle);
222 	fHandle += sizeof(float);
223 
224 	return true;
225 }
226 
227 // Read double
228 bool
229 LittleEndianBuffer::Read(double& value)
230 {
231 	if ((fHandle + sizeof(double) - 1) >= fBufferEnd)
232 		return false;
233 
234 	value = B_LENDIAN_TO_HOST_DOUBLE(*(double*)fHandle);
235 	fHandle += sizeof(double);
236 
237 	return true;
238 }
239 
240 // Read LittleEndianBuffer
241 bool
242 LittleEndianBuffer::Read(LittleEndianBuffer& other, size_t bytes)
243 {
244 	if ((fHandle + bytes - 1) >= fBufferEnd)
245 		return false;
246 
247 	if (other.Write(fHandle, bytes)) {
248 		// reset other handle to beginning of pasted data
249 		other.fHandle -= bytes;
250 		fHandle += bytes;
251 		return true;
252 	}
253 
254 	return false;
255 }
256 
257 // #pragma mark -
258 
259 // Skip
260 void
261 LittleEndianBuffer::Skip(size_t bytes)
262 {
263 	// NOTE: is ment to be used while reading!!
264 	// when used while writing, the growing will not work reliably
265 	fHandle += bytes;
266 }
267 
268 // Reset
269 void
270 LittleEndianBuffer::Reset()
271 {
272 	fHandle = fBuffer;
273 }
274 
275 // #pragma mark -
276 
277 // _SetSize
278 void
279 LittleEndianBuffer::_SetSize(size_t size)
280 {
281 	if (!fOwnsBuffer) {
282 		// prevent user error
283 		// (we are in read mode)
284 		fBuffer = NULL;
285 		return;
286 	}
287 
288 	int32 pos = fHandle - fBuffer;
289 	fBuffer = (uint8*)realloc((void*)fBuffer, size);
290 	fHandle = fBuffer + pos;
291 	fBufferEnd = fBuffer + size;
292 	fSize = size;
293 }
294 
295