/* CircularBuffer.tpp - Circular buffer library for Arduino. Copyright (c) 2017 Roberto Lo Giacco. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ template constexpr CircularBuffer::CircularBuffer() : head(buffer), tail(buffer), count(0) { } template bool CircularBuffer::unshift(T value) { if (head == buffer) { head = buffer + capacity; } *--head = value; if (count == capacity) { if (tail-- == buffer) { tail = buffer + capacity - 1; } return false; } else { if (count++ == 0) { tail = head; } return true; } } template bool CircularBuffer::push(T value) { if (++tail == buffer + capacity) { tail = buffer; } *tail = value; if (count == capacity) { if (++head == buffer + capacity) { head = buffer; } return false; } else { if (count++ == 0) { head = tail; } return true; } } template T CircularBuffer::shift() { if (count == 0) return *head; T result = *head++; if (head >= buffer + capacity) { head = buffer; } count--; return result; } template T CircularBuffer::pop() { if (count == 0) return *tail; T result = *tail--; if (tail < buffer) { tail = buffer + capacity - 1; } count--; return result; } template T inline CircularBuffer::first() const { return *head; } template T inline CircularBuffer::last() const { return *tail; } template T CircularBuffer::operator [](IT index) const { if (index >= count) return *tail; return *(buffer + ((head - buffer + index) % capacity)); } template IT inline CircularBuffer::size() const { return count; } template IT inline CircularBuffer::available() const { return capacity - count; } template bool inline CircularBuffer::isEmpty() const { return count == 0; } template bool inline CircularBuffer::isFull() const { return count == capacity; } template void inline CircularBuffer::clear() { head = tail = buffer; count = 0; } #ifdef CIRCULAR_BUFFER_DEBUG #include template void inline CircularBuffer::debug(Print* out) { for (IT i = 0; i < capacity; i++) { int hex = (int)buffer + i; out->print("["); out->print(hex, HEX); out->print("] "); out->print(*(buffer + i)); if (head == buffer + i) { out->print("<-head"); } if (tail == buffer + i) { out->print("<-tail"); } out->println(); } } template void inline CircularBuffer::debugFn(Print* out, void (*printFunction)(Print*, T)) { for (IT i = 0; i < capacity; i++) { int hex = (int)buffer + i; out->print("["); out->print(hex, HEX); out->print("] "); printFunction(out, *(buffer + i)); if (head == buffer + i) { out->print("<-head"); } if (tail == buffer + i) { out->print("<-tail"); } out->println(); } } #endif