Untitled diff

Created Diff never expires
27 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
255 lines
80 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
306 lines
#ifndef CIRCULAR_BUFFER_H
#ifndef CIRCULAR_BUFFER_H
#define CIRCULAR_BUFFER_H
#define CIRCULAR_BUFFER_H


template<typename T, uint16_t _size, uint16_t multi = 0>
template<typename T, uint16_t _size, uint16_t multi = 0>
class Circular_Buffer {
class Circular_Buffer {
public:
public:


void push_back(T value) { return write(value); }
void push_back(T value) { return write(value); }
void push_front(T value);
void push_front(T value);
T pop_front() { return read(); }
T pop_front() { return read(); }
T pop_back();
T pop_back();
void write(T value);
void write(T value);
void push_back(const T *buffer, uint16_t length) { write(buffer, length); }
void push_back(const T *buffer, uint16_t length) { write(buffer, length); }
void write(const T *buffer, uint16_t length);
void write(const T *buffer, uint16_t length);
void push_front(const T *buffer, uint16_t length);
void push_front(const T *buffer, uint16_t length);
T peek(uint16_t pos = 0);
T peek(uint16_t pos = 0);
T peekBytes(T *buffer, uint16_t length);
T peekBytes(T *buffer, uint16_t length);
T read();
T read();
T list();
T pop_front(T *buffer, uint16_t length) { readBytes(buffer,length); }
T pop_front(T *buffer, uint16_t length) { readBytes(buffer,length); }
T read(T *buffer, uint16_t length) { readBytes(buffer,length); }
T read(T *buffer, uint16_t length) { readBytes(buffer,length); }
T readBytes(T *buffer, uint16_t length);
T readBytes(T *buffer, uint16_t length);
T pop_back(T *buffer, uint16_t length);
void flush() { return head = tail = _available = 0; }
void flush() { return head = tail = _available = 0; }
void print(const char *p);
void print(const char *p);
void println(const char *p);
void println(const char *p);
uint16_t size() { return _available; }
uint16_t size() { return _available; }
uint16_t available() { return _available; }
uint16_t available() { return _available; }
T* front() { return _cabuf[peek()]; }
T* front() { return _cabuf[_cbuf[(head)&(_size-1)]]+1; }
T* back() { return _cabuf[(tail-1)&(_size-1)]; }
T* back() { return _cabuf[(tail-1)&(_size-1)]+1; }

void match(T *buffer, uint16_t length, int pos1, int pos2, int pos3, int pos4 = -1, int pos5 = -1);
void match(T *buffer, uint16_t length, int pos1, int pos2, int pos3, int pos4 = -1, int pos5 = -1);


protected:
protected:
private:
private:
uint16_t head = 0, tail = 0, _available = 0, _array_pointer = 0;
volatile uint16_t head = 0, tail = 0, _available = 0;
bool init_ca = 1;
T _cbuf[_size];
T _cbuf[_size];
T _cabuf[_size][multi];
T _cabuf[_size][multi];
void _init();
// T _peek(uint16_t pos = 0); // internal array peek version
};
};




template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T, _size, multi>::match(T *buffer, uint16_t length, int pos1, int pos2, int pos3, int pos4, int pos5) {
void Circular_Buffer<T, _size, multi>::match(T *buffer, uint16_t length, int pos1, int pos2, int pos3, int pos4, int pos5) {
uint8_t input_count = 3;
uint8_t input_count = 3;
uint8_t queue_position = 0;
uint8_t queue_position = 0;
bool found = 0;
bool found = 0;
if ( pos4 != -1 ) input_count = 4;
if ( pos4 != -1 ) input_count = 4;
if ( pos5 != -1 ) input_count = 5;
if ( pos5 != -1 ) input_count = 5;
Serial.print("Q Size: "); Serial.println(_available);
Serial.print("Q Size: "); Serial.println(_available);


Serial.println("Displaying current queue: ");
Serial.println("Displaying current queue: ");
for ( uint8_t j = 0; j < _size; j++ ) {
for ( uint8_t j = 0; j < _size; j++ ) {


/*
/*
Serial.print("Peeking: ");
Serial.print("Peeking: ");
for ( uint8_t i = 0; i < _available; i++ ) {
for ( uint8_t i = 0; i < _available; i++ ) {
Serial.print(peek(i));
Serial.print(peek(i));
Serial.print(" ");
Serial.print(" ");
} Serial.println();
} Serial.println();




Serial.print(j); Serial.print(": ");
Serial.print(j); Serial.print(": ");
for ( uint8_t i = 0; i < multi; i++ ) {
for ( uint8_t i = 0; i < multi; i++ ) {
Serial.print(_cabuf[peek(j)][i]);
Serial.print(_cabuf[peek(j)][i]);
Serial.print(" ");
Serial.print(" ");
} Serial.println();
} Serial.println();


*/
*/
}
}




//Serial.print(head); Serial.print(" "); Serial.println(tail);
//Serial.print(head); Serial.print(" "); Serial.println(tail);


// good when head is in front of tail
// good when head is in front of tail


Serial.println("Displaying current queue: ");
Serial.println("Displaying current queue: ");
for ( uint8_t j = 0; j < size(); j++ ) {
for ( uint8_t j = 0; j < size(); j++ ) {
Serial.print(j); Serial.print(": ");
Serial.print(j); Serial.print(": ");
for ( uint8_t i = 0; i < multi; i++ ) {
for ( uint8_t i = 0; i < multi; i++ ) {
Serial.print(_cabuf[peek(j)][i]);
Serial.print(_cabuf[peek(j)][i]);
Serial.print(" ");
Serial.print(" ");
} Serial.println();
} Serial.println();
}
}










for ( uint8_t j = 0; j <= _available; j++ ) {
for ( uint8_t j = 0; j <= _available; j++ ) {
queue_position = j;
queue_position = j;
switch ( input_count ) {
switch ( input_count ) {
case 3: {
case 3: {
if ( _cabuf[j][pos1] == buffer[pos1] && _cabuf[j][pos2] == buffer[pos2] &&
if ( _cabuf[j][pos1] == buffer[pos1] && _cabuf[j][pos2] == buffer[pos2] &&
_cabuf[j][pos3] == buffer[pos3] ) {
_cabuf[j][pos3] == buffer[pos3] ) {
found = 1;
found = 1;
break;
break;
}
}
}
}
case 4: {
case 4: {
if ( _cabuf[j][pos1] == buffer[pos1] && _cabuf[j][pos2] == buffer[pos2] &&
if ( _cabuf[j][pos1] == buffer[pos1] && _cabuf[j][pos2] == buffer[pos2] &&
_cabuf[j][pos3] == buffer[pos3] && _cabuf[j][pos4] == buffer[pos4] ) {
_cabuf[j][pos3] == buffer[pos3] && _cabuf[j][pos4] == buffer[pos4] ) {
found = 1;
found = 1;
break;
break;
}
}
}
}
case 5: {
case 5: {
if ( _cabuf[j][pos1] == buffer[pos1] && _cabuf[j][pos2] == buffer[pos2] &&
if ( _cabuf[j][pos1] == buffer[pos1] && _cabuf[j][pos2] == buffer[pos2] &&
_cabuf[j][pos3] == buffer[pos3] && _cabuf[j][pos4] == buffer[pos4] &&
_cabuf[j][pos3] == buffer[pos3] && _cabuf[j][pos4] == buffer[pos4] &&
_cabuf[j][pos5] == buffer[pos5] ) {
_cabuf[j][pos5] == buffer[pos5] ) {
found = 1;
found = 1;
break;
break;
}
}
}
}
}
}
if ( found ) {
if ( found ) {
memmove(_cabuf[j],buffer,length*sizeof(T));
memmove(_cabuf[j],buffer,length*sizeof(T));
break;
break;
}
}
}
}


Serial.print("Q Size: "); Serial.println(_available);
Serial.print("Q Size: "); Serial.println(_available);
if ( !found ) { Serial.println("Nothing Found"); }
if ( !found ) { Serial.println("Nothing Found"); }
Serial.println();
Serial.println();
Serial.println("Displaying updated queue: ");
Serial.println("Displaying updated queue: ");
for ( uint8_t j = 0; j < _available; j++ ) {
for ( uint8_t j = 0; j < _available; j++ ) {
Serial.print(j); Serial.print(": ");
Serial.print(j); Serial.print(": ");
for ( uint8_t i = 0; i < multi; i++ ) {
for ( uint8_t i = 0; i < multi; i++ ) {
Serial.print(_cabuf[j][i]);
Serial.print(_cabuf[j][i]);
Serial.print(" ");
Serial.print(" ");
} Serial.println();
} Serial.println();
}
}


}
}
template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::print(const char *p) {
void Circular_Buffer<T,_size,multi>::print(const char *p) {
if ( multi ) return;
if ( multi ) return;
write((T*)p,strlen(p));
write((T*)p,strlen(p));
}
}


template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::println(const char *p) {
void Circular_Buffer<T,_size,multi>::println(const char *p) {
if ( multi ) return;
if ( multi ) return;
write((T*)p,strlen(p));
write((T*)p,strlen(p));
write('\n');
write('\n');
}
}


template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::_init() {
for ( uint16_t i = 0; i < _size; i++ ) _cbuf[i] = i;
init_ca = 0;
}


template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::push_front(const T *buffer, uint16_t length) {
void Circular_Buffer<T,_size,multi>::push_front(const T *buffer, uint16_t length) {
if ( multi ) {
if ( multi ) {
push_front(_array_pointer);
if ( init_ca ) _init();
memmove(_cabuf[peek()],buffer,length*sizeof(T));
if ( tail == (head ^ _size) ) tail = (tail - 1)&(2*_size-1);
if ( _array_pointer++ >= _size -1 ) _array_pointer = 0;
head = (head - 1)&(2*_size-1);
_cabuf[_cbuf[(head)&(_size-1)]][0] = length;
memmove(_cabuf[_cbuf[(head)&(_size-1)]]+1,buffer,length*sizeof(T));
if ( _available < _size ) _available++;
return;
return;
}
}
for ( uint16_t i = length-1; i > 0; i-- ) push_front(buffer[i]);
for ( uint16_t i = length-1; i > 0; i-- ) push_front(buffer[i]);
push_front(buffer[0]);
push_front(buffer[0]);
}
}


template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
T Circular_Buffer<T,_size,multi>::pop_back() {
T Circular_Buffer<T,_size,multi>::pop_back() {
if ( _available ) {
if ( _available ) {
_available--;
( !_available ) ? _available = 0 : _available--;
tail = (tail - 1)&(2*_size-1);
tail = (tail - 1)&(2*_size-1);
return _cbuf[tail&(_size-1)];
return _cbuf[tail&(_size-1)];
}
}
return -1;
return -1;
}
}


template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::push_front(T value) {
void Circular_Buffer<T,_size,multi>::push_front(T value) {
if ( multi ) return;
if ( multi ) return;
head = (head - 1)&(2*_size-1);
head = (head - 1)&(2*_size-1);
_cbuf[head&(_size-1)] = value;
_cbuf[head&(_size-1)] = value;
if ( _available++ >= _size ) _available = _size;
if ( _available < _size ) _available++;
}
}
template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::write(const T *buffer, uint16_t length) {
void Circular_Buffer<T,_size,multi>::write(const T *buffer, uint16_t length) {
if ( multi ) {
if ( multi ) {
memmove(_cabuf[_array_pointer],buffer,length*sizeof(T));
if ( init_ca ) _init();
if ( _available++ >= _size ) _available = _size;
_cabuf[_cbuf[tail&(_size-1)]][0] = length;
_cbuf[tail&(_size-1)] = _array_pointer;
memmove(_cabuf[_cbuf[tail&(_size-1)]]+1,buffer,length*sizeof(T));
if ( tail == (head ^ _size) ) head = (head + 1)&(2*_size-1);
if ( tail == (head ^ _size) ) head = (head + 1)&(2*_size-1);
tail = (tail + 1)&(2*_size-1);
tail = (tail + 1)&(2*_size-1);
if ( _array_pointer++ >= _size -1 ) _array_pointer = 0;
if ( _available < _size ) _available++;
return;
return;
}
}
if ( ( _available += length ) >= _size ) _available = _size;
if ( ( _available += length ) >= _size ) _available = _size;
if ( length < ( _size - tail ) ) {
if ( length < ( _size - tail ) ) {
memmove(_cbuf+tail,buffer,length*sizeof(T));
memmove(_cbuf+tail,buffer,length*sizeof(T));
tail = (tail + length)&(2*_size-1);
tail = (tail + length)&(2*_size-1);
}
}
else for ( uint16_t i = 0; i < length; i++ ) write(buffer[i]);
else for ( uint16_t i = 0; i < length; i++ ) write(buffer[i]);
}
}


template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::write(T value) {
void Circular_Buffer<T,_size,multi>::write(T value) {
if ( multi ) return;
if ( multi ) return;
if ( _available++ >= _size ) _available = _size;
if ( _available < _size ) _available++;
_cbuf[tail&(_size-1)] = value;
_cbuf[tail&(_size-1)] = value;
if ( tail == (head ^ _size) ) head = (head + 1)&(2*_size-1);
if ( tail == (head ^ _size) ) head = (head + 1)&(2*_size-1);
tail = (tail + 1)&(2*_size-1);
tail = (tail + 1)&(2*_size-1);
}
}



template<typename T, uint16_t _size, uint16_t multi>
T Circular_Buffer<T,_size,multi>::list() {
if ( multi ) {
if ( init_ca ) _init();
Serial.print("Queue Size: "); Serial.print(size()); Serial.print(", Index order: ");
for ( uint8_t i = 0; i < size(); i++ ) {
Serial.print(_cbuf[(head+i)&(_size-1)]); Serial.print(" ");
} Serial.println();
Serial.print("First Entry: ");
for ( uint8_t i = 1; i <= _cabuf[_cbuf[(head)&(_size-1)]][0]; i++ ) {
Serial.print(_cabuf[_cbuf[(head)&(_size-1)]][i]); Serial.print(" ");
} Serial.print("("); Serial.print(_cabuf[_cbuf[(head)&(_size-1)]][0]); Serial.println(" entries.)");
Serial.print("Last Entry: ");
for ( uint8_t i = 1; i <= _cabuf[_cbuf[(head+size()-1)&(_size-1)]][0]; i++ ) {
Serial.print(_cabuf[_cbuf[(head+size()-1)&(_size-1)]][i]); Serial.print(" ");
} Serial.print("("); Serial.print(_cabuf[_cbuf[(head+size()-1)&(_size-1)]][0]); Serial.println(" entries.)");
Serial.println();
Serial.println("Queue list: ");
for ( uint8_t i = 0; i < _available; i++ ) {
Serial.print(i); Serial.print(") ");
for ( uint8_t j = 1; j <= _cabuf[_cbuf[(head+i)&(_size-1)]][0]; j++ ) {
Serial.print(_cabuf[_cbuf[(head+i)&(_size-1)]][j]); Serial.print(" ");
} Serial.print("("); Serial.print(_cabuf[_cbuf[(head+i)&(_size-1)]][0]); Serial.println(" entries.)");
} Serial.println();
}
}


template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
T Circular_Buffer<T,_size,multi>::read() {
T Circular_Buffer<T,_size,multi>::read() {
_available--;
if ( multi ) {
if ( init_ca ) _init();
if ( tail == (head ^ _size) ) tail = (size() - 1)&(2*_size-1);
head = (head + 1)&(2*_size-1);
( !_available ) ? _available = 0 : _available--;
return 0;
}
( !_available ) ? _available = 0 : _available--;
T value = _cbuf[head&(_size-1)];
T value = _cbuf[head&(_size-1)];
head = (head + 1)&(2*_size-1);
head = (head + 1)&(2*_size-1);
return value;
return value;
}
}


template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
T Circular_Buffer<T,_size,multi>::peek(uint16_t pos) {
T Circular_Buffer<T,_size,multi>::peek(uint16_t pos) {
if ( multi ) {
return _cbuf[(head+pos)&(_size-1)];
}
if ( pos > _size ) return 0;
if ( pos > _size ) return 0;
return _cbuf[(head+pos)&(_size-1)];
return _cbuf[(head+pos)&(_size-1)];
}
}


template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
T Circular_Buffer<T,_size,multi>::peekBytes(T *buffer, uint16_t length) {
T Circular_Buffer<T,_size,multi>::peekBytes(T *buffer, uint16_t length) {
if ( multi ) return 0;
if ( multi ) return 0;
uint16_t _count;
uint16_t _count;
( _available < length ) ? _count = _available : _count = length;
( _available < length ) ? _count = _available : _count = length;
if ( _count < ( _size - head ) ) memmove(buffer,_cbuf,_count*sizeof(T));
if ( _count < ( _size - head ) ) memmove(buffer,_cbuf,_count*sizeof(T));
else for ( uint16_t i = 0; i < _count; i++ ) buffer[i] = peek(i);
else for ( uint16_t i = 0; i < _count; i++ ) buffer[i] = peek(i);
return _count;
return _count;
}
}


template<typename T, uint16_t _size, uint16_t multi>
template<typename T, uint16_t _size, uint16_t multi>
T Circular_Buffer<T,_size,multi>::readBytes(T *buffer, uint16_t length) {
T Circular_Buffer<T,_size,multi>::readBytes(T *buffer, uint16_t length) {
if ( multi ) {
if ( multi ) {
memmove(&buffer[0],&_cabuf[peek()],length*sizeof(T)); // update CA buffer
if ( init_ca ) _init();
read(); // deque item
memmove(&buffer[0],&_cabuf[_cbuf[(head)&(_size-1)]][1],length*sizeof(T)); // update CA buffer
read();
return 0;
return 0;
}
}
uint16_t _count;
uint16_t _count;
( _available < length ) ? _count = _available : _count = length; // memmove if aligned
( _available < length ) ? _count = _available : _count = length; // memmove if aligned
if ( _count < ( _size - head ) ) {
if ( _count < ( _size - head ) ) {
_available -= length;
_available -= length;
memmove(buffer,_cbuf,_count*sizeof(T));
memmove(buffer,_cbuf,_count*sizeof(T));
head = (head + _count)&(2*_size-1);
head = (head + _count)&(2*_size-1);
}
}
else for ( uint16_t i = 0; i < _count; i++ ) buffer[i] = read(); // if buffer rollover
else for ( uint16_t i = 0; i < _count; i++ ) buffer[i] = read(); // if buffer rollover
return _count;
return _count;
}
}



template<typename T, uint16_t _size, uint16_t multi>

T Circular_Buffer<T,_size,multi>::pop_back(T *buffer, uint16_t length) {

if ( multi ) {

if ( init_ca ) _init();
memmove(&buffer[0],&_cabuf[(tail-1)&(_size-1)][1],length*sizeof(T));
tail = (tail - 1)&(2*_size-1);
( !_available ) ? _available = 0 : _available--;
return 0;
}
}


#endif // Circular_Buffer_H
#endif // Circular_Buffer_H