/************************************************************************* * * Copyright 2019 Realm Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **************************************************************************/ #ifndef REALM_UTIL_FIXED_SIZE_BUFFER_HPP #define REALM_UTIL_FIXED_SIZE_BUFFER_HPP #include <vector> #include <cstddef> #include <stdexcept> namespace realm { namespace util { /// This is a buffer with a fixed size. You can only insert elements. /// When the number of elements inserted matches the size of the buffer, /// additional insertions will overwrite the oldest elements. template <class T> class FixedSizeBuffer { public: class iterator; FixedSizeBuffer(size_t sz) : m_size(sz) { if (sz == 0) throw std::runtime_error("FixedSizeBuffer size cannot be 0"); m_buffer.reserve(sz); } size_t size() { return m_buffer.size(); } void insert(const T& val) { if (m_buffer.size() < m_size) { m_buffer.emplace_back(val); } else { m_buffer[m_oldest] = val; ++m_oldest; if (m_oldest == m_size) m_oldest = 0; } } T& at(size_t n) { auto idx = (n + m_oldest) % m_size; return m_buffer[idx]; } T& operator[](size_t n) { return at(n); } iterator begin() { return iterator(*this, 0); } iterator end() { return iterator(*this, m_buffer.size()); } private: std::vector<T> m_buffer; size_t m_size; size_t m_oldest = 0; }; template <class T> class FixedSizeBuffer<T>::iterator { public: typedef std::forward_iterator_tag iterator_category; typedef T value_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; iterator(FixedSizeBuffer<T>& b, size_t ndx) : m_cb(b) , m_ndx(ndx) { } pointer operator->() { return &m_cb[m_ndx]; } reference operator*() { return m_cb[m_ndx]; } iterator& operator++() { ++m_ndx; return *this; } iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; } bool operator!=(const iterator& rhs) const { return m_ndx != rhs.m_ndx; } bool operator==(const iterator& rhs) const { return m_ndx == rhs.m_ndx; } private: FixedSizeBuffer<T>& m_cb; size_t m_ndx; }; } // namespace util } // namespace realm #endif /* REALM_UTIL_FIXED_SIZE_BUFFER_HPP */