diff --git a/Foundation/include/Poco/Buffer.h b/Foundation/include/Poco/Buffer.h index d2f244722..b80c110e3 100644 --- a/Foundation/include/Poco/Buffer.h +++ b/Foundation/include/Poco/Buffer.h @@ -60,6 +60,7 @@ class Buffer public: Buffer(std::size_t size): _size(size), + _used(size), _ptr(new T[size]) /// Creates and allocates the Buffer. { @@ -79,21 +80,30 @@ public: { poco_assert(newSize); - T* ptr = new T[newSize]; - if (preserveContent) + if (newSize > _size) { - std::size_t n = newSize > _size ? _size : newSize; - std::memcpy(ptr, _ptr, n); + T* ptr = new T[newSize]; + if (preserveContent) + std::memcpy(ptr, _ptr, newSize); + + delete [] _ptr; + _ptr = ptr; + _size = newSize; } - delete [] _ptr; - _ptr = ptr; - _size = newSize; + + _used = newSize; + } + + std::size_t allocated() const + /// Returns the allocated memory size. + { + return _size; } std::size_t size() const - /// Returns the size of the buffer. + /// Returns the used size of the buffer. { - return _size; + return _used; } T* begin() @@ -111,25 +121,25 @@ public: T* end() /// Returns a pointer to end of the buffer. { - return _ptr + _size; + return _ptr + _used; } const T* end() const /// Returns a pointer to the end of the buffer. { - return _ptr + _size; + return _ptr + _used; } T& operator [] (std::size_t index) { - poco_assert (index < _size); + poco_assert (index < _used); return _ptr[index]; } const T& operator [] (std::size_t index) const { - poco_assert (index < _size); + poco_assert (index < _used); return _ptr[index]; } @@ -140,6 +150,7 @@ private: Buffer& operator = (const Buffer&); std::size_t _size; + std::size_t _used; T* _ptr; }; diff --git a/Foundation/include/Poco/FIFOBuffer.h b/Foundation/include/Poco/FIFOBuffer.h index 37a06dcc7..b34602935 100644 --- a/Foundation/include/Poco/FIFOBuffer.h +++ b/Foundation/include/Poco/FIFOBuffer.h @@ -89,6 +89,7 @@ public: FIFOBuffer(std::size_t size, bool notify = false): _buffer(size), + _begin(0), _used(0), _notify(notify) /// Creates and allocates the FIFOBuffer. @@ -124,7 +125,7 @@ public: /// Peeks into the data currently in the FIFO /// without actually extracting it. /// Resizes the supplied buffer to the size of - ///.data written to it. If length is not + /// data written to it. If length is not /// supplied by the caller, the current FIFO used length /// is substituted for it. /// @@ -135,7 +136,7 @@ public: if (0 == length || length > _used) length = _used; poco_assert (length <= _buffer.size()); buffer.resize(length); - std::memcpy(buffer.begin(), _buffer.begin(), length * sizeof(T)); + std::memcpy(buffer.begin(), _buffer.begin() + _begin, length * sizeof(T)); return length; } @@ -144,7 +145,7 @@ public: /// Copies the data currently in the FIFO /// into the supplied buffer. /// Resizes the supplied buffer to the size of - ///.data written to it. + /// data written to it. /// /// Returns the reference to the buffer. { @@ -156,9 +157,9 @@ public: std::size_t readLen = peek(buffer, length); poco_assert (_used >= readLen); _used -= readLen; - if (_used > 0) - std::memmove(_buffer.begin(), _buffer.begin() + usedBefore - _used, _used); - + if (0 == _used) _begin = 0; + else _begin += length; + if (_notify) notify(usedBefore); return readLen; @@ -174,11 +175,16 @@ public: { Mutex::ScopedLock lock(_mutex); - poco_assert (_used <= _buffer.size()); + if (_buffer.size() - (_begin + _used) < buffer.size()) + { + std::memmove(_buffer.begin(), _buffer.begin() + _begin, _used); + _begin = 0; + } + std::size_t usedBefore = _used; - std::size_t available = _buffer.size() - _used; + std::size_t available = _buffer.size() - _used - _begin; std::size_t len = buffer.size() > available ? available : buffer.size(); - std::memcpy(_buffer.begin() + _used, buffer.begin(), len * sizeof(T)); + std::memcpy(_buffer.begin() + _begin + _used, buffer.begin(), len * sizeof(T)); _used += len; poco_assert (_used <= _buffer.size()); if (_notify) notify(usedBefore); @@ -212,7 +218,7 @@ public: if (index >= _used) throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1)); - return _buffer[index]; + return _buffer[_begin + index]; } const T& operator [] (std::size_t index) const @@ -223,7 +229,7 @@ public: if (index >= _used) throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1)); - return _buffer[index]; + return _buffer[_begin + index]; } bool isEmpty() const @@ -251,6 +257,7 @@ private: FIFOBuffer& operator = (const FIFOBuffer&); Buffer _buffer; + std::size_t _begin; std::size_t _used; bool _notify; mutable Mutex _mutex; diff --git a/Foundation/testsuite/src/CoreTest.cpp b/Foundation/testsuite/src/CoreTest.cpp index 62549dae4..e36e9f1ea 100644 --- a/Foundation/testsuite/src/CoreTest.cpp +++ b/Foundation/testsuite/src/CoreTest.cpp @@ -197,6 +197,8 @@ void CoreTest::testBuffer() { std::size_t s = 10; Buffer b(s); + assert (b.size() == s); + assert (b.allocated() == s); std::vector v; for (int i = 0; i < s; ++i) v.push_back(i); @@ -207,6 +209,26 @@ void CoreTest::testBuffer() for (int i = 0; i < s; ++i) assert (b[i] == i); + b.resize(s/2); + for (int i = 0; i < s/2; ++i) + assert (b[i] == i); + + assert (b.size() == s/2); + assert (b.allocated() == s); + + b.resize(s*2); + v.clear(); + for (int i = 0; i < s*2; ++i) + v.push_back(i); + + std::memcpy(b.begin(), &v[0], sizeof(int) * v.size()); + + for (int i = 0; i < s*2; ++i) + assert (b[i] == i); + + assert (b.size() == s*2); + assert (b.allocated() == s*2); + #if ENABLE_BUGCHECK_TEST try { int i = b[s]; fail ("must fail"); } catch (Exception&) { }