mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-26 18:42:41 +01:00
FIFOBuffer::drain() and partial write
This commit is contained in:
@@ -58,10 +58,10 @@ class Buffer
|
||||
/// is needed.
|
||||
{
|
||||
public:
|
||||
Buffer(std::size_t size):
|
||||
_capacity(size),
|
||||
_used(size),
|
||||
_ptr(new T[size])
|
||||
Buffer(std::size_t capacity):
|
||||
_capacity(capacity),
|
||||
_used(capacity),
|
||||
_ptr(new T[capacity])
|
||||
/// Creates and allocates the Buffer.
|
||||
{
|
||||
}
|
||||
@@ -75,8 +75,8 @@ public:
|
||||
void resize(std::size_t newCapacity, bool preserveContent = true)
|
||||
/// Resizes the buffer. If preserveContent is true,
|
||||
/// the content of the old buffer is copied over to the
|
||||
/// new buffer. NewSize can be larger or smaller than
|
||||
/// the current size, but it must not be 0.
|
||||
/// new buffer. The new capacity can be larger or smaller than
|
||||
/// the current one, but it must not be 0.
|
||||
{
|
||||
poco_assert(newCapacity);
|
||||
|
||||
|
||||
@@ -54,10 +54,10 @@ namespace Poco {
|
||||
template <class T>
|
||||
class BasicFIFOBuffer
|
||||
/// A simple buffer class with support for re-entrant,
|
||||
/// FIFO-style read/write operations. as well as
|
||||
/// empty/full transition notifications. Buffer size
|
||||
/// introspection as well as amount of unread data and
|
||||
/// available space are supported as well.
|
||||
/// FIFO-style read/write operations, as well as (optional)
|
||||
/// empty/non-empty/full (i.e. writable/readable) transition
|
||||
/// notifications. Buffer size, as well as amount of unread data
|
||||
/// and available space introspections are supported as well.
|
||||
///
|
||||
/// This class is useful anywhere where a FIFO functionality
|
||||
/// is needed.
|
||||
@@ -167,17 +167,22 @@ public:
|
||||
return readLen;
|
||||
}
|
||||
|
||||
std::size_t write(const Buffer<T>& buffer)
|
||||
/// Writes data.size() to the FIFO buffer.
|
||||
std::size_t write(const Buffer<T>& buffer, std::size_t length = 0)
|
||||
/// Writes data from supplied buffer to the FIFO buffer.
|
||||
/// If there is no sufficient space for the whole
|
||||
/// buffer to be written, data up to available
|
||||
/// length is written.
|
||||
/// The length of data to be written is determined from the
|
||||
/// length argument or buffer size (when length argument is
|
||||
/// default zero or greater than buffer size).
|
||||
///
|
||||
/// Returns the length of data written.
|
||||
{
|
||||
Mutex::ScopedLock lock(_mutex);
|
||||
|
||||
if (_buffer.size() - (_begin + _used) < buffer.size())
|
||||
if (0 == length || length > buffer.size()) length = buffer.size();
|
||||
|
||||
if (_buffer.size() - (_begin + _used) < length)
|
||||
{
|
||||
std::memmove(_buffer.begin(), _buffer.begin() + _begin, _used);
|
||||
_begin = 0;
|
||||
@@ -185,7 +190,7 @@ public:
|
||||
|
||||
std::size_t usedBefore = _used;
|
||||
std::size_t available = _buffer.size() - _used - _begin;
|
||||
std::size_t len = buffer.size() > available ? available : buffer.size();
|
||||
std::size_t len = length > available ? available : length;
|
||||
std::memcpy(_buffer.begin() + _begin + _used, buffer.begin(), len * sizeof(T));
|
||||
_used += len;
|
||||
poco_assert (_used <= _buffer.size());
|
||||
@@ -212,6 +217,24 @@ public:
|
||||
return _buffer.size() - _used;
|
||||
}
|
||||
|
||||
void drain(std::size_t length = 0)
|
||||
/// Drains length number of elements from the buffer.
|
||||
/// If length is zero or greater than buffer current
|
||||
/// content length, buffer is emptied.
|
||||
{
|
||||
std::size_t usedBefore = _used;
|
||||
|
||||
if (0 == length || length >= _used)
|
||||
{
|
||||
_begin = 0;
|
||||
_used = 0;
|
||||
}
|
||||
else
|
||||
_used -= length;
|
||||
|
||||
if (_notify) notify(usedBefore);
|
||||
}
|
||||
|
||||
T& operator [] (std::size_t index)
|
||||
/// Returns value at index position.
|
||||
/// Throws InvalidAccessException if index is larger than
|
||||
@@ -234,6 +257,12 @@ public:
|
||||
return _buffer[_begin + index];
|
||||
}
|
||||
|
||||
const Buffer<T>& buffer() const
|
||||
/// Returns const reference to the underlying buffer.
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
/// Returns true is buffer is empty, flase otherwise.
|
||||
{
|
||||
|
||||
@@ -406,6 +406,83 @@ void CoreTest::testFIFOBufferChar()
|
||||
assert(1 == _writableToNot);
|
||||
assert (f.isEmpty());
|
||||
|
||||
f.resize(10);
|
||||
assert (10 == f.size());
|
||||
assert (0 == f.used());
|
||||
assert (10 == f.available());
|
||||
assert (f.isEmpty());
|
||||
|
||||
assert(3 == _notToReadable);
|
||||
assert(3 == _readableToNot);
|
||||
assert(1 == _notToWritable);
|
||||
assert(1 == _writableToNot);
|
||||
f.write(b);
|
||||
assert(4 == _notToReadable);
|
||||
assert(3 == _readableToNot);
|
||||
assert(1 == _notToWritable);
|
||||
assert(1 == _writableToNot);
|
||||
|
||||
assert (10 == f.size());
|
||||
assert (3 == f.used());
|
||||
assert (7 == f.available());
|
||||
assert (!f.isEmpty());
|
||||
|
||||
f.drain(1);
|
||||
assert(4 == _notToReadable);
|
||||
assert(3 == _readableToNot);
|
||||
assert(1 == _notToWritable);
|
||||
assert(1 == _writableToNot);
|
||||
|
||||
assert (10 == f.size());
|
||||
assert (2 == f.used());
|
||||
assert (8 == f.available());
|
||||
assert (!f.isEmpty());
|
||||
|
||||
f.drain(2);
|
||||
assert(4 == _notToReadable);
|
||||
assert(4 == _readableToNot);
|
||||
assert(1 == _notToWritable);
|
||||
assert(1 == _writableToNot);
|
||||
|
||||
assert (10 == f.size());
|
||||
assert (0 == f.used());
|
||||
assert (10 == f.available());
|
||||
assert (f.isEmpty());
|
||||
|
||||
f.write(b);
|
||||
assert(5 == _notToReadable);
|
||||
assert(4 == _readableToNot);
|
||||
assert(1 == _notToWritable);
|
||||
assert(1 == _writableToNot);
|
||||
|
||||
assert (10 == f.size());
|
||||
assert (3 == f.used());
|
||||
assert (7 == f.available());
|
||||
assert (!f.isEmpty());
|
||||
|
||||
f.drain();
|
||||
assert(5 == _notToReadable);
|
||||
assert(5 == _readableToNot);
|
||||
assert(1 == _notToWritable);
|
||||
assert(1 == _writableToNot);
|
||||
assert (10 == f.size());
|
||||
assert (0 == f.used());
|
||||
assert (10 == f.available());
|
||||
assert (f.isEmpty());
|
||||
|
||||
f.write(b, 2);
|
||||
assert (10 == f.size());
|
||||
assert (2 == f.used());
|
||||
assert (8 == f.available());
|
||||
assert (!f.isEmpty());
|
||||
|
||||
f.drain();
|
||||
assert (3 == f.write(b, 10));
|
||||
assert (10 == f.size());
|
||||
assert (3 == f.used());
|
||||
assert (7 == f.available());
|
||||
assert (!f.isEmpty());
|
||||
|
||||
f.Readable -= delegate(this, &CoreTest::onReadable);
|
||||
f.Writable -= delegate(this, &CoreTest::onReadable);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user