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