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