mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
[PluginStats] Update recorded timestamps when time is first set
This commit is contained in:
+150
-148
@@ -1,148 +1,150 @@
|
||||
/*
|
||||
CircularBuffer.h - 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CIRCULAR_BUFFER_H_
|
||||
#define CIRCULAR_BUFFER_H_
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef CIRCULAR_BUFFER_DEBUG
|
||||
#include <Print.h>
|
||||
#endif
|
||||
|
||||
namespace Helper {
|
||||
template<bool FITS8, bool FITS16> struct Index {
|
||||
using Type = uint32_t;
|
||||
};
|
||||
|
||||
template<> struct Index<false, true> {
|
||||
using Type = uint16_t;
|
||||
};
|
||||
|
||||
template<> struct Index<true, true> {
|
||||
using Type = uint8_t;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT = typename Helper::Index<(S <= UINT8_MAX), (S <= UINT16_MAX)>::Type> class CircularBuffer {
|
||||
public:
|
||||
/**
|
||||
* The buffer capacity: read only as it cannot ever change.
|
||||
*/
|
||||
static constexpr IT capacity = static_cast<IT>(S);
|
||||
|
||||
/**
|
||||
* Aliases the index type, can be used to obtain the right index type with `decltype(buffer)::index_t`.
|
||||
*/
|
||||
using index_t = IT;
|
||||
|
||||
constexpr CircularBuffer();
|
||||
|
||||
/**
|
||||
* Disables copy constructor
|
||||
*/
|
||||
CircularBuffer(const CircularBuffer&) = delete;
|
||||
CircularBuffer(CircularBuffer&&) = delete;
|
||||
|
||||
/**
|
||||
* Disables assignment operator
|
||||
*/
|
||||
CircularBuffer& operator=(const CircularBuffer&) = delete;
|
||||
CircularBuffer& operator=(CircularBuffer&&) = delete;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* *WARNING* Calling this operation on an empty buffer has an unpredictable behaviour.
|
||||
*/
|
||||
T shift();
|
||||
|
||||
/**
|
||||
* Removes an element from the end of the buffer.
|
||||
* *WARNING* Calling this operation on an empty buffer has an unpredictable behaviour.
|
||||
*/
|
||||
T pop();
|
||||
|
||||
/**
|
||||
* Returns the element at the beginning of the buffer.
|
||||
*/
|
||||
T inline first() const;
|
||||
|
||||
/**
|
||||
* Returns the element at the end of the buffer.
|
||||
*/
|
||||
T inline last() const;
|
||||
|
||||
/**
|
||||
* Array-like access to buffer.
|
||||
* Calling this operation using and index value greater than `size - 1` returns the tail element.
|
||||
* *WARNING* Calling this operation on an empty buffer has an unpredictable behaviour.
|
||||
*/
|
||||
T operator [] (IT index) const;
|
||||
|
||||
/**
|
||||
* Returns how many elements are actually stored in the buffer.
|
||||
*/
|
||||
IT inline size() const;
|
||||
|
||||
/**
|
||||
* Returns how many elements can be safely pushed into the buffer.
|
||||
*/
|
||||
IT inline available() const;
|
||||
|
||||
/**
|
||||
* Returns `true` if no elements can be removed from the buffer.
|
||||
*/
|
||||
bool inline isEmpty() const;
|
||||
|
||||
/**
|
||||
* Returns `true` if no elements can be added to the buffer without overwriting existing elements.
|
||||
*/
|
||||
bool inline isFull() const;
|
||||
|
||||
/**
|
||||
* Resets the buffer to a clean status, making all buffer positions available.
|
||||
*/
|
||||
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] = {0};
|
||||
T *head;
|
||||
T *tail;
|
||||
#ifndef CIRCULAR_BUFFER_INT_SAFE
|
||||
IT count;
|
||||
#else
|
||||
volatile IT count;
|
||||
#endif
|
||||
};
|
||||
|
||||
#include <CircularBuffer.tpp>
|
||||
#endif
|
||||
/*
|
||||
CircularBuffer.h - 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CIRCULAR_BUFFER_H_
|
||||
#define CIRCULAR_BUFFER_H_
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef CIRCULAR_BUFFER_DEBUG
|
||||
#include <Print.h>
|
||||
#endif
|
||||
|
||||
namespace Helper {
|
||||
template<bool FITS8, bool FITS16> struct Index {
|
||||
using Type = uint32_t;
|
||||
};
|
||||
|
||||
template<> struct Index<false, true> {
|
||||
using Type = uint16_t;
|
||||
};
|
||||
|
||||
template<> struct Index<true, true> {
|
||||
using Type = uint8_t;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT = typename Helper::Index<(S <= UINT8_MAX), (S <= UINT16_MAX)>::Type> class CircularBuffer {
|
||||
public:
|
||||
/**
|
||||
* The buffer capacity: read only as it cannot ever change.
|
||||
*/
|
||||
static constexpr IT capacity = static_cast<IT>(S);
|
||||
|
||||
/**
|
||||
* Aliases the index type, can be used to obtain the right index type with `decltype(buffer)::index_t`.
|
||||
*/
|
||||
using index_t = IT;
|
||||
|
||||
constexpr CircularBuffer();
|
||||
|
||||
/**
|
||||
* Disables copy constructor
|
||||
*/
|
||||
CircularBuffer(const CircularBuffer&) = delete;
|
||||
CircularBuffer(CircularBuffer&&) = delete;
|
||||
|
||||
/**
|
||||
* Disables assignment operator
|
||||
*/
|
||||
CircularBuffer& operator=(const CircularBuffer&) = delete;
|
||||
CircularBuffer& operator=(CircularBuffer&&) = delete;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* *WARNING* Calling this operation on an empty buffer has an unpredictable behaviour.
|
||||
*/
|
||||
T shift();
|
||||
|
||||
/**
|
||||
* Removes an element from the end of the buffer.
|
||||
* *WARNING* Calling this operation on an empty buffer has an unpredictable behaviour.
|
||||
*/
|
||||
T pop();
|
||||
|
||||
/**
|
||||
* Returns the element at the beginning of the buffer.
|
||||
*/
|
||||
T inline first() const;
|
||||
|
||||
/**
|
||||
* Returns the element at the end of the buffer.
|
||||
*/
|
||||
T inline last() const;
|
||||
|
||||
/**
|
||||
* Array-like access to buffer.
|
||||
* Calling this operation using and index value greater than `size - 1` returns the tail element.
|
||||
* *WARNING* Calling this operation on an empty buffer has an unpredictable behaviour.
|
||||
*/
|
||||
T operator [] (IT index) const;
|
||||
|
||||
T& operator [] (IT index);
|
||||
|
||||
/**
|
||||
* Returns how many elements are actually stored in the buffer.
|
||||
*/
|
||||
IT inline size() const;
|
||||
|
||||
/**
|
||||
* Returns how many elements can be safely pushed into the buffer.
|
||||
*/
|
||||
IT inline available() const;
|
||||
|
||||
/**
|
||||
* Returns `true` if no elements can be removed from the buffer.
|
||||
*/
|
||||
bool inline isEmpty() const;
|
||||
|
||||
/**
|
||||
* Returns `true` if no elements can be added to the buffer without overwriting existing elements.
|
||||
*/
|
||||
bool inline isFull() const;
|
||||
|
||||
/**
|
||||
* Resets the buffer to a clean status, making all buffer positions available.
|
||||
*/
|
||||
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] = {0};
|
||||
T *head;
|
||||
T *tail;
|
||||
#ifndef CIRCULAR_BUFFER_INT_SAFE
|
||||
IT count;
|
||||
#else
|
||||
volatile IT count;
|
||||
#endif
|
||||
};
|
||||
|
||||
#include <CircularBuffer.tpp>
|
||||
#endif
|
||||
|
||||
@@ -1,163 +1,169 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
constexpr CircularBuffer<T,S,IT>::CircularBuffer() :
|
||||
head(buffer), tail(buffer), count(0) {
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
bool CircularBuffer<T,S,IT>::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<typename T, size_t S, typename IT>
|
||||
bool CircularBuffer<T,S,IT>::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<typename T, size_t S, typename IT>
|
||||
T CircularBuffer<T,S,IT>::shift() {
|
||||
if (count == 0) return *head;
|
||||
T result = *head++;
|
||||
if (head >= buffer + capacity) {
|
||||
head = buffer;
|
||||
}
|
||||
count--;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
T CircularBuffer<T,S,IT>::pop() {
|
||||
if (count == 0) return *tail;
|
||||
T result = *tail--;
|
||||
if (tail < buffer) {
|
||||
tail = buffer + capacity - 1;
|
||||
}
|
||||
count--;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
T inline CircularBuffer<T,S,IT>::first() const {
|
||||
return *head;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
T inline CircularBuffer<T,S,IT>::last() const {
|
||||
return *tail;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
T CircularBuffer<T,S,IT>::operator [](IT index) const {
|
||||
if (index >= count) return *tail;
|
||||
return *(buffer + ((head - buffer + index) % capacity));
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
IT inline CircularBuffer<T,S,IT>::size() const {
|
||||
return count;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
IT inline CircularBuffer<T,S,IT>::available() const {
|
||||
return capacity - count;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
bool inline CircularBuffer<T,S,IT>::isEmpty() const {
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
bool inline CircularBuffer<T,S,IT>::isFull() const {
|
||||
return count == capacity;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
void inline CircularBuffer<T,S,IT>::clear() {
|
||||
head = tail = buffer;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
#ifdef CIRCULAR_BUFFER_DEBUG
|
||||
#include <string.h>
|
||||
template<typename T, size_t S, typename IT>
|
||||
void inline CircularBuffer<T,S,IT>::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<typename T, size_t S, typename IT>
|
||||
void inline CircularBuffer<T,S,IT>::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
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
constexpr CircularBuffer<T,S,IT>::CircularBuffer() :
|
||||
head(buffer), tail(buffer), count(0) {
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
bool CircularBuffer<T,S,IT>::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<typename T, size_t S, typename IT>
|
||||
bool CircularBuffer<T,S,IT>::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<typename T, size_t S, typename IT>
|
||||
T CircularBuffer<T,S,IT>::shift() {
|
||||
if (count == 0) return *head;
|
||||
T result = *head++;
|
||||
if (head >= buffer + capacity) {
|
||||
head = buffer;
|
||||
}
|
||||
count--;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
T CircularBuffer<T,S,IT>::pop() {
|
||||
if (count == 0) return *tail;
|
||||
T result = *tail--;
|
||||
if (tail < buffer) {
|
||||
tail = buffer + capacity - 1;
|
||||
}
|
||||
count--;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
T inline CircularBuffer<T,S,IT>::first() const {
|
||||
return *head;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
T inline CircularBuffer<T,S,IT>::last() const {
|
||||
return *tail;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
T CircularBuffer<T,S,IT>::operator [](IT index) const {
|
||||
if (index >= count) return *tail;
|
||||
return *(buffer + ((head - buffer + index) % capacity));
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
T& CircularBuffer<T,S,IT>::operator [](IT index) {
|
||||
if (index >= count) return *tail;
|
||||
return *(buffer + ((head - buffer + index) % capacity));
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
IT inline CircularBuffer<T,S,IT>::size() const {
|
||||
return count;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
IT inline CircularBuffer<T,S,IT>::available() const {
|
||||
return capacity - count;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
bool inline CircularBuffer<T,S,IT>::isEmpty() const {
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
bool inline CircularBuffer<T,S,IT>::isFull() const {
|
||||
return count == capacity;
|
||||
}
|
||||
|
||||
template<typename T, size_t S, typename IT>
|
||||
void inline CircularBuffer<T,S,IT>::clear() {
|
||||
head = tail = buffer;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
#ifdef CIRCULAR_BUFFER_DEBUG
|
||||
#include <string.h>
|
||||
template<typename T, size_t S, typename IT>
|
||||
void inline CircularBuffer<T,S,IT>::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<typename T, size_t S, typename IT>
|
||||
void inline CircularBuffer<T,S,IT>::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
|
||||
|
||||
Reference in New Issue
Block a user