Arduino MIDI File Parser
RingBuffer.h
1 #pragma once
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <assert.h>
6 
7 #define PEEK_MAX 80
8 
9 namespace midi {
10 
16 class RingBuffer {
17 public:
18  RingBuffer() = default;
19 
21  _aucBuffer = nullptr;
22  reset();
23  }
24 
25  RingBuffer(int size) {
26  resize(size);
27  reset();
28  }
29 
30  ~RingBuffer() { if (_aucBuffer!=nullptr)delete[] _aucBuffer; }
31 
32  uint8_t read() {
33  if (isEmpty())
34  return -1;
35 
36  uint8_t value = _aucBuffer[_iTail];
37  _iTail = nextIndex(_iTail);
38  _numElems--;
39 
40  return value;
41  }
42 
43  // checks if the buffer is full
44  bool isFull() { return available() == max_size; }
45 
46  bool isEmpty() { return available() == 0; }
47 
48  // write add an entry to the buffer
49  bool write(uint8_t data) {
50  bool result = false;
51  if (!isFull()) {
52  _aucBuffer[_iHead] = data;
53  _iHead = nextIndex(_iHead);
54  _numElems++;
55  result = true;
56  }
57  return result;
58  }
59 
60  int write(const uint8_t *data, size_t len) {
61  for (int j = 0; j < len; j++) {
62  if (!write(data[j])) {
63  return j;
64  }
65  }
66  return len;
67  }
68 
69  // clears the buffer
70  void reset() {
71  _iHead = 0;
72  _iTail = 0;
73  _numElems = 0;
74  }
75 
76  // provides the number of entries that are available to read
77  int available() { return _numElems; }
78 
79  // provides the number of entries that are available to write
80  int availableForWrite() { return (max_size - _numElems); }
81 
82  void resize(int len) {
83  // if no change: we can leave
84  if (this->max_size==len && _aucBuffer!=nullptr){
85  return;
86  }
87  // (re)allocate buffer
88  if (_aucBuffer != nullptr) {
89  delete[] _aucBuffer;
90  }
91  this->max_size = len;
92  if (len > 0) {
93  _aucBuffer = new uint8_t[max_size];
94  assert(_aucBuffer != nullptr);
95  }
96  reset();
97  }
98 
100  int size() { return max_size; }
101 
102  // peeks the actual entry from the buffer
103  int peek() {
104  if (isEmpty())
105  return -1;
106 
107  return _aucBuffer[_iTail];
108  }
109 
111  int peek(int idx) {
112  if (idx > available())
113  return -1;
114  int tmp_tail = (_iTail + idx) % max_size;
115  return _aucBuffer[tmp_tail];
116  }
117 
119  uint8_t *peekStr(int idx, int len) {
120  if (len==0) return 0;
121  static uint8_t tmp_copy[PEEK_MAX];
122  assert(len < PEEK_MAX);
123  assert(idx+len<available());
124  memset(&tmp_copy, 0, PEEK_MAX);
125  for (int j = 0; j < len; j++) {
126  tmp_copy[j] = peek(idx + j);
127  }
128  return tmp_copy;
129  }
130 
132  uint8_t operator[](int idx) {
133  int result = peek(idx);
134  assert(result!=-1);
135  return result;
136  }
137 
139  bool equals(const char *str) {
140  int len = strlen(str);
141  return strncmp(str, (char*)peekStr(0, len), len) == 0;
142  }
143 
145  void consume(int offset) {
146  assert(available() >= offset);
147  for (int j = 0; j < offset; j++) {
148  read();
149  }
150  }
151 
152 protected:
153  uint8_t *_aucBuffer = nullptr;
154  int _iHead;
155  int _iTail;
156  int _numElems;
157  int max_size = 0;
158 
159  int nextIndex(int index) { return (uint32_t)(index + 1) % max_size; }
160 };
161 
162 } // namespace
RingBuffer that supports extensive peek operations to access and compare the next values.
Definition: RingBuffer.h:16
uint8_t operator[](int idx)
alternaive syntax to peek(idx)
Definition: RingBuffer.h:132
void consume(int offset)
Removes the next n characters from the ringbuffer.
Definition: RingBuffer.h:145
bool equals(const char *str)
Compares the string with the current peek values.
Definition: RingBuffer.h:139
uint8_t * peekStr(int idx, int len)
returns a temporary copy of the requested bytes
Definition: RingBuffer.h:119
int size()
Returns the maximum capacity of the buffer.
Definition: RingBuffer.h:100
int peek(int idx)
peeks the idx next entry from the buffer
Definition: RingBuffer.h:111