1852b0119SRene Gollent/*
2852b0119SRene Gollent * Copyright 2009, Haiku, Inc. All Rights Reserved.
3852b0119SRene Gollent * Distributed under the terms of the MIT License.
4852b0119SRene Gollent *
5852b0119SRene Gollent * Authors:
6852b0119SRene Gollent *              Bruno Albuquerque, bga@bug-br.org.br
7852b0119SRene Gollent */
8852b0119SRene Gollent
9852b0119SRene Gollent#include "DynamicBuffer.h"
10852b0119SRene Gollent
11852b0119SRene Gollent#include <stdio.h>
12852b0119SRene Gollent#include <string.h>
13852b0119SRene Gollent
1425d34313SIngo Weinhold#include <algorithm>
1525d34313SIngo Weinhold
16852b0119SRene Gollent#include <Errors.h>
17852b0119SRene Gollent#include <SupportDefs.h>
18852b0119SRene Gollent
19852b0119SRene Gollent#include <new>
20852b0119SRene Gollent
21852b0119SRene GollentDynamicBuffer::DynamicBuffer(size_t initialSize) :
22852b0119SRene Gollent	fBuffer(NULL),
23852b0119SRene Gollent	fBufferSize(0),
24852b0119SRene Gollent	fDataStart(0),
25852b0119SRene Gollent	fDataEnd(0),
26852b0119SRene Gollent	fInit(B_NO_INIT)
27852b0119SRene Gollent{
28194ce33dSJessica Hamilton	fBuffer = new (std::nothrow) unsigned char[initialSize];
29194ce33dSJessica Hamilton	if (fBuffer != NULL) {
30194ce33dSJessica Hamilton		fBufferSize = initialSize;
31194ce33dSJessica Hamilton		fInit = B_OK;
32852b0119SRene Gollent	}
33852b0119SRene Gollent}
34852b0119SRene Gollent
35852b0119SRene Gollent
36852b0119SRene GollentDynamicBuffer::~DynamicBuffer()
37852b0119SRene Gollent{
38852b0119SRene Gollent	delete[] fBuffer;
39852b0119SRene Gollent	fBufferSize = 0;
40852b0119SRene Gollent	fDataStart = 0;
41852b0119SRene Gollent	fDataEnd = 0;
42852b0119SRene Gollent}
43852b0119SRene Gollent
44852b0119SRene Gollent
45852b0119SRene GollentDynamicBuffer::DynamicBuffer(const DynamicBuffer& buffer) :
46852b0119SRene Gollent	fBuffer(NULL),
47852b0119SRene Gollent	fBufferSize(0),
48852b0119SRene Gollent	fDataStart(0),
49852b0119SRene Gollent	fDataEnd(0),
50852b0119SRene Gollent	fInit(B_NO_INIT)
51852b0119SRene Gollent{
52852b0119SRene Gollent	fInit = buffer.fInit;
53852b0119SRene Gollent	if (fInit == B_OK) {
54852b0119SRene Gollent		status_t result = _GrowToFit(buffer.fBufferSize, true);
55852b0119SRene Gollent		if (result == B_OK) {
56852b0119SRene Gollent			memcpy(fBuffer, buffer.fBuffer, fBufferSize);
57852b0119SRene Gollent			fDataStart = buffer.fDataStart;
58852b0119SRene Gollent			fDataEnd = buffer.fDataEnd;
59852b0119SRene Gollent		} else
60852b0119SRene Gollent			fInit = result;
61852b0119SRene Gollent	}
62852b0119SRene Gollent}
63852b0119SRene Gollent
64852b0119SRene Gollent
65852b0119SRene Gollentstatus_t
66852b0119SRene GollentDynamicBuffer::InitCheck() const
67852b0119SRene Gollent{
68852b0119SRene Gollent	return fInit;
69852b0119SRene Gollent}
70852b0119SRene Gollent
71852b0119SRene Gollent
726926863eSIngo Weinholdssize_t
73739f15e1SIngo WeinholdDynamicBuffer::Write(const void* data, size_t size)
74852b0119SRene Gollent{
75852b0119SRene Gollent	if (fInit != B_OK)
76754bbf48SJérôme Duval		return fInit;
77852b0119SRene Gollent
78852b0119SRene Gollent	status_t result = _GrowToFit(size);
79852b0119SRene Gollent	if (result != B_OK)
80852b0119SRene Gollent		return result;
81754bbf48SJérôme Duval
82852b0119SRene Gollent	memcpy(fBuffer + fDataEnd, data, size);
83852b0119SRene Gollent	fDataEnd += size;
84754bbf48SJérôme Duval
856926863eSIngo Weinhold	return (ssize_t)size;
86852b0119SRene Gollent}
87852b0119SRene Gollent
88852b0119SRene Gollent
89739f15e1SIngo Weinholdssize_t
90739f15e1SIngo WeinholdDynamicBuffer::Read(void* data, size_t size)
91852b0119SRene Gollent{
92852b0119SRene Gollent	if (fInit != B_OK)
93852b0119SRene Gollent		return fInit;
94852b0119SRene Gollent
9525d34313SIngo Weinhold	size = std::min(size, Size());
9625d34313SIngo Weinhold	if (size == 0)
9725d34313SIngo Weinhold		return 0;
98754bbf48SJérôme Duval
99852b0119SRene Gollent	memcpy(data, fBuffer + fDataStart, size);
100852b0119SRene Gollent	fDataStart += size;
101754bbf48SJérôme Duval
102852b0119SRene Gollent	if (fDataStart == fDataEnd)
103852b0119SRene Gollent		fDataStart = fDataEnd = 0;
104754bbf48SJérôme Duval
105739f15e1SIngo Weinhold	return size;
106852b0119SRene Gollent}
107852b0119SRene Gollent
108852b0119SRene Gollent
109852b0119SRene Gollentunsigned char*
110852b0119SRene GollentDynamicBuffer::Data() const
111852b0119SRene Gollent{
112852b0119SRene Gollent	return fBuffer + fDataStart;
113852b0119SRene Gollent}
114852b0119SRene Gollent
115852b0119SRene Gollent
116852b0119SRene Gollentsize_t
117852b0119SRene GollentDynamicBuffer::Size() const
118852b0119SRene Gollent{
119852b0119SRene Gollent	return fDataEnd - fDataStart;
120852b0119SRene Gollent}
121852b0119SRene Gollent
122852b0119SRene Gollent
123852b0119SRene Gollentsize_t
124852b0119SRene GollentDynamicBuffer::BytesRemaining() const
125852b0119SRene Gollent{
126852b0119SRene Gollent	return fBufferSize - fDataEnd;
127852b0119SRene Gollent}
128852b0119SRene Gollent
129852b0119SRene Gollent
130852b0119SRene Gollentvoid
131852b0119SRene GollentDynamicBuffer::PrintToStream()
132852b0119SRene Gollent{
133852b0119SRene Gollent	printf("Current buffer size : %ld\n", fBufferSize);
134852b0119SRene Gollent	printf("Data start position : %ld\n", fDataStart);
135852b0119SRene Gollent	printf("Data end position   : %ld\n", fDataEnd);
136852b0119SRene Gollent	printf("Bytes wasted        : %ld\n", fDataStart);
137754bbf48SJérôme Duval	printf("Bytes available     : %ld\n", fBufferSize - fDataEnd);
138852b0119SRene Gollent}
139852b0119SRene Gollent
140852b0119SRene Gollent
141852b0119SRene Gollentstatus_t
142852b0119SRene GollentDynamicBuffer::_GrowToFit(size_t size, bool exact)
143852b0119SRene Gollent{
144852b0119SRene Gollent	if (size <= fBufferSize - fDataEnd)
145852b0119SRene Gollent		return B_OK;
146852b0119SRene Gollent
147852b0119SRene Gollent	size_t newSize;
148754bbf48SJérôme Duval	if (!exact)
149852b0119SRene Gollent		newSize = (fBufferSize + size) * 2;
150852b0119SRene Gollent	else
151852b0119SRene Gollent		newSize = size;
152852b0119SRene Gollent
153852b0119SRene Gollent	unsigned char* newBuffer = new (std::nothrow) unsigned char[newSize];
154852b0119SRene Gollent	if (newBuffer == NULL)
155852b0119SRene Gollent		return B_NO_MEMORY;
156852b0119SRene Gollent
157754bbf48SJérôme Duval	if (fDataStart != fDataEnd)
158754bbf48SJérôme Duval		memcpy(newBuffer, fBuffer + fDataStart, fDataEnd - fDataStart);
159754bbf48SJérôme Duval
160852b0119SRene Gollent	delete[] fBuffer;
161852b0119SRene Gollent	fBuffer = newBuffer;
162852b0119SRene Gollent	fDataEnd -= fDataStart;
163852b0119SRene Gollent	fDataStart = 0;
164852b0119SRene Gollent	fBufferSize = newSize;
165852b0119SRene Gollent
166852b0119SRene Gollent	return B_OK;
167852b0119SRene Gollent}
168