Program Listing for File KPFoundation.hpp¶
↰ Return to documentation for file (src/KPFoundation.hpp)
#pragma once
#include <Arduino.h>
#undef min
#undef max
#include <algorithm>
#include <numeric>
#define TRACE "[Trace ", millis() / 1000, " ", __FILE__, ":", __LINE__, __PRETTY_FUNCTION__, "] "
extern "C" char * sbrk(int i);
class KPController;
class KPComponent {
public:
const char * name;
KPController * controller;
KPComponent(const char * name, KPController * controller = nullptr)
: name(name),
controller(controller) {}
virtual bool enabled() {
return true;
}
virtual void setup(){};
virtual void update(){};
};
//
// ────────────────────────────────────────────────── I ──────────
// :::::: P R I N T : : : : : : : :
// ────────────────────────────────────────────────────────────
//
// Overload unsupported types here...
inline size_t printTo(Print & printer, time_t val) {
return printer.print((long) val);
}
template <typename T0, typename T1>
size_t printTo(Print & printer, std::pair<T0, T1> val) {
using namespace std;
return printer.print("(") + printTo(printer, val.first) + printer.print(",")
+ printTo(printer, val.second) + printer.print(")");
}
//...
template <typename T>
size_t printTo(Print & printer, T && val) {
return printer.print(std::forward<T>(val));
}
template <typename... Types>
size_t printTo(Print & printer, Types &&... values) {
size_t sizes[sizeof...(Types)] = {printTo(printer, std::forward<Types>(values))...};
return std::accumulate(sizes, sizes + sizeof...(Types), 0);
}
template <typename T>
Print & operator<<(Print & printer, T && val) {
printTo(printer, std::forward<T>(val));
return printer;
}
// ────────────────────────────────────────────────────────────────────────────────
// Output to Serial
// ────────────────────────────────────────────────────────────────────────────────
template <typename... Types>
size_t print(Types &&... values) {
return printTo(Serial, std::forward<Types>(values)...);
}
inline size_t println() {
return Serial.println();
}
template <typename... Types>
size_t println(Types... values) {
return print(std::forward<Types>(values)...) + println();
}
[[noreturn]] inline void halt() {
while (true) {}
}
template <typename... Types>
[[noreturn]] void halt(Types &&... values) {
println(std::forward<Types>(values)...);
halt();
}
class KPString {
private:
const char * ptr = nullptr;
public:
KPString() = default;
KPString(const char * _ptr) : ptr(_ptr) {}
bool operator==(const char * rhs) const {
return strcmp(ptr, rhs) == 0;
}
bool operator!=(const char * rhs) const {
return !this->operator==(rhs);
}
operator const char *() const {
return ptr;
}
};
template <size_t capacity>
class KPStringBuilder : public Print {
private:
char buffer[capacity + 1]{0};
size_t _size = 0;
public:
template <typename... Types>
KPStringBuilder(Types &&... args) {
using expand_type = int[];
expand_type{0, (::printTo(*this, std::forward<Types>(args)), 0)...};
}
size_t write(const uint8_t * p, size_t n) override {
size_t bound = std::min(capacity - _size, n);
memcpy(buffer + _size, p, bound);
_size += bound;
buffer[_size] = 0;
return bound;
}
size_t write(uint8_t c) override {
if (c == 0 || _size >= capacity) {
return 0;
}
buffer[_size++] = static_cast<char>(c);
buffer[_size] = 0;
return 1;
}
void clear() {
_size = 0;
buffer[0] = 0;
}
size_t size() const {
return _size;
}
const char * c_str() const {
return buffer;
}
operator const char *() const {
return buffer;
}
bool operator==(const char * rhs) const {
return strncmp(buffer, rhs, size()) == 0;
}
bool operator!=(const char * rhs) const {
return !(operator==(rhs));
}
};
inline double secsToMillis(double seconds) {
return seconds * 1000;
}
inline double millisToSecs(double ms) {
return ms / 1000;
}
inline size_t free_ram() {
char stack_dummy;
return &stack_dummy - sbrk(0);
}
inline int strcmpi(const char * left, const char * right) {
for (int i = 0;; i++) {
int l = left[i], r = right[i];
if (l == 0 && r == 0) {
return 0;
}
if (toupper(l) != toupper(r)) {
return l - r;
}
}
}
inline size_t printFreeRam() {
return println("Free Memory: ", free_ram());
}