util/ForeignFifoBuffer: store buffer as std::span

This commit is contained in:
Max Kellermann 2024-11-08 19:44:52 +01:00 committed by Max Kellermann
parent 8a3b48754e
commit c9c5e84119
1 changed files with 28 additions and 34 deletions

View File

@ -27,37 +27,34 @@ public:
using const_pointer = typename Range::const_pointer; using const_pointer = typename Range::const_pointer;
protected: protected:
size_type head = 0, tail = 0, capacity; Range buffer;
T *data; size_type head = 0, tail = 0;
public: public:
explicit constexpr ForeignFifoBuffer(std::nullptr_t n) noexcept explicit constexpr ForeignFifoBuffer(std::nullptr_t) noexcept
:capacity(0), data(n) {} :buffer() {}
constexpr ForeignFifoBuffer(T *_data, size_type _capacity) noexcept constexpr ForeignFifoBuffer(T *_data, size_type _capacity) noexcept
:capacity(_capacity), data(_data) {} :buffer(_data, _capacity) {}
constexpr ForeignFifoBuffer(ForeignFifoBuffer &&src) noexcept constexpr ForeignFifoBuffer(ForeignFifoBuffer &&src) noexcept
:head(src.head), tail(src.tail), :buffer(src.buffer), head(src.head), tail(src.tail) {
capacity(src.capacity), data(src.data) {
src.SetNull(); src.SetNull();
} }
constexpr ForeignFifoBuffer &operator=(ForeignFifoBuffer &&src) noexcept { constexpr ForeignFifoBuffer &operator=(ForeignFifoBuffer &&src) noexcept {
buffer = src.buffer;
head = src.head; head = src.head;
tail = src.tail; tail = src.tail;
capacity = src.capacity;
data = src.data;
src.SetNull(); src.SetNull();
return *this; return *this;
} }
constexpr void swap(ForeignFifoBuffer<T> &other) noexcept { constexpr void swap(ForeignFifoBuffer<T> &other) noexcept {
using std::swap; using std::swap;
swap(buffer, other.buffer);
swap(head, other.head); swap(head, other.head);
swap(tail, other.tail); swap(tail, other.tail);
swap(capacity, other.capacity);
swap(data, other.data);
} }
friend constexpr void swap(ForeignFifoBuffer<T> &a, friend constexpr void swap(ForeignFifoBuffer<T> &a,
@ -66,7 +63,7 @@ public:
} }
constexpr bool IsNull() const noexcept { constexpr bool IsNull() const noexcept {
return data == nullptr; return buffer.data() == nullptr;
} }
constexpr bool IsDefined() const noexcept { constexpr bool IsDefined() const noexcept {
@ -74,26 +71,24 @@ public:
} }
T *GetBuffer() noexcept { T *GetBuffer() noexcept {
return data; return buffer.data();
} }
constexpr size_type GetCapacity() const noexcept { constexpr size_type GetCapacity() const noexcept {
return capacity; return buffer.size();
} }
void SetNull() noexcept { void SetNull() noexcept {
buffer = {};
head = tail = 0; head = tail = 0;
capacity = 0;
data = nullptr;
} }
void SetBuffer(T *_data, size_type _capacity) noexcept { void SetBuffer(T *_data, size_type _capacity) noexcept {
assert(_data != nullptr); assert(_data != nullptr);
assert(_capacity > 0); assert(_capacity > 0);
buffer = {_data, _capacity};
head = tail = 0; head = tail = 0;
capacity = _capacity;
data = _data;
} }
void MoveBuffer(T *new_data, size_type new_capacity) noexcept { void MoveBuffer(T *new_data, size_type new_capacity) noexcept {
@ -101,8 +96,7 @@ public:
assert(new_capacity >= r.size()); assert(new_capacity >= r.size());
std::move(r.begin(), r.end(), new_data); std::move(r.begin(), r.end(), new_data);
data = new_data; buffer = {new_data, new_capacity};
capacity = new_capacity;
tail -= head; tail -= head;
head = 0; head = 0;
} }
@ -116,7 +110,7 @@ public:
} }
constexpr bool IsFull() const noexcept { constexpr bool IsFull() const noexcept {
return head == 0 && tail == capacity; return head == 0 && tail == buffer.size();
} }
/** /**
@ -126,24 +120,24 @@ public:
constexpr Range Write() noexcept { constexpr Range Write() noexcept {
if (empty()) if (empty())
Clear(); Clear();
else if (tail == capacity) else if (tail == buffer.size())
Shift(); Shift();
return Range(data + tail, capacity - tail); return buffer.subspan(tail);
} }
constexpr bool WantWrite(size_type n) noexcept { constexpr bool WantWrite(size_type n) noexcept {
if (tail + n <= capacity) if (tail + n <= buffer.size())
/* enough space after the tail */ /* enough space after the tail */
return true; return true;
const size_type in_use = tail - head; const size_type in_use = tail - head;
const size_type required_capacity = in_use + n; const size_type required_capacity = in_use + n;
if (required_capacity > capacity) if (required_capacity > buffer.size())
return false; return false;
Shift(); Shift();
assert(tail + n <= capacity); assert(tail + n <= buffer.size());
return true; return true;
} }
@ -152,9 +146,9 @@ public:
* the buffer returned by Write(). * the buffer returned by Write().
*/ */
constexpr void Append(size_type n) noexcept { constexpr void Append(size_type n) noexcept {
assert(tail <= capacity); assert(tail <= buffer.size());
assert(n <= capacity); assert(n <= buffer.size());
assert(tail + n <= capacity); assert(tail + n <= buffer.size());
tail += n; tail += n;
} }
@ -168,14 +162,14 @@ public:
* writable, to allow modifications while parsing. * writable, to allow modifications while parsing.
*/ */
constexpr Range Read() const noexcept { constexpr Range Read() const noexcept {
return Range(data + head, tail - head); return buffer.subspan(head, tail - head);
} }
/** /**
* Marks a chunk as consumed. * Marks a chunk as consumed.
*/ */
constexpr void Consume(size_type n) noexcept { constexpr void Consume(size_type n) noexcept {
assert(tail <= capacity); assert(tail <= buffer.size());
assert(head <= tail); assert(head <= tail);
assert(n <= tail); assert(n <= tail);
assert(head + n <= tail); assert(head + n <= tail);
@ -228,12 +222,12 @@ protected:
if (head == 0) if (head == 0)
return; return;
assert(head <= capacity); assert(head <= buffer.size());
assert(tail <= capacity); assert(tail <= buffer.size());
assert(tail >= head); assert(tail >= head);
const auto r = Read(); const auto r = Read();
std::move(r.begin(), r.end(), data); std::move(r.begin(), r.end(), buffer.begin());
tail -= head; tail -= head;
head = 0; head = 0;