copia12092018

Dependencies:   mbed

Revision:
0:b0a79a3a9da8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CB1.h	Wed Jun 13 08:41:23 2018 +0000
@@ -0,0 +1,275 @@
+/*
+ CB1.h - Circular buffer library for Arduino.
+ Copyright (c) 2017 Roberto Lo Giacco.  All right reserved.
+
+ This library 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 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef __CIRCULAR_BUFFER__
+#define __CIRCULAR_BUFFER__
+#include <inttypes.h>
+
+#ifndef CIRCULAR_BUFFER_XS
+#define __CB_ST__ uint16_t
+#else
+#define __CB_ST__ uint8_t
+#endif
+
+#ifdef CIRCULAR_BUFFER_DEBUG
+#include <Print.h>
+#endif
+
+#include <string.h>
+
+template<typename T, __CB_ST__ S> class CB1 {
+public:
+
+    CB1();
+
+    ~CB1();
+
+    /**
+     * Adds an element to the beginning of buffer: the operation returns `false` if the addition caused overwriting an existing element.
+     */
+    bool unshift(T value);
+
+    /**
+     * Adds an element to the end of buffer: the operation returns `false` if the addition caused overwriting an existing element.
+     */
+    bool push(T value);
+
+    /**
+     * Removes an element from the beginning of the buffer.
+     */
+    T shift();
+
+    /**
+     * Removes an element from the end of the buffer.
+     */
+    T pop();
+
+    /**
+     * Returns the element at the beginning of the buffer.
+     */
+    T inline first();
+
+    /**
+     * Returns the element at the end of the buffer.
+     */
+    T inline last();
+
+    /**
+     * Array-like access to buffer
+     */
+    T operator [] (__CB_ST__ index);
+
+    /**
+     * Returns how many elements are actually stored in the buffer.
+     */
+    __CB_ST__ inline size();
+
+    /**
+     * Returns how many elements can be safely pushed into the buffer.
+     */
+    __CB_ST__ inline available();
+
+    /**
+     * Returns how many elements can be potentially stored into the buffer.
+     */
+    __CB_ST__ inline capacity();
+
+    /**
+     * Returns `true` if no elements can be removed from the buffer.
+     */
+    bool inline isEmpty();
+
+    /**
+     * Returns `true` if no elements can be added to the buffer without overwriting existing elements.
+     */
+    bool inline isFull();
+
+    /**
+     * Resets the buffer to a clean status, dropping any reference to current elements
+     * and making all buffer positions available again.
+     */
+    void inline clear();
+
+    #ifdef CIRCULAR_BUFFER_DEBUG
+    void inline debug(Print* out);
+    void inline debugFn(Print* out, void (*printFunction)(Print*, T));
+    #endif
+
+private:
+    T buffer[S];
+    T *head;
+    T *tail;
+    uint16_t count;
+};
+
+
+template<typename T, __CB_ST__ S> 
+CB1<T,S>::CB1() :
+        head(buffer), tail(buffer), count(0) {
+}
+
+template<typename T, __CB_ST__ S> 
+CB1<T,S>::~CB1() {
+}
+
+template<typename T, __CB_ST__ S> 
+bool CB1<T,S>::unshift(T value) {
+    if (head == buffer) {
+        head = buffer + S;
+    }
+    *--head = value;
+    if (count == S) {
+        if (tail-- == buffer) {
+            tail = buffer + S - 1;
+        }
+        return false;
+    } else {
+        if (count++ == 0) {
+            tail = head;
+        }
+        return true;
+    }
+}
+
+template<typename T, __CB_ST__ S> 
+bool CB1<T,S>::push(T value) {
+    if (++tail == buffer + S) {
+        tail = buffer;
+    }
+    *tail = value;
+    if (count == S) {
+        if (++head == buffer + S) {
+            head = buffer;
+        }
+        return false;
+    } else {
+        if (count++ == 0) {
+            head = tail;
+        }
+        return true;
+    }
+}
+
+template<typename T, __CB_ST__ S> 
+T CB1<T,S>::shift() {
+    void(* crash) (void) = 0;
+    if (count <= 0) crash();
+    T result = *head++;
+    if (head >= buffer + S) {
+        head = buffer;
+    }
+    count--;
+    return result;
+}
+
+template<typename T, __CB_ST__ S> 
+T CB1<T,S>::pop() {
+    void(* crash) (void) = 0;
+    if (count <= 0) crash();
+    T result = *tail--;
+    if (tail < buffer) {
+        tail = buffer + S - 1;
+    }
+    count--;
+    return result;
+}
+
+template<typename T, __CB_ST__ S> 
+T inline CB1<T,S>::first() {
+    return *head;
+}
+
+template<typename T, __CB_ST__ S> 
+T inline CB1<T,S>::last() {
+    return *tail;
+}
+
+template<typename T, __CB_ST__ S> 
+T CB1<T,S>::operator [](__CB_ST__ index) {
+    return *(buffer + ((head - buffer + index) % S));
+}
+
+template<typename T, __CB_ST__ S> 
+__CB_ST__ inline CB1<T,S>::size() {
+    return count;
+}
+
+template<typename T, __CB_ST__ S> 
+__CB_ST__ inline CB1<T,S>::available() {
+    return S - count;
+}
+
+template<typename T, __CB_ST__ S> 
+__CB_ST__ inline CB1<T,S>::capacity() {
+    return S;
+}
+
+template<typename T, __CB_ST__ S> 
+bool inline CB1<T,S>::isEmpty() {
+    return count == 0;
+}
+
+template<typename T, __CB_ST__ S> 
+bool inline CB1<T,S>::isFull() {
+    return count == S;
+}
+
+template<typename T, __CB_ST__ S> 
+void inline CB1<T,S>::clear() {
+    memset(buffer, 0, sizeof(buffer));
+    head = tail = buffer;
+    count = 0;
+}
+
+#ifdef CIRCULAR_BUFFER_DEBUG
+template<typename T, __CB_ST__ S> 
+void inline CB1<T,S>::debug(Print* out) {
+    for (__CB_ST__ i = 0; i < S; i++) {
+        int hex = (int)buffer + i;
+        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<typename T, __CB_ST__ S> 
+void inline CB1<T,S>::debugFn(Print* out, void (*printFunction)(Print*, T)) {
+    for (__CB_ST__ i = 0; i < S; i++) {
+        int hex = (int)buffer + i;
+        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
+
+#endif
\ No newline at end of file