mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-02 13:21:23 +02:00
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:
29
CHANGELOG.md
29
CHANGELOG.md
@ -4,8 +4,37 @@ ArduinoJson: change log
|
|||||||
HEAD
|
HEAD
|
||||||
----
|
----
|
||||||
|
|
||||||
|
* 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
|
||||||
* Increased default nesting limit to 50 when compiled for a computer (issue #349)
|
* Increased default nesting limit to 50 when compiled for a computer (issue #349)
|
||||||
|
|
||||||
|
**BREAKING CHANGES**:
|
||||||
|
|
||||||
|
The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return.
|
||||||
|
|
||||||
|
Old code:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#define ARDUINOJSON_USE_ARDUINO_STRING 0
|
||||||
|
JsonVariant value1 = myObject.get("myKey");
|
||||||
|
JsonVariant value2 = myArray.get(0);
|
||||||
|
```
|
||||||
|
|
||||||
|
New code:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||||
|
#define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||||
|
JsonVariant value1 = myObject.get<JsonVariant>("myKey");
|
||||||
|
JsonVariant value2 = myArray.get<JsonVariant>(0);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
v5.6.7
|
v5.6.7
|
||||||
------
|
------
|
||||||
|
|
||||||
|
53
examples/StringExample/StringExample.ino
Normal file
53
examples/StringExample/StringExample.ino
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
// About
|
||||||
|
// -----
|
||||||
|
// This example shows the different ways you can use String with ArduinoJson.
|
||||||
|
// Please don't see this as an invitation to use String.
|
||||||
|
// On the contrary, you should always use char[] when possible, it's much more
|
||||||
|
// efficient in term of code size, speed and memory usage.
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
DynamicJsonBuffer jsonBuffer;
|
||||||
|
|
||||||
|
// You can use a String as your JSON input.
|
||||||
|
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||||
|
String input =
|
||||||
|
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||||
|
JsonObject& root = jsonBuffer.parseObject(input);
|
||||||
|
|
||||||
|
// You can use a String to get an element of a JsonObject
|
||||||
|
// No duplication is done.
|
||||||
|
long time = root[String("time")];
|
||||||
|
|
||||||
|
// You can use a String to set an element of a JsonObject
|
||||||
|
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||||
|
root[String("time")] = time;
|
||||||
|
|
||||||
|
// You can get a String from a JsonObject or JsonArray:
|
||||||
|
// No duplication is done, at least not in the JsonBuffer.
|
||||||
|
String sensor = root[String("sensor")];
|
||||||
|
|
||||||
|
// You can set a String to a JsonObject or JsonArray:
|
||||||
|
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||||
|
root["sensor"] = sensor;
|
||||||
|
|
||||||
|
// You can also concatenate strings
|
||||||
|
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||||
|
root[String("sen") + "sor"] = String("gp") + "s";
|
||||||
|
|
||||||
|
// Lastly, you can print the resulting JSON to a String
|
||||||
|
String output;
|
||||||
|
root.printTo(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// not used in this example
|
||||||
|
}
|
@ -22,12 +22,17 @@
|
|||||||
#define ARDUINOJSON_USE_INT64 0
|
#define ARDUINOJSON_USE_INT64 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// arduino has its own implementation of String to replace std::string
|
// Arduino has its own implementation of String to replace std::string
|
||||||
#ifndef ARDUINOJSON_USE_ARDUINO_STRING
|
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||||
#define ARDUINOJSON_USE_ARDUINO_STRING 1
|
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// arduino doesn't support STL stream
|
// Arduino doesn't have std::string
|
||||||
|
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||||
|
#define ARDUINOJSON_ENABLE_STD_STRING 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Arduino doesn't support STL stream
|
||||||
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
|
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
#define ARDUINOJSON_ENABLE_STD_STREAM 0
|
#define ARDUINOJSON_ENABLE_STD_STREAM 0
|
||||||
#endif
|
#endif
|
||||||
@ -73,8 +78,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// on a computer, we can use std::string
|
// on a computer, we can use std::string
|
||||||
#ifndef ARDUINOJSON_USE_ARDUINO_STRING
|
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||||
#define ARDUINOJSON_USE_ARDUINO_STRING 0
|
#define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// on a computer, there is no reason to beleive Arduino String is available
|
||||||
|
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||||
|
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// on a computer, we can assume that the STL is there
|
// on a computer, we can assume that the STL is there
|
||||||
|
@ -8,26 +8,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Print.hpp"
|
#include "../Print.hpp"
|
||||||
#include "../String.hpp"
|
#include "StringFuncs.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
namespace Internals {
|
namespace Internals {
|
||||||
|
|
||||||
// A Print implementation that allows to write in a String
|
// A Print implementation that allows to write in a String
|
||||||
|
template <typename TString>
|
||||||
class DynamicStringBuilder : public Print {
|
class DynamicStringBuilder : public Print {
|
||||||
public:
|
public:
|
||||||
DynamicStringBuilder(String &str) : _str(str) {}
|
DynamicStringBuilder(TString &str) : _str(str) {}
|
||||||
|
|
||||||
virtual size_t write(uint8_t c) {
|
virtual size_t write(uint8_t c) {
|
||||||
// Need to cast to char, otherwise String will print a number (issue #120)
|
StringFuncs<TString>::append(_str, static_cast<char>(c));
|
||||||
_str += static_cast<char>(c);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DynamicStringBuilder &operator=(const DynamicStringBuilder &);
|
DynamicStringBuilder &operator=(const DynamicStringBuilder &);
|
||||||
|
|
||||||
String &_str;
|
TString &_str;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Configuration.hpp"
|
#include "../Configuration.hpp"
|
||||||
|
#include "../TypeTraits/EnableIf.hpp"
|
||||||
#include "DummyPrint.hpp"
|
#include "DummyPrint.hpp"
|
||||||
#include "DynamicStringBuilder.hpp"
|
#include "DynamicStringBuilder.hpp"
|
||||||
#include "IndentedPrint.hpp"
|
#include "IndentedPrint.hpp"
|
||||||
@ -49,8 +50,10 @@ class JsonPrintable {
|
|||||||
return printTo(sb);
|
return printTo(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t printTo(String &str) const {
|
template <typename TString>
|
||||||
DynamicStringBuilder sb(str);
|
typename TypeTraits::EnableIf<StringFuncs<TString>::has_append, size_t>::type
|
||||||
|
printTo(TString &str) const {
|
||||||
|
DynamicStringBuilder<TString> sb(str);
|
||||||
return printTo(sb);
|
return printTo(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,8 +72,10 @@ class JsonPrintable {
|
|||||||
return prettyPrintTo(indentedPrint);
|
return prettyPrintTo(indentedPrint);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t prettyPrintTo(String &str) const {
|
template <typename TString>
|
||||||
DynamicStringBuilder sb(str);
|
typename TypeTraits::EnableIf<StringFuncs<TString>::has_append, size_t>::type
|
||||||
|
prettyPrintTo(TString &str) const {
|
||||||
|
DynamicStringBuilder<TString> sb(str);
|
||||||
return prettyPrintTo(sb);
|
return prettyPrintTo(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,17 +8,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
namespace TypeTraits {
|
namespace Internals {
|
||||||
|
|
||||||
// A meta-function that returns true if T is a reference
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct IsReference {
|
struct JsonVariantDefault {
|
||||||
static const bool value = false;
|
static T get() {
|
||||||
|
return T();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct IsReference<T&> {
|
struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
|
||||||
static const bool value = true;
|
|
||||||
};
|
template <typename T>
|
||||||
|
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
|
||||||
}
|
}
|
||||||
}
|
}
|
94
include/ArduinoJson/Internals/StringFuncs.hpp
Normal file
94
include/ArduinoJson/Internals/StringFuncs.hpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Configuration.hpp"
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||||
|
#include <WString.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||||
|
#include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
|
||||||
|
template <typename TString>
|
||||||
|
struct StringFuncs {};
|
||||||
|
|
||||||
|
template <typename TString>
|
||||||
|
struct StringFuncs<const TString> : StringFuncs<TString> {};
|
||||||
|
|
||||||
|
template <typename TString>
|
||||||
|
struct StringFuncs<TString&> : StringFuncs<TString> {};
|
||||||
|
|
||||||
|
struct CharPtrFuncs {
|
||||||
|
static bool equals(const char* str, const char* expected) {
|
||||||
|
return strcmp(str, expected) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Buffer>
|
||||||
|
static char* duplicate(const char* str, Buffer* buffer) {
|
||||||
|
if (!str) return NULL;
|
||||||
|
size_t size = strlen(str) + 1;
|
||||||
|
void* dup = buffer->alloc(size);
|
||||||
|
if (dup != NULL) memcpy(dup, str, size);
|
||||||
|
return static_cast<char*>(dup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bool has_append = false;
|
||||||
|
static const bool should_duplicate = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<const char*> : CharPtrFuncs {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<char*> : CharPtrFuncs {};
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
struct StringFuncs<char[N]> : CharPtrFuncs {};
|
||||||
|
|
||||||
|
template <typename TString>
|
||||||
|
struct StdStringFuncs {
|
||||||
|
template <typename Buffer>
|
||||||
|
static char* duplicate(const TString& str, Buffer* buffer) {
|
||||||
|
if (!str.c_str()) return NULL; // <- Arduino string can return NULL
|
||||||
|
size_t size = str.length() + 1;
|
||||||
|
void* dup = buffer->alloc(size);
|
||||||
|
if (dup != NULL) memcpy(dup, str.c_str(), size);
|
||||||
|
return static_cast<char*>(dup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool equals(const TString& str, const char* expected) {
|
||||||
|
return str == expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void append(TString& str, char c) {
|
||||||
|
str += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bool has_append = true;
|
||||||
|
static const bool should_duplicate = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<String> : StdStringFuncs<String> {};
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<StringSumHelper> : StdStringFuncs<StringSumHelper> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||||
|
template <>
|
||||||
|
struct StringFuncs<std::string> : StdStringFuncs<std::string> {};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
41
include/ArduinoJson/Internals/ValueSetter.hpp
Normal file
41
include/ArduinoJson/Internals/ValueSetter.hpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../JsonBuffer.hpp"
|
||||||
|
#include "../JsonVariant.hpp"
|
||||||
|
#include "../TypeTraits/EnableIf.hpp"
|
||||||
|
#include "StringFuncs.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
|
||||||
|
template <typename TSource, typename Enable = void>
|
||||||
|
struct ValueSetter {
|
||||||
|
template <typename TDestination>
|
||||||
|
static bool set(JsonBuffer*, TDestination& destination,
|
||||||
|
const TSource& source) {
|
||||||
|
destination = source;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TSource>
|
||||||
|
struct ValueSetter<TSource, typename TypeTraits::EnableIf<
|
||||||
|
StringFuncs<TSource>::should_duplicate>::type> {
|
||||||
|
template <typename TDestination>
|
||||||
|
static bool set(JsonBuffer* buffer, TDestination& destination,
|
||||||
|
const TSource& source) {
|
||||||
|
const char* copy = buffer->strdup(source);
|
||||||
|
if (!copy) return false;
|
||||||
|
destination = copy;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -11,10 +11,12 @@
|
|||||||
#include "Internals/JsonPrintable.hpp"
|
#include "Internals/JsonPrintable.hpp"
|
||||||
#include "Internals/List.hpp"
|
#include "Internals/List.hpp"
|
||||||
#include "Internals/ReferenceType.hpp"
|
#include "Internals/ReferenceType.hpp"
|
||||||
|
#include "Internals/StringFuncs.hpp"
|
||||||
|
#include "Internals/ValueSetter.hpp"
|
||||||
#include "JsonVariant.hpp"
|
#include "JsonVariant.hpp"
|
||||||
|
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
||||||
#include "TypeTraits/EnableIf.hpp"
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||||
#include "TypeTraits/IsReference.hpp"
|
|
||||||
#include "TypeTraits/IsSame.hpp"
|
#include "TypeTraits/IsSame.hpp"
|
||||||
|
|
||||||
// Returns the size (in bytes) of an array with n elements.
|
// Returns the size (in bytes) of an array with n elements.
|
||||||
@ -40,15 +42,6 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
public Internals::List<JsonVariant>,
|
public Internals::List<JsonVariant>,
|
||||||
public Internals::JsonBufferAllocated {
|
public Internals::JsonBufferAllocated {
|
||||||
public:
|
public:
|
||||||
// A meta-function that returns true if type T can be used in
|
|
||||||
// JsonArray::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.
|
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||||
// You should not call this constructor directly.
|
// You should not call this constructor directly.
|
||||||
// Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray().
|
// Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray().
|
||||||
@ -57,7 +50,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
|
|
||||||
// Gets the value at the specified index
|
// Gets the value at the specified index
|
||||||
JsonVariant operator[](size_t index) const {
|
JsonVariant operator[](size_t index) const {
|
||||||
return get(index);
|
return get<JsonVariant>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets the value at specified index
|
// Gets or sets the value at specified index
|
||||||
@ -73,29 +66,24 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
// bool add(float value);
|
// bool add(float value);
|
||||||
// bool add(double value);
|
// bool add(double value);
|
||||||
// bool add(const char*);
|
// bool add(const char*);
|
||||||
template <typename T>
|
// bool add(const char[]);
|
||||||
bool add(
|
// bool add(const char[N]);
|
||||||
T value,
|
// bool add(RawJson);
|
||||||
typename TypeTraits::EnableIf<
|
// bool add(const std::string&)
|
||||||
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) {
|
|
||||||
return addNode<T>(value);
|
|
||||||
}
|
|
||||||
// bool add(const String&)
|
// bool add(const String&)
|
||||||
// bool add(const JsonVariant&);
|
// bool add(const JsonVariant&);
|
||||||
// bool add(JsonArray&);
|
// bool add(JsonArray&);
|
||||||
// bool add(JsonObject&);
|
// bool add(JsonObject&);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool add(const T &value,
|
bool add(const T &value) {
|
||||||
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
|
// reduce the number of template function instanciation to reduce code size
|
||||||
return addNode<T &>(const_cast<T &>(value));
|
return addNodeImpl<typename TypeTraits::ConstRefOrConstPtr<T>::type>(value);
|
||||||
}
|
}
|
||||||
// bool add(float value, uint8_t decimals);
|
// bool add(float value, uint8_t decimals);
|
||||||
// bool add(double value, uint8_t decimals);
|
// bool add(double value, uint8_t decimals);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool add(T value, uint8_t decimals,
|
bool add(T value, uint8_t decimals) {
|
||||||
typename TypeTraits::EnableIf<
|
return add(JsonVariant(value, decimals));
|
||||||
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
|
||||||
return addNode<JsonVariant>(JsonVariant(value, decimals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the value at specified index.
|
// Sets the value at specified index.
|
||||||
@ -104,42 +92,33 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
// bool set(size_t index, long value);
|
// bool set(size_t index, long value);
|
||||||
// bool set(size_t index, int value);
|
// bool set(size_t index, int value);
|
||||||
// bool set(size_t index, short value);
|
// bool set(size_t index, short value);
|
||||||
template <typename T>
|
// bool set(size_t index, const std::string&)
|
||||||
bool set(
|
|
||||||
size_t index, T value,
|
|
||||||
typename TypeTraits::EnableIf<
|
|
||||||
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) {
|
|
||||||
return setNodeAt<T>(index, value);
|
|
||||||
}
|
|
||||||
// bool set(size_t index, const String&)
|
// bool set(size_t index, const String&)
|
||||||
// bool set(size_t index, const JsonVariant&);
|
// bool set(size_t index, const JsonVariant&);
|
||||||
// bool set(size_t index, JsonArray&);
|
// bool set(size_t index, JsonArray&);
|
||||||
// bool set(size_t index, JsonObject&);
|
// bool set(size_t index, JsonObject&);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool set(size_t index, const T &value,
|
bool set(size_t index, const T &value) {
|
||||||
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
|
// reduce the number of template function instanciation to reduce code size
|
||||||
return setNodeAt<T &>(index, const_cast<T &>(value));
|
return setNodeAt<typename TypeTraits::ConstRefOrConstPtr<T>::type>(index,
|
||||||
|
value);
|
||||||
}
|
}
|
||||||
// bool set(size_t index, float value, uint8_t decimals = 2);
|
// bool set(size_t index, float value, uint8_t decimals = 2);
|
||||||
// bool set(size_t index, double value, uint8_t decimals = 2);
|
// bool set(size_t index, double value, uint8_t decimals = 2);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool set(size_t index, T value, uint8_t decimals,
|
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||||
typename TypeTraits::EnableIf<
|
bool>::type
|
||||||
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
set(size_t index, T value, uint8_t decimals) {
|
||||||
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
|
return set(index, JsonVariant(value, decimals));
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the value at the specified index.
|
|
||||||
JsonVariant get(size_t index) const {
|
|
||||||
node_type *node = getNodeAt(index);
|
|
||||||
return node ? node->content : JsonVariant();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the value at the specified index.
|
// Gets the value at the specified index.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
|
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
|
||||||
node_type *node = getNodeAt(index);
|
node_type *node = getNodeAt(index);
|
||||||
return node ? node->content.as<T>() : JsonVariant::defaultValue<T>();
|
return node ? node->content.as<T>()
|
||||||
|
: Internals::JsonVariantDefault<T>::get();
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the type of the value at specified index.
|
// Check the type of the value at specified index.
|
||||||
@ -172,7 +151,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
|
|
||||||
// Imports a 1D array
|
// Imports a 1D array
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
bool copyFrom(T(&array)[N]) {
|
bool copyFrom(T (&array)[N]) {
|
||||||
return copyFrom(array, N);
|
return copyFrom(array, N);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +167,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
|
|
||||||
// Imports a 2D array
|
// Imports a 2D array
|
||||||
template <typename T, size_t N1, size_t N2>
|
template <typename T, size_t N1, size_t N2>
|
||||||
bool copyFrom(T(&array)[N1][N2]) {
|
bool copyFrom(T (&array)[N1][N2]) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
for (size_t i = 0; i < N1; i++) {
|
for (size_t i = 0; i < N1; i++) {
|
||||||
JsonArray &nestedArray = createNestedArray();
|
JsonArray &nestedArray = createNestedArray();
|
||||||
@ -201,7 +180,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
|
|
||||||
// Exports a 1D array
|
// Exports a 1D array
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
size_t copyTo(T(&array)[N]) const {
|
size_t copyTo(T (&array)[N]) const {
|
||||||
return copyTo(array, N);
|
return copyTo(array, N);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +195,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
|
|
||||||
// Exports a 2D array
|
// Exports a 2D array
|
||||||
template <typename T, size_t N1, size_t N2>
|
template <typename T, size_t N1, size_t N2>
|
||||||
void copyTo(T(&array)[N1][N2]) const {
|
void copyTo(T (&array)[N1][N2]) const {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
|
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
|
||||||
it->asArray().copyTo(array[i++]);
|
it->asArray().copyTo(array[i++]);
|
||||||
@ -230,22 +209,22 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValueRef>
|
||||||
bool setNodeAt(size_t index, TValue value) {
|
bool setNodeAt(size_t index, TValueRef value) {
|
||||||
node_type *node = getNodeAt(index);
|
node_type *node = getNodeAt(index);
|
||||||
return node != NULL && setNodeValue<TValue>(node, value);
|
if (!node) return false;
|
||||||
|
|
||||||
|
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content,
|
||||||
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValueRef>
|
||||||
bool addNode(TValue value) {
|
bool addNodeImpl(TValueRef value) {
|
||||||
node_type *node = addNewNode();
|
node_type *node = addNewNode();
|
||||||
return node != NULL && setNodeValue<TValue>(node, value);
|
if (!node) return false;
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content,
|
||||||
bool setNodeValue(node_type *node, T value) {
|
value);
|
||||||
node->content = value;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,50 +13,31 @@
|
|||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
|
||||||
inline JsonVariant::JsonVariant(JsonArray &array) {
|
inline JsonVariant::JsonVariant(const JsonArray &array) {
|
||||||
if (array.success()) {
|
if (array.success()) {
|
||||||
_type = Internals::JSON_ARRAY;
|
_type = Internals::JSON_ARRAY;
|
||||||
_content.asArray = &array;
|
_content.asArray = const_cast<JsonArray *>(&array);
|
||||||
} else {
|
} else {
|
||||||
_type = Internals::JSON_UNDEFINED;
|
_type = Internals::JSON_UNDEFINED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JsonVariant::JsonVariant(JsonObject &object) {
|
inline JsonVariant::JsonVariant(const JsonObject &object) {
|
||||||
if (object.success()) {
|
if (object.success()) {
|
||||||
_type = Internals::JSON_OBJECT;
|
_type = Internals::JSON_OBJECT;
|
||||||
_content.asObject = &object;
|
_content.asObject = const_cast<JsonObject *>(&object);
|
||||||
} else {
|
} else {
|
||||||
_type = Internals::JSON_UNDEFINED;
|
_type = Internals::JSON_UNDEFINED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Internals {
|
||||||
template <>
|
template <>
|
||||||
inline bool JsonArray::setNodeValue(node_type *node, String &value) {
|
struct JsonVariantDefault<JsonArray> {
|
||||||
const char *copy = _buffer->strdup(value);
|
static JsonArray &get() {
|
||||||
if (!copy) return false;
|
return JsonArray::invalid();
|
||||||
node->content = copy;
|
}
|
||||||
return true;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline JsonArray &JsonVariant::defaultValue<JsonArray>() {
|
|
||||||
return JsonArray::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline JsonArray &JsonVariant::defaultValue<JsonArray &>() {
|
|
||||||
return JsonArray::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline const JsonArray &JsonVariant::defaultValue<const JsonArray>() {
|
|
||||||
return JsonArray::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline const JsonArray &JsonVariant::defaultValue<const JsonArray &>() {
|
|
||||||
return JsonArray::invalid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JsonArray &JsonVariant::asArray() const {
|
inline JsonArray &JsonVariant::asArray() const {
|
||||||
@ -71,10 +52,11 @@ inline JsonArray &JsonArray::createNestedArray() {
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JsonArray &JsonObject::createNestedArray(JsonObjectKey key) {
|
template <typename TString>
|
||||||
|
inline JsonArray &JsonObject::createNestedArray(const TString &key) {
|
||||||
if (!_buffer) return JsonArray::invalid();
|
if (!_buffer) return JsonArray::invalid();
|
||||||
JsonArray &array = _buffer->createArray();
|
JsonArray &array = _buffer->createArray();
|
||||||
setNodeAt<const JsonVariant &>(key, array);
|
set(key, array);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,24 +21,14 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
|||||||
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
|
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
|
||||||
: _array(array), _index(index) {}
|
: _array(array), _index(index) {}
|
||||||
|
|
||||||
JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
||||||
_array.set<const JsonVariant&>(_index, src);
|
_array.set(_index, src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename TypeTraits::EnableIf<JsonArray::CanSet<T&>::value,
|
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
|
||||||
JsonArraySubscript>::type&
|
_array.set(_index, src);
|
||||||
operator=(const T& src) {
|
|
||||||
_array.set<T&>(_index, const_cast<T&>(src));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename TypeTraits::EnableIf<JsonArray::CanSet<T>::value,
|
|
||||||
JsonArraySubscript>::type&
|
|
||||||
operator=(T src) {
|
|
||||||
_array.set<T>(_index, src);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,10 +36,6 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
|||||||
return _index < _array.size();
|
return _index < _array.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE operator JsonVariant() const {
|
|
||||||
return _array.get(_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const {
|
FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const {
|
||||||
return _array.get<T>(_index);
|
return _array.get<T>(_index);
|
||||||
@ -61,7 +47,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
void set(TValue value) {
|
FORCE_INLINE void set(const TValue& value) {
|
||||||
_array.set(_index, value);
|
_array.set(_index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "JsonVariant.hpp"
|
#include "JsonVariant.hpp"
|
||||||
#include "String.hpp"
|
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
@ -58,67 +57,56 @@ class JsonBuffer {
|
|||||||
// writable
|
// writable
|
||||||
// because the parser will insert null-terminators and replace escaped chars.
|
// because the parser will insert null-terminators and replace escaped chars.
|
||||||
//
|
//
|
||||||
// The second argument set the nesting limit (see comment on DEFAULT_LIMIT)
|
// The second argument set the nesting limit
|
||||||
//
|
//
|
||||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||||
// allocation fails.
|
// allocation fails.
|
||||||
JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
JsonArray &parseArray(
|
||||||
|
char *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT);
|
||||||
|
|
||||||
// Same with a const char*.
|
|
||||||
// With this overload, the JsonBuffer will make a copy of the string
|
// With this overload, the JsonBuffer will make a copy of the string
|
||||||
JsonArray &parseArray(const char *json, uint8_t nesting = DEFAULT_LIMIT) {
|
template <typename TString>
|
||||||
|
JsonArray &parseArray(const TString &json,
|
||||||
|
uint8_t nesting = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||||
return parseArray(strdup(json), nesting);
|
return parseArray(strdup(json), nesting);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as above with a String class
|
|
||||||
JsonArray &parseArray(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
|
||||||
return parseArray(json.c_str(), nesting);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocates and populate a JsonObject from a JSON string.
|
// Allocates and populate a JsonObject from a JSON string.
|
||||||
//
|
//
|
||||||
// The First argument is a pointer to the JSON string, the memory must be
|
// The First argument is a pointer to the JSON string, the memory must be
|
||||||
// writable
|
// writable
|
||||||
// because the parser will insert null-terminators and replace escaped chars.
|
// because the parser will insert null-terminators and replace escaped chars.
|
||||||
//
|
//
|
||||||
// The second argument set the nesting limit (see comment on DEFAULT_LIMIT)
|
// The second argument set the nesting limit
|
||||||
//
|
//
|
||||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||||
// allocation fails.
|
// allocation fails.
|
||||||
JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
JsonObject &parseObject(
|
||||||
|
char *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT);
|
||||||
|
|
||||||
// Same with a const char*.
|
|
||||||
// With this overload, the JsonBuffer will make a copy of the string
|
// With this overload, the JsonBuffer will make a copy of the string
|
||||||
JsonObject &parseObject(const char *json, uint8_t nesting = DEFAULT_LIMIT) {
|
template <typename TString>
|
||||||
|
JsonObject &parseObject(const TString &json,
|
||||||
|
uint8_t nesting = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||||
return parseObject(strdup(json), nesting);
|
return parseObject(strdup(json), nesting);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as above with a String class
|
|
||||||
JsonObject &parseObject(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
|
||||||
return parseObject(json.c_str(), nesting);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generalized version of parseArray() and parseObject(), also works for
|
// Generalized version of parseArray() and parseObject(), also works for
|
||||||
// integral types.
|
// integral types.
|
||||||
JsonVariant parse(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
JsonVariant parse(char *json,
|
||||||
|
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT);
|
||||||
|
|
||||||
// Same with a const char*.
|
|
||||||
// With this overload, the JsonBuffer will make a copy of the string
|
// With this overload, the JsonBuffer will make a copy of the string
|
||||||
JsonVariant parse(const char *json, uint8_t nesting = DEFAULT_LIMIT) {
|
template <typename TString>
|
||||||
|
JsonVariant parse(const TString &json,
|
||||||
|
uint8_t nesting = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||||
return parse(strdup(json), nesting);
|
return parse(strdup(json), nesting);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as above with a String class
|
|
||||||
JsonVariant parse(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
|
||||||
return parse(json.c_str(), nesting);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Duplicate a string
|
// Duplicate a string
|
||||||
char *strdup(const char *src) {
|
template <typename TString>
|
||||||
return src ? strdup(src, strlen(src)) : NULL;
|
char *strdup(const TString &src) {
|
||||||
}
|
return Internals::StringFuncs<TString>::duplicate(src, this);
|
||||||
char *strdup(const String &src) {
|
|
||||||
return strdup(src.c_str(), src.length());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocates n bytes in the JsonBuffer.
|
// Allocates n bytes in the JsonBuffer.
|
||||||
@ -135,23 +123,6 @@ class JsonBuffer {
|
|||||||
return bytes;
|
return bytes;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
char *strdup(const char *, size_t);
|
|
||||||
|
|
||||||
// Default value of nesting limit of parseArray() and parseObject().
|
|
||||||
//
|
|
||||||
// The nesting limit is a constrain on the level of nesting allowed in the
|
|
||||||
// JSON string.
|
|
||||||
// If set to 0, only a flat array or objects can be parsed.
|
|
||||||
// If set to 1, the object can contain nested arrays or objects but only 1
|
|
||||||
// level deep.
|
|
||||||
// And bigger values will allow more level of nesting.
|
|
||||||
//
|
|
||||||
// The purpose of this feature is to prevent stack overflow that could
|
|
||||||
// lead to
|
|
||||||
// a security risk.
|
|
||||||
static const uint8_t DEFAULT_LIMIT = ARDUINOJSON_DEFAULT_NESTING_LIMIT;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,11 +36,3 @@ inline ArduinoJson::JsonVariant ArduinoJson::JsonBuffer::parse(
|
|||||||
Internals::JsonParser parser(this, json, nestingLimit);
|
Internals::JsonParser parser(this, json, nestingLimit);
|
||||||
return parser.parseVariant();
|
return parser.parseVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char *ArduinoJson::JsonBuffer::strdup(const char *source,
|
|
||||||
size_t length) {
|
|
||||||
size_t size = length + 1;
|
|
||||||
char *dest = static_cast<char *>(alloc(size));
|
|
||||||
if (dest != NULL) memcpy(dest, source, size);
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "String.hpp"
|
|
||||||
#include "Internals/JsonBufferAllocated.hpp"
|
#include "Internals/JsonBufferAllocated.hpp"
|
||||||
#include "Internals/JsonPrintable.hpp"
|
#include "Internals/JsonPrintable.hpp"
|
||||||
#include "Internals/List.hpp"
|
#include "Internals/List.hpp"
|
||||||
#include "Internals/ReferenceType.hpp"
|
#include "Internals/ReferenceType.hpp"
|
||||||
|
#include "Internals/StringFuncs.hpp"
|
||||||
|
#include "Internals/ValueSetter.hpp"
|
||||||
#include "JsonPair.hpp"
|
#include "JsonPair.hpp"
|
||||||
|
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
||||||
#include "TypeTraits/EnableIf.hpp"
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||||
#include "TypeTraits/IsReference.hpp"
|
|
||||||
#include "TypeTraits/IsSame.hpp"
|
#include "TypeTraits/IsSame.hpp"
|
||||||
|
|
||||||
// Returns the size (in bytes) of an object with n elements.
|
// 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::List<JsonPair>,
|
||||||
public Internals::JsonBufferAllocated {
|
public Internals::JsonBufferAllocated {
|
||||||
public:
|
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.
|
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||||
// You should not use this constructor directly.
|
// You should not use this constructor directly.
|
||||||
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
|
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
|
||||||
explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {}
|
explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {}
|
||||||
|
|
||||||
// Gets or sets the value associated with the specified key.
|
// Gets or sets the value associated with the specified key.
|
||||||
JsonObjectSubscript<const char*> operator[](const char* key);
|
template <typename TString>
|
||||||
JsonObjectSubscript<const String&> operator[](const String& key);
|
JsonObjectSubscript<TString> operator[](const TString& key);
|
||||||
|
|
||||||
// Gets the value associated with the specified key.
|
// Gets the value associated with the specified key.
|
||||||
JsonVariant operator[](JsonObjectKey key) const {
|
template <typename TString>
|
||||||
return get(key);
|
JsonVariant operator[](const TString& key) const {
|
||||||
|
return get<JsonVariant>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the specified key with the specified value.
|
// 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, double value);
|
||||||
// bool set(TKey key, const char* value);
|
// bool set(TKey key, const char* value);
|
||||||
// bool set(TKey key, RawJson 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, String&);
|
||||||
// bool set(Key, JsonArray&);
|
// bool set(Key, JsonArray&);
|
||||||
// bool set(Key, JsonObject&);
|
// bool set(Key, JsonObject&);
|
||||||
// bool set(Key, JsonVariant&);
|
// bool set(Key, JsonVariant&);
|
||||||
template <typename T>
|
template <typename TValue, typename TString>
|
||||||
bool set(JsonObjectKey key, const T& value,
|
bool set(const TString& key, const TValue& value) {
|
||||||
typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) {
|
// reduce the number of template function instanciation to reduce code size
|
||||||
return setNodeAt<T&>(key, const_cast<T&>(value));
|
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, float value, uint8_t decimals);
|
||||||
// bool set(Key, double value, uint8_t decimals);
|
// bool set(Key, double value, uint8_t decimals);
|
||||||
template <typename TValue>
|
template <typename TValue, typename TString>
|
||||||
bool set(JsonObjectKey key, TValue value, uint8_t decimals,
|
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value,
|
||||||
typename TypeTraits::EnableIf<
|
bool>::type
|
||||||
TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) {
|
set(const TString& key, TValue value, uint8_t decimals) {
|
||||||
return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals));
|
return set(key, JsonVariant(value, decimals));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the value associated with the specified key.
|
// Gets the value associated with the specified key.
|
||||||
JsonVariant get(JsonObjectKey key) const {
|
template <typename TValue, typename TString>
|
||||||
node_type* node = getNodeAt(key.c_str());
|
typename Internals::JsonVariantAs<TValue>::type get(
|
||||||
return node ? node->content.value : JsonVariant();
|
const TString& key) const {
|
||||||
}
|
node_type* node = getNodeAt(key);
|
||||||
|
return node ? node->content.value.as<TValue>()
|
||||||
// Gets the value associated with the specified key.
|
: Internals::JsonVariantDefault<TValue>::get();
|
||||||
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>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks the type of the value associated with the specified key.
|
// Checks the type of the value associated with the specified key.
|
||||||
template <typename T>
|
template <typename TValue, typename TString>
|
||||||
bool is(JsonObjectKey key) const {
|
bool is(const TString& key) const {
|
||||||
node_type* node = getNodeAt(key.c_str());
|
node_type* node = getNodeAt(key);
|
||||||
return node ? node->content.value.is<T>() : false;
|
return node ? node->content.value.is<TValue>() : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates and adds a JsonArray.
|
// Creates and adds a JsonArray.
|
||||||
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
// 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.
|
// Creates and adds a JsonObject.
|
||||||
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
// 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.
|
// Tells weither the specified key is present and associated with a value.
|
||||||
bool containsKey(JsonObjectKey key) const {
|
template <typename TString>
|
||||||
return getNodeAt(key.c_str()) != NULL;
|
bool containsKey(const TString& key) const {
|
||||||
|
return getNodeAt(key) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the specified key and the associated value.
|
// Removes the specified key and the associated value.
|
||||||
void remove(JsonObjectKey key) {
|
template <typename TString>
|
||||||
removeNode(getNodeAt(key.c_str()));
|
void remove(const TString& key) {
|
||||||
|
removeNode(getNodeAt(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a reference an invalid JsonObject.
|
// Returns a reference an invalid JsonObject.
|
||||||
@ -146,37 +134,35 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Returns the list node that matches the specified key.
|
// 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) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename TStringRef, typename TValueRef>
|
||||||
bool setNodeAt(JsonObjectKey key, T value) {
|
bool setNodeAt(TStringRef key, TValueRef value) {
|
||||||
node_type* node = getNodeAt(key.c_str());
|
node_type* node = getNodeAtImpl<TStringRef>(key);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
node = addNewNode();
|
node = addNewNode();
|
||||||
if (!node || !setNodeKey(node, key)) return false;
|
if (!node) return false;
|
||||||
}
|
|
||||||
return setNodeValue<T>(node, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool setNodeKey(node_type* node, JsonObjectKey key) {
|
bool key_ok = Internals::ValueSetter<TStringRef>::set(
|
||||||
if (key.needs_copy()) {
|
_buffer, node->content.key, key);
|
||||||
node->content.key = _buffer->strdup(key.c_str());
|
if (!key_ok) return false;
|
||||||
if (node->content.key == NULL) return false;
|
|
||||||
} else {
|
|
||||||
node->content.key = key.c_str();
|
|
||||||
}
|
}
|
||||||
return true;
|
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content.value,
|
||||||
}
|
value);
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool setNodeValue(node_type* node, T value) {
|
|
||||||
node->content.value = value;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,38 +13,13 @@
|
|||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
namespace Internals {
|
||||||
template <>
|
template <>
|
||||||
inline bool JsonObject::setNodeValue(node_type *node, String &value) {
|
struct JsonVariantDefault<JsonObject> {
|
||||||
const char *dup = _buffer->strdup(value);
|
static JsonObject &get() {
|
||||||
node->content.value = dup;
|
return JsonObject::invalid();
|
||||||
return dup != NULL;
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool JsonObject::setNodeValue(node_type *node, const String &value) {
|
|
||||||
const char *dup = _buffer->strdup(value);
|
|
||||||
node->content.value = dup;
|
|
||||||
return dup != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline const JsonObject &JsonVariant::defaultValue<const JsonObject &>() {
|
|
||||||
return JsonObject::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline const JsonObject &JsonVariant::defaultValue<const JsonObject>() {
|
|
||||||
return JsonObject::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline JsonObject &JsonVariant::defaultValue<JsonObject &>() {
|
|
||||||
return JsonObject::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline JsonObject &JsonVariant::defaultValue<JsonObject>() {
|
|
||||||
return JsonObject::invalid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JsonObject &JsonVariant::asObject() const {
|
inline JsonObject &JsonVariant::asObject() const {
|
||||||
@ -52,11 +27,12 @@ inline JsonObject &JsonVariant::asObject() const {
|
|||||||
return JsonObject::invalid();
|
return JsonObject::invalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JsonObject &JsonObject::createNestedObject(JsonObjectKey key) {
|
template <typename TString>
|
||||||
|
inline JsonObject &JsonObject::createNestedObject(const TString &key) {
|
||||||
if (!_buffer) return JsonObject::invalid();
|
if (!_buffer) return JsonObject::invalid();
|
||||||
JsonObject &array = _buffer->createObject();
|
JsonObject &object = _buffer->createObject();
|
||||||
setNodeAt<const JsonVariant &>(key, array);
|
set(key, object);
|
||||||
return array;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JsonObject &JsonArray::createNestedObject() {
|
inline JsonObject &JsonArray::createNestedObject() {
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2016
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
// If you like this project, please add a star!
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "String.hpp"
|
|
||||||
|
|
||||||
namespace ArduinoJson {
|
|
||||||
|
|
||||||
// Represents a key in a JsonObject
|
|
||||||
class JsonObjectKey {
|
|
||||||
public:
|
|
||||||
JsonObjectKey(const char* key) : _value(key), _needs_copy(false) {}
|
|
||||||
JsonObjectKey(const String& key) : _value(key.c_str()), _needs_copy(true) {}
|
|
||||||
|
|
||||||
const char* c_str() const { return _value; }
|
|
||||||
bool needs_copy() const { return _needs_copy; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char* _value;
|
|
||||||
bool _needs_copy;
|
|
||||||
};
|
|
||||||
}
|
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "Configuration.hpp"
|
#include "Configuration.hpp"
|
||||||
#include "JsonVariantBase.hpp"
|
#include "JsonVariantBase.hpp"
|
||||||
|
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
||||||
#include "TypeTraits/EnableIf.hpp"
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@ -18,30 +19,27 @@
|
|||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
|
||||||
template <typename TKey>
|
template <typename TString>
|
||||||
class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
|
class JsonObjectSubscript
|
||||||
|
: public JsonVariantBase<JsonObjectSubscript<TString> > {
|
||||||
|
// const String&
|
||||||
|
// const std::string&
|
||||||
|
// const char*
|
||||||
|
typedef typename TypeTraits::ConstRefOrConstPtr<TString>::type TStringRef;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key)
|
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TStringRef key)
|
||||||
: _object(object), _key(key) {}
|
: _object(object), _key(key) {}
|
||||||
|
|
||||||
JsonObjectSubscript<TKey>& operator=(const JsonObjectSubscript<TKey>& src) {
|
FORCE_INLINE JsonObjectSubscript<TString>& operator=(
|
||||||
_object.set<const JsonVariant&>(_key, src);
|
const JsonObjectSubscript<TString>& src) {
|
||||||
|
_object.set(_key, src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename TypeTraits::EnableIf<JsonObject::CanSet<T&>::value,
|
FORCE_INLINE JsonObjectSubscript<TString>& operator=(const T& src) {
|
||||||
JsonObjectSubscript<TKey> >::type&
|
_object.set(_key, src);
|
||||||
operator=(const T& src) {
|
|
||||||
_object.set<T&>(_key, const_cast<T&>(src));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename TypeTraits::EnableIf<JsonObject::CanSet<T>::value,
|
|
||||||
JsonObjectSubscript<TKey> >::type&
|
|
||||||
operator=(T src) {
|
|
||||||
_object.set<T>(_key, src);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,13 +47,9 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
|
|||||||
return _object.containsKey(_key);
|
return _object.containsKey(_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE operator JsonVariant() const {
|
|
||||||
return _object.get(_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const {
|
FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const {
|
||||||
return _object.get<TValue>(_key);
|
return _object.get<TValue, TStringRef>(_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
@ -64,58 +58,39 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE bool set(TValue value) {
|
FORCE_INLINE bool set(const TValue& value) {
|
||||||
return _object.set<TValue>(_key, value);
|
return _object.set(_key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE bool set(TValue value, uint8_t decimals) {
|
FORCE_INLINE bool set(const TValue& value, uint8_t decimals) {
|
||||||
return _object.set(_key, value, decimals);
|
return _object.set(_key, value, decimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE JsonVariant get() {
|
|
||||||
return _object.get(_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonObject& _object;
|
JsonObject& _object;
|
||||||
TKey _key;
|
TStringRef _key;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
inline std::ostream& operator<<(
|
template <typename TString>
|
||||||
std::ostream& os, const JsonObjectSubscript<const String&>& source) {
|
inline std::ostream& operator<<(std::ostream& os,
|
||||||
return source.printTo(os);
|
const JsonObjectSubscript<TString>& source) {
|
||||||
}
|
|
||||||
|
|
||||||
inline std::ostream& operator<<(
|
|
||||||
std::ostream& os, const JsonObjectSubscript<const char*>& source) {
|
|
||||||
return source.printTo(os);
|
return source.printTo(os);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline JsonObjectSubscript<const char*> JsonObject::operator[](
|
template <typename TString>
|
||||||
const char* key) {
|
inline JsonObjectSubscript<TString> JsonObject::operator[](const TString& key) {
|
||||||
return JsonObjectSubscript<const char*>(*this, key);
|
return JsonObjectSubscript<TString>(*this, key);
|
||||||
}
|
|
||||||
|
|
||||||
inline JsonObjectSubscript<const String&> JsonObject::operator[](
|
|
||||||
const String& key) {
|
|
||||||
return JsonObjectSubscript<const String&>(*this, key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TImplem>
|
template <typename TImplem>
|
||||||
inline const JsonObjectSubscript<const char*> JsonVariantBase<TImplem>::
|
template <class TString>
|
||||||
operator[](const char* key) const {
|
inline const JsonObjectSubscript<TString> JsonVariantBase<TImplem>::operator[](
|
||||||
|
const TString& key) const {
|
||||||
return asObject()[key];
|
return asObject()[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TImplem>
|
|
||||||
inline const JsonObjectSubscript<const String&> JsonVariantBase<TImplem>::
|
|
||||||
operator[](const String& key) const {
|
|
||||||
return asObject()[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ArduinoJson
|
} // namespace ArduinoJson
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "JsonObjectKey.hpp"
|
|
||||||
#include "JsonVariant.hpp"
|
#include "JsonVariant.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "Internals/JsonPrintable.hpp"
|
#include "Internals/JsonPrintable.hpp"
|
||||||
#include "Internals/JsonVariantContent.hpp"
|
#include "Internals/JsonVariantContent.hpp"
|
||||||
|
#include "Internals/JsonVariantDefault.hpp"
|
||||||
#include "Internals/JsonVariantType.hpp"
|
#include "Internals/JsonVariantType.hpp"
|
||||||
#include "JsonVariantBase.hpp"
|
#include "JsonVariantBase.hpp"
|
||||||
#include "RawJson.hpp"
|
#include "RawJson.hpp"
|
||||||
@ -19,6 +20,8 @@
|
|||||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||||
#include "TypeTraits/IsIntegral.hpp"
|
#include "TypeTraits/IsIntegral.hpp"
|
||||||
#include "TypeTraits/IsSame.hpp"
|
#include "TypeTraits/IsSame.hpp"
|
||||||
|
#include "TypeTraits/IsSignedIntegral.hpp"
|
||||||
|
#include "TypeTraits/IsUnsignedIntegral.hpp"
|
||||||
#include "TypeTraits/RemoveConst.hpp"
|
#include "TypeTraits/RemoveConst.hpp"
|
||||||
#include "TypeTraits/RemoveReference.hpp"
|
#include "TypeTraits/RemoveReference.hpp"
|
||||||
|
|
||||||
@ -40,9 +43,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
JsonWriter &);
|
JsonWriter &);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T>
|
|
||||||
struct IsConstructibleFrom;
|
|
||||||
|
|
||||||
// Creates an uninitialized JsonVariant
|
// Creates an uninitialized JsonVariant
|
||||||
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||||
|
|
||||||
@ -110,10 +110,14 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a JsonVariant containing a reference to an array.
|
// Create a JsonVariant containing a reference to an array.
|
||||||
JsonVariant(JsonArray &array);
|
// CAUTION: we are lying about constness, because the array can be modified if
|
||||||
|
// the variant is converted back to a JsonArray&
|
||||||
|
JsonVariant(const JsonArray &array);
|
||||||
|
|
||||||
// Create a JsonVariant containing a reference to an object.
|
// Create a JsonVariant containing a reference to an object.
|
||||||
JsonVariant(JsonObject &object);
|
// CAUTION: we are lying about constness, because the object can be modified
|
||||||
|
// if the variant is converted back to a JsonObject&
|
||||||
|
JsonVariant(const JsonObject &object);
|
||||||
|
|
||||||
// Get the variant as the specified type.
|
// Get the variant as the specified type.
|
||||||
//
|
//
|
||||||
@ -146,14 +150,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
return static_cast<T>(asFloat());
|
return static_cast<T>(asFloat());
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// const String as<String>() const;
|
|
||||||
template <typename T>
|
|
||||||
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, String>::value,
|
|
||||||
T>::type
|
|
||||||
as() const {
|
|
||||||
return toString();
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// const char* as<const char*>() const;
|
// const char* as<const char*>() const;
|
||||||
// const char* as<char*>() const;
|
// const char* as<char*>() const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -164,6 +160,18 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
return asString();
|
return asString();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
// std::string as<std::string>() const;
|
||||||
|
// String as<String>() const;
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<Internals::StringFuncs<T>::has_append, T>::type
|
||||||
|
as() const {
|
||||||
|
const char *cstr = asString();
|
||||||
|
if (cstr) return T(cstr);
|
||||||
|
T s;
|
||||||
|
printTo(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
//
|
||||||
// const bool as<bool>() const
|
// const bool as<bool>() const
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
||||||
@ -230,7 +238,8 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
// int as<int>() const;
|
// int as<int>() const;
|
||||||
// long as<long>() const;
|
// long as<long>() const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value,
|
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value &&
|
||||||
|
!TypeTraits::IsSame<T, bool>::value,
|
||||||
bool>::type
|
bool>::type
|
||||||
is() const {
|
is() const {
|
||||||
return isInteger();
|
return isInteger();
|
||||||
@ -296,12 +305,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
return _type != Internals::JSON_UNDEFINED;
|
return _type != Internals::JSON_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value returned if the variant has an incompatible type
|
|
||||||
template <typename T>
|
|
||||||
static typename Internals::JsonVariantAs<T>::type defaultValue() {
|
|
||||||
return T();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use as<char*>() instead
|
// DEPRECATED: use as<char*>() instead
|
||||||
const char *asString() const;
|
const char *asString() const;
|
||||||
|
|
||||||
@ -317,7 +320,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
JsonVariant(T value, typename TypeTraits::EnableIf<
|
JsonVariant(T value, typename TypeTraits::EnableIf<
|
||||||
TypeTraits::IsSame<T, char>::value>::type * = 0);
|
TypeTraits::IsSame<T, char>::value>::type * = 0);
|
||||||
|
|
||||||
String toString() const;
|
|
||||||
Internals::JsonFloat asFloat() const;
|
Internals::JsonFloat asFloat() const;
|
||||||
Internals::JsonInteger asInteger() const;
|
Internals::JsonInteger asInteger() const;
|
||||||
Internals::JsonUInt asUnsignedInteger() const;
|
Internals::JsonUInt asUnsignedInteger() const;
|
||||||
@ -350,27 +352,4 @@ inline JsonVariant float_with_n_digits(float value, uint8_t digits) {
|
|||||||
inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
|
inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
|
||||||
return JsonVariant(value, digits);
|
return JsonVariant(value, digits);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct JsonVariant::IsConstructibleFrom {
|
|
||||||
static const bool value =
|
|
||||||
TypeTraits::IsIntegral<T>::value ||
|
|
||||||
TypeTraits::IsFloatingPoint<T>::value ||
|
|
||||||
TypeTraits::IsSame<T, bool>::value ||
|
|
||||||
TypeTraits::IsSame<T, char *>::value ||
|
|
||||||
TypeTraits::IsSame<T, const char *>::value ||
|
|
||||||
TypeTraits::IsSame<T, RawJson>::value ||
|
|
||||||
TypeTraits::IsSame<T, JsonArray &>::value ||
|
|
||||||
TypeTraits::IsSame<T, const JsonArray &>::value ||
|
|
||||||
TypeTraits::IsSame<T, JsonArraySubscript &>::value ||
|
|
||||||
TypeTraits::IsSame<T, const JsonArraySubscript &>::value ||
|
|
||||||
TypeTraits::IsSame<T, JsonObject &>::value ||
|
|
||||||
TypeTraits::IsSame<T, const JsonObject &>::value ||
|
|
||||||
TypeTraits::IsSame<T, JsonObjectSubscript<const char *> &>::value ||
|
|
||||||
TypeTraits::IsSame<T, const JsonObjectSubscript<const char *> &>::value ||
|
|
||||||
TypeTraits::IsSame<T, JsonObjectSubscript<String> &>::value ||
|
|
||||||
TypeTraits::IsSame<T, const JsonObjectSubscript<String> &>::value ||
|
|
||||||
TypeTraits::IsSame<T, JsonVariant &>::value ||
|
|
||||||
TypeTraits::IsSame<T, const JsonVariant &>::value;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Configuration.hpp"
|
#include "Configuration.hpp"
|
||||||
#include "JsonVariant.hpp"
|
|
||||||
#include "Internals/Parse.hpp"
|
#include "Internals/Parse.hpp"
|
||||||
#include "JsonArray.hpp"
|
#include "JsonArray.hpp"
|
||||||
#include "JsonObject.hpp"
|
#include "JsonObject.hpp"
|
||||||
|
#include "JsonVariant.hpp"
|
||||||
|
|
||||||
#include <string.h> // for strcmp
|
|
||||||
#include <errno.h> // for errno
|
#include <errno.h> // for errno
|
||||||
#include <stdlib.h> // for strtol, strtod
|
#include <stdlib.h> // for strtol, strtod
|
||||||
|
#include <string.h> // for strcmp
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
|
||||||
@ -85,17 +85,6 @@ inline Internals::JsonFloat JsonVariant::asFloat() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String JsonVariant::toString() const {
|
|
||||||
using namespace Internals;
|
|
||||||
String s;
|
|
||||||
if ((_type == JSON_STRING || _type == JSON_UNPARSED) &&
|
|
||||||
_content.asString != NULL)
|
|
||||||
s = _content.asString;
|
|
||||||
else
|
|
||||||
printTo(s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool JsonVariant::isBoolean() const {
|
inline bool JsonVariant::isBoolean() const {
|
||||||
using namespace Internals;
|
using namespace Internals;
|
||||||
if (_type == JSON_BOOLEAN) return true;
|
if (_type == JSON_BOOLEAN) return true;
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Internals/JsonVariantAs.hpp"
|
#include "Internals/JsonVariantAs.hpp"
|
||||||
#include "JsonObjectKey.hpp"
|
|
||||||
#include "Polyfills/attributes.hpp"
|
#include "Polyfills/attributes.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
@ -77,10 +76,9 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
|||||||
// Returns the value associated with the specified key if the variant is
|
// Returns the value associated with the specified key if the variant is
|
||||||
// an object.
|
// an object.
|
||||||
// Return JsonVariant::invalid() if the variant is not an object.
|
// Return JsonVariant::invalid() if the variant is not an object.
|
||||||
FORCE_INLINE const JsonObjectSubscript<const char *> operator[](
|
template <typename TString>
|
||||||
const char *key) const;
|
FORCE_INLINE const JsonObjectSubscript<TString> operator[](
|
||||||
FORCE_INLINE const JsonObjectSubscript<const String &> operator[](
|
const TString &key) const;
|
||||||
const String &key) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const TImpl *impl() const {
|
const TImpl *impl() const {
|
||||||
|
@ -13,7 +13,9 @@ namespace ArduinoJson {
|
|||||||
class RawJson {
|
class RawJson {
|
||||||
public:
|
public:
|
||||||
explicit RawJson(const char* str) : _str(str) {}
|
explicit RawJson(const char* str) : _str(str) {}
|
||||||
operator const char*() const { return _str; }
|
operator const char*() const {
|
||||||
|
return _str;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* _str;
|
const char* _str;
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2016
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
// If you like this project, please add a star!
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Configuration.hpp"
|
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_ARDUINO_STRING
|
|
||||||
|
|
||||||
#include <WString.h>
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace ArduinoJson {
|
|
||||||
typedef std::string String;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
31
include/ArduinoJson/TypeTraits/ConstRefOrConstPtr.hpp
Normal file
31
include/ArduinoJson/TypeTraits/ConstRefOrConstPtr.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that return the type T without the const modifier
|
||||||
|
template <typename T>
|
||||||
|
struct ConstRefOrConstPtr {
|
||||||
|
typedef const T& type;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct ConstRefOrConstPtr<T*> {
|
||||||
|
typedef const T* type;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct ConstRefOrConstPtr<T[]> {
|
||||||
|
typedef const T* type;
|
||||||
|
};
|
||||||
|
template <typename T, size_t N>
|
||||||
|
struct ConstRefOrConstPtr<T[N]> {
|
||||||
|
typedef const T* type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Configuration.hpp"
|
|
||||||
#include "IsSame.hpp"
|
#include "IsSame.hpp"
|
||||||
#include "IsSignedIntegral.hpp"
|
#include "IsSignedIntegral.hpp"
|
||||||
#include "IsUnsignedIntegral.hpp"
|
#include "IsUnsignedIntegral.hpp"
|
||||||
@ -20,7 +19,11 @@ template <typename T>
|
|||||||
struct IsIntegral {
|
struct IsIntegral {
|
||||||
static const bool value = TypeTraits::IsSignedIntegral<T>::value ||
|
static const bool value = TypeTraits::IsSignedIntegral<T>::value ||
|
||||||
TypeTraits::IsUnsignedIntegral<T>::value ||
|
TypeTraits::IsUnsignedIntegral<T>::value ||
|
||||||
TypeTraits::IsSame<T, char>::value;
|
TypeTraits::IsSame<T, char>::value ||
|
||||||
|
TypeTraits::IsSame<T, bool>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct IsIntegral<const T> : IsIntegral<T> {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
// If you like this project, please add a star!
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
class DynamicJsonBuffer_Basic_Tests : public testing::Test {
|
class DynamicJsonBuffer_Basic_Tests : public testing::Test {
|
||||||
protected:
|
protected:
|
||||||
@ -38,3 +38,16 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, Alignment) {
|
|||||||
ASSERT_EQ(0, addr & mask);
|
ASSERT_EQ(0, addr & mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DynamicJsonBuffer_Basic_Tests, strdup) {
|
||||||
|
char original[] = "hello";
|
||||||
|
char* copy = buffer.strdup(original);
|
||||||
|
strcpy(original, "world");
|
||||||
|
ASSERT_STREQ("hello", copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DynamicJsonBuffer_Basic_Tests, strdup_givenNull) {
|
||||||
|
const char* original = NULL;
|
||||||
|
char* copy = buffer.strdup(original);
|
||||||
|
ASSERT_EQ(NULL, copy);
|
||||||
|
}
|
||||||
|
26
test/JsonObject_Get_Tests.cpp
Normal file
26
test/JsonObject_Get_Tests.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
class JsonObject_Get_Tests : public ::testing::Test {
|
||||||
|
public:
|
||||||
|
JsonObject_Get_Tests() : _object(_jsonBuffer.createObject()) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DynamicJsonBuffer _jsonBuffer;
|
||||||
|
JsonObject& _object;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TEST_(name) TEST_F(JsonObject_Get_Tests, name)
|
||||||
|
|
||||||
|
TEST_(GetConstCharPointer_GivenStringLiteral) {
|
||||||
|
_object.set("hello", "world");
|
||||||
|
const char* value = _object.get<const char*>("hello");
|
||||||
|
EXPECT_STREQ("world", value);
|
||||||
|
}
|
@ -5,11 +5,11 @@
|
|||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
// If you like this project, please add a star!
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
TEST(JsonObject_Invalid_Tests, SubscriptFails) {
|
TEST(JsonObject_Invalid_Tests, SubscriptFails) {
|
||||||
ASSERT_FALSE(JsonObject::invalid()[0].success());
|
ASSERT_FALSE(JsonObject::invalid()["key"].success());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(JsonObject_Invalid_Tests, AddFails) {
|
TEST(JsonObject_Invalid_Tests, AddFails) {
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
// If you like this project, please add a star!
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
class JsonObject_Set_Tests : public ::testing::Test {
|
class JsonObject_Set_Tests : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
@ -112,7 +112,7 @@ TEST_(ShouldReturnTrue_WhenAllocationSucceeds) {
|
|||||||
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer;
|
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer;
|
||||||
JsonObject& obj = jsonBuffer.createObject();
|
JsonObject& obj = jsonBuffer.createObject();
|
||||||
|
|
||||||
bool result = obj.set(String("hello"), String("world"));
|
bool result = obj.set(std::string("hello"), std::string("world"));
|
||||||
|
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ TEST_(ShouldReturnFalse_WhenAllocationFails) {
|
|||||||
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer;
|
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer;
|
||||||
JsonObject& obj = jsonBuffer.createObject();
|
JsonObject& obj = jsonBuffer.createObject();
|
||||||
|
|
||||||
bool result = obj.set(String("hello"), String("world"));
|
bool result = obj.set(std::string("hello"), std::string("world"));
|
||||||
|
|
||||||
ASSERT_FALSE(result);
|
ASSERT_FALSE(result);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ TEST(JsonVariant_As_Tests, DoubleAsCstr) {
|
|||||||
|
|
||||||
TEST(JsonVariant_As_Tests, DoubleAsString) {
|
TEST(JsonVariant_As_Tests, DoubleAsString) {
|
||||||
JsonVariant variant = 4.2;
|
JsonVariant variant = 4.2;
|
||||||
ASSERT_EQ(String("4.20"), variant.as<String>());
|
ASSERT_EQ(std::string("4.20"), variant.as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(JsonVariant_As_Tests, DoubleAsLong) {
|
TEST(JsonVariant_As_Tests, DoubleAsLong) {
|
||||||
@ -64,7 +64,7 @@ TEST(JsonVariant_As_Tests, FalseAsLong) {
|
|||||||
|
|
||||||
TEST(JsonVariant_As_Tests, FalseAsString) {
|
TEST(JsonVariant_As_Tests, FalseAsString) {
|
||||||
JsonVariant variant = false;
|
JsonVariant variant = false;
|
||||||
ASSERT_EQ(String("false"), variant.as<String>());
|
ASSERT_EQ(std::string("false"), variant.as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(JsonVariant_As_Tests, TrueAsBool) {
|
TEST(JsonVariant_As_Tests, TrueAsBool) {
|
||||||
@ -84,7 +84,7 @@ TEST(JsonVariant_As_Tests, TrueAsLong) {
|
|||||||
|
|
||||||
TEST(JsonVariant_As_Tests, TrueAsString) {
|
TEST(JsonVariant_As_Tests, TrueAsString) {
|
||||||
JsonVariant variant = true;
|
JsonVariant variant = true;
|
||||||
ASSERT_EQ(String("true"), variant.as<String>());
|
ASSERT_EQ(std::string("true"), variant.as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(JsonVariant_As_Tests, LongAsBool) {
|
TEST(JsonVariant_As_Tests, LongAsBool) {
|
||||||
@ -109,7 +109,7 @@ TEST(JsonVariant_As_Tests, NegativeLongAsDouble) {
|
|||||||
|
|
||||||
TEST(JsonVariant_As_Tests, LongAsString) {
|
TEST(JsonVariant_As_Tests, LongAsString) {
|
||||||
JsonVariant variant = 42L;
|
JsonVariant variant = 42L;
|
||||||
ASSERT_EQ(String("42"), variant.as<String>());
|
ASSERT_EQ(std::string("42"), variant.as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(JsonVariant_As_Tests, LongZeroAsDouble) {
|
TEST(JsonVariant_As_Tests, LongZeroAsDouble) {
|
||||||
@ -134,7 +134,7 @@ TEST(JsonVariant_As_Tests, NullAsLong) {
|
|||||||
|
|
||||||
TEST(JsonVariant_As_Tests, NullAsString) {
|
TEST(JsonVariant_As_Tests, NullAsString) {
|
||||||
JsonVariant variant = null;
|
JsonVariant variant = null;
|
||||||
ASSERT_EQ(String("null"), variant.as<String>());
|
ASSERT_EQ(std::string("null"), variant.as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(JsonVariant_As_Tests, NumberStringAsBool) {
|
TEST(JsonVariant_As_Tests, NumberStringAsBool) {
|
||||||
@ -181,7 +181,7 @@ TEST(JsonVariant_As_Tests, RandomStringAsCharPtr) {
|
|||||||
|
|
||||||
TEST(JsonVariant_As_Tests, RandomStringAsString) {
|
TEST(JsonVariant_As_Tests, RandomStringAsString) {
|
||||||
JsonVariant variant = "hello";
|
JsonVariant variant = "hello";
|
||||||
ASSERT_EQ(String("hello"), variant.as<String>());
|
ASSERT_EQ(std::string("hello"), variant.as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(JsonVariant_As_Tests, TrueStringAsBool) {
|
TEST(JsonVariant_As_Tests, TrueStringAsBool) {
|
||||||
@ -201,7 +201,7 @@ TEST(JsonVariant_As_Tests, ObjectAsString) {
|
|||||||
obj["key"] = "value";
|
obj["key"] = "value";
|
||||||
|
|
||||||
JsonVariant variant = obj;
|
JsonVariant variant = obj;
|
||||||
ASSERT_EQ(String("{\"key\":\"value\"}"), variant.as<String>());
|
ASSERT_EQ(std::string("{\"key\":\"value\"}"), variant.as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(JsonVariant_As_Tests, ArrayAsString) {
|
TEST(JsonVariant_As_Tests, ArrayAsString) {
|
||||||
@ -212,7 +212,7 @@ TEST(JsonVariant_As_Tests, ArrayAsString) {
|
|||||||
arr.add(2);
|
arr.add(2);
|
||||||
|
|
||||||
JsonVariant variant = arr;
|
JsonVariant variant = arr;
|
||||||
ASSERT_EQ(String("[4,2]"), variant.as<String>());
|
ASSERT_EQ(std::string("[4,2]"), variant.as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(JsonVariant_As_Tests, ArrayAsJsonArray) {
|
TEST(JsonVariant_As_Tests, ArrayAsJsonArray) {
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
// If you like this project, please add a star!
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
class ArduinoStringTests : public ::testing::Test {
|
class StringTests : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
static void eraseString(String &str) {
|
static void eraseString(std::string &str) {
|
||||||
char *p = const_cast<char *>(str.c_str());
|
char *p = const_cast<char *>(str.c_str());
|
||||||
while (*p) *p++ = '*';
|
while (*p) *p++ = '*';
|
||||||
}
|
}
|
||||||
@ -18,100 +18,100 @@ class ArduinoStringTests : public ::testing::Test {
|
|||||||
DynamicJsonBuffer _jsonBuffer;
|
DynamicJsonBuffer _jsonBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonBuffer_ParseArray) {
|
TEST_F(StringTests, JsonBuffer_ParseArray) {
|
||||||
String json("[\"hello\"]");
|
std::string json("[\"hello\"]");
|
||||||
JsonArray &array = _jsonBuffer.parseArray(json);
|
JsonArray &array = _jsonBuffer.parseArray(json);
|
||||||
eraseString(json);
|
eraseString(json);
|
||||||
ASSERT_TRUE(array.success());
|
ASSERT_TRUE(array.success());
|
||||||
ASSERT_STREQ("hello", array[0]);
|
ASSERT_STREQ("hello", array[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonBuffer_ParseObject) {
|
TEST_F(StringTests, JsonBuffer_ParseObject) {
|
||||||
String json("{\"hello\":\"world\"}");
|
std::string json("{\"hello\":\"world\"}");
|
||||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||||
eraseString(json);
|
eraseString(json);
|
||||||
ASSERT_TRUE(object.success());
|
ASSERT_TRUE(object.success());
|
||||||
ASSERT_STREQ("world", object["hello"]);
|
ASSERT_STREQ("world", object["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_Subscript) {
|
TEST_F(StringTests, JsonObject_Subscript) {
|
||||||
char json[] = "{\"key\":\"value\"}";
|
char json[] = "{\"key\":\"value\"}";
|
||||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||||
ASSERT_STREQ("value", object[String("key")]);
|
ASSERT_STREQ("value", object[std::string("key")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_ConstSubscript) {
|
TEST_F(StringTests, JsonObject_ConstSubscript) {
|
||||||
char json[] = "{\"key\":\"value\"}";
|
char json[] = "{\"key\":\"value\"}";
|
||||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||||
ASSERT_STREQ("value", object[String("key")]);
|
ASSERT_STREQ("value", object[std::string("key")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_SetKey) {
|
TEST_F(StringTests, JsonObject_SetKey) {
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
String key("hello");
|
std::string key("hello");
|
||||||
object.set(key, "world");
|
object.set(key, "world");
|
||||||
eraseString(key);
|
eraseString(key);
|
||||||
ASSERT_STREQ("world", object["hello"]);
|
ASSERT_STREQ("world", object["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_SetValue) {
|
TEST_F(StringTests, JsonObject_SetValue) {
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
String value("world");
|
std::string value("world");
|
||||||
object.set("hello", value);
|
object.set("hello", value);
|
||||||
eraseString(value);
|
eraseString(value);
|
||||||
ASSERT_STREQ("world", object["hello"]);
|
ASSERT_STREQ("world", object["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_SetKeyValue) {
|
TEST_F(StringTests, JsonObject_SetKeyValue) {
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
String key("hello");
|
std::string key("hello");
|
||||||
String value("world");
|
std::string value("world");
|
||||||
object.set(key, value);
|
object.set(key, value);
|
||||||
eraseString(key);
|
eraseString(key);
|
||||||
eraseString(value);
|
eraseString(value);
|
||||||
ASSERT_STREQ("world", object["hello"]);
|
ASSERT_STREQ("world", object["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_SetToArraySubscript) {
|
TEST_F(StringTests, JsonObject_SetToArraySubscript) {
|
||||||
JsonArray &arr = _jsonBuffer.createArray();
|
JsonArray &arr = _jsonBuffer.createArray();
|
||||||
arr.add("world");
|
arr.add("world");
|
||||||
|
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
object.set(String("hello"), arr[0]);
|
object.set(std::string("hello"), arr[0]);
|
||||||
|
|
||||||
ASSERT_STREQ("world", object["hello"]);
|
ASSERT_STREQ("world", object["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_SetToObjectSubscript) {
|
TEST_F(StringTests, JsonObject_SetToObjectSubscript) {
|
||||||
JsonObject &arr = _jsonBuffer.createObject();
|
JsonObject &arr = _jsonBuffer.createObject();
|
||||||
arr.set("x", "world");
|
arr.set("x", "world");
|
||||||
|
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
object.set(String("hello"), arr["x"]);
|
object.set(std::string("hello"), arr["x"]);
|
||||||
|
|
||||||
ASSERT_STREQ("world", object["hello"]);
|
ASSERT_STREQ("world", object["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_Get) {
|
TEST_F(StringTests, JsonObject_Get) {
|
||||||
char json[] = "{\"key\":\"value\"}";
|
char json[] = "{\"key\":\"value\"}";
|
||||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||||
ASSERT_STREQ("value", object.get(String("key")));
|
ASSERT_STREQ("value", object.get<const char *>(std::string("key")));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_GetT) {
|
TEST_F(StringTests, JsonObject_GetT) {
|
||||||
char json[] = "{\"key\":\"value\"}";
|
char json[] = "{\"key\":\"value\"}";
|
||||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||||
ASSERT_STREQ("value", object.get<const char *>(String("key")));
|
ASSERT_STREQ("value", object.get<const char *>(std::string("key")));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_IsT) {
|
TEST_F(StringTests, JsonObject_IsT) {
|
||||||
char json[] = "{\"key\":\"value\"}";
|
char json[] = "{\"key\":\"value\"}";
|
||||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||||
ASSERT_TRUE(object.is<const char *>(String("key")));
|
ASSERT_TRUE(object.is<const char *>(std::string("key")));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_CreateNestedObject) {
|
TEST_F(StringTests, JsonObject_CreateNestedObject) {
|
||||||
String key = "key";
|
std::string key = "key";
|
||||||
char json[64];
|
char json[64];
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
object.createNestedObject(key);
|
object.createNestedObject(key);
|
||||||
@ -120,8 +120,8 @@ TEST_F(ArduinoStringTests, JsonObject_CreateNestedObject) {
|
|||||||
ASSERT_STREQ("{\"key\":{}}", json);
|
ASSERT_STREQ("{\"key\":{}}", json);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) {
|
TEST_F(StringTests, JsonObject_CreateNestedArray) {
|
||||||
String key = "key";
|
std::string key = "key";
|
||||||
char json[64];
|
char json[64];
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
object.createNestedArray(key);
|
object.createNestedArray(key);
|
||||||
@ -130,99 +130,99 @@ TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) {
|
|||||||
ASSERT_STREQ("{\"key\":[]}", json);
|
ASSERT_STREQ("{\"key\":[]}", json);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_ContainsKey) {
|
TEST_F(StringTests, JsonObject_ContainsKey) {
|
||||||
char json[] = "{\"key\":\"value\"}";
|
char json[] = "{\"key\":\"value\"}";
|
||||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||||
ASSERT_TRUE(object.containsKey(String("key")));
|
ASSERT_TRUE(object.containsKey(std::string("key")));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_Remove) {
|
TEST_F(StringTests, JsonObject_Remove) {
|
||||||
char json[] = "{\"key\":\"value\"}";
|
char json[] = "{\"key\":\"value\"}";
|
||||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||||
ASSERT_EQ(1, object.size());
|
ASSERT_EQ(1, object.size());
|
||||||
object.remove(String("key"));
|
object.remove(std::string("key"));
|
||||||
ASSERT_EQ(0, object.size());
|
ASSERT_EQ(0, object.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetKey) {
|
TEST_F(StringTests, JsonObjectSubscript_SetKey) {
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
String key("hello");
|
std::string key("hello");
|
||||||
object[key] = "world";
|
object[key] = "world";
|
||||||
eraseString(key);
|
eraseString(key);
|
||||||
ASSERT_STREQ("world", object["hello"]);
|
ASSERT_STREQ("world", object["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetValue) {
|
TEST_F(StringTests, JsonObjectSubscript_SetValue) {
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
String value("world");
|
std::string value("world");
|
||||||
object["hello"] = value;
|
object["hello"] = value;
|
||||||
eraseString(value);
|
eraseString(value);
|
||||||
ASSERT_STREQ("world", object["hello"]);
|
ASSERT_STREQ("world", object["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonArray_Add) {
|
TEST_F(StringTests, JsonArray_Add) {
|
||||||
JsonArray &array = _jsonBuffer.createArray();
|
JsonArray &array = _jsonBuffer.createArray();
|
||||||
String value("hello");
|
std::string value("hello");
|
||||||
array.add(value);
|
array.add(value);
|
||||||
eraseString(value);
|
eraseString(value);
|
||||||
ASSERT_STREQ("hello", array[0]);
|
ASSERT_STREQ("hello", array[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonArray_Set) {
|
TEST_F(StringTests, JsonArray_Set) {
|
||||||
JsonArray &array = _jsonBuffer.createArray();
|
JsonArray &array = _jsonBuffer.createArray();
|
||||||
String value("world");
|
std::string value("world");
|
||||||
array.add("hello");
|
array.add("hello");
|
||||||
array.set(0, value);
|
array.set(0, value);
|
||||||
eraseString(value);
|
eraseString(value);
|
||||||
ASSERT_STREQ("world", array[0]);
|
ASSERT_STREQ("world", array[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonArraySubscript) {
|
TEST_F(StringTests, JsonArraySubscript) {
|
||||||
JsonArray &array = _jsonBuffer.createArray();
|
JsonArray &array = _jsonBuffer.createArray();
|
||||||
String value("world");
|
std::string value("world");
|
||||||
array.add("hello");
|
array.add("hello");
|
||||||
array[0] = value;
|
array[0] = value;
|
||||||
eraseString(value);
|
eraseString(value);
|
||||||
ASSERT_STREQ("world", array[0]);
|
ASSERT_STREQ("world", array[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonArray_PrintTo) {
|
TEST_F(StringTests, JsonArray_PrintTo) {
|
||||||
JsonArray &array = _jsonBuffer.createArray();
|
JsonArray &array = _jsonBuffer.createArray();
|
||||||
array.add(4);
|
array.add(4);
|
||||||
array.add(2);
|
array.add(2);
|
||||||
String json;
|
std::string json;
|
||||||
array.printTo(json);
|
array.printTo(json);
|
||||||
ASSERT_EQ(String("[4,2]"), json);
|
ASSERT_EQ(std::string("[4,2]"), json);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonArray_PrettyPrintTo) {
|
TEST_F(StringTests, JsonArray_PrettyPrintTo) {
|
||||||
JsonArray &array = _jsonBuffer.createArray();
|
JsonArray &array = _jsonBuffer.createArray();
|
||||||
array.add(4);
|
array.add(4);
|
||||||
array.add(2);
|
array.add(2);
|
||||||
String json;
|
std::string json;
|
||||||
array.prettyPrintTo(json);
|
array.prettyPrintTo(json);
|
||||||
ASSERT_EQ(String("[\r\n 4,\r\n 2\r\n]"), json);
|
ASSERT_EQ(std::string("[\r\n 4,\r\n 2\r\n]"), json);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_PrintTo) {
|
TEST_F(StringTests, JsonObject_PrintTo) {
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
object["key"] = "value";
|
object["key"] = "value";
|
||||||
String json;
|
std::string json;
|
||||||
object.printTo(json);
|
object.printTo(json);
|
||||||
ASSERT_EQ(String("{\"key\":\"value\"}"), json);
|
ASSERT_EQ(std::string("{\"key\":\"value\"}"), json);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonObject_PrettyPrintTo) {
|
TEST_F(StringTests, JsonObject_PrettyPrintTo) {
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
object["key"] = "value";
|
object["key"] = "value";
|
||||||
String json;
|
std::string json;
|
||||||
object.prettyPrintTo(json);
|
object.prettyPrintTo(json);
|
||||||
ASSERT_EQ(String("{\r\n \"key\": \"value\"\r\n}"), json);
|
ASSERT_EQ(std::string("{\r\n \"key\": \"value\"\r\n}"), json);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonBuffer_GrowWhenAddingNewKey) {
|
TEST_F(StringTests, JsonBuffer_GrowWhenAddingNewKey) {
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
String key1("hello"), key2("world");
|
std::string key1("hello"), key2("world");
|
||||||
|
|
||||||
object[key1] = 1;
|
object[key1] = 1;
|
||||||
size_t sizeBefore = _jsonBuffer.size();
|
size_t sizeBefore = _jsonBuffer.size();
|
||||||
@ -232,9 +232,9 @@ TEST_F(ArduinoStringTests, JsonBuffer_GrowWhenAddingNewKey) {
|
|||||||
ASSERT_GT(sizeAfter - sizeBefore, key2.size());
|
ASSERT_GT(sizeAfter - sizeBefore, key2.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ArduinoStringTests, JsonBuffer_DontGrowWhenReusingKey) {
|
TEST_F(StringTests, JsonBuffer_DontGrowWhenReusingKey) {
|
||||||
JsonObject &object = _jsonBuffer.createObject();
|
JsonObject &object = _jsonBuffer.createObject();
|
||||||
String key("hello");
|
std::string key("hello");
|
||||||
|
|
||||||
object[key] = 1;
|
object[key] = 1;
|
||||||
size_t sizeBefore = _jsonBuffer.size();
|
size_t sizeBefore = _jsonBuffer.size();
|
||||||
@ -243,3 +243,10 @@ TEST_F(ArduinoStringTests, JsonBuffer_DontGrowWhenReusingKey) {
|
|||||||
|
|
||||||
ASSERT_EQ(sizeBefore, sizeAfter);
|
ASSERT_EQ(sizeBefore, sizeAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(StringTests, JsonBuffer_strdup) {
|
||||||
|
std::string original("hello");
|
||||||
|
char *copy = _jsonBuffer.strdup(original);
|
||||||
|
original[0] = 'w';
|
||||||
|
ASSERT_STREQ("hello", copy);
|
||||||
|
}
|
Reference in New Issue
Block a user