forked from bblanchon/ArduinoJson
Templatized all functions using String
or std::string
* Removed `ArduinoJson::String` * Removed `JsonVariant::defaultValue<T>()` * Removed non-template `JsonObject::get()` and `JsonArray.get()` * Fixed support for `StringSumHelper` (issue #184) * Replaced `ARDUINOJSON_USE_ARDUINO_STRING` by `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_ARDUINO_STRING` (issue #378) * Added example `StringExample.ino` to show where `String` can be used
This commit is contained in:
@ -7,15 +7,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "String.hpp"
|
||||
#include "Internals/JsonBufferAllocated.hpp"
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/List.hpp"
|
||||
#include "Internals/ReferenceType.hpp"
|
||||
#include "Internals/StringFuncs.hpp"
|
||||
#include "Internals/ValueSetter.hpp"
|
||||
#include "JsonPair.hpp"
|
||||
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsReference.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
@ -40,27 +41,19 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
public Internals::List<JsonPair>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
public:
|
||||
// A meta-function that returns true if type T can be used in
|
||||
// JsonObject::set()
|
||||
template <typename T>
|
||||
struct CanSet {
|
||||
static const bool value = JsonVariant::IsConstructibleFrom<T>::value ||
|
||||
TypeTraits::IsSame<T, String&>::value ||
|
||||
TypeTraits::IsSame<T, const String&>::value;
|
||||
};
|
||||
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not use this constructor directly.
|
||||
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
|
||||
explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
JsonObjectSubscript<const char*> operator[](const char* key);
|
||||
JsonObjectSubscript<const String&> operator[](const String& key);
|
||||
template <typename TString>
|
||||
JsonObjectSubscript<TString> operator[](const TString& key);
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
JsonVariant operator[](JsonObjectKey key) const {
|
||||
return get(key);
|
||||
template <typename TString>
|
||||
JsonVariant operator[](const TString& key) const {
|
||||
return get<JsonVariant>(key);
|
||||
}
|
||||
|
||||
// Sets the specified key with the specified value.
|
||||
@ -73,67 +66,62 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
// bool set(TKey key, double value);
|
||||
// bool set(TKey key, const char* value);
|
||||
// bool set(TKey key, RawJson value);
|
||||
template <typename T>
|
||||
bool set(
|
||||
JsonObjectKey key, T value,
|
||||
typename TypeTraits::EnableIf<
|
||||
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) {
|
||||
return setNodeAt<T>(key, value);
|
||||
}
|
||||
// bool set(Key, String&);
|
||||
// bool set(Key, JsonArray&);
|
||||
// bool set(Key, JsonObject&);
|
||||
// bool set(Key, JsonVariant&);
|
||||
template <typename T>
|
||||
bool set(JsonObjectKey key, const T& value,
|
||||
typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) {
|
||||
return setNodeAt<T&>(key, const_cast<T&>(value));
|
||||
template <typename TValue, typename TString>
|
||||
bool set(const TString& key, const TValue& value) {
|
||||
// reduce the number of template function instanciation to reduce code size
|
||||
return setNodeAt<typename TypeTraits::ConstRefOrConstPtr<TString>::type,
|
||||
typename TypeTraits::ConstRefOrConstPtr<TValue>::type>(
|
||||
key, value);
|
||||
}
|
||||
// bool set(Key, float value, uint8_t decimals);
|
||||
// bool set(Key, double value, uint8_t decimals);
|
||||
template <typename TValue>
|
||||
bool set(JsonObjectKey key, TValue value, uint8_t decimals,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) {
|
||||
return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals));
|
||||
template <typename TValue, typename TString>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value,
|
||||
bool>::type
|
||||
set(const TString& key, TValue value, uint8_t decimals) {
|
||||
return set(key, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
JsonVariant get(JsonObjectKey key) const {
|
||||
node_type* node = getNodeAt(key.c_str());
|
||||
return node ? node->content.value : JsonVariant();
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type get(JsonObjectKey key) const {
|
||||
node_type* node = getNodeAt(key.c_str());
|
||||
return node ? node->content.value.as<T>() : JsonVariant::defaultValue<T>();
|
||||
template <typename TValue, typename TString>
|
||||
typename Internals::JsonVariantAs<TValue>::type get(
|
||||
const TString& key) const {
|
||||
node_type* node = getNodeAt(key);
|
||||
return node ? node->content.value.as<TValue>()
|
||||
: Internals::JsonVariantDefault<TValue>::get();
|
||||
}
|
||||
|
||||
// Checks the type of the value associated with the specified key.
|
||||
template <typename T>
|
||||
bool is(JsonObjectKey key) const {
|
||||
node_type* node = getNodeAt(key.c_str());
|
||||
return node ? node->content.value.is<T>() : false;
|
||||
template <typename TValue, typename TString>
|
||||
bool is(const TString& key) const {
|
||||
node_type* node = getNodeAt(key);
|
||||
return node ? node->content.value.is<TValue>() : false;
|
||||
}
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
||||
JsonArray& createNestedArray(JsonObjectKey key);
|
||||
template <typename TString>
|
||||
JsonArray& createNestedArray(const TString& key);
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
||||
JsonObject& createNestedObject(JsonObjectKey key);
|
||||
template <typename TString>
|
||||
JsonObject& createNestedObject(const TString& key);
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
bool containsKey(JsonObjectKey key) const {
|
||||
return getNodeAt(key.c_str()) != NULL;
|
||||
template <typename TString>
|
||||
bool containsKey(const TString& key) const {
|
||||
return getNodeAt(key) != NULL;
|
||||
}
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
void remove(JsonObjectKey key) {
|
||||
removeNode(getNodeAt(key.c_str()));
|
||||
template <typename TString>
|
||||
void remove(const TString& key) {
|
||||
removeNode(getNodeAt(key));
|
||||
}
|
||||
|
||||
// Returns a reference an invalid JsonObject.
|
||||
@ -146,37 +134,35 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
|
||||
private:
|
||||
// Returns the list node that matches the specified key.
|
||||
node_type* getNodeAt(const char* key) const {
|
||||
template <typename TString>
|
||||
node_type* getNodeAt(const TString& key) const {
|
||||
// reduce the number of template function instanciation to reduce code size
|
||||
return getNodeAtImpl<
|
||||
typename TypeTraits::ConstRefOrConstPtr<TString>::type>(key);
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
node_type* getNodeAtImpl(TStringRef key) const {
|
||||
for (node_type* node = _firstNode; node; node = node->next) {
|
||||
if (!strcmp(node->content.key, key)) return node;
|
||||
if (Internals::StringFuncs<TStringRef>::equals(key, node->content.key))
|
||||
return node;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool setNodeAt(JsonObjectKey key, T value) {
|
||||
node_type* node = getNodeAt(key.c_str());
|
||||
template <typename TStringRef, typename TValueRef>
|
||||
bool setNodeAt(TStringRef key, TValueRef value) {
|
||||
node_type* node = getNodeAtImpl<TStringRef>(key);
|
||||
if (!node) {
|
||||
node = addNewNode();
|
||||
if (!node || !setNodeKey(node, key)) return false;
|
||||
}
|
||||
return setNodeValue<T>(node, value);
|
||||
}
|
||||
if (!node) return false;
|
||||
|
||||
bool setNodeKey(node_type* node, JsonObjectKey key) {
|
||||
if (key.needs_copy()) {
|
||||
node->content.key = _buffer->strdup(key.c_str());
|
||||
if (node->content.key == NULL) return false;
|
||||
} else {
|
||||
node->content.key = key.c_str();
|
||||
bool key_ok = Internals::ValueSetter<TStringRef>::set(
|
||||
_buffer, node->content.key, key);
|
||||
if (!key_ok) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool setNodeValue(node_type* node, T value) {
|
||||
node->content.value = value;
|
||||
return true;
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content.value,
|
||||
value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user