// copied from llama-impl.h template struct RingBuffer { RingBuffer(size_t cap) : capacity(cap), data(cap) {} T & front() { if (sz == 0) { throw std::runtime_error("ring buffer is empty"); } return data[first]; } const T & front() const { if (sz == 0) { throw std::runtime_error("ring buffer is empty"); } return data[first]; } T & back() { if (sz == 0) { throw std::runtime_error("ring buffer is empty"); } return data[pos]; } const T & back() const { if (sz == 0) { throw std::runtime_error("ring buffer is empty"); } return data[pos]; } void push_back(const T & value) { if (capacity == 0) { throw std::runtime_error("ring buffer: capacity is zero"); } if (sz == capacity) { // advance the start when buffer is full first = (first + 1) % capacity; } else { sz++; } data[pos] = value; pos = (pos + 1) % capacity; } T pop_front() { if (sz == 0) { throw std::runtime_error("ring buffer is empty"); } T value = data[first]; first = (first + 1) % capacity; sz--; return value; } //T & operator[](size_t i) { // if (i >= sz) { // throw std::runtime_error("ring buffer: index out of bounds"); // } // return data[(first + i) % capacity]; //} //const T & at(size_t i) const { // if (i >= sz) { // throw std::runtime_error("ring buffer: index out of bounds"); // } // return data[(first + i) % capacity]; //} const T & rat(size_t i) const { if (i >= sz) { throw std::runtime_error("ring buffer: index out of bounds"); } return data[(first + sz - i - 1) % capacity]; } std::vector to_vector() const { std::vector result; result.reserve(sz); for (size_t i = 0; i < sz; i++) { result.push_back(data[(first + i) % capacity]); } return result; } void clear() { // here only reset the status of the buffer sz = 0; first = 0; pos = 0; } bool empty() const { return sz == 0; } size_t size() const { return sz; } size_t capacity = 0; size_t sz = 0; size_t first = 0; size_t pos = 0; std::vector data; };