OXYGENHUB
◆ main openmsx / src / utils / CircularBuffer.hh
2.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef CIRCULARBUFFER_HH
2
#define CIRCULARBUFFER_HH
3
4
#include <array>
5
#include <cassert>
6
#include <cstddef>
7
#include <utility>
8
9
namespace openmsx {
10
11
template<typename T, size_t MAXSIZE>
12
class CircularBuffer
13
{
14
public:
15
	constexpr CircularBuffer() = default;
16
17
	constexpr void push_front(const T& element) {
18
		assert(!full());
19
		first = prev(first);
20
		buffer[first] = element;
21
	}
22
	constexpr void push_front(T&& element) {
23
		assert(!full());
24
		first = prev(first);
25
		buffer[first] = std::move(element);
26
	}
27
	constexpr void push_back(const T& element) {
28
		assert(!full());
29
		buffer[last] = element;
30
		last = next(last);
31
	}
32
	constexpr void push_back(T&& element) {
33
		assert(!full());
34
		buffer[last] = std::move(element);
35
		last = next(last);
36
	}
37
	constexpr T& pop_front() {
38
		assert(!empty());
39
		auto tmp = first;
40
		first = next(first);
41
		return buffer[tmp];
42
	}
43
	constexpr T& pop_back() {
44
		assert(!empty());
45
		last = prev(last);
46
		return buffer[last];
47
	}
48
49
	[[nodiscard]] constexpr T& operator[](size_t pos) {
50
		assert(pos < size());
51
		auto tmp = first + pos;
52
		if (tmp > MAXSIZE) {
53
			tmp -= (MAXSIZE + 1);
54
		}
55
		return buffer[tmp];
56
	}
57
	[[nodiscard]] constexpr const T& operator[](size_t pos) const {
58
		assert(pos < size());
59
		auto tmp = first + pos;
60
		if (tmp > MAXSIZE) {
61
			tmp -= (MAXSIZE + 1);
62
		}
63
		return buffer[tmp];
64
	}
65
66
	[[nodiscard]] constexpr T& front() {
67
		assert(!empty());
68
		return buffer[first];
69
	}
70
	[[nodiscard]] constexpr const T& front() const {
71
		assert(!empty());
72
		return buffer[first];
73
	}
74
75
	[[nodiscard]] constexpr T& back() {
76
		assert(!empty());
77
		return buffer[prev(last)];
78
	}
79
	[[nodiscard]] constexpr const T& back() const {
80
		assert(!empty());
81
		return buffer[prev(last)];
82
	}
83
84
	[[nodiscard]] constexpr bool empty() const {
85
		return (first == last);
86
	}
87
	[[nodiscard]] constexpr bool full() const {
88
		return (first == next(last));
89
	}
90
	[[nodiscard]] constexpr size_t size() const {
91
		if (first > last) {
92
			return MAXSIZE + 1 - first + last;
93
		} else {
94
			return last - first;
95
		}
96
	}
97
98
	void clear() {
99
		first = last = 0;
100
	}
101
102
private:
103
	[[nodiscard]] constexpr size_t next(size_t a) const {
104
		return (a != MAXSIZE) ? a + 1 : 0;
105
	}
106
	[[nodiscard]] constexpr size_t prev(size_t a) const {
107
		return (a != 0) ? a - 1 : MAXSIZE;
108
	}
109
110
	size_t first = 0;
111
	size_t last = 0;
112
	// one extra to be able to distinguish full and empty
113
	std::array<T, MAXSIZE + 1> buffer;
114
};
115
116
} // namespace openmsx
117
118
#endif