19#include <fmt/ostream.h>
27template<
class T,
size_t _Padding = 0>
40 _data.reserve(maxSize + _Padding);
41 _data.resize(_Padding);
49 _data.reserve(init.size());
51 for (
auto& val : init)
75 [[nodiscard]]
const T&
at(
size_t pos)
const
79 throw std::out_of_range(
"ScrollingBuffer::at: pos (which is "
80 + std::to_string(pos) +
") >= this->size() (which is " + std::to_string(
size()) +
")");
107 [[nodiscard]]
const T&
front()
const
123 [[nodiscard]]
const T&
back()
const
291 if (
index < 0) {
return *
this; }
354 if (
index < 0) {
return *
this; }
414 [[nodiscard]]
bool full()
const
420 [[nodiscard]]
size_t size()
const
424 return _data.size() - _Padding;
439 _data.reserve(new_cap);
459 for (
size_t i = 0; i < _Padding; i++)
471 _data.push_back(value);
476 _data.push_back(value);
533 std::vector<T> to_vector;
538 std::back_inserter(to_vector));
542 std::copy(std::next(
_data.begin(), std::max(
static_cast<int>(
_dataStart - _Padding), 0)),
544 std::back_inserter(to_vector));
546 if (int64_t elementsFront = std::min(
static_cast<int64_t
>(
_dataEnd),
static_cast<int64_t
>(
_dataStart - _Padding));
549 std::copy(
_data.begin(), std::next(
_data.begin(), elementsFront),
550 std::back_inserter(to_vector));
552 _data.swap(to_vector);
564 if (
_maxSize - _Padding > targetSize)
568 size_t elementsToDelete =
_maxSize - _Padding - targetSize;
571 size_t emptyAtTheBackToDelete = std::min(emptyAtTheBack, elementsToDelete))
577 elementsToDelete -= emptyAtTheBackToDelete;
583 if (elementsToDelete)
586 std::next(
_data.begin(),
static_cast<int64_t
>(
_dataStart + elementsToDelete)));
601 size_t elementsToDelete =
_maxSize - _Padding - targetSize;
603 if (
size_t emptyInBetween =
static_cast<size_t>(std::max(
static_cast<int>(
_dataStart - _Padding -
_dataEnd), 0));
604 size_t emptyInBetweenToDelete = std::min(emptyInBetween, elementsToDelete))
608 std::next(
_data.begin(),
static_cast<int64_t
>(
_dataEnd + emptyInBetweenToDelete)));
612 elementsToDelete -= emptyInBetweenToDelete;
618 if (
size_t paddingAtTheEnd =
static_cast<size_t>(std::max(
static_cast<int>(_Padding -
_dataStart), 0));
619 size_t paddingAtTheEndToDelete = std::min(paddingAtTheEnd, elementsToDelete))
622 std::next(
_data.begin(),
static_cast<int64_t
>(
_dataEnd + paddingAtTheEndToDelete)));
623 _maxSize -= paddingAtTheEndToDelete;
626 elementsToDelete -= paddingAtTheEndToDelete;
633 size_t elementsAtTheBackToDelete = std::min(elementsAtTheBack, elementsToDelete))
637 std::next(
_data.begin(),
static_cast<int64_t
>(
_dataStart - _Padding + elementsAtTheBackToDelete)));
640 _maxSize -= elementsAtTheBackToDelete;
647 elementsToDelete -= elementsAtTheBackToDelete;
649 if (elementsToDelete)
663 else if (
_maxSize - _Padding < targetSize)
677 _data.resize(targetSize + _Padding);
679 auto copy_backward = [](
auto first,
auto last,
auto d_last) {
680 while (first != last)
682 *(--d_last) = *(--last);
686 copy_backward(std::next(
_data.begin(),
static_cast<int64_t
>(
_dataEnd)),
688 std::next(
_data.begin(),
static_cast<int64_t
>(targetSize + _Padding)));
690 auto diff = targetSize + _Padding -
_maxSize;
707 [[nodiscard]] T
max()
const
709 T currentMax =
front();
710 for (
size_t i = 0; i <
_data.size(); i++)
714 currentMax = std::max(currentMax,
_data.at(i));
721 [[nodiscard]] T
min()
const
723 T currentMin =
front();
724 for (
size_t i = 0; i <
_data.size(); i++)
728 currentMin = std::min(currentMin,
_data.at(i));
741 [[nodiscard]]
const T*
data()
const
789 for (
int i = 0;
static_cast<size_t>(i) <
_maxSize; i++)
797 (scrolled &&
static_cast<size_t>(i) >=
_dataEnd && (
static_cast<int>(
_dataStart - _Padding) < 0 || i < static_cast<int>(
_dataStart - _Padding)))
799 || (!scrolled &&
static_cast<size_t>(i) >=
_dataEnd))
805 out += std::to_string(
_data.at(
static_cast<size_t>(i)));
807 if (
static_cast<size_t>(i) !=
_maxSize - 1)
821 os << fmt::format(
"{}", fmt::join(buffer,
", "));
865#ifndef DOXYGEN_IGNORE
867template<
class T,
size_t _Padding>
868struct fmt::formatter<NAV::ScrollingBuffer<T, _Padding>> : ostream_formatter