forked from bblanchon/ArduinoJson
Compare commits
19 Commits
v6.7.0-bet
...
v6.8.0-bet
Author | SHA1 | Date | |
---|---|---|---|
169c83431c | |||
5f72c68d87 | |||
b184af6d00 | |||
6f55d1e58f | |||
5aea1363cc | |||
0685a36f0e | |||
70739f5cfd | |||
933a66a070 | |||
4167b11434 | |||
2a3b51ac3a | |||
e633292df1 | |||
30b94493bb | |||
c51cc91f92 | |||
8b04046321 | |||
11bb5e26ff | |||
9ac2ac303c | |||
f0784d3b41 | |||
3d8ece8c8b | |||
b0fb71f7d8 |
64
CHANGELOG.md
64
CHANGELOG.md
@ -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)
|
||||
-----------
|
||||
|
||||
|
10
README.md
10
README.md
@ -2,7 +2,11 @@
|
||||
|
||||
---
|
||||
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=6.x) [](https://github.com/bblanchon/ArduinoJson)
|
||||
[](https://www.ardu-badge.com/ArduinoJson/6.7.0-beta)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
[](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
|
||||
[](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";
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
39
keywords.txt
39
keywords.txt
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
47
src/ArduinoJson/Array/ArrayShortcuts.hpp
Normal file
47
src/ArduinoJson/Array/ArrayShortcuts.hpp
Normal 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
|
@ -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
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
17
src/ArduinoJson/Deserialization/NestingLimit.hpp
Normal file
17
src/ArduinoJson/Deserialization/NestingLimit.hpp
Normal 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
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
158
src/ArduinoJson/Object/MemberProxy.hpp
Normal file
158
src/ArduinoJson/Object/MemberProxy.hpp
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
61
src/ArduinoJson/Object/ObjectShortcuts.hpp
Normal file
61
src/ArduinoJson/Object/ObjectShortcuts.hpp
Normal 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
|
@ -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
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
23
src/ArduinoJson/Operators/VariantShortcuts.hpp
Normal file
23
src/ArduinoJson/Operators/VariantShortcuts.hpp
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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 <>
|
@ -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>
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
11
test/ElementProxy/CMakeLists.txt
Normal file
11
test/ElementProxy/CMakeLists.txt
Normal 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
26
test/ElementProxy/add.cpp
Normal 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
26
test/ElementProxy/set.cpp
Normal 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\"]");
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("Gbathree") {
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
DeserializationError error = deserializeJson(
|
||||
doc,
|
||||
|
@ -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\","
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <catch.hpp>
|
||||
|
||||
void check(std::string originalJson) {
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(16384);
|
||||
|
||||
std::string prettyJson;
|
||||
deserializeJson(doc, originalJson);
|
||||
|
@ -11,6 +11,8 @@ add_executable(JsonArrayTests
|
||||
get.cpp
|
||||
isNull.cpp
|
||||
iterator.cpp
|
||||
memoryUsage.cpp
|
||||
nesting.cpp
|
||||
remove.cpp
|
||||
size.cpp
|
||||
std_string.cpp
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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}};
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::copyTo()") {
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("BiggerOneDimensionIntegerArray") {
|
||||
char json[] = "[1,2,3]";
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray basics") {
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
|
||||
SECTION("CreateNestedArray") {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>();
|
||||
|
||||
|
@ -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;
|
||||
|
42
test/JsonArray/memoryUsage.cpp
Normal file
42
test/JsonArray/memoryUsage.cpp
Normal 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));
|
||||
}
|
||||
}
|
35
test/JsonArray/nesting.cpp
Normal file
35
test/JsonArray/nesting.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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()") {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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, "[]");
|
||||
|
@ -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, "{}");
|
||||
|
@ -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));
|
||||
|
@ -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 */ ] ");
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
22
test/JsonDocument/add.cpp
Normal 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\"]");
|
||||
}
|
||||
}
|
66
test/JsonDocument/createNested.cpp
Normal file
66
test/JsonDocument/createNested.cpp
Normal 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>());
|
||||
}
|
||||
}
|
||||
}
|
39
test/JsonDocument/isNull.cpp
Normal file
39
test/JsonDocument/isNull.cpp
Normal 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
Reference in New Issue
Block a user