diff --git a/headers/private/net/DynamicBuffer.h b/headers/private/net/DynamicBuffer.h new file mode 100644 index 0000000000..61961214ba --- /dev/null +++ b/headers/private/net/DynamicBuffer.h @@ -0,0 +1,60 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Bruno Albuquerque, bga@bug-br.org.br + */ + +#ifndef _DYNAMIC_BUFFER_H +#define _DYNAMIC_BUFFER_H + +#include + + +class DynamicBuffer { +public: + DynamicBuffer(size_t _initialSize = 0); + ~DynamicBuffer(); + + // InitCheck() should be called to guarantee the object initialization + // didn't fail. If it does not return B_OK, the initialization failed. + status_t InitCheck() const; + + // Insert data at the end of the buffer. The buffer will be increased to + // accomodate the data if needed. + status_t Insert(const void* _data, size_t _size); + + // Remove data from the start of the buffer. Move the buffer start + // pointer to point to the data following it. + status_t Remove(void* _data, size_t _size); + + // Return a pointer to the underlying buffer. Note this will not + // necessarily be a pointer to the start of the allocated memory as the + // initial data may be positioned at an offset inside the buffer. In other + // words, this returns a pointer to the start of data inside the buffer. + unsigned char* Data() const; + + // Returns the actual buffer size. This is the amount of memory allocated + // for the buffer. + size_t Size() const; + + // Number of bytes of data still present in the buffer that can be + // extracted through calls to Remove(). + size_t BytesRemaining() const; + + // Dump some buffer statistics to stdout. + void PrintToStream(); + +private: + status_t _GrowToFit(size_t _size); + + unsigned char* fBuffer; + size_t fBufferSize; + size_t fDataStart; + size_t fDataEnd; + + status_t fInit; +}; + +#endif // _DYNAMIC_BUFFER_H diff --git a/src/kits/network/libnetapi/DynamicBuffer.cpp b/src/kits/network/libnetapi/DynamicBuffer.cpp new file mode 100644 index 0000000000..874f3bc3c3 --- /dev/null +++ b/src/kits/network/libnetapi/DynamicBuffer.cpp @@ -0,0 +1,139 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Bruno Albuquerque, bga@bug-br.org.br + */ + +#include "DynamicBuffer.h" + +#include +#include + + +DynamicBuffer::DynamicBuffer(size_t _initialSize) : + fBuffer(NULL), + fBufferSize(0), + fDataStart(0), + fDataEnd(0), + fInit(B_NO_INIT) +{ + if (_initialSize > 0) { + fBuffer = new unsigned char[_initialSize]; + if (fBuffer != NULL) { + fBufferSize = _initialSize; + fInit = B_OK; + } + } +} + + +DynamicBuffer::~DynamicBuffer() +{ + delete[] fBuffer; + fBufferSize = 0; + fDataStart = 0; + fDataEnd = 0; +} + + +status_t +DynamicBuffer::InitCheck() const +{ + return fInit; +} + + +status_t +DynamicBuffer::Insert(const void* _data, size_t _size) +{ + if (fInit != B_OK) + return fInit; + + status_t result = _GrowToFit(_size); + if (result != B_OK) + return result; + + memcpy(fBuffer + fDataEnd, _data, _size); + fDataEnd += _size; + + return B_OK; +} + + +status_t +DynamicBuffer::Remove(void* _data, size_t _size) +{ + if (fInit != B_OK) + return fInit; + + if (fDataStart + _size > fDataEnd) + return B_BUFFER_OVERFLOW; + + memcpy(_data, fBuffer + fDataStart, _size); + fDataStart += _size; + + if (fDataStart == fDataEnd) + fDataStart = fDataEnd = 0; + + return B_OK; +} + + +unsigned char* +DynamicBuffer::Data() const +{ + return fBuffer + fDataStart; +} + + +size_t +DynamicBuffer::Size() const +{ + return fBufferSize; +} + + +size_t +DynamicBuffer::BytesRemaining() const +{ + return fDataEnd - fDataStart; +} + + +void +DynamicBuffer::PrintToStream() +{ + printf("Current buffer size : %ld\n", fBufferSize); + printf("Data start position : %ld\n", fDataStart); + printf("Data end position : %ld\n", fDataEnd); + printf("Bytes wasted : %ld\n", fDataStart); + printf("Bytes available : %ld\n", fBufferSize - fDataEnd); +} + + +status_t +DynamicBuffer::_GrowToFit(size_t _size) +{ + if (_size <= fBufferSize - fDataEnd) + return B_OK; + + size_t newSize = (fBufferSize + _size) * 2; + + unsigned char* newBuffer = new unsigned char[newSize]; + if (newBuffer == NULL) + return B_NO_MEMORY; + + if (fDataStart != fDataEnd) { + memcpy(newBuffer, fBuffer + fDataStart, fDataEnd - fDataStart); + } + + delete[] fBuffer; + fBuffer = newBuffer; + fDataEnd -= fDataStart; + fDataStart = 0; + fBufferSize = newSize; + + return B_OK; +}