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 21DynamicBuffer::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 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 72ssize_t 73DynamicBuffer::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 89ssize_t 90DynamicBuffer::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 109unsigned char* 110DynamicBuffer::Data() const 111{ 112 return fBuffer + fDataStart; 113} 114 115 116size_t 117DynamicBuffer::Size() const 118{ 119 return fDataEnd - fDataStart; 120} 121 122 123size_t 124DynamicBuffer::BytesRemaining() const 125{ 126 return fBufferSize - fDataEnd; 127} 128 129 130void 131DynamicBuffer::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 141status_t 142DynamicBuffer::_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