Files
Martin Slachta f4174eb0c7 #1 - quicr module
2026-08-01 22:43:09 +02:00

82 lines
2.1 KiB
C++

#pragma once
#include "common.hpp"
#include <optional>
#include <string>
#include <vector>
/**
* Stores history of a property for data analysis
*/
template<typename TKey, typename TValue>
class HistoryBuffer {
private:
size_t m_head, m_tail;
std::vector<std::pair<TKey, TValue>> m_buffer;
public:
size_t size() const {
if(m_tail > m_head) {
return max_size() - m_tail + m_head;
}
return (m_head - m_tail) % max_size();
}
size_t max_size() const { return m_buffer.size(); }
bool is_full(float percentage) {
return size() / (float)max_size() > percentage;
}
void clear() {
m_tail = m_head = 0;
}
GET_REF(m_buffer, buffer);
HistoryBuffer(TKey default_key, TValue&& default_value, size_t size) :
m_head(0), m_tail(0), m_buffer(size) {
}
std::optional<const TValue*> get(TKey key) const {
for(size_t i = m_tail; i != m_head; i = (i + 1) % max_size()) {
if(m_buffer[i].first > key) {
return {};
}
if(m_buffer[i].first == key) {
return &m_buffer[i].second;
}
}
return {};
}
bool set(TKey key, const TValue& value) {
// If buffer has entries and key is older than the oldest, reject it
if(m_tail != m_head && key < m_buffer.at(m_tail).first) {
return false;
}
size_t i = (m_tail + 1) % max_size();
if(m_tail != m_head) {
for(i = (m_tail + 1) % max_size(); i != m_head; i = (i + 1) % max_size()) {
if(m_buffer.at(i).first > key) {
m_buffer[(i - 1 + max_size()) % max_size()] = std::make_pair(key, value);
m_head = (m_head + 1) % max_size();
return true;
} else {
m_buffer[(i - 1 + max_size()) % max_size()] = m_buffer[i];
}
}
}
m_buffer[(i - 1 + max_size()) % max_size()] = std::make_pair(key, value);
m_head = (m_head + 1) % max_size();
return true;
}
};