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