xref: /haiku/src/kits/network/libnetapi/DynamicBuffer.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
1 /*
2  * Copyright 2009, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *              Bruno Albuquerque, bga@bug-br.org.br
7  */
8 
9 #include "DynamicBuffer.h"
10 
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include <Errors.h>
15 #include <SupportDefs.h>
16 
17 #include <new>
18 
19 DynamicBuffer::DynamicBuffer(size_t initialSize) :
20 	fBuffer(NULL),
21 	fBufferSize(0),
22 	fDataStart(0),
23 	fDataEnd(0),
24 	fInit(B_NO_INIT)
25 {
26 	if (initialSize >= 0) {
27 		fBuffer = new (std::nothrow) unsigned char[initialSize];
28 		if (fBuffer != NULL) {
29 			fBufferSize = initialSize;
30 			fInit = B_OK;
31 		}
32 	}
33 }
34 
35 
36 DynamicBuffer::~DynamicBuffer()
37 {
38 	delete[] fBuffer;
39 	fBufferSize = 0;
40 	fDataStart = 0;
41 	fDataEnd = 0;
42 }
43 
44 
45 DynamicBuffer::DynamicBuffer(const DynamicBuffer& buffer) :
46 	fBuffer(NULL),
47 	fBufferSize(0),
48 	fDataStart(0),
49 	fDataEnd(0),
50 	fInit(B_NO_INIT)
51 {
52 	fInit = buffer.fInit;
53 	if (fInit == B_OK) {
54 		status_t result = _GrowToFit(buffer.fBufferSize, true);
55 		if (result == B_OK) {
56 			memcpy(fBuffer, buffer.fBuffer, fBufferSize);
57 			fDataStart = buffer.fDataStart;
58 			fDataEnd = buffer.fDataEnd;
59 		} else
60 			fInit = result;
61 	}
62 }
63 
64 
65 status_t
66 DynamicBuffer::InitCheck() const
67 {
68 	return fInit;
69 }
70 
71 
72 status_t
73 DynamicBuffer::Insert(const void* data, size_t size)
74 {
75 	if (fInit != B_OK)
76 		return fInit;
77 
78 	status_t result = _GrowToFit(size);
79 	if (result != B_OK)
80 		return result;
81 
82 	memcpy(fBuffer + fDataEnd, data, size);
83 	fDataEnd += size;
84 
85 	return B_OK;
86 }
87 
88 
89 status_t
90 DynamicBuffer::Remove(void* data, size_t size)
91 {
92 	if (fInit != B_OK)
93 		return fInit;
94 
95 	if (fDataStart + size > fDataEnd)
96 		return B_BUFFER_OVERFLOW;
97 
98 	memcpy(data, fBuffer + fDataStart, size);
99 	fDataStart += size;
100 
101 	if (fDataStart == fDataEnd)
102 		fDataStart = fDataEnd = 0;
103 
104 	return B_OK;
105 }
106 
107 
108 unsigned char*
109 DynamicBuffer::Data() const
110 {
111 	return fBuffer + fDataStart;
112 }
113 
114 
115 size_t
116 DynamicBuffer::Size() const
117 {
118 	return fDataEnd - fDataStart;
119 }
120 
121 
122 size_t
123 DynamicBuffer::BytesRemaining() const
124 {
125 	return fBufferSize - fDataEnd;
126 }
127 
128 
129 void
130 DynamicBuffer::PrintToStream()
131 {
132 	printf("Current buffer size : %ld\n", fBufferSize);
133 	printf("Data start position : %ld\n", fDataStart);
134 	printf("Data end position   : %ld\n", fDataEnd);
135 	printf("Bytes wasted        : %ld\n", fDataStart);
136 	printf("Bytes available     : %ld\n", fBufferSize - fDataEnd);
137 }
138 
139 
140 status_t
141 DynamicBuffer::_GrowToFit(size_t size, bool exact)
142 {
143 	if (size <= fBufferSize - fDataEnd)
144 		return B_OK;
145 
146 	size_t newSize;
147 	if (!exact)
148 		newSize = (fBufferSize + size) * 2;
149 	else
150 		newSize = size;
151 
152 	unsigned char* newBuffer = new (std::nothrow) unsigned char[newSize];
153 	if (newBuffer == NULL)
154 		return B_NO_MEMORY;
155 
156 	if (fDataStart != fDataEnd) {
157 		memcpy(newBuffer, fBuffer + fDataStart, fDataEnd - fDataStart);
158 	}
159 
160 	delete[] fBuffer;
161 	fBuffer = newBuffer;
162 	fDataEnd -= fDataStart;
163 	fDataStart = 0;
164 	fBufferSize = newSize;
165 
166 	return B_OK;
167 }
168