blob: c42dea8e8c6cb6ec5013b0c880f0257447c275ce [file] [log] [blame]
Brian Silverman1a675112016-02-20 20:42:49 -05001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2015-2016. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include <algorithm>
9
10template <class T>
11CircularBuffer<T>::CircularBuffer(size_t size) : m_data(size, 0) {}
12
13/**
14 * Push new value onto front of the buffer. The value at the back is overwritten
15 * if the buffer is full.
16 */
17template <class T>
18void CircularBuffer<T>::PushFront(T value) {
19 if (m_data.size() == 0) {
20 return;
21 }
22
23 m_front = ModuloDec(m_front);
24
25 m_data[m_front] = value;
26
27 if (m_length < m_data.size()) {
28 m_length++;
29 }
30}
31
32/**
33 * Push new value onto back of the buffer. The value at the front is overwritten
34 * if the buffer is full.
35 */
36template <class T>
37void CircularBuffer<T>::PushBack(T value) {
38 if (m_data.size() == 0) {
39 return;
40 }
41
42 m_data[(m_front + m_length) % m_data.size()] = value;
43
44 if (m_length < m_data.size()) {
45 m_length++;
46 } else {
47 // Increment front if buffer is full to maintain size
48 m_front = ModuloInc(m_front);
49 }
50}
51
52/**
53 * Pop value at front of buffer.
54 */
55template <class T>
56T CircularBuffer<T>::PopFront() {
57 // If there are no elements in the buffer, do nothing
58 if (m_length == 0) {
59 return 0;
60 }
61
62 T& temp = m_data[m_front];
63 m_front = ModuloInc(m_front);
64 m_length--;
65 return temp;
66}
67
68/**
69 * Pop value at back of buffer.
70 */
71template <class T>
72T CircularBuffer<T>::PopBack() {
73 // If there are no elements in the buffer, do nothing
74 if (m_length == 0) {
75 return 0;
76 }
77
78 m_length--;
79 return m_data[(m_front + m_length) % m_data.size()];
80}
81
82template <class T>
83void CircularBuffer<T>::Reset() {
84 std::fill(m_data.begin(), m_data.end(), 0);
85 m_front = 0;
86 m_length = 0;
87}
88
89/**
90 * Returns element at index starting from front of buffer.
91 */
92template <class T>
93T& CircularBuffer<T>::operator[](size_t index) {
94 return m_data[(m_front + index) % m_data.size()];
95}
96
97/**
98 * Returns element at index starting from front of buffer.
99 */
100template <class T>
101const T& CircularBuffer<T>::operator[](size_t index) const {
102 return m_data[(m_front + index) % m_data.size()];
103}
104
105/**
106 * Increment an index modulo the length of the m_data buffer
107 */
108template <class T>
109size_t CircularBuffer<T>::ModuloInc(size_t index) {
110 return (index + 1) % m_data.size();
111}
112
113/**
114 * Decrement an index modulo the length of the m_data buffer
115 */
116template <class T>
117size_t CircularBuffer<T>::ModuloDec(size_t index) {
118 if (index == 0) {
119 return m_data.size() - 1;
120 } else {
121 return index - 1;
122 }
123}