78 lines
2.1 KiB
C++
78 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include <array>
|
|
#include <optional>
|
|
#include <cstddef>
|
|
|
|
namespace netcode {
|
|
|
|
template<typename T, size_t Capacity>
|
|
class RingBuffer {
|
|
public:
|
|
void push(const T& item) {
|
|
data_[write_index_] = item;
|
|
write_index_ = (write_index_ + 1) % Capacity;
|
|
if (count_ < Capacity) {
|
|
count_++;
|
|
} else {
|
|
read_index_ = (read_index_ + 1) % Capacity;
|
|
}
|
|
}
|
|
|
|
std::optional<T> pop() {
|
|
if (count_ == 0) return std::nullopt;
|
|
|
|
T item = data_[read_index_];
|
|
read_index_ = (read_index_ + 1) % Capacity;
|
|
count_--;
|
|
return item;
|
|
}
|
|
|
|
const T* peek() const {
|
|
if (count_ == 0) return nullptr;
|
|
return &data_[read_index_];
|
|
}
|
|
|
|
const T* at(size_t index) const {
|
|
if (index >= count_) return nullptr;
|
|
size_t actual_index = (read_index_ + index) % Capacity;
|
|
return &data_[actual_index];
|
|
}
|
|
|
|
T* at(size_t index) {
|
|
if (index >= count_) return nullptr;
|
|
size_t actual_index = (read_index_ + index) % Capacity;
|
|
return &data_[actual_index];
|
|
}
|
|
|
|
// Доступ по sequence number (для команд)
|
|
template<typename SeqGetter>
|
|
const T* find_by_sequence(uint32_t seq, SeqGetter getter) const {
|
|
for (size_t i = 0; i < count_; ++i) {
|
|
const T* item = at(i);
|
|
if (item && getter(*item) == seq) {
|
|
return item;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void clear() {
|
|
read_index_ = 0;
|
|
write_index_ = 0;
|
|
count_ = 0;
|
|
}
|
|
|
|
size_t size() const { return count_; }
|
|
bool empty() const { return count_ == 0; }
|
|
bool full() const { return count_ == Capacity; }
|
|
static constexpr size_t capacity() { return Capacity; }
|
|
|
|
private:
|
|
std::array<T, Capacity> data_;
|
|
size_t read_index_ = 0;
|
|
size_t write_index_ = 0;
|
|
size_t count_ = 0;
|
|
};
|
|
|
|
} // namespace netcode
|