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