1/*
2 * Copyright 2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *				Scott T. Mansfield, thephantom@mac.com
7 *              Bruno Albuquerque, bga@bug-br.org.br
8 */
9
10#include <ByteOrder.h>
11#include <Message.h>
12#include <TypeConstants.h>
13
14#include "DynamicBuffer.h"
15#include "NetBuffer.h"
16
17#include <new>
18#include <string.h>
19
20BNetBuffer::BNetBuffer(size_t size) :
21	BArchivable(),
22	fInit(B_NO_INIT)
23{
24	fImpl = new (std::nothrow) DynamicBuffer(size);
25	if (fImpl != NULL)
26		fInit = fImpl->InitCheck();
27}
28
29
30BNetBuffer::~BNetBuffer()
31{
32	delete fImpl;
33}
34
35
36BNetBuffer::BNetBuffer(const BNetBuffer& buffer) :
37	BArchivable(),
38	fInit(B_NO_INIT)
39{
40	fImpl = new (std::nothrow) DynamicBuffer(*buffer.GetImpl());
41	if (fImpl != NULL)
42		fInit = fImpl->InitCheck();
43}
44
45
46BNetBuffer::BNetBuffer(BMessage* archive) :
47	BArchivable(),
48	fInit(B_NO_INIT)
49{
50	const unsigned char* bufferPtr;
51	ssize_t bufferSize;
52
53	if (archive->FindData("buffer", B_RAW_TYPE, (const void**)&bufferPtr,
54		&bufferSize) == B_OK) {
55		fImpl = new (std::nothrow) DynamicBuffer(bufferSize);
56		if (fImpl != NULL) {
57			status_t result = fImpl->Insert(bufferPtr, bufferSize);
58			if (result == B_OK)
59				fInit = fImpl->InitCheck();
60			else
61				fInit = result;
62		}
63	}
64}
65
66BNetBuffer&
67BNetBuffer::operator=(const BNetBuffer& buffer)
68{
69	delete fImpl;
70
71	fImpl = new (std::nothrow) DynamicBuffer(*buffer.GetImpl());
72	if (fImpl != NULL)
73		fInit = fImpl->InitCheck();
74
75	return *this;
76}
77
78
79status_t
80BNetBuffer::Archive(BMessage* into, bool deep) const
81{
82	if (fInit != B_OK)
83		return B_NO_INIT;
84
85	status_t result = into->AddData("buffer", B_RAW_TYPE, fImpl->Data(),
86		fImpl->BytesRemaining());
87
88	return result;
89}
90
91
92BArchivable*
93BNetBuffer::Instantiate(BMessage* archive)
94{
95    if (!validate_instantiation(archive, "BNetBuffer")) {
96        return NULL;
97    }
98
99    BNetBuffer* buffer = new (std::nothrow) BNetBuffer(archive);
100    if (buffer == NULL)
101        return NULL;
102
103    if (buffer->InitCheck() != B_OK) {
104        delete buffer;
105        return NULL;
106    }
107
108    return buffer;
109}
110
111
112status_t
113BNetBuffer::InitCheck()
114{
115	return fInit;
116}
117
118
119status_t
120BNetBuffer::AppendInt8(int8 data)
121{
122	return AppendData((const void*)&data, sizeof(int8));
123}
124
125
126status_t
127BNetBuffer::AppendUint8(uint8 data)
128{
129	return AppendData((const void*)&data, sizeof(int8));
130}
131
132
133status_t
134BNetBuffer::AppendInt16(int16 data)
135{
136	int16 be_data = B_HOST_TO_BENDIAN_INT16(data);
137	return AppendData((const void*)&be_data, sizeof(int16));
138}
139
140
141status_t
142BNetBuffer::AppendUint16(uint16 data)
143{
144	uint16 be_data = B_HOST_TO_BENDIAN_INT16(data);
145	return AppendData((const void*)&be_data, sizeof(uint16));
146}
147
148
149status_t
150BNetBuffer::AppendInt32(int32 data)
151{
152	int32 be_data = B_HOST_TO_BENDIAN_INT32(data);
153	return AppendData((const void*)&be_data, sizeof(int32));
154}
155
156
157status_t
158BNetBuffer::AppendUint32(uint32 data)
159{
160	uint32 be_data = B_HOST_TO_BENDIAN_INT32(data);
161	return AppendData((const void*)&be_data, sizeof(uint32));
162}
163
164
165status_t
166BNetBuffer::AppendFloat(float data)
167{
168	return AppendData((const void*)&data, sizeof(float));
169}
170
171
172status_t
173BNetBuffer::AppendDouble(double data)
174{
175	return AppendData((const void*)&data, sizeof(double));
176}
177
178
179status_t
180BNetBuffer::AppendString(const char* data)
181{
182	return AppendData((const void*)data, strlen(data) + 1);
183}
184
185
186status_t
187BNetBuffer::AppendData(const void* data, size_t size)
188{
189	return fImpl->Insert(data, size);
190}
191
192
193#define STACK_BUFFER_SIZE 2048
194
195status_t
196BNetBuffer::AppendMessage(const BMessage& data)
197{
198	char stackFlattenedData[STACK_BUFFER_SIZE];
199
200	size_t dataSize = data.FlattenedSize();
201	if (dataSize == 0)
202		return B_ERROR;
203
204	status_t result = B_OK;
205
206	if (dataSize > STACK_BUFFER_SIZE) {
207		char* flattenedData = new (std::nothrow) char[dataSize];
208		if (flattenedData == NULL)
209			return B_NO_MEMORY;
210
211		if (data.Flatten(flattenedData, dataSize) == B_OK)
212			result = AppendData((const void*)&flattenedData, dataSize);
213
214		delete[] flattenedData;
215	} else {
216		if (data.Flatten(stackFlattenedData, dataSize) == B_OK)
217			result = AppendData((const void*)&stackFlattenedData, dataSize);
218	}
219
220	return result;
221}
222
223
224status_t
225BNetBuffer::AppendInt64(int64 data)
226{
227	int64 be_data = B_HOST_TO_BENDIAN_INT64(data);
228	return AppendData((const void*)&be_data, sizeof(int64));
229}
230
231
232status_t
233BNetBuffer::AppendUint64(uint64 data)
234{
235	uint64 be_data = B_HOST_TO_BENDIAN_INT64(data);
236	return AppendData((const void*)&be_data, sizeof(uint64));
237}
238
239
240status_t
241BNetBuffer::RemoveInt8(int8& data)
242{
243	return RemoveData((void*)&data, sizeof(int8));
244}
245
246
247status_t
248BNetBuffer::RemoveUint8(uint8& data)
249{
250	return RemoveData((void*)&data, sizeof(uint8));
251}
252
253
254status_t
255BNetBuffer::RemoveInt16(int16& data)
256{
257	int16 be_data;
258	status_t result = RemoveData((void*)&be_data, sizeof(int16));
259	if (result != B_OK)
260		return result;
261
262	data = B_BENDIAN_TO_HOST_INT16(be_data);
263
264	return B_OK;
265}
266
267
268status_t
269BNetBuffer::RemoveUint16(uint16& data)
270{
271	uint16 be_data;
272	status_t result = RemoveData((void*)&be_data, sizeof(uint16));
273	if (result != B_OK)
274		return result;
275
276	data = B_BENDIAN_TO_HOST_INT16(be_data);
277
278	return B_OK;
279}
280
281
282status_t
283BNetBuffer::RemoveInt32(int32& data)
284{
285	int32 be_data;
286	status_t result = RemoveData((void*)&be_data, sizeof(int32));
287	if (result != B_OK)
288		return result;
289
290	data = B_BENDIAN_TO_HOST_INT32(be_data);
291
292	return B_OK;
293}
294
295
296status_t
297BNetBuffer::RemoveUint32(uint32& data)
298{
299	uint32 be_data;
300	status_t result = RemoveData((void*)&be_data, sizeof(uint32));
301	if (result != B_OK)
302		return result;
303
304	data = B_BENDIAN_TO_HOST_INT32(be_data);
305
306	return B_OK;
307}
308
309
310status_t
311BNetBuffer::RemoveFloat(float& data)
312{
313	return RemoveData((void*)&data, sizeof(float));
314}
315
316
317status_t
318BNetBuffer::RemoveDouble(double& data)
319{
320	return RemoveData((void*)&data, sizeof(double));
321}
322
323
324status_t
325BNetBuffer::RemoveString(char* data, size_t size)
326{
327	// TODO(bga): Should we do anything specific to handle the terminating
328	// NULL byte?
329	return RemoveData((void*)data, size);
330}
331
332
333status_t
334BNetBuffer::RemoveData(void* data, size_t size)
335{
336	return fImpl->Remove(data, size);
337}
338
339
340status_t
341BNetBuffer::RemoveMessage(BMessage& data)
342{
343	unsigned char* bufferPtr = fImpl->Data();
344
345	if (*(int32*)bufferPtr != B_MESSAGE_TYPE)
346		return B_ERROR;
347
348
349	bufferPtr += sizeof(int32);
350	int32 dataSize = *(int32*)bufferPtr;
351
352	char* flattenedData = new (std::nothrow) char[dataSize];
353	if (flattenedData == NULL)
354		return B_NO_MEMORY;
355
356	status_t result = RemoveData(flattenedData, dataSize);
357	if (result == B_OK)
358		result = data.Unflatten(flattenedData);
359
360	delete[] flattenedData;
361
362	return result;
363}
364
365
366status_t
367BNetBuffer::RemoveInt64(int64& data)
368{
369	int64 be_data;
370	status_t result = RemoveData((void*)&be_data, sizeof(int64));
371	if (result != B_OK)
372		return result;
373
374	data = B_BENDIAN_TO_HOST_INT64(be_data);
375
376	return B_OK;
377}
378
379
380status_t
381BNetBuffer::RemoveUint64(uint64& data)
382{
383	uint64 be_data;
384	status_t result = RemoveData((void*)&be_data, sizeof(uint64));
385	if (result != B_OK)
386		return result;
387
388	data = B_BENDIAN_TO_HOST_INT64(be_data);
389
390	return B_OK;
391}
392
393
394unsigned char*
395BNetBuffer::Data() const
396{
397	return fImpl->Data();
398}
399
400
401size_t
402BNetBuffer::Size() const
403{
404	return fImpl->Size();
405}
406
407
408size_t
409BNetBuffer::BytesRemaining() const
410{
411	return fImpl->BytesRemaining();
412}
413
414
415void
416BNetBuffer::_ReservedBNetBufferFBCCruft1()
417{
418}
419
420
421void
422BNetBuffer::_ReservedBNetBufferFBCCruft2()
423{
424}
425
426
427void
428BNetBuffer::_ReservedBNetBufferFBCCruft3()
429{
430}
431
432
433void
434BNetBuffer::_ReservedBNetBufferFBCCruft4()
435{
436}
437
438
439void
440BNetBuffer::_ReservedBNetBufferFBCCruft5()
441{
442}
443
444
445void
446BNetBuffer::_ReservedBNetBufferFBCCruft6()
447{
448}
449