forked from bblanchon/ArduinoJson
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
146a76247c | |||
f28157cab7 | |||
1ce16ce449 | |||
c310e7e8b7 | |||
aa2ef79e55 | |||
7ad57f1c33 | |||
cbfd331e50 | |||
e6f55b1f6f | |||
bb805e93cb | |||
deb57b960b | |||
8a9b918bf4 | |||
2f6f3d0629 | |||
a60b35f41c | |||
6757f35a3a | |||
ffb9b6d1ba | |||
e401498e4a | |||
d30e940b3b | |||
05ea5e04c8 | |||
a7ef99d0fe | |||
f2a8b52c2c | |||
409ca7ee4e | |||
387b565705 | |||
96f486001d | |||
a498abc14a | |||
c64340a9bb |
5
.mbedignore
Normal file
5
.mbedignore
Normal file
@ -0,0 +1,5 @@
|
||||
.github/
|
||||
examples/
|
||||
scripts/
|
||||
test/
|
||||
third-party/
|
73
CHANGELOG.md
73
CHANGELOG.md
@ -1,6 +1,71 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v5.7.1
|
||||
------
|
||||
|
||||
* Added support for PROGMEM (issue #76)
|
||||
* Fixed compilation error when index is not an `int` (issue #381)
|
||||
|
||||
v5.7.0
|
||||
------
|
||||
|
||||
* 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)
|
||||
|
||||
**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
|
||||
------
|
||||
|
||||
* Fixed `array[idx].as<JsonVariant>()` and `object[key].as<JsonVariant>()`
|
||||
* Fixed return value of `JsonObject::set()` (issue #350)
|
||||
* Fixed undefined behavior in `Prettyfier` and `Print` (issue #354)
|
||||
* Fixed parser that incorrectly rejected floats containing a `+` (issue #349)
|
||||
|
||||
v5.6.6
|
||||
------
|
||||
|
||||
* Fixed `-Wparentheses` warning introduced in v5.6.5 (PR #335 by @nuket)
|
||||
* Added `.mbedignore` for ARM mbdeb (PR #334 by @nuket)
|
||||
* Fixed `JsonVariant::success()` which didn't propagate `JsonArray::success()` nor `JsonObject::success()` (issue #342).
|
||||
|
||||
v5.6.5
|
||||
------
|
||||
|
||||
* `as<char*>()` now returns `true` when input is `null` (issue #330)
|
||||
|
||||
v5.6.4
|
||||
------
|
||||
|
||||
* Fixed error in float serialization (issue #324)
|
||||
|
||||
v5.6.3
|
||||
------
|
||||
|
||||
@ -112,7 +177,7 @@ v5.0.3
|
||||
v5.0.2
|
||||
------
|
||||
|
||||
* Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the
|
||||
* Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the
|
||||
`StaticJsonBuffer` is too small to hold a copy of the string
|
||||
* Fixed Clang warning "register specifier is deprecated" (issue #102)
|
||||
* Fixed GCC warning "declaration shadows a member" (issue #103)
|
||||
@ -228,14 +293,14 @@ v3.1
|
||||
|
||||
Old generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
JsonObject<3> root;
|
||||
root.add("sensor", "gps");
|
||||
root.add("time", 1351824120);
|
||||
root.add("data", array);
|
||||
|
||||
New generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
JsonObject<3> root;
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
root["data"] = array;
|
||||
@ -292,7 +357,7 @@ v1.1
|
||||
* Example: changed `char* json` into `char[] json` so that the bytes are not write protected
|
||||
* Fixed parsing bug when the JSON contains multi-dimensional arrays
|
||||
|
||||
v1.0
|
||||
v1.0
|
||||
----
|
||||
|
||||
Initial release
|
||||
|
@ -86,9 +86,6 @@ From Arduino's Forum user `jflaplante`:
|
||||
> I tried aJson json-arduino before trying your library. I always ran into memory problem after a while.
|
||||
> I have no such problem so far with your library. It is working perfectly with my web services.
|
||||
|
||||
From Arduino's Forum user `gbathree`:
|
||||
> Thanks so much - this is an awesome library! If you want to see what we're doing with it - the project is located at www.photosynq.org.
|
||||
|
||||
From StackOverflow user `thegreendroid`:
|
||||
> It has a really elegant, simple API and it works like a charm on embedded and Windows/Linux platforms. We recently started using this on an embedded project and I can vouch for its quality.
|
||||
|
||||
@ -124,6 +121,8 @@ Special thanks to the following persons and companies who made generous donation
|
||||
* Nick Koumaris <img alt='Greece' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1f7.svg' width='18' height='18'>
|
||||
* Jon Williams <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Kestutis Liaugminas <img alt='Lithuania' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1f9.svg' width='18' height='18'>
|
||||
* Darlington Adibe <img alt='Nigeria' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1ec.svg' width='18' height='18'>
|
||||
* Yoeri Kroon <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
|
||||
---
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 5.6.3.{build}
|
||||
version: 5.7.1.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
|
51
examples/ProgmemExample/ProgmemExample.ino
Normal file
51
examples/ProgmemExample/ProgmemExample.ino
Normal file
@ -0,0 +1,51 @@
|
||||
// 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 PROGMEM with ArduinoJson.
|
||||
// Please don't see this as an invitation to use PROGMEM.
|
||||
// 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() {
|
||||
#if ARDUINO_ARCH_AVR
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
// You can use a Flash String as your JSON input.
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
JsonObject& root =
|
||||
jsonBuffer.parseObject(F("{\"sensor\":\"gps\",\"time\":1351824120,"
|
||||
"\"data\":[48.756080,2.302038]}"));
|
||||
|
||||
// You can use a Flash String to get an element of a JsonObject
|
||||
// No duplication is done.
|
||||
long time = root[F("time")];
|
||||
|
||||
// You can use a Flash String to set an element of a JsonObject
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
root[F("time")] = time;
|
||||
|
||||
// You can set a Flash String to a JsonObject or JsonArray:
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
root["sensor"] = F("gps");
|
||||
|
||||
#else
|
||||
|
||||
#warning PROGMEM is only supported on AVR architecture
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
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
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
#include "ArduinoJson/Internals/JsonParser.ipp"
|
||||
#include "ArduinoJson/Internals/JsonSerializer.ipp"
|
||||
#include "ArduinoJson/JsonArray.ipp"
|
||||
#include "ArduinoJson/JsonBuffer.ipp"
|
||||
#include "ArduinoJson/JsonObject.ipp"
|
||||
|
@ -22,12 +22,26 @@
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
|
||||
// arduino has its own implementation of String to replace std::string
|
||||
#ifndef ARDUINOJSON_USE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_USE_ARDUINO_STRING 1
|
||||
// Arduino has its own implementation of String to replace std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||
#endif
|
||||
|
||||
// arduino doesn't support STL stream
|
||||
// On AVR archiecture, we can use PROGMEM
|
||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 1
|
||||
#else
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 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
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM 0
|
||||
#endif
|
||||
@ -42,6 +56,11 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// low value to prevent stack overflow
|
||||
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
|
||||
#endif
|
||||
|
||||
#else // assume this is a computer
|
||||
|
||||
// on a computer we have plenty of memory so we can use doubles
|
||||
@ -68,8 +87,18 @@
|
||||
#endif
|
||||
|
||||
// on a computer, we can use std::string
|
||||
#ifndef ARDUINOJSON_USE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_USE_ARDUINO_STRING 0
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
#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
|
||||
|
||||
// PROGMEM is only available on AVR architecture
|
||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||
#endif
|
||||
|
||||
// on a computer, we can assume that the STL is there
|
||||
@ -82,6 +111,11 @@
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
// on a computer, we should have a lot of space on the stack
|
||||
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
|
||||
|
@ -8,26 +8,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Print.hpp"
|
||||
#include "../String.hpp"
|
||||
#include "StringFuncs.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A Print implementation that allows to write in a String
|
||||
template <typename TString>
|
||||
class DynamicStringBuilder : public Print {
|
||||
public:
|
||||
DynamicStringBuilder(String &str) : _str(str) {}
|
||||
DynamicStringBuilder(TString &str) : _str(str) {}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
// Need to cast to char, otherwise String will print a number (issue #120)
|
||||
_str += static_cast<char>(c);
|
||||
StringFuncs<TString>::append(_str, static_cast<char>(c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
DynamicStringBuilder &operator=(const DynamicStringBuilder &);
|
||||
|
||||
String &_str;
|
||||
TString &_str;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class JsonParser {
|
||||
|
||||
static inline bool isLetterOrNumber(char c) {
|
||||
return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
|
||||
isInRange(c, 'A', 'Z') || c == '-' || c == '.';
|
||||
isInRange(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) {
|
||||
|
@ -8,12 +8,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
#include "DummyPrint.hpp"
|
||||
#include "DynamicStringBuilder.hpp"
|
||||
#include "IndentedPrint.hpp"
|
||||
#include "JsonSerializer.hpp"
|
||||
#include "JsonWriter.hpp"
|
||||
#include "Prettyfier.hpp"
|
||||
#include "StaticStringBuilder.hpp"
|
||||
#include "DynamicStringBuilder.hpp"
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include "StreamPrintAdapter.hpp"
|
||||
@ -31,7 +33,7 @@ class JsonPrintable {
|
||||
public:
|
||||
size_t printTo(Print &print) const {
|
||||
JsonWriter writer(print);
|
||||
downcast().writeTo(writer);
|
||||
JsonSerializer::serialize(downcast(), writer);
|
||||
return writer.bytesWritten();
|
||||
}
|
||||
|
||||
@ -48,8 +50,10 @@ class JsonPrintable {
|
||||
return printTo(sb);
|
||||
}
|
||||
|
||||
size_t printTo(String &str) const {
|
||||
DynamicStringBuilder sb(str);
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<StringFuncs<TString>::has_append, size_t>::type
|
||||
printTo(TString &str) const {
|
||||
DynamicStringBuilder<TString> sb(str);
|
||||
return printTo(sb);
|
||||
}
|
||||
|
||||
@ -68,8 +72,10 @@ class JsonPrintable {
|
||||
return prettyPrintTo(indentedPrint);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(String &str) const {
|
||||
DynamicStringBuilder sb(str);
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<StringFuncs<TString>::has_append, size_t>::type
|
||||
prettyPrintTo(TString &str) const {
|
||||
DynamicStringBuilder<TString> sb(str);
|
||||
return prettyPrintTo(sb);
|
||||
}
|
||||
|
||||
@ -84,7 +90,9 @@ class JsonPrintable {
|
||||
}
|
||||
|
||||
private:
|
||||
const T &downcast() const { return *static_cast<const T *>(this); }
|
||||
const T &downcast() const {
|
||||
return *static_cast<const T *>(this);
|
||||
}
|
||||
};
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
|
33
include/ArduinoJson/Internals/JsonSerializer.hpp
Normal file
33
include/ArduinoJson/Internals/JsonSerializer.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
// 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 "JsonWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class JsonArray;
|
||||
class JsonArraySubscript;
|
||||
class JsonObject;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
class JsonVariant;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
class JsonSerializer {
|
||||
public:
|
||||
static void serialize(const JsonArray &, JsonWriter &);
|
||||
static void serialize(const JsonArraySubscript &, JsonWriter &);
|
||||
static void serialize(const JsonObject &, JsonWriter &);
|
||||
template <typename TKey>
|
||||
static void serialize(const JsonObjectSubscript<TKey> &, JsonWriter &);
|
||||
static void serialize(const JsonVariant &, JsonWriter &);
|
||||
};
|
||||
}
|
||||
}
|
101
include/ArduinoJson/Internals/JsonSerializer.ipp
Normal file
101
include/ArduinoJson/Internals/JsonSerializer.ipp
Normal file
@ -0,0 +1,101 @@
|
||||
// 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 "../JsonArray.hpp"
|
||||
#include "../JsonArraySubscript.hpp"
|
||||
#include "../JsonObject.hpp"
|
||||
#include "../JsonObjectSubscript.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "JsonSerializer.hpp"
|
||||
|
||||
inline void ArduinoJson::Internals::JsonSerializer::serialize(
|
||||
const JsonArray& array, JsonWriter& writer) {
|
||||
writer.beginArray();
|
||||
|
||||
JsonArray::const_iterator it = array.begin();
|
||||
while (it != array.end()) {
|
||||
serialize(*it, writer);
|
||||
|
||||
++it;
|
||||
if (it == array.end()) break;
|
||||
|
||||
writer.writeComma();
|
||||
}
|
||||
|
||||
writer.endArray();
|
||||
}
|
||||
|
||||
inline void ArduinoJson::Internals::JsonSerializer::serialize(
|
||||
const JsonArraySubscript& arraySubscript, JsonWriter& writer) {
|
||||
serialize(arraySubscript.as<JsonVariant>(), writer);
|
||||
}
|
||||
|
||||
inline void ArduinoJson::Internals::JsonSerializer::serialize(
|
||||
const JsonObject& object, JsonWriter& writer) {
|
||||
writer.beginObject();
|
||||
|
||||
JsonObject::const_iterator it = object.begin();
|
||||
while (it != object.end()) {
|
||||
writer.writeString(it->key);
|
||||
writer.writeColon();
|
||||
serialize(it->value, writer);
|
||||
|
||||
++it;
|
||||
if (it == object.end()) break;
|
||||
|
||||
writer.writeComma();
|
||||
}
|
||||
|
||||
writer.endObject();
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline void ArduinoJson::Internals::JsonSerializer::serialize(
|
||||
const JsonObjectSubscript<TKey>& objectSubscript, JsonWriter& writer) {
|
||||
serialize(objectSubscript.template as<JsonVariant>(), writer);
|
||||
}
|
||||
|
||||
inline void ArduinoJson::Internals::JsonSerializer::serialize(
|
||||
const JsonVariant& variant, JsonWriter& writer) {
|
||||
switch (variant._type) {
|
||||
case JSON_UNDEFINED:
|
||||
return;
|
||||
|
||||
case JSON_ARRAY:
|
||||
serialize(*variant._content.asArray, writer);
|
||||
return;
|
||||
|
||||
case JSON_OBJECT:
|
||||
serialize(*variant._content.asObject, writer);
|
||||
return;
|
||||
|
||||
case JSON_STRING:
|
||||
writer.writeString(variant._content.asString);
|
||||
return;
|
||||
|
||||
case JSON_UNPARSED:
|
||||
writer.writeRaw(variant._content.asString);
|
||||
return;
|
||||
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
writer.writeRaw('-');
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
writer.writeInteger(variant._content.asInteger);
|
||||
return;
|
||||
|
||||
case JSON_BOOLEAN:
|
||||
writer.writeBoolean(variant._content.asInteger != 0);
|
||||
return;
|
||||
|
||||
default:
|
||||
uint8_t decimals =
|
||||
static_cast<uint8_t>(variant._type - JSON_FLOAT_0_DECIMALS);
|
||||
writer.writeFloat(variant._content.asFloat, decimals);
|
||||
}
|
||||
}
|
@ -8,17 +8,19 @@
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace TypeTraits {
|
||||
namespace Internals {
|
||||
|
||||
// A meta-function that returns true if T is a reference
|
||||
template <typename T>
|
||||
struct IsReference {
|
||||
static const bool value = false;
|
||||
struct JsonVariantDefault {
|
||||
static T get() {
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IsReference<T&> {
|
||||
static const bool value = true;
|
||||
};
|
||||
struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
|
||||
}
|
||||
}
|
@ -81,7 +81,7 @@ class JsonWriter {
|
||||
}
|
||||
}
|
||||
|
||||
void writeFloat(JsonFloat value, int digits = 2) {
|
||||
void writeFloat(JsonFloat value, uint8_t digits = 2) {
|
||||
if (Polyfills::isNaN(value)) return writeRaw("NaN");
|
||||
|
||||
if (value < 0.0) {
|
||||
@ -98,6 +98,9 @@ class JsonWriter {
|
||||
powersOf10 = 0;
|
||||
}
|
||||
|
||||
// Round up last digit (so that print(1.999, 2) prints as "2.00")
|
||||
value += getRoundingBias(digits);
|
||||
|
||||
// Extract the integer part of the value and print it
|
||||
JsonUInt int_part = static_cast<JsonUInt>(value);
|
||||
JsonFloat remainder = value - static_cast<JsonFloat>(int_part);
|
||||
@ -115,9 +118,6 @@ class JsonWriter {
|
||||
char currentDigit = char(remainder);
|
||||
remainder -= static_cast<JsonFloat>(currentDigit);
|
||||
|
||||
// Round up last digit (so that print(1.999, 2) prints as "2.00")
|
||||
if (digits == 0 && remainder >= 0.5) currentDigit++;
|
||||
|
||||
// Print
|
||||
writeRaw(char('0' + currentDigit));
|
||||
}
|
||||
@ -135,16 +135,15 @@ class JsonWriter {
|
||||
|
||||
void writeInteger(JsonUInt value) {
|
||||
char buffer[22];
|
||||
char *ptr = buffer + sizeof(buffer) - 1;
|
||||
|
||||
uint8_t i = 0;
|
||||
*ptr = 0;
|
||||
do {
|
||||
buffer[i++] = static_cast<char>(value % 10 + '0');
|
||||
*--ptr = static_cast<char>(value % 10 + '0');
|
||||
value /= 10;
|
||||
} while (value);
|
||||
|
||||
while (i > 0) {
|
||||
writeRaw(buffer[--i]);
|
||||
}
|
||||
writeRaw(ptr);
|
||||
}
|
||||
|
||||
void writeRaw(const char *s) {
|
||||
@ -160,6 +159,26 @@ class JsonWriter {
|
||||
|
||||
private:
|
||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||
|
||||
static JsonFloat getLastDigit(uint8_t digits) {
|
||||
// Designed as a compromise between code size and speed
|
||||
switch (digits) {
|
||||
case 0:
|
||||
return 1e-0;
|
||||
case 1:
|
||||
return 1e-1;
|
||||
case 2:
|
||||
return 1e-2;
|
||||
case 3:
|
||||
return 1e-3;
|
||||
default:
|
||||
return getLastDigit(uint8_t(digits - 4)) * 1e-4;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE static JsonFloat getRoundingBias(uint8_t digits) {
|
||||
return 0.5 * getLastDigit(digits);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -66,28 +66,46 @@ class Prettyfier : public Print {
|
||||
}
|
||||
|
||||
size_t writeBlockClose(uint8_t c) {
|
||||
return unindentIfNeeded() + _sink.write(c);
|
||||
size_t n = 0;
|
||||
n += unindentIfNeeded();
|
||||
n += _sink.write(c);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeBlockOpen(uint8_t c) {
|
||||
return indentIfNeeded() + _sink.write(c);
|
||||
size_t n = 0;
|
||||
n += indentIfNeeded();
|
||||
n += _sink.write(c);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeColon() {
|
||||
return _sink.write(':') + _sink.write(' ');
|
||||
size_t n = 0;
|
||||
n += _sink.write(':');
|
||||
n += _sink.write(' ');
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeComma() {
|
||||
return _sink.write(',') + _sink.println();
|
||||
size_t n = 0;
|
||||
n += _sink.write(',');
|
||||
n += _sink.println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeQuoteOpen() {
|
||||
_inString = true;
|
||||
return indentIfNeeded() + _sink.write('"');
|
||||
size_t n = 0;
|
||||
n += indentIfNeeded();
|
||||
n += _sink.write('"');
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeNormalChar(uint8_t c) {
|
||||
return indentIfNeeded() + _sink.write(c);
|
||||
size_t n = 0;
|
||||
n += indentIfNeeded();
|
||||
n += _sink.write(c);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t indentIfNeeded() {
|
||||
|
121
include/ArduinoJson/Internals/StringFuncs.hpp
Normal file
121
include/ArduinoJson/Internals/StringFuncs.hpp
Normal file
@ -0,0 +1,121 @@
|
||||
// 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 has_equals = true;
|
||||
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 <size_t N>
|
||||
struct StringFuncs<const 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 has_equals = 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
|
||||
|
||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||
template <>
|
||||
struct StringFuncs<const __FlashStringHelper*> {
|
||||
static bool equals(const __FlashStringHelper* str, const char* expected) {
|
||||
return strcmp_P((PGM_P)str, expected) == 0;
|
||||
}
|
||||
|
||||
template <typename Buffer>
|
||||
static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
|
||||
if (!str) return NULL;
|
||||
size_t size = strlen_P((PGM_P)str) + 1;
|
||||
void* dup = buffer->alloc(size);
|
||||
if (dup != NULL) memcpy_P(dup, (PGM_P)str, size);
|
||||
return static_cast<char*>(dup);
|
||||
}
|
||||
|
||||
static const bool has_append = false;
|
||||
static const bool has_equals = true;
|
||||
static const bool should_duplicate = true;
|
||||
};
|
||||
#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/List.hpp"
|
||||
#include "Internals/ReferenceType.hpp"
|
||||
#include "Internals/StringFuncs.hpp"
|
||||
#include "Internals/ValueSetter.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsReference.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
@ -40,15 +42,6 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
public Internals::List<JsonVariant>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
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.
|
||||
// You should not call this constructor directly.
|
||||
// Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray().
|
||||
@ -57,7 +50,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
|
||||
// Gets the value at the specified index
|
||||
JsonVariant operator[](size_t index) const {
|
||||
return get(index);
|
||||
return get<JsonVariant>(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(double value);
|
||||
// bool add(const char*);
|
||||
template <typename T>
|
||||
bool add(
|
||||
T value,
|
||||
typename TypeTraits::EnableIf<
|
||||
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) {
|
||||
return addNode<T>(value);
|
||||
}
|
||||
// bool add(const char[]);
|
||||
// bool add(const char[N]);
|
||||
// bool add(RawJson);
|
||||
// bool add(const std::string&)
|
||||
// bool add(const String&)
|
||||
// bool add(const JsonVariant&);
|
||||
// bool add(JsonArray&);
|
||||
// bool add(JsonObject&);
|
||||
template <typename T>
|
||||
bool add(const T &value,
|
||||
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
|
||||
return addNode<T &>(const_cast<T &>(value));
|
||||
bool add(const T &value) {
|
||||
// reduce the number of template function instanciation to reduce code size
|
||||
return addNodeImpl<typename TypeTraits::ConstRefOrConstPtr<T>::type>(value);
|
||||
}
|
||||
// bool add(float value, uint8_t decimals);
|
||||
// bool add(double value, uint8_t decimals);
|
||||
template <typename T>
|
||||
bool add(T value, uint8_t decimals,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
||||
return addNode<JsonVariant>(JsonVariant(value, decimals));
|
||||
bool add(T value, uint8_t decimals) {
|
||||
return add(JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
// 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, int value);
|
||||
// bool set(size_t index, short value);
|
||||
template <typename T>
|
||||
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 std::string&)
|
||||
// bool set(size_t index, const String&)
|
||||
// bool set(size_t index, const JsonVariant&);
|
||||
// bool set(size_t index, JsonArray&);
|
||||
// bool set(size_t index, JsonObject&);
|
||||
template <typename T>
|
||||
bool set(size_t index, const T &value,
|
||||
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
|
||||
return setNodeAt<T &>(index, const_cast<T &>(value));
|
||||
bool set(size_t index, const T &value) {
|
||||
// reduce the number of template function instanciation to reduce code size
|
||||
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, double value, uint8_t decimals = 2);
|
||||
template <typename T>
|
||||
bool set(size_t index, T value, uint8_t decimals,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
||||
return setNodeAt<const JsonVariant &>(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();
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||
bool>::type
|
||||
set(size_t index, T value, uint8_t decimals) {
|
||||
return set(index, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
// Gets the value at the specified index.
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
|
||||
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.
|
||||
@ -170,26 +149,9 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Serialize the array to the specified JsonWriter.
|
||||
void writeTo(Internals::JsonWriter &writer) const {
|
||||
writer.beginArray();
|
||||
|
||||
const node_type *child = _firstNode;
|
||||
while (child) {
|
||||
child->content.writeTo(writer);
|
||||
|
||||
child = child->next;
|
||||
if (!child) break;
|
||||
|
||||
writer.writeComma();
|
||||
}
|
||||
|
||||
writer.endArray();
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T, size_t N>
|
||||
bool copyFrom(T(&array)[N]) {
|
||||
bool copyFrom(T (&array)[N]) {
|
||||
return copyFrom(array, N);
|
||||
}
|
||||
|
||||
@ -205,7 +167,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
|
||||
// Imports a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
bool copyFrom(T(&array)[N1][N2]) {
|
||||
bool copyFrom(T (&array)[N1][N2]) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < N1; i++) {
|
||||
JsonArray &nestedArray = createNestedArray();
|
||||
@ -218,7 +180,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T, size_t N>
|
||||
size_t copyTo(T(&array)[N]) const {
|
||||
size_t copyTo(T (&array)[N]) const {
|
||||
return copyTo(array, N);
|
||||
}
|
||||
|
||||
@ -233,7 +195,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
|
||||
// Exports a 2D array
|
||||
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;
|
||||
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
|
||||
it->asArray().copyTo(array[i++]);
|
||||
@ -247,22 +209,22 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
return node;
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
bool setNodeAt(size_t index, TValue value) {
|
||||
template <typename TValueRef>
|
||||
bool setNodeAt(size_t index, TValueRef value) {
|
||||
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>
|
||||
bool addNode(TValue value) {
|
||||
template <typename TValueRef>
|
||||
bool addNodeImpl(TValueRef value) {
|
||||
node_type *node = addNewNode();
|
||||
return node != NULL && setNodeValue<TValue>(node, value);
|
||||
}
|
||||
if (!node) return false;
|
||||
|
||||
template <typename T>
|
||||
bool setNodeValue(node_type *node, T value) {
|
||||
node->content = value;
|
||||
return true;
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content,
|
||||
value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -8,37 +8,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
#include "JsonArraySubscript.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <>
|
||||
inline bool JsonArray::setNodeValue(node_type *node, String &value) {
|
||||
const char *copy = _buffer->strdup(value);
|
||||
if (!copy) return false;
|
||||
node->content = copy;
|
||||
return true;
|
||||
inline JsonVariant::JsonVariant(const JsonArray &array) {
|
||||
if (array.success()) {
|
||||
_type = Internals::JSON_ARRAY;
|
||||
_content.asArray = const_cast<JsonArray *>(&array);
|
||||
} else {
|
||||
_type = Internals::JSON_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonArray &JsonVariant::defaultValue<JsonArray>() {
|
||||
return JsonArray::invalid();
|
||||
inline JsonVariant::JsonVariant(const JsonObject &object) {
|
||||
if (object.success()) {
|
||||
_type = Internals::JSON_OBJECT;
|
||||
_content.asObject = const_cast<JsonObject *>(&object);
|
||||
} else {
|
||||
_type = Internals::JSON_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Internals {
|
||||
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();
|
||||
struct JsonVariantDefault<JsonArray> {
|
||||
static JsonArray &get() {
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline JsonArray &JsonVariant::asArray() const {
|
||||
@ -53,10 +52,11 @@ inline JsonArray &JsonArray::createNestedArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
inline JsonArray &JsonObject::createNestedArray(JsonObjectKey key) {
|
||||
template <typename TString>
|
||||
inline JsonArray &JsonObject::createNestedArray(const TString &key) {
|
||||
if (!_buffer) return JsonArray::invalid();
|
||||
JsonArray &array = _buffer->createArray();
|
||||
setNodeAt<const JsonVariant &>(key, array);
|
||||
set(key, array);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
@ -21,24 +21,14 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
||||
_array.set<const JsonVariant&>(_index, src);
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<JsonArray::CanSet<T&>::value,
|
||||
JsonArraySubscript>::type&
|
||||
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);
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -46,10 +36,6 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
return _index < _array.size();
|
||||
}
|
||||
|
||||
FORCE_INLINE operator JsonVariant() const {
|
||||
return _array.get(_index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const {
|
||||
return _array.get<T>(_index);
|
||||
@ -60,12 +46,8 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
return _array.is<T>(_index);
|
||||
}
|
||||
|
||||
void writeTo(Internals::JsonWriter& writer) const {
|
||||
_array.get(_index).writeTo(writer);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
void set(TValue value) {
|
||||
FORCE_INLINE void set(const TValue& value) {
|
||||
_array.set(_index, value);
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "JsonVariant.hpp"
|
||||
#include "String.hpp"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
@ -58,66 +57,57 @@ class JsonBuffer {
|
||||
// writable
|
||||
// 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
|
||||
// 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
|
||||
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);
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// The First argument is a pointer to the JSON string, the memory must be
|
||||
// writable
|
||||
// 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
|
||||
// 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
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
char *strdup(const char *src) {
|
||||
return src ? strdup(src, strlen(src)) : NULL;
|
||||
template <typename TString>
|
||||
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.
|
||||
// Return a pointer to the allocated memory or NULL if allocation fails.
|
||||
@ -133,24 +123,6 @@ class JsonBuffer {
|
||||
return bytes;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
char *strdup(const char *, size_t);
|
||||
|
||||
// Default value of nesting limit of parseArray() and parseObject().
|
||||
//
|
||||
// The nesting limit is a contain 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 = 10;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -36,11 +36,3 @@ inline ArduinoJson::JsonVariant ArduinoJson::JsonBuffer::parse(
|
||||
Internals::JsonParser parser(this, json, nestingLimit);
|
||||
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
|
||||
|
||||
#include "String.hpp"
|
||||
#include "Internals/JsonBufferAllocated.hpp"
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/List.hpp"
|
||||
#include "Internals/ReferenceType.hpp"
|
||||
#include "Internals/StringFuncs.hpp"
|
||||
#include "Internals/ValueSetter.hpp"
|
||||
#include "JsonPair.hpp"
|
||||
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsReference.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
@ -40,27 +41,19 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
public Internals::List<JsonPair>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
public:
|
||||
// A meta-function that returns true if type T can be used in
|
||||
// JsonObject::set()
|
||||
template <typename T>
|
||||
struct CanSet {
|
||||
static const bool value = JsonVariant::IsConstructibleFrom<T>::value ||
|
||||
TypeTraits::IsSame<T, String&>::value ||
|
||||
TypeTraits::IsSame<T, const String&>::value;
|
||||
};
|
||||
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not use this constructor directly.
|
||||
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
|
||||
explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
JsonObjectSubscript<const char*> operator[](const char* key);
|
||||
JsonObjectSubscript<const String&> operator[](const String& key);
|
||||
template <typename TString>
|
||||
JsonObjectSubscript<TString> operator[](const TString& key);
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
JsonVariant operator[](JsonObjectKey key) const {
|
||||
return get(key);
|
||||
template <typename TString>
|
||||
JsonVariant operator[](const TString& key) const {
|
||||
return get<JsonVariant>(key);
|
||||
}
|
||||
|
||||
// Sets the specified key with the specified value.
|
||||
@ -73,67 +66,62 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
// bool set(TKey key, double value);
|
||||
// bool set(TKey key, const char* value);
|
||||
// bool set(TKey key, RawJson value);
|
||||
template <typename T>
|
||||
bool set(
|
||||
JsonObjectKey key, T value,
|
||||
typename TypeTraits::EnableIf<
|
||||
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) {
|
||||
return setNodeAt<T>(key, value);
|
||||
}
|
||||
// bool set(Key, String&);
|
||||
// bool set(Key, JsonArray&);
|
||||
// bool set(Key, JsonObject&);
|
||||
// bool set(Key, JsonVariant&);
|
||||
template <typename T>
|
||||
bool set(JsonObjectKey key, const T& value,
|
||||
typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) {
|
||||
return setNodeAt<T&>(key, const_cast<T&>(value));
|
||||
template <typename TValue, typename TString>
|
||||
bool set(const TString& key, const TValue& value) {
|
||||
// reduce the number of template function instanciation to reduce code size
|
||||
return setNodeAt<typename TypeTraits::ConstRefOrConstPtr<TString>::type,
|
||||
typename TypeTraits::ConstRefOrConstPtr<TValue>::type>(
|
||||
key, value);
|
||||
}
|
||||
// bool set(Key, float value, uint8_t decimals);
|
||||
// bool set(Key, double value, uint8_t decimals);
|
||||
template <typename TValue>
|
||||
bool set(JsonObjectKey key, TValue value, uint8_t decimals,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) {
|
||||
return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals));
|
||||
template <typename TValue, typename TString>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value,
|
||||
bool>::type
|
||||
set(const TString& key, TValue value, uint8_t decimals) {
|
||||
return set(key, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
JsonVariant get(JsonObjectKey key) const {
|
||||
node_type* node = getNodeAt(key.c_str());
|
||||
return node ? node->content.value : JsonVariant();
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type get(JsonObjectKey key) const {
|
||||
node_type* node = getNodeAt(key.c_str());
|
||||
return node ? node->content.value.as<T>() : JsonVariant::defaultValue<T>();
|
||||
template <typename TValue, typename TString>
|
||||
typename Internals::JsonVariantAs<TValue>::type get(
|
||||
const TString& key) const {
|
||||
node_type* node = getNodeAt(key);
|
||||
return node ? node->content.value.as<TValue>()
|
||||
: Internals::JsonVariantDefault<TValue>::get();
|
||||
}
|
||||
|
||||
// Checks the type of the value associated with the specified key.
|
||||
template <typename T>
|
||||
bool is(JsonObjectKey key) const {
|
||||
node_type* node = getNodeAt(key.c_str());
|
||||
return node ? node->content.value.is<T>() : false;
|
||||
template <typename TValue, typename TString>
|
||||
bool is(const TString& key) const {
|
||||
node_type* node = getNodeAt(key);
|
||||
return node ? node->content.value.is<TValue>() : false;
|
||||
}
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
||||
JsonArray& createNestedArray(JsonObjectKey key);
|
||||
template <typename TString>
|
||||
JsonArray& createNestedArray(const TString& key);
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
||||
JsonObject& createNestedObject(JsonObjectKey key);
|
||||
template <typename TString>
|
||||
JsonObject& createNestedObject(const TString& key);
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
bool containsKey(JsonObjectKey key) const {
|
||||
return getNodeAt(key.c_str()) != NULL;
|
||||
template <typename TString>
|
||||
bool containsKey(const TString& key) const {
|
||||
return getNodeAt(key) != NULL;
|
||||
}
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
void remove(JsonObjectKey key) {
|
||||
removeNode(getNodeAt(key.c_str()));
|
||||
template <typename TString>
|
||||
void remove(const TString& key) {
|
||||
removeNode(getNodeAt(key));
|
||||
}
|
||||
|
||||
// Returns a reference an invalid JsonObject.
|
||||
@ -144,58 +132,37 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Serialize the object to the specified JsonWriter
|
||||
void writeTo(Internals::JsonWriter& writer) const {
|
||||
writer.beginObject();
|
||||
|
||||
const node_type* node = _firstNode;
|
||||
while (node) {
|
||||
writer.writeString(node->content.key);
|
||||
writer.writeColon();
|
||||
node->content.value.writeTo(writer);
|
||||
|
||||
node = node->next;
|
||||
if (!node) break;
|
||||
|
||||
writer.writeComma();
|
||||
}
|
||||
|
||||
writer.endObject();
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns the list node that matches the specified key.
|
||||
node_type* getNodeAt(const char* key) const {
|
||||
template <typename TString>
|
||||
node_type* getNodeAt(const TString& key) const {
|
||||
// reduce the number of template function instanciation to reduce code size
|
||||
return getNodeAtImpl<
|
||||
typename TypeTraits::ConstRefOrConstPtr<TString>::type>(key);
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
node_type* getNodeAtImpl(TStringRef key) const {
|
||||
for (node_type* node = _firstNode; node; node = node->next) {
|
||||
if (!strcmp(node->content.key, key)) return node;
|
||||
if (Internals::StringFuncs<TStringRef>::equals(key, node->content.key))
|
||||
return node;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool setNodeAt(JsonObjectKey key, T value) {
|
||||
node_type* node = getNodeAt(key.c_str());
|
||||
template <typename TStringRef, typename TValueRef>
|
||||
bool setNodeAt(TStringRef key, TValueRef value) {
|
||||
node_type* node = getNodeAtImpl<TStringRef>(key);
|
||||
if (!node) {
|
||||
node = addNewNode();
|
||||
if (!node || !setNodeKey(node, key)) return false;
|
||||
}
|
||||
return setNodeValue<T>(node, value);
|
||||
}
|
||||
if (!node) return false;
|
||||
|
||||
bool setNodeKey(node_type* node, JsonObjectKey key) {
|
||||
if (key.needs_copy()) {
|
||||
node->content.key = _buffer->strdup(key.c_str());
|
||||
if (node->content.key == NULL) return false;
|
||||
} else {
|
||||
node->content.key = key.c_str();
|
||||
bool key_ok = Internals::ValueSetter<TStringRef>::set(
|
||||
_buffer, node->content.key, key);
|
||||
if (!key_ok) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool setNodeValue(node_type* node, T value) {
|
||||
node->content.value = value;
|
||||
return true;
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content.value,
|
||||
value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -13,36 +13,13 @@
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
namespace Internals {
|
||||
template <>
|
||||
inline bool JsonObject::setNodeValue(node_type *node, String &value) {
|
||||
node->content.value = _buffer->strdup(value);
|
||||
return node->content.value;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonObject::setNodeValue(node_type *node, const String &value) {
|
||||
node->content.value = _buffer->strdup(value);
|
||||
return node->content.value;
|
||||
}
|
||||
|
||||
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();
|
||||
struct JsonVariantDefault<JsonObject> {
|
||||
static JsonObject &get() {
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline JsonObject &JsonVariant::asObject() const {
|
||||
@ -50,11 +27,12 @@ inline JsonObject &JsonVariant::asObject() const {
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
inline JsonObject &JsonObject::createNestedObject(JsonObjectKey key) {
|
||||
template <typename TString>
|
||||
inline JsonObject &JsonObject::createNestedObject(const TString &key) {
|
||||
if (!_buffer) return JsonObject::invalid();
|
||||
JsonObject &array = _buffer->createObject();
|
||||
setNodeAt<const JsonVariant &>(key, array);
|
||||
return array;
|
||||
JsonObject &object = _buffer->createObject();
|
||||
set(key, object);
|
||||
return object;
|
||||
}
|
||||
|
||||
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 "JsonVariantBase.hpp"
|
||||
#include "TypeTraits/ConstRefOrConstPtr.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -18,30 +19,27 @@
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
|
||||
template <typename TString>
|
||||
class JsonObjectSubscript
|
||||
: public JsonVariantBase<JsonObjectSubscript<TString> > {
|
||||
// const String&
|
||||
// const std::string&
|
||||
// const char*
|
||||
typedef typename TypeTraits::ConstRefOrConstPtr<TString>::type TStringRef;
|
||||
|
||||
public:
|
||||
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key)
|
||||
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TStringRef key)
|
||||
: _object(object), _key(key) {}
|
||||
|
||||
JsonObjectSubscript<TKey>& operator=(const JsonObjectSubscript<TKey>& src) {
|
||||
_object.set<const JsonVariant&>(_key, src);
|
||||
FORCE_INLINE JsonObjectSubscript<TString>& operator=(
|
||||
const JsonObjectSubscript<TString>& src) {
|
||||
_object.set(_key, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<JsonObject::CanSet<T&>::value,
|
||||
JsonObjectSubscript<TKey> >::type&
|
||||
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);
|
||||
FORCE_INLINE JsonObjectSubscript<TString>& operator=(const T& src) {
|
||||
_object.set(_key, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -49,13 +47,9 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
|
||||
return _object.containsKey(_key);
|
||||
}
|
||||
|
||||
FORCE_INLINE operator JsonVariant() const {
|
||||
return _object.get(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const {
|
||||
return _object.get<TValue>(_key);
|
||||
return _object.get<TValue, TStringRef>(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
@ -64,62 +58,32 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue value) {
|
||||
return _object.set<TValue>(_key, value);
|
||||
FORCE_INLINE bool set(const TValue& value) {
|
||||
return _object.set(_key, value);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonVariant get() {
|
||||
return _object.get(_key);
|
||||
}
|
||||
|
||||
void writeTo(Internals::JsonWriter& writer) const {
|
||||
_object.get(_key).writeTo(writer);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonObject& _object;
|
||||
TKey _key;
|
||||
TStringRef _key;
|
||||
};
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(
|
||||
std::ostream& os, const JsonObjectSubscript<const String&>& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(
|
||||
std::ostream& os, const JsonObjectSubscript<const char*>& source) {
|
||||
template <typename TString>
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
const JsonObjectSubscript<TString>& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline JsonObjectSubscript<const char*> JsonObject::operator[](
|
||||
const char* key) {
|
||||
return JsonObjectSubscript<const char*>(*this, key);
|
||||
template <typename TString>
|
||||
inline JsonObjectSubscript<TString> JsonObject::operator[](const TString& key) {
|
||||
return JsonObjectSubscript<TString>(*this, key);
|
||||
}
|
||||
|
||||
inline JsonObjectSubscript<const String&> JsonObject::operator[](
|
||||
const String& key) {
|
||||
return JsonObjectSubscript<const String&>(*this, key);
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonObjectSubscript<const char*> JsonVariantBase<TImplem>::
|
||||
operator[](const char* key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonObjectSubscript<const String&> JsonVariantBase<TImplem>::
|
||||
operator[](const String& key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonObjectKey.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/JsonVariantContent.hpp"
|
||||
#include "Internals/JsonVariantDefault.hpp"
|
||||
#include "Internals/JsonVariantType.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "RawJson.hpp"
|
||||
@ -19,6 +20,8 @@
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsIntegral.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
#include "TypeTraits/IsSignedIntegral.hpp"
|
||||
#include "TypeTraits/IsUnsignedIntegral.hpp"
|
||||
#include "TypeTraits/RemoveConst.hpp"
|
||||
#include "TypeTraits/RemoveReference.hpp"
|
||||
|
||||
@ -36,10 +39,10 @@ class JsonObject;
|
||||
// - a string (const char*)
|
||||
// - a reference to a JsonArray or JsonObject
|
||||
class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
public:
|
||||
template <typename T>
|
||||
struct IsConstructibleFrom;
|
||||
friend void Internals::JsonSerializer::serialize(const JsonVariant &,
|
||||
JsonWriter &);
|
||||
|
||||
public:
|
||||
// Creates an uninitialized JsonVariant
|
||||
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||
|
||||
@ -107,16 +110,14 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing a reference to an array.
|
||||
JsonVariant(JsonArray &array) {
|
||||
_type = Internals::JSON_ARRAY;
|
||||
_content.asArray = &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.
|
||||
JsonVariant(JsonObject &object) {
|
||||
_type = Internals::JSON_OBJECT;
|
||||
_content.asObject = &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.
|
||||
//
|
||||
@ -149,14 +150,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
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<char*>() const;
|
||||
template <typename T>
|
||||
@ -167,6 +160,18 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
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
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
||||
@ -217,6 +222,14 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
as() const {
|
||||
return asObject();
|
||||
}
|
||||
//
|
||||
// JsonVariant as<JsonVariant> const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, JsonVariant>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Tells weither the variant has the specified type.
|
||||
// Returns true if the variant has type type T, false otherwise.
|
||||
@ -225,7 +238,8 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
// int as<int>() const;
|
||||
// long as<long>() const;
|
||||
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
|
||||
is() const {
|
||||
return isInteger();
|
||||
@ -272,9 +286,9 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
return isArray();
|
||||
}
|
||||
//
|
||||
// JsonObject& as<JsonObject> const;
|
||||
// JsonObject& as<JsonObject&> const;
|
||||
// JsonObject& as<const JsonObject&> const;
|
||||
// bool is<JsonObject> const;
|
||||
// bool is<JsonObject&> const;
|
||||
// bool is<const JsonObject&> const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSame<
|
||||
@ -291,17 +305,13 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
return _type != Internals::JSON_UNDEFINED;
|
||||
}
|
||||
|
||||
// Serialize the variant to a JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
// 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
|
||||
const char *asString() const;
|
||||
|
||||
// DEPRECATED: use as<JsonArray>() instead
|
||||
JsonArray &asArray() const;
|
||||
|
||||
// DEPRECATED: use as<JsonObject>() instead
|
||||
JsonObject &asObject() const;
|
||||
|
||||
private:
|
||||
@ -310,7 +320,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
JsonVariant(T value, typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSame<T, char>::value>::type * = 0);
|
||||
|
||||
String toString() const;
|
||||
Internals::JsonFloat asFloat() const;
|
||||
Internals::JsonInteger asInteger() const;
|
||||
Internals::JsonUInt asUnsignedInteger() const;
|
||||
@ -324,7 +333,9 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
bool isString() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
return _type == Internals::JSON_STRING ||
|
||||
(_type == Internals::JSON_UNPARSED && _content.asString &&
|
||||
!strcmp("null", _content.asString));
|
||||
}
|
||||
|
||||
// The current type of the variant
|
||||
@ -341,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) {
|
||||
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
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Internals/Parse.hpp"
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
#include <errno.h> // for errno
|
||||
#include <stdlib.h> // for strtol, strtod
|
||||
#include <string.h> // for strcmp
|
||||
|
||||
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 {
|
||||
using namespace Internals;
|
||||
if (_type == JSON_BOOLEAN) return true;
|
||||
@ -133,44 +122,6 @@ inline bool JsonVariant::isFloat() const {
|
||||
return *end == '\0' && errno == 0 && !is<long>();
|
||||
}
|
||||
|
||||
inline void JsonVariant::writeTo(Internals::JsonWriter &writer) const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
return;
|
||||
|
||||
case JSON_ARRAY:
|
||||
_content.asArray->writeTo(writer);
|
||||
return;
|
||||
|
||||
case JSON_OBJECT:
|
||||
_content.asObject->writeTo(writer);
|
||||
return;
|
||||
|
||||
case JSON_STRING:
|
||||
writer.writeString(_content.asString);
|
||||
return;
|
||||
|
||||
case JSON_UNPARSED:
|
||||
writer.writeRaw(_content.asString);
|
||||
return;
|
||||
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
writer.writeRaw('-');
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
writer.writeInteger(_content.asInteger);
|
||||
return;
|
||||
|
||||
case JSON_BOOLEAN:
|
||||
writer.writeBoolean(_content.asInteger != 0);
|
||||
return;
|
||||
|
||||
default:
|
||||
uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS);
|
||||
writer.writeFloat(_content.asFloat, decimals);
|
||||
}
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
|
||||
return source.printTo(os);
|
||||
|
@ -8,7 +8,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Internals/JsonVariantAs.hpp"
|
||||
#include "JsonObjectKey.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
@ -77,13 +76,13 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||
// Returns the value associated with the specified key if the variant is
|
||||
// an object.
|
||||
// Return JsonVariant::invalid() if the variant is not an object.
|
||||
FORCE_INLINE const JsonObjectSubscript<const char *> operator[](
|
||||
const char *key) const;
|
||||
FORCE_INLINE const JsonObjectSubscript<const String &> operator[](
|
||||
const String &key) const;
|
||||
|
||||
// Serialize the variant to a JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename TypeTraits::EnableIf<Internals::StringFuncs<TString>::has_equals,
|
||||
const JsonObjectSubscript<TString> >::type
|
||||
operator[](const TString &key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
|
@ -23,12 +23,17 @@ class Print {
|
||||
size_t print(const char* s) {
|
||||
size_t n = 0;
|
||||
while (*s) {
|
||||
n += write(*s++);
|
||||
n += write(static_cast<uint8_t>(*s++));
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t println() { return write('\r') + write('\n'); }
|
||||
size_t println() {
|
||||
size_t n = 0;
|
||||
n += write('\r');
|
||||
n += write('\n');
|
||||
return n;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,9 @@ namespace ArduinoJson {
|
||||
class RawJson {
|
||||
public:
|
||||
explicit RawJson(const char* str) : _str(str) {}
|
||||
operator const char*() const { return _str; }
|
||||
operator const char*() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
private:
|
||||
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
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "IsSame.hpp"
|
||||
#include "IsSignedIntegral.hpp"
|
||||
#include "IsUnsignedIntegral.hpp"
|
||||
@ -20,7 +19,11 @@ template <typename T>
|
||||
struct IsIntegral {
|
||||
static const bool value = TypeTraits::IsSignedIntegral<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> {};
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "Json",
|
||||
"name": "ArduinoJson",
|
||||
"keywords": "json, rest, http, web",
|
||||
"description": "An elegant and efficient JSON library for embedded systems",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"version": "5.6.3",
|
||||
"version": "5.7.1",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "http://blog.benoitblanchon.fr"
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=ArduinoJson
|
||||
version=5.6.3
|
||||
version=5.7.1
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
|
143
scripts/buffer-size-calculator.html
Normal file
143
scripts/buffer-size-calculator.html
Normal file
@ -0,0 +1,143 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ArduinoJson - JsonBuffer size calculator</title>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="jumbotron">
|
||||
<h1>JsonBuffer size calculator</h1>
|
||||
</div>
|
||||
<div id='error' class="alert alert-danger" role="alert">
|
||||
Please paste your JSON in the "input" box
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h2>Input</h2>
|
||||
<textarea class="form-control" rows=30 id='input'></textarea><br>
|
||||
</div>
|
||||
<div id='results' class="col-md-6" style='display:none'>
|
||||
<h2>Result</h2>
|
||||
<h3>Expression</h3>
|
||||
<p><code id='resultexpr'></code></p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th>Platform</th>
|
||||
<th>Size (in bytes)</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>AVR 8-bit</td>
|
||||
<td id='sizeavr8'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ESP8266</td>
|
||||
<td id='sizeesp8266'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>x86</td>
|
||||
<td id='sizex86'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>x64</td>
|
||||
<td id='sizex64'></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
function Recipe() {
|
||||
var arrays = [];
|
||||
var objects = [];
|
||||
|
||||
this.addJsonArray = function(size) {
|
||||
if (arrays[size])
|
||||
arrays[size]++;
|
||||
else
|
||||
arrays[size] = 1;
|
||||
}
|
||||
|
||||
this.addJsonObject = function(size) {
|
||||
if (objects[size])
|
||||
objects[size]++;
|
||||
else
|
||||
objects[size] = 1;
|
||||
}
|
||||
|
||||
this.getExpression = function() {
|
||||
var elements = [];
|
||||
for (var size in arrays) {
|
||||
var count = arrays[size];
|
||||
if (count > 1)
|
||||
elements.push(count + "*JSON_ARRAY_SIZE("+size+")");
|
||||
else
|
||||
elements.push("JSON_ARRAY_SIZE("+size+")");
|
||||
}
|
||||
for (var size in objects) {
|
||||
var count = objects[size];
|
||||
if (count > 1)
|
||||
elements.push(count + "*JSON_OBJECT_SIZE("+size+")");
|
||||
else
|
||||
elements.push("JSON_OBJECT_SIZE("+size+")");
|
||||
}
|
||||
return elements.join(" + ");
|
||||
}
|
||||
}
|
||||
|
||||
function scanJson(recipe, obj) {
|
||||
if (obj instanceof Array) {
|
||||
recipe.addJsonArray(obj.length);
|
||||
for (var i = 0; i<obj.length; i++)
|
||||
scanJson(recipe, obj[i]);
|
||||
}
|
||||
else if (obj instanceof Object) {
|
||||
recipe.addJsonObject(Object.keys(obj).length);
|
||||
for (var key in obj)
|
||||
scanJson(recipe, obj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
input.oninput = function(e) {
|
||||
results.style.display = 'none';
|
||||
error.style.visibility = 'hidden';
|
||||
|
||||
try {
|
||||
var recipe = new Recipe();
|
||||
scanJson(recipe, JSON.parse(input.value));
|
||||
var expression = recipe.getExpression();
|
||||
|
||||
resultexpr.innerText = expression;
|
||||
sizeavr8.innerText = eval(
|
||||
"function JSON_ARRAY_SIZE(n) { return 4 + 8*n }" +
|
||||
"function JSON_OBJECT_SIZE(n) { return 4 + 10*n }" +
|
||||
expression
|
||||
);
|
||||
sizeesp8266.innerText = eval(
|
||||
"function JSON_ARRAY_SIZE(n) { return 8 + 12*n }" +
|
||||
"function JSON_OBJECT_SIZE(n) { return 8 + 16*n }" +
|
||||
expression
|
||||
);
|
||||
sizex86.innerText = eval(
|
||||
"function JSON_ARRAY_SIZE(n) { return 12 + 24*n }" +
|
||||
"function JSON_OBJECT_SIZE(n) { return 12 + 32*n }" +
|
||||
expression
|
||||
);
|
||||
sizex64.innerText = eval(
|
||||
"function JSON_ARRAY_SIZE(n) { return 24 + 24*n }" +
|
||||
"function JSON_OBJECT_SIZE(n) { return 24 + 32*n }" +
|
||||
expression
|
||||
);
|
||||
results.style.display = 'block';
|
||||
}
|
||||
catch (ex) {
|
||||
error.innerText = "ERROR: " + ex.message;
|
||||
error.style.visibility = 'visible';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</html>
|
@ -1,6 +1,6 @@
|
||||
# Copyright Benoit Blanchon 2014-2016
|
||||
# MIT License
|
||||
#
|
||||
#
|
||||
# Arduino JSON library
|
||||
# https://github.com/bblanchon/ArduinoJson
|
||||
# If you like this project, please add a star!
|
||||
@ -25,10 +25,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
-Wformat=2
|
||||
-Winit-self
|
||||
-Wmissing-include-dirs
|
||||
-Wno-parentheses
|
||||
-Wno-sign-conversion
|
||||
-Wno-unused
|
||||
-Wno-variadic-macros
|
||||
-Wparentheses
|
||||
-Wnon-virtual-dtor
|
||||
-Wold-style-cast
|
||||
-Woverloaded-virtual
|
||||
@ -63,7 +60,10 @@ endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_compile_options(-W4)
|
||||
add_compile_options(
|
||||
/W4 # Set warning level
|
||||
/WX # Treats all compiler warnings as errors.
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(ArduinoJsonTests ${TESTS_FILES})
|
||||
|
@ -5,8 +5,8 @@
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class DynamicJsonBuffer_Basic_Tests : public testing::Test {
|
||||
protected:
|
||||
@ -38,3 +38,16 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, Alignment) {
|
||||
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
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(JsonObject_Invalid_Tests, SubscriptFails) {
|
||||
ASSERT_FALSE(JsonObject::invalid()[0].success());
|
||||
ASSERT_FALSE(JsonObject::invalid()["key"].success());
|
||||
}
|
||||
|
||||
TEST(JsonObject_Invalid_Tests, AddFails) {
|
||||
|
@ -5,8 +5,8 @@
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class JsonObject_Set_Tests : public ::testing::Test {
|
||||
public:
|
||||
@ -107,3 +107,21 @@ TEST_(StoreObjectSubscript) {
|
||||
|
||||
EXPECT_EQ(42, _object["a"]);
|
||||
}
|
||||
|
||||
TEST_(ShouldReturnTrue_WhenAllocationSucceeds) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer;
|
||||
JsonObject& obj = jsonBuffer.createObject();
|
||||
|
||||
bool result = obj.set(std::string("hello"), std::string("world"));
|
||||
|
||||
ASSERT_TRUE(result);
|
||||
}
|
||||
|
||||
TEST_(ShouldReturnFalse_WhenAllocationFails) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer;
|
||||
JsonObject& obj = jsonBuffer.createObject();
|
||||
|
||||
bool result = obj.set(std::string("hello"), std::string("world"));
|
||||
|
||||
ASSERT_FALSE(result);
|
||||
}
|
||||
|
@ -5,12 +5,14 @@
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class JsonParser_Array_Tests : public testing::Test {
|
||||
protected:
|
||||
void whenInputIs(const char *json) { strcpy(_jsonString, json); }
|
||||
void whenInputIs(const char *json) {
|
||||
strcpy(_jsonString, json);
|
||||
}
|
||||
|
||||
void whenInputIs(const char *json, size_t len) {
|
||||
memcpy(_jsonString, json, len);
|
||||
@ -27,7 +29,9 @@ class JsonParser_Array_Tests : public testing::Test {
|
||||
EXPECT_EQ(0, _array->size());
|
||||
}
|
||||
|
||||
void sizeMustBe(int expected) { ASSERT_EQ(expected, _array->size()); }
|
||||
void sizeMustBe(int expected) {
|
||||
ASSERT_EQ(expected, _array->size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void firstElementMustBe(T expected) {
|
||||
@ -346,3 +350,8 @@ TEST_F(JsonParser_Array_Tests, UnfinishedCComment) {
|
||||
whenInputIs("[/*COMMENT]");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, DeeplyNested) {
|
||||
whenInputIs("[[[[[[[[[[[[[[[[[[[\"Not too deep\"]]]]]]]]]]]]]]]]]]]");
|
||||
parseMustSucceed();
|
||||
}
|
||||
|
@ -24,13 +24,29 @@ class JsonParser_Variant_Test : public testing::Test {
|
||||
EXPECT_STREQ(expected, _result.as<char*>());
|
||||
}
|
||||
|
||||
void resultMustEqual(double expected) {
|
||||
EXPECT_DOUBLE_EQ(expected, _result.as<double>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void resultTypeMustBe() {
|
||||
EXPECT_TRUE(_result.is<T>());
|
||||
}
|
||||
|
||||
void resultMustBeInvalid() { EXPECT_FALSE(_result.success()); }
|
||||
void resultMustBeValid() { EXPECT_TRUE(_result.success()); }
|
||||
void resultMustBeInvalid() {
|
||||
EXPECT_FALSE(_result.success());
|
||||
}
|
||||
void resultMustBeValid() {
|
||||
EXPECT_TRUE(_result.success());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void verify(const char* input, T expected) {
|
||||
whenInputIs(input);
|
||||
resultMustBeValid();
|
||||
resultTypeMustBe<T>();
|
||||
resultMustEqual(expected);
|
||||
}
|
||||
|
||||
private:
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
@ -51,38 +67,29 @@ TEST_F(JsonParser_Variant_Test, EmptyArray) {
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Variant_Test, Integer) {
|
||||
whenInputIs("42");
|
||||
resultMustBeValid();
|
||||
resultTypeMustBe<int>();
|
||||
resultMustEqual(42);
|
||||
verify("42", 42);
|
||||
verify("-42", -42);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Variant_Test, Double) {
|
||||
whenInputIs("3.14");
|
||||
resultMustBeValid();
|
||||
resultTypeMustBe<double>();
|
||||
resultMustEqual(3.14);
|
||||
verify("3.14", 3.14);
|
||||
verify("3.14", 3.14);
|
||||
verify("1E+10", 1E+10);
|
||||
verify("-1E+10", -1E+10);
|
||||
verify("1.234E+10", 1.234E+10);
|
||||
verify("1.79769e+308", 1.79769e+308);
|
||||
verify("-1.79769e+308", -1.79769e+308);
|
||||
verify("1.7976931348623157e+308", 1.7976931348623157e+308);
|
||||
verify("0.017976931348623157e+310", 0.017976931348623157e+310);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Variant_Test, String) {
|
||||
whenInputIs("\"hello world\"");
|
||||
resultMustBeValid();
|
||||
resultTypeMustBe<char*>();
|
||||
resultMustEqual("hello world");
|
||||
verify("\"hello world\"", "hello world");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Variant_Test, True) {
|
||||
whenInputIs("true");
|
||||
resultMustBeValid();
|
||||
resultTypeMustBe<bool>();
|
||||
resultMustEqual(true);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Variant_Test, False) {
|
||||
whenInputIs("false");
|
||||
resultMustBeValid();
|
||||
resultTypeMustBe<bool>();
|
||||
resultMustEqual(false);
|
||||
verify("true", true);
|
||||
verify("false", false);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Variant_Test, Invalid) {
|
||||
|
@ -24,7 +24,7 @@ TEST(JsonVariant_As_Tests, DoubleAsCstr) {
|
||||
|
||||
TEST(JsonVariant_As_Tests, DoubleAsString) {
|
||||
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) {
|
||||
@ -64,7 +64,7 @@ TEST(JsonVariant_As_Tests, FalseAsLong) {
|
||||
|
||||
TEST(JsonVariant_As_Tests, FalseAsString) {
|
||||
JsonVariant variant = false;
|
||||
ASSERT_EQ(String("false"), variant.as<String>());
|
||||
ASSERT_EQ(std::string("false"), variant.as<std::string>());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_As_Tests, TrueAsBool) {
|
||||
@ -84,7 +84,7 @@ TEST(JsonVariant_As_Tests, TrueAsLong) {
|
||||
|
||||
TEST(JsonVariant_As_Tests, TrueAsString) {
|
||||
JsonVariant variant = true;
|
||||
ASSERT_EQ(String("true"), variant.as<String>());
|
||||
ASSERT_EQ(std::string("true"), variant.as<std::string>());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_As_Tests, LongAsBool) {
|
||||
@ -109,7 +109,7 @@ TEST(JsonVariant_As_Tests, NegativeLongAsDouble) {
|
||||
|
||||
TEST(JsonVariant_As_Tests, LongAsString) {
|
||||
JsonVariant variant = 42L;
|
||||
ASSERT_EQ(String("42"), variant.as<String>());
|
||||
ASSERT_EQ(std::string("42"), variant.as<std::string>());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_As_Tests, LongZeroAsDouble) {
|
||||
@ -134,7 +134,7 @@ TEST(JsonVariant_As_Tests, NullAsLong) {
|
||||
|
||||
TEST(JsonVariant_As_Tests, NullAsString) {
|
||||
JsonVariant variant = null;
|
||||
ASSERT_EQ(String("null"), variant.as<String>());
|
||||
ASSERT_EQ(std::string("null"), variant.as<std::string>());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_As_Tests, NumberStringAsBool) {
|
||||
@ -181,7 +181,7 @@ TEST(JsonVariant_As_Tests, RandomStringAsCharPtr) {
|
||||
|
||||
TEST(JsonVariant_As_Tests, RandomStringAsString) {
|
||||
JsonVariant variant = "hello";
|
||||
ASSERT_EQ(String("hello"), variant.as<String>());
|
||||
ASSERT_EQ(std::string("hello"), variant.as<std::string>());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_As_Tests, TrueStringAsBool) {
|
||||
@ -201,7 +201,7 @@ TEST(JsonVariant_As_Tests, ObjectAsString) {
|
||||
obj["key"] = "value";
|
||||
|
||||
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) {
|
||||
@ -212,7 +212,7 @@ TEST(JsonVariant_As_Tests, ArrayAsString) {
|
||||
arr.add(2);
|
||||
|
||||
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) {
|
||||
|
@ -5,8 +5,8 @@
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#define SUITE JsonVariant_Is_Tests
|
||||
|
||||
@ -34,75 +34,229 @@ void assertIs(JsonArray& value) {
|
||||
ASSERT_TRUE(variant.is<TTo>());
|
||||
}
|
||||
|
||||
TEST(SUITE, ArrayIsArry) { assertIs<JsonArray&>(JsonArray::invalid()); }
|
||||
TEST(SUITE, ArrayIsBool) { assertIsNot<bool>(JsonArray::invalid()); }
|
||||
TEST(SUITE, ArrayIsDouble) { assertIsNot<double>(JsonArray::invalid()); }
|
||||
TEST(SUITE, ArrayIsFloat) { assertIsNot<float>(JsonArray::invalid()); }
|
||||
TEST(SUITE, ArrayIsInt) { assertIsNot<int>(JsonArray::invalid()); }
|
||||
TEST(SUITE, ArrayIsLong) { assertIsNot<long>(JsonArray::invalid()); }
|
||||
TEST(SUITE, ArrayIsString) { assertIsNot<const char*>(JsonArray::invalid()); }
|
||||
TEST(SUITE, ArrayIsArray) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
assertIs<JsonArray&>(jsonBuffer.createArray());
|
||||
}
|
||||
TEST(SUITE, ArrayIsNotBool) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
assertIsNot<bool>(jsonBuffer.createArray());
|
||||
}
|
||||
TEST(SUITE, ArrayIsNotDouble) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
assertIsNot<double>(jsonBuffer.createArray());
|
||||
}
|
||||
TEST(SUITE, ArrayIsNotFloat) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
assertIsNot<float>(jsonBuffer.createArray());
|
||||
}
|
||||
TEST(SUITE, ArrayIsNotInt) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
assertIsNot<int>(jsonBuffer.createArray());
|
||||
}
|
||||
TEST(SUITE, ArrayIsNotLong) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
assertIsNot<long>(jsonBuffer.createArray());
|
||||
}
|
||||
TEST(SUITE, ArrayIsNotString) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
assertIsNot<const char*>(jsonBuffer.createArray());
|
||||
}
|
||||
|
||||
TEST(SUITE, BoolIsArray) { assertIsNot<JsonArray&>(true); }
|
||||
TEST(SUITE, BoolIsBool) { assertIs<bool>(true); }
|
||||
TEST(SUITE, BoolIsDouble) { assertIsNot<double>(true); }
|
||||
TEST(SUITE, BoolIsFloat) { assertIsNot<float>(true); }
|
||||
TEST(SUITE, BoolIsInt) { assertIsNot<int>(true); }
|
||||
TEST(SUITE, BoolIsLong) { assertIsNot<long>(true); }
|
||||
TEST(SUITE, BoolIsString) { assertIsNot<const char*>(true); }
|
||||
TEST(SUITE, BoolIsArray) {
|
||||
assertIsNot<JsonArray&>(true);
|
||||
}
|
||||
TEST(SUITE, BoolIsBool) {
|
||||
assertIs<bool>(true);
|
||||
}
|
||||
TEST(SUITE, BoolIsDouble) {
|
||||
assertIsNot<double>(true);
|
||||
}
|
||||
TEST(SUITE, BoolIsFloat) {
|
||||
assertIsNot<float>(true);
|
||||
}
|
||||
TEST(SUITE, BoolIsInt) {
|
||||
assertIsNot<int>(true);
|
||||
}
|
||||
TEST(SUITE, BoolIsLong) {
|
||||
assertIsNot<long>(true);
|
||||
}
|
||||
TEST(SUITE, BoolIsString) {
|
||||
assertIsNot<const char*>(true);
|
||||
}
|
||||
|
||||
TEST(SUITE, DoubleIsArray) { assertIsNot<JsonArray&>(4.2); }
|
||||
TEST(SUITE, DoubleIsBool) { assertIsNot<bool>(4.2); }
|
||||
TEST(SUITE, DoubleIsDouble) { assertIs<double>(4.2); }
|
||||
TEST(SUITE, DoubleIsFloat) { assertIs<float>(4.2); }
|
||||
TEST(SUITE, DoubleIsInt) { assertIsNot<int>(4.2); }
|
||||
TEST(SUITE, DoubleIsLong) { assertIsNot<long>(4.2); }
|
||||
TEST(SUITE, DoubleIsString) { assertIsNot<const char*>(4.2); }
|
||||
TEST(SUITE, DoubleIsArray) {
|
||||
assertIsNot<JsonArray&>(4.2);
|
||||
}
|
||||
TEST(SUITE, DoubleIsBool) {
|
||||
assertIsNot<bool>(4.2);
|
||||
}
|
||||
TEST(SUITE, DoubleIsDouble) {
|
||||
assertIs<double>(4.2);
|
||||
}
|
||||
TEST(SUITE, DoubleIsFloat) {
|
||||
assertIs<float>(4.2);
|
||||
}
|
||||
TEST(SUITE, DoubleIsInt) {
|
||||
assertIsNot<int>(4.2);
|
||||
}
|
||||
TEST(SUITE, DoubleIsLong) {
|
||||
assertIsNot<long>(4.2);
|
||||
}
|
||||
TEST(SUITE, DoubleIsString) {
|
||||
assertIsNot<const char*>(4.2);
|
||||
}
|
||||
|
||||
TEST(SUITE, LongIsArray) { assertIsNot<JsonArray&>(42L); }
|
||||
TEST(SUITE, LongIsBool) { assertIsNot<bool>(42L); }
|
||||
TEST(SUITE, LongIsDouble) { assertIsNot<double>(42L); }
|
||||
TEST(SUITE, LongIsFloat) { assertIsNot<float>(42L); }
|
||||
TEST(SUITE, LongIsInt) { assertIs<int>(42L); }
|
||||
TEST(SUITE, LongIsLong) { assertIs<long>(42L); }
|
||||
TEST(SUITE, LongIsString) { assertIsNot<const char*>(42L); }
|
||||
TEST(SUITE, LongIsArray) {
|
||||
assertIsNot<JsonArray&>(42L);
|
||||
}
|
||||
TEST(SUITE, LongIsBool) {
|
||||
assertIsNot<bool>(42L);
|
||||
}
|
||||
TEST(SUITE, LongIsDouble) {
|
||||
assertIsNot<double>(42L);
|
||||
}
|
||||
TEST(SUITE, LongIsFloat) {
|
||||
assertIsNot<float>(42L);
|
||||
}
|
||||
TEST(SUITE, LongIsInt) {
|
||||
assertIs<int>(42L);
|
||||
}
|
||||
TEST(SUITE, LongIsLong) {
|
||||
assertIs<long>(42L);
|
||||
}
|
||||
TEST(SUITE, LongIsString) {
|
||||
assertIsNot<const char*>(42L);
|
||||
}
|
||||
|
||||
TEST(SUITE, StringIsArray) { assertIsNot<JsonArray&>("42"); }
|
||||
TEST(SUITE, StringIsBool) { assertIsNot<bool>("42"); }
|
||||
TEST(SUITE, StringIsDouble) { assertIsNot<double>("42"); }
|
||||
TEST(SUITE, StringIsFloat) { assertIsNot<float>("42"); }
|
||||
TEST(SUITE, StringIsInt) { assertIsNot<int>("42"); }
|
||||
TEST(SUITE, StringIsLong) { assertIsNot<long>("42"); }
|
||||
TEST(SUITE, StringIsString) { assertIs<const char*>("42"); }
|
||||
TEST(SUITE, StringIsArray) {
|
||||
assertIsNot<JsonArray&>("42");
|
||||
}
|
||||
TEST(SUITE, StringIsBool) {
|
||||
assertIsNot<bool>("42");
|
||||
}
|
||||
TEST(SUITE, StringIsDouble) {
|
||||
assertIsNot<double>("42");
|
||||
}
|
||||
TEST(SUITE, StringIsFloat) {
|
||||
assertIsNot<float>("42");
|
||||
}
|
||||
TEST(SUITE, StringIsInt) {
|
||||
assertIsNot<int>("42");
|
||||
}
|
||||
TEST(SUITE, StringIsLong) {
|
||||
assertIsNot<long>("42");
|
||||
}
|
||||
TEST(SUITE, StringIsString) {
|
||||
assertIs<const char*>("42");
|
||||
}
|
||||
|
||||
TEST(SUITE, UnparsedTrueIsArra) { assertIsNot<JsonArray&>(RawJson("true")); }
|
||||
TEST(SUITE, UnparsedTrueIsBool) { assertIs<bool>(RawJson("true")); }
|
||||
TEST(SUITE, UnparsedTrueIsDouble) { assertIsNot<double>(RawJson("true")); }
|
||||
TEST(SUITE, UnparsedTrueIsFloat) { assertIsNot<float>(RawJson("true")); }
|
||||
TEST(SUITE, UnparsedTrueIsInt) { assertIsNot<int>(RawJson("true")); }
|
||||
TEST(SUITE, UnparsedTrueIsLong) { assertIsNot<long>(RawJson("true")); }
|
||||
TEST(SUITE, UnparsedTrueIsString) { assertIsNot<const char*>(RawJson("true")); }
|
||||
TEST(SUITE, UnparsedTrueIsArray) {
|
||||
assertIsNot<JsonArray&>(RawJson("true"));
|
||||
}
|
||||
TEST(SUITE, UnparsedTrueIsBool) {
|
||||
assertIs<bool>(RawJson("true"));
|
||||
}
|
||||
TEST(SUITE, UnparsedTrueIsDouble) {
|
||||
assertIsNot<double>(RawJson("true"));
|
||||
}
|
||||
TEST(SUITE, UnparsedTrueIsFloat) {
|
||||
assertIsNot<float>(RawJson("true"));
|
||||
}
|
||||
TEST(SUITE, UnparsedTrueIsInt) {
|
||||
assertIsNot<int>(RawJson("true"));
|
||||
}
|
||||
TEST(SUITE, UnparsedTrueIsLong) {
|
||||
assertIsNot<long>(RawJson("true"));
|
||||
}
|
||||
TEST(SUITE, UnparsedTrueIsString) {
|
||||
assertIsNot<const char*>(RawJson("true"));
|
||||
}
|
||||
|
||||
TEST(SUITE, UnparsedFalseIsArra) { assertIsNot<JsonArray&>(RawJson("false")); }
|
||||
TEST(SUITE, UnparsedFalseIsBool) { assertIs<bool>(RawJson("false")); }
|
||||
TEST(SUITE, UnparsedFalseIsDouble) { assertIsNot<double>(RawJson("false")); }
|
||||
TEST(SUITE, UnparsedFalseIsFloat) { assertIsNot<float>(RawJson("false")); }
|
||||
TEST(SUITE, UnparsedFalseIsInt) { assertIsNot<int>(RawJson("false")); }
|
||||
TEST(SUITE, UnparsedFalseIsLong) { assertIsNot<long>(RawJson("false")); }
|
||||
TEST(SUITE, UnparsedFalseIsArray) {
|
||||
assertIsNot<JsonArray&>(RawJson("false"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFalseIsBool) {
|
||||
assertIs<bool>(RawJson("false"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFalseIsDouble) {
|
||||
assertIsNot<double>(RawJson("false"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFalseIsFloat) {
|
||||
assertIsNot<float>(RawJson("false"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFalseIsInt) {
|
||||
assertIsNot<int>(RawJson("false"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFalseIsLong) {
|
||||
assertIsNot<long>(RawJson("false"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFalseIsString) {
|
||||
assertIsNot<const char*>(RawJson("false"));
|
||||
}
|
||||
|
||||
TEST(SUITE, UnparsedIntIsArra) { assertIsNot<JsonArray&>(RawJson("42")); }
|
||||
TEST(SUITE, UnparsedIntIsBool) { assertIsNot<bool>(RawJson("42")); }
|
||||
TEST(SUITE, UnparsedIntIsDouble) { assertIsNot<double>(RawJson("42")); }
|
||||
TEST(SUITE, UnparsedIntIsFloat) { assertIsNot<float>(RawJson("42")); }
|
||||
TEST(SUITE, UnparsedIntIsInt) { assertIs<int>(RawJson("42")); }
|
||||
TEST(SUITE, UnparsedIntIsLong) { assertIs<long>(RawJson("42")); }
|
||||
TEST(SUITE, UnparsedIntIsString) { assertIsNot<const char*>(RawJson("42")); }
|
||||
TEST(SUITE, UnparsedIntIsArray) {
|
||||
assertIsNot<JsonArray&>(RawJson("42"));
|
||||
}
|
||||
TEST(SUITE, UnparsedIntIsBool) {
|
||||
assertIsNot<bool>(RawJson("42"));
|
||||
}
|
||||
TEST(SUITE, UnparsedIntIsDouble) {
|
||||
assertIsNot<double>(RawJson("42"));
|
||||
}
|
||||
TEST(SUITE, UnparsedIntIsFloat) {
|
||||
assertIsNot<float>(RawJson("42"));
|
||||
}
|
||||
TEST(SUITE, UnparsedIntIsInt) {
|
||||
assertIs<int>(RawJson("42"));
|
||||
}
|
||||
TEST(SUITE, UnparsedIntIsLong) {
|
||||
assertIs<long>(RawJson("42"));
|
||||
}
|
||||
TEST(SUITE, UnparsedIntIsString) {
|
||||
assertIsNot<const char*>(RawJson("42"));
|
||||
}
|
||||
|
||||
TEST(SUITE, UnparsedFloatIsBool) { assertIsNot<bool>(RawJson("4.2e-10")); }
|
||||
TEST(SUITE, UnparsedFloatIsDouble) { assertIs<double>(RawJson("4.2e-10")); }
|
||||
TEST(SUITE, UnparsedFloatIsFloat) { assertIs<float>(RawJson("4.2e-10")); }
|
||||
TEST(SUITE, UnparsedFloatIsInt) { assertIsNot<int>(RawJson("4.2e-10")); }
|
||||
TEST(SUITE, UnparsedFloatIsLong) { assertIsNot<long>(RawJson("4.2e-10")); }
|
||||
TEST(SUITE, UnparsedFloatIsStr) { assertIsNot<const char*>(RawJson("4.2")); }
|
||||
TEST(SUITE, UnparsedFloatIsBool) {
|
||||
assertIsNot<bool>(RawJson("4.2e-10"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFloatIsDouble) {
|
||||
assertIs<double>(RawJson("4.2e-10"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFloatIsFloat) {
|
||||
assertIs<float>(RawJson("4.2e-10"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFloatIsInt) {
|
||||
assertIsNot<int>(RawJson("4.2e-10"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFloatIsLong) {
|
||||
assertIsNot<long>(RawJson("4.2e-10"));
|
||||
}
|
||||
TEST(SUITE, UnparsedFloatIsStr) {
|
||||
assertIsNot<const char*>(RawJson("4.2"));
|
||||
}
|
||||
|
||||
TEST(SUITE, UnparsedNullIsArray) {
|
||||
assertIsNot<JsonArray&>(RawJson("null"));
|
||||
}
|
||||
TEST(SUITE, UnparsedNullIsBool) {
|
||||
assertIsNot<bool>(RawJson("null"));
|
||||
}
|
||||
TEST(SUITE, UnparsedNullIsDouble) {
|
||||
assertIsNot<double>(RawJson("null"));
|
||||
}
|
||||
TEST(SUITE, UnparsedNullIsFloat) {
|
||||
assertIsNot<float>(RawJson("null"));
|
||||
}
|
||||
TEST(SUITE, UnparsedNullIsInt) {
|
||||
assertIsNot<int>(RawJson("null"));
|
||||
}
|
||||
TEST(SUITE, UnparsedNullIsLong) {
|
||||
assertIsNot<long>(RawJson("null"));
|
||||
}
|
||||
TEST(SUITE, UnparsedNullIsConstCharPtr) {
|
||||
assertIs<const char*>(RawJson("null"));
|
||||
}
|
||||
TEST(SUITE, UnparsedNullIsCharPtr) {
|
||||
assertIs<char*>(RawJson("null"));
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class JsonVariant_Subscript_Tests : public ::testing::Test {
|
||||
protected:
|
||||
@ -24,6 +24,9 @@ TEST_F(JsonVariant_Subscript_Tests, Array) {
|
||||
EXPECT_EQ(2, _variant.size());
|
||||
EXPECT_STREQ("element at index 0", _variant[0].asString());
|
||||
EXPECT_STREQ("element at index 1", _variant[1].asString());
|
||||
EXPECT_STREQ(
|
||||
"element at index 0",
|
||||
_variant[static_cast<unsigned char>(0)].asString()); // issue #381
|
||||
EXPECT_FALSE(_variant[-1].success());
|
||||
EXPECT_FALSE(_variant[3].success());
|
||||
EXPECT_FALSE(_variant["0"].success());
|
||||
|
43
test/JsonVariant_Success_Tests.cpp
Normal file
43
test/JsonVariant_Success_Tests.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
// 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>
|
||||
|
||||
TEST(JsonVariant_Success_Tests, ReturnsFalse_WhenUndefined) {
|
||||
JsonVariant variant;
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_Success_Tests, ReturnsTrue_WhenInteger) {
|
||||
JsonVariant variant = 0;
|
||||
EXPECT_TRUE(variant.success());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_Success_Tests, ReturnsTrue_WhenEmptyArray) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
JsonVariant variant = jsonBuffer.createArray();
|
||||
EXPECT_TRUE(variant.success());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_Success_Tests, ReturnsTrue_WhenEmptyObject) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
JsonVariant variant = jsonBuffer.createObject();
|
||||
EXPECT_TRUE(variant.success());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_Success_Tests, ReturnsFalse_WhenInvalidArray) {
|
||||
JsonVariant variant = JsonArray::invalid();
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
||||
|
||||
TEST(JsonVariant_Success_Tests, ReturnsFalse_WhenInvalidObject) {
|
||||
JsonVariant variant = JsonObject::invalid();
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
113
test/JsonWriter_WriteFloat_Tests.cpp
Normal file
113
test/JsonWriter_WriteFloat_Tests.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
#include <limits>
|
||||
|
||||
#include <ArduinoJson/Internals/JsonWriter.hpp>
|
||||
#include <ArduinoJson/Internals/StaticStringBuilder.hpp>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
class JsonWriter_WriteFloat_Tests : public testing::Test {
|
||||
protected:
|
||||
void whenInputIs(double input, uint8_t digits = 2) {
|
||||
StaticStringBuilder sb(buffer, sizeof(buffer));
|
||||
JsonWriter writer(sb);
|
||||
writer.writeFloat(input, digits);
|
||||
returnValue = writer.bytesWritten();
|
||||
}
|
||||
|
||||
void outputMustBe(const char *expected) {
|
||||
EXPECT_STREQ(expected, buffer);
|
||||
EXPECT_EQ(strlen(expected), returnValue);
|
||||
}
|
||||
|
||||
private:
|
||||
char buffer[1024];
|
||||
size_t returnValue;
|
||||
};
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, NaN) {
|
||||
whenInputIs(std::numeric_limits<double>::signaling_NaN());
|
||||
outputMustBe("NaN");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, PositiveInfinity) {
|
||||
whenInputIs(std::numeric_limits<double>::infinity());
|
||||
outputMustBe("Infinity");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, NegativeInfinity) {
|
||||
whenInputIs(-std::numeric_limits<double>::infinity());
|
||||
outputMustBe("-Infinity");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, Zero) {
|
||||
whenInputIs(0);
|
||||
outputMustBe("0.00");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, ZeroDigits_Rounding) {
|
||||
whenInputIs(9.5, 0);
|
||||
outputMustBe("10");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, ZeroDigits_NoRounding) {
|
||||
whenInputIs(9.4, 0);
|
||||
outputMustBe("9");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, OneDigit_Rounding) {
|
||||
whenInputIs(9.95, 1);
|
||||
outputMustBe("10.0");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, OneDigit_NoRounding) {
|
||||
whenInputIs(9.94, 1);
|
||||
outputMustBe("9.9");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, TwoDigits_Rounding) {
|
||||
whenInputIs(9.995, 2);
|
||||
outputMustBe("10.00");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, TwoDigits_NoRounding) {
|
||||
whenInputIs(9.994, 2);
|
||||
outputMustBe("9.99");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, ThreeDigits_Rounding) {
|
||||
whenInputIs(9.9995, 3);
|
||||
outputMustBe("10.000");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, ThreeDigits_NoRounding) {
|
||||
whenInputIs(9.9994, 3);
|
||||
outputMustBe("9.999");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, FourDigits_Rounding) {
|
||||
whenInputIs(9.99995, 4);
|
||||
outputMustBe("10.0000");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, FourDigits_NoRounding) {
|
||||
whenInputIs(9.99994, 4);
|
||||
outputMustBe("9.9999");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, FiveDigits_Rounding) {
|
||||
whenInputIs(9.999995, 5);
|
||||
outputMustBe("10.00000");
|
||||
}
|
||||
|
||||
TEST_F(JsonWriter_WriteFloat_Tests, FiveDigits_NoRounding) {
|
||||
whenInputIs(9.999994, 5);
|
||||
outputMustBe("9.99999");
|
||||
}
|
@ -5,12 +5,12 @@
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class ArduinoStringTests : public ::testing::Test {
|
||||
class StringTests : public ::testing::Test {
|
||||
protected:
|
||||
static void eraseString(String &str) {
|
||||
static void eraseString(std::string &str) {
|
||||
char *p = const_cast<char *>(str.c_str());
|
||||
while (*p) *p++ = '*';
|
||||
}
|
||||
@ -18,100 +18,100 @@ class ArduinoStringTests : public ::testing::Test {
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
};
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonBuffer_ParseArray) {
|
||||
String json("[\"hello\"]");
|
||||
TEST_F(StringTests, JsonBuffer_ParseArray) {
|
||||
std::string json("[\"hello\"]");
|
||||
JsonArray &array = _jsonBuffer.parseArray(json);
|
||||
eraseString(json);
|
||||
ASSERT_TRUE(array.success());
|
||||
ASSERT_STREQ("hello", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonBuffer_ParseObject) {
|
||||
String json("{\"hello\":\"world\"}");
|
||||
TEST_F(StringTests, JsonBuffer_ParseObject) {
|
||||
std::string json("{\"hello\":\"world\"}");
|
||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
eraseString(json);
|
||||
ASSERT_TRUE(object.success());
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_Subscript) {
|
||||
TEST_F(StringTests, JsonObject_Subscript) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
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\"}";
|
||||
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();
|
||||
String key("hello");
|
||||
std::string key("hello");
|
||||
object.set(key, "world");
|
||||
eraseString(key);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetValue) {
|
||||
TEST_F(StringTests, JsonObject_SetValue) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String value("world");
|
||||
std::string value("world");
|
||||
object.set("hello", value);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetKeyValue) {
|
||||
TEST_F(StringTests, JsonObject_SetKeyValue) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String key("hello");
|
||||
String value("world");
|
||||
std::string key("hello");
|
||||
std::string value("world");
|
||||
object.set(key, value);
|
||||
eraseString(key);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetToArraySubscript) {
|
||||
TEST_F(StringTests, JsonObject_SetToArraySubscript) {
|
||||
JsonArray &arr = _jsonBuffer.createArray();
|
||||
arr.add("world");
|
||||
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.set(String("hello"), arr[0]);
|
||||
object.set(std::string("hello"), arr[0]);
|
||||
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetToObjectSubscript) {
|
||||
TEST_F(StringTests, JsonObject_SetToObjectSubscript) {
|
||||
JsonObject &arr = _jsonBuffer.createObject();
|
||||
arr.set("x", "world");
|
||||
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.set(String("hello"), arr["x"]);
|
||||
object.set(std::string("hello"), arr["x"]);
|
||||
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_Get) {
|
||||
TEST_F(StringTests, JsonObject_Get) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
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\"}";
|
||||
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\"}";
|
||||
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) {
|
||||
String key = "key";
|
||||
TEST_F(StringTests, JsonObject_CreateNestedObject) {
|
||||
std::string key = "key";
|
||||
char json[64];
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.createNestedObject(key);
|
||||
@ -120,8 +120,8 @@ TEST_F(ArduinoStringTests, JsonObject_CreateNestedObject) {
|
||||
ASSERT_STREQ("{\"key\":{}}", json);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) {
|
||||
String key = "key";
|
||||
TEST_F(StringTests, JsonObject_CreateNestedArray) {
|
||||
std::string key = "key";
|
||||
char json[64];
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.createNestedArray(key);
|
||||
@ -130,99 +130,99 @@ TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) {
|
||||
ASSERT_STREQ("{\"key\":[]}", json);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_ContainsKey) {
|
||||
TEST_F(StringTests, JsonObject_ContainsKey) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
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\"}";
|
||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_EQ(1, object.size());
|
||||
object.remove(String("key"));
|
||||
object.remove(std::string("key"));
|
||||
ASSERT_EQ(0, object.size());
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetKey) {
|
||||
TEST_F(StringTests, JsonObjectSubscript_SetKey) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String key("hello");
|
||||
std::string key("hello");
|
||||
object[key] = "world";
|
||||
eraseString(key);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetValue) {
|
||||
TEST_F(StringTests, JsonObjectSubscript_SetValue) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String value("world");
|
||||
std::string value("world");
|
||||
object["hello"] = value;
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArray_Add) {
|
||||
TEST_F(StringTests, JsonArray_Add) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
String value("hello");
|
||||
std::string value("hello");
|
||||
array.add(value);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("hello", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArray_Set) {
|
||||
TEST_F(StringTests, JsonArray_Set) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
String value("world");
|
||||
std::string value("world");
|
||||
array.add("hello");
|
||||
array.set(0, value);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArraySubscript) {
|
||||
TEST_F(StringTests, JsonArraySubscript) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
String value("world");
|
||||
std::string value("world");
|
||||
array.add("hello");
|
||||
array[0] = value;
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArray_PrintTo) {
|
||||
TEST_F(StringTests, JsonArray_PrintTo) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
array.add(4);
|
||||
array.add(2);
|
||||
String json;
|
||||
std::string 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();
|
||||
array.add(4);
|
||||
array.add(2);
|
||||
String json;
|
||||
std::string 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();
|
||||
object["key"] = "value";
|
||||
String json;
|
||||
std::string 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();
|
||||
object["key"] = "value";
|
||||
String json;
|
||||
std::string 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();
|
||||
String key1("hello"), key2("world");
|
||||
std::string key1("hello"), key2("world");
|
||||
|
||||
object[key1] = 1;
|
||||
size_t sizeBefore = _jsonBuffer.size();
|
||||
@ -232,9 +232,9 @@ TEST_F(ArduinoStringTests, JsonBuffer_GrowWhenAddingNewKey) {
|
||||
ASSERT_GT(sizeAfter - sizeBefore, key2.size());
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonBuffer_DontGrowWhenReusingKey) {
|
||||
TEST_F(StringTests, JsonBuffer_DontGrowWhenReusingKey) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String key("hello");
|
||||
std::string key("hello");
|
||||
|
||||
object[key] = 1;
|
||||
size_t sizeBefore = _jsonBuffer.size();
|
||||
@ -243,3 +243,10 @@ TEST_F(ArduinoStringTests, JsonBuffer_DontGrowWhenReusingKey) {
|
||||
|
||||
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