Massimo Viaro / Mbed 2 deprecated Viaro_SpandiConcime_V3

Dependencies:   mbed

Fork of Viaro_SpandiConcime_V2b by Neri Tiziano

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CB1.h Source File

CB1.h

00001 /*
00002  CB1.h - Circular buffer library for Arduino.
00003  Copyright (c) 2017 Roberto Lo Giacco.  All right reserved.
00004 
00005  This library is free software; you can redistribute it and/or
00006  modify it under the terms of the GNU Lesser General Public
00007  License as published by the Free Software Foundation; either
00008  version 2.1 of the License, or (at your option) any later version.
00009 
00010  This library is distributed in the hope that it will be useful,
00011  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  Lesser General Public License for more details.
00014 
00015  You should have received a copy of the GNU Lesser General Public
00016  License along with this library; if not, write to the Free Software
00017  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 #ifndef __CIRCULAR_BUFFER__
00020 #define __CIRCULAR_BUFFER__
00021 #include <inttypes.h>
00022 
00023 #ifndef CIRCULAR_BUFFER_XS
00024 #define __CB_ST__ uint16_t
00025 #else
00026 #define __CB_ST__ uint8_t
00027 #endif
00028 
00029 #ifdef CIRCULAR_BUFFER_DEBUG
00030 #include <Print.h>
00031 #endif
00032 
00033 #include <string.h>
00034 
00035 template<typename T, __CB_ST__ S> class CB1 {
00036 public:
00037 
00038     CB1();
00039 
00040     ~CB1();
00041 
00042     /**
00043      * Adds an element to the beginning of buffer: the operation returns `false` if the addition caused overwriting an existing element.
00044      */
00045     bool unshift(T value);
00046 
00047     /**
00048      * Adds an element to the end of buffer: the operation returns `false` if the addition caused overwriting an existing element.
00049      */
00050     bool push(T value);
00051 
00052     /**
00053      * Removes an element from the beginning of the buffer.
00054      */
00055     T shift();
00056 
00057     /**
00058      * Removes an element from the end of the buffer.
00059      */
00060     T pop();
00061 
00062     /**
00063      * Returns the element at the beginning of the buffer.
00064      */
00065     T inline first();
00066 
00067     /**
00068      * Returns the element at the end of the buffer.
00069      */
00070     T inline last();
00071 
00072     /**
00073      * Array-like access to buffer
00074      */
00075     T operator [] (__CB_ST__ index);
00076 
00077     /**
00078      * Returns how many elements are actually stored in the buffer.
00079      */
00080     __CB_ST__ inline size();
00081 
00082     /**
00083      * Returns how many elements can be safely pushed into the buffer.
00084      */
00085     __CB_ST__ inline available();
00086 
00087     /**
00088      * Returns how many elements can be potentially stored into the buffer.
00089      */
00090     __CB_ST__ inline capacity();
00091 
00092     /**
00093      * Returns `true` if no elements can be removed from the buffer.
00094      */
00095     bool inline isEmpty();
00096 
00097     /**
00098      * Returns `true` if no elements can be added to the buffer without overwriting existing elements.
00099      */
00100     bool inline isFull();
00101 
00102     /**
00103      * Resets the buffer to a clean status, dropping any reference to current elements
00104      * and making all buffer positions available again.
00105      */
00106     void inline clear();
00107 
00108     #ifdef CIRCULAR_BUFFER_DEBUG
00109     void inline debug(Print* out);
00110     void inline debugFn(Print* out, void (*printFunction)(Print*, T));
00111     #endif
00112 
00113 private:
00114     T buffer[S];
00115     T *head;
00116     T *tail;
00117     uint16_t count;
00118 };
00119 
00120 
00121 template<typename T, __CB_ST__ S> 
00122 CB1<T,S>::CB1() :
00123         head(buffer), tail(buffer), count(0) {
00124 }
00125 
00126 template<typename T, __CB_ST__ S> 
00127 CB1<T,S>::~CB1() {
00128 }
00129 
00130 template<typename T, __CB_ST__ S> 
00131 bool CB1<T,S>::unshift(T value) {
00132     if (head == buffer) {
00133         head = buffer + S;
00134     }
00135     *--head = value;
00136     if (count == S) {
00137         if (tail-- == buffer) {
00138             tail = buffer + S - 1;
00139         }
00140         return false;
00141     } else {
00142         if (count++ == 0) {
00143             tail = head;
00144         }
00145         return true;
00146     }
00147 }
00148 
00149 template<typename T, __CB_ST__ S> 
00150 bool CB1<T,S>::push(T value) {
00151     if (++tail == buffer + S) {
00152         tail = buffer;
00153     }
00154     *tail = value;
00155     if (count == S) {
00156         if (++head == buffer + S) {
00157             head = buffer;
00158         }
00159         return false;
00160     } else {
00161         if (count++ == 0) {
00162             head = tail;
00163         }
00164         return true;
00165     }
00166 }
00167 
00168 template<typename T, __CB_ST__ S> 
00169 T CB1<T,S>::shift() {
00170     void(* crash) (void) = 0;
00171     if (count <= 0) crash();
00172     T result = *head++;
00173     if (head >= buffer + S) {
00174         head = buffer;
00175     }
00176     count--;
00177     return result;
00178 }
00179 
00180 template<typename T, __CB_ST__ S> 
00181 T CB1<T,S>::pop() {
00182     void(* crash) (void) = 0;
00183     if (count <= 0) crash();
00184     T result = *tail--;
00185     if (tail < buffer) {
00186         tail = buffer + S - 1;
00187     }
00188     count--;
00189     return result;
00190 }
00191 
00192 template<typename T, __CB_ST__ S> 
00193 T inline CB1<T,S>::first() {
00194     return *head;
00195 }
00196 
00197 template<typename T, __CB_ST__ S> 
00198 T inline CB1<T,S>::last() {
00199     return *tail;
00200 }
00201 
00202 template<typename T, __CB_ST__ S> 
00203 T CB1<T,S>::operator [](__CB_ST__ index) {
00204     return *(buffer + ((head - buffer + index) % S));
00205 }
00206 
00207 template<typename T, __CB_ST__ S> 
00208 __CB_ST__ inline CB1<T,S>::size() {
00209     return count;
00210 }
00211 
00212 template<typename T, __CB_ST__ S> 
00213 __CB_ST__ inline CB1<T,S>::available() {
00214     return S - count;
00215 }
00216 
00217 template<typename T, __CB_ST__ S> 
00218 __CB_ST__ inline CB1<T,S>::capacity() {
00219     return S;
00220 }
00221 
00222 template<typename T, __CB_ST__ S> 
00223 bool inline CB1<T,S>::isEmpty() {
00224     return count == 0;
00225 }
00226 
00227 template<typename T, __CB_ST__ S> 
00228 bool inline CB1<T,S>::isFull() {
00229     return count == S;
00230 }
00231 
00232 template<typename T, __CB_ST__ S> 
00233 void inline CB1<T,S>::clear() {
00234     memset(buffer, 0, sizeof(buffer));
00235     head = tail = buffer;
00236     count = 0;
00237 }
00238 
00239 #ifdef CIRCULAR_BUFFER_DEBUG
00240 template<typename T, __CB_ST__ S> 
00241 void inline CB1<T,S>::debug(Print* out) {
00242     for (__CB_ST__ i = 0; i < S; i++) {
00243         int hex = (int)buffer + i;
00244         out->print(hex, HEX);
00245         out->print("  ");
00246         out->print(*(buffer + i));
00247         if (head == buffer + i) {
00248             out->print(" head");
00249         } 
00250         if (tail == buffer + i) {
00251             out->print(" tail");
00252         }
00253         out->println();
00254     }
00255 }
00256 
00257 template<typename T, __CB_ST__ S> 
00258 void inline CB1<T,S>::debugFn(Print* out, void (*printFunction)(Print*, T)) {
00259     for (__CB_ST__ i = 0; i < S; i++) {
00260         int hex = (int)buffer + i;
00261         out->print(hex, HEX);
00262         out->print("  ");
00263         printFunction(out, *(buffer + i));
00264         if (head == buffer + i) {
00265             out->print(" head");
00266         } 
00267         if (tail == buffer + i) {
00268             out->print(" tail");
00269         }
00270         out->println();
00271     }
00272 }
00273 #endif
00274 
00275 #endif