From 550d24175fdf61ba73af4ef30c28386894deb4d0 Mon Sep 17 00:00:00 2001 From: "Bruno G. Albuquerque" Date: Sat, 17 Jan 2009 13:30:21 +0000 Subject: [PATCH] - Simple dynamic buffer class implementation. - Will be used by the new (R5 compatible) NetBuffer class. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28918 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/net/DynamicBuffer.h | 60 ++++++++ src/kits/network/libnetapi/DynamicBuffer.cpp | 139 +++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 headers/private/net/DynamicBuffer.h create mode 100644 src/kits/network/libnetapi/DynamicBuffer.cpp 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; +}