19#include <fmt/ostream.h>
20#include <fmt/ranges.h>
30template<
class T,
size_t _Padding = 0>
43 _data.reserve(maxSize + _Padding);
44 _data.resize(_Padding);
52 _data.reserve(init.size());
54 for (
auto& val : init)
70 requires(!std::is_same_v<T, bool>)
73 return const_cast<T&
>(
static_cast<const ScrollingBuffer&
>(*this).at(pos));
81 [[nodiscard]]
auto at(
size_t pos)
const
82 -> std::conditional_t<std::is_same_v<T, bool>, bool,
const T&>
86 throw std::out_of_range(
"ScrollingBuffer::at: pos (which is "
87 + std::to_string(pos) +
") >= this->size() (which is " + std::to_string(
size()) +
")");
107 requires(!std::is_same_v<T, bool>)
110 return const_cast<T&
>(
static_cast<const ScrollingBuffer&
>(*this).front());
118 ->
std::conditional_t<
std::is_same_v<T,
bool>,
bool, const T&>
128 requires(!std::is_same_v<T, bool>)
130 return const_cast<T&
>(
static_cast<const ScrollingBuffer&
>(*this).back());
137 [[nodiscard]]
auto back() const
138 ->
std::conditional_t<
std::is_same_v<T,
bool>,
bool, const T&>
306 if (
index < 0) {
return *
this; }
369 if (
index < 0) {
return *
this; }
429 [[nodiscard]]
bool full()
const
435 [[nodiscard]]
size_t size()
const
439 return _data.size() - _Padding;
454 _data.reserve(new_cap);
474 for (
size_t i = 0; i < _Padding; i++)
486 _data.push_back(value);
491 _data.push_back(value);
532 if constexpr (!std::is_same_v<T, bool>)
560 if constexpr (!std::is_same_v<T, bool>)
581 std::vector<T> to_vector;
586 std::back_inserter(to_vector));
590 std::copy(std::next(
_data.begin(), std::max(
static_cast<int>(
_dataStart - _Padding), 0)),
592 std::back_inserter(to_vector));
594 if (int64_t elementsFront = std::min(
static_cast<int64_t
>(
_dataEnd),
static_cast<int64_t
>(
_dataStart - _Padding));
597 std::copy(
_data.begin(), std::next(
_data.begin(), elementsFront),
598 std::back_inserter(to_vector));
600 _data.swap(to_vector);
612 if (
_maxSize - _Padding > targetSize)
616 size_t elementsToDelete =
_maxSize - _Padding - targetSize;
619 size_t emptyAtTheBackToDelete = std::min(emptyAtTheBack, elementsToDelete))
625 elementsToDelete -= emptyAtTheBackToDelete;
631 if (elementsToDelete)
634 std::next(
_data.begin(),
static_cast<int64_t
>(
_dataStart + elementsToDelete)));
649 size_t elementsToDelete =
_maxSize - _Padding - targetSize;
651 if (
size_t emptyInBetween =
static_cast<size_t>(std::max(
static_cast<int>(
_dataStart - _Padding -
_dataEnd), 0));
652 size_t emptyInBetweenToDelete = std::min(emptyInBetween, elementsToDelete))
656 std::next(
_data.begin(),
static_cast<int64_t
>(
_dataEnd + emptyInBetweenToDelete)));
660 elementsToDelete -= emptyInBetweenToDelete;
666 if (
size_t paddingAtTheEnd =
static_cast<size_t>(std::max(
static_cast<int>(_Padding -
_dataStart), 0));
667 size_t paddingAtTheEndToDelete = std::min(paddingAtTheEnd, elementsToDelete))
670 std::next(
_data.begin(),
static_cast<int64_t
>(
_dataEnd + paddingAtTheEndToDelete)));
671 _maxSize -= paddingAtTheEndToDelete;
674 elementsToDelete -= paddingAtTheEndToDelete;
681 size_t elementsAtTheBackToDelete = std::min(elementsAtTheBack, elementsToDelete))
685 std::next(
_data.begin(),
static_cast<int64_t
>(
_dataStart - _Padding + elementsAtTheBackToDelete)));
688 _maxSize -= elementsAtTheBackToDelete;
695 elementsToDelete -= elementsAtTheBackToDelete;
697 if (elementsToDelete)
711 else if (
_maxSize - _Padding < targetSize)
734 _data.resize(targetSize + _Padding);
736 auto copy_backward = [](
auto first,
auto last,
auto d_last) {
737 while (first != last)
739 *(--d_last) = *(--last);
743 copy_backward(std::next(
_data.begin(),
static_cast<int64_t
>(
_dataEnd)),
745 std::next(
_data.begin(),
static_cast<int64_t
>(targetSize + _Padding)));
747 auto diff = targetSize + _Padding -
_maxSize;
764 [[nodiscard]] T
max()
const
766 T currentMax =
front();
767 for (
size_t i = 0; i <
_data.size(); i++)
771 currentMax = std::max(currentMax,
_data.at(i));
778 [[nodiscard]] T
min()
const
780 T currentMin =
front();
781 for (
size_t i = 0; i <
_data.size(); i++)
785 currentMin = std::min(currentMin,
_data.at(i));
798 [[nodiscard]]
const T*
data()
const
846 for (
int i = 0;
static_cast<size_t>(i) <
_maxSize; i++)
854 static_cast<size_t>(i) >=
_data.size()
855 || (scrolled &&
static_cast<size_t>(i) >=
_dataEnd && (
static_cast<int>(
_dataStart - _Padding) < 0 || i <
static_cast<int>(
_dataStart - _Padding)))
857 || (
_data.size() > 1 && !scrolled &&
static_cast<size_t>(i) >=
_dataEnd))
863 out += std::to_string(
_data.at(
static_cast<size_t>(i)));
865 if (
static_cast<size_t>(i) !=
_maxSize - 1)
879 os << fmt::format(
"{}", fmt::join(buffer,
", "));
899 if (
_data.size() == 1) {
return false; }
925#ifndef DOXYGEN_IGNORE
927template<
class T,
size_t _Padding>
928struct fmt::formatter<
NAV::ScrollingBuffer<T, _Padding>> : ostream_formatter