diff --git a/wiring/inc/spark_wiring_ledger_v1.h b/wiring/inc/spark_wiring_ledger_v1.h new file mode 100644 index 0000000000..36661bfe11 --- /dev/null +++ b/wiring/inc/spark_wiring_ledger_v1.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 Particle Industries, Inc. All rights 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 3 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, see . + */ + +#pragma once + +#include "spark_wiring_variant.h" + +namespace particle { + +/** + * A ledger. + * + * Use `Particle.ledger()` to create an instance of this class. + */ +class Ledger { +public: + /** + * A callback invoked when the ledger data has been synchronized with the Cloud. + * + * @param ledger Ledger instance. + * @param userData User data. + */ + typedef void (*OnSyncCallback)(Ledger ledger, void* userData); + + /** + * Default constructor. + * + * Constructs an invalid ledger instance. + */ + Ledger(); + + /** + * Set the ledger data. + * + * This method replaces the current contents of the ledger. + * + * @param data New ledger data. + * @return 0 on success, otherwise an error code defined by `Error::Type`. + */ + int set(const Variant& data); + + /** + * Update the ledger data. + * + * This method partially updates the contents of the ledger. + * + * @param data New ledger data. + * @return 0 on success, otherwise an error code defined by `Error::Type`. + */ + int merge(const Variant& data); + + /** + * Get the ledger data. + * + * @return Ledger data. + */ + Variant get() const; + + /** + * Get the last time, in milliseconds since the Unix epoch, when the ledger was synchronized with the Cloud. + * + * @return Time the ledger was synchronized with the Cloud, or 0 if the ledger was never synchronized. + */ + time64_t lastSyncedAt() const; + + /** + * Get the ledger name. + * + * @return Ledger name. + */ + const char* name() const; + + /** + * Set a callback to be invoked when the ledger data has been synchronized with the Cloud. + * + * @param callback Callback. + * @param userData User data. + */ + void onSync(OnSyncCallback callback, void* userData = nullptr); + // TODO: Add an overload taking a functor object +}; + +} // namespace particle diff --git a/wiring/inc/spark_wiring_ledger_v2.h b/wiring/inc/spark_wiring_ledger_v2.h new file mode 100644 index 0000000000..d36c0b83ab --- /dev/null +++ b/wiring/inc/spark_wiring_ledger_v2.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2023 Particle Industries, Inc. All rights 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 3 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, see . + */ + +#pragma once + +#include "spark_wiring_variant.h" +#include "spark_wiring_print.h" + +namespace particle { + +class LedgerData; + +/** + * A ledger. + * + * Use `Particle.ledger()` to create an instance of this class. + */ +class Ledger { +public: + /** + * A callback invoked when the ledger data has been synchronized with the Cloud. + * + * @param ledger Ledger instance. + * @param userData User data. + */ + typedef void (*OnSyncCallback)(Ledger ledger, void* userData); + + /** + * Default constructor. + * + * Constructs an invalid ledger instance. + */ + Ledger(); + + /** + * Set the ledger data. + * + * This method replaces the current contents of the ledger. + * + * @param data New ledger data. + * @return 0 on success, otherwise an error code defined by `Error::Type`. + */ + int set(const LedgerData& data); + + /** + * Update the ledger data. + * + * This method replaces the current contents of the ledger. + * + * @param data New ledger data. + * @return 0 on success, otherwise an error code defined by `Error::Type`. + */ + int update(const LedgerData& data); + + /** + * Get the ledger data. + * + * @return Ledger data. + */ + LedgerData get() const; + + /** + * Get the last time, in milliseconds since the Unix epoch, the ledger was synchronized with the Cloud. + * + * @return Time the ledger was synchronized with the Cloud, or 0 if the ledger was never synchronized. + */ + time64_t lastSyncedAt() const; + + /** + * Get the ledger name. + * + * @return Ledger name. + */ + const char* name() const; + + /** + * Set a callback to be invoked when the ledger data has been synchronized with the Cloud. + * + * @param callback Callback. + * @param userData User data. + */ + void onSync(OnSyncCallback callback, void* userData = nullptr); + // TODO: Add an overload taking a functor object +}; + +/** + * Ledger data. + */ +class LedgerData { +public: + /** + * Set the value of an entry. + * + * @param name Entry name. + * @param value Entry value. + * @return `true` if the value was set, otherwise `false`. + */ + bool set(const char* name, Variant value); + + /** + * Get the value of an entry. + * + * @param name Entry name. + * @return Entry value. + */ + Variant get(const char* name) const; + + /** + * Check if an entry with a given name exists. + * + * @param name Entry name. + * @return `true` if the entry exists, otherwise `false`. + */ + bool has(const char* name) const; + + /** + * Remove an entry. + * + * @param name Entry name. + * @return `true` if the entry was removed, otherwise `false`. + */ + bool remove(const char* name); + +private: + enum EntryFlag { + SET = 0x01, + REMOVED = 0x02 + }; + + struct Entry { + Variant data; + int flags; + }; + + Map entries_; +}; + +} // namespace particle diff --git a/wiring/inc/spark_wiring_map.h b/wiring/inc/spark_wiring_map.h new file mode 100644 index 0000000000..a9179d47d7 --- /dev/null +++ b/wiring/inc/spark_wiring_map.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Particle Industries, Inc. All rights 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 3 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, see . + */ + +#pragma once + +#include +#include + +#include "spark_wiring_vector.h" + +namespace particle { + +template> +class Map { +public: + typedef std::tuple Entry; + + Map() = default; + Map(const Map& map); + Map(Map&& map); + + bool set(KeyT key, ValueT value); + ValueT get(const KeyT& key, ValueT defaultValue = ValueT()) const; + ValueT take(const KeyT& key, ValueT defaultValue = ValueT()); + bool remove(const KeyT& key); + bool has(const KeyT& key) const; + + const Vector& entries() const; + + int size() const; + bool isEmpty() const; + + bool reserve(int n); + int capacity() const; + bool trimToSize(); + + ValueT& operator[](int index); + + // TODO: Iterator-based API + + Map& operator=(Map map); + + bool operator==(const Map& map); + + friend void swap(Map& map1, Map& map2); + +private: + Vector entries_; // Sorted + CompareT cmp_; +}; + +} // namespace particle diff --git a/wiring/inc/spark_wiring_variant.h b/wiring/inc/spark_wiring_variant.h new file mode 100644 index 0000000000..e82ccfc9e1 --- /dev/null +++ b/wiring/inc/spark_wiring_variant.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2023 Particle Industries, Inc. All rights 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 3 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, see . + */ + +#pragma once + +#include +#include + +#include "spark_wiring_string.h" +#include "spark_wiring_stream.h" +#include "spark_wiring_vector.h" +#include "spark_wiring_map.h" + +namespace particle { + +class Variant; + +typedef Vector VariantArray; +typedef Map VariantMap; + +class Variant { +public: + enum Type { + // INVALID, + NULL_, + BOOL, + INT, + INT64, + DOUBLE, + STRING, + ARRAY, + MAP + }; + + Variant() = default; + + Variant(bool value); + Variant(char value); + Variant(unsigned char value); + Variant(short value); + Variant(unsigned short value); + Variant(int value); + Variant(unsigned value); + Variant(long value); + Variant(unsigned long value); + Variant(long long value); + Variant(unsigned long long value); + Variant(double value); + Variant(const char* value); + Variant(String value); + Variant(VariantArray value); + Variant(VariantMap value); + + Variant(const Variant& variant); + Variant(Variant&& variant); + + Type type() const; + + // bool isValid() const; + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isInt64() const; + bool isDouble() const; + bool isString() const; + bool isArray() const; + bool isMap() const; + + bool toBool() const; + int toInt() const; + int64_t toInt64() const; + double toDouble() const; + String toString() const; + VariantArray toArray() const; + VariantMap toMap() const; + + // TODO: Add helper methods for in-place modification of array, map and string variants - + // see the Vector, Map and String classes respectively + + String toJson() const; + void toJson(Print& stream) const; + + template + T valueAs(); + + template + T& valueRef(); + + template + const T& valueRef() const; + + Variant& operator=(Variant variant); + + bool operator==(const Variant& variant) const; + bool operator<(const Variant& variant) const; + + // Conversion operators + operator bool() const; + operator char() const; + operator unsigned char() const; + operator short() const; + operator unsigned short() const; + operator int() const; + operator unsigned() const; + operator int64_t() const; + operator double() const; + operator const char*() const; + operator String() const; + operator VariantArray() const; + operator VariantMap() const; + + static Variant fromJson(const char* str); + static Variant fromJson(Stream& stream); + + friend void swap(Variant& variant1, Variant& variant2); + +private: + using VariantType = std::variant; + + VariantType v_; +}; + +} // namespace particle