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 19DynamicBuffer::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 36DynamicBuffer::~DynamicBuffer() 37{ 38 delete[] fBuffer; 39 fBufferSize = 0; 40 fDataStart = 0; 41 fDataEnd = 0; 42} 43 44 45DynamicBuffer::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 65status_t 66DynamicBuffer::InitCheck() const 67{ 68 return fInit; 69} 70 71 72status_t 73DynamicBuffer::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 89status_t 90DynamicBuffer::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 108unsigned char* 109DynamicBuffer::Data() const 110{ 111 return fBuffer + fDataStart; 112} 113 114 115size_t 116DynamicBuffer::Size() const 117{ 118 return fDataEnd - fDataStart; 119} 120 121 122size_t 123DynamicBuffer::BytesRemaining() const 124{ 125 return fBufferSize - fDataEnd; 126} 127 128 129void 130DynamicBuffer::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 140status_t 141DynamicBuffer::_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