355 lines
5.9 KiB
C++
355 lines
5.9 KiB
C++
#pragma once
|
|
|
|
#include <ostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
template <typename T>
|
|
struct CyclicVector
|
|
{
|
|
std::vector<T> vector;
|
|
size_t offset{0};
|
|
|
|
CyclicVector(const std::initializer_list<T>& vector)
|
|
: vector{vector}
|
|
{
|
|
}
|
|
|
|
CyclicVector(const std::vector<T>& vector)
|
|
: vector{vector}
|
|
{
|
|
}
|
|
|
|
template <typename U = T, typename = std::enable_if_t<std::is_same_v<U, char>>>
|
|
CyclicVector(const std::string& str)
|
|
: vector{str.begin(), str.end()}
|
|
{
|
|
}
|
|
|
|
template <std::size_t N, typename U = T, typename = std::enable_if_t<std::is_same_v<U, char>>>
|
|
CyclicVector(const char (&str)[N])
|
|
{
|
|
vector.resize(N - 1); // don't include \0 character
|
|
for (size_t i = 0; i < N - 1; i++)
|
|
{
|
|
vector[i] = str[i];
|
|
}
|
|
}
|
|
|
|
void Rotate(int i)
|
|
{
|
|
if (i < 0)
|
|
RotateLeft(-i);
|
|
else
|
|
RotateRight(i);
|
|
}
|
|
|
|
void RotateRight(int i)
|
|
{
|
|
offset = (offset + vector.size() - (i % vector.size())) % vector.size();
|
|
}
|
|
|
|
void RotateLeft(size_t i)
|
|
{
|
|
offset = (offset + i) % vector.size();
|
|
}
|
|
|
|
T& operator[](size_t i)
|
|
{
|
|
return vector[(i + offset) % vector.size()];
|
|
}
|
|
|
|
const T& operator[](size_t i) const
|
|
{
|
|
return vector[(i + offset) % vector.size()];
|
|
}
|
|
|
|
size_t size() const
|
|
{
|
|
return vector.size();
|
|
}
|
|
|
|
bool empty() const
|
|
{
|
|
return vector.empty();
|
|
}
|
|
|
|
size_t Find(const T& t) const
|
|
{
|
|
return std::find(begin(), end(), t).GetPos();
|
|
}
|
|
|
|
struct iterator;
|
|
struct const_iterator;
|
|
|
|
iterator begin()
|
|
{
|
|
return iterator{*this, 0};
|
|
}
|
|
|
|
iterator end()
|
|
{
|
|
return iterator{*this, vector.size()};
|
|
}
|
|
|
|
const_iterator begin() const
|
|
{
|
|
return const_iterator{*this, 0};
|
|
}
|
|
|
|
const_iterator end() const
|
|
{
|
|
return const_iterator{*this, vector.size()};
|
|
}
|
|
|
|
const_iterator cbegin() const
|
|
{
|
|
return const_iterator{*this, 0};
|
|
}
|
|
|
|
const_iterator cend() const
|
|
{
|
|
return const_iterator{*this, vector.size()};
|
|
}
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, const CyclicVector& vector)
|
|
{
|
|
os << "[";
|
|
if (!vector.empty())
|
|
os << vector[0];
|
|
|
|
for (auto it = vector.cbegin() + 1; it != vector.cend(); it++)
|
|
{
|
|
os << ", " << *it;
|
|
}
|
|
os << "]";
|
|
return os;
|
|
}
|
|
|
|
class iterator
|
|
{
|
|
private:
|
|
CyclicVector<T>& data;
|
|
size_t pos;
|
|
|
|
public:
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
using value_type = T;
|
|
using difference_type = int;
|
|
using pointer = T*;
|
|
using reference = T&;
|
|
|
|
iterator(CyclicVector<T>& data, size_t pos)
|
|
: data{data},
|
|
pos{pos}
|
|
{
|
|
}
|
|
|
|
size_t GetPos() const
|
|
{
|
|
return pos;
|
|
}
|
|
|
|
reference operator*() const
|
|
{
|
|
return data[pos];
|
|
}
|
|
|
|
pointer operator->() const
|
|
{
|
|
return &data[pos];
|
|
}
|
|
|
|
iterator& operator++()
|
|
{
|
|
++pos;
|
|
return *this;
|
|
}
|
|
|
|
iterator operator++(int)
|
|
{
|
|
iterator ret = *this;
|
|
++(*this);
|
|
return ret;
|
|
}
|
|
|
|
iterator& operator--()
|
|
{
|
|
--pos;
|
|
return *this;
|
|
}
|
|
|
|
iterator operator--(int)
|
|
{
|
|
iterator ret = *this;
|
|
--(*this);
|
|
return ret;
|
|
}
|
|
|
|
iterator& operator+=(size_t advance)
|
|
{
|
|
if (std::numeric_limits<size_t>::max() - pos < advance)
|
|
{
|
|
pos = data.size();
|
|
}
|
|
else
|
|
{
|
|
pos += advance;
|
|
if (pos >= data.size())
|
|
pos = data.size();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
iterator& operator-=(size_t advance)
|
|
{
|
|
if (advance > pos)
|
|
{
|
|
pos = data.size();
|
|
}
|
|
else
|
|
{
|
|
pos -= advance;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
iterator operator+(size_t advance) const
|
|
{
|
|
iterator ret = *this;
|
|
ret += advance;
|
|
return ret;
|
|
}
|
|
|
|
iterator operator-(size_t advance) const
|
|
{
|
|
iterator ret = *this;
|
|
ret -= advance;
|
|
return ret;
|
|
}
|
|
|
|
bool operator==(const iterator& other) const
|
|
{
|
|
return pos == other.pos;
|
|
}
|
|
|
|
bool operator!=(const iterator& other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
};
|
|
|
|
class const_iterator
|
|
{
|
|
private:
|
|
const CyclicVector<T>& data;
|
|
size_t pos;
|
|
|
|
public:
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
using value_type = T;
|
|
using difference_type = int;
|
|
using pointer = const T*;
|
|
using reference = const T&;
|
|
|
|
const_iterator(const CyclicVector<T>& data, size_t pos)
|
|
: data{data},
|
|
pos{pos}
|
|
{
|
|
}
|
|
|
|
size_t GetPos() const
|
|
{
|
|
return pos;
|
|
}
|
|
|
|
reference operator*() const
|
|
{
|
|
return data[pos];
|
|
}
|
|
|
|
pointer operator->() const
|
|
{
|
|
return &data[pos];
|
|
}
|
|
|
|
const_iterator& operator++()
|
|
{
|
|
++pos;
|
|
return *this;
|
|
}
|
|
|
|
const_iterator operator++(int)
|
|
{
|
|
const_iterator ret = *this;
|
|
++(*this);
|
|
return ret;
|
|
}
|
|
|
|
const_iterator& operator--()
|
|
{
|
|
--pos;
|
|
return *this;
|
|
}
|
|
|
|
const_iterator operator--(int)
|
|
{
|
|
const_iterator ret = *this;
|
|
--(*this);
|
|
return ret;
|
|
}
|
|
|
|
const_iterator& operator+=(size_t advance)
|
|
{
|
|
if (std::numeric_limits<size_t>::max() - pos < advance)
|
|
{
|
|
pos = data.size();
|
|
}
|
|
else
|
|
{
|
|
pos += advance;
|
|
if (pos >= data.size())
|
|
pos = data.size();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
const_iterator& operator-=(size_t advance)
|
|
{
|
|
if (advance > pos)
|
|
{
|
|
pos = data.size();
|
|
}
|
|
else
|
|
{
|
|
pos -= advance;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
const_iterator operator+(size_t advance) const
|
|
{
|
|
const_iterator ret = *this;
|
|
ret += advance;
|
|
return ret;
|
|
}
|
|
|
|
const_iterator operator-(size_t advance) const
|
|
{
|
|
const_iterator ret = *this;
|
|
ret -= advance;
|
|
return ret;
|
|
}
|
|
|
|
bool operator==(const const_iterator& other) const
|
|
{
|
|
return pos == other.pos;
|
|
}
|
|
|
|
bool operator!=(const const_iterator& other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
};
|
|
};
|