Compare commits

...

19 Commits

Author SHA1 Message Date
169c83431c Set version to 6.8.0-beta 2019-01-30 16:39:38 +01:00
5f72c68d87 Updated publish script for the "ardu-badge" 2019-01-30 15:23:55 +01:00
b184af6d00 User can now use a JsonString as a key or a value 2019-01-29 17:00:11 +01:00
6f55d1e58f JsonVariant automatically promotes to JsonObject or JsonArray on write 2019-01-29 14:09:09 +01:00
5aea1363cc Merge branch 'master' into 6.x 2019-01-24 21:07:02 +01:00
0685a36f0e Added ArduBadge badge 2019-01-24 20:55:55 +01:00
70739f5cfd Reduced the size of the pretty JSON serializer 2019-01-23 18:19:24 +01:00
933a66a070 Added JsonDocument::operator[] 2019-01-23 11:43:29 +01:00
4167b11434 Create or assign a JsonDocument from a JsonArray/JsonObject/JsonVariant 2019-01-23 10:47:20 +01:00
2a3b51ac3a Fixed uninitialized variant in JsonDocument 2019-01-20 14:35:22 +01:00
e633292df1 Replaced JsonDocument::nestingLimit with a param to deserializeJson() 2019-01-19 14:45:16 +01:00
30b94493bb Added nesting() to JsonArray, JsonDocument, JsonObject, and JsonVariant 2019-01-17 09:55:51 +01:00
c51cc91f92 Added memoryUsage() to JsonArray, JsonObject, and JsonVariant 2019-01-16 09:50:57 +01:00
8b04046321 Import JsonDocument into the ArduinoJson namespace 2019-01-15 12:04:48 +01:00
11bb5e26ff Fixed copying from JsonObjectConst and JsonArrayConst 2019-01-14 11:17:57 +01:00
9ac2ac303c Removed default capacity of DynamicJsonDocument 2019-01-14 10:32:19 +01:00
f0784d3b41 Simplified deserializeJson() and deserializeMsgPack() 2019-01-04 12:33:39 +01:00
3d8ece8c8b Improved syntax highlighting in Arduino IDE 2018-12-14 17:35:40 +01:00
b0fb71f7d8 Import functions in the ArduinoJson namespace to get clearer errors 2018-12-14 17:34:49 +01:00
163 changed files with 2994 additions and 1484 deletions

View File

@ -1,6 +1,70 @@
ArduinoJson: change log
=======================
v6.8.0-beta (2019-01-30)
-----------
* Import functions in the ArduinoJson namespace to get clearer errors
* Improved syntax highlighting in Arduino IDE
* Removed default capacity of `DynamicJsonDocument`
* `JsonArray::copyFrom()` accepts `JsonArrayConst`
* `JsonVariant::set()` accepts `JsonArrayConst` and `JsonObjectConst`
* `JsonDocument` was missing in the ArduinoJson namespace
* Added `memoryUsage()` to `JsonArray`, `JsonObject`, and `JsonVariant`
* Added `nesting()` to `JsonArray`, `JsonDocument`, `JsonObject`, and `JsonVariant`
* Replaced `JsonDocument::nestingLimit` with an additional parameter
to `deserializeJson()` and `deserializeMsgPack()`
* Fixed uninitialized variant in `JsonDocument`
* Fixed `StaticJsonDocument` copy constructor and copy assignment
* The copy constructor of `DynamicJsonDocument` chooses the capacity according to the memory usage of the source, not from the capacity of the source.
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
* Added `JsonDocument::isNull()`
* Added `JsonDocument::operator[]`
* Added `ARDUINOJSON_TAB` to configure the indentation character
* Reduced the size of the pretty JSON serializer
* Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant`
* `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write.
Calling `JsonVariant::to<T>()` is not required anymore.
* `JsonDocument` now support the same operations as `JsonVariant`.
Calling `JsonDocument::as<T>()` is not required anymore.
* Fixed example `JsonHttpClient.ino`
* User can now use a `JsonString` as a key or a value
> ### BREAKING CHANGES
>
> #### `DynamicJsonDocument`'s constructor
>
> The parameter to the constructor of `DynamicJsonDocument` is now mandatory
>
> Old code:
>
> ```c++
> DynamicJsonDocument doc;
> ```
>
> New code:
>
> ```c++
> DynamicJsonDocument doc(1024);
> ```
>
> #### Nesting limit
>
> `JsonDocument::nestingLimit` was replaced with a new parameter to `deserializeJson()` and `deserializeMsgPack()`.
>
> Old code:
>
> ```c++
> doc.nestingLimit = 15;
> deserializeJson(doc, input);
> ```
>
> New code:
>
> ```c++
> deserializeJson(doc, input, DeserializationOption::NestingLimit(15));
> ```
v6.7.0-beta (2018-12-07)
-----------

View File

@ -2,7 +2,11 @@
---
[![Build status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=6.x) [![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.7.0-beta)](https://www.ardu-badge.com/ArduinoJson/6.7.0-beta)
[![Build Status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson)
[![Coverage Status](https://coveralls.io/repos/github/bblanchon/ArduinoJson/badge.svg?branch=6.x)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
[![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
@ -60,7 +64,7 @@ Here is a program that parses a JSON document with ArduinoJson.
```c++
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
deserializeJson(doc, json);
JsonObjectRef root = doc.as<JsonObject>();
@ -77,7 +81,7 @@ See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_
Here is a program that generates a JSON document with ArduinoJson:
```c++
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
JsonObject root = doc.to<JsonObject>();
root["sensor"] = "gps";

View File

@ -15,7 +15,11 @@
#include <SD.h>
#include <SPI.h>
// Configuration that we'll store on disk
// Our configuration structure.
//
// Never use a JsonDocument to store the configuration!
// A JsonDocument is *not* a permanent storage; it's only a temporary storage
// used during the serialization phase.
struct Config {
char hostname[64];
int port;
@ -29,9 +33,9 @@ void loadConfiguration(const char *filename, Config &config) {
// Open file for reading
File file = SD.open(filename);
// Allocate the document on the stack.
// Allocate a temporary JsonDocument
// Don't forget to change the capacity to match your requirements.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<512> doc;
// Deserialize the JSON document
@ -39,16 +43,13 @@ void loadConfiguration(const char *filename, Config &config) {
if (error)
Serial.println(F("Failed to read file, using default configuration"));
// Get the root object in the document
JsonObject root = doc.as<JsonObject>();
// Copy values from the JsonDocument to the Config
config.port = doc["port"] | 2731;
strlcpy(config.hostname, // <- destination
doc["hostname"] | "example.com", // <- source
sizeof(config.hostname)); // <- destination's capacity
// Copy values from the JsonObject to the Config
config.port = root["port"] | 2731;
strlcpy(config.hostname, // <- destination
root["hostname"] | "example.com", // <- source
sizeof(config.hostname)); // <- destination's capacity
// Close the file (File's destructor doesn't close the file)
// Close the file (Curiously, File's destructor doesn't close the file)
file.close();
}
@ -64,24 +65,21 @@ void saveConfiguration(const char *filename, const Config &config) {
return;
}
// Allocate the document on the stack.
// Allocate a temporary JsonDocument
// Don't forget to change the capacity to match your requirements.
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonDocument<256> doc;
// Make our document contain an object
JsonObject root = doc.to<JsonObject>();
// Set the values in the object
root["hostname"] = config.hostname;
root["port"] = config.port;
// Set the values in the document
doc["hostname"] = config.hostname;
doc["port"] = config.port;
// Serialize JSON to file
if (serializeJson(doc, file) == 0) {
Serial.println(F("Failed to write to file"));
}
// Close the file (File's destructor doesn't close the file)
// Close the file
file.close();
}
@ -100,7 +98,7 @@ void printFile(const char *filename) {
}
Serial.println();
// Close the file (File's destructor doesn't close the file)
// Close the file
file.close();
}

View File

@ -15,7 +15,7 @@ void setup() {
//
// Inside the brackets, 200 is the RAM allocated to this document.
// Don't forget to change this value to match your requirement.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be
@ -23,30 +23,30 @@ void setup() {
//
// DynamicJsonDocument doc(200);
// Make our document be an object
JsonObject root = doc.to<JsonObject>();
// Add values in the object
// Add values in the document
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root.set<long>("time", 1351824120);
root["sensor"] = "gps";
root["time"] = 1351824120;
doc["sensor"] = "gps";
doc["time"] = 1351824120;
// Add an array.
//
JsonArray data = root.createNestedArray("data");
JsonArray data = doc.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
serializeJson(root, Serial);
// This prints:
// Generate the minified JSON and send it to the Serial port.
//
serializeJson(doc, Serial);
// The above line prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
// Start a new line
Serial.println();
serializeJsonPretty(root, Serial);
// This prints:
// Generate the prettified JSON and send it to the Serial port.
//
serializeJsonPretty(doc, Serial);
// The above line prints:
// {
// "sensor": "gps",
// "time": 1351824120,

View File

@ -71,7 +71,7 @@ void setup() {
}
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
DynamicJsonDocument doc(capacity);
@ -84,12 +84,11 @@ void setup() {
}
// Extract values
JsonObject root = doc.as<JsonObject>();
Serial.println(F("Response:"));
Serial.println(root["sensor"].as<char*>());
Serial.println(root["time"].as<char*>());
Serial.println(root["data"][0].as<char*>());
Serial.println(root["data"][1].as<char*>());
Serial.println(doc["sensor"].as<char*>());
Serial.println(doc["time"].as<long>());
Serial.println(doc["data"][0].as<float>(), 6);
Serial.println(doc["data"][1].as<float>(), 6);
// Disconnect
client.stop();

View File

@ -13,9 +13,9 @@ void setup() {
// Allocate the JSON document
//
// Inside the brackets, 200 is the size of the memory pool in bytes.
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonDocument<N> allocates memory on the stack, it can be
@ -25,9 +25,12 @@ void setup() {
// JSON input string.
//
// It's better to use a char[] as shown here.
// If you use a const char* or a String, ArduinoJson will
// have to make a copy of the input in the JsonBuffer.
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
// the minimal amount of memory because the JsonDocument stores pointers to
// the input buffer.
// If you use another type of input, ArduinoJson must copy the strings from
// the input to the JsonDocument, so you need to increase the capacity of the
// JsonDocument.
char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
@ -41,17 +44,14 @@ void setup() {
return;
}
// Get the root object in the document
JsonObject root = doc.as<JsonObject>();
// Fetch values.
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root["time"].as<long>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
// In other case, you can do doc["time"].as<long>();
const char* sensor = doc["sensor"];
long time = doc["time"];
double latitude = doc["data"][0];
double longitude = doc["data"][1];
// Print values.
Serial.println(sensor);

View File

@ -2,15 +2,15 @@
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to implement an HTTP server that sends JSON document
// in the responses.
// This example shows how to implement an HTTP server that sends a JSON document
// in the response.
// It uses the Ethernet library but can be easily adapted for Wifi.
//
// It sends the value of the analog and digital pins.
// The JSON document looks like the following:
// The JSON document contains the values of the analog and digital pins.
// It looks like that:
// {
// "analog": [ 0, 1, 2, 3, 4, 5 ],
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
// "analog": [0, 76, 123, 158, 192, 205],
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
// }
#include <ArduinoJson.h>
@ -51,15 +51,12 @@ void loop() {
// Read the request (we ignore the content in this example)
while (client.available()) client.read();
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
// Allocate a temporary JsonDocument
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<500> doc;
// Make our document represent an object
JsonObject root = doc.to<JsonObject>();
// Create the "analog" array
JsonArray analogValues = root.createNestedArray("analog");
JsonArray analogValues = doc.createNestedArray("analog");
for (int pin = 0; pin < 6; pin++) {
// Read the analog input
int value = analogRead(pin);
@ -69,7 +66,7 @@ void loop() {
}
// Create the "digital" array
JsonArray digitalValues = root.createNestedArray("digital");
JsonArray digitalValues = doc.createNestedArray("digital");
for (int pin = 0; pin < 14; pin++) {
// Read the digital input
int value = digitalRead(pin);
@ -79,17 +76,19 @@ void loop() {
}
Serial.print(F("Sending: "));
serializeJson(root, Serial);
serializeJson(doc, Serial);
Serial.println();
// Write response headers
client.println("HTTP/1.0 200 OK");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.println(F("HTTP/1.0 200 OK"));
client.println(F("Content-Type: application/json"));
client.println(F("Connection: close"));
client.print(F("Content-Length: "));
client.println(measureJsonPretty(doc));
client.println();
// Write JSON document
serializeJsonPretty(root, client);
serializeJsonPretty(doc, client);
// Disconnect
client.stop();

View File

@ -5,10 +5,10 @@
// This example shows how to send a JSON document to a UDP socket.
// At regular interval, it sends a UDP packet that contains the status of
// analog and digital pins.
// The JSON document looks like the following:
// It looks like that:
// {
// "analog": [ 0, 1, 2, 3, 4, 5 ],
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
// "analog": [0, 76, 123, 158, 192, 205],
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
// }
//
// If you want to test this program, you need to be able to receive the UDP
@ -43,15 +43,12 @@ void setup() {
}
void loop() {
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
// Allocate a temporary JsonDocument
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<500> doc;
// Make our document represent an object
JsonObject root = doc.to<JsonObject>();
// Create the "analog" array
JsonArray analogValues = root.createNestedArray("analog");
JsonArray analogValues = doc.createNestedArray("analog");
for (int pin = 0; pin < 6; pin++) {
// Read the analog input
int value = analogRead(pin);
@ -61,7 +58,7 @@ void loop() {
}
// Create the "digital" array
JsonArray digitalValues = root.createNestedArray("digital");
JsonArray digitalValues = doc.createNestedArray("digital");
for (int pin = 0; pin < 14; pin++) {
// Read the digital input
int value = digitalRead(pin);
@ -75,11 +72,11 @@ void loop() {
Serial.print(remoteIp);
Serial.print(F(" on port "));
Serial.println(remotePort);
serializeJson(root, Serial);
serializeJson(doc, Serial);
// Send UDP packet
udp.beginPacket(remoteIp, remotePort);
serializeJson(root, udp);
serializeJson(doc, udp);
udp.println();
udp.endPacket();

View File

@ -14,9 +14,9 @@ void setup() {
// Allocate the JSON document
//
// Inside the brackets, 200 is the size of the memory pool in bytes.
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be
@ -26,9 +26,12 @@ void setup() {
// MessagePack input string.
//
// It's better to use a char[] as shown here.
// If you use a const char* or a String, ArduinoJson will
// have to make a copy of the input in the JsonBuffer.
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
// the minimal amount of memory because the JsonDocument stores pointers to
// the input buffer.
// If you use another type of input, ArduinoJson must copy the strings from
// the input to the JsonDocument, so you need to increase the capacity of the
// JsonDocument.
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
@ -40,31 +43,23 @@ void setup() {
// "data": [48.75608, 2.302038]
// }
// doc of the object tree.
//
// It's a reference to the JsonObject, the actual bytes are inside the
// JsonBuffer with all the other nodes of the object tree.
// Memory is freed when jsonBuffer goes out of scope.
DeserializationError error = deserializeMsgPack(doc, input);
// Test if parsing succeeds.
// Test if parsing succeeded.
if (error) {
Serial.print("deserializeMsgPack() failed: ");
Serial.println(error.c_str());
return;
}
// Get the root object in the document
JsonObject root = doc.as<JsonObject>();
// Fetch values.
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root["time"].as<long>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
// In other case, you can do doc["time"].as<long>();
const char* sensor = doc["sensor"];
long time = doc["time"];
double latitude = doc["data"][0];
double longitude = doc["data"][1];
// Print values.
Serial.println(sensor);

View File

@ -6,7 +6,7 @@
// ArduinoJson.
//
// Use Flash strings sparingly, because ArduinoJson duplicates them in the
// JsonBuffer. Prefer plain old char*, as they are more efficient in term of
// JsonDocument. Prefer plain old char*, as they are more efficient in term of
// code size, speed, and memory usage.
#include <ArduinoJson.h>
@ -14,11 +14,10 @@
void setup() {
#ifdef PROGMEM // <- check that Flash strings are supported
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
// You can use a Flash String as your JSON input.
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
// WARNING: the string in the input will be duplicated in the JsonDocument.
deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120,"
"\"data\":[48.756080,2.302038]}"));
JsonObject obj = doc.as<JsonObject>();
@ -29,12 +28,12 @@ void setup() {
// 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.
// JsonDocument.
obj[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.
// JsonDocument.
obj["sensor"] = F("gps");
// It works with serialized() too:

View File

@ -5,16 +5,16 @@
// This example shows the different ways you can use String with ArduinoJson.
//
// Use String objects sparingly, because ArduinoJson duplicates them in the
// JsonBuffer. Prefer plain old char[], as they are more efficient in term of
// JsonDocument. Prefer plain old char[], as they are more efficient in term of
// code size, speed, and memory usage.
#include <ArduinoJson.h>
void setup() {
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
// You can use a String as your JSON input.
// WARNING: the content of the String will be duplicated in the JsonBuffer.
// WARNING: the string in the input will be duplicated in the JsonDocument.
String input =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
deserializeJson(doc, input);
@ -25,11 +25,11 @@ void setup() {
long time = obj[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.
// WARNING: the content of the String will be duplicated in the JsonDocument.
obj[String("time")] = time;
// You can get a String from a JsonObject or JsonArray:
// No duplication is done, at least not in the JsonBuffer.
// No duplication is done, at least not in the JsonDocument.
String sensor = obj["sensor"];
// Unfortunately, the following doesn't work (issue #118):
@ -38,14 +38,14 @@ void setup() {
sensor = obj["sensor"].as<String>();
// You can set a String to a JsonObject or JsonArray:
// WARNING: the content of the String will be duplicated in the JsonBuffer.
// WARNING: the content of the String will be duplicated in the JsonDocument.
obj["sensor"] = sensor;
// It works with serialized() too:
obj["sensor"] = serialized(sensor);
// You can also concatenate strings
// WARNING: the content of the String will be duplicated in the JsonBuffer.
// WARNING: the content of the String will be duplicated in the JsonDocument.
obj[String("sen") + "sor"] = String("gp") + "s";
// You can compare the content of a JsonObject with a String

View File

@ -1,7 +1,7 @@
#include <ArduinoJson.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeJson(doc, data, size);
if (!error) {
std::string json;

View File

@ -1,7 +1,7 @@
#include <ArduinoJson.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeMsgPack(doc, data, size);
if (!error) {
std::string json;

View File

@ -1,17 +1,36 @@
# Macros
JSON_ARRAY_SIZE KEYWORD2
JSON_OBJECT_SIZE KEYWORD2
JSON_STRING_SIZE KEYWORD2
# Free functions
deserializeJson KEYWORD2
deserializeMsgPack KEYWORD2
serialized KEYWORD2
serializeJson KEYWORD2
serializeJsonPretty KEYWORD2
serializeMsgPack KEYWORD2
# Methods
add KEYWORD2
as KEYWORD2
createNestedArray KEYWORD2
createNestedObject KEYWORD2
deserializeJson KEYWORD2
deserializeMsgPack KEYWORD2
DynamicJsonDocument KEYWORD1
get KEYWORD2
JsonArray KEYWORD1
JsonObject KEYWORD1
JsonVariant KEYWORD1
serializeMsgPack KEYWORD2
serializeJson KEYWORD2
serializeJsonPretty KEYWORD2
set KEYWORD2
StaticJsonDocument KEYWORD1
to KEYWORD2
# Type names
DeserializationError KEYWORD1 DATA_TYPE
DynamicJsonDocument KEYWORD1 DATA_TYPE
JsonArray KEYWORD1 DATA_TYPE
JsonArrayConst KEYWORD1 DATA_TYPE
JsonFloat KEYWORD1 DATA_TYPE
JsonInteger KEYWORD1 DATA_TYPE
JsonObject KEYWORD1 DATA_TYPE
JsonObjectConst KEYWORD1 DATA_TYPE
JsonString KEYWORD1 DATA_TYPE
JsonUInt KEYWORD1 DATA_TYPE
JsonVariant KEYWORD1 DATA_TYPE
JsonVariantConst KEYWORD1 DATA_TYPE
StaticJsonDocument KEYWORD1 DATA_TYPE

View File

@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"version": "6.7.0-beta",
"version": "6.8.0-beta",
"authors": {
"name": "Benoit Blanchon",
"url": "https://blog.benoitblanchon.fr"

View File

@ -1,5 +1,5 @@
name=ArduinoJson
version=6.7.0-beta
version=6.8.0-beta
author=Benoit Blanchon <blog.benoitblanchon.fr>
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
sentence=An efficient and elegant JSON library for Arduino.

View File

@ -7,11 +7,15 @@ cd "$(dirname "$0")/.."
VERSION="$1"
DATE=$(date +%F)
TAG="v$VERSION"
VERSION_REGEX="[0-9a-z\\.\\-]+"
update_version_in_source () {
IFS=".-" read MAJOR MINOR REVISION EXTRA < <(echo "$VERSION")
UNDERLINE=$(printf -- '-%.0s' $(seq 1 ${#TAG}))
sed -i~ -bE "s/version=$VERSION_REGEX/version=$VERSION/; s|ardu-badge.com/ArduinoJson/$VERSION_REGEX|ardu-badge.com/ArduinoJson/$VERSION|; " README.md
rm README.md*~
sed -i~ -bE "4s/HEAD/$TAG ($DATE)/; 5s/-+/$UNDERLINE/" CHANGELOG.md
rm CHANGELOG.md*~
sed -i~ -bE "s/\"version\":.*$/\"version\": \"$VERSION\",/" library.json

View File

@ -14,10 +14,10 @@
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
#include "ArduinoJson/Array/ArrayImpl.hpp"
#include "ArduinoJson/Array/ArraySubscript.hpp"
#include "ArduinoJson/Array/ElementProxy.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Object/MemberProxy.hpp"
#include "ArduinoJson/Object/ObjectImpl.hpp"
#include "ArduinoJson/Object/ObjectSubscript.hpp"
#include "ArduinoJson/Variant/VariantAsImpl.hpp"
#include "ArduinoJson/Variant/VariantImpl.hpp"
@ -28,19 +28,29 @@
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
namespace ArduinoJson {
typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
typedef ARDUINOJSON_NAMESPACE::String JsonString;
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
using ARDUINOJSON_NAMESPACE::DeserializationError;
using ARDUINOJSON_NAMESPACE::deserializeJson;
using ARDUINOJSON_NAMESPACE::deserializeMsgPack;
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
using ARDUINOJSON_NAMESPACE::JsonDocument;
using ARDUINOJSON_NAMESPACE::serialized;
using ARDUINOJSON_NAMESPACE::serializeJson;
using ARDUINOJSON_NAMESPACE::serializeJsonPretty;
using ARDUINOJSON_NAMESPACE::serializeMsgPack;
using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
namespace DeserializationOption {
using ARDUINOJSON_NAMESPACE::NestingLimit;
}
} // namespace ArduinoJson

View File

@ -9,11 +9,14 @@
namespace ARDUINOJSON_NAMESPACE {
inline ArrayRef ArrayRef::createNestedArray() const {
return add().to<ArrayRef>();
template <typename TArray>
inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const {
return impl()->add().template to<ArrayRef>();
}
inline ObjectRef ArrayRef::createNestedObject() const {
return add().to<ObjectRef>();
template <typename TArray>
inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
return impl()->add().template to<ObjectRef>();
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -16,11 +16,16 @@
namespace ARDUINOJSON_NAMESPACE {
class ObjectRef;
class ArraySubscript;
template <typename>
class ElementProxy;
template <typename TData>
class ArrayRefBase {
public:
operator VariantConstRef() const {
return VariantConstRef(reinterpret_cast<const VariantData*>(_data));
}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
arrayAccept(_data, visitor);
@ -30,8 +35,12 @@ class ArrayRefBase {
return _data == 0;
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return VariantConstRef(_data ? _data->get(index) : 0);
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0;
}
FORCE_INLINE size_t size() const {
@ -66,9 +75,15 @@ class ArrayConstRef : public ArrayRefBase<const CollectionData>,
FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
return arrayEquals(_data, rhs._data);
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return VariantConstRef(_data ? _data->get(index) : 0);
}
};
class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
class ArrayRef : public ArrayRefBase<CollectionData>,
public ArrayShortcuts<ArrayRef>,
public Visitable {
typedef ArrayRefBase<CollectionData> base_type;
public:
@ -86,27 +101,7 @@ class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
return ArrayConstRef(_data);
}
// Adds the specified value at the end of the array.
//
// bool add(TValue);
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ObjectRef
template <typename T>
FORCE_INLINE bool add(const T& value) const {
return add().set(value);
}
// Adds the specified value at the end of the array.
FORCE_INLINE bool add(ArrayRef value) const {
return add().set(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const __FlashStringHelper*
template <typename T>
FORCE_INLINE bool add(T* value) const {
return add().set(value);
}
using ArrayShortcuts::add;
VariantRef add() const {
return VariantRef(_pool, arrayAdd(_data, _pool));
}
@ -150,7 +145,7 @@ class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
}
// Copy a ArrayRef
FORCE_INLINE bool copyFrom(ArrayRef src) const {
FORCE_INLINE bool copyFrom(ArrayConstRef src) const {
if (!_data || !src._data) return false;
return _data->copyFrom(*src._data, _pool);
}
@ -179,11 +174,6 @@ class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
}
}
FORCE_INLINE ArrayRef createNestedArray() const;
FORCE_INLINE ObjectRef createNestedObject() const;
FORCE_INLINE ArraySubscript operator[](size_t index) const;
FORCE_INLINE bool operator==(ArrayRef rhs) const {
return arrayEquals(_data, rhs._data);
}

View File

@ -0,0 +1,47 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Polyfills/attributes.hpp"
#include "../Polyfills/type_traits.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Forward declarations.
template <typename>
class ElementProxy;
template <typename TArray>
class ArrayShortcuts {
public:
// Returns the element at specified index if the variant is an array.
FORCE_INLINE ElementProxy<const TArray &> operator[](size_t index) const;
FORCE_INLINE ObjectRef createNestedObject() const;
FORCE_INLINE ArrayRef createNestedArray() const;
// Adds the specified value at the end of the array.
//
// bool add(TValue);
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ObjectRef
template <typename T>
FORCE_INLINE bool add(const T &value) const {
return impl()->add().set(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const __FlashStringHelper*
template <typename T>
FORCE_INLINE bool add(T *value) const {
return impl()->add().set(value);
}
private:
const TArray *impl() const {
return static_cast<const TArray *>(this);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -13,14 +13,18 @@
#endif
namespace ARDUINOJSON_NAMESPACE {
class ArraySubscript : public VariantOperators<ArraySubscript>,
public Visitable {
template <typename TArray>
class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
public Visitable {
typedef ElementProxy<TArray> this_type;
public:
FORCE_INLINE ArraySubscript(ArrayRef array, size_t index)
FORCE_INLINE ElementProxy(TArray array, size_t index)
: _array(array), _index(index) {}
FORCE_INLINE ArraySubscript& operator=(const ArraySubscript& src) {
get_impl().set(src.as<VariantConstRef>());
FORCE_INLINE this_type& operator=(const this_type& src) {
getElement().set(src.as<VariantConstRef>());
return *this;
}
@ -30,36 +34,36 @@ class ArraySubscript : public VariantOperators<ArraySubscript>,
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ArrayRef, ObjectRef
template <typename T>
FORCE_INLINE ArraySubscript& operator=(const T& src) {
get_impl().set(src);
FORCE_INLINE this_type& operator=(const T& src) {
getElement().set(src);
return *this;
}
//
// operator=(TValue)
// TValue = char*, const char*, const __FlashStringHelper*
template <typename T>
FORCE_INLINE ArraySubscript& operator=(T* src) {
get_impl().set(src);
FORCE_INLINE this_type& operator=(T* src) {
getElement().set(src);
return *this;
}
FORCE_INLINE bool isNull() const {
return get_impl().isNull();
return getElement().isNull();
}
template <typename T>
FORCE_INLINE typename VariantAs<T>::type as() const {
return get_impl().as<T>();
return getElement().template as<T>();
}
template <typename T>
FORCE_INLINE bool is() const {
return get_impl().is<T>();
return getElement().template is<T>();
}
template <typename T>
FORCE_INLINE typename VariantTo<T>::type to() const {
return get_impl().to<T>();
return getElement().template to<T>();
}
// Replaces the value
@ -69,42 +73,65 @@ class ArraySubscript : public VariantOperators<ArraySubscript>,
// std::string, String, ArrayRef, ObjectRef
template <typename TValue>
FORCE_INLINE bool set(const TValue& value) const {
return get_impl().set(value);
return getElement().set(value);
}
//
// bool set(TValue)
// TValue = char*, const char*, const __FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(TValue* value) const {
return get_impl().set(value);
return getElement().set(value);
}
template <typename Visitor>
void accept(Visitor& visitor) const {
return get_impl().accept(visitor);
return getElement().accept(visitor);
}
FORCE_INLINE size_t size() const {
return get_impl().size();
return getElement().size();
}
template <typename TNestedKey>
VariantRef get(TNestedKey* key) const {
return getElement().get(key);
}
template <typename TNestedKey>
VariantRef get(const TNestedKey& key) const {
return getElement().get(key);
}
template <typename TNestedKey>
VariantRef getOrCreate(TNestedKey* key) const {
return getElement().getOrCreate(key);
}
template <typename TNestedKey>
VariantRef getOrCreate(const TNestedKey& key) const {
return getElement().getOrCreate(key);
}
using ArrayShortcuts<ElementProxy>::add;
VariantRef add() const {
return getElement().add();
}
private:
FORCE_INLINE VariantRef get_impl() const {
FORCE_INLINE VariantRef getElement() const {
return _array.get(_index);
}
ArrayRef _array;
TArray _array;
const size_t _index;
};
template <typename TImpl>
inline ArraySubscript VariantSubscripts<TImpl>::operator[](size_t index) const {
return impl()->template as<ArrayRef>()[index];
template <typename TArray>
inline ElementProxy<const TArray&> ArrayShortcuts<TArray>::operator[](
size_t index) const {
return ElementProxy<const TArray&>(*impl(), index);
}
inline ArraySubscript ArrayRef::operator[](size_t index) const {
return ArraySubscript(*this, index);
}
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER

View File

@ -24,13 +24,13 @@ class CollectionData {
VariantData *add(MemoryPool *pool);
template <typename TKey>
VariantData *add(TKey key, MemoryPool *pool);
template <typename TAdaptedString>
VariantData *add(TAdaptedString key, MemoryPool *pool);
void clear();
template <typename TKey>
bool containsKey(const TKey &key) const;
template <typename TAdaptedString>
bool containsKey(const TAdaptedString &key) const;
bool copyFrom(const CollectionData &src, MemoryPool *pool);
@ -39,8 +39,8 @@ class CollectionData {
VariantData *get(size_t index) const;
template <typename TKey>
VariantData *get(TKey key) const;
template <typename TAdaptedString>
VariantData *get(TAdaptedString key) const;
VariantSlot *head() const {
return _head;
@ -48,20 +48,22 @@ class CollectionData {
void remove(size_t index);
template <typename TKey>
void remove(TKey key) {
template <typename TAdaptedString>
void remove(TAdaptedString key) {
remove(getSlot(key));
}
void remove(VariantSlot *slot);
size_t memoryUsage() const;
size_t nesting() const;
size_t size() const;
private:
VariantSlot *getSlot(size_t index) const;
template <typename TKey>
VariantSlot *getSlot(TKey key) const;
template <typename TAdaptedString>
VariantSlot *getSlot(TAdaptedString key) const;
VariantSlot *getPreviousSlot(VariantSlot *) const;
};

View File

@ -29,8 +29,8 @@ inline VariantData* CollectionData::add(MemoryPool* pool) {
return addSlot(pool)->data();
}
template <typename TKey>
inline VariantData* CollectionData::add(TKey key, MemoryPool* pool) {
template <typename TAdaptedString>
inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) {
VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool)) return 0;
return slot->data();
@ -41,8 +41,8 @@ inline void CollectionData::clear() {
_tail = 0;
}
template <typename TKey>
inline bool CollectionData::containsKey(const TKey& key) const {
template <typename TAdaptedString>
inline bool CollectionData::containsKey(const TAdaptedString& key) const {
return getSlot(key) != 0;
}
@ -53,9 +53,9 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
VariantData* var;
if (s->key() != 0) {
if (s->ownsKey())
var = add(RamStringWrapper(s->key()), pool);
var = add(RamStringAdapter(s->key()), pool);
else
var = add(ConstRamStringWrapper(s->key()), pool);
var = add(ConstRamStringAdapter(s->key()), pool);
} else {
var = add(pool);
}
@ -69,7 +69,7 @@ inline bool CollectionData::equalsObject(const CollectionData& other) const {
size_t count = 0;
for (VariantSlot* slot = _head; slot; slot = slot->next()) {
VariantData* v1 = slot->data();
VariantData* v2 = other.get(wrapString(slot->key()));
VariantData* v2 = other.get(adaptString(slot->key()));
if (!variantEquals(v1, v2)) return false;
count++;
}
@ -88,8 +88,8 @@ inline bool CollectionData::equalsArray(const CollectionData& other) const {
}
}
template <typename TKey>
inline VariantSlot* CollectionData::getSlot(TKey key) const {
template <typename TAdaptedString>
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
VariantSlot* slot = _head;
while (slot) {
if (key.equals(slot->key())) break;
@ -112,8 +112,8 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
return 0;
}
template <typename TKey>
inline VariantData* CollectionData::get(TKey key) const {
template <typename TAdaptedString>
inline VariantData* CollectionData::get(TAdaptedString key) const {
VariantSlot* slot = getSlot(key);
return slot ? slot->data() : 0;
}
@ -138,6 +138,24 @@ inline void CollectionData::remove(size_t index) {
remove(getSlot(index));
}
inline size_t CollectionData::memoryUsage() const {
size_t total = 0;
for (VariantSlot* s = _head; s; s = s->next()) {
total += sizeof(VariantSlot) + s->data()->memoryUsage();
if (s->ownsKey()) total += strlen(s->key()) + 1;
}
return total;
}
inline size_t CollectionData::nesting() const {
size_t maxChildNesting = 0;
for (VariantSlot* s = _head; s; s = s->next()) {
size_t childNesting = s->data()->nesting();
if (childNesting > maxChildNesting) maxChildNesting = childNesting;
}
return maxChildNesting + 1;
}
inline size_t CollectionData::size() const {
return slotSize(_head);
}

View File

@ -53,11 +53,6 @@
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
#endif
// Default capacity for DynamicJsonDocument
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
#define ARDUINOJSON_DEFAULT_POOL_SIZE 1024
#endif
#else // ARDUINOJSON_EMBEDDED_MODE
// On a computer we have plenty of memory so we can use doubles
@ -89,11 +84,6 @@
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
#endif
// Default capacity for DynamicJsonDocument
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
#define ARDUINOJSON_DEFAULT_POOL_SIZE 16384
#endif
#endif // ARDUINOJSON_EMBEDDED_MODE
#ifdef ARDUINO
@ -150,3 +140,7 @@
#define ARDUINOJSON_LITTLE_ENDIAN 0
#endif
#endif
#ifndef ARDUINOJSON_TAB
#define ARDUINOJSON_TAB " "
#endif

View File

@ -0,0 +1,17 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Configuration.hpp"
namespace ARDUINOJSON_NAMESPACE {
struct NestingLimit {
NestingLimit() : value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
explicit NestingLimit(uint8_t n) : value(n) {}
uint8_t value;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -5,12 +5,13 @@
#pragma once
#include "../StringStorage/StringStorage.hpp"
#include "./ArduinoStreamReader.hpp"
#include "./CharPointerReader.hpp"
#include "./DeserializationError.hpp"
#include "./FlashStringReader.hpp"
#include "./IteratorReader.hpp"
#include "./StdStreamReader.hpp"
#include "ArduinoStreamReader.hpp"
#include "CharPointerReader.hpp"
#include "DeserializationError.hpp"
#include "FlashStringReader.hpp"
#include "IteratorReader.hpp"
#include "NestingLimit.hpp"
#include "StdStreamReader.hpp"
namespace ARDUINOJSON_NAMESPACE {
@ -22,50 +23,54 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit);
}
// DeserializationError deserialize(JsonDocument& doc, TString input);
// TString = const std::string&, const String&
// deserialize(JsonDocument&, const std::string&);
// deserialize(JsonDocument&, const String&);
template <template <typename, typename> class TDeserializer, typename TString>
typename enable_if<!is_array<TString>::value, DeserializationError>::type
deserialize(JsonDocument &doc, const TString &input) {
deserialize(JsonDocument &doc, const TString &input,
NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
//
// DeserializationError deserialize(JsonDocument& doc, TChar* input);
// TChar* = char*, const char*, const __FlashStringHelper*
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
.parse(doc.data());
}
//
// DeserializationError deserialize(JsonDocument& doc, TChar* input, size_t
// inputSize);
// TChar* = char*, const char*, const __FlashStringHelper*
// deserialize(JsonDocument&, char*);
// deserialize(JsonDocument&, const char*);
// deserialize(JsonDocument&, const __FlashStringHelper*);
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
size_t inputSize) {
NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
//
// deserialize(JsonDocument&, char*, size_t);
// deserialize(JsonDocument&, const char*, size_t);
// deserialize(JsonDocument&, const __FlashStringHelper*, size_t);
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
size_t inputSize, NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input, inputSize),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
//
// DeserializationError deserialize(JsonDocument& doc, TStream input);
// TStream = std::istream&, Stream&
// deserialize(JsonDocument&, std::istream&);
// deserialize(JsonDocument&, Stream&);
template <template <typename, typename> class TDeserializer, typename TStream>
DeserializationError deserialize(JsonDocument &doc, TStream &input) {
DeserializationError deserialize(JsonDocument &doc, TStream &input,
NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -12,17 +12,25 @@ namespace ARDUINOJSON_NAMESPACE {
class DynamicJsonDocument : public JsonDocument {
public:
DynamicJsonDocument(size_t capa = ARDUINOJSON_DEFAULT_POOL_SIZE)
: JsonDocument(allocPool(addPadding(capa))) {}
explicit DynamicJsonDocument(size_t capa)
: JsonDocument(allocPool(capa)) {}
DynamicJsonDocument(const DynamicJsonDocument& src)
: JsonDocument(allocPool(src.capacity())) {
copy(src);
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
DynamicJsonDocument(const JsonDocument& src)
: JsonDocument(allocPool(src.capacity())) {
copy(src);
template <typename T>
DynamicJsonDocument(const T& src,
typename enable_if<IsVisitable<T>::value>::type* = 0)
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
// disambiguate
DynamicJsonDocument(VariantRef src)
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
~DynamicJsonDocument() {
@ -31,19 +39,20 @@ class DynamicJsonDocument : public JsonDocument {
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
reallocPoolIfTooSmall(src.memoryUsage());
copy(src);
set(src);
return *this;
}
template <typename T>
DynamicJsonDocument& operator=(const JsonDocument& src) {
DynamicJsonDocument& operator=(const T& src) {
reallocPoolIfTooSmall(src.memoryUsage());
copy(src);
set(src);
return *this;
}
private:
MemoryPool allocPool(size_t capa) {
MemoryPool allocPool(size_t requiredSize) {
size_t capa = addPadding(requiredSize);
return MemoryPool(reinterpret_cast<char*>(malloc(capa)), capa);
}

View File

@ -5,15 +5,17 @@
#pragma once
#include "../Memory/MemoryPool.hpp"
#include "../Object/ObjectRef.hpp"
#include "../Variant/VariantRef.hpp"
#include "../Variant/VariantTo.hpp"
#include "../Array/ElementProxy.hpp"
#include "../Object/MemberProxy.hpp"
namespace ARDUINOJSON_NAMESPACE {
class JsonDocument : public Visitable {
public:
uint8_t nestingLimit;
template <typename Visitor>
void accept(Visitor& visitor) const {
return getVariant().accept(visitor);
@ -39,14 +41,32 @@ class JsonDocument : public Visitable {
return getVariant().template is<T>();
}
bool isNull() const {
return getVariant().isNull();
}
size_t memoryUsage() const {
return _pool.size();
}
size_t nesting() const {
return _data.nesting();
}
size_t capacity() const {
return _pool.capacity();
}
bool set(const JsonDocument& src) {
return to<VariantRef>().set(src.as<VariantRef>());
}
template <typename T>
typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set(
const T& src) {
return to<VariantRef>().set(src);
}
template <typename T>
typename VariantTo<T>::type to() {
clear();
@ -62,16 +82,150 @@ class JsonDocument : public Visitable {
return _data;
}
ArrayRef createNestedArray() {
return add().to<ArrayRef>();
}
// createNestedArray(char*)
// createNestedArray(const char*)
// createNestedArray(const __FlashStringHelper*)
template <typename TChar>
ArrayRef createNestedArray(TChar* key) {
return getOrCreate(key).template to<ArrayRef>();
}
// createNestedArray(const std::string&)
// createNestedArray(const String&)
template <typename TString>
ArrayRef createNestedArray(const TString& key) {
return getOrCreate(key).template to<ArrayRef>();
}
ObjectRef createNestedObject() {
return add().to<ObjectRef>();
}
// createNestedObject(char*)
// createNestedObject(const char*)
// createNestedObject(const __FlashStringHelper*)
template <typename TChar>
ObjectRef createNestedObject(TChar* key) {
return getOrCreate(key).template to<ObjectRef>();
}
// createNestedObject(const std::string&)
// createNestedObject(const String&)
template <typename TString>
ObjectRef createNestedObject(const TString& key) {
return getOrCreate(key).template to<ObjectRef>();
}
// operator[](const std::string&)
// operator[](const String&)
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value,
MemberProxy<JsonDocument&, const TString&> >::type
operator[](const TString& key) {
return MemberProxy<JsonDocument&, const TString&>(*this, key);
}
// operator[](char*)
// operator[](const char*)
// operator[](const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<JsonDocument&, TChar*> >::type
operator[](TChar* key) {
return MemberProxy<JsonDocument&, TChar*>(*this, key);
}
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString& key) const {
return getVariant()[key];
}
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
operator[](TChar* key) const {
return getVariant()[key];
}
FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
return ElementProxy<JsonDocument&>(*this, index);
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return VariantConstRef(_data.get(index));
}
FORCE_INLINE VariantRef get(size_t index) {
return VariantRef(&_pool, _data.get(index));
}
// get(char*) const
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef get(TChar* key) {
return VariantRef(&_pool, _data.get(adaptString(key)));
}
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
get(const TString& key) {
return VariantRef(&_pool, _data.get(adaptString(key)));
}
// getOrCreate(char*)
// getOrCreate(const char*)
// getOrCreate(const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE VariantRef getOrCreate(TChar* key) {
return VariantRef(&_pool, _data.getOrCreate(adaptString(key), &_pool));
}
// getOrCreate(const std::string&)
// getOrCreate(const String&)
template <typename TString>
FORCE_INLINE VariantRef getOrCreate(const TString& key) {
return VariantRef(&_pool, _data.getOrCreate(adaptString(key), &_pool));
}
FORCE_INLINE VariantRef add() {
return VariantRef(&_pool, _data.add(&_pool));
}
template <typename TValue>
FORCE_INLINE bool add(const TValue& value) {
return add().set(value);
}
// add(char*) const
// add(const char*) const
// add(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE bool add(TChar* value) {
return add().set(value);
}
protected:
JsonDocument(MemoryPool pool)
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(pool) {}
JsonDocument(MemoryPool pool) : _pool(pool) {
_data.setNull();
}
JsonDocument(char* buf, size_t capa)
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(buf, capa) {}
void copy(const JsonDocument& src) {
nestingLimit = src.nestingLimit;
to<VariantRef>().set(src.as<VariantRef>());
JsonDocument(char* buf, size_t capa) : _pool(buf, capa) {
_data.setNull();
}
void replacePool(MemoryPool pool) {

View File

@ -16,13 +16,31 @@ class StaticJsonDocument : public JsonDocument {
public:
StaticJsonDocument() : JsonDocument(_buffer, ACTUAL_CAPACITY) {}
StaticJsonDocument(const JsonDocument& src)
StaticJsonDocument(const StaticJsonDocument& src)
: JsonDocument(_buffer, ACTUAL_CAPACITY) {
copy(src);
set(src);
}
StaticJsonDocument operator=(const JsonDocument& src) {
copy(src);
template <typename T>
StaticJsonDocument(const T& src,
typename enable_if<IsVisitable<T>::value>::type* = 0)
: JsonDocument(_buffer, ACTUAL_CAPACITY) {
set(src);
}
// disambiguate
StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, ACTUAL_CAPACITY) {
set(src);
}
StaticJsonDocument operator=(const StaticJsonDocument& src) {
set(src);
return *this;
}
template <typename T>
StaticJsonDocument operator=(const T& src) {
set(src);
return *this;
}

View File

@ -1,69 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
// Decorator on top of Print to allow indented output.
// This class is used by serializeJsonPretty() but can also be used
// for your own purpose, like logging.
template <typename Print>
class IndentedPrint {
public:
explicit IndentedPrint(Print &p) : sink(&p) {
level = 0;
tabSize = 2;
isNewLine = true;
}
size_t write(uint8_t c) {
size_t n = 0;
if (isNewLine) n += writeTabs();
n += sink->write(c);
isNewLine = c == '\n';
return n;
}
size_t write(const uint8_t *s, size_t n) {
// TODO: optimize
size_t bytesWritten = 0;
while (n > 0) {
bytesWritten += write(*s++);
n--;
}
return bytesWritten;
}
// Adds one level of indentation
void indent() {
if (level < MAX_LEVEL) level++;
}
// Removes one level of indentation
void unindent() {
if (level > 0) level--;
}
// Set the number of space printed for each level of indentation
void setTabSize(uint8_t n) {
if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE;
}
private:
Print *sink;
uint8_t level : 4;
uint8_t tabSize : 3;
bool isNewLine : 1;
size_t writeTabs() {
size_t n = 0;
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
return n;
}
static const int MAX_LEVEL = 15; // because it's only 4 bits
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -336,24 +336,31 @@ class JsonDeserializer {
bool _loaded;
};
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, const TInput &input) {
return deserialize<JsonDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, const TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input) {
return deserialize<JsonDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, TInput *input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input,
size_t inputSize) {
return deserialize<JsonDeserializer>(doc, input, inputSize);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, TInput *input, size_t inputSize,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput &input) {
return deserialize<JsonDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -7,21 +7,17 @@
#include "../Misc/Visitable.hpp"
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "JsonWriter.hpp"
#include "TextFormatter.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class JsonSerializer {
public:
JsonSerializer(TWriter &writer) : _writer(writer) {}
JsonSerializer(TWriter &writer) : _formatter(writer) {}
void visitFloat(Float value) {
_writer.writeFloat(value);
}
void visitArray(const CollectionData &array) {
_writer.beginArray();
FORCE_INLINE void visitArray(const CollectionData &array) {
write('[');
VariantSlot *slot = array.head();
@ -31,63 +27,74 @@ class JsonSerializer {
slot = slot->next();
if (slot == 0) break;
_writer.writeComma();
write(',');
}
_writer.endArray();
write(']');
}
void visitObject(const CollectionData &object) {
_writer.beginObject();
write('{');
VariantSlot *slot = object.head();
while (slot != 0) {
_writer.writeString(slot->key());
_writer.writeColon();
_formatter.writeString(slot->key());
write(':');
slot->data()->accept(*this);
slot = slot->next();
if (slot == 0) break;
_writer.writeComma();
write(',');
}
_writer.endObject();
write('}');
}
void visitFloat(Float value) {
_formatter.writeFloat(value);
}
void visitString(const char *value) {
_writer.writeString(value);
_formatter.writeString(value);
}
void visitRawJson(const char *data, size_t n) {
// TODO
for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]);
_formatter.writeRaw(data, n);
}
void visitNegativeInteger(UInt value) {
_writer.writeRaw('-');
_writer.writeInteger(value);
_formatter.writeNegativeInteger(value);
}
void visitPositiveInteger(UInt value) {
_writer.writeInteger(value);
_formatter.writePositiveInteger(value);
}
void visitBoolean(bool value) {
_writer.writeBoolean(value);
_formatter.writeBoolean(value);
}
void visitNull() {
_writer.writeRaw("null");
_formatter.writeRaw("null");
}
size_t bytesWritten() const {
return _writer.bytesWritten();
return _formatter.bytesWritten();
}
protected:
void write(char c) {
_formatter.writeRaw(c);
}
void write(const char *s) {
_formatter.writeRaw(s);
}
private:
JsonWriter<TWriter> _writer;
TextFormatter<TWriter> _formatter;
};
template <typename TSource, typename TDestination>

View File

@ -4,37 +4,68 @@
#pragma once
#include "../Configuration.hpp"
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "./IndentedPrint.hpp"
#include "./JsonSerializer.hpp"
#include "./Prettyfier.hpp"
#include "JsonSerializer.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TPrint>
class PrettyJsonSerializer_Base {
public:
PrettyJsonSerializer_Base(TPrint &output)
: _indentedPrint(output), _prettyfier(_indentedPrint) {}
template <typename TWriter>
class PrettyJsonSerializer : public JsonSerializer<TWriter> {
typedef JsonSerializer<TWriter> base;
protected:
IndentedPrint<TPrint> _indentedPrint;
Prettyfier<TPrint> _prettyfier;
};
template <typename TPrint>
class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>,
public JsonSerializer<Prettyfier<TPrint> > {
public:
PrettyJsonSerializer(TPrint &output)
: PrettyJsonSerializer_Base<TPrint>(output),
JsonSerializer<Prettyfier<TPrint> >(
PrettyJsonSerializer_Base<TPrint>::_prettyfier) {}
PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
void visitArray(const CollectionData &array) {
VariantSlot *slot = array.head();
if (!slot) return base::write("[]");
base::write("[\r\n");
_nesting++;
while (slot != 0) {
indent();
slot->data()->accept(*this);
slot = slot->next();
base::write(slot ? ",\r\n" : "\r\n");
}
_nesting--;
indent();
base::write("]");
}
void visitObject(const CollectionData &object) {
VariantSlot *slot = object.head();
if (!slot) return base::write("{}");
base::write("{\r\n");
_nesting++;
while (slot != 0) {
indent();
base::visitString(slot->key());
base::write(": ");
slot->data()->accept(*this);
slot = slot->next();
base::write(slot ? ",\r\n" : "\r\n");
}
_nesting--;
indent();
base::write("}");
}
private:
void indent() {
for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB);
}
uint8_t _nesting;
};
template <typename TSource, typename TDestination>
size_t serializeJsonPretty(TSource &source, TDestination &destination) {
size_t serializeJsonPretty(const TSource &source, TDestination &destination) {
return serialize<PrettyJsonSerializer>(source, destination);
}

View File

@ -1,143 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "IndentedPrint.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Converts a compact JSON string into an indented one.
template <typename TWriter>
class Prettyfier {
public:
explicit Prettyfier(IndentedPrint<TWriter>& p) : _sink(p) {
_previousChar = 0;
_inString = false;
}
size_t write(uint8_t c) {
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(char(c));
_previousChar = char(c);
return n;
}
size_t write(const uint8_t* s, size_t n) {
// TODO: optimize
size_t bytesWritten = 0;
while (n > 0) {
bytesWritten += write(*s++);
n--;
}
return bytesWritten;
}
private:
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
bool inEmptyBlock() {
return _previousChar == '{' || _previousChar == '[';
}
size_t handleStringChar(uint8_t c) {
bool isQuote = c == '"' && _previousChar != '\\';
if (isQuote) _inString = false;
return _sink.write(c);
}
size_t handleMarkupChar(char c) {
switch (c) {
case '{':
case '[':
return writeBlockOpen(c);
case '}':
case ']':
return writeBlockClose(c);
case ':':
return writeColon();
case ',':
return writeComma();
case '"':
return writeQuoteOpen();
default:
return writeNormalChar(c);
}
}
size_t writeBlockClose(char c) {
size_t n = 0;
n += unindentIfNeeded();
n += write(c);
return n;
}
size_t writeBlockOpen(char c) {
size_t n = 0;
n += indentIfNeeded();
n += write(c);
return n;
}
size_t writeColon() {
size_t n = 0;
n += write(": ");
return n;
}
size_t writeComma() {
size_t n = 0;
n += write(",\r\n");
return n;
}
size_t writeQuoteOpen() {
_inString = true;
size_t n = 0;
n += indentIfNeeded();
n += write('"');
return n;
}
size_t writeNormalChar(char c) {
size_t n = 0;
n += indentIfNeeded();
n += write(c);
return n;
}
size_t indentIfNeeded() {
if (!inEmptyBlock()) return 0;
_sink.indent();
return write("\r\n");
}
size_t unindentIfNeeded() {
if (inEmptyBlock()) return 0;
_sink.unindent();
return write("\r\n");
}
size_t write(char c) {
return _sink.write(static_cast<uint8_t>(c));
}
template <size_t N>
size_t write(const char (&s)[N]) {
return _sink.write(reinterpret_cast<const uint8_t*>(s), N - 1);
}
char _previousChar;
IndentedPrint<TWriter>& _sink;
bool _inString;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -14,36 +14,15 @@
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class JsonWriter {
class TextFormatter {
public:
explicit JsonWriter(TWriter &writer) : _writer(writer), _length(0) {}
explicit TextFormatter(TWriter &writer) : _writer(writer), _length(0) {}
// Returns the number of bytes sent to the TWriter implementation.
size_t bytesWritten() const {
return _length;
}
void beginArray() {
writeRaw('[');
}
void endArray() {
writeRaw(']');
}
void beginObject() {
writeRaw('{');
}
void endObject() {
writeRaw('}');
}
void writeColon() {
writeRaw(':');
}
void writeComma() {
writeRaw(',');
}
void writeBoolean(bool value) {
if (value)
writeRaw("true");
@ -84,22 +63,27 @@ class JsonWriter {
FloatParts<T> parts(value);
writeInteger(parts.integral);
writePositiveInteger(parts.integral);
if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces);
if (parts.exponent < 0) {
writeRaw("e-");
writeInteger(-parts.exponent);
writePositiveInteger(-parts.exponent);
}
if (parts.exponent > 0) {
writeRaw('e');
writeInteger(parts.exponent);
writePositiveInteger(parts.exponent);
}
}
void writeNegativeInteger(UInt value) {
writeRaw('-');
writePositiveInteger(value);
}
template <typename T>
void writeInteger(T value) {
void writePositiveInteger(T value) {
char buffer[22];
char *end = buffer + sizeof(buffer);
char *begin = end;
@ -134,10 +118,16 @@ class JsonWriter {
void writeRaw(const char *s) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
}
void writeRaw(const char *s, size_t n) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), n);
}
void writeRaw(const char *begin, const char *end) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(begin),
static_cast<size_t>(end - begin));
}
template <size_t N>
void writeRaw(const char (&s)[N]) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
@ -151,6 +141,6 @@ class JsonWriter {
size_t _length;
private:
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
TextFormatter &operator=(const TextFormatter &); // cannot be assigned
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,7 +4,7 @@
#pragma once
#include "../Strings/StringWrappers.hpp"
#include "../Strings/StringAdapters.hpp"
namespace ARDUINOJSON_NAMESPACE {
@ -58,7 +58,7 @@ inline SerializedValue<T> serialized(T str) {
template <typename TChar>
inline SerializedValue<TChar*> serialized(TChar* p) {
return SerializedValue<TChar*>(p, wrapString(p).size());
return SerializedValue<TChar*>(p, adaptString(p).size());
}
template <typename TChar>

View File

@ -15,4 +15,7 @@ struct Visitable {
template <typename T>
struct IsVisitable : is_base_of<Visitable, T> {};
template <typename T>
struct IsVisitable<T&> : IsVisitable<T> {};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -326,24 +326,31 @@ class MsgPackDeserializer {
uint8_t _nestingLimit;
};
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, const TInput &input) {
return deserialize<MsgPackDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeMsgPack(
JsonDocument &doc, const TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input) {
return deserialize<MsgPackDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TInput *input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input,
size_t inputSize) {
return deserialize<MsgPackDeserializer>(doc, input, inputSize);
template <typename TInput>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TInput *input, size_t inputSize,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, TInput &input) {
return deserialize<MsgPackDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,158 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Configuration.hpp"
#include "../Operators/VariantOperators.hpp"
#include "../Polyfills/type_traits.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE {
template <typename TObject, typename TStringRef>
class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
public Visitable {
typedef MemberProxy<TObject, TStringRef> this_type;
public:
FORCE_INLINE MemberProxy(TObject variant, TStringRef key)
: _object(variant), _key(key) {}
FORCE_INLINE operator VariantConstRef() const {
return getMember();
}
FORCE_INLINE this_type &operator=(const this_type &src) {
getOrCreateMember().set(src);
return *this;
}
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
operator=(const TValue &src) {
getOrCreateMember().set(src);
return *this;
}
// operator=(char*) const
// operator=(const char*) const
// operator=(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE this_type &operator=(TChar *src) {
getOrCreateMember().set(src);
return *this;
}
FORCE_INLINE bool isNull() const {
return getMember().isNull();
}
template <typename TValue>
FORCE_INLINE typename VariantAs<TValue>::type as() const {
return getMember().template as<TValue>();
}
template <typename TValue>
FORCE_INLINE bool is() const {
return getMember().template is<TValue>();
}
template <typename TValue>
FORCE_INLINE typename VariantTo<TValue>::type to() {
return getOrCreateMember().template to<TValue>();
}
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
const TValue &value) {
return getOrCreateMember().set(value);
}
// set(char*) const
// set(const char*) const
// set(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE bool set(const TChar *value) {
return getOrCreateMember().set(value);
}
template <typename Visitor>
void accept(Visitor &visitor) const {
return getMember().accept(visitor);
}
using ArrayShortcuts<MemberProxy>::add;
FORCE_INLINE VariantRef add() const {
return getOrCreateMember().add();
}
// get(char*) const
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef get(TChar *key) const {
return getMember().get(key);
}
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE VariantRef get(const TString &key) const {
return getMember().get(key);
}
// getOrCreate(char*) const
// getOrCreate(const char*) const
// getOrCreate(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getOrCreate(TChar *key) const {
return getOrCreateMember().getOrCreate(key);
}
// getOrCreate(const std::string&) const
// getOrCreate(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getOrCreate(const TString &key) const {
return getOrCreateMember().getOrCreate(key);
}
private:
FORCE_INLINE VariantRef getMember() const {
return _object.get(_key);
}
FORCE_INLINE VariantRef getOrCreateMember() const {
return _object.getOrCreate(_key);
}
TObject _object;
TStringRef _key;
};
template <typename TObject>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
MemberProxy<const TObject &, const TString &> >::type
ObjectShortcuts<TObject>::operator[](const TString &key) const {
return MemberProxy<const TObject &, const TString &>(*impl(), key);
}
template <typename TObject>
template <typename TString>
inline typename enable_if<IsString<TString *>::value,
MemberProxy<const TObject &, TString *> >::type
ObjectShortcuts<TObject>::operator[](TString *key) const {
return MemberProxy<const TObject &, TString *>(*impl(), key);
}
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)
#endif

View File

@ -16,8 +16,8 @@ void objectAccept(const CollectionData *obj, Visitor &visitor) {
visitor.visitNull();
}
template <typename TKey>
inline bool objectContainsKey(const CollectionData *obj, TKey key) {
template <typename TAdaptedString>
inline bool objectContainsKey(const CollectionData *obj, TAdaptedString key) {
return obj && obj->containsKey(key);
}
@ -27,20 +27,21 @@ inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
return lhs->equalsObject(*rhs);
}
template <typename TKey>
inline VariantData *objectGet(const CollectionData *obj, TKey key) {
template <typename TAdaptedString>
inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) {
if (!obj) return 0;
return obj->get(key);
}
template <typename TKey>
void objectRemove(CollectionData *obj, TKey key) {
template <typename TAdaptedString>
void objectRemove(CollectionData *obj, TAdaptedString key) {
if (!obj) return;
obj->remove(key);
}
template <typename TKey>
inline VariantData *objectSet(CollectionData *obj, TKey key, MemoryPool *pool) {
template <typename TAdaptedString>
inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key,
MemoryPool *pool) {
if (!obj) return 0;
// ignore null key

View File

@ -9,13 +9,30 @@
namespace ARDUINOJSON_NAMESPACE {
template <typename TObject>
template <typename TString>
inline ArrayRef ObjectRef::createNestedArray(const TString& key) const {
return set(key).template to<ArrayRef>();
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
const TString& key) const {
return impl()->getOrCreate(key).template to<ArrayRef>();
}
template <typename TObject>
template <typename TChar>
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(TChar* key) const {
return impl()->getOrCreate(key).template to<ArrayRef>();
}
template <typename TObject>
template <typename TString>
inline ArrayRef ObjectRef::createNestedArray(TString* key) const {
return set(key).template to<ArrayRef>();
inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
const TString& key) const {
return impl()->getOrCreate(key).template to<ObjectRef>();
}
template <typename TObject>
template <typename TChar>
inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
TChar* key) const {
return impl()->getOrCreate(key).template to<ObjectRef>();
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -17,31 +17,42 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename TData>
class ObjectRefBase {
public:
operator VariantConstRef() const {
return VariantConstRef(reinterpret_cast<const VariantData*>(_data));
}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
objectAccept(_data, visitor);
}
// Tells weither the specified key is present and associated with a value.
//
// bool containsKey(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE bool containsKey(const TKey& key) const {
return objectContainsKey(_data, wrapString(key));
// containsKey(const std::string&) const
// containsKey(const String&) const
template <typename TString>
FORCE_INLINE bool containsKey(const TString& key) const {
return objectContainsKey(_data, adaptString(key));
}
//
// bool containsKey(TKey);
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE bool containsKey(TKey* key) const {
return objectContainsKey(_data, wrapString(key));
// containsKey(char*) const
// containsKey(const char*) const
// containsKey(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE bool containsKey(TChar* key) const {
return objectContainsKey(_data, adaptString(key));
}
FORCE_INLINE bool isNull() const {
return _data == 0;
}
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0;
}
FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0;
}
@ -71,41 +82,38 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>,
return iterator();
}
// Gets the value associated with the specified key.
//
// TValue get<TValue>(TKey) const;
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, ArrayConstRef, ObjectConstRef
template <typename TKey>
FORCE_INLINE VariantConstRef get(const TKey& key) const {
return get_impl(wrapString(key));
}
//
// TValue get<TValue>(TKey) const;
// TKey = char*, const char*, const __FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, ArrayConstRef, ObjectConstRef
template <typename TKey>
FORCE_INLINE VariantConstRef get(TKey* key) const {
return get_impl(wrapString(key));
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE VariantConstRef get(const TString& key) const {
return get_impl(adaptString(key));
}
//
// VariantConstRef operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantConstRef>::type
operator[](const TKey& key) const {
return get_impl(wrapString(key));
// get(char*) const
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantConstRef get(TChar* key) const {
return get_impl(adaptString(key));
}
//
// VariantConstRef operator[](TKey) const;
// TKey = const char*, const char[N], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey*>::value, VariantConstRef>::type
operator[](TKey* key) const {
return get_impl(wrapString(key));
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString& key) const {
return get_impl(adaptString(key));
}
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
operator[](TChar* key) const {
return get_impl(adaptString(key));
}
FORCE_INLINE bool operator==(ObjectConstRef rhs) const {
@ -113,13 +121,15 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>,
}
private:
template <typename TKey>
FORCE_INLINE VariantConstRef get_impl(TKey key) const {
template <typename TAdaptedString>
FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const {
return VariantConstRef(objectGet(_data, key));
}
};
class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable {
class ObjectRef : public ObjectRefBase<CollectionData>,
public ObjectShortcuts<ObjectRef>,
public Visitable {
typedef ObjectRefBase<CollectionData> base_type;
public:
@ -156,68 +166,34 @@ class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable {
return _data->copyFrom(*src._data, _pool);
}
// Creates and adds a ArrayRef.
//
// ArrayRef createNestedArray(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE ArrayRef createNestedArray(const TKey& key) const;
// ArrayRef createNestedArray(TKey);
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE ArrayRef createNestedArray(TKey* key) const;
// Creates and adds a ObjectRef.
//
// ObjectRef createNestedObject(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE ObjectRef createNestedObject(const TKey& key) const {
return set(key).template to<ObjectRef>();
}
//
// ObjectRef createNestedObject(TKey);
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE ObjectRef createNestedObject(TKey* key) const {
return set(key).template to<ObjectRef>();
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE VariantRef get(const TString& key) const {
return get_impl(adaptString(key));
}
// Gets the value associated with the specified key.
//
// TValue get<TValue>(TKey) const;
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, ArrayRef, ObjectRef
template <typename TKey>
FORCE_INLINE VariantRef get(const TKey& key) const {
return get_impl(wrapString(key));
}
//
// TValue get<TValue>(TKey) const;
// TKey = char*, const char*, const __FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, ArrayRef, ObjectRef
template <typename TKey>
FORCE_INLINE VariantRef get(TKey* key) const {
return get_impl(wrapString(key));
// get(char*) const
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef get(TChar* key) const {
return get_impl(adaptString(key));
}
// Gets or sets the value associated with the specified key.
//
// ObjectSubscript operator[](TKey)
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE ObjectSubscript<const TKey&> operator[](const TKey& key) const {
return ObjectSubscript<const TKey&>(*this, key);
// getOrCreate(const std::string&) const
// getOrCreate(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getOrCreate(const TString& key) const {
return getOrCreate_impl(adaptString(key));
}
//
// ObjectSubscript operator[](TKey)
// TKey = char*, const char*, char[], const char[N], const
// __FlashStringHelper*
template <typename TKey>
FORCE_INLINE ObjectSubscript<TKey*> operator[](TKey* key) const {
return ObjectSubscript<TKey*>(*this, key);
// getOrCreate(char*) const
// getOrCreate(const char*) const
// getOrCreate(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getOrCreate(TChar* key) const {
return getOrCreate_impl(adaptString(key));
}
FORCE_INLINE bool operator==(ObjectRef rhs) const {
@ -229,41 +205,30 @@ class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable {
_data->remove(it.internal());
}
// Removes the specified key and the associated value.
//
// void remove(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE void remove(const TKey& key) const {
objectRemove(_data, wrapString(key));
}
//
// void remove(TKey);
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE void remove(TKey* key) const {
objectRemove(_data, wrapString(key));
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE void remove(const TString& key) const {
objectRemove(_data, adaptString(key));
}
template <typename TKey>
FORCE_INLINE VariantRef set(TKey* key) const {
return set_impl(wrapString(key));
}
template <typename TKey>
FORCE_INLINE VariantRef set(const TKey& key) const {
return set_impl(wrapString(key));
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE void remove(TChar* key) const {
objectRemove(_data, adaptString(key));
}
private:
template <typename TKey>
FORCE_INLINE VariantRef get_impl(TKey key) const {
template <typename TAdaptedString>
FORCE_INLINE VariantRef get_impl(TAdaptedString key) const {
return VariantRef(_pool, objectGet(_data, key));
}
template <typename TKey>
FORCE_INLINE VariantRef set_impl(TKey key) const {
return VariantRef(_pool, objectSet(_data, key, _pool));
template <typename TAdaptedString>
FORCE_INLINE VariantRef getOrCreate_impl(TAdaptedString key) const {
return VariantRef(_pool, objectGetOrCreate(_data, key, _pool));
}
MemoryPool* _pool;

View File

@ -0,0 +1,61 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Polyfills/attributes.hpp"
#include "../Polyfills/type_traits.hpp"
#include "../Strings/StringAdapters.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TParent, typename TStringRef>
class MemberProxy;
template <typename TObject>
class ObjectShortcuts {
public:
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value,
MemberProxy<const TObject &, const TString &> >::type
operator[](const TString &key) const;
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar *>::value,
MemberProxy<const TObject &, TChar *> >::type
operator[](TChar *key) const;
// createNestedArray(const std::string&) const
// createNestedArray(const String&) const
template <typename TString>
FORCE_INLINE ArrayRef createNestedArray(const TString &key) const;
// createNestedArray(char*) const
// createNestedArray(const char*) const
// createNestedArray(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE ArrayRef createNestedArray(TChar *key) const;
// createNestedObject(const std::string&) const
// createNestedObject(const String&) const
template <typename TString>
ObjectRef createNestedObject(const TString &key) const;
// createNestedObject(char*) const
// createNestedObject(const char*) const
// createNestedObject(const __FlashStringHelper*) const
template <typename TChar>
ObjectRef createNestedObject(TChar *key) const;
private:
const TObject *impl() const {
return static_cast<const TObject *>(this);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,132 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Configuration.hpp"
#include "../Operators/VariantOperators.hpp"
#include "../Polyfills/type_traits.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE {
template <typename TStringRef>
class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >,
public Visitable {
typedef ObjectSubscript<TStringRef> this_type;
public:
FORCE_INLINE ObjectSubscript(ObjectRef object, TStringRef key)
: _object(object), _key(key) {}
operator VariantConstRef() const {
return get_impl();
}
FORCE_INLINE this_type &operator=(const this_type &src) {
set_impl().set(src);
return *this;
}
// Set the specified value
//
// operator=(const TValue&);
// TValue = bool, char, long, int, short, float, double,
// std::string, String, ArrayRef, ObjectRef
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
operator=(const TValue &src) {
set_impl().set(src);
return *this;
}
//
// operator=(TValue);
// TValue = char*, const char*, const __FlashStringHelper*
template <typename TValue>
FORCE_INLINE this_type &operator=(TValue *src) {
set_impl().set(src);
return *this;
}
FORCE_INLINE bool isNull() const {
return get_impl().isNull();
}
template <typename TValue>
FORCE_INLINE typename VariantAs<TValue>::type as() const {
return get_impl().template as<TValue>();
}
template <typename TValue>
FORCE_INLINE bool is() const {
return get_impl().template is<TValue>();
}
template <typename TValue>
FORCE_INLINE typename VariantTo<TValue>::type to() {
return set_impl().template to<TValue>();
}
// Sets the specified value.
//
// bool set(const TValue&);
// TValue = bool, char, long, int, short, float, double, serialized,
// VariantRef,
// std::string, String, ArrayRef, ObjectRef
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
const TValue &value) {
return set_impl().set(value);
}
//
// bool set(TValue);
// TValue = char*, const char, const __FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(const TValue *value) {
return set_impl().set(value);
}
template <typename Visitor>
void accept(Visitor &visitor) const {
return get_impl().accept(visitor);
}
private:
FORCE_INLINE VariantRef get_impl() const {
return _object.get(_key);
}
FORCE_INLINE VariantRef set_impl() const {
return _object.set(_key);
}
ObjectRef _object;
TStringRef _key;
};
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
ObjectSubscript<const TString &> >::type
VariantSubscripts<TImpl>::operator[](const TString &key) const {
return impl()->template as<ObjectRef>()[key];
}
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString *>::value,
ObjectSubscript<TString *> >::type
VariantSubscripts<TImpl>::operator[](TString *key) const {
return impl()->template as<ObjectRef>()[key];
}
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)
#endif

View File

@ -13,7 +13,7 @@ class Pair {
public:
Pair(MemoryPool* pool, VariantSlot* slot) {
if (slot) {
_key = slot->key();
_key = String(slot->key(), !slot->ownsKey());
_value = VariantRef(pool, slot->data());
}
}
@ -35,7 +35,7 @@ class PairConst {
public:
PairConst(const VariantSlot* slot) {
if (slot) {
_key = slot->key();
_key = String(slot->key(), !slot->ownsKey());
_value = VariantConstRef(slot->data());
}
}

View File

@ -21,28 +21,28 @@ class VariantComparisons {
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator==(
T *lhs, TVariant rhs) {
return wrapString(lhs).equals(rhs.template as<const char *>());
return adaptString(lhs).equals(rhs.template as<const char *>());
}
// std::string == TVariant
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator==(
const T &lhs, TVariant rhs) {
return wrapString(lhs).equals(rhs.template as<const char *>());
return adaptString(lhs).equals(rhs.template as<const char *>());
}
// TVariant == const char*
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator==(
TVariant lhs, T *rhs) {
return wrapString(rhs).equals(lhs.template as<const char *>());
return adaptString(rhs).equals(lhs.template as<const char *>());
}
// TVariant == std::string
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator==(
TVariant lhs, const T &rhs) {
return wrapString(rhs).equals(lhs.template as<const char *>());
return adaptString(rhs).equals(lhs.template as<const char *>());
}
// bool/int/float == TVariant
@ -63,28 +63,28 @@ class VariantComparisons {
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
T *lhs, TVariant rhs) {
return !wrapString(lhs).equals(rhs.template as<const char *>());
return !adaptString(lhs).equals(rhs.template as<const char *>());
}
// std::string != TVariant
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator!=(
const T &lhs, TVariant rhs) {
return !wrapString(lhs).equals(rhs.template as<const char *>());
return !adaptString(lhs).equals(rhs.template as<const char *>());
}
// TVariant != const char*
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
TVariant lhs, T *rhs) {
return !wrapString(rhs).equals(lhs.template as<const char *>());
return !adaptString(rhs).equals(lhs.template as<const char *>());
}
// TVariant != std::string
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator!=(
TVariant lhs, const T &rhs) {
return !wrapString(rhs).equals(lhs.template as<const char *>());
return !adaptString(rhs).equals(lhs.template as<const char *>());
}
// bool/int/float != TVariant

View File

@ -7,7 +7,7 @@
#include "VariantCasts.hpp"
#include "VariantComparisons.hpp"
#include "VariantOr.hpp"
#include "VariantSubscripts.hpp"
#include "VariantShortcuts.hpp"
namespace ARDUINOJSON_NAMESPACE {
@ -15,5 +15,5 @@ template <typename TImpl>
class VariantOperators : public VariantCasts<TImpl>,
public VariantComparisons<TImpl>,
public VariantOr<TImpl>,
public VariantSubscripts<TImpl> {};
public VariantShortcuts<TImpl> {};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,23 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Array/ArrayShortcuts.hpp"
#include "../Object/ObjectShortcuts.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TVariant>
class VariantShortcuts : public ObjectShortcuts<TVariant>,
public ArrayShortcuts<TVariant> {
public:
using ArrayShortcuts<TVariant>::createNestedArray;
using ArrayShortcuts<TVariant>::createNestedObject;
using ArrayShortcuts<TVariant>::operator[];
using ObjectShortcuts<TVariant>::createNestedArray;
using ObjectShortcuts<TVariant>::createNestedObject;
using ObjectShortcuts<TVariant>::operator[];
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,51 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Polyfills/attributes.hpp"
#include "../Polyfills/type_traits.hpp"
#include "../Strings/StringWrappers.hpp"
#include "../Variant/VariantAs.hpp"
namespace ARDUINOJSON_NAMESPACE {
class ArrayRef;
class ObjectRef;
// Forward declarations.
class ArraySubscript;
template <typename TKey>
class ObjectSubscript;
template <typename TImpl>
class VariantSubscripts {
public:
// Mimics an array.
// Returns the element at specified index if the variant is an array.
FORCE_INLINE ArraySubscript operator[](size_t index) const;
// Mimics an object.
// Returns the value associated with the specified key if the variant is
// an object.
//
// ObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
ObjectSubscript<const TString &> >::type
operator[](const TString &key) const;
//
// ObjectSubscript operator[](TKey) const;
// TKey = const char*, const char[N], const __FlashStringHelper*
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString *>::value,
ObjectSubscript<TString *> >::type
operator[](TString *key) const;
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,9 +8,9 @@
namespace ARDUINOJSON_NAMESPACE {
class ArduinoStringWrapper {
class ArduinoStringAdapter {
public:
ArduinoStringWrapper(const ::String& str) : _str(&str) {}
ArduinoStringAdapter(const ::String& str) : _str(&str) {}
char* save(MemoryPool* pool) const {
if (isNull()) return NULL;
@ -40,6 +40,10 @@ class ArduinoStringWrapper {
return _str->length();
}
bool isStatic() const {
return false;
}
private:
const ::String* _str;
};
@ -50,8 +54,8 @@ struct IsString< ::String> : true_type {};
template <>
struct IsString< ::StringSumHelper> : true_type {};
inline ArduinoStringWrapper wrapString(const ::String& str) {
return ArduinoStringWrapper(str);
inline ArduinoStringAdapter adaptString(const ::String& str) {
return ArduinoStringAdapter(str);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -9,9 +9,9 @@
namespace ARDUINOJSON_NAMESPACE {
class ConstRamStringWrapper {
class ConstRamStringAdapter {
public:
ConstRamStringWrapper(const char* str = 0) : _str(str) {}
ConstRamStringAdapter(const char* str = 0) : _str(str) {}
bool equals(const char* expected) const {
const char* actual = _str;
@ -23,25 +23,29 @@ class ConstRamStringWrapper {
return !_str;
}
// template <typename TMemoryPool>
// const char* save(TMemoryPool*) const {
// return _str;
// }
template <typename TMemoryPool>
char* save(TMemoryPool*) const {
return 0;
}
size_t size() const {
return strlen(_str);
}
const char* c_str() const {
const char* data() const {
return _str;
}
bool isStatic() const {
return true;
}
protected:
const char* _str;
};
inline ConstRamStringWrapper wrapString(const char* str) {
return ConstRamStringWrapper(str);
inline ConstRamStringAdapter adaptString(const char* str) {
return ConstRamStringAdapter(str);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,9 +6,9 @@
namespace ARDUINOJSON_NAMESPACE {
class FlashStringWrapper {
class FlashStringAdapter {
public:
FlashStringWrapper(const __FlashStringHelper* str) : _str(str) {}
FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {}
bool equals(const char* expected) const {
const char* actual = reinterpret_cast<const char*>(_str);
@ -28,16 +28,24 @@ class FlashStringWrapper {
return dup;
}
const char* data() const {
return 0;
}
size_t size() const {
return strlen_P(reinterpret_cast<const char*>(_str));
}
bool isStatic() const {
return false;
}
private:
const __FlashStringHelper* _str;
};
inline FlashStringWrapper wrapString(const __FlashStringHelper* str) {
return FlashStringWrapper(str);
inline FlashStringAdapter adaptString(const __FlashStringHelper* str) {
return FlashStringAdapter(str);
}
template <>

View File

@ -4,13 +4,13 @@
#pragma once
#include "ConstRamStringWrapper.hpp"
#include "ConstRamStringAdapter.hpp"
namespace ARDUINOJSON_NAMESPACE {
class RamStringWrapper : public ConstRamStringWrapper {
class RamStringAdapter : public ConstRamStringAdapter {
public:
RamStringWrapper(const char* str) : ConstRamStringWrapper(str) {}
RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
char* save(MemoryPool* pool) const {
if (!_str) return NULL;
@ -19,15 +19,19 @@ class RamStringWrapper : public ConstRamStringWrapper {
if (dup) memcpy(dup, _str, n);
return dup;
}
bool isStatic() const {
return false;
}
};
template <typename TChar>
inline RamStringWrapper wrapString(const TChar* str) {
return RamStringWrapper(reinterpret_cast<const char*>(str));
inline RamStringAdapter adaptString(const TChar* str) {
return RamStringAdapter(reinterpret_cast<const char*>(str));
}
inline RamStringWrapper wrapString(char* str) {
return RamStringWrapper(str);
inline RamStringAdapter adaptString(char* str) {
return RamStringAdapter(str);
}
template <typename TChar>

View File

@ -6,9 +6,9 @@
namespace ARDUINOJSON_NAMESPACE {
class SizedFlashStringWrapper {
class SizedFlashStringAdapter {
public:
SizedFlashStringWrapper(const __FlashStringHelper* str, size_t sz)
SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz)
: _str(str), _size(sz) {}
bool equals(const char* expected) const {
@ -32,13 +32,17 @@ class SizedFlashStringWrapper {
return strlen_P(reinterpret_cast<const char*>(_str));
}
bool isStatic() const {
return false;
}
private:
const __FlashStringHelper* _str;
size_t _size;
};
inline SizedFlashStringWrapper wrapString(const __FlashStringHelper* str,
size_t sz) {
return SizedFlashStringWrapper(str, sz);
inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str,
size_t sz) {
return SizedFlashStringAdapter(str, sz);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,9 +8,9 @@
namespace ARDUINOJSON_NAMESPACE {
class SizedRamStringWrapper {
class SizedRamStringAdapter {
public:
SizedRamStringWrapper(const char* str, size_t n) : _str(str), _size(n) {}
SizedRamStringAdapter(const char* str, size_t n) : _str(str), _size(n) {}
bool equals(const char* expected) const {
const char* actual = reinterpret_cast<const char*>(_str);
@ -33,14 +33,18 @@ class SizedRamStringWrapper {
return strlen(reinterpret_cast<const char*>(_str));
}
bool isStatic() const {
return false;
}
private:
const char* _str;
size_t _size;
};
template <typename TChar>
inline SizedRamStringWrapper wrapString(const TChar* str, size_t size) {
return SizedRamStringWrapper(reinterpret_cast<const char*>(str), size);
inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) {
return SizedRamStringAdapter(reinterpret_cast<const char*>(str), size);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,9 +8,9 @@
namespace ARDUINOJSON_NAMESPACE {
class StlStringWrapper {
class StlStringAdapter {
public:
StlStringWrapper(const std::string& str) : _str(&str) {}
StlStringAdapter(const std::string& str) : _str(&str) {}
char* save(MemoryPool* pool) const {
size_t n = _str->length() + 1;
@ -36,6 +36,10 @@ class StlStringWrapper {
return _str->size();
}
bool isStatic() const {
return false;
}
private:
const std::string* _str;
};
@ -43,8 +47,8 @@ class StlStringWrapper {
template <>
struct IsString<std::string> : true_type {};
inline StlStringWrapper wrapString(const std::string& str) {
return StlStringWrapper(str);
inline StlStringAdapter adaptString(const std::string& str) {
return StlStringAdapter(str);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,12 +4,15 @@
#pragma once
#include "ConstRamStringAdapter.hpp"
namespace ARDUINOJSON_NAMESPACE {
class String {
public:
String() : _data(0) {}
String(const char* slot) : _data(slot) {}
String() : _data(0), _isStatic(true) {}
String(const char* data, bool isStaticData = true)
: _data(data), _isStatic(isStaticData) {}
const char* c_str() const {
return _data;
@ -19,6 +22,10 @@ class String {
return !_data;
}
bool isStatic() const {
return _isStatic;
}
friend bool operator==(String lhs, String rhs) {
if (lhs._data == rhs._data) return true;
if (!lhs._data) return false;
@ -28,5 +35,31 @@ class String {
private:
const char* _data;
bool _isStatic;
};
class StringAdapter : public RamStringAdapter {
public:
StringAdapter(const String& str)
: RamStringAdapter(str.c_str()), _isStatic(str.isStatic()) {}
bool isStatic() const {
return _isStatic;
}
/* const char* save(MemoryPool* pool) const {
if (_isStatic) return c_str();
return RamStringAdapter::save(pool);
}*/
private:
bool _isStatic;
};
template <>
struct IsString<String> : true_type {};
inline StringAdapter adaptString(const String& str) {
return StringAdapter(str);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -18,19 +18,19 @@ template <typename T>
struct IsString<T&> : IsString<T> {};
} // namespace ARDUINOJSON_NAMESPACE
#include "ConstRamStringWrapper.hpp"
#include "RamStringWrapper.hpp"
#include "SizedRamStringWrapper.hpp"
#include "ConstRamStringAdapter.hpp"
#include "RamStringAdapter.hpp"
#include "SizedRamStringAdapter.hpp"
#if ARDUINOJSON_ENABLE_STD_STRING
#include "StlStringWrapper.hpp"
#include "StlStringAdapter.hpp"
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include "ArduinoStringWrapper.hpp"
#include "ArduinoStringAdapter.hpp"
#endif
#if ARDUINOJSON_ENABLE_PROGMEM
#include "FlashStringWrapper.hpp"
#include "SizedFlashStringWrapper.hpp"
#include "FlashStringAdapter.hpp"
#include "SizedFlashStringAdapter.hpp"
#endif

View File

@ -6,24 +6,21 @@
#include "../Memory/MemoryPool.hpp"
#include "../Polyfills/assert.hpp"
#include "../Strings/StringWrappers.hpp"
#include "../Strings/StringAdapters.hpp"
#include "VariantData.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) {
template <typename TAdaptedString>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
if (!var) return false;
char* dup = key.save(pool);
if (!dup) return false;
var->setOwnedKey(dup);
return true;
}
inline bool slotSetKey(VariantSlot* var, ConstRamStringWrapper key,
MemoryPool*) {
if (!var) return false;
var->setLinkedKey(key.c_str());
if (key.isStatic()) {
var->setLinkedKey(key.data());
} else {
char* dup = key.save(pool);
if (!dup) return false;
var->setOwnedKey(dup);
}
return true;
}

View File

@ -77,6 +77,14 @@ variantAs(const VariantData* _data) {
return _data != 0 ? _data->asString() : 0;
}
template <typename T>
inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs(
const VariantData* _data);
template <typename T>
inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs(
const VariantData* _data);
template <typename T>
inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
variantAs(const VariantData* _data);

View File

@ -5,10 +5,23 @@
#pragma once
#include "../Serialization/DynamicStringWriter.hpp"
#include "VariantFunctions.hpp"
#include "VariantRef.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs(
const VariantData* _data) {
return ArrayConstRef(variantAsArray(_data));
}
template <typename T>
inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs(
const VariantData* _data) {
return ObjectConstRef(variantAsObject(_data));
}
template <typename T>
inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
variantAs(const VariantData* _data) {

View File

@ -12,19 +12,24 @@
namespace ARDUINOJSON_NAMESPACE {
//
enum {
VALUE_IS_NULL = 0,
VALUE_IS_LINKED_RAW,
VALUE_IS_OWNED_RAW,
VALUE_IS_LINKED_STRING,
VALUE_IS_OWNED_STRING,
VALUE_IS_BOOLEAN,
VALUE_IS_POSITIVE_INTEGER,
VALUE_IS_NEGATIVE_INTEGER,
VALUE_IS_ARRAY,
VALUE_IS_OBJECT,
VALUE_IS_FLOAT,
VALUE_MASK = 0x7F,
VALUE_IS_NULL = 0,
VALUE_IS_LINKED_RAW = 0x01,
VALUE_IS_OWNED_RAW = 0x02,
VALUE_IS_LINKED_STRING = 0x03,
VALUE_IS_OWNED_STRING = 0x04,
VALUE_IS_BOOLEAN = 0x05,
VALUE_IS_POSITIVE_INTEGER = 0x06,
VALUE_IS_NEGATIVE_INTEGER = 0x07,
VALUE_IS_FLOAT = 0x08,
COLLECTION_MASK = 0x60,
VALUE_IS_OBJECT = 0x20,
VALUE_IS_ARRAY = 0x40,
KEY_IS_OWNED = 0x80
};

View File

@ -67,10 +67,7 @@ class VariantData {
}
CollectionData *asArray() {
if (type() == VALUE_IS_ARRAY)
return &_content.asCollection;
else
return 0;
return isArray() ? &_content.asCollection : 0;
}
const CollectionData *asArray() const {
@ -78,10 +75,7 @@ class VariantData {
}
CollectionData *asObject() {
if (type() == VALUE_IS_OBJECT)
return &_content.asCollection;
else
return 0;
return isObject() ? &_content.asCollection : 0;
}
const CollectionData *asObject() const {
@ -95,7 +89,7 @@ class VariantData {
case VALUE_IS_OBJECT:
return toObject().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OWNED_STRING:
return setOwnedString(RamStringWrapper(src._content.asString), pool);
return setOwnedString(RamStringAdapter(src._content.asString), pool);
case VALUE_IS_OWNED_RAW:
return setOwnedRaw(
serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
@ -141,13 +135,17 @@ class VariantData {
}
bool isArray() const {
return type() == VALUE_IS_ARRAY;
return (_flags & VALUE_IS_ARRAY) != 0;
}
bool isBoolean() const {
return type() == VALUE_IS_BOOLEAN;
}
bool isCollection() const {
return (_flags & COLLECTION_MASK) != 0;
}
bool isInteger() const {
return type() == VALUE_IS_POSITIVE_INTEGER ||
type() == VALUE_IS_NEGATIVE_INTEGER;
@ -159,12 +157,11 @@ class VariantData {
}
bool isString() const {
return (type() == VALUE_IS_LINKED_STRING ||
type() == VALUE_IS_OWNED_STRING);
return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
}
bool isObject() const {
return type() == VALUE_IS_OBJECT;
return (_flags & VALUE_IS_OBJECT) != 0;
}
bool isNull() const {
@ -189,7 +186,7 @@ class VariantData {
template <typename T>
bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
char *dup = wrapString(value.data(), value.size()).save(pool);
char *dup = adaptString(value.data(), value.size()).save(pool);
if (dup) {
setType(VALUE_IS_OWNED_RAW);
_content.asRaw.data = dup;
@ -266,11 +263,50 @@ class VariantData {
return _content.asCollection;
}
size_t memoryUsage() const {
switch (type()) {
case VALUE_IS_OWNED_STRING:
return strlen(_content.asString) + 1;
case VALUE_IS_OWNED_RAW:
return _content.asRaw.size;
case VALUE_IS_OBJECT:
case VALUE_IS_ARRAY:
return _content.asCollection.memoryUsage();
default:
return 0;
}
}
size_t nesting() const {
return isCollection() ? _content.asCollection.nesting() : 0;
}
size_t size() const {
if (type() == VALUE_IS_OBJECT || type() == VALUE_IS_ARRAY)
return _content.asCollection.size();
else
return 0;
return isCollection() ? _content.asCollection.size() : 0;
}
VariantData *get(size_t index) const {
return isArray() ? _content.asCollection.get(index) : 0;
}
template <typename TAdaptedString>
VariantData *get(TAdaptedString key) const {
return isObject() ? _content.asCollection.get(key) : 0;
}
template <typename TAdaptedString>
VariantData *getOrCreate(TAdaptedString key, MemoryPool *pool) {
if (isNull()) toObject();
if (!isObject()) return 0;
VariantData *var = _content.asCollection.get(key);
if (var) return var;
return _content.asCollection.add(key, pool);
}
VariantData *add(MemoryPool *pool) {
if (isNull()) toArray();
if (!isArray()) return 0;
return _content.asCollection.add(pool);
}
private:

View File

@ -16,6 +16,10 @@ inline void variantAccept(const VariantData *var, Visitor &visitor) {
visitor.visitNull();
}
inline const CollectionData *variantAsArray(const VariantData *var) {
return var != 0 ? var->asArray() : 0;
}
inline const CollectionData *variantAsObject(const VariantData *var) {
return var != 0 ? var->asObject() : 0;
}
@ -142,4 +146,20 @@ inline CollectionData *variantToObject(VariantData *var) {
return &var->toObject();
}
inline NO_INLINE VariantData *variantAdd(VariantData *var, MemoryPool *pool) {
return var != 0 ? var->add(pool) : 0;
}
template <typename TChar>
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TChar *key,
MemoryPool *pool) {
return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0;
}
template <typename TString>
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TString &key,
MemoryPool *pool) {
return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -50,7 +50,7 @@ inline T VariantData::asFloat() const {
}
}
inline const char* VariantData::asString() const {
inline const char *VariantData::asString() const {
switch (type()) {
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
@ -60,29 +60,11 @@ inline const char* VariantData::asString() const {
}
}
inline bool VariantRef::set(ArrayRef array) const {
return to<ArrayRef>().copyFrom(array);
}
inline bool VariantRef::set(const ArraySubscript& value) const {
return set(value.as<VariantRef>());
}
inline bool VariantRef::set(ObjectRef object) const {
return to<ObjectRef>().copyFrom(object);
}
template <typename TString>
inline bool VariantRef::set(const ObjectSubscript<TString>& value) const {
return set(value.template as<VariantRef>());
}
inline bool VariantRef::set(VariantConstRef value) const {
return variantCopyFrom(_data, value._data, _pool);
}
inline bool VariantRef::set(VariantRef value) const {
return variantCopyFrom(_data, value._data, _pool);
template <typename TVariant>
typename enable_if<IsVisitable<TVariant>::value, bool>::type VariantRef::set(
const TVariant &value) const {
VariantConstRef v = value;
return variantCopyFrom(_data, v._data, _pool);
}
template <typename T>
@ -120,4 +102,32 @@ inline VariantConstRef VariantConstRef::operator[](size_t index) const {
return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index];
}
inline VariantRef VariantRef::add() const {
return VariantRef(_pool, variantAdd(_data, _pool));
}
inline VariantRef VariantRef::get(size_t index) const {
return VariantRef(_pool, _data != 0 ? _data->get(index) : 0);
}
template <typename TChar>
inline VariantRef VariantRef::get(TChar *key) const {
return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0);
}
template <typename TString>
inline typename enable_if<IsString<TString>::value, VariantRef>::type
VariantRef::get(const TString &key) const {
return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0);
}
template <typename TChar>
inline VariantRef VariantRef::getOrCreate(TChar *key) const {
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
}
template <typename TString>
inline VariantRef VariantRef::getOrCreate(const TString &key) const {
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -23,6 +23,9 @@ namespace ARDUINOJSON_NAMESPACE {
class ArrayRef;
class ObjectRef;
template <typename, typename>
class MemberProxy;
// Contains the methods shared by VariantRef and VariantConstRef
template <typename TData>
class VariantRefBase {
@ -95,6 +98,14 @@ class VariantRefBase {
return variantIsNull(_data);
}
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0;
}
size_t size() const {
return variantSize(_data);
}
@ -183,7 +194,7 @@ class VariantRef : public VariantRefBase<VariantData>,
FORCE_INLINE bool set(
const T &value,
typename enable_if<IsString<T>::value>::type * = 0) const {
return variantSetOwnedString(_data, wrapString(value), _pool);
return variantSetOwnedString(_data, adaptString(value), _pool);
}
// set(char*)
@ -191,7 +202,7 @@ class VariantRef : public VariantRefBase<VariantData>,
template <typename T>
FORCE_INLINE bool set(
T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
return variantSetOwnedString(_data, wrapString(value), _pool);
return variantSetOwnedString(_data, adaptString(value), _pool);
}
// set(const char*);
@ -199,14 +210,15 @@ class VariantRef : public VariantRefBase<VariantData>,
return variantSetLinkedString(_data, value);
}
bool set(VariantConstRef value) const;
bool set(VariantRef value) const;
FORCE_INLINE bool set(ArrayRef array) const;
FORCE_INLINE bool set(const ArraySubscript &) const;
FORCE_INLINE bool set(ObjectRef object) const;
template <typename TString>
FORCE_INLINE bool set(const ObjectSubscript<TString> &) const;
// set(VariantRef)
// set(VariantConstRef)
// set(ArrayRef)
// set(ArrayConstRef)
// set(ObjectRef)
// set(ObjecConstRef)
template <typename TVariant>
typename enable_if<IsVisitable<TVariant>::value, bool>::type set(
const TVariant &value) const;
// Get the variant as the specified type.
//
@ -268,6 +280,33 @@ class VariantRef : public VariantRefBase<VariantData>,
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
const;
VariantRef add() const;
using ArrayShortcuts::add;
FORCE_INLINE VariantRef get(size_t) const;
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef get(TChar *) const;
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
get(const TString &) const;
// getOrCreate(char*) const
// getOrCreate(const char*) const
// getOrCreate(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getOrCreate(TChar *) const;
// getOrCreate(const std::string&) const
// getOrCreate(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getOrCreate(const TString &) const;
private:
MemoryPool *_pool;
};
@ -297,24 +336,24 @@ class VariantConstRef : public VariantRefBase<const VariantData>,
FORCE_INLINE VariantConstRef operator[](size_t index) const;
//
// const VariantConstRef operator[](TKey) const;
// TKey = const std::string&, const String&
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString &key) const {
return VariantConstRef(objectGet(variantAsObject(_data), wrapString(key)));
return VariantConstRef(objectGet(variantAsObject(_data), adaptString(key)));
}
//
// VariantConstRef operator[](TKey);
// TKey = const char*, const char[N], const __FlashStringHelper*
template <typename TString>
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TString *>::value, VariantConstRef>::type
operator[](TString *key) const {
typename enable_if<IsString<TChar *>::value, VariantConstRef>::type
operator[](TChar *key) const {
const CollectionData *obj = variantAsObject(_data);
return VariantConstRef(obj ? obj->get(wrapString(key)) : 0);
return VariantConstRef(obj ? obj->get(adaptString(key)) : 0);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,7 +4,7 @@
#pragma once
#define ARDUINOJSON_VERSION "6.7.0-beta"
#define ARDUINOJSON_VERSION "6.8.0-beta"
#define ARDUINOJSON_VERSION_MAJOR 6
#define ARDUINOJSON_VERSION_MINOR 7
#define ARDUINOJSON_VERSION_MINOR 8
#define ARDUINOJSON_VERSION_REVISION 0

View File

@ -71,6 +71,7 @@ if(MSVC)
)
endif()
add_subdirectory(ElementProxy)
add_subdirectory(IntegrationTests)
add_subdirectory(JsonArray)
add_subdirectory(JsonDeserializer)
@ -78,10 +79,11 @@ add_subdirectory(JsonDocument)
add_subdirectory(JsonObject)
add_subdirectory(JsonSerializer)
add_subdirectory(JsonVariant)
add_subdirectory(JsonWriter)
add_subdirectory(MemberProxy)
add_subdirectory(MemoryPool)
add_subdirectory(Misc)
add_subdirectory(MixedConfiguration)
add_subdirectory(MsgPackDeserializer)
add_subdirectory(MsgPackSerializer)
add_subdirectory(Numbers)
add_subdirectory(TextFormatter)

View File

@ -0,0 +1,11 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2018
# MIT License
add_executable(ElementProxyTests
add.cpp
set.cpp
)
target_link_libraries(ElementProxyTests catch)
add_test(ElementProxy ElementProxyTests)

26
test/ElementProxy/add.cpp Normal file
View File

@ -0,0 +1,26 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
using namespace ARDUINOJSON_NAMESPACE;
TEST_CASE("ElementProxy::add()") {
DynamicJsonDocument doc(4096);
doc.add();
ElementProxy<JsonDocument&> ep = doc[0];
SECTION("add(int)") {
ep.add(42);
REQUIRE(doc.as<std::string>() == "[[42]]");
}
SECTION("add(const char*)") {
ep.add("world");
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
}
}

26
test/ElementProxy/set.cpp Normal file
View File

@ -0,0 +1,26 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
using namespace ARDUINOJSON_NAMESPACE;
TEST_CASE("ElementProxy::set()") {
DynamicJsonDocument doc(4096);
doc.add();
ElementProxy<JsonDocument&> ep = doc[0];
SECTION("set(int)") {
ep.set(42);
REQUIRE(doc.as<std::string>() == "[42]");
}
SECTION("set(const char*)") {
ep.set("world");
REQUIRE(doc.as<std::string>() == "[\"world\"]");
}
}

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
TEST_CASE("Gbathree") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeJson(
doc,

View File

@ -8,7 +8,8 @@
// https://github.com/bblanchon/ArduinoJson/issues/772
TEST_CASE("Issue772") {
DynamicJsonDocument doc1, doc2;
DynamicJsonDocument doc1(4096);
DynamicJsonDocument doc2(4096);
DeserializationError err;
std::string data =
"{\"state\":{\"reported\":{\"timestamp\":\"2018-07-02T09:40:12Z\","

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
void check(std::string originalJson) {
DynamicJsonDocument doc;
DynamicJsonDocument doc(16384);
std::string prettyJson;
deserializeJson(doc, originalJson);

View File

@ -11,6 +11,8 @@ add_executable(JsonArrayTests
get.cpp
isNull.cpp
iterator.cpp
memoryUsage.cpp
nesting.cpp
remove.cpp
size.cpp
std_string.cpp

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
TEST_CASE("JsonArray::add()") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
SECTION("int") {
@ -51,7 +51,7 @@ TEST_CASE("JsonArray::add()") {
#endif
SECTION("nested array") {
DynamicJsonDocument doc2;
DynamicJsonDocument doc2(4096);
JsonArray arr = doc2.to<JsonArray>();
array.add(arr);
@ -62,7 +62,7 @@ TEST_CASE("JsonArray::add()") {
}
SECTION("nested object") {
DynamicJsonDocument doc2;
DynamicJsonDocument doc2(4096);
JsonObject obj = doc2.to<JsonObject>();
array.add(obj);
@ -74,7 +74,7 @@ TEST_CASE("JsonArray::add()") {
SECTION("array subscript") {
const char* str = "hello";
DynamicJsonDocument doc2;
DynamicJsonDocument doc2(4096);
JsonArray arr = doc2.to<JsonArray>();
arr.add(str);
@ -85,7 +85,7 @@ TEST_CASE("JsonArray::add()") {
SECTION("object subscript") {
const char* str = "hello";
DynamicJsonDocument doc2;
DynamicJsonDocument doc2(4096);
JsonObject obj = doc2.to<JsonObject>();
obj["x"] = str;

View File

@ -7,7 +7,7 @@
TEST_CASE("JsonArray::copyFrom()") {
SECTION("OneDimension") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
char json[32];
int source[] = {1, 2, 3};
@ -34,7 +34,7 @@ TEST_CASE("JsonArray::copyFrom()") {
}
SECTION("TwoDimensions") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
char json[32];
int source[][3] = {{1, 2, 3}, {4, 5, 6}};

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
TEST_CASE("JsonArray::copyTo()") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
SECTION("BiggerOneDimensionIntegerArray") {
char json[] = "[1,2,3]";

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
TEST_CASE("JsonArray basics") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
SECTION("CreateNestedArray") {

View File

@ -6,11 +6,11 @@
#include <catch.hpp>
TEST_CASE("JsonArray::operator==()") {
DynamicJsonDocument doc1;
DynamicJsonDocument doc1(4096);
JsonArray array1 = doc1.to<JsonArray>();
JsonArrayConst array1c = array1;
DynamicJsonDocument doc2;
DynamicJsonDocument doc2(4096);
JsonArray array2 = doc2.to<JsonArray>();
JsonArrayConst array2c = array2;

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
TEST_CASE("JsonArray::get()") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
deserializeJson(doc, "[1,2,3]");
JsonArray array = doc.as<JsonArray>();

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
TEST_CASE("JsonArray::isNull()") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
SECTION("returns true") {
JsonArray arr;
@ -20,7 +20,7 @@ TEST_CASE("JsonArray::isNull()") {
}
TEST_CASE("JsonArrayConst::isNull()") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
SECTION("returns true") {
JsonArrayConst arr;

View File

@ -0,0 +1,42 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
TEST_CASE("JsonArray::memoryUsage()") {
DynamicJsonDocument doc(4096);
JsonArray arr = doc.to<JsonArray>();
SECTION("return 0 if uninitialized") {
JsonArray unitialized;
REQUIRE(unitialized.memoryUsage() == 0);
}
SECTION("JSON_ARRAY_SIZE(0) if empty") {
REQUIRE(arr.memoryUsage() == JSON_ARRAY_SIZE(0));
}
SECTION("JSON_ARRAY_SIZE(1) after add") {
arr.add("hello");
REQUIRE(arr.memoryUsage() == JSON_ARRAY_SIZE(1));
}
SECTION("includes the size of the string") {
arr.add(std::string("hello"));
REQUIRE(arr.memoryUsage() == JSON_ARRAY_SIZE(1) + 6);
}
SECTION("includes the size of the nested array") {
JsonArray nested = arr.createNestedArray();
nested.add(42);
REQUIRE(arr.memoryUsage() == 2 * JSON_ARRAY_SIZE(1));
}
SECTION("includes the size of the nested arrect") {
JsonObject nested = arr.createNestedObject();
nested["hello"] = "world";
REQUIRE(arr.memoryUsage() == JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1));
}
}

View File

@ -0,0 +1,35 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
TEST_CASE("JsonArray::nesting()") {
DynamicJsonDocument doc(4096);
JsonArray arr = doc.to<JsonArray>();
SECTION("return 0 if uninitialized") {
JsonArray unitialized;
REQUIRE(unitialized.nesting() == 0);
}
SECTION("returns 1 for empty array") {
REQUIRE(arr.nesting() == 1);
}
SECTION("returns 1 for flat array") {
arr.add("hello");
REQUIRE(arr.nesting() == 1);
}
SECTION("returns 2 with nested array") {
arr.createNestedArray();
REQUIRE(arr.nesting() == 2);
}
SECTION("returns 2 with nested object") {
arr.createNestedObject();
REQUIRE(arr.nesting() == 2);
}
}

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
TEST_CASE("JsonArray::remove()") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
JsonArray _array = doc.to<JsonArray>();
_array.add(1);
_array.add(2);

View File

@ -6,10 +6,10 @@
#include <catch.hpp>
TEST_CASE("JsonArray::size()") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
SECTION("InitialSizeIsZero") {
SECTION("returns 0 is empty") {
REQUIRE(0U == array.size());
}

View File

@ -11,7 +11,7 @@ static void eraseString(std::string &str) {
}
TEST_CASE("std::string") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
SECTION("add()") {

View File

@ -7,7 +7,7 @@
#include <catch.hpp>
TEST_CASE("JsonArray::operator[]") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
array.add(0);
@ -52,7 +52,7 @@ TEST_CASE("JsonArray::operator[]") {
}
SECTION("nested array") {
DynamicJsonDocument doc2;
DynamicJsonDocument doc2(4096);
JsonArray arr2 = doc2.to<JsonArray>();
array[0] = arr2;
@ -63,7 +63,7 @@ TEST_CASE("JsonArray::operator[]") {
}
SECTION("nested object") {
DynamicJsonDocument doc2;
DynamicJsonDocument doc2(4096);
JsonObject obj = doc2.to<JsonObject>();
array[0] = obj;
@ -74,7 +74,7 @@ TEST_CASE("JsonArray::operator[]") {
}
SECTION("array subscript") {
DynamicJsonDocument doc2;
DynamicJsonDocument doc2(4096);
JsonArray arr2 = doc2.to<JsonArray>();
const char* str = "hello";
@ -87,7 +87,7 @@ TEST_CASE("JsonArray::operator[]") {
SECTION("object subscript") {
const char* str = "hello";
DynamicJsonDocument doc2;
DynamicJsonDocument doc2(4096);
JsonObject obj = doc2.to<JsonObject>();
obj["x"] = str;
@ -146,7 +146,7 @@ TEST_CASE("JsonArray::operator[]") {
}
TEST_CASE("JsonArrayConst::operator[]") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
array.add(0);

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
TEST_CASE("deserialize JSON array") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
SECTION("An empty array") {
DeserializationError err = deserializeJson(doc, "[]");

View File

@ -6,7 +6,7 @@
#include <catch.hpp>
TEST_CASE("deserialize JSON object") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
SECTION("An empty object") {
DeserializationError err = deserializeJson(doc, "{}");

View File

@ -13,7 +13,7 @@ using ARDUINOJSON_NAMESPACE::isnan;
} // namespace my
TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
SECTION("null char*") {
DeserializationError err = deserializeJson(doc, static_cast<char*>(0));

View File

@ -7,7 +7,7 @@
#include <sstream>
TEST_CASE("deserializeJson(const std::string&)") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
SECTION("should accept const string") {
const std::string input("[42]");
@ -36,7 +36,7 @@ TEST_CASE("deserializeJson(const std::string&)") {
}
TEST_CASE("deserializeJson(std::istream&)") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
SECTION("array") {
std::istringstream json(" [ 42 /* comment */ ] ");

View File

@ -9,27 +9,93 @@
#define SHOULD_FAIL(expression) \
REQUIRE(DeserializationError::TooDeep == expression);
TEST_CASE("JsonDeserializer nestingLimit") {
DynamicJsonDocument doc;
TEST_CASE("JsonDeserializer nesting") {
DynamicJsonDocument doc(4096);
SECTION("limit = 0") {
doc.nestingLimit = 0;
SHOULD_WORK(deserializeJson(doc, "\"toto\""));
SHOULD_WORK(deserializeJson(doc, "123"));
SHOULD_WORK(deserializeJson(doc, "true"));
SHOULD_FAIL(deserializeJson(doc, "[]"));
SHOULD_FAIL(deserializeJson(doc, "{}"));
SHOULD_FAIL(deserializeJson(doc, "[\"toto\"]"));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":1}"));
SECTION("Input = const char*") {
SECTION("limit = 0") {
DeserializationOption::NestingLimit nesting(0);
SHOULD_WORK(deserializeJson(doc, "\"toto\"", nesting));
SHOULD_WORK(deserializeJson(doc, "123", nesting));
SHOULD_WORK(deserializeJson(doc, "true", nesting));
SHOULD_FAIL(deserializeJson(doc, "[]", nesting));
SHOULD_FAIL(deserializeJson(doc, "{}", nesting));
SHOULD_FAIL(deserializeJson(doc, "[\"toto\"]", nesting));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":1}", nesting));
}
SECTION("limit = 1") {
DeserializationOption::NestingLimit nesting(1);
SHOULD_WORK(deserializeJson(doc, "[\"toto\"]", nesting));
SHOULD_WORK(deserializeJson(doc, "{\"toto\":1}", nesting));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":{}}", nesting));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":[]}", nesting));
SHOULD_FAIL(deserializeJson(doc, "[[\"toto\"]]", nesting));
SHOULD_FAIL(deserializeJson(doc, "[{\"toto\":1}]", nesting));
}
}
SECTION("limit = 1") {
doc.nestingLimit = 1;
SHOULD_WORK(deserializeJson(doc, "[\"toto\"]"));
SHOULD_WORK(deserializeJson(doc, "{\"toto\":1}"));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":{}}"));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":[]}"));
SHOULD_FAIL(deserializeJson(doc, "[[\"toto\"]]"));
SHOULD_FAIL(deserializeJson(doc, "[{\"toto\":1}]"));
SECTION("char* and size_t") {
SECTION("limit = 0") {
DeserializationOption::NestingLimit nesting(0);
SHOULD_WORK(deserializeJson(doc, "\"toto\"", 6, nesting));
SHOULD_WORK(deserializeJson(doc, "123", 3, nesting));
SHOULD_WORK(deserializeJson(doc, "true", 4, nesting));
SHOULD_FAIL(deserializeJson(doc, "[]", 2, nesting));
SHOULD_FAIL(deserializeJson(doc, "{}", 2, nesting));
SHOULD_FAIL(deserializeJson(doc, "[\"toto\"]", 8, nesting));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":1}", 10, nesting));
}
SECTION("limit = 1") {
DeserializationOption::NestingLimit nesting(1);
SHOULD_WORK(deserializeJson(doc, "[\"toto\"]", 8, nesting));
SHOULD_WORK(deserializeJson(doc, "{\"toto\":1}", 10, nesting));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":{}}", 11, nesting));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":[]}", 11, nesting));
SHOULD_FAIL(deserializeJson(doc, "[[\"toto\"]]", 10, nesting));
SHOULD_FAIL(deserializeJson(doc, "[{\"toto\":1}]", 12, nesting));
}
}
SECTION("Input = std::string") {
SECTION("limit = 0") {
DeserializationOption::NestingLimit nesting(0);
SHOULD_WORK(deserializeJson(doc, std::string("\"toto\""), nesting));
SHOULD_WORK(deserializeJson(doc, std::string("123"), nesting));
SHOULD_WORK(deserializeJson(doc, std::string("true"), nesting));
SHOULD_FAIL(deserializeJson(doc, std::string("[]"), nesting));
SHOULD_FAIL(deserializeJson(doc, std::string("{}"), nesting));
SHOULD_FAIL(deserializeJson(doc, std::string("[\"toto\"]"), nesting));
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":1}"), nesting));
}
SECTION("limit = 1") {
DeserializationOption::NestingLimit nesting(1);
SHOULD_WORK(deserializeJson(doc, std::string("[\"toto\"]"), nesting));
SHOULD_WORK(deserializeJson(doc, std::string("{\"toto\":1}"), nesting));
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":{}}"), nesting));
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":[]}"), nesting));
SHOULD_FAIL(deserializeJson(doc, std::string("[[\"toto\"]]"), nesting));
SHOULD_FAIL(deserializeJson(doc, std::string("[{\"toto\":1}]"), nesting));
}
}
SECTION("Input = std::istream") {
SECTION("limit = 0") {
DeserializationOption::NestingLimit nesting(0);
std::istringstream good("true");
std::istringstream bad("[]");
SHOULD_WORK(deserializeJson(doc, good, nesting));
SHOULD_FAIL(deserializeJson(doc, bad, nesting));
}
SECTION("limit = 1") {
DeserializationOption::NestingLimit nesting(1);
std::istringstream good("[\"toto\"]");
std::istringstream bad("{\"toto\":{}}");
SHOULD_WORK(deserializeJson(doc, good, nesting));
SHOULD_FAIL(deserializeJson(doc, bad, nesting));
}
}
}

View File

@ -3,8 +3,13 @@
# MIT License
add_executable(JsonDocumentTests
add.cpp
createNested.cpp
DynamicJsonDocument.cpp
isNull.cpp
nesting.cpp
StaticJsonDocument.cpp
subscript.cpp
)
target_link_libraries(JsonDocumentTests catch)

View File

@ -5,8 +5,16 @@
#include <ArduinoJson.h>
#include <catch.hpp>
using ARDUINOJSON_NAMESPACE::addPadding;
static void REQUIRE_JSON(JsonDocument& doc, const std::string& expected) {
std::string json;
serializeJson(doc, json);
REQUIRE(json == expected);
}
TEST_CASE("DynamicJsonDocument") {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
SECTION("serializeJson()") {
JsonObject obj = doc.to<JsonObject>();
@ -74,80 +82,128 @@ TEST_CASE("DynamicJsonDocument") {
}
}
TEST_CASE("DynamicJsonDocument copies") {
TEST_CASE("DynamicJsonDocument constructor") {
SECTION("Copy constructor") {
DynamicJsonDocument doc1(1234);
deserializeJson(doc1, "{\"hello\":\"world\"}");
doc1.nestingLimit = 42;
DynamicJsonDocument doc2 = doc1;
std::string json;
serializeJson(doc2, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
REQUIRE(doc2.nestingLimit == 42);
REQUIRE(doc2.capacity() == doc1.capacity());
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
}
SECTION("Construct from StaticJsonDocument") {
StaticJsonDocument<200> doc1;
deserializeJson(doc1, "{\"hello\":\"world\"}");
DynamicJsonDocument doc2 = doc1;
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
}
SECTION("Construct from JsonObject") {
StaticJsonDocument<200> doc1;
JsonObject obj = doc1.to<JsonObject>();
obj["hello"] = "world";
DynamicJsonDocument doc2 = obj;
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
}
SECTION("Construct from JsonArray") {
StaticJsonDocument<200> doc1;
JsonArray arr = doc1.to<JsonArray>();
arr.add("hello");
DynamicJsonDocument doc2 = arr;
REQUIRE_JSON(doc2, "[\"hello\"]");
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
}
SECTION("Construct from JsonVariant") {
StaticJsonDocument<200> doc1;
deserializeJson(doc1, "42");
DynamicJsonDocument doc2 = doc1.as<JsonVariant>();
REQUIRE_JSON(doc2, "42");
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
}
}
TEST_CASE("DynamicJsonDocument assignment") {
SECTION("Copy assignment preserves the buffer when capacity is sufficient") {
DynamicJsonDocument doc1(1234);
deserializeJson(doc1, "{\"hello\":\"world\"}");
doc1.nestingLimit = 42;
DynamicJsonDocument doc2(doc1.capacity());
doc2 = doc1;
std::string json;
serializeJson(doc2, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(doc2.nestingLimit == 42);
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
REQUIRE(doc2.capacity() == doc1.capacity());
}
SECTION("Copy assignment realloc the buffer when capacity is insufficient") {
DynamicJsonDocument doc1(1234);
deserializeJson(doc1, "{\"hello\":\"world\"}");
doc1.nestingLimit = 42;
DynamicJsonDocument doc2(8);
REQUIRE(doc2.capacity() < doc1.memoryUsage());
doc2 = doc1;
REQUIRE(doc2.capacity() >= doc1.memoryUsage());
std::string json;
serializeJson(doc2, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(doc2.nestingLimit == 42);
}
SECTION("Construct from StaticJsonDocument") {
StaticJsonDocument<200> sdoc;
deserializeJson(sdoc, "{\"hello\":\"world\"}");
sdoc.nestingLimit = 42;
DynamicJsonDocument ddoc = sdoc;
std::string json;
serializeJson(ddoc, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(ddoc.nestingLimit == 42);
REQUIRE(ddoc.capacity() == sdoc.capacity());
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Assign from StaticJsonDocument") {
DynamicJsonDocument ddoc;
ddoc.to<JsonVariant>().set(666);
StaticJsonDocument<200> doc1;
deserializeJson(doc1, "{\"hello\":\"world\"}");
DynamicJsonDocument doc2(4096);
doc2.to<JsonVariant>().set(666);
StaticJsonDocument<200> sdoc;
deserializeJson(sdoc, "{\"hello\":\"world\"}");
sdoc.nestingLimit = 42;
doc2 = doc1;
ddoc = sdoc;
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
std::string json;
serializeJson(ddoc, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(ddoc.nestingLimit == 42);
SECTION("Assign from JsonObject") {
StaticJsonDocument<200> doc1;
JsonObject obj = doc1.to<JsonObject>();
obj["hello"] = "world";
DynamicJsonDocument doc2(4096);
doc2 = obj;
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
REQUIRE(doc2.capacity() == 4096);
}
SECTION("Assign from JsonArray") {
StaticJsonDocument<200> doc1;
JsonArray arr = doc1.to<JsonArray>();
arr.add("hello");
DynamicJsonDocument doc2(4096);
doc2 = arr;
REQUIRE_JSON(doc2, "[\"hello\"]");
REQUIRE(doc2.capacity() == 4096);
}
SECTION("Assign from JsonVariant") {
StaticJsonDocument<200> doc1;
deserializeJson(doc1, "42");
DynamicJsonDocument doc2(4096);
doc2 = doc1.as<JsonVariant>();
REQUIRE_JSON(doc2, "42");
REQUIRE(doc2.capacity() == 4096);
}
}

View File

@ -5,6 +5,12 @@
#include <ArduinoJson.h>
#include <catch.hpp>
static void REQUIRE_JSON(JsonDocument& doc, const std::string& expected) {
std::string json;
serializeJson(doc, json);
REQUIRE(json == expected);
}
TEST_CASE("StaticJsonDocument") {
SECTION("capacity()") {
SECTION("matches template argument") {
@ -33,82 +39,174 @@ TEST_CASE("StaticJsonDocument") {
StaticJsonDocument<200> doc1, doc2;
doc1.to<JsonVariant>().set(666);
deserializeJson(doc2, "{\"hello\":\"world\"}");
doc2.nestingLimit = 42;
doc1 = doc2;
std::string json;
serializeJson(doc1, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(doc1.nestingLimit == 42);
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Copy constructor") {
StaticJsonDocument<200> doc1;
deserializeJson(doc1, "{\"hello\":\"world\"}");
doc1.nestingLimit = 42;
SECTION("Contructor") {
SECTION("Copy constructor") {
StaticJsonDocument<200> doc1;
deserializeJson(doc1, "{\"hello\":\"world\"}");
StaticJsonDocument<200> doc2 = doc1;
StaticJsonDocument<200> doc2 = doc1;
std::string json;
serializeJson(doc2, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(doc2.nestingLimit == 42);
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Construct from StaticJsonDocument of different size") {
StaticJsonDocument<300> doc1;
deserializeJson(doc1, "{\"hello\":\"world\"}");
StaticJsonDocument<200> doc2 = doc1;
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Construct from DynamicJsonDocument") {
DynamicJsonDocument doc1(4096);
deserializeJson(doc1, "{\"hello\":\"world\"}");
StaticJsonDocument<200> doc2 = doc1;
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Construct from JsonObject") {
DynamicJsonDocument doc1(4096);
deserializeJson(doc1, "{\"hello\":\"world\"}");
StaticJsonDocument<200> doc2 = doc1.as<JsonObject>();
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Construct from JsonArray") {
DynamicJsonDocument doc1(4096);
deserializeJson(doc1, "[\"hello\",\"world\"]");
StaticJsonDocument<200> doc2 = doc1.as<JsonArray>();
deserializeJson(doc1, "[\"HELLO\",\"WORLD\"]");
REQUIRE_JSON(doc2, "[\"hello\",\"world\"]");
}
SECTION("Construct from JsonVariant") {
DynamicJsonDocument doc1(4096);
deserializeJson(doc1, "42");
StaticJsonDocument<200> doc2 = doc1.as<JsonVariant>();
REQUIRE_JSON(doc2, "42");
}
}
SECTION("Assign from StaticJsonDocument of different capacity") {
StaticJsonDocument<200> doc1;
StaticJsonDocument<300> doc2;
doc1.to<JsonVariant>().set(666);
deserializeJson(doc2, "{\"hello\":\"world\"}");
doc2.nestingLimit = 42;
SECTION("Assignment") {
SECTION("Copy assignment") {
StaticJsonDocument<200> doc1, doc2;
doc1.to<JsonVariant>().set(666);
deserializeJson(doc1, "{\"hello\":\"world\"}");
doc1 = doc2;
doc2 = doc1;
std::string json;
serializeJson(doc1, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(doc1.nestingLimit == 42);
}
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Assign from DynamicJsonDocument") {
StaticJsonDocument<200> doc1;
DynamicJsonDocument doc2;
doc1.to<JsonVariant>().set(666);
deserializeJson(doc2, "{\"hello\":\"world\"}");
doc2.nestingLimit = 42;
SECTION("Assign from StaticJsonDocument of different capacity") {
StaticJsonDocument<200> doc1;
StaticJsonDocument<300> doc2;
doc1.to<JsonVariant>().set(666);
deserializeJson(doc1, "{\"hello\":\"world\"}");
doc1 = doc2;
doc2 = doc1;
std::string json;
serializeJson(doc1, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(doc1.nestingLimit == 42);
}
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Construct from StaticJsonDocument of different size") {
StaticJsonDocument<300> doc2;
deserializeJson(doc2, "{\"hello\":\"world\"}");
doc2.nestingLimit = 42;
SECTION("Assign from DynamicJsonDocument") {
StaticJsonDocument<200> doc1;
DynamicJsonDocument doc2(4096);
doc1.to<JsonVariant>().set(666);
deserializeJson(doc1, "{\"hello\":\"world\"}");
StaticJsonDocument<200> doc1 = doc2;
doc2 = doc1;
std::string json;
serializeJson(doc1, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(doc1.nestingLimit == 42);
}
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Construct from DynamicJsonDocument") {
DynamicJsonDocument doc2;
deserializeJson(doc2, "{\"hello\":\"world\"}");
doc2.nestingLimit = 42;
SECTION("Assign from JsonArray") {
StaticJsonDocument<200> doc1;
DynamicJsonDocument doc2(4096);
doc1.to<JsonVariant>().set(666);
deserializeJson(doc1, "[\"hello\",\"world\"]");
StaticJsonDocument<200> doc1 = doc2;
doc2 = doc1.as<JsonArray>();
std::string json;
serializeJson(doc1, json);
REQUIRE(json == "{\"hello\":\"world\"}");
REQUIRE(doc1.nestingLimit == 42);
deserializeJson(doc1, "[\"HELLO\",\"WORLD\"]");
REQUIRE_JSON(doc2, "[\"hello\",\"world\"]");
}
SECTION("Assign from JsonArrayConst") {
StaticJsonDocument<200> doc1;
DynamicJsonDocument doc2(4096);
doc1.to<JsonVariant>().set(666);
deserializeJson(doc1, "[\"hello\",\"world\"]");
doc2 = doc1.as<JsonArrayConst>();
deserializeJson(doc1, "[\"HELLO\",\"WORLD\"]");
REQUIRE_JSON(doc2, "[\"hello\",\"world\"]");
}
SECTION("Assign from JsonObject") {
StaticJsonDocument<200> doc1;
DynamicJsonDocument doc2(4096);
doc1.to<JsonVariant>().set(666);
deserializeJson(doc1, "{\"hello\":\"world\"}");
doc2 = doc1.as<JsonObject>();
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Assign from JsonObjectConst") {
StaticJsonDocument<200> doc1;
DynamicJsonDocument doc2(4096);
doc1.to<JsonVariant>().set(666);
deserializeJson(doc1, "{\"hello\":\"world\"}");
doc2 = doc1.as<JsonObjectConst>();
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
}
SECTION("Assign from JsonVariant") {
DynamicJsonDocument doc1(4096);
doc1.to<JsonVariant>().set(666);
deserializeJson(doc1, "42");
StaticJsonDocument<200> doc2;
doc2 = doc1.as<JsonVariant>();
REQUIRE_JSON(doc2, "42");
}
SECTION("Assign from JsonVariantConst") {
DynamicJsonDocument doc1(4096);
doc1.to<JsonVariant>().set(666);
deserializeJson(doc1, "42");
StaticJsonDocument<200> doc2;
doc2 = doc1.as<JsonVariantConst>();
REQUIRE_JSON(doc2, "42");
}
}
}

22
test/JsonDocument/add.cpp Normal file
View File

@ -0,0 +1,22 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
TEST_CASE("JsonDocument::add()") {
DynamicJsonDocument doc(4096);
SECTION("integer") {
doc.add(42);
REQUIRE(doc.as<std::string>() == "[42]");
}
SECTION("const char*") {
doc.add("hello");
REQUIRE(doc.as<std::string>() == "[\"hello\"]");
}
}

View File

@ -0,0 +1,66 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
TEST_CASE("JsonDocument::createNestedArray()") {
DynamicJsonDocument doc(4096);
SECTION("promotes to array") {
doc.createNestedArray();
REQUIRE(doc.is<JsonArray>());
}
}
TEST_CASE("JsonDocument::createNestedArray(key)") {
DynamicJsonDocument doc(4096);
SECTION("key is const char*") {
SECTION("promotes to object") {
doc.createNestedArray("hello");
REQUIRE(doc.is<JsonObject>());
}
}
SECTION("key is std::string") {
SECTION("promotes to object") {
doc.createNestedArray(std::string("hello"));
REQUIRE(doc.is<JsonObject>());
}
}
}
TEST_CASE("JsonDocument::createNestedObject()") {
DynamicJsonDocument doc(4096);
SECTION("promotes to array") {
doc.createNestedObject();
REQUIRE(doc.is<JsonArray>());
}
}
TEST_CASE("JsonDocument::createNestedObject(key)") {
DynamicJsonDocument doc(4096);
SECTION("key is const char*") {
SECTION("promotes to object") {
doc.createNestedObject("hello");
REQUIRE(doc.is<JsonObject>());
}
}
SECTION("key is std::string") {
SECTION("promotes to object") {
doc.createNestedObject(std::string("hello"));
REQUIRE(doc.is<JsonObject>());
}
}
}

View File

@ -0,0 +1,39 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
TEST_CASE("JsonDocument::isNull()") {
DynamicJsonDocument doc(4096);
SECTION("returns true if uninitialized") {
REQUIRE(doc.isNull() == true);
}
SECTION("returns false after to<JsonObject>()") {
doc.to<JsonObject>();
REQUIRE(doc.isNull() == false);
}
SECTION("returns false after to<JsonArray>()") {
doc.to<JsonArray>();
REQUIRE(doc.isNull() == false);
}
SECTION("returns true after to<JsonVariant>()") {
REQUIRE(doc.isNull() == true);
}
SECTION("returns false after set()") {
doc.to<JsonVariant>().set(42);
REQUIRE(doc.isNull() == false);
}
SECTION("returns true after clear()") {
doc.to<JsonObject>();
doc.clear();
REQUIRE(doc.isNull() == true);
}
}

Some files were not shown because too many files have changed in this diff Show More