mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-15 19:42:12 +02:00
Changed the rules of string duplication (fixes #658)
This commit is contained in:
16
CHANGELOG.md
16
CHANGELOG.md
@ -1,6 +1,22 @@
|
|||||||
ArduinoJson: change log
|
ArduinoJson: change log
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
HEAD
|
||||||
|
----
|
||||||
|
|
||||||
|
* Changed the rules of string duplication (issue #658)
|
||||||
|
|
||||||
|
> ### New rules for string duplication
|
||||||
|
>
|
||||||
|
> | type | duplication |
|
||||||
|
> |:-------------|:------------|
|
||||||
|
> | const char* | no |
|
||||||
|
> | char* | ~~no~~ yes |
|
||||||
|
> | String | yes |
|
||||||
|
> | std::string | yes |
|
||||||
|
>
|
||||||
|
> These new rules make `JsonBuffer::strdup()` useless.
|
||||||
|
|
||||||
v5.12.0
|
v5.12.0
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
34
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
34
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../JsonBuffer.hpp"
|
||||||
|
#include "../JsonVariant.hpp"
|
||||||
|
#include "../StringTraits/StringTraits.hpp"
|
||||||
|
#include "../TypeTraits/EnableIf.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
|
||||||
|
template <typename Source, typename Enable = void>
|
||||||
|
struct ValueSaver {
|
||||||
|
template <typename Destination>
|
||||||
|
static bool save(JsonBuffer*, Destination& destination, Source source) {
|
||||||
|
destination = source;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
struct ValueSaver<Source, typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsString<Source>::value>::type> {
|
||||||
|
template <typename Destination>
|
||||||
|
static bool save(JsonBuffer* buffer, Destination& destination,
|
||||||
|
Source source) {
|
||||||
|
return StringTraits<Source>::save(source, destination, buffer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,48 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2018
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../JsonBuffer.hpp"
|
|
||||||
#include "../JsonVariant.hpp"
|
|
||||||
#include "../StringTraits/StringTraits.hpp"
|
|
||||||
#include "../TypeTraits/EnableIf.hpp"
|
|
||||||
|
|
||||||
namespace ArduinoJson {
|
|
||||||
namespace Internals {
|
|
||||||
|
|
||||||
template <typename TSourceRef, typename Enable = void>
|
|
||||||
struct ValueSetter {
|
|
||||||
template <typename TDestination>
|
|
||||||
static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
|
|
||||||
destination = source;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TSourceRef>
|
|
||||||
struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<StringTraits<
|
|
||||||
TSourceRef>::should_duplicate>::type> {
|
|
||||||
template <typename TDestination>
|
|
||||||
static bool set(JsonBuffer* buffer, TDestination& destination,
|
|
||||||
TSourceRef source) {
|
|
||||||
const char* copy = buffer->strdup(source);
|
|
||||||
if (!copy) return false;
|
|
||||||
destination = copy;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TSourceRef>
|
|
||||||
struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<!StringTraits<
|
|
||||||
TSourceRef>::should_duplicate>::type> {
|
|
||||||
template <typename TDestination>
|
|
||||||
static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
|
|
||||||
// unsigned char* -> char*
|
|
||||||
destination = reinterpret_cast<const char*>(source);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,7 +7,7 @@
|
|||||||
#include "Data/JsonBufferAllocated.hpp"
|
#include "Data/JsonBufferAllocated.hpp"
|
||||||
#include "Data/List.hpp"
|
#include "Data/List.hpp"
|
||||||
#include "Data/ReferenceType.hpp"
|
#include "Data/ReferenceType.hpp"
|
||||||
#include "Data/ValueSetter.hpp"
|
#include "Data/ValueSaver.hpp"
|
||||||
#include "JsonVariant.hpp"
|
#include "JsonVariant.hpp"
|
||||||
#include "Serialization/JsonPrintable.hpp"
|
#include "Serialization/JsonPrintable.hpp"
|
||||||
#include "StringTraits/StringTraits.hpp"
|
#include "StringTraits/StringTraits.hpp"
|
||||||
@ -56,19 +56,17 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
//
|
//
|
||||||
// bool add(TValue);
|
// bool add(TValue);
|
||||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type add(
|
bool add(const T &value) {
|
||||||
const T &value) {
|
|
||||||
return add_impl<const T &>(value);
|
return add_impl<const T &>(value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool add(TValue);
|
// bool add(TValue);
|
||||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
// TValue = char*, const char*, const FlashStringHelper*
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool add(const T *value) {
|
bool add(T *value) {
|
||||||
return add_impl<const T *>(value);
|
return add_impl<T *>(value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool add(TValue value, uint8_t decimals);
|
// bool add(TValue value, uint8_t decimals);
|
||||||
@ -81,21 +79,19 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
|
|
||||||
// Sets the value at specified index.
|
// Sets the value at specified index.
|
||||||
//
|
//
|
||||||
// bool add(size_t index, TValue);
|
// bool add(size_t index, const TValue&);
|
||||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type set(
|
bool set(size_t index, const T &value) {
|
||||||
size_t index, const T &value) {
|
|
||||||
return set_impl<const T &>(index, value);
|
return set_impl<const T &>(index, value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool add(size_t index, TValue);
|
// bool add(size_t index, TValue);
|
||||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
// TValue = char*, const char*, const FlashStringHelper*
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool set(size_t index, const T *value) {
|
bool set(size_t index, T *value) {
|
||||||
return set_impl<const T *>(index, value);
|
return set_impl<T *>(index, value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(size_t index, TValue value, uint8_t decimals);
|
// bool set(size_t index, TValue value, uint8_t decimals);
|
||||||
@ -208,14 +204,14 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
bool set_impl(size_t index, TValueRef value) {
|
bool set_impl(size_t index, TValueRef value) {
|
||||||
iterator it = begin() += index;
|
iterator it = begin() += index;
|
||||||
if (it == end()) return false;
|
if (it == end()) return false;
|
||||||
return Internals::ValueSetter<TValueRef>::set(_buffer, *it, value);
|
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValueRef>
|
template <typename TValueRef>
|
||||||
bool add_impl(TValueRef value) {
|
bool add_impl(TValueRef value) {
|
||||||
iterator it = Internals::List<JsonVariant>::add();
|
iterator it = Internals::List<JsonVariant>::add();
|
||||||
if (it == end()) return false;
|
if (it == end()) return false;
|
||||||
return Internals::ValueSetter<TValueRef>::set(_buffer, *it, value);
|
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,10 +25,9 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
|||||||
|
|
||||||
// Replaces the value
|
// Replaces the value
|
||||||
//
|
//
|
||||||
// operator=(TValue)
|
// operator=(const TValue&)
|
||||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
|
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
|
||||||
_array.set(_index, src);
|
_array.set(_index, src);
|
||||||
@ -36,9 +35,9 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
// operator=(TValue)
|
// operator=(TValue)
|
||||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
// TValue = char*, const char*, const FlashStringHelper*
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE JsonArraySubscript& operator=(const T* src) {
|
FORCE_INLINE JsonArraySubscript& operator=(T* src) {
|
||||||
_array.set(_index, src);
|
_array.set(_index, src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -59,19 +58,18 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
|||||||
|
|
||||||
// Replaces the value
|
// Replaces the value
|
||||||
//
|
//
|
||||||
// bool set(TValue)
|
// bool set(const TValue&)
|
||||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE bool set(const TValue& value) {
|
FORCE_INLINE bool set(const TValue& value) {
|
||||||
return _array.set(_index, value);
|
return _array.set(_index, value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(TValue)
|
// bool set(TValue)
|
||||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
// TValue = char*, const char*, const FlashStringHelper*
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE bool set(const TValue* value) {
|
FORCE_INLINE bool set(TValue* value) {
|
||||||
return _array.set(_index, value);
|
return _array.set(_index, value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "Data/JsonBufferAllocated.hpp"
|
#include "Data/JsonBufferAllocated.hpp"
|
||||||
#include "Data/List.hpp"
|
#include "Data/List.hpp"
|
||||||
#include "Data/ReferenceType.hpp"
|
#include "Data/ReferenceType.hpp"
|
||||||
#include "Data/ValueSetter.hpp"
|
#include "Data/ValueSaver.hpp"
|
||||||
#include "JsonPair.hpp"
|
#include "JsonPair.hpp"
|
||||||
#include "Serialization/JsonPrintable.hpp"
|
#include "Serialization/JsonPrintable.hpp"
|
||||||
#include "StringTraits/StringTraits.hpp"
|
#include "StringTraits/StringTraits.hpp"
|
||||||
@ -50,17 +50,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// JsonObjectSubscript operator[](TKey)
|
// JsonObjectSubscript operator[](TKey)
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
JsonObjectSubscript<const TString&> operator[](const TString& key) {
|
||||||
JsonObjectSubscript<const TString&> >::type
|
|
||||||
operator[](const TString& key) {
|
|
||||||
return JsonObjectSubscript<const TString&>(*this, key);
|
return JsonObjectSubscript<const TString&>(*this, key);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// JsonObjectSubscript operator[](TKey)
|
// JsonObjectSubscript operator[](TKey)
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
JsonObjectSubscript<const TString*> operator[](const TString* key) {
|
JsonObjectSubscript<TString*> operator[](TString* key) {
|
||||||
return JsonObjectSubscript<const TString*>(*this, key);
|
return JsonObjectSubscript<TString*>(*this, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the value associated with the specified key.
|
// Gets the value associated with the specified key.
|
||||||
@ -68,10 +66,8 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// const JsonObjectSubscript operator[](TKey) const;
|
// const JsonObjectSubscript operator[](TKey) const;
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename TypeTraits::EnableIf<
|
const JsonObjectSubscript<const TString&> operator[](
|
||||||
!TypeTraits::IsArray<TString>::value,
|
const TString& key) const {
|
||||||
const JsonObjectSubscript<const TString&> >::type
|
|
||||||
operator[](const TString& key) const {
|
|
||||||
return JsonObjectSubscript<const TString&>(*const_cast<JsonObject*>(this),
|
return JsonObjectSubscript<const TString&>(*const_cast<JsonObject*>(this),
|
||||||
key);
|
key);
|
||||||
}
|
}
|
||||||
@ -79,10 +75,8 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// const JsonObjectSubscript operator[](TKey) const;
|
// const JsonObjectSubscript operator[](TKey) const;
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
const JsonObjectSubscript<const TString*> operator[](
|
const JsonObjectSubscript<TString*> operator[](TString* key) const {
|
||||||
const TString* key) const {
|
return JsonObjectSubscript<TString*>(*const_cast<JsonObject*>(this), key);
|
||||||
return JsonObjectSubscript<const TString*>(*const_cast<JsonObject*>(this),
|
|
||||||
key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the specified key with the specified value.
|
// Sets the specified key with the specified value.
|
||||||
@ -90,43 +84,35 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// bool set(TKey, TValue);
|
// bool set(TKey, TValue);
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value &&
|
bool set(const TString& key, const TValue& value) {
|
||||||
!TypeTraits::IsArray<TValue>::value,
|
|
||||||
bool>::type
|
|
||||||
set(const TString& key, const TValue& value) {
|
|
||||||
return set_impl<const TString&, const TValue&>(key, value);
|
return set_impl<const TString&, const TValue&>(key, value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(TKey, TValue);
|
// bool set(TKey, TValue);
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
// TValue = char*, const char*, const FlashStringHelper*
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
bool set(const TString& key, TValue* value) {
|
||||||
bool>::type
|
return set_impl<const TString&, TValue*>(key, value);
|
||||||
set(const TString& key, const TValue* value) {
|
|
||||||
return set_impl<const TString&, const TValue*>(key, value);
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(TKey, TValue);
|
// bool set(TKey, const TValue&);
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, const FlashStringHelper*
|
||||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, bool>::type
|
bool set(TString* key, const TValue& value) {
|
||||||
set(const TString* key, const TValue& value) {
|
return set_impl<TString*, const TValue&>(key, value);
|
||||||
return set_impl<const TString*, const TValue&>(key, value);
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(TKey, TValue);
|
// bool set(TKey, TValue);
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, const FlashStringHelper*
|
||||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
// TValue = char*, const char*, const FlashStringHelper*
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
bool set(const TString* key, const TValue* value) {
|
bool set(TString* key, TValue* value) {
|
||||||
return set_impl<const TString*, const TValue*>(key, value);
|
return set_impl<TString*, TValue*>(key, value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(TKey, TValue, uint8_t decimals);
|
// bool set(TKey, TValue, uint8_t decimals);
|
||||||
@ -134,8 +120,7 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// TValue = float, double
|
// TValue = float, double
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
DEPRECATED("Second argument is not supported anymore")
|
DEPRECATED("Second argument is not supported anymore")
|
||||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value &&
|
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value,
|
||||||
!TypeTraits::IsArray<TString>::value,
|
|
||||||
bool>::type
|
bool>::type
|
||||||
set(const TString& key, TValue value, uint8_t) {
|
set(const TString& key, TValue value, uint8_t) {
|
||||||
return set_impl<const TString&, const JsonVariant&>(key,
|
return set_impl<const TString&, const JsonVariant&>(key,
|
||||||
@ -143,41 +128,35 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(TKey, TValue, uint8_t decimals);
|
// bool set(TKey, TValue, uint8_t decimals);
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, const FlashStringHelper*
|
||||||
// TValue = float, double
|
// TValue = float, double
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
DEPRECATED("Second argument is not supported anymore")
|
DEPRECATED("Second argument is not supported anymore")
|
||||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value,
|
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value,
|
||||||
bool>::type
|
bool>::type
|
||||||
set(const TString* key, TValue value, uint8_t) {
|
set(TString* key, TValue value, uint8_t) {
|
||||||
return set_impl<const TString*, const JsonVariant&>(key,
|
return set_impl<TString*, const JsonVariant&>(key, JsonVariant(value));
|
||||||
JsonVariant(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the value associated with the specified key.
|
// Gets the value associated with the specified key.
|
||||||
//
|
//
|
||||||
// TValue get<TValue>(TKey);
|
// TValue get<TValue>(TKey) const;
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
// TValue = bool, char, long, int, short, float, double,
|
// TValue = bool, char, long, int, short, float, double,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
typename TypeTraits::EnableIf<
|
typename Internals::JsonVariantAs<TValue>::type get(
|
||||||
!TypeTraits::IsArray<TString>::value,
|
const TString& key) const {
|
||||||
typename Internals::JsonVariantAs<TValue>::type>::type
|
|
||||||
get(const TString& key) const {
|
|
||||||
return get_impl<const TString&, TValue>(key);
|
return get_impl<const TString&, TValue>(key);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// TValue get<TValue>(TKey);
|
// TValue get<TValue>(TKey) const;
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, const FlashStringHelper*
|
||||||
// TValue = bool, char, long, int, short, float, double,
|
// TValue = bool, char, long, int, short, float, double,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
typename Internals::JsonVariantAs<TValue>::type get(
|
typename Internals::JsonVariantAs<TValue>::type get(TString* key) const {
|
||||||
const TString* key) const {
|
return get_impl<TString*, TValue>(key);
|
||||||
return get_impl<const TString*, TValue>(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks the type of the value associated with the specified key.
|
// Checks the type of the value associated with the specified key.
|
||||||
@ -186,23 +165,19 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// bool is<TValue>(TKey) const;
|
// bool is<TValue>(TKey) const;
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
// TValue = bool, char, long, int, short, float, double,
|
// TValue = bool, char, long, int, short, float, double,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
bool is(const TString& key) const {
|
||||||
bool>::type
|
|
||||||
is(const TString& key) const {
|
|
||||||
return is_impl<const TString&, TValue>(key);
|
return is_impl<const TString&, TValue>(key);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool is<TValue>(TKey) const;
|
// bool is<TValue>(TKey) const;
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, const FlashStringHelper*
|
||||||
// TValue = bool, char, long, int, short, float, double,
|
// TValue = bool, char, long, int, short, float, double,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename TValue, typename TString>
|
template <typename TValue, typename TString>
|
||||||
bool is(const TString* key) const {
|
bool is(TString* key) const {
|
||||||
return is_impl<const TString*, TValue>(key);
|
return is_impl<TString*, TValue>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates and adds a JsonArray.
|
// Creates and adds a JsonArray.
|
||||||
@ -210,16 +185,14 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// JsonArray& createNestedArray(TKey);
|
// JsonArray& createNestedArray(TKey);
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
JsonArray& createNestedArray(const TString& key) {
|
||||||
JsonArray&>::type
|
|
||||||
createNestedArray(const TString& key) {
|
|
||||||
return createNestedArray_impl<const TString&>(key);
|
return createNestedArray_impl<const TString&>(key);
|
||||||
}
|
}
|
||||||
// JsonArray& createNestedArray(TKey);
|
// JsonArray& createNestedArray(TKey);
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
JsonArray& createNestedArray(const TString* key) {
|
JsonArray& createNestedArray(TString* key) {
|
||||||
return createNestedArray_impl<const TString*>(key);
|
return createNestedArray_impl<TString*>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates and adds a JsonObject.
|
// Creates and adds a JsonObject.
|
||||||
@ -227,17 +200,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// JsonObject& createNestedObject(TKey);
|
// JsonObject& createNestedObject(TKey);
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
JsonObject& createNestedObject(const TString& key) {
|
||||||
JsonObject&>::type
|
|
||||||
createNestedObject(const TString& key) {
|
|
||||||
return createNestedObject_impl<const TString&>(key);
|
return createNestedObject_impl<const TString&>(key);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// JsonObject& createNestedObject(TKey);
|
// JsonObject& createNestedObject(TKey);
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
JsonObject& createNestedObject(const TString* key) {
|
JsonObject& createNestedObject(TString* key) {
|
||||||
return createNestedObject_impl<const TString*>(key);
|
return createNestedObject_impl<TString*>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tells weither the specified key is present and associated with a value.
|
// Tells weither the specified key is present and associated with a value.
|
||||||
@ -245,17 +216,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// bool containsKey(TKey);
|
// bool containsKey(TKey);
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
bool containsKey(const TString& key) const {
|
||||||
bool>::type
|
|
||||||
containsKey(const TString& key) const {
|
|
||||||
return findKey<const TString&>(key) != end();
|
return findKey<const TString&>(key) != end();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool containsKey(TKey);
|
// bool containsKey(TKey);
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
bool containsKey(const TString* key) const {
|
bool containsKey(TString* key) const {
|
||||||
return findKey<const TString*>(key) != end();
|
return findKey<TString*>(key) != end();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the specified key and the associated value.
|
// Removes the specified key and the associated value.
|
||||||
@ -263,17 +232,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
// void remove(TKey);
|
// void remove(TKey);
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
void remove(const TString& key) {
|
||||||
void>::type
|
|
||||||
remove(const TString& key) {
|
|
||||||
remove(findKey<const TString&>(key));
|
remove(findKey<const TString&>(key));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// void remove(TKey);
|
// void remove(TKey);
|
||||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
void remove(const TString* key) {
|
void remove(TString* key) {
|
||||||
remove(findKey<const TString*>(key));
|
remove(findKey<TString*>(key));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// void remove(iterator)
|
// void remove(iterator)
|
||||||
@ -318,10 +285,10 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
if (it == end()) return false;
|
if (it == end()) return false;
|
||||||
|
|
||||||
bool key_ok =
|
bool key_ok =
|
||||||
Internals::ValueSetter<TStringRef>::set(_buffer, it->key, key);
|
Internals::ValueSaver<TStringRef>::save(_buffer, it->key, key);
|
||||||
if (!key_ok) return false;
|
if (!key_ok) return false;
|
||||||
}
|
}
|
||||||
return Internals::ValueSetter<TValueRef>::set(_buffer, it->value, value);
|
return Internals::ValueSaver<TValueRef>::save(_buffer, it->value, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TStringRef, typename TValue>
|
template <typename TStringRef, typename TValue>
|
||||||
|
@ -31,10 +31,9 @@ class JsonObjectSubscript
|
|||||||
|
|
||||||
// Set the specified value
|
// Set the specified value
|
||||||
//
|
//
|
||||||
// operator=(TValue);
|
// operator=(const TValue&);
|
||||||
// TValue = bool, char, long, int, short, float, double,
|
// TValue = bool, char, long, int, short, float, double,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE
|
FORCE_INLINE
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value,
|
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value,
|
||||||
@ -45,7 +44,7 @@ class JsonObjectSubscript
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
// operator=(TValue);
|
// operator=(TValue);
|
||||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
// TValue = char*, const char*, const FlashStringHelper*
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE this_type& operator=(const TValue* src) {
|
FORCE_INLINE this_type& operator=(const TValue* src) {
|
||||||
_object.set(_key, src);
|
_object.set(_key, src);
|
||||||
@ -68,10 +67,9 @@ class JsonObjectSubscript
|
|||||||
|
|
||||||
// Sets the specified value.
|
// Sets the specified value.
|
||||||
//
|
//
|
||||||
// bool set(TValue);
|
// bool set(const TValue&);
|
||||||
// TValue = bool, char, long, int, short, float, double, RawJson, JsonVariant,
|
// TValue = bool, char, long, int, short, float, double, RawJson, JsonVariant,
|
||||||
// const std::string&, const String&,
|
// std::string, String, JsonArray, JsonObject
|
||||||
// const JsonArray&, const JsonObject&
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE
|
FORCE_INLINE
|
||||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value,
|
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value,
|
||||||
@ -81,7 +79,7 @@ class JsonObjectSubscript
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(TValue);
|
// bool set(TValue);
|
||||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
// TValue = char*, const char, const FlashStringHelper*
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE bool set(const TValue* value) {
|
FORCE_INLINE bool set(const TValue* value) {
|
||||||
return _object.set(_key, value);
|
return _object.set(_key, value);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#ifdef _MSC_VER // Visual Studio
|
#ifdef _MSC_VER // Visual Studio
|
||||||
|
|
||||||
#define FORCE_INLINE __forceinline
|
#define FORCE_INLINE // __forceinline causes C4714 when returning std::string
|
||||||
#define NO_INLINE __declspec(noinline)
|
#define NO_INLINE __declspec(noinline)
|
||||||
#define DEPRECATED(msg) __declspec(deprecated(msg))
|
#define DEPRECATED(msg) __declspec(deprecated(msg))
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ struct CharPointerTraits {
|
|||||||
return strcmp(reinterpret_cast<const char*>(str), expected) == 0;
|
return strcmp(reinterpret_cast<const char*>(str), expected) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove
|
||||||
template <typename Buffer>
|
template <typename Buffer>
|
||||||
static char* duplicate(const TChar* str, Buffer* buffer) {
|
static char* duplicate(const TChar* str, Buffer* buffer) {
|
||||||
if (!str) return NULL;
|
if (!str) return NULL;
|
||||||
@ -44,12 +45,46 @@ struct CharPointerTraits {
|
|||||||
|
|
||||||
static const bool has_append = false;
|
static const bool has_append = false;
|
||||||
static const bool has_equals = true;
|
static const bool has_equals = true;
|
||||||
static const bool should_duplicate = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const char*, const unsigned char*, const signed char*
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
struct StringTraits<TChar*, typename TypeTraits::EnableIf<
|
struct StringTraits<TChar*, typename TypeTraits::EnableIf<
|
||||||
TypeTraits::IsChar<TChar>::value>::type>
|
TypeTraits::IsChar<TChar>::value &&
|
||||||
: CharPointerTraits<TChar> {};
|
TypeTraits::IsConst<TChar>::value>::type>
|
||||||
|
: CharPointerTraits<TChar> {
|
||||||
|
// Just save the pointer
|
||||||
|
template <typename Buffer, typename Destination>
|
||||||
|
static typename TypeTraits::EnableIf<TypeTraits::IsConst<TChar>::value,
|
||||||
|
bool>::type
|
||||||
|
save(const TChar* source, Destination& dest, Buffer*) {
|
||||||
|
dest = reinterpret_cast<const char*>(source);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// char*, unsigned char*, signed char*
|
||||||
|
template <typename TChar>
|
||||||
|
struct StringTraits<TChar*, typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsChar<TChar>::value &&
|
||||||
|
!TypeTraits::IsConst<TChar>::value>::type>
|
||||||
|
: CharPointerTraits<TChar> {
|
||||||
|
// Make a copy of the string
|
||||||
|
template <typename Buffer, typename Destination>
|
||||||
|
static typename TypeTraits::EnableIf<!TypeTraits::IsConst<TChar>::value,
|
||||||
|
bool>::type
|
||||||
|
save(const TChar* source, Destination& dest, Buffer* buffer) {
|
||||||
|
if (source) {
|
||||||
|
size_t size = strlen(reinterpret_cast<const char*>(source)) + 1;
|
||||||
|
void* dup = buffer->alloc(size);
|
||||||
|
if (!dup) return false;
|
||||||
|
memcpy(dup, source, size);
|
||||||
|
dest = reinterpret_cast<const char*>(dup);
|
||||||
|
} else {
|
||||||
|
dest = reinterpret_cast<const char*>(source);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ struct StringTraits<const __FlashStringHelper*, void> {
|
|||||||
return strcmp_P(expected, (const char*)str) == 0;
|
return strcmp_P(expected, (const char*)str) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove
|
||||||
template <typename Buffer>
|
template <typename Buffer>
|
||||||
static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
|
static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
|
||||||
if (!str) return NULL;
|
if (!str) return NULL;
|
||||||
@ -43,9 +44,22 @@ struct StringTraits<const __FlashStringHelper*, void> {
|
|||||||
return static_cast<char*>(dup);
|
return static_cast<char*>(dup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Buffer, typename Destination>
|
||||||
|
static bool save(const __FlashStringHelper* source, Destination& dest,
|
||||||
|
Buffer* buffer) {
|
||||||
|
if (source) {
|
||||||
|
size_t size = strlen_P((const char*)source) + 1;
|
||||||
|
void* dup = buffer->alloc(size);
|
||||||
|
if (dup != NULL) memcpy_P(dup, (const char*)source, size);
|
||||||
|
dest = reinterpret_cast<const char*>(dup);
|
||||||
|
} else {
|
||||||
|
dest = reinterpret_cast<const char*>(source);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static const bool has_append = false;
|
static const bool has_append = false;
|
||||||
static const bool has_equals = true;
|
static const bool has_equals = true;
|
||||||
static const bool should_duplicate = true;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ namespace Internals {
|
|||||||
|
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
struct StdStringTraits {
|
struct StdStringTraits {
|
||||||
|
// TODO: remove
|
||||||
template <typename Buffer>
|
template <typename Buffer>
|
||||||
static char* duplicate(const TString& str, Buffer* buffer) {
|
static char* duplicate(const TString& str, Buffer* buffer) {
|
||||||
if (!str.c_str()) return NULL; // <- Arduino string can return NULL
|
if (!str.c_str()) return NULL; // <- Arduino string can return NULL
|
||||||
@ -28,6 +29,21 @@ struct StdStringTraits {
|
|||||||
return static_cast<char*>(dup);
|
return static_cast<char*>(dup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Buffer, typename Destination>
|
||||||
|
static bool save(const TString& str, Destination& dest, Buffer* buffer) {
|
||||||
|
// Arduino's String::c_str() can return NULL
|
||||||
|
if (str.c_str()) {
|
||||||
|
size_t size = str.length() + 1;
|
||||||
|
void* dup = buffer->alloc(size);
|
||||||
|
if (!dup) return false;
|
||||||
|
memcpy(dup, str.c_str(), size);
|
||||||
|
dest = reinterpret_cast<const char*>(dup);
|
||||||
|
} else {
|
||||||
|
dest = str.c_str();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
struct Reader : CharPointerTraits<char>::Reader {
|
struct Reader : CharPointerTraits<char>::Reader {
|
||||||
Reader(const TString& str) : CharPointerTraits<char>::Reader(str.c_str()) {}
|
Reader(const TString& str) : CharPointerTraits<char>::Reader(str.c_str()) {}
|
||||||
};
|
};
|
||||||
@ -46,7 +62,6 @@ struct StdStringTraits {
|
|||||||
|
|
||||||
static const bool has_append = true;
|
static const bool has_append = true;
|
||||||
static const bool has_equals = true;
|
static const bool has_equals = true;
|
||||||
static const bool should_duplicate = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "../TypeTraits/EnableIf.hpp"
|
#include "../TypeTraits/EnableIf.hpp"
|
||||||
#include "../TypeTraits/IsBaseOf.hpp"
|
#include "../TypeTraits/IsBaseOf.hpp"
|
||||||
#include "../TypeTraits/IsChar.hpp"
|
#include "../TypeTraits/IsChar.hpp"
|
||||||
|
#include "../TypeTraits/IsConst.hpp"
|
||||||
#include "../TypeTraits/RemoveReference.hpp"
|
#include "../TypeTraits/RemoveReference.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
@ -13,6 +13,7 @@ add_executable(JsonArrayTests
|
|||||||
printTo.cpp
|
printTo.cpp
|
||||||
remove.cpp
|
remove.cpp
|
||||||
set.cpp
|
set.cpp
|
||||||
|
size.cpp
|
||||||
subscript.cpp
|
subscript.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,11 +9,6 @@ TEST_CASE("JsonArray::add()") {
|
|||||||
DynamicJsonBuffer _jsonBuffer;
|
DynamicJsonBuffer _jsonBuffer;
|
||||||
JsonArray& _array = _jsonBuffer.createArray();
|
JsonArray& _array = _jsonBuffer.createArray();
|
||||||
|
|
||||||
SECTION("SizeIncreased_WhenValuesAreAdded") {
|
|
||||||
_array.add("hello");
|
|
||||||
REQUIRE(1U == _array.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("int") {
|
SECTION("int") {
|
||||||
_array.add(123);
|
_array.add(123);
|
||||||
REQUIRE(123 == _array[0].as<int>());
|
REQUIRE(123 == _array[0].as<int>());
|
||||||
@ -38,7 +33,7 @@ TEST_CASE("JsonArray::add()") {
|
|||||||
SECTION("const char*") {
|
SECTION("const char*") {
|
||||||
const char* str = "hello";
|
const char* str = "hello";
|
||||||
_array.add(str);
|
_array.add(str);
|
||||||
REQUIRE(str == _array[0].as<const char*>());
|
REQUIRE(str == _array[0].as<std::string>());
|
||||||
REQUIRE(_array[0].is<const char*>());
|
REQUIRE(_array[0].is<const char*>());
|
||||||
REQUIRE_FALSE(_array[0].is<int>());
|
REQUIRE_FALSE(_array[0].is<int>());
|
||||||
}
|
}
|
||||||
@ -82,4 +77,22 @@ TEST_CASE("JsonArray::add()") {
|
|||||||
|
|
||||||
REQUIRE(str == _array[0]);
|
REQUIRE(str == _array[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("should not duplicate const char*") {
|
||||||
|
_array.add("world");
|
||||||
|
const size_t expectedSize = JSON_ARRAY_SIZE(1);
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate char*") {
|
||||||
|
_array.add(const_cast<char*>("world"));
|
||||||
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate std::string") {
|
||||||
|
_array.add(std::string("world"));
|
||||||
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,6 @@ TEST_CASE("JsonArray::set()") {
|
|||||||
JsonArray& _array = _jsonBuffer.createArray();
|
JsonArray& _array = _jsonBuffer.createArray();
|
||||||
_array.add(0);
|
_array.add(0);
|
||||||
|
|
||||||
SECTION("SizeIsUnchanged") {
|
|
||||||
_array.set(0, "hello");
|
|
||||||
REQUIRE(1U == _array.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("int") {
|
SECTION("int") {
|
||||||
_array.set(0, 123);
|
_array.set(0, 123);
|
||||||
REQUIRE(123 == _array[0].as<int>());
|
REQUIRE(123 == _array[0].as<int>());
|
||||||
@ -82,4 +77,22 @@ TEST_CASE("JsonArray::set()") {
|
|||||||
|
|
||||||
REQUIRE_THAT(_array[0].as<char*>(), Equals("hello"));
|
REQUIRE_THAT(_array[0].as<char*>(), Equals("hello"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("should not duplicate const char*") {
|
||||||
|
_array.set(0, "world");
|
||||||
|
const size_t expectedSize = JSON_ARRAY_SIZE(1);
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate char*") {
|
||||||
|
_array.set(0, const_cast<char*>("world"));
|
||||||
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate std::string") {
|
||||||
|
_array.set(0, std::string("world"));
|
||||||
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
35
test/JsonArray/size.cpp
Normal file
35
test/JsonArray/size.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("JsonArray::size()") {
|
||||||
|
DynamicJsonBuffer _jsonBuffer;
|
||||||
|
JsonArray& _array = _jsonBuffer.createArray();
|
||||||
|
|
||||||
|
SECTION("increases after add()") {
|
||||||
|
_array.add("hello");
|
||||||
|
REQUIRE(1U == _array.size());
|
||||||
|
|
||||||
|
_array.add("world");
|
||||||
|
REQUIRE(2U == _array.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("remains the same after set()") {
|
||||||
|
_array.add("hello");
|
||||||
|
REQUIRE(1U == _array.size());
|
||||||
|
|
||||||
|
_array.set(0, "hello");
|
||||||
|
REQUIRE(1U == _array.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("remains the same after assigment") {
|
||||||
|
_array.add("hello");
|
||||||
|
REQUIRE(1U == _array.size());
|
||||||
|
|
||||||
|
_array[0] = "hello";
|
||||||
|
REQUIRE(1U == _array.size());
|
||||||
|
}
|
||||||
|
}
|
@ -11,11 +11,6 @@ TEST_CASE("JsonArray::operator[]") {
|
|||||||
JsonArray& _array = _jsonBuffer.createArray();
|
JsonArray& _array = _jsonBuffer.createArray();
|
||||||
_array.add(0);
|
_array.add(0);
|
||||||
|
|
||||||
SECTION("SizeIsUnchanged") {
|
|
||||||
_array[0] = "hello";
|
|
||||||
REQUIRE(1U == _array.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("int") {
|
SECTION("int") {
|
||||||
_array[0] = 123;
|
_array[0] = 123;
|
||||||
REQUIRE(123 == _array[0].as<int>());
|
REQUIRE(123 == _array[0].as<int>());
|
||||||
@ -103,4 +98,22 @@ TEST_CASE("JsonArray::operator[]") {
|
|||||||
|
|
||||||
REQUIRE(str == _array[0]);
|
REQUIRE(str == _array[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("should not duplicate const char*") {
|
||||||
|
_array[0] = "world";
|
||||||
|
const size_t expectedSize = JSON_ARRAY_SIZE(1);
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate char*") {
|
||||||
|
_array[0] = const_cast<char*>("world");
|
||||||
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate std::string") {
|
||||||
|
_array[0] = std::string("world");
|
||||||
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ add_executable(JsonObjectTests
|
|||||||
printTo.cpp
|
printTo.cpp
|
||||||
remove.cpp
|
remove.cpp
|
||||||
set.cpp
|
set.cpp
|
||||||
|
size.cpp
|
||||||
subscript.cpp
|
subscript.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,17 +10,6 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
DynamicJsonBuffer jb;
|
DynamicJsonBuffer jb;
|
||||||
JsonObject& _object = jb.createObject();
|
JsonObject& _object = jb.createObject();
|
||||||
|
|
||||||
SECTION("SizeIncreased_WhenValuesAreAdded") {
|
|
||||||
_object.set("hello", 42);
|
|
||||||
REQUIRE(1 == _object.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("SizeUntouched_WhenSameValueIsAdded") {
|
|
||||||
_object["hello"] = 1;
|
|
||||||
_object["hello"] = 2;
|
|
||||||
REQUIRE(1 == _object.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("int") {
|
SECTION("int") {
|
||||||
_object.set("hello", 123);
|
_object.set("hello", 123);
|
||||||
|
|
||||||
@ -91,17 +80,59 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
REQUIRE(42 == _object["a"]);
|
REQUIRE(42 == _object["a"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("ShouldReturnTrue_WhenAllocationSucceeds") {
|
SECTION("returns true when allocation succeeds") {
|
||||||
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer;
|
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer;
|
||||||
JsonObject& obj = jsonBuffer.createObject();
|
JsonObject& obj = jsonBuffer.createObject();
|
||||||
|
|
||||||
REQUIRE(true == obj.set(std::string("hello"), std::string("world")));
|
REQUIRE(true == obj.set(std::string("hello"), std::string("world")));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("ShouldReturnFalse_WhenAllocationFails") {
|
SECTION("returns false when allocation fails") {
|
||||||
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer;
|
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer;
|
||||||
JsonObject& obj = jsonBuffer.createObject();
|
JsonObject& obj = jsonBuffer.createObject();
|
||||||
|
|
||||||
REQUIRE(false == obj.set(std::string("hello"), std::string("world")));
|
REQUIRE(false == obj.set(std::string("hello"), std::string("world")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("should not duplicate const char*") {
|
||||||
|
_object.set("hello", "world");
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1);
|
||||||
|
REQUIRE(expectedSize == jb.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate char* value") {
|
||||||
|
_object.set("hello", const_cast<char*>("world"));
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == jb.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate char* key") {
|
||||||
|
_object.set(const_cast<char*>("hello"), "world");
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == jb.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate char* key&value") {
|
||||||
|
_object.set(const_cast<char*>("hello"), const_cast<char*>("world"));
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12;
|
||||||
|
REQUIRE(expectedSize <= jb.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate std::string value") {
|
||||||
|
_object.set("hello", std::string("world"));
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == jb.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate std::string key") {
|
||||||
|
_object.set(std::string("hello"), "world");
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == jb.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate std::string key&value") {
|
||||||
|
_object.set(std::string("hello"), std::string("world"));
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12;
|
||||||
|
REQUIRE(expectedSize <= jb.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
23
test/JsonObject/size.cpp
Normal file
23
test/JsonObject/size.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
TEST_CASE("JsonObject::size()") {
|
||||||
|
DynamicJsonBuffer jb;
|
||||||
|
JsonObject& _object = jb.createObject();
|
||||||
|
|
||||||
|
SECTION("increases when values are added") {
|
||||||
|
_object.set("hello", 42);
|
||||||
|
REQUIRE(1 == _object.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("doesn't increase when the smae key is added twice") {
|
||||||
|
_object["hello"] = 1;
|
||||||
|
_object["hello"] = 2;
|
||||||
|
REQUIRE(1 == _object.size());
|
||||||
|
}
|
||||||
|
}
|
@ -9,17 +9,6 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
DynamicJsonBuffer _jsonBuffer;
|
DynamicJsonBuffer _jsonBuffer;
|
||||||
JsonObject& _object = _jsonBuffer.createObject();
|
JsonObject& _object = _jsonBuffer.createObject();
|
||||||
|
|
||||||
SECTION("SizeIncreased_WhenValuesAreAdded") {
|
|
||||||
_object["hello"] = 1;
|
|
||||||
REQUIRE(1 == _object.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("SizeUntouched_WhenSameValueIsAdded") {
|
|
||||||
_object["hello"] = 1;
|
|
||||||
_object["hello"] = 2;
|
|
||||||
REQUIRE(1 == _object.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("int") {
|
SECTION("int") {
|
||||||
_object["hello"] = 123;
|
_object["hello"] = 123;
|
||||||
|
|
||||||
@ -113,9 +102,51 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
REQUIRE(42 == _object["a"]);
|
REQUIRE(42 == _object["a"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("KeyAsCharArray") { // issue #423
|
SECTION("char key[]") { // issue #423
|
||||||
char key[] = "hello";
|
char key[] = "hello";
|
||||||
_object[key] = 42;
|
_object[key] = 42;
|
||||||
REQUIRE(42 == _object[key]);
|
REQUIRE(42 == _object[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("should not duplicate const char*") {
|
||||||
|
_object["hello"] = "world";
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1);
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate char* value") {
|
||||||
|
_object["hello"] = const_cast<char*>("world");
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate char* key") {
|
||||||
|
_object[const_cast<char*>("hello")] = "world";
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate char* key&value") {
|
||||||
|
_object[const_cast<char*>("hello")] = const_cast<char*>("world");
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12;
|
||||||
|
REQUIRE(expectedSize <= _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate std::string value") {
|
||||||
|
_object["hello"] = std::string("world");
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate std::string key") {
|
||||||
|
_object[std::string("hello")] = "world";
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
|
||||||
|
REQUIRE(expectedSize == _jsonBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("should duplicate std::string key&value") {
|
||||||
|
_object[std::string("hello")] = std::string("world");
|
||||||
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12;
|
||||||
|
REQUIRE(expectedSize <= _jsonBuffer.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,4 +36,9 @@ TEST_CASE("TypeTraits") {
|
|||||||
REQUIRE((IsString<std::string>::value));
|
REQUIRE((IsString<std::string>::value));
|
||||||
REQUIRE_FALSE((IsString<double>::value));
|
REQUIRE_FALSE((IsString<double>::value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("IsConst") {
|
||||||
|
REQUIRE_FALSE((IsConst<char>::value));
|
||||||
|
REQUIRE((IsConst<const char>::value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user