xref: /haiku/src/kits/network/libnetapi/DynamicBuffer.cpp (revision 25d34313d0c467b45748a535c888aa54ff864aa7)
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 <algorithm>
15 
16 #include <Errors.h>
17 #include <SupportDefs.h>
18 
19 #include <new>
20 
DynamicBuffer(size_t initialSize)21 DynamicBuffer::DynamicBuffer(size_t initialSize) :
22 	fBuffer(NULL),
23 	fBufferSize(0),
24 	fDataStart(0),
25 	fDataEnd(0),
26 	fInit(B_NO_INIT)
27 {
28 	fBuffer = new (std::nothrow) unsigned char[initialSize];
29 	if (fBuffer != NULL) {
30 		fBufferSize = initialSize;
31 		fInit = B_OK;
32 	}
33 }
34 
35 
~DynamicBuffer()36 DynamicBuffer::~DynamicBuffer()
37 {
38 	delete[] fBuffer;
39 	fBufferSize = 0;
40 	fDataStart = 0;
41 	fDataEnd = 0;
42 }
43 
44 
DynamicBuffer(const DynamicBuffer & buffer)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
InitCheck() const66 DynamicBuffer::InitCheck() const
67 {
68 	return fInit;
69 }
70 
71 
72 ssize_t
Write(const void * data,size_t size)73 DynamicBuffer::Write(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 (ssize_t)size;
86 }
87 
88 
89 ssize_t
Read(void * data,size_t size)90 DynamicBuffer::Read(void* data, size_t size)
91 {
92 	if (fInit != B_OK)
93 		return fInit;
94 
95 	size = std::min(size, Size());
96 	if (size == 0)
97 		return 0;
98 
99 	memcpy(data, fBuffer + fDataStart, size);
100 	fDataStart += size;
101 
102 	if (fDataStart == fDataEnd)
103 		fDataStart = fDataEnd = 0;
104 
105 	return size;
106 }
107 
108 
109 unsigned char*
Data() const110 DynamicBuffer::Data() const
111 {
112 	return fBuffer + fDataStart;
113 }
114 
115 
116 size_t
Size() const117 DynamicBuffer::Size() const
118 {
119 	return fDataEnd - fDataStart;
120 }
121 
122 
123 size_t
BytesRemaining() const124 DynamicBuffer::BytesRemaining() const
125 {
126 	return fBufferSize - fDataEnd;
127 }
128 
129 
130 void
PrintToStream()131 DynamicBuffer::PrintToStream()
132 {
133 	printf("Current buffer size : %ld\n", fBufferSize);
134 	printf("Data start position : %ld\n", fDataStart);
135 	printf("Data end position   : %ld\n", fDataEnd);
136 	printf("Bytes wasted        : %ld\n", fDataStart);
137 	printf("Bytes available     : %ld\n", fBufferSize - fDataEnd);
138 }
139 
140 
141 status_t
_GrowToFit(size_t size,bool exact)142 DynamicBuffer::_GrowToFit(size_t size, bool exact)
143 {
144 	if (size <= fBufferSize - fDataEnd)
145 		return B_OK;
146 
147 	size_t newSize;
148 	if (!exact)
149 		newSize = (fBufferSize + size) * 2;
150 	else
151 		newSize = size;
152 
153 	unsigned char* newBuffer = new (std::nothrow) unsigned char[newSize];
154 	if (newBuffer == NULL)
155 		return B_NO_MEMORY;
156 
157 	if (fDataStart != fDataEnd)
158 		memcpy(newBuffer, fBuffer + fDataStart, fDataEnd - fDataStart);
159 
160 	delete[] fBuffer;
161 	fBuffer = newBuffer;
162 	fDataEnd -= fDataStart;
163 	fDataStart = 0;
164 	fBufferSize = newSize;
165 
166 	return B_OK;
167 }
168