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 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 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 ssize_t 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 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* 110 DynamicBuffer::Data() const 111 { 112 return fBuffer + fDataStart; 113 } 114 115 116 size_t 117 DynamicBuffer::Size() const 118 { 119 return fDataEnd - fDataStart; 120 } 121 122 123 size_t 124 DynamicBuffer::BytesRemaining() const 125 { 126 return fBufferSize - fDataEnd; 127 } 128 129 130 void 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 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