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