xref: /haiku/src/kits/network/libnetapi/DynamicBuffer.cpp (revision 37fedaf8494b34aad811abcc49e79aa32943f880)
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 	fBuffer = new (std::nothrow) unsigned char[initialSize];
27 	if (fBuffer != NULL) {
28 		fBufferSize = initialSize;
29 		fInit = B_OK;
30 	}
31 }
32 
33 
34 DynamicBuffer::~DynamicBuffer()
35 {
36 	delete[] fBuffer;
37 	fBufferSize = 0;
38 	fDataStart = 0;
39 	fDataEnd = 0;
40 }
41 
42 
43 DynamicBuffer::DynamicBuffer(const DynamicBuffer& buffer) :
44 	fBuffer(NULL),
45 	fBufferSize(0),
46 	fDataStart(0),
47 	fDataEnd(0),
48 	fInit(B_NO_INIT)
49 {
50 	fInit = buffer.fInit;
51 	if (fInit == B_OK) {
52 		status_t result = _GrowToFit(buffer.fBufferSize, true);
53 		if (result == B_OK) {
54 			memcpy(fBuffer, buffer.fBuffer, fBufferSize);
55 			fDataStart = buffer.fDataStart;
56 			fDataEnd = buffer.fDataEnd;
57 		} else
58 			fInit = result;
59 	}
60 }
61 
62 
63 status_t
64 DynamicBuffer::InitCheck() const
65 {
66 	return fInit;
67 }
68 
69 
70 ssize_t
71 DynamicBuffer::Write(const void* data, size_t size)
72 {
73 	if (fInit != B_OK)
74 		return fInit;
75 
76 	status_t result = _GrowToFit(size);
77 	if (result != B_OK)
78 		return result;
79 
80 	memcpy(fBuffer + fDataEnd, data, size);
81 	fDataEnd += size;
82 
83 	return size;
84 }
85 
86 
87 ssize_t
88 DynamicBuffer::Read(void* data, size_t size)
89 {
90 	if (fInit != B_OK)
91 		return fInit;
92 
93 	if (size > Size())
94 		size = Size();
95 
96 	memcpy(data, fBuffer + fDataStart, size);
97 	fDataStart += size;
98 
99 	if (fDataStart == fDataEnd)
100 		fDataStart = fDataEnd = 0;
101 
102 	return size;
103 }
104 
105 
106 unsigned char*
107 DynamicBuffer::Data() const
108 {
109 	return fBuffer + fDataStart;
110 }
111 
112 
113 size_t
114 DynamicBuffer::Size() const
115 {
116 	return fDataEnd - fDataStart;
117 }
118 
119 
120 size_t
121 DynamicBuffer::BytesRemaining() const
122 {
123 	return fBufferSize - fDataEnd;
124 }
125 
126 
127 void
128 DynamicBuffer::PrintToStream()
129 {
130 	printf("Current buffer size : %ld\n", fBufferSize);
131 	printf("Data start position : %ld\n", fDataStart);
132 	printf("Data end position   : %ld\n", fDataEnd);
133 	printf("Bytes wasted        : %ld\n", fDataStart);
134 	printf("Bytes available     : %ld\n", fBufferSize - fDataEnd);
135 }
136 
137 
138 status_t
139 DynamicBuffer::_GrowToFit(size_t size, bool exact)
140 {
141 	if (size <= fBufferSize - fDataEnd)
142 		return B_OK;
143 
144 	size_t newSize;
145 	if (!exact)
146 		newSize = (fBufferSize + size) * 2;
147 	else
148 		newSize = size;
149 
150 	unsigned char* newBuffer = new (std::nothrow) unsigned char[newSize];
151 	if (newBuffer == NULL)
152 		return B_NO_MEMORY;
153 
154 	if (fDataStart != fDataEnd)
155 		memcpy(newBuffer, fBuffer + fDataStart, fDataEnd - fDataStart);
156 
157 	delete[] fBuffer;
158 	fBuffer = newBuffer;
159 	fDataEnd -= fDataStart;
160 	fDataStart = 0;
161 	fBufferSize = newSize;
162 
163 	return B_OK;
164 }
165