Обёртка для передачи чисел, строк и бинарных данных с преобразованием совместимых типов
enum class AType : uint8_t { None, Bool, Int, Uint, Float, Str, CStr, String, FStr, Bin };// ПОДКЛЮЧЕНИЕ ДАННЫХ
// указанный тип
Any(AType type, void* p, uint16_t size = 0);
// бинарные
static Any bin(T* p);
static Any bin(void* p, uint16_t size);
// строки
Any(String* p);
Any(String& s);
Any(char* p);
Any(__FlashStringHelper* p);
Any(char* p, uint16_t len); // len не считая \0
Any(PGM_P p, uint16_t len, bool pgm); // len не считая \0
Any(char* p, size_t cap, uint16_t len); // len не считая \0
template <size_t N>
Any(char (&arr)[N]);
// числа
Any(bool* p);
Any(signed char* p);
Any(unsigned char* p);
Any(short* p);
Any(unsigned short* p);
Any(int* p);
Any(unsigned int* p);
Any(long* p);
Any(unsigned long* p);
Any(long long* p);
Any(unsigned long long* p);
Any(float* p);
// ПРОСТО ЗНАЧЕНИЕ
Any(bool v);
Any(char v);
Any(signed char v);
Any(unsigned char v);
Any(short v);
Any(unsigned short v);
Any(int v);
Any(unsigned int v);
Any(long v);
Any(unsigned long v);
Any(float v);
Any(double v);
// МЕТОДЫ
// валидность
explicit operator bool();
// длина строк, размер int и bin
uint16_t size();
// тип
AType type();
// ram-строка
bool isStr();
// число
bool isInt();
// указатель на данные
void* data();
// записать в
bool writeTo(Any& dst);
// записать только в совместимый базовый тип:
// Str/CStr -> Str/String, Int/Uint -> Int/Uint, остальные без преобразования
bool writeToSame(Any& dst);
// прочитать из Any
bool readFrom(Any& src);
// прочитать из строки (в Str/String/Int/Uint/Float)
bool readFromStr(const char* s);
// напечатать в (целые до 32 бит)
void printTo(Print& p);
// в String-строку (целые до 32 бит)
String toString();
// получить нуль-терминированную RAM-строку
char* c_str();
// получить как int (для числовых типов)
int32_t toInt();
// получить как int64 (для числовых типов)
int64_t toInt64();
// получить как uint (для числовых типов)
uint32_t toUint();
// получить как uint64 (для числовых типов)
uint64_t toUint64();
// получить как float (для числовых типов)
float toFloat();Основная идея Any - передавать в функцию данные любого типа, т.е. перегрузка на уровне конструктора Any, а не на уровне функции:
void foo(Any v1, Any v2);
foo(123, "str");
foo(F("fstr"), 3.14);Any позволяет печататься и конвертироваться между базовыми типами, а также копировать в любой неконстантный тип данные из строки.
Any передаёт значения разных типов через единый интерфейс. Числа до 32 бит и float, переданные по значению, хранятся внутри объекта. double приводится к float. Указатели на числа, строки и бинарные данные не передают владение памятью: источник должен существовать до завершения работы с Any. Для 64-битных целых используйте указатель на переменную и toInt64() или toUint64().
Копирование и присваивание Any запрещены, доступен конструктор перемещения. operator bool() проверяет наличие данных, а не логическое значение числа. Any(char) представляет строку из одного символа - для числового байта используйте signed char или unsigned char.
#include <Any.h>
int value = 10;
Any ref(&value);
ref.readFrom(42);
Any snapshot(value);
value = 7;
Serial.println(ref.toInt()); // 7
Serial.println(snapshot.toInt()); // 42- Целые числа преобразуются в целые,
boolиfloat - Значение
boolзаписывается вboolи целые числа - Значение
floatзаписывается вfloatи целые числа, дробная часть отбрасывается - Строки записываются в изменяемый массив
charилиString - Бинарные блоки копируются только в бинарные блоки того же размера
writeTo() и readFrom() возвращают false для неподдерживаемого преобразования. Числа не парсятся из строк. toInt(), toUint(), toFloat(), printTo() и toString() не обеспечивают полноценную обработку 64-битных целых. Сужение целых не проверяет переполнение.
writeToSame() допускает Int/Uint → Int/Uint, Str/CStr → Str/String, а также одинаковые Bool, Float и Bin. Источники String и FStr этим методом не поддерживаются. Для них используйте writeTo().
char text[16] = "";
String dynamic;
Any("hello").writeTo(text);
Any(F("world")).writeTo(&dynamic);Any(String*) ссылается на изменяемый объект String, а Any(const String&) сохраняет указатель на его текущий буфер. Не сохраняйте Any от временного String и не меняйте адрес буфера источника до чтения.
Длина строки не включает нулевой терминатор, вместимость массива включает его. При нехватке места writeTo() обрезает строку, добавляет \0 и возвращает false. writeToSame() для изменяемой строки обновляет сохранённую длину и возвращает true даже при обрезании. Обычный writeTo() сохранённую длину приёмника не обновляет. Для c_str(), toString() и записи в String исходная строка должна быть нуль-терминированной даже при явно заданной длине.
struct Config { uint16_t period; uint8_t mode; };
Config source{1000, 1};
Config target{};
bool ok = Any::bin(&source).writeTo(Any::bin(&target));Размер строк и бинарных блоков хранится в uint16_t. Бинарное копирование переносит представление объекта в памяти, включая возможные байты выравнивания.
- Библиотеку можно найти по названию Any и установить через менеджер библиотек в:
- Arduino IDE
- Arduino IDE v2
- PlatformIO
- Скачать библиотеку .zip архивом для ручной установки:
- Распаковать и положить в C:\Program Files (x86)\Arduino\libraries (Windows x64)
- Распаковать и положить в C:\Program Files\Arduino\libraries (Windows x32)
- Распаковать и положить в Документы/Arduino/libraries/
- (Arduino IDE) автоматическая установка из .zip: Скетч/Подключить библиотеку/Добавить .ZIP библиотеку… и указать скачанный архив
- Читай более подробную инструкцию по установке библиотек здесь
- Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи
- Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить"
- Вручную: удалить папку со старой версией, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам!
При нахождении багов создавайте Issue, а лучше сразу пишите на почту alex@alexgyver.ru
Библиотека открыта для доработки и ваших Pull Request'ов!
При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать:
- Версия библиотеки
- Какой используется МК
- Версия SDK (для ESP)
- Версия Arduino IDE
- Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде
- Какой код загружался, какая работа от него ожидалась и как он работает в реальности
- В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код