mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
upgrade arduinojson to 6.17.0
This commit is contained in:
@@ -1,6 +1,19 @@
|
|||||||
ArduinoJson: change log
|
ArduinoJson: change log
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
v6.17.0 (2020-10-19)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added a build failure when nullptr is defined as a macro (issue #1355)
|
||||||
|
* Added `JsonDocument::overflowed()` which tells if the memory pool was too small (issue #1358)
|
||||||
|
* Added `DeserializationError::EmptyInput` which tells if the input was empty
|
||||||
|
* Added `DeserializationError::f_str()` which returns a `const __FlashStringHelper*` (issue #846)
|
||||||
|
* Added `operator|(JsonVariantConst, JsonVariantConst)`
|
||||||
|
* Added filtering for MessagePack (issue #1298, PR #1394 by Luca Passarella)
|
||||||
|
* Moved float convertion tables to PROGMEM
|
||||||
|
* Fixed `JsonVariant::set((char*)0)` which returned false instead of true (issue #1368)
|
||||||
|
* Fixed error `No such file or directory #include <WString.h>` (issue #1381)
|
||||||
|
|
||||||
v6.16.1 (2020-08-04)
|
v6.16.1 (2020-08-04)
|
||||||
-------
|
-------
|
||||||
|
|
||||||
@@ -12,6 +25,7 @@ v6.16.0 (2020-08-01)
|
|||||||
* Added comparisons (`>`, `>=`, `==`, `!=`, `<`, and `<=`) between `JsonVariant`s
|
* Added comparisons (`>`, `>=`, `==`, `!=`, `<`, and `<=`) between `JsonVariant`s
|
||||||
* Added string deduplication (issue #1303)
|
* Added string deduplication (issue #1303)
|
||||||
* Added `JsonString::operator!=`
|
* Added `JsonString::operator!=`
|
||||||
|
* Added wildcard key (`*`) for filters (issue #1309)
|
||||||
* Set `ARDUINOJSON_DECODE_UNICODE` to `1` by default
|
* Set `ARDUINOJSON_DECODE_UNICODE` to `1` by default
|
||||||
* Fixed `copyArray()` not working with `String`, `ElementProxy`, and `MemberProxy`
|
* Fixed `copyArray()` not working with `String`, `ElementProxy`, and `MemberProxy`
|
||||||
* Fixed error `getOrAddElement is not a member of ElementProxy` (issue #1311)
|
* Fixed error `getOrAddElement is not a member of ElementProxy` (issue #1311)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[](https://www.ardu-badge.com/ArduinoJson/6.16.1)
|
[](https://www.ardu-badge.com/ArduinoJson/6.17.0)
|
||||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
||||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
|
||||||
|
|||||||
27
lib/ArduinoJson/SUPPORT.md
Normal file
27
lib/ArduinoJson/SUPPORT.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# ArduinoJson Support
|
||||||
|
|
||||||
|
First off, thank you very much for using ArduinoJson.
|
||||||
|
|
||||||
|
We'll be very happy to help you, but first please read the following.
|
||||||
|
|
||||||
|
## Before asking for help
|
||||||
|
|
||||||
|
1. Read the [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=support)
|
||||||
|
2. Search in the [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=support)
|
||||||
|
|
||||||
|
If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new).
|
||||||
|
|
||||||
|
It is OK to add a comment to a currently opened issue, but please avoid adding comments to a closed issue.
|
||||||
|
|
||||||
|
## Before hitting the Submit button
|
||||||
|
|
||||||
|
Please provide all the relevant information:
|
||||||
|
|
||||||
|
* Good title
|
||||||
|
* Short description of the problem
|
||||||
|
* Target platform
|
||||||
|
* Compiler model and version
|
||||||
|
* [MVCE](https://stackoverflow.com/help/mcve)
|
||||||
|
* Compiler output
|
||||||
|
|
||||||
|
Good questions get fast answers!
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// This example shows how to store your project configuration in a file.
|
|
||||||
// It uses the SD library but can be easily modified for any other file-system.
|
|
||||||
//
|
|
||||||
// The file contains a JSON document with the following content:
|
|
||||||
// {
|
|
||||||
// "hostname": "examples.com",
|
|
||||||
// "port": 2731
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// To run this program, you need an SD card connected to the SPI bus as follows:
|
|
||||||
// * MOSI <-> pin 11
|
|
||||||
// * MISO <-> pin 12
|
|
||||||
// * CLK <-> pin 13
|
|
||||||
// * CS <-> pin 4
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/config/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <SD.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
|
|
||||||
// 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. See:
|
|
||||||
// https://arduinojson.org/v6/faq/why-must-i-create-a-separate-config-object/
|
|
||||||
struct Config {
|
|
||||||
char hostname[64];
|
|
||||||
int port;
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *filename = "/config.txt"; // <- SD library uses 8.3 filenames
|
|
||||||
Config config; // <- global configuration object
|
|
||||||
|
|
||||||
// Loads the configuration from a file
|
|
||||||
void loadConfiguration(const char *filename, Config &config) {
|
|
||||||
// Open file for reading
|
|
||||||
File file = SD.open(filename);
|
|
||||||
|
|
||||||
// Allocate a temporary JsonDocument
|
|
||||||
// Don't forget to change the capacity to match your requirements.
|
|
||||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
|
||||||
StaticJsonDocument<512> doc;
|
|
||||||
|
|
||||||
// Deserialize the JSON document
|
|
||||||
DeserializationError error = deserializeJson(doc, file);
|
|
||||||
if (error)
|
|
||||||
Serial.println(F("Failed to read file, using default configuration"));
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// Close the file (Curiously, File's destructor doesn't close the file)
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Saves the configuration to a file
|
|
||||||
void saveConfiguration(const char *filename, const Config &config) {
|
|
||||||
// Delete existing file, otherwise the configuration is appended to the file
|
|
||||||
SD.remove(filename);
|
|
||||||
|
|
||||||
// Open file for writing
|
|
||||||
File file = SD.open(filename, FILE_WRITE);
|
|
||||||
if (!file) {
|
|
||||||
Serial.println(F("Failed to create file"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// 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.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints the content of a file to the Serial
|
|
||||||
void printFile(const char *filename) {
|
|
||||||
// Open file for reading
|
|
||||||
File file = SD.open(filename);
|
|
||||||
if (!file) {
|
|
||||||
Serial.println(F("Failed to read file"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract each characters by one by one
|
|
||||||
while (file.available()) {
|
|
||||||
Serial.print((char)file.read());
|
|
||||||
}
|
|
||||||
Serial.println();
|
|
||||||
|
|
||||||
// Close the file
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// Initialize serial port
|
|
||||||
Serial.begin(9600);
|
|
||||||
while (!Serial) continue;
|
|
||||||
|
|
||||||
// Initialize SD library
|
|
||||||
const int chipSelect = 4;
|
|
||||||
while (!SD.begin(chipSelect)) {
|
|
||||||
Serial.println(F("Failed to initialize SD library"));
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should load default config if run for the first time
|
|
||||||
Serial.println(F("Loading configuration..."));
|
|
||||||
loadConfiguration(filename, config);
|
|
||||||
|
|
||||||
// Create configuration file
|
|
||||||
Serial.println(F("Saving configuration..."));
|
|
||||||
saveConfiguration(filename, config);
|
|
||||||
|
|
||||||
// Dump config file
|
|
||||||
Serial.println(F("Print config file..."));
|
|
||||||
printFile(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// not used in this example
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also
|
|
||||||
// --------
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/ contains the documentation for all the functions
|
|
||||||
// used above. It also includes an FAQ that will help you solve any
|
|
||||||
// serialization or deserialization problem.
|
|
||||||
//
|
|
||||||
// The book "Mastering ArduinoJson" contains a case study of a project that has
|
|
||||||
// a complex configuration with nested members.
|
|
||||||
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
|
|
||||||
// Learn more at https://arduinojson.org/book/
|
|
||||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// This example shows how to use DeserializationOpion::Filter
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/filter/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// Initialize serial port
|
|
||||||
Serial.begin(9600);
|
|
||||||
while (!Serial) continue;
|
|
||||||
|
|
||||||
// The huge input: an extract from OpenWeatherMap response
|
|
||||||
const __FlashStringHelper* input_json = F(
|
|
||||||
"{\"cod\":\"200\",\"message\":0,\"list\":[{\"dt\":1581498000,\"main\":{"
|
|
||||||
"\"temp\":3.23,\"feels_like\":-3.63,\"temp_min\":3.23,\"temp_max\":4.62,"
|
|
||||||
"\"pressure\":1014,\"sea_level\":1014,\"grnd_level\":1010,\"humidity\":"
|
|
||||||
"58,\"temp_kf\":-1.39},\"weather\":[{\"id\":800,\"main\":\"Clear\","
|
|
||||||
"\"description\":\"clear "
|
|
||||||
"sky\",\"icon\":\"01d\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":6."
|
|
||||||
"19,\"deg\":266},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2020-02-12 "
|
|
||||||
"09:00:00\"},{\"dt\":1581508800,\"main\":{\"temp\":6.09,\"feels_like\":-"
|
|
||||||
"1.07,\"temp_min\":6.09,\"temp_max\":7.13,\"pressure\":1015,\"sea_"
|
|
||||||
"level\":1015,\"grnd_level\":1011,\"humidity\":48,\"temp_kf\":-1.04},"
|
|
||||||
"\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear "
|
|
||||||
"sky\",\"icon\":\"01d\"}],\"clouds\":{\"all\":9},\"wind\":{\"speed\":6."
|
|
||||||
"64,\"deg\":268},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2020-02-12 "
|
|
||||||
"12:00:00\"}],\"city\":{\"id\":2643743,\"name\":\"London\",\"coord\":{"
|
|
||||||
"\"lat\":51.5085,\"lon\":-0.1257},\"country\":\"GB\",\"population\":"
|
|
||||||
"1000000,\"timezone\":0,\"sunrise\":1581492085,\"sunset\":1581527294}}");
|
|
||||||
|
|
||||||
// The filter: it contains "true" for each value we want to keep
|
|
||||||
StaticJsonDocument<200> filter;
|
|
||||||
filter["list"][0]["dt"] = true;
|
|
||||||
filter["list"][0]["main"]["temp"] = true;
|
|
||||||
|
|
||||||
// Deserialize the document
|
|
||||||
StaticJsonDocument<400> doc;
|
|
||||||
deserializeJson(doc, input_json, DeserializationOption::Filter(filter));
|
|
||||||
|
|
||||||
// Print the result
|
|
||||||
serializeJsonPretty(doc, Serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// not used in this example
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also
|
|
||||||
// --------
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/ contains the documentation for all the functions
|
|
||||||
// used above. It also includes an FAQ that will help you solve any
|
|
||||||
// deserialization problem.
|
|
||||||
//
|
|
||||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
|
|
||||||
// It begins with a simple example, like the one above, and then adds more
|
|
||||||
// features like deserializing directly from a file or an HTTP request.
|
|
||||||
// Learn more at https://arduinojson.org/book/
|
|
||||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// This example shows how to generate a JSON document with ArduinoJson.
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/generator/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// Initialize Serial port
|
|
||||||
Serial.begin(9600);
|
|
||||||
while (!Serial) continue;
|
|
||||||
|
|
||||||
// Allocate the JSON document
|
|
||||||
//
|
|
||||||
// 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/v6/assistant to compute the capacity.
|
|
||||||
StaticJsonDocument<200> doc;
|
|
||||||
|
|
||||||
// StaticJsonObject allocates memory on the stack, it can be
|
|
||||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
|
||||||
//
|
|
||||||
// DynamicJsonDocument doc(200);
|
|
||||||
|
|
||||||
// Add values in the document
|
|
||||||
//
|
|
||||||
doc["sensor"] = "gps";
|
|
||||||
doc["time"] = 1351824120;
|
|
||||||
|
|
||||||
// Add an array.
|
|
||||||
//
|
|
||||||
JsonArray data = doc.createNestedArray("data");
|
|
||||||
data.add(48.756080);
|
|
||||||
data.add(2.302038);
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
// Generate the prettified JSON and send it to the Serial port.
|
|
||||||
//
|
|
||||||
serializeJsonPretty(doc, Serial);
|
|
||||||
// The above line prints:
|
|
||||||
// {
|
|
||||||
// "sensor": "gps",
|
|
||||||
// "time": 1351824120,
|
|
||||||
// "data": [
|
|
||||||
// 48.756080,
|
|
||||||
// 2.302038
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// not used in this example
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also
|
|
||||||
// --------
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/ contains the documentation for all the functions
|
|
||||||
// used above. It also includes an FAQ that will help you solve any
|
|
||||||
// serialization problem.
|
|
||||||
//
|
|
||||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
|
||||||
// It begins with a simple example, like the one above, and then adds more
|
|
||||||
// features like serializing directly to a file or an HTTP request.
|
|
||||||
// Learn more at https://arduinojson.org/book/
|
|
||||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// This example shows how to parse a JSON document in an HTTP response.
|
|
||||||
// It uses the Ethernet library, but can be easily adapted for Wifi.
|
|
||||||
//
|
|
||||||
// It performs a GET resquest on arduinojson.org/example.json
|
|
||||||
// Here is the expected response:
|
|
||||||
// {
|
|
||||||
// "sensor": "gps",
|
|
||||||
// "time": 1351824120,
|
|
||||||
// "data": [
|
|
||||||
// 48.756080,
|
|
||||||
// 2.302038
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/http-client/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <Ethernet.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// Initialize Serial port
|
|
||||||
Serial.begin(9600);
|
|
||||||
while (!Serial) continue;
|
|
||||||
|
|
||||||
// Initialize Ethernet library
|
|
||||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
|
||||||
if (!Ethernet.begin(mac)) {
|
|
||||||
Serial.println(F("Failed to configure Ethernet"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
Serial.println(F("Connecting..."));
|
|
||||||
|
|
||||||
// Connect to HTTP server
|
|
||||||
EthernetClient client;
|
|
||||||
client.setTimeout(10000);
|
|
||||||
if (!client.connect("arduinojson.org", 80)) {
|
|
||||||
Serial.println(F("Connection failed"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial.println(F("Connected!"));
|
|
||||||
|
|
||||||
// Send HTTP request
|
|
||||||
client.println(F("GET /example.json HTTP/1.0"));
|
|
||||||
client.println(F("Host: arduinojson.org"));
|
|
||||||
client.println(F("Connection: close"));
|
|
||||||
if (client.println() == 0) {
|
|
||||||
Serial.println(F("Failed to send request"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check HTTP status
|
|
||||||
char status[32] = {0};
|
|
||||||
client.readBytesUntil('\r', status, sizeof(status));
|
|
||||||
// It should be "HTTP/1.0 200 OK" or "HTTP/1.1 200 OK"
|
|
||||||
if (strcmp(status + 9, "200 OK") != 0) {
|
|
||||||
Serial.print(F("Unexpected response: "));
|
|
||||||
Serial.println(status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip HTTP headers
|
|
||||||
char endOfHeaders[] = "\r\n\r\n";
|
|
||||||
if (!client.find(endOfHeaders)) {
|
|
||||||
Serial.println(F("Invalid response"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate the JSON document
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Parse JSON object
|
|
||||||
DeserializationError error = deserializeJson(doc, client);
|
|
||||||
if (error) {
|
|
||||||
Serial.print(F("deserializeJson() failed: "));
|
|
||||||
Serial.println(error.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract values
|
|
||||||
Serial.println(F("Response:"));
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// not used in this example
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also
|
|
||||||
// --------
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/ contains the documentation for all the functions
|
|
||||||
// used above. It also includes an FAQ that will help you solve any
|
|
||||||
// serialization problem.
|
|
||||||
//
|
|
||||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization
|
|
||||||
// showing how to parse the response from GitHub's API. In the last chapter,
|
|
||||||
// it shows how to parse the huge documents from OpenWeatherMap
|
|
||||||
// and Reddit.
|
|
||||||
// Learn more at https://arduinojson.org/book/
|
|
||||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/parser/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// Initialize serial port
|
|
||||||
Serial.begin(9600);
|
|
||||||
while (!Serial) continue;
|
|
||||||
|
|
||||||
// Allocate the JSON document
|
|
||||||
//
|
|
||||||
// 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/v6/assistant to compute the capacity.
|
|
||||||
StaticJsonDocument<200> doc;
|
|
||||||
|
|
||||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
|
||||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
|
||||||
//
|
|
||||||
// DynamicJsonDocument doc(200);
|
|
||||||
|
|
||||||
// JSON input string.
|
|
||||||
//
|
|
||||||
// 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]}";
|
|
||||||
|
|
||||||
// Deserialize the JSON document
|
|
||||||
DeserializationError error = deserializeJson(doc, json);
|
|
||||||
|
|
||||||
// Test if parsing succeeds.
|
|
||||||
if (error) {
|
|
||||||
Serial.print(F("deserializeJson() failed: "));
|
|
||||||
Serial.println(error.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch values.
|
|
||||||
//
|
|
||||||
// Most of the time, you can rely on the implicit casts.
|
|
||||||
// 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);
|
|
||||||
Serial.println(time);
|
|
||||||
Serial.println(latitude, 6);
|
|
||||||
Serial.println(longitude, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// not used in this example
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also
|
|
||||||
// --------
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/ contains the documentation for all the functions
|
|
||||||
// used above. It also includes an FAQ that will help you solve any
|
|
||||||
// deserialization problem.
|
|
||||||
//
|
|
||||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
|
|
||||||
// It begins with a simple example, like the one above, and then adds more
|
|
||||||
// features like deserializing directly from a file or an HTTP request.
|
|
||||||
// Learn more at https://arduinojson.org/book/
|
|
||||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// The JSON document contains the values of the analog and digital pins.
|
|
||||||
// It looks like that:
|
|
||||||
// {
|
|
||||||
// "analog": [0, 76, 123, 158, 192, 205],
|
|
||||||
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/http-server/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <Ethernet.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
|
|
||||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
|
||||||
EthernetServer server(80);
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// Initialize serial port
|
|
||||||
Serial.begin(9600);
|
|
||||||
while (!Serial) continue;
|
|
||||||
|
|
||||||
// Initialize Ethernet libary
|
|
||||||
if (!Ethernet.begin(mac)) {
|
|
||||||
Serial.println(F("Failed to initialize Ethernet library"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start to listen
|
|
||||||
server.begin();
|
|
||||||
|
|
||||||
Serial.println(F("Server is ready."));
|
|
||||||
Serial.print(F("Please connect to http://"));
|
|
||||||
Serial.println(Ethernet.localIP());
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// Wait for an incomming connection
|
|
||||||
EthernetClient client = server.available();
|
|
||||||
|
|
||||||
// Do we have a client?
|
|
||||||
if (!client) return;
|
|
||||||
|
|
||||||
Serial.println(F("New client"));
|
|
||||||
|
|
||||||
// Read the request (we ignore the content in this example)
|
|
||||||
while (client.available()) client.read();
|
|
||||||
|
|
||||||
// Allocate a temporary JsonDocument
|
|
||||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
|
||||||
StaticJsonDocument<500> doc;
|
|
||||||
|
|
||||||
// Create the "analog" array
|
|
||||||
JsonArray analogValues = doc.createNestedArray("analog");
|
|
||||||
for (int pin = 0; pin < 6; pin++) {
|
|
||||||
// Read the analog input
|
|
||||||
int value = analogRead(pin);
|
|
||||||
|
|
||||||
// Add the value at the end of the array
|
|
||||||
analogValues.add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the "digital" array
|
|
||||||
JsonArray digitalValues = doc.createNestedArray("digital");
|
|
||||||
for (int pin = 0; pin < 14; pin++) {
|
|
||||||
// Read the digital input
|
|
||||||
int value = digitalRead(pin);
|
|
||||||
|
|
||||||
// Add the value at the end of the array
|
|
||||||
digitalValues.add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial.print(F("Sending: "));
|
|
||||||
serializeJson(doc, Serial);
|
|
||||||
Serial.println();
|
|
||||||
|
|
||||||
// Write response headers
|
|
||||||
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(doc, client);
|
|
||||||
|
|
||||||
// Disconnect
|
|
||||||
client.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also
|
|
||||||
// --------
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/ contains the documentation for all the functions
|
|
||||||
// used above. It also includes an FAQ that will help you solve any
|
|
||||||
// serialization problem.
|
|
||||||
//
|
|
||||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
|
||||||
// It begins with a simple example, then adds more features like serializing
|
|
||||||
// directly to a file or an HTTP client.
|
|
||||||
// Learn more at https://arduinojson.org/book/
|
|
||||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
// It looks like that:
|
|
||||||
// {
|
|
||||||
// "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
|
|
||||||
// packets.
|
|
||||||
// For example, you can run netcat on your computer
|
|
||||||
// $ ncat -ulp 8888
|
|
||||||
// See https://nmap.org/ncat/
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/udp-beacon/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <Ethernet.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
|
|
||||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
|
||||||
IPAddress remoteIp(192, 168, 0, 108); // <- EDIT!!!!
|
|
||||||
unsigned short remotePort = 8888;
|
|
||||||
unsigned short localPort = 8888;
|
|
||||||
EthernetUDP udp;
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// Initialize serial port
|
|
||||||
Serial.begin(9600);
|
|
||||||
while (!Serial) continue;
|
|
||||||
|
|
||||||
// Initialize Ethernet libary
|
|
||||||
if (!Ethernet.begin(mac)) {
|
|
||||||
Serial.println(F("Failed to initialize Ethernet library"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable UDP
|
|
||||||
udp.begin(localPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// Allocate a temporary JsonDocument
|
|
||||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
|
||||||
StaticJsonDocument<500> doc;
|
|
||||||
|
|
||||||
// Create the "analog" array
|
|
||||||
JsonArray analogValues = doc.createNestedArray("analog");
|
|
||||||
for (int pin = 0; pin < 6; pin++) {
|
|
||||||
// Read the analog input
|
|
||||||
int value = analogRead(pin);
|
|
||||||
|
|
||||||
// Add the value at the end of the array
|
|
||||||
analogValues.add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the "digital" array
|
|
||||||
JsonArray digitalValues = doc.createNestedArray("digital");
|
|
||||||
for (int pin = 0; pin < 14; pin++) {
|
|
||||||
// Read the digital input
|
|
||||||
int value = digitalRead(pin);
|
|
||||||
|
|
||||||
// Add the value at the end of the array
|
|
||||||
digitalValues.add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log
|
|
||||||
Serial.print(F("Sending to "));
|
|
||||||
Serial.print(remoteIp);
|
|
||||||
Serial.print(F(" on port "));
|
|
||||||
Serial.println(remotePort);
|
|
||||||
serializeJson(doc, Serial);
|
|
||||||
|
|
||||||
// Send UDP packet
|
|
||||||
udp.beginPacket(remoteIp, remotePort);
|
|
||||||
serializeJson(doc, udp);
|
|
||||||
udp.println();
|
|
||||||
udp.endPacket();
|
|
||||||
|
|
||||||
// Wait
|
|
||||||
delay(10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also
|
|
||||||
// --------
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/ contains the documentation for all the functions
|
|
||||||
// used above. It also includes an FAQ that will help you solve any
|
|
||||||
// serialization problem.
|
|
||||||
//
|
|
||||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
|
||||||
// It begins with a simple example, then adds more features like serializing
|
|
||||||
// directly to a file or any stream.
|
|
||||||
// Learn more at https://arduinojson.org/book/
|
|
||||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// This example shows how to deserialize a MessagePack document with
|
|
||||||
// ArduinoJson.
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/msgpack-parser/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// Initialize serial port
|
|
||||||
Serial.begin(9600);
|
|
||||||
while (!Serial) continue;
|
|
||||||
|
|
||||||
// Allocate the JSON document
|
|
||||||
//
|
|
||||||
// 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/v6/assistant to compute the capacity.
|
|
||||||
StaticJsonDocument<200> doc;
|
|
||||||
|
|
||||||
// StaticJsonObject allocates memory on the stack, it can be
|
|
||||||
// replaced by DynamicJsonObject which allocates in the heap.
|
|
||||||
//
|
|
||||||
// DynamicJsonObject doc(200);
|
|
||||||
|
|
||||||
// MessagePack input string.
|
|
||||||
//
|
|
||||||
// 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,
|
|
||||||
112, 203, 64, 2, 106, 146, 230, 33, 49, 169};
|
|
||||||
// This MessagePack document contains:
|
|
||||||
// {
|
|
||||||
// "sensor": "gps",
|
|
||||||
// "time": 1351824120,
|
|
||||||
// "data": [48.75608, 2.302038]
|
|
||||||
// }
|
|
||||||
|
|
||||||
DeserializationError error = deserializeMsgPack(doc, input);
|
|
||||||
|
|
||||||
// Test if parsing succeeded.
|
|
||||||
if (error) {
|
|
||||||
Serial.print("deserializeMsgPack() failed: ");
|
|
||||||
Serial.println(error.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch values.
|
|
||||||
//
|
|
||||||
// Most of the time, you can rely on the implicit casts.
|
|
||||||
// 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);
|
|
||||||
Serial.println(time);
|
|
||||||
Serial.println(latitude, 6);
|
|
||||||
Serial.println(longitude, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// not used in this example
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// This example shows the different ways you can use Flash strings with
|
|
||||||
// ArduinoJson.
|
|
||||||
//
|
|
||||||
// Use Flash strings sparingly, because ArduinoJson duplicates them in the
|
|
||||||
// JsonDocument. Prefer plain old char*, as they are more efficient in term of
|
|
||||||
// code size, speed, and memory usage.
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/progmem/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
#ifdef PROGMEM // <- check that Flash strings are supported
|
|
||||||
|
|
||||||
DynamicJsonDocument doc(1024);
|
|
||||||
|
|
||||||
// You can use a Flash String as your JSON input.
|
|
||||||
// WARNING: the strings 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>();
|
|
||||||
|
|
||||||
// You can use a Flash String to get an element of a JsonObject
|
|
||||||
// No duplication is done.
|
|
||||||
long time = obj[F("time")];
|
|
||||||
|
|
||||||
// You can use a Flash String to set an element of a JsonObject
|
|
||||||
// WARNING: the content of the Flash String will be duplicated in the
|
|
||||||
// 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
|
|
||||||
// JsonDocument.
|
|
||||||
obj["sensor"] = F("gps");
|
|
||||||
|
|
||||||
// It works with serialized() too:
|
|
||||||
obj["sensor"] = serialized(F("\"gps\""));
|
|
||||||
obj["sensor"] = serialized(F("\xA3gps"), 3);
|
|
||||||
|
|
||||||
// You can compare the content of a JsonVariant to a Flash String
|
|
||||||
if (obj["sensor"] == F("gps")) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#warning PROGMEM is not supported on this platform
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// not used in this example
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also
|
|
||||||
// --------
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/ contains the documentation for all the functions
|
|
||||||
// used above. It also includes an FAQ that will help you solve any memory
|
|
||||||
// problem.
|
|
||||||
//
|
|
||||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
|
||||||
// how your microcontroller stores strings in memory. It also tells why you
|
|
||||||
// should not abuse Flash strings with ArduinoJson.
|
|
||||||
// Learn more at https://arduinojson.org/book/
|
|
||||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// This example shows the different ways you can use String with ArduinoJson.
|
|
||||||
//
|
|
||||||
// Use String objects sparingly, because ArduinoJson duplicates them in the
|
|
||||||
// JsonDocument. Prefer plain old char[], as they are more efficient in term of
|
|
||||||
// code size, speed, and memory usage.
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/v6/example/string/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
DynamicJsonDocument doc(1024);
|
|
||||||
|
|
||||||
// You can use a String as your JSON input.
|
|
||||||
// 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);
|
|
||||||
JsonObject obj = doc.as<JsonObject>();
|
|
||||||
|
|
||||||
// You can use a String to get an element of a JsonObject
|
|
||||||
// No duplication is done.
|
|
||||||
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 JsonDocument.
|
|
||||||
obj[String("time")] = time;
|
|
||||||
|
|
||||||
// You can get a String from a JsonObject or JsonArray:
|
|
||||||
// No duplication is done, at least not in the JsonDocument.
|
|
||||||
String sensor = obj["sensor"];
|
|
||||||
|
|
||||||
// Unfortunately, the following doesn't work (issue #118):
|
|
||||||
// sensor = obj["sensor"]; // <- error "ambiguous overload for 'operator='"
|
|
||||||
// As a workaround, you need to replace by:
|
|
||||||
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 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 JsonDocument.
|
|
||||||
obj[String("sen") + "sor"] = String("gp") + "s";
|
|
||||||
|
|
||||||
// You can compare the content of a JsonObject with a String
|
|
||||||
if (obj["sensor"] == sensor) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lastly, you can print the resulting JSON to a String
|
|
||||||
String output;
|
|
||||||
serializeJson(doc, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// not used in this example
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also
|
|
||||||
// --------
|
|
||||||
//
|
|
||||||
// https://arduinojson.org/ contains the documentation for all the functions
|
|
||||||
// used above. It also includes an FAQ that will help you solve any problem.
|
|
||||||
//
|
|
||||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
|
||||||
// how your microcontroller stores strings in memory. On several occasions, it
|
|
||||||
// shows how you can avoid String in your program.
|
|
||||||
// Learn more at https://arduinojson.org/book/
|
|
||||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# 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
|
|
||||||
measureJson KEYWORD2
|
|
||||||
measureJsonPretty KEYWORD2
|
|
||||||
measureMsgPack KEYWORD2
|
|
||||||
|
|
||||||
# Methods
|
|
||||||
add KEYWORD2
|
|
||||||
as KEYWORD2
|
|
||||||
createNestedArray KEYWORD2
|
|
||||||
createNestedObject KEYWORD2
|
|
||||||
get KEYWORD2
|
|
||||||
set KEYWORD2
|
|
||||||
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
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
name=ArduinoJson
|
|
||||||
version=6.16.1
|
|
||||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
|
||||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
|
||||||
sentence=A simple and efficient JSON library for embedded C++.
|
|
||||||
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ MessagePack, ✔ fixed allocation, ✔ zero-copy, ✔ streams, ✔ filtering, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
|
||||||
category=Data Processing
|
|
||||||
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
|
|
||||||
architectures=*
|
|
||||||
repository=https://github.com/bblanchon/ArduinoJson.git
|
|
||||||
license=MIT
|
|
||||||
@@ -12,12 +12,13 @@ inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) {
|
|||||||
return arr ? arr->addElement(pool) : 0;
|
return arr ? arr->addElement(pool) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
inline void arrayAccept(const CollectionData *arr, Visitor &visitor) {
|
inline typename TVisitor::result_type arrayAccept(const CollectionData *arr,
|
||||||
|
TVisitor &visitor) {
|
||||||
if (arr)
|
if (arr)
|
||||||
visitor.visitArray(*arr);
|
return visitor.visitArray(*arr);
|
||||||
else
|
else
|
||||||
visitor.visitNull();
|
return visitor.visitNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
|
inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ class ArrayRefBase {
|
|||||||
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
|
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||||
arrayAccept(_data, visitor);
|
return arrayAccept(_data, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
|||||||
return getOrAddUpstreamElement().set(value);
|
return getOrAddUpstreamElement().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
void accept(Visitor& visitor) const {
|
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||||
return getUpstreamElement().accept(visitor);
|
return getUpstreamElement().accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,40 +65,61 @@ inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ArrayCopier1D {
|
class ArrayCopier1D : public Visitor<size_t> {
|
||||||
public:
|
public:
|
||||||
ArrayCopier1D(T* destination, size_t capacity)
|
ArrayCopier1D(T* destination, size_t capacity)
|
||||||
: _destination(destination), _capacity(capacity), _size(0) {}
|
: _destination(destination), _capacity(capacity) {}
|
||||||
|
|
||||||
void visitArray(const CollectionData& array) {
|
size_t visitArray(const CollectionData& array) {
|
||||||
|
size_t size = 0;
|
||||||
VariantSlot* slot = array.head();
|
VariantSlot* slot = array.head();
|
||||||
|
|
||||||
while (slot != 0 && _size < _capacity) {
|
while (slot != 0 && size < _capacity) {
|
||||||
_destination[_size++] = variantAs<T>(slot->data());
|
_destination[size++] = variantAs<T>(slot->data());
|
||||||
slot = slot->next();
|
slot = slot->next();
|
||||||
}
|
}
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
void visitObject(const CollectionData&) {}
|
|
||||||
void visitFloat(Float) {}
|
|
||||||
void visitString(const char*) {}
|
|
||||||
void visitRawJson(const char*, size_t) {}
|
|
||||||
void visitNegativeInteger(UInt) {}
|
|
||||||
void visitPositiveInteger(UInt) {}
|
|
||||||
void visitBoolean(bool) {}
|
|
||||||
void visitNull() {}
|
|
||||||
|
|
||||||
size_t result() const {
|
size_t visitObject(const CollectionData&) {
|
||||||
return _size;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t visitFloat(Float) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t visitString(const char*) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t visitRawJson(const char*, size_t) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t visitNegativeInteger(UInt) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t visitPositiveInteger(UInt) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t visitBoolean(bool) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t visitNull() {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* _destination;
|
T* _destination;
|
||||||
size_t _capacity;
|
size_t _capacity;
|
||||||
size_t _size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, size_t N1, size_t N2>
|
template <typename T, size_t N1, size_t N2>
|
||||||
class ArrayCopier2D {
|
class ArrayCopier2D : public Visitor<void> {
|
||||||
public:
|
public:
|
||||||
ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {}
|
ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {}
|
||||||
|
|
||||||
@@ -136,8 +157,8 @@ inline typename enable_if<!is_array<T>::value, size_t>::type copyArray(
|
|||||||
template <typename TSource, typename T>
|
template <typename TSource, typename T>
|
||||||
inline size_t copyArray(const TSource& src, T* dst, size_t len) {
|
inline size_t copyArray(const TSource& src, T* dst, size_t len) {
|
||||||
ArrayCopier1D<T> copier(dst, len);
|
ArrayCopier1D<T> copier(dst, len);
|
||||||
src.accept(copier);
|
|
||||||
return copier.result();
|
return src.accept(copier);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy a JsonArray to a 2D array
|
// Copy a JsonArray to a 2D array
|
||||||
|
|||||||
@@ -230,3 +230,8 @@
|
|||||||
#define ARDUINOJSON_DEBUG 0
|
#define ARDUINOJSON_DEBUG 0
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_HAS_NULLPTR && defined(nullptr)
|
||||||
|
#error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
|
||||||
|
// See https://github.com/bblanchon/ArduinoJson/issues/1355
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
|
#include <ArduinoJson/Polyfills/preprocessor.hpp>
|
||||||
|
#include <ArduinoJson/Polyfills/static_array.hpp>
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
@@ -20,6 +22,7 @@ class DeserializationError {
|
|||||||
public:
|
public:
|
||||||
enum Code {
|
enum Code {
|
||||||
Ok,
|
Ok,
|
||||||
|
EmptyInput,
|
||||||
IncompleteInput,
|
IncompleteInput,
|
||||||
InvalidInput,
|
InvalidInput,
|
||||||
NoMemory,
|
NoMemory,
|
||||||
@@ -77,24 +80,31 @@ class DeserializationError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char* c_str() const {
|
const char* c_str() const {
|
||||||
switch (_code) {
|
static const char* messages[] = {
|
||||||
case Ok:
|
"Ok", "EmptyInput", "IncompleteInput", "InvalidInput",
|
||||||
return "Ok";
|
"NoMemory", "NotSupported", "TooDeep"};
|
||||||
case TooDeep:
|
ARDUINOJSON_ASSERT(static_cast<size_t>(_code) <
|
||||||
return "TooDeep";
|
sizeof(messages) / sizeof(messages[0]));
|
||||||
case NoMemory:
|
return messages[_code];
|
||||||
return "NoMemory";
|
|
||||||
case InvalidInput:
|
|
||||||
return "InvalidInput";
|
|
||||||
case IncompleteInput:
|
|
||||||
return "IncompleteInput";
|
|
||||||
case NotSupported:
|
|
||||||
return "NotSupported";
|
|
||||||
default:
|
|
||||||
return "???";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||||
|
const __FlashStringHelper* f_str() const {
|
||||||
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s0, "Ok");
|
||||||
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s1, "EmptyInput");
|
||||||
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s2, "IncompleteInput");
|
||||||
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s3, "InvalidInput");
|
||||||
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s4, "NoMemory");
|
||||||
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s5, "NotSupported");
|
||||||
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s6, "TooDeep");
|
||||||
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(
|
||||||
|
const char*, messages,
|
||||||
|
ARDUINOJSON_EXPAND7({s0, s1, s2, s3, s4, s5, s6}));
|
||||||
|
return ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages,
|
||||||
|
_code);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Code _code;
|
Code _code;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class Filter {
|
|||||||
if (_variant == true) // "true" means "allow recursively"
|
if (_variant == true) // "true" means "allow recursively"
|
||||||
return *this;
|
return *this;
|
||||||
else
|
else
|
||||||
return Filter(_variant[key]);
|
return Filter(_variant[key] | _variant["*"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Stream.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,9 @@ deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit,
|
|||||||
TFilter filter) {
|
TFilter filter) {
|
||||||
Reader<TString> reader(input);
|
Reader<TString> reader(input);
|
||||||
doc.clear();
|
doc.clear();
|
||||||
return makeDeserializer<TDeserializer>(doc.memoryPool(), reader,
|
return makeDeserializer<TDeserializer>(
|
||||||
makeStringStorage(input))
|
doc.memoryPool(), reader,
|
||||||
|
makeStringStorage(input, doc.memoryPool()))
|
||||||
.parse(doc.data(), filter, nestingLimit);
|
.parse(doc.data(), filter, nestingLimit);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@@ -47,8 +48,9 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
|||||||
TFilter filter) {
|
TFilter filter) {
|
||||||
BoundedReader<TChar *> reader(input, inputSize);
|
BoundedReader<TChar *> reader(input, inputSize);
|
||||||
doc.clear();
|
doc.clear();
|
||||||
return makeDeserializer<TDeserializer>(doc.memoryPool(), reader,
|
return makeDeserializer<TDeserializer>(
|
||||||
makeStringStorage(input))
|
doc.memoryPool(), reader,
|
||||||
|
makeStringStorage(input, doc.memoryPool()))
|
||||||
.parse(doc.data(), filter, nestingLimit);
|
.parse(doc.data(), filter, nestingLimit);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@@ -60,8 +62,9 @@ DeserializationError deserialize(JsonDocument &doc, TStream &input,
|
|||||||
NestingLimit nestingLimit, TFilter filter) {
|
NestingLimit nestingLimit, TFilter filter) {
|
||||||
Reader<TStream> reader(input);
|
Reader<TStream> reader(input);
|
||||||
doc.clear();
|
doc.clear();
|
||||||
return makeDeserializer<TDeserializer>(doc.memoryPool(), reader,
|
return makeDeserializer<TDeserializer>(
|
||||||
makeStringStorage(input))
|
doc.memoryPool(), reader,
|
||||||
|
makeStringStorage(input, doc.memoryPool()))
|
||||||
.parse(doc.data(), filter, nestingLimit);
|
.parse(doc.data(), filter, nestingLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ namespace ARDUINOJSON_NAMESPACE {
|
|||||||
|
|
||||||
class JsonDocument : public Visitable {
|
class JsonDocument : public Visitable {
|
||||||
public:
|
public:
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
void accept(Visitor& visitor) const {
|
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||||
return getVariant().accept(visitor);
|
return getVariant().accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +48,10 @@ class JsonDocument : public Visitable {
|
|||||||
return _pool.size();
|
return _pool.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool overflowed() const {
|
||||||
|
return _pool.overflowed();
|
||||||
|
}
|
||||||
|
|
||||||
size_t nesting() const {
|
size_t nesting() const {
|
||||||
return _data.nesting();
|
return _data.nesting();
|
||||||
}
|
}
|
||||||
@@ -81,6 +85,7 @@ class JsonDocument : public Visitable {
|
|||||||
return _pool;
|
return _pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for internal use only
|
||||||
VariantData& data() {
|
VariantData& data() {
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class JsonDeserializer {
|
|||||||
JsonDeserializer(MemoryPool &pool, TReader reader,
|
JsonDeserializer(MemoryPool &pool, TReader reader,
|
||||||
TStringStorage stringStorage)
|
TStringStorage stringStorage)
|
||||||
: _stringStorage(stringStorage),
|
: _stringStorage(stringStorage),
|
||||||
|
_foundSomething(false),
|
||||||
_latch(reader),
|
_latch(reader),
|
||||||
_pool(&pool),
|
_pool(&pool),
|
||||||
_error(DeserializationError::Ok) {}
|
_error(DeserializationError::Ok) {}
|
||||||
@@ -34,7 +35,7 @@ class JsonDeserializer {
|
|||||||
|
|
||||||
if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
|
if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
|
||||||
// We don't detect trailing characters earlier, so we need to check now
|
// We don't detect trailing characters earlier, so we need to check now
|
||||||
_error = DeserializationError::InvalidInput;
|
return DeserializationError::InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _error;
|
return _error;
|
||||||
@@ -241,7 +242,7 @@ class JsonDeserializer {
|
|||||||
if (!variant) {
|
if (!variant) {
|
||||||
// Save key in memory pool.
|
// Save key in memory pool.
|
||||||
// This MUST be done before adding the slot.
|
// This MUST be done before adding the slot.
|
||||||
key = _stringStorage.save(_pool);
|
key = _stringStorage.save();
|
||||||
|
|
||||||
// Allocate slot in object
|
// Allocate slot in object
|
||||||
VariantSlot *slot = object.addSlot(_pool);
|
VariantSlot *slot = object.addSlot(_pool);
|
||||||
@@ -334,7 +335,7 @@ class JsonDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool parseKey() {
|
bool parseKey() {
|
||||||
_stringStorage.startString(_pool);
|
_stringStorage.startString();
|
||||||
if (isQuote(current())) {
|
if (isQuote(current())) {
|
||||||
return parseQuotedString();
|
return parseQuotedString();
|
||||||
} else {
|
} else {
|
||||||
@@ -343,12 +344,11 @@ class JsonDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool parseStringValue(VariantData &variant) {
|
bool parseStringValue(VariantData &variant) {
|
||||||
_stringStorage.startString(_pool);
|
_stringStorage.startString();
|
||||||
if (!parseQuotedString())
|
if (!parseQuotedString())
|
||||||
return false;
|
return false;
|
||||||
const char *value = _stringStorage.save(_pool);
|
const char *value = _stringStorage.save();
|
||||||
variant.setString(make_not_null(value),
|
variant.setStringPointer(value, typename TStringStorage::storage_policy());
|
||||||
typename TStringStorage::storage_policy());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,26 +499,12 @@ class JsonDeserializer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParsedNumber<Float, UInt> num;
|
if (!parseNumber(_buffer, result)) {
|
||||||
parseNumber<Float, UInt>(_buffer, num);
|
_error = DeserializationError::InvalidInput;
|
||||||
|
return false;
|
||||||
switch (num.type()) {
|
|
||||||
case VALUE_IS_NEGATIVE_INTEGER:
|
|
||||||
result.setNegativeInteger(num.uintValue);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case VALUE_IS_POSITIVE_INTEGER:
|
|
||||||
result.setPositiveInteger(num.uintValue);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case VALUE_IS_FLOAT:
|
|
||||||
result.setFloat(num.floatValue);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
_error = DeserializationError::InvalidInput;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool skipNumericValue() {
|
bool skipNumericValue() {
|
||||||
@@ -574,7 +560,8 @@ class JsonDeserializer {
|
|||||||
switch (current()) {
|
switch (current()) {
|
||||||
// end of string
|
// end of string
|
||||||
case '\0':
|
case '\0':
|
||||||
_error = DeserializationError::IncompleteInput;
|
_error = _foundSomething ? DeserializationError::IncompleteInput
|
||||||
|
: DeserializationError::EmptyInput;
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// spaces
|
// spaces
|
||||||
@@ -634,12 +621,14 @@ class JsonDeserializer {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
_foundSomething = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TStringStorage _stringStorage;
|
TStringStorage _stringStorage;
|
||||||
|
bool _foundSomething;
|
||||||
Latch<TReader> _latch;
|
Latch<TReader> _latch;
|
||||||
MemoryPool *_pool;
|
MemoryPool *_pool;
|
||||||
char _buffer[64]; // using a member instead of a local variable because it
|
char _buffer[64]; // using a member instead of a local variable because it
|
||||||
@@ -648,47 +637,60 @@ class JsonDeserializer {
|
|||||||
DeserializationError _error;
|
DeserializationError _error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
// deserializeJson(JsonDocument&, const std::string&, ...)
|
// deserializeJson(JsonDocument&, const std::string&, ...)
|
||||||
template <typename TInput>
|
//
|
||||||
|
// ... = NestingLimit
|
||||||
|
template <typename TString>
|
||||||
DeserializationError deserializeJson(
|
DeserializationError deserializeJson(
|
||||||
JsonDocument &doc, const TInput &input,
|
JsonDocument &doc, const TString &input,
|
||||||
NestingLimit nestingLimit = NestingLimit()) {
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
||||||
AllowAllFilter());
|
AllowAllFilter());
|
||||||
}
|
}
|
||||||
template <typename TInput>
|
// ... = Filter, NestingLimit
|
||||||
|
template <typename TString>
|
||||||
DeserializationError deserializeJson(
|
DeserializationError deserializeJson(
|
||||||
JsonDocument &doc, const TInput &input, Filter filter,
|
JsonDocument &doc, const TString &input, Filter filter,
|
||||||
NestingLimit nestingLimit = NestingLimit()) {
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||||
}
|
}
|
||||||
template <typename TInput>
|
// ... = NestingLimit, Filter
|
||||||
DeserializationError deserializeJson(JsonDocument &doc, const TInput &input,
|
template <typename TString>
|
||||||
|
DeserializationError deserializeJson(JsonDocument &doc, const TString &input,
|
||||||
NestingLimit nestingLimit, Filter filter) {
|
NestingLimit nestingLimit, Filter filter) {
|
||||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deserializeJson(JsonDocument&, const std::istream&, ...)
|
//
|
||||||
template <typename TInput>
|
// deserializeJson(JsonDocument&, std::istream&, ...)
|
||||||
|
//
|
||||||
|
// ... = NestingLimit
|
||||||
|
template <typename TStream>
|
||||||
DeserializationError deserializeJson(
|
DeserializationError deserializeJson(
|
||||||
JsonDocument &doc, TInput &input,
|
JsonDocument &doc, TStream &input,
|
||||||
NestingLimit nestingLimit = NestingLimit()) {
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
||||||
AllowAllFilter());
|
AllowAllFilter());
|
||||||
}
|
}
|
||||||
template <typename TInput>
|
// ... = Filter, NestingLimit
|
||||||
|
template <typename TStream>
|
||||||
DeserializationError deserializeJson(
|
DeserializationError deserializeJson(
|
||||||
JsonDocument &doc, TInput &input, Filter filter,
|
JsonDocument &doc, TStream &input, Filter filter,
|
||||||
NestingLimit nestingLimit = NestingLimit()) {
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||||
}
|
}
|
||||||
template <typename TInput>
|
// ... = NestingLimit, Filter
|
||||||
DeserializationError deserializeJson(JsonDocument &doc, TInput &input,
|
template <typename TStream>
|
||||||
|
DeserializationError deserializeJson(JsonDocument &doc, TStream &input,
|
||||||
NestingLimit nestingLimit, Filter filter) {
|
NestingLimit nestingLimit, Filter filter) {
|
||||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// deserializeJson(JsonDocument&, char*, ...)
|
// deserializeJson(JsonDocument&, char*, ...)
|
||||||
|
//
|
||||||
|
// ... = NestingLimit
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
DeserializationError deserializeJson(
|
DeserializationError deserializeJson(
|
||||||
JsonDocument &doc, TChar *input,
|
JsonDocument &doc, TChar *input,
|
||||||
@@ -696,19 +698,24 @@ DeserializationError deserializeJson(
|
|||||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
||||||
AllowAllFilter());
|
AllowAllFilter());
|
||||||
}
|
}
|
||||||
|
// ... = Filter, NestingLimit
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
DeserializationError deserializeJson(
|
DeserializationError deserializeJson(
|
||||||
JsonDocument &doc, TChar *input, Filter filter,
|
JsonDocument &doc, TChar *input, Filter filter,
|
||||||
NestingLimit nestingLimit = NestingLimit()) {
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||||
}
|
}
|
||||||
|
// ... = NestingLimit, Filter
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
|
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
|
||||||
NestingLimit nestingLimit, Filter filter) {
|
NestingLimit nestingLimit, Filter filter) {
|
||||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// deserializeJson(JsonDocument&, char*, size_t, ...)
|
// deserializeJson(JsonDocument&, char*, size_t, ...)
|
||||||
|
//
|
||||||
|
// ... = NestingLimit
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
DeserializationError deserializeJson(
|
DeserializationError deserializeJson(
|
||||||
JsonDocument &doc, TChar *input, size_t inputSize,
|
JsonDocument &doc, TChar *input, size_t inputSize,
|
||||||
@@ -716,6 +723,7 @@ DeserializationError deserializeJson(
|
|||||||
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
|
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
|
||||||
AllowAllFilter());
|
AllowAllFilter());
|
||||||
}
|
}
|
||||||
|
// ... = Filter, NestingLimit
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
DeserializationError deserializeJson(
|
DeserializationError deserializeJson(
|
||||||
JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
|
JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
|
||||||
@@ -723,6 +731,7 @@ DeserializationError deserializeJson(
|
|||||||
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
|
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
|
||||||
filter);
|
filter);
|
||||||
}
|
}
|
||||||
|
// ... = NestingLimit, Filter
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
|
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
|
||||||
size_t inputSize,
|
size_t inputSize,
|
||||||
|
|||||||
@@ -12,11 +12,11 @@
|
|||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TWriter>
|
template <typename TWriter>
|
||||||
class JsonSerializer {
|
class JsonSerializer : public Visitor<size_t> {
|
||||||
public:
|
public:
|
||||||
JsonSerializer(TWriter writer) : _formatter(writer) {}
|
JsonSerializer(TWriter writer) : _formatter(writer) {}
|
||||||
|
|
||||||
FORCE_INLINE void visitArray(const CollectionData &array) {
|
FORCE_INLINE size_t visitArray(const CollectionData &array) {
|
||||||
write('[');
|
write('[');
|
||||||
|
|
||||||
VariantSlot *slot = array.head();
|
VariantSlot *slot = array.head();
|
||||||
@@ -32,9 +32,10 @@ class JsonSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
write(']');
|
write(']');
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitObject(const CollectionData &object) {
|
size_t visitObject(const CollectionData &object) {
|
||||||
write('{');
|
write('{');
|
||||||
|
|
||||||
VariantSlot *slot = object.head();
|
VariantSlot *slot = object.head();
|
||||||
@@ -52,41 +53,49 @@ class JsonSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
write('}');
|
write('}');
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitFloat(Float value) {
|
size_t visitFloat(Float value) {
|
||||||
_formatter.writeFloat(value);
|
_formatter.writeFloat(value);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitString(const char *value) {
|
size_t visitString(const char *value) {
|
||||||
_formatter.writeString(value);
|
_formatter.writeString(value);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitRawJson(const char *data, size_t n) {
|
size_t visitRawJson(const char *data, size_t n) {
|
||||||
_formatter.writeRaw(data, n);
|
_formatter.writeRaw(data, n);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNegativeInteger(UInt value) {
|
size_t visitNegativeInteger(UInt value) {
|
||||||
_formatter.writeNegativeInteger(value);
|
_formatter.writeNegativeInteger(value);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitPositiveInteger(UInt value) {
|
size_t visitPositiveInteger(UInt value) {
|
||||||
_formatter.writePositiveInteger(value);
|
_formatter.writePositiveInteger(value);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitBoolean(bool value) {
|
size_t visitBoolean(bool value) {
|
||||||
_formatter.writeBoolean(value);
|
_formatter.writeBoolean(value);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNull() {
|
size_t visitNull() {
|
||||||
_formatter.writeRaw("null");
|
_formatter.writeRaw("null");
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
size_t bytesWritten() const {
|
size_t bytesWritten() const {
|
||||||
return _formatter.bytesWritten();
|
return _formatter.bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
void write(char c) {
|
void write(char c) {
|
||||||
_formatter.writeRaw(c);
|
_formatter.writeRaw(c);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,44 +18,48 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
|||||||
public:
|
public:
|
||||||
PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
|
PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
|
||||||
|
|
||||||
void visitArray(const CollectionData &array) {
|
size_t visitArray(const CollectionData &array) {
|
||||||
VariantSlot *slot = array.head();
|
VariantSlot *slot = array.head();
|
||||||
if (!slot)
|
if (slot) {
|
||||||
return base::write("[]");
|
base::write("[\r\n");
|
||||||
|
_nesting++;
|
||||||
|
while (slot != 0) {
|
||||||
|
indent();
|
||||||
|
slot->data()->accept(*this);
|
||||||
|
|
||||||
base::write("[\r\n");
|
slot = slot->next();
|
||||||
_nesting++;
|
base::write(slot ? ",\r\n" : "\r\n");
|
||||||
while (slot != 0) {
|
}
|
||||||
|
_nesting--;
|
||||||
indent();
|
indent();
|
||||||
slot->data()->accept(*this);
|
base::write("]");
|
||||||
|
} else {
|
||||||
slot = slot->next();
|
base::write("[]");
|
||||||
base::write(slot ? ",\r\n" : "\r\n");
|
|
||||||
}
|
}
|
||||||
_nesting--;
|
return this->bytesWritten();
|
||||||
indent();
|
|
||||||
base::write("]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitObject(const CollectionData &object) {
|
size_t visitObject(const CollectionData &object) {
|
||||||
VariantSlot *slot = object.head();
|
VariantSlot *slot = object.head();
|
||||||
if (!slot)
|
if (slot) {
|
||||||
return base::write("{}");
|
base::write("{\r\n");
|
||||||
|
_nesting++;
|
||||||
|
while (slot != 0) {
|
||||||
|
indent();
|
||||||
|
base::visitString(slot->key());
|
||||||
|
base::write(": ");
|
||||||
|
slot->data()->accept(*this);
|
||||||
|
|
||||||
base::write("{\r\n");
|
slot = slot->next();
|
||||||
_nesting++;
|
base::write(slot ? ",\r\n" : "\r\n");
|
||||||
while (slot != 0) {
|
}
|
||||||
|
_nesting--;
|
||||||
indent();
|
indent();
|
||||||
base::visitString(slot->key());
|
base::write("}");
|
||||||
base::write(": ");
|
} else {
|
||||||
slot->data()->accept(*this);
|
base::write("{}");
|
||||||
|
|
||||||
slot = slot->next();
|
|
||||||
base::write(slot ? ",\r\n" : "\r\n");
|
|
||||||
}
|
}
|
||||||
_nesting--;
|
return this->bytesWritten();
|
||||||
indent();
|
|
||||||
base::write("}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -12,17 +12,18 @@
|
|||||||
#include <ArduinoJson/Numbers/Integer.hpp>
|
#include <ArduinoJson/Numbers/Integer.hpp>
|
||||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||||
#include <ArduinoJson/Polyfills/attributes.hpp>
|
#include <ArduinoJson/Polyfills/attributes.hpp>
|
||||||
|
#include <ArduinoJson/Serialization/CountingDecorator.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TWriter>
|
template <typename TWriter>
|
||||||
class TextFormatter {
|
class TextFormatter {
|
||||||
public:
|
public:
|
||||||
explicit TextFormatter(TWriter writer) : _writer(writer), _length(0) {}
|
explicit TextFormatter(TWriter writer) : _writer(writer) {}
|
||||||
|
|
||||||
// Returns the number of bytes sent to the TWriter implementation.
|
// Returns the number of bytes sent to the TWriter implementation.
|
||||||
size_t bytesWritten() const {
|
size_t bytesWritten() const {
|
||||||
return _length;
|
return _writer.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeBoolean(bool value) {
|
void writeBoolean(bool value) {
|
||||||
@@ -128,28 +129,28 @@ class TextFormatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writeRaw(const char *s) {
|
void writeRaw(const char *s) {
|
||||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
|
_writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeRaw(const char *s, size_t n) {
|
void writeRaw(const char *s, size_t n) {
|
||||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), n);
|
_writer.write(reinterpret_cast<const uint8_t *>(s), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeRaw(const char *begin, const char *end) {
|
void writeRaw(const char *begin, const char *end) {
|
||||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(begin),
|
_writer.write(reinterpret_cast<const uint8_t *>(begin),
|
||||||
static_cast<size_t>(end - begin));
|
static_cast<size_t>(end - begin));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
void writeRaw(const char (&s)[N]) {
|
void writeRaw(const char (&s)[N]) {
|
||||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
|
_writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
|
||||||
}
|
}
|
||||||
void writeRaw(char c) {
|
void writeRaw(char c) {
|
||||||
_length += _writer.write(static_cast<uint8_t>(c));
|
_writer.write(static_cast<uint8_t>(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TWriter _writer;
|
CountingDecorator<TWriter> _writer;
|
||||||
size_t _length;
|
size_t _length;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -5,13 +5,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/Alignment.hpp>
|
#include <ArduinoJson/Memory/Alignment.hpp>
|
||||||
#include <ArduinoJson/Memory/StringSlot.hpp>
|
|
||||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||||
#include <ArduinoJson/Polyfills/mpl/max.hpp>
|
#include <ArduinoJson/Polyfills/mpl/max.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantSlot.hpp>
|
#include <ArduinoJson/Variant/VariantSlot.hpp>
|
||||||
|
|
||||||
#include <string.h> // memmove
|
#include <string.h> // memmove
|
||||||
|
|
||||||
|
#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
// _begin _end
|
// _begin _end
|
||||||
@@ -28,7 +29,8 @@ class MemoryPool {
|
|||||||
: _begin(buf),
|
: _begin(buf),
|
||||||
_left(buf),
|
_left(buf),
|
||||||
_right(buf ? buf + capa : 0),
|
_right(buf ? buf + capa : 0),
|
||||||
_end(buf ? buf + capa : 0) {
|
_end(buf ? buf + capa : 0),
|
||||||
|
_overflowed(false) {
|
||||||
ARDUINOJSON_ASSERT(isAligned(_begin));
|
ARDUINOJSON_ASSERT(isAligned(_begin));
|
||||||
ARDUINOJSON_ASSERT(isAligned(_right));
|
ARDUINOJSON_ASSERT(isAligned(_right));
|
||||||
ARDUINOJSON_ASSERT(isAligned(_end));
|
ARDUINOJSON_ASSERT(isAligned(_end));
|
||||||
@@ -47,6 +49,10 @@ class MemoryPool {
|
|||||||
return size_t(_left - _begin + _end - _right);
|
return size_t(_left - _begin + _end - _right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool overflowed() const {
|
||||||
|
return _overflowed;
|
||||||
|
}
|
||||||
|
|
||||||
VariantSlot* allocVariant() {
|
VariantSlot* allocVariant() {
|
||||||
return allocRight<VariantSlot>();
|
return allocRight<VariantSlot>();
|
||||||
}
|
}
|
||||||
@@ -90,9 +96,14 @@ class MemoryPool {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void markAsOverflowed() {
|
||||||
|
_overflowed = true;
|
||||||
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
_left = _begin;
|
_left = _begin;
|
||||||
_right = _end;
|
_right = _end;
|
||||||
|
_overflowed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canAlloc(size_t bytes) const {
|
bool canAlloc(size_t bytes) const {
|
||||||
@@ -143,10 +154,6 @@ class MemoryPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StringSlot* allocStringSlot() {
|
|
||||||
return allocRight<StringSlot>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkInvariants() {
|
void checkInvariants() {
|
||||||
ARDUINOJSON_ASSERT(_begin <= _left);
|
ARDUINOJSON_ASSERT(_begin <= _left);
|
||||||
ARDUINOJSON_ASSERT(_left <= _right);
|
ARDUINOJSON_ASSERT(_left <= _right);
|
||||||
@@ -174,8 +181,10 @@ class MemoryPool {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* allocString(size_t n) {
|
char* allocString(size_t n) {
|
||||||
if (!canAlloc(n))
|
if (!canAlloc(n)) {
|
||||||
|
_overflowed = true;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
char* s = _left;
|
char* s = _left;
|
||||||
_left += n;
|
_left += n;
|
||||||
checkInvariants();
|
checkInvariants();
|
||||||
@@ -188,13 +197,16 @@ class MemoryPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* allocRight(size_t bytes) {
|
void* allocRight(size_t bytes) {
|
||||||
if (!canAlloc(bytes))
|
if (!canAlloc(bytes)) {
|
||||||
|
_overflowed = true;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
_right -= bytes;
|
_right -= bytes;
|
||||||
return _right;
|
return _right;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *_begin, *_left, *_right, *_end;
|
char *_begin, *_left, *_right, *_end;
|
||||||
|
bool _overflowed;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stddef.h> // for size_t
|
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
|
|
||||||
#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
struct StringSlot {
|
|
||||||
char *value;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
||||||
@@ -8,6 +8,11 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename TResult>
|
||||||
|
struct Visitor {
|
||||||
|
typedef TResult result_type;
|
||||||
|
};
|
||||||
|
|
||||||
struct Visitable {
|
struct Visitable {
|
||||||
// template<Visitor>
|
// template<Visitor>
|
||||||
// void accept(Visitor&) const;
|
// void accept(Visitor&) const;
|
||||||
|
|||||||
@@ -21,121 +21,244 @@ class MsgPackDeserializer {
|
|||||||
: _pool(&pool),
|
: _pool(&pool),
|
||||||
_reader(reader),
|
_reader(reader),
|
||||||
_stringStorage(stringStorage),
|
_stringStorage(stringStorage),
|
||||||
_error(DeserializationError::Ok) {}
|
_error(DeserializationError::Ok),
|
||||||
|
_foundSomething(false) {}
|
||||||
|
|
||||||
DeserializationError parse(VariantData &variant, AllowAllFilter,
|
template <typename TFilter>
|
||||||
|
DeserializationError parse(VariantData &variant, TFilter filter,
|
||||||
NestingLimit nestingLimit) {
|
NestingLimit nestingLimit) {
|
||||||
parseVariant(variant, nestingLimit);
|
parseVariant(variant, filter, nestingLimit);
|
||||||
return _error;
|
return _foundSomething ? _error : DeserializationError::EmptyInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool parseVariant(VariantData &variant, NestingLimit nestingLimit) {
|
// Prevent VS warning "assignment operator could not be generated"
|
||||||
uint8_t code;
|
MsgPackDeserializer &operator=(const MsgPackDeserializer &);
|
||||||
if (!readByte(code)) {
|
|
||||||
_error = DeserializationError::IncompleteInput;
|
bool invalidInput() {
|
||||||
|
_error = DeserializationError::InvalidInput;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool notSupported() {
|
||||||
|
_error = DeserializationError::NotSupported;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TFilter>
|
||||||
|
bool parseVariant(VariantData &variant, TFilter filter,
|
||||||
|
NestingLimit nestingLimit) {
|
||||||
|
uint8_t code = 0;
|
||||||
|
if (!readByte(code))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if ((code & 0x80) == 0) {
|
_foundSomething = true;
|
||||||
variant.setUnsignedInteger(code);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((code & 0xe0) == 0xe0) {
|
bool allowValue = filter.allowValue();
|
||||||
variant.setSignedInteger(static_cast<int8_t>(code));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((code & 0xe0) == 0xa0) {
|
|
||||||
return readString(variant, code & 0x1f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((code & 0xf0) == 0x90) {
|
|
||||||
return readArray(variant.toArray(), code & 0x0F, nestingLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((code & 0xf0) == 0x80) {
|
|
||||||
return readObject(variant.toObject(), code & 0x0F, nestingLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 0xc0:
|
case 0xc0:
|
||||||
// already null
|
// already null
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case 0xc1:
|
||||||
|
return invalidInput();
|
||||||
|
|
||||||
case 0xc2:
|
case 0xc2:
|
||||||
variant.setBoolean(false);
|
if (allowValue)
|
||||||
|
variant.setBoolean(false);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case 0xc3:
|
case 0xc3:
|
||||||
variant.setBoolean(true);
|
if (allowValue)
|
||||||
|
variant.setBoolean(true);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case 0xcc:
|
case 0xc4: // bin 8
|
||||||
return readInteger<uint8_t>(variant);
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
|
else
|
||||||
|
return skipString<uint8_t>();
|
||||||
|
|
||||||
case 0xcd:
|
case 0xc5: // bin 16
|
||||||
return readInteger<uint16_t>(variant);
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
|
else
|
||||||
|
return skipString<uint16_t>();
|
||||||
|
|
||||||
case 0xce:
|
case 0xc6: // bin 32
|
||||||
return readInteger<uint32_t>(variant);
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
|
else
|
||||||
|
return skipString<uint32_t>();
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
case 0xc7: // ext 8
|
||||||
case 0xcf:
|
if (allowValue)
|
||||||
return readInteger<uint64_t>(variant);
|
return notSupported();
|
||||||
#endif
|
else
|
||||||
|
return skipExt<uint8_t>();
|
||||||
|
|
||||||
case 0xd0:
|
case 0xc8: // ext 16
|
||||||
return readInteger<int8_t>(variant);
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
|
else
|
||||||
|
return skipExt<uint16_t>();
|
||||||
|
|
||||||
case 0xd1:
|
case 0xc9: // ext 32
|
||||||
return readInteger<int16_t>(variant);
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
case 0xd2:
|
else
|
||||||
return readInteger<int32_t>(variant);
|
return skipExt<uint32_t>();
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
|
||||||
case 0xd3:
|
|
||||||
return readInteger<int64_t>(variant);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case 0xca:
|
case 0xca:
|
||||||
return readFloat<float>(variant);
|
if (allowValue)
|
||||||
|
return readFloat<float>(variant);
|
||||||
|
else
|
||||||
|
return skipBytes(4);
|
||||||
|
|
||||||
case 0xcb:
|
case 0xcb:
|
||||||
return readDouble<double>(variant);
|
if (allowValue)
|
||||||
|
return readDouble<double>(variant);
|
||||||
|
else
|
||||||
|
return skipBytes(8);
|
||||||
|
|
||||||
|
case 0xcc:
|
||||||
|
if (allowValue)
|
||||||
|
return readInteger<uint8_t>(variant);
|
||||||
|
else
|
||||||
|
return skipBytes(1);
|
||||||
|
|
||||||
|
case 0xcd:
|
||||||
|
if (allowValue)
|
||||||
|
return readInteger<uint16_t>(variant);
|
||||||
|
else
|
||||||
|
return skipBytes(2);
|
||||||
|
|
||||||
|
case 0xce:
|
||||||
|
if (allowValue)
|
||||||
|
return readInteger<uint32_t>(variant);
|
||||||
|
else
|
||||||
|
return skipBytes(4);
|
||||||
|
|
||||||
|
case 0xcf:
|
||||||
|
if (allowValue)
|
||||||
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
|
return readInteger<uint64_t>(variant);
|
||||||
|
#else
|
||||||
|
return notSupported();
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return skipBytes(8);
|
||||||
|
|
||||||
|
case 0xd0:
|
||||||
|
if (allowValue)
|
||||||
|
return readInteger<int8_t>(variant);
|
||||||
|
else
|
||||||
|
return skipBytes(1);
|
||||||
|
|
||||||
|
case 0xd1:
|
||||||
|
if (allowValue)
|
||||||
|
return readInteger<int16_t>(variant);
|
||||||
|
else
|
||||||
|
return skipBytes(2);
|
||||||
|
|
||||||
|
case 0xd2:
|
||||||
|
if (allowValue)
|
||||||
|
return readInteger<int32_t>(variant);
|
||||||
|
else
|
||||||
|
return skipBytes(4);
|
||||||
|
|
||||||
|
case 0xd3:
|
||||||
|
if (allowValue)
|
||||||
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
|
return readInteger<int64_t>(variant);
|
||||||
|
#else
|
||||||
|
return notSupported();
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return skipBytes(8);
|
||||||
|
|
||||||
|
case 0xd4: // fixext 1
|
||||||
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
|
else
|
||||||
|
return skipBytes(2);
|
||||||
|
|
||||||
|
case 0xd5: // fixext 2
|
||||||
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
|
else
|
||||||
|
return skipBytes(3);
|
||||||
|
|
||||||
|
case 0xd6: // fixext 4
|
||||||
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
|
else
|
||||||
|
return skipBytes(5);
|
||||||
|
|
||||||
|
case 0xd7: // fixext 8
|
||||||
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
|
else
|
||||||
|
return skipBytes(9);
|
||||||
|
|
||||||
|
case 0xd8: // fixext 16
|
||||||
|
if (allowValue)
|
||||||
|
return notSupported();
|
||||||
|
else
|
||||||
|
return skipBytes(17);
|
||||||
|
|
||||||
case 0xd9:
|
case 0xd9:
|
||||||
return readString<uint8_t>(variant);
|
if (allowValue)
|
||||||
|
return readString<uint8_t>(variant);
|
||||||
|
else
|
||||||
|
return skipString<uint8_t>();
|
||||||
|
|
||||||
case 0xda:
|
case 0xda:
|
||||||
return readString<uint16_t>(variant);
|
if (allowValue)
|
||||||
|
return readString<uint16_t>(variant);
|
||||||
|
else
|
||||||
|
return skipString<uint16_t>();
|
||||||
|
|
||||||
case 0xdb:
|
case 0xdb:
|
||||||
return readString<uint32_t>(variant);
|
if (allowValue)
|
||||||
|
return readString<uint32_t>(variant);
|
||||||
|
else
|
||||||
|
return skipString<uint32_t>();
|
||||||
|
|
||||||
case 0xdc:
|
case 0xdc:
|
||||||
return readArray<uint16_t>(variant.toArray(), nestingLimit);
|
return readArray<uint16_t>(variant, filter, nestingLimit);
|
||||||
|
|
||||||
case 0xdd:
|
case 0xdd:
|
||||||
return readArray<uint32_t>(variant.toArray(), nestingLimit);
|
return readArray<uint32_t>(variant, filter, nestingLimit);
|
||||||
|
|
||||||
case 0xde:
|
case 0xde:
|
||||||
return readObject<uint16_t>(variant.toObject(), nestingLimit);
|
return readObject<uint16_t>(variant, filter, nestingLimit);
|
||||||
|
|
||||||
case 0xdf:
|
case 0xdf:
|
||||||
return readObject<uint32_t>(variant.toObject(), nestingLimit);
|
return readObject<uint32_t>(variant, filter, nestingLimit);
|
||||||
|
|
||||||
default:
|
|
||||||
_error = DeserializationError::NotSupported;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
switch (code & 0xf0) {
|
||||||
// Prevent VS warning "assignment operator could not be generated"
|
case 0x80:
|
||||||
MsgPackDeserializer &operator=(const MsgPackDeserializer &);
|
return readObject(variant, code & 0x0F, filter, nestingLimit);
|
||||||
|
|
||||||
|
case 0x90:
|
||||||
|
return readArray(variant, code & 0x0F, filter, nestingLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((code & 0xe0) == 0xa0) {
|
||||||
|
if (allowValue)
|
||||||
|
return readString(variant, code & 0x1f);
|
||||||
|
else
|
||||||
|
return skipBytes(code & 0x1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowValue)
|
||||||
|
variant.setInteger(static_cast<int8_t>(code));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool readByte(uint8_t &value) {
|
bool readByte(uint8_t &value) {
|
||||||
int c = _reader.read();
|
int c = _reader.read();
|
||||||
@@ -159,6 +282,16 @@ class MsgPackDeserializer {
|
|||||||
return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
|
return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool skipBytes(size_t n) {
|
||||||
|
for (; n; --n) {
|
||||||
|
if (_reader.read() < 0) {
|
||||||
|
_error = DeserializationError::IncompleteInput;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool readInteger(T &value) {
|
bool readInteger(T &value) {
|
||||||
if (!readBytes(value))
|
if (!readBytes(value))
|
||||||
@@ -221,24 +354,31 @@ class MsgPackDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool readString(const char *&str) {
|
bool readString() {
|
||||||
T size;
|
T size;
|
||||||
if (!readInteger(size))
|
if (!readInteger(size))
|
||||||
return false;
|
return false;
|
||||||
return readString(str, size);
|
return readString(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool skipString() {
|
||||||
|
T size;
|
||||||
|
if (!readInteger(size))
|
||||||
|
return false;
|
||||||
|
return skipBytes(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readString(VariantData &variant, size_t n) {
|
bool readString(VariantData &variant, size_t n) {
|
||||||
const char *s = 0; // <- mute "maybe-uninitialized" (+4 bytes on AVR)
|
if (!readString(n))
|
||||||
if (!readString(s, n))
|
|
||||||
return false;
|
return false;
|
||||||
variant.setString(make_not_null(s),
|
variant.setStringPointer(_stringStorage.save(),
|
||||||
typename TStringStorage::storage_policy());
|
typename TStringStorage::storage_policy());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readString(const char *&result, size_t n) {
|
bool readString(size_t n) {
|
||||||
_stringStorage.startString(_pool);
|
_stringStorage.startString();
|
||||||
for (; n; --n) {
|
for (; n; --n) {
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
if (!readBytes(c))
|
if (!readBytes(c))
|
||||||
@@ -251,131 +391,247 @@ class MsgPackDeserializer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = _stringStorage.save(_pool);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TSize>
|
template <typename TSize, typename TFilter>
|
||||||
bool readArray(CollectionData &array, NestingLimit nestingLimit) {
|
bool readArray(VariantData &variant, TFilter filter,
|
||||||
|
NestingLimit nestingLimit) {
|
||||||
TSize size;
|
TSize size;
|
||||||
if (!readInteger(size))
|
if (!readInteger(size))
|
||||||
return false;
|
return false;
|
||||||
return readArray(array, size, nestingLimit);
|
return readArray(variant, size, filter, nestingLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readArray(CollectionData &array, size_t n, NestingLimit nestingLimit) {
|
template <typename TFilter>
|
||||||
|
bool readArray(VariantData &variant, size_t n, TFilter filter,
|
||||||
|
NestingLimit nestingLimit) {
|
||||||
if (nestingLimit.reached()) {
|
if (nestingLimit.reached()) {
|
||||||
_error = DeserializationError::TooDeep;
|
_error = DeserializationError::TooDeep;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool allowArray = filter.allowArray();
|
||||||
|
|
||||||
|
CollectionData *array = allowArray ? &variant.toArray() : 0;
|
||||||
|
|
||||||
|
TFilter memberFilter = filter[0U];
|
||||||
|
|
||||||
for (; n; --n) {
|
for (; n; --n) {
|
||||||
VariantData *value = array.addElement(_pool);
|
VariantData *value;
|
||||||
if (!value) {
|
|
||||||
_error = DeserializationError::NoMemory;
|
if (memberFilter.allow()) {
|
||||||
return false;
|
value = array->addElement(_pool);
|
||||||
|
if (!value) {
|
||||||
|
_error = DeserializationError::NoMemory;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parseVariant(*value, nestingLimit.decrement()))
|
if (!parseVariant(*value, memberFilter, nestingLimit.decrement()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TSize>
|
template <typename TSize, typename TFilter>
|
||||||
bool readObject(CollectionData &object, NestingLimit nestingLimit) {
|
bool readObject(VariantData &variant, TFilter filter,
|
||||||
|
NestingLimit nestingLimit) {
|
||||||
TSize size;
|
TSize size;
|
||||||
if (!readInteger(size))
|
if (!readInteger(size))
|
||||||
return false;
|
return false;
|
||||||
return readObject(object, size, nestingLimit);
|
return readObject(variant, size, filter, nestingLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readObject(CollectionData &object, size_t n, NestingLimit nestingLimit) {
|
template <typename TFilter>
|
||||||
|
bool readObject(VariantData &variant, size_t n, TFilter filter,
|
||||||
|
NestingLimit nestingLimit) {
|
||||||
if (nestingLimit.reached()) {
|
if (nestingLimit.reached()) {
|
||||||
_error = DeserializationError::TooDeep;
|
_error = DeserializationError::TooDeep;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CollectionData *object = filter.allowObject() ? &variant.toObject() : 0;
|
||||||
|
|
||||||
for (; n; --n) {
|
for (; n; --n) {
|
||||||
VariantSlot *slot = object.addSlot(_pool);
|
if (!readKey())
|
||||||
if (!slot) {
|
|
||||||
_error = DeserializationError::NoMemory;
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
const char *key = _stringStorage.c_str();
|
||||||
|
TFilter memberFilter = filter[key];
|
||||||
|
VariantData *member;
|
||||||
|
|
||||||
|
if (memberFilter.allow()) {
|
||||||
|
// Save key in memory pool.
|
||||||
|
// This MUST be done before adding the slot.
|
||||||
|
key = _stringStorage.save();
|
||||||
|
|
||||||
|
VariantSlot *slot = object->addSlot(_pool);
|
||||||
|
if (!slot) {
|
||||||
|
_error = DeserializationError::NoMemory;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot->setKey(key, typename TStringStorage::storage_policy());
|
||||||
|
|
||||||
|
member = slot->data();
|
||||||
|
} else {
|
||||||
|
member = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *key = 0; // <- mute "maybe-uninitialized" (+4 bytes on AVR)
|
if (!parseVariant(*member, memberFilter, nestingLimit.decrement()))
|
||||||
if (!parseKey(key))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
slot->setKey(key, typename TStringStorage::storage_policy());
|
|
||||||
|
|
||||||
if (!parseVariant(*slot->data(), nestingLimit.decrement()))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseKey(const char *&key) {
|
bool readKey() {
|
||||||
uint8_t code;
|
uint8_t code;
|
||||||
if (!readByte(code))
|
if (!readByte(code))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((code & 0xe0) == 0xa0)
|
if ((code & 0xe0) == 0xa0)
|
||||||
return readString(key, code & 0x1f);
|
return readString(code & 0x1f);
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 0xd9:
|
case 0xd9:
|
||||||
return readString<uint8_t>(key);
|
return readString<uint8_t>();
|
||||||
|
|
||||||
case 0xda:
|
case 0xda:
|
||||||
return readString<uint16_t>(key);
|
return readString<uint16_t>();
|
||||||
|
|
||||||
case 0xdb:
|
case 0xdb:
|
||||||
return readString<uint32_t>(key);
|
return readString<uint32_t>();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_error = DeserializationError::NotSupported;
|
return notSupported();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool skipExt() {
|
||||||
|
T size;
|
||||||
|
if (!readInteger(size))
|
||||||
|
return false;
|
||||||
|
return skipBytes(size + 1);
|
||||||
|
}
|
||||||
|
|
||||||
MemoryPool *_pool;
|
MemoryPool *_pool;
|
||||||
TReader _reader;
|
TReader _reader;
|
||||||
TStringStorage _stringStorage;
|
TStringStorage _stringStorage;
|
||||||
DeserializationError _error;
|
DeserializationError _error;
|
||||||
|
bool _foundSomething;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TInput>
|
//
|
||||||
|
// deserializeMsgPack(JsonDocument&, const std::string&, ...)
|
||||||
|
//
|
||||||
|
// ... = NestingLimit
|
||||||
|
template <typename TString>
|
||||||
DeserializationError deserializeMsgPack(
|
DeserializationError deserializeMsgPack(
|
||||||
JsonDocument &doc, const TInput &input,
|
JsonDocument &doc, const TString &input,
|
||||||
NestingLimit nestingLimit = NestingLimit()) {
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
||||||
AllowAllFilter());
|
AllowAllFilter());
|
||||||
}
|
}
|
||||||
|
// ... = Filter, NestingLimit
|
||||||
template <typename TInput>
|
template <typename TString>
|
||||||
DeserializationError deserializeMsgPack(
|
DeserializationError deserializeMsgPack(
|
||||||
JsonDocument &doc, TInput *input,
|
JsonDocument &doc, const TString &input, Filter filter,
|
||||||
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
|
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||||
|
}
|
||||||
|
// ... = NestingLimit, Filter
|
||||||
|
template <typename TString>
|
||||||
|
DeserializationError deserializeMsgPack(JsonDocument &doc, const TString &input,
|
||||||
|
NestingLimit nestingLimit,
|
||||||
|
Filter filter) {
|
||||||
|
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// deserializeMsgPack(JsonDocument&, std::istream&, ...)
|
||||||
|
//
|
||||||
|
// ... = NestingLimit
|
||||||
|
template <typename TStream>
|
||||||
|
DeserializationError deserializeMsgPack(
|
||||||
|
JsonDocument &doc, TStream &input,
|
||||||
NestingLimit nestingLimit = NestingLimit()) {
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
||||||
AllowAllFilter());
|
AllowAllFilter());
|
||||||
}
|
}
|
||||||
|
// ... = Filter, NestingLimit
|
||||||
template <typename TInput>
|
template <typename TStream>
|
||||||
DeserializationError deserializeMsgPack(
|
DeserializationError deserializeMsgPack(
|
||||||
JsonDocument &doc, TInput *input, size_t inputSize,
|
JsonDocument &doc, TStream &input, Filter filter,
|
||||||
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
|
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||||
|
}
|
||||||
|
// ... = NestingLimit, Filter
|
||||||
|
template <typename TStream>
|
||||||
|
DeserializationError deserializeMsgPack(JsonDocument &doc, TStream &input,
|
||||||
|
NestingLimit nestingLimit,
|
||||||
|
Filter filter) {
|
||||||
|
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// deserializeMsgPack(JsonDocument&, char*, ...)
|
||||||
|
//
|
||||||
|
// ... = NestingLimit
|
||||||
|
template <typename TChar>
|
||||||
|
DeserializationError deserializeMsgPack(
|
||||||
|
JsonDocument &doc, TChar *input,
|
||||||
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
|
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
||||||
|
AllowAllFilter());
|
||||||
|
}
|
||||||
|
// ... = Filter, NestingLimit
|
||||||
|
template <typename TChar>
|
||||||
|
DeserializationError deserializeMsgPack(
|
||||||
|
JsonDocument &doc, TChar *input, Filter filter,
|
||||||
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
|
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||||
|
}
|
||||||
|
// ... = NestingLimit, Filter
|
||||||
|
template <typename TChar>
|
||||||
|
DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
|
||||||
|
NestingLimit nestingLimit,
|
||||||
|
Filter filter) {
|
||||||
|
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// deserializeMsgPack(JsonDocument&, char*, size_t, ...)
|
||||||
|
//
|
||||||
|
// ... = NestingLimit
|
||||||
|
template <typename TChar>
|
||||||
|
DeserializationError deserializeMsgPack(
|
||||||
|
JsonDocument &doc, TChar *input, size_t inputSize,
|
||||||
NestingLimit nestingLimit = NestingLimit()) {
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
|
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
|
||||||
AllowAllFilter());
|
AllowAllFilter());
|
||||||
}
|
}
|
||||||
|
// ... = Filter, NestingLimit
|
||||||
template <typename TInput>
|
template <typename TChar>
|
||||||
DeserializationError deserializeMsgPack(
|
DeserializationError deserializeMsgPack(
|
||||||
JsonDocument &doc, TInput &input,
|
JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
|
||||||
NestingLimit nestingLimit = NestingLimit()) {
|
NestingLimit nestingLimit = NestingLimit()) {
|
||||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
|
||||||
AllowAllFilter());
|
filter);
|
||||||
}
|
}
|
||||||
|
// ... = NestingLimit, Filter
|
||||||
|
template <typename TChar>
|
||||||
|
DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
|
||||||
|
size_t inputSize,
|
||||||
|
NestingLimit nestingLimit,
|
||||||
|
Filter filter) {
|
||||||
|
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
|
||||||
|
filter);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <ArduinoJson/MsgPack/endianess.hpp>
|
#include <ArduinoJson/MsgPack/endianess.hpp>
|
||||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
|
#include <ArduinoJson/Serialization/CountingDecorator.hpp>
|
||||||
#include <ArduinoJson/Serialization/measure.hpp>
|
#include <ArduinoJson/Serialization/measure.hpp>
|
||||||
#include <ArduinoJson/Serialization/serialize.hpp>
|
#include <ArduinoJson/Serialization/serialize.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||||
@@ -14,19 +15,20 @@
|
|||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TWriter>
|
template <typename TWriter>
|
||||||
class MsgPackSerializer {
|
class MsgPackSerializer : public Visitor<size_t> {
|
||||||
public:
|
public:
|
||||||
MsgPackSerializer(TWriter writer) : _writer(writer), _bytesWritten(0) {}
|
MsgPackSerializer(TWriter writer) : _writer(writer) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename enable_if<sizeof(T) == 4>::type visitFloat(T value32) {
|
typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) {
|
||||||
writeByte(0xCA);
|
writeByte(0xCA);
|
||||||
writeInteger(value32);
|
writeInteger(value32);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
ARDUINOJSON_NO_SANITIZE("float-cast-overflow")
|
ARDUINOJSON_NO_SANITIZE("float-cast-overflow")
|
||||||
typename enable_if<sizeof(T) == 8>::type visitFloat(T value64) {
|
typename enable_if<sizeof(T) == 8, size_t>::type visitFloat(T value64) {
|
||||||
float value32 = float(value64);
|
float value32 = float(value64);
|
||||||
if (value32 == value64) {
|
if (value32 == value64) {
|
||||||
writeByte(0xCA);
|
writeByte(0xCA);
|
||||||
@@ -35,9 +37,10 @@ class MsgPackSerializer {
|
|||||||
writeByte(0xCB);
|
writeByte(0xCB);
|
||||||
writeInteger(value64);
|
writeInteger(value64);
|
||||||
}
|
}
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitArray(const CollectionData& array) {
|
size_t visitArray(const CollectionData& array) {
|
||||||
size_t n = array.size();
|
size_t n = array.size();
|
||||||
if (n < 0x10) {
|
if (n < 0x10) {
|
||||||
writeByte(uint8_t(0x90 + array.size()));
|
writeByte(uint8_t(0x90 + array.size()));
|
||||||
@@ -51,9 +54,10 @@ class MsgPackSerializer {
|
|||||||
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
|
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
|
||||||
slot->data()->accept(*this);
|
slot->data()->accept(*this);
|
||||||
}
|
}
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitObject(const CollectionData& object) {
|
size_t visitObject(const CollectionData& object) {
|
||||||
size_t n = object.size();
|
size_t n = object.size();
|
||||||
if (n < 0x10) {
|
if (n < 0x10) {
|
||||||
writeByte(uint8_t(0x80 + n));
|
writeByte(uint8_t(0x80 + n));
|
||||||
@@ -68,9 +72,10 @@ class MsgPackSerializer {
|
|||||||
visitString(slot->key());
|
visitString(slot->key());
|
||||||
slot->data()->accept(*this);
|
slot->data()->accept(*this);
|
||||||
}
|
}
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitString(const char* value) {
|
size_t visitString(const char* value) {
|
||||||
ARDUINOJSON_ASSERT(value != NULL);
|
ARDUINOJSON_ASSERT(value != NULL);
|
||||||
|
|
||||||
size_t n = strlen(value);
|
size_t n = strlen(value);
|
||||||
@@ -88,13 +93,15 @@ class MsgPackSerializer {
|
|||||||
writeInteger(uint32_t(n));
|
writeInteger(uint32_t(n));
|
||||||
}
|
}
|
||||||
writeBytes(reinterpret_cast<const uint8_t*>(value), n);
|
writeBytes(reinterpret_cast<const uint8_t*>(value), n);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitRawJson(const char* data, size_t size) {
|
size_t visitRawJson(const char* data, size_t size) {
|
||||||
writeBytes(reinterpret_cast<const uint8_t*>(data), size);
|
writeBytes(reinterpret_cast<const uint8_t*>(data), size);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNegativeInteger(UInt value) {
|
size_t visitNegativeInteger(UInt value) {
|
||||||
UInt negated = UInt(~value + 1);
|
UInt negated = UInt(~value + 1);
|
||||||
if (value <= 0x20) {
|
if (value <= 0x20) {
|
||||||
writeInteger(int8_t(negated));
|
writeInteger(int8_t(negated));
|
||||||
@@ -114,9 +121,10 @@ class MsgPackSerializer {
|
|||||||
writeInteger(int64_t(negated));
|
writeInteger(int64_t(negated));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitPositiveInteger(UInt value) {
|
size_t visitPositiveInteger(UInt value) {
|
||||||
if (value <= 0x7F) {
|
if (value <= 0x7F) {
|
||||||
writeInteger(uint8_t(value));
|
writeInteger(uint8_t(value));
|
||||||
} else if (value <= 0xFF) {
|
} else if (value <= 0xFF) {
|
||||||
@@ -141,27 +149,30 @@ class MsgPackSerializer {
|
|||||||
writeInteger(uint64_t(value));
|
writeInteger(uint64_t(value));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitBoolean(bool value) {
|
size_t visitBoolean(bool value) {
|
||||||
writeByte(value ? 0xC3 : 0xC2);
|
writeByte(value ? 0xC3 : 0xC2);
|
||||||
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNull() {
|
size_t visitNull() {
|
||||||
writeByte(0xC0);
|
writeByte(0xC0);
|
||||||
}
|
return bytesWritten();
|
||||||
|
|
||||||
size_t bytesWritten() const {
|
|
||||||
return _bytesWritten;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
size_t bytesWritten() const {
|
||||||
|
return _writer.count();
|
||||||
|
}
|
||||||
|
|
||||||
void writeByte(uint8_t c) {
|
void writeByte(uint8_t c) {
|
||||||
_bytesWritten += _writer.write(c);
|
_writer.write(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeBytes(const uint8_t* p, size_t n) {
|
void writeBytes(const uint8_t* p, size_t n) {
|
||||||
_bytesWritten += _writer.write(p, n);
|
_writer.write(p, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -170,8 +181,7 @@ class MsgPackSerializer {
|
|||||||
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
|
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
TWriter _writer;
|
CountingDecorator<TWriter> _writer;
|
||||||
size_t _bytesWritten;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TSource, typename TDestination>
|
template <typename TSource, typename TDestination>
|
||||||
|
|||||||
@@ -5,45 +5,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Configuration.hpp>
|
#include <ArduinoJson/Configuration.hpp>
|
||||||
|
#include <ArduinoJson/Polyfills/preprocessor.hpp>
|
||||||
#include <ArduinoJson/version.hpp>
|
#include <ArduinoJson/version.hpp>
|
||||||
|
|
||||||
#ifndef ARDUINOJSON_NAMESPACE
|
#ifndef ARDUINOJSON_NAMESPACE
|
||||||
|
|
||||||
#define ARDUINOJSON_HEX_DIGIT_0000() 0
|
#define ARDUINOJSON_NAMESPACE \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_0001() 1
|
ARDUINOJSON_CONCAT4( \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_0010() 2
|
ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_0011() 3
|
ARDUINOJSON_VERSION_MINOR, \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_0100() 4
|
ARDUINOJSON_VERSION_REVISION), \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_0101() 5
|
_, \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_0110() 6
|
ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM, \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_0111() 7
|
ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_1000() 8
|
ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_1001() 9
|
ARDUINOJSON_HEX_DIGIT( \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_1010() A
|
ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \
|
||||||
#define ARDUINOJSON_HEX_DIGIT_1011() B
|
|
||||||
#define ARDUINOJSON_HEX_DIGIT_1100() C
|
|
||||||
#define ARDUINOJSON_HEX_DIGIT_1101() D
|
|
||||||
#define ARDUINOJSON_HEX_DIGIT_1110() E
|
|
||||||
#define ARDUINOJSON_HEX_DIGIT_1111() F
|
|
||||||
#define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D()
|
|
||||||
#define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D)
|
|
||||||
|
|
||||||
#define ARDUINOJSON_CONCAT_(A, B) A##B
|
|
||||||
#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B)
|
|
||||||
#define ARDUINOJSON_CONCAT4(A, B, C, D) \
|
|
||||||
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
|
|
||||||
|
|
||||||
#define ARDUINOJSON_NAMESPACE \
|
|
||||||
ARDUINOJSON_CONCAT4( \
|
|
||||||
ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
|
|
||||||
ARDUINOJSON_VERSION_MINOR, \
|
|
||||||
ARDUINOJSON_VERSION_REVISION), \
|
|
||||||
_, \
|
|
||||||
ARDUINOJSON_HEX_DIGIT(0, ARDUINOJSON_USE_LONG_LONG, \
|
|
||||||
ARDUINOJSON_USE_DOUBLE, \
|
|
||||||
ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \
|
|
||||||
ARDUINOJSON_HEX_DIGIT( \
|
|
||||||
ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \
|
|
||||||
ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE))
|
ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <ArduinoJson/Configuration.hpp>
|
#include <ArduinoJson/Configuration.hpp>
|
||||||
#include <ArduinoJson/Polyfills/alias_cast.hpp>
|
#include <ArduinoJson/Polyfills/alias_cast.hpp>
|
||||||
#include <ArduinoJson/Polyfills/math.hpp>
|
#include <ArduinoJson/Polyfills/math.hpp>
|
||||||
|
#include <ArduinoJson/Polyfills/preprocessor.hpp>
|
||||||
|
#include <ArduinoJson/Polyfills/static_array.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
@@ -46,48 +48,60 @@ struct FloatTraits<T, 8 /*64bits*/> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static T positiveBinaryPowerOfTen(int index) {
|
static T positiveBinaryPowerOfTen(int index) {
|
||||||
static T factors[] = {
|
ARDUINOJSON_DEFINE_STATIC_ARRAY( //
|
||||||
1e1,
|
uint32_t, factors,
|
||||||
1e2,
|
ARDUINOJSON_EXPAND18({
|
||||||
1e4,
|
0x40240000, 0x00000000, // 1e1
|
||||||
1e8,
|
0x40590000, 0x00000000, // 1e2
|
||||||
1e16,
|
0x40C38800, 0x00000000, // 1e4
|
||||||
forge(0x4693B8B5, 0xB5056E17), // 1e32
|
0x4197D784, 0x00000000, // 1e8
|
||||||
forge(0x4D384F03, 0xE93FF9F5), // 1e64
|
0x4341C379, 0x37E08000, // 1e16
|
||||||
forge(0x5A827748, 0xF9301D32), // 1e128
|
0x4693B8B5, 0xB5056E17, // 1e32
|
||||||
forge(0x75154FDD, 0x7F73BF3C) // 1e256
|
0x4D384F03, 0xE93FF9F5, // 1e64
|
||||||
};
|
0x5A827748, 0xF9301D32, // 1e128
|
||||||
return factors[index];
|
0x75154FDD, 0x7F73BF3C // 1e256
|
||||||
|
}));
|
||||||
|
return forge(
|
||||||
|
ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
|
||||||
|
ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static T negativeBinaryPowerOfTen(int index) {
|
static T negativeBinaryPowerOfTen(int index) {
|
||||||
static T factors[] = {
|
ARDUINOJSON_DEFINE_STATIC_ARRAY( //
|
||||||
forge(0x3FB99999, 0x9999999A), // 1e-1
|
uint32_t, factors,
|
||||||
forge(0x3F847AE1, 0x47AE147B), // 1e-2
|
ARDUINOJSON_EXPAND18({
|
||||||
forge(0x3F1A36E2, 0xEB1C432D), // 1e-4
|
0x3FB99999, 0x9999999A, // 1e-1
|
||||||
forge(0x3E45798E, 0xE2308C3A), // 1e-8
|
0x3F847AE1, 0x47AE147B, // 1e-2
|
||||||
forge(0x3C9CD2B2, 0x97D889BC), // 1e-16
|
0x3F1A36E2, 0xEB1C432D, // 1e-4
|
||||||
forge(0x3949F623, 0xD5A8A733), // 1e-32
|
0x3E45798E, 0xE2308C3A, // 1e-8
|
||||||
forge(0x32A50FFD, 0x44F4A73D), // 1e-64
|
0x3C9CD2B2, 0x97D889BC, // 1e-16
|
||||||
forge(0x255BBA08, 0xCF8C979D), // 1e-128
|
0x3949F623, 0xD5A8A733, // 1e-32
|
||||||
forge(0x0AC80628, 0x64AC6F43) // 1e-256
|
0x32A50FFD, 0x44F4A73D, // 1e-64
|
||||||
};
|
0x255BBA08, 0xCF8C979D, // 1e-128
|
||||||
return factors[index];
|
0x0AC80628, 0x64AC6F43 // 1e-256
|
||||||
|
}));
|
||||||
|
return forge(
|
||||||
|
ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
|
||||||
|
ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static T negativeBinaryPowerOfTenPlusOne(int index) {
|
static T negativeBinaryPowerOfTenPlusOne(int index) {
|
||||||
static T factors[] = {
|
ARDUINOJSON_DEFINE_STATIC_ARRAY( //
|
||||||
1e0,
|
uint32_t, factors,
|
||||||
forge(0x3FB99999, 0x9999999A), // 1e-1
|
ARDUINOJSON_EXPAND18({
|
||||||
forge(0x3F50624D, 0xD2F1A9FC), // 1e-3
|
0x3FF00000, 0x00000000, // 1e0
|
||||||
forge(0x3E7AD7F2, 0x9ABCAF48), // 1e-7
|
0x3FB99999, 0x9999999A, // 1e-1
|
||||||
forge(0x3CD203AF, 0x9EE75616), // 1e-15
|
0x3F50624D, 0xD2F1A9FC, // 1e-3
|
||||||
forge(0x398039D6, 0x65896880), // 1e-31
|
0x3E7AD7F2, 0x9ABCAF48, // 1e-7
|
||||||
forge(0x32DA53FC, 0x9631D10D), // 1e-63
|
0x3CD203AF, 0x9EE75616, // 1e-15
|
||||||
forge(0x25915445, 0x81B7DEC2), // 1e-127
|
0x398039D6, 0x65896880, // 1e-31
|
||||||
forge(0x0AFE07B2, 0x7DD78B14) // 1e-255
|
0x32DA53FC, 0x9631D10D, // 1e-63
|
||||||
};
|
0x25915445, 0x81B7DEC2, // 1e-127
|
||||||
return factors[index];
|
0x0AFE07B2, 0x7DD78B14 // 1e-255
|
||||||
|
}));
|
||||||
|
return forge(
|
||||||
|
ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
|
||||||
|
ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static T nan() {
|
static T nan() {
|
||||||
@@ -144,18 +158,24 @@ struct FloatTraits<T, 4 /*32bits*/> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static T positiveBinaryPowerOfTen(int index) {
|
static T positiveBinaryPowerOfTen(int index) {
|
||||||
static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f};
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(
|
||||||
return factors[index];
|
T, factors,
|
||||||
|
ARDUINOJSON_EXPAND6({1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}));
|
||||||
|
return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static T negativeBinaryPowerOfTen(int index) {
|
static T negativeBinaryPowerOfTen(int index) {
|
||||||
static T factors[] = {1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f};
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(
|
||||||
return factors[index];
|
T, factors,
|
||||||
|
ARDUINOJSON_EXPAND6({1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}));
|
||||||
|
return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static T negativeBinaryPowerOfTenPlusOne(int index) {
|
static T negativeBinaryPowerOfTenPlusOne(int index) {
|
||||||
static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f};
|
ARDUINOJSON_DEFINE_STATIC_ARRAY(
|
||||||
return factors[index];
|
T, factors,
|
||||||
|
ARDUINOJSON_EXPAND6({1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}));
|
||||||
|
return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static T forge(uint32_t bits) {
|
static T forge(uint32_t bits) {
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
|
||||||
#include <ArduinoJson/Numbers/parseNumber.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T parseFloat(const char* s) {
|
|
||||||
// try to reuse the same parameters as JsonDeserializer
|
|
||||||
typedef typename choose_largest<Float, T>::type TFloat;
|
|
||||||
ParsedNumber<TFloat, UInt> value;
|
|
||||||
parseNumber(s, value);
|
|
||||||
return value.template as<T>();
|
|
||||||
}
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
|
||||||
#include <ArduinoJson/Numbers/parseNumber.hpp>
|
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
template <typename T>
|
|
||||||
T parseInteger(const char *s) {
|
|
||||||
// try to reuse the same parameters as JsonDeserializer
|
|
||||||
typedef typename choose_largest<UInt, typename make_unsigned<T>::type>::type
|
|
||||||
TUInt;
|
|
||||||
ParsedNumber<Float, TUInt> value;
|
|
||||||
parseNumber(s, value);
|
|
||||||
return value.template as<T>();
|
|
||||||
}
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
||||||
@@ -10,59 +10,18 @@
|
|||||||
#include <ArduinoJson/Polyfills/ctype.hpp>
|
#include <ArduinoJson/Polyfills/ctype.hpp>
|
||||||
#include <ArduinoJson/Polyfills/math.hpp>
|
#include <ArduinoJson/Polyfills/math.hpp>
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
#include <ArduinoJson/Variant/VariantAs.hpp>
|
||||||
|
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TFloat, typename TUInt>
|
|
||||||
struct ParsedNumber {
|
|
||||||
ParsedNumber() : _type(VALUE_IS_NULL) {}
|
|
||||||
|
|
||||||
void setInteger(TUInt value, bool is_negative) {
|
|
||||||
uintValue = value;
|
|
||||||
_type = uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER
|
|
||||||
: VALUE_IS_POSITIVE_INTEGER);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFloat(TFloat value) {
|
|
||||||
floatValue = value;
|
|
||||||
_type = VALUE_IS_FLOAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T as() const {
|
|
||||||
switch (_type) {
|
|
||||||
case VALUE_IS_NEGATIVE_INTEGER:
|
|
||||||
return convertNegativeInteger<T>(uintValue);
|
|
||||||
case VALUE_IS_POSITIVE_INTEGER:
|
|
||||||
return convertPositiveInteger<T>(uintValue);
|
|
||||||
case VALUE_IS_FLOAT:
|
|
||||||
return convertFloat<T>(floatValue);
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t type() const {
|
|
||||||
return _type;
|
|
||||||
}
|
|
||||||
|
|
||||||
union {
|
|
||||||
TUInt uintValue;
|
|
||||||
TFloat floatValue;
|
|
||||||
};
|
|
||||||
uint8_t _type;
|
|
||||||
}; // namespace ARDUINOJSON_NAMESPACE
|
|
||||||
|
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
|
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
|
||||||
|
|
||||||
template <typename TFloat, typename TUInt>
|
inline bool parseNumber(const char* s, VariantData& result) {
|
||||||
inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
typedef FloatTraits<Float> traits;
|
||||||
typedef FloatTraits<TFloat> traits;
|
typedef choose_largest<traits::mantissa_type, UInt>::type mantissa_t;
|
||||||
typedef typename choose_largest<typename traits::mantissa_type, TUInt>::type
|
typedef traits::exponent_type exponent_t;
|
||||||
mantissa_t;
|
|
||||||
typedef typename traits::exponent_type exponent_t;
|
|
||||||
|
|
||||||
ARDUINOJSON_ASSERT(s != 0);
|
ARDUINOJSON_ASSERT(s != 0);
|
||||||
|
|
||||||
@@ -80,24 +39,23 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
|||||||
#if ARDUINOJSON_ENABLE_NAN
|
#if ARDUINOJSON_ENABLE_NAN
|
||||||
if (*s == 'n' || *s == 'N') {
|
if (*s == 'n' || *s == 'N') {
|
||||||
result.setFloat(traits::nan());
|
result.setFloat(traits::nan());
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_INFINITY
|
#if ARDUINOJSON_ENABLE_INFINITY
|
||||||
if (*s == 'i' || *s == 'I') {
|
if (*s == 'i' || *s == 'I') {
|
||||||
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!isdigit(*s) && *s != '.')
|
if (!isdigit(*s) && *s != '.')
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
mantissa_t mantissa = 0;
|
mantissa_t mantissa = 0;
|
||||||
exponent_t exponent_offset = 0;
|
exponent_t exponent_offset = 0;
|
||||||
const mantissa_t maxUint = TUInt(-1);
|
const mantissa_t maxUint = UInt(-1);
|
||||||
|
|
||||||
while (isdigit(*s)) {
|
while (isdigit(*s)) {
|
||||||
uint8_t digit = uint8_t(*s - '0');
|
uint8_t digit = uint8_t(*s - '0');
|
||||||
@@ -111,8 +69,11 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*s == '\0') {
|
if (*s == '\0') {
|
||||||
result.setInteger(TUInt(mantissa), is_negative);
|
if (is_negative)
|
||||||
return;
|
result.setNegativeInteger(UInt(mantissa));
|
||||||
|
else
|
||||||
|
result.setPositiveInteger(UInt(mantissa));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// avoid mantissa overflow
|
// avoid mantissa overflow
|
||||||
@@ -156,7 +117,7 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
|||||||
result.setFloat(is_negative ? -0.0f : 0.0f);
|
result.setFloat(is_negative ? -0.0f : 0.0f);
|
||||||
else
|
else
|
||||||
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
@@ -167,11 +128,20 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
|||||||
|
|
||||||
// we should be at the end of the string, otherwise it's an error
|
// we should be at the end of the string, otherwise it's an error
|
||||||
if (*s != '\0')
|
if (*s != '\0')
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
TFloat final_result =
|
Float final_result =
|
||||||
traits::make_float(static_cast<TFloat>(mantissa), exponent);
|
traits::make_float(static_cast<Float>(mantissa), exponent);
|
||||||
|
|
||||||
result.setFloat(is_negative ? -final_result : final_result);
|
result.setFloat(is_negative ? -final_result : final_result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T parseNumber(const char* s) {
|
||||||
|
VariantData value;
|
||||||
|
value.init(); // VariantData is a POD, so it has no constructor
|
||||||
|
parseNumber(s, value);
|
||||||
|
return variantAs<T>(&value);
|
||||||
}
|
}
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
|
|||||||
return getOrAddUpstreamMember().set(value);
|
return getOrAddUpstreamMember().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
void accept(Visitor &visitor) const {
|
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||||
return getUpstreamMember().accept(visitor);
|
return getUpstreamMember().accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,13 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
void objectAccept(const CollectionData *obj, Visitor &visitor) {
|
typename TVisitor::result_type objectAccept(const CollectionData *obj,
|
||||||
|
TVisitor &visitor) {
|
||||||
if (obj)
|
if (obj)
|
||||||
visitor.visitObject(*obj);
|
return visitor.visitObject(*obj);
|
||||||
else
|
else
|
||||||
visitor.visitNull();
|
return visitor.visitNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
|
inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ class ObjectRefBase {
|
|||||||
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
|
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||||
objectAccept(_data, visitor);
|
return objectAccept(_data, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2020
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class not_null {
|
|
||||||
public:
|
|
||||||
explicit not_null(T ptr) : _ptr(ptr) {
|
|
||||||
ARDUINOJSON_ASSERT(ptr != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
T get() const {
|
|
||||||
ARDUINOJSON_ASSERT(_ptr != NULL);
|
|
||||||
return _ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T _ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
not_null<T> make_not_null(T ptr) {
|
|
||||||
ARDUINOJSON_ASSERT(ptr != NULL);
|
|
||||||
return not_null<T>(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Configuration.hpp>
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2020
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename enable_if<is_pointer<T>::value, T>::type pgm_read(const void* p) {
|
||||||
|
return reinterpret_cast<T>(pgm_read_ptr(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename enable_if<is_floating_point<T>::value &&
|
||||||
|
sizeof(T) == sizeof(float), // on AVR sizeof(double) ==
|
||||||
|
// sizeof(float)
|
||||||
|
T>::type
|
||||||
|
pgm_read(const void* p) {
|
||||||
|
return pgm_read_float(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename enable_if<is_same<T, uint32_t>::value, T>::type pgm_read(
|
||||||
|
const void* p) {
|
||||||
|
return pgm_read_dword(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
36
lib/ArduinoJson/src/ArduinoJson/Polyfills/preprocessor.hpp
Normal file
36
lib/ArduinoJson/src/ArduinoJson/Polyfills/preprocessor.hpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2020
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define ARDUINOJSON_EXPAND6(a, b, c, d, e, f) a, b, c, d, e, f
|
||||||
|
#define ARDUINOJSON_EXPAND7(a, b, c, d, e, f, g) a, b, c, d, e, f, g
|
||||||
|
#define ARDUINOJSON_EXPAND9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i
|
||||||
|
#define ARDUINOJSON_EXPAND18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, \
|
||||||
|
q, r) \
|
||||||
|
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r
|
||||||
|
|
||||||
|
#define ARDUINOJSON_CONCAT_(A, B) A##B
|
||||||
|
#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B)
|
||||||
|
#define ARDUINOJSON_CONCAT4(A, B, C, D) \
|
||||||
|
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
|
||||||
|
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_0000() 0
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_0001() 1
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_0010() 2
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_0011() 3
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_0100() 4
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_0101() 5
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_0110() 6
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_0111() 7
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_1000() 8
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_1001() 9
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_1010() A
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_1011() B
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_1100() C
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_1101() D
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_1110() E
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_1111() F
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D()
|
||||||
|
#define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D)
|
||||||
34
lib/ArduinoJson/src/ArduinoJson/Polyfills/static_array.hpp
Normal file
34
lib/ArduinoJson/src/ArduinoJson/Polyfills/static_array.hpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2020
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Configuration.hpp>
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||||
|
|
||||||
|
#include <ArduinoJson/Polyfills/pgmspace_generic.hpp>
|
||||||
|
|
||||||
|
#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY
|
||||||
|
#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \
|
||||||
|
static type const name[] PROGMEM = value;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARDUINOJSON_READ_STATIC_ARRAY
|
||||||
|
#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \
|
||||||
|
pgm_read<type>(name + index)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0
|
||||||
|
|
||||||
|
#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY
|
||||||
|
#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \
|
||||||
|
static type const name[] = value;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARDUINOJSON_READ_STATIC_ARRAY
|
||||||
|
#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "type_traits/is_enum.hpp"
|
#include "type_traits/is_enum.hpp"
|
||||||
#include "type_traits/is_floating_point.hpp"
|
#include "type_traits/is_floating_point.hpp"
|
||||||
#include "type_traits/is_integral.hpp"
|
#include "type_traits/is_integral.hpp"
|
||||||
|
#include "type_traits/is_pointer.hpp"
|
||||||
#include "type_traits/is_same.hpp"
|
#include "type_traits/is_same.hpp"
|
||||||
#include "type_traits/is_signed.hpp"
|
#include "type_traits/is_signed.hpp"
|
||||||
#include "type_traits/is_unsigned.hpp"
|
#include "type_traits/is_unsigned.hpp"
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2020
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "integral_constant.hpp"
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_pointer : false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_pointer<T*> : true_type {};
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2020
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename TWriter>
|
||||||
|
class CountingDecorator {
|
||||||
|
public:
|
||||||
|
explicit CountingDecorator(TWriter& writer) : _writer(writer), _count(0) {}
|
||||||
|
|
||||||
|
void write(uint8_t c) {
|
||||||
|
_count += _writer.write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(const uint8_t* s, size_t n) {
|
||||||
|
_count += _writer.write(s, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count() const {
|
||||||
|
return _count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TWriter _writer;
|
||||||
|
size_t _count;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <WString.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ template <template <typename> class TSerializer, typename TSource>
|
|||||||
size_t measure(const TSource &source) {
|
size_t measure(const TSource &source) {
|
||||||
DummyWriter dp;
|
DummyWriter dp;
|
||||||
TSerializer<DummyWriter> serializer(dp);
|
TSerializer<DummyWriter> serializer(dp);
|
||||||
source.accept(serializer);
|
return source.accept(serializer);
|
||||||
return serializer.bytesWritten();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ template <template <typename> class TSerializer, typename TSource,
|
|||||||
typename TWriter>
|
typename TWriter>
|
||||||
size_t doSerialize(const TSource &source, TWriter writer) {
|
size_t doSerialize(const TSource &source, TWriter writer) {
|
||||||
TSerializer<TWriter> serializer(writer);
|
TSerializer<TWriter> serializer(writer);
|
||||||
source.accept(serializer);
|
return source.accept(serializer);
|
||||||
return serializer.bytesWritten();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <template <typename> class TSerializer, typename TSource,
|
template <template <typename> class TSerializer, typename TSource,
|
||||||
|
|||||||
@@ -10,14 +10,16 @@ namespace ARDUINOJSON_NAMESPACE {
|
|||||||
|
|
||||||
class StringCopier {
|
class StringCopier {
|
||||||
public:
|
public:
|
||||||
void startString(MemoryPool* pool) {
|
StringCopier(MemoryPool& pool) : _pool(&pool) {}
|
||||||
pool->getFreeZone(&_ptr, &_capacity);
|
|
||||||
|
void startString() {
|
||||||
|
_pool->getFreeZone(&_ptr, &_capacity);
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* save(MemoryPool* pool) {
|
const char* save() {
|
||||||
ARDUINOJSON_ASSERT(_ptr);
|
ARDUINOJSON_ASSERT(_ptr);
|
||||||
return pool->saveStringFromFreeZone(_size);
|
return _pool->saveStringFromFreeZone(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(const char* s) {
|
void append(const char* s) {
|
||||||
@@ -34,6 +36,7 @@ class StringCopier {
|
|||||||
|
|
||||||
if (_size >= _capacity) {
|
if (_size >= _capacity) {
|
||||||
_ptr = 0;
|
_ptr = 0;
|
||||||
|
_pool->markAsOverflowed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +54,7 @@ class StringCopier {
|
|||||||
typedef storage_policies::store_by_copy storage_policy;
|
typedef storage_policies::store_by_copy storage_policy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
MemoryPool* _pool;
|
||||||
char* _ptr;
|
char* _ptr;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
size_t _capacity;
|
size_t _capacity;
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ class StringMover {
|
|||||||
public:
|
public:
|
||||||
StringMover(char* ptr) : _writePtr(ptr) {}
|
StringMover(char* ptr) : _writePtr(ptr) {}
|
||||||
|
|
||||||
void startString(MemoryPool*) {
|
void startString() {
|
||||||
_startPtr = _writePtr;
|
_startPtr = _writePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* save(MemoryPool*) const {
|
const char* save() const {
|
||||||
return _startPtr;
|
return _startPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,32 +9,15 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TInput, typename Enable = void>
|
|
||||||
struct StringStorage {
|
|
||||||
typedef StringCopier type;
|
|
||||||
|
|
||||||
static type create(TInput&) {
|
|
||||||
return type();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TChar>
|
|
||||||
struct StringStorage<TChar*,
|
|
||||||
typename enable_if<!is_const<TChar>::value>::type> {
|
|
||||||
typedef StringMover type;
|
|
||||||
|
|
||||||
static type create(TChar* input) {
|
|
||||||
return type(reinterpret_cast<char*>(input));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TInput>
|
template <typename TInput>
|
||||||
typename StringStorage<TInput>::type makeStringStorage(TInput& input) {
|
StringCopier makeStringStorage(TInput&, MemoryPool& pool) {
|
||||||
return StringStorage<TInput>::create(input);
|
return StringCopier(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
typename StringStorage<TChar*>::type makeStringStorage(TChar* input) {
|
StringMover makeStringStorage(
|
||||||
return StringStorage<TChar*>::create(input);
|
TChar* input, MemoryPool&,
|
||||||
|
typename enable_if<!is_const<TChar>::value>::type* = 0) {
|
||||||
|
return StringMover(reinterpret_cast<char*>(input));
|
||||||
}
|
}
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <WString.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
|
#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
|
||||||
#include <ArduinoJson/Strings/IsString.hpp>
|
#include <ArduinoJson/Strings/IsString.hpp>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||||
#include <WString.h>
|
#include <Arduino.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STRING
|
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
class StlStringAdapter {
|
class StdStringAdapter {
|
||||||
public:
|
public:
|
||||||
StlStringAdapter(const TString& str) : _str(&str) {}
|
StdStringAdapter(const TString& str) : _str(&str) {}
|
||||||
|
|
||||||
void copyTo(char* p, size_t n) const {
|
void copyTo(char* p, size_t n) const {
|
||||||
memcpy(p, _str->c_str(), n);
|
memcpy(p, _str->c_str(), n);
|
||||||
@@ -56,9 +56,9 @@ struct IsString<std::basic_string<char, TCharTraits, TAllocator> > : true_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename TCharTraits, typename TAllocator>
|
template <typename TCharTraits, typename TAllocator>
|
||||||
inline StlStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >
|
inline StdStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >
|
||||||
adaptString(const std::basic_string<char, TCharTraits, TAllocator>& str) {
|
adaptString(const std::basic_string<char, TCharTraits, TAllocator>& str) {
|
||||||
return StlStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >(
|
return StdStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >(
|
||||||
str);
|
str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <ArduinoJson/Strings/SizedRamStringAdapter.hpp>
|
#include <ArduinoJson/Strings/SizedRamStringAdapter.hpp>
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STRING
|
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||||
#include <ArduinoJson/Strings/StlStringAdapter.hpp>
|
#include <ArduinoJson/Strings/StdStringAdapter.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||||
|
|||||||
@@ -14,20 +14,34 @@ namespace ARDUINOJSON_NAMESPACE {
|
|||||||
|
|
||||||
class CollectionData;
|
class CollectionData;
|
||||||
|
|
||||||
struct ComparerBase {
|
struct ComparerBase : Visitor<CompareResult> {
|
||||||
CompareResult result;
|
CompareResult visitArray(const CollectionData &) {
|
||||||
|
return COMPARE_RESULT_DIFFER;
|
||||||
ComparerBase() : result(COMPARE_RESULT_DIFFER) {}
|
}
|
||||||
|
CompareResult visitBoolean(bool) {
|
||||||
void visitArray(const CollectionData &) {}
|
return COMPARE_RESULT_DIFFER;
|
||||||
void visitBoolean(bool) {}
|
}
|
||||||
void visitFloat(Float) {}
|
CompareResult visitFloat(Float) {
|
||||||
void visitNegativeInteger(UInt) {}
|
return COMPARE_RESULT_DIFFER;
|
||||||
void visitNull() {}
|
}
|
||||||
void visitObject(const CollectionData &) {}
|
CompareResult visitNegativeInteger(UInt) {
|
||||||
void visitPositiveInteger(UInt) {}
|
return COMPARE_RESULT_DIFFER;
|
||||||
void visitRawJson(const char *, size_t) {}
|
}
|
||||||
void visitString(const char *) {}
|
CompareResult visitNull() {
|
||||||
|
return COMPARE_RESULT_DIFFER;
|
||||||
|
}
|
||||||
|
CompareResult visitObject(const CollectionData &) {
|
||||||
|
return COMPARE_RESULT_DIFFER;
|
||||||
|
}
|
||||||
|
CompareResult visitPositiveInteger(UInt) {
|
||||||
|
return COMPARE_RESULT_DIFFER;
|
||||||
|
}
|
||||||
|
CompareResult visitRawJson(const char *, size_t) {
|
||||||
|
return COMPARE_RESULT_DIFFER;
|
||||||
|
}
|
||||||
|
CompareResult visitString(const char *) {
|
||||||
|
return COMPARE_RESULT_DIFFER;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Enable = void>
|
template <typename T, typename Enable = void>
|
||||||
@@ -40,19 +54,21 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type>
|
|||||||
|
|
||||||
explicit Comparer(T value) : rhs(value) {}
|
explicit Comparer(T value) : rhs(value) {}
|
||||||
|
|
||||||
void visitString(const char *lhs) {
|
CompareResult visitString(const char *lhs) {
|
||||||
int i = adaptString(rhs).compare(lhs);
|
int i = adaptString(rhs).compare(lhs);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
result = COMPARE_RESULT_GREATER;
|
return COMPARE_RESULT_GREATER;
|
||||||
else if (i > 0)
|
else if (i > 0)
|
||||||
result = COMPARE_RESULT_LESS;
|
return COMPARE_RESULT_LESS;
|
||||||
else
|
else
|
||||||
result = COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNull() {
|
CompareResult visitNull() {
|
||||||
if (adaptString(rhs).isNull())
|
if (adaptString(rhs).isNull())
|
||||||
result = COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
|
else
|
||||||
|
return COMPARE_RESULT_DIFFER;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,26 +80,26 @@ struct Comparer<T, typename enable_if<is_integral<T>::value ||
|
|||||||
|
|
||||||
explicit Comparer(T value) : rhs(value) {}
|
explicit Comparer(T value) : rhs(value) {}
|
||||||
|
|
||||||
void visitFloat(Float lhs) {
|
CompareResult visitFloat(Float lhs) {
|
||||||
result = arithmeticCompare(lhs, rhs);
|
return arithmeticCompare(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNegativeInteger(UInt lhs) {
|
CompareResult visitNegativeInteger(UInt lhs) {
|
||||||
result = arithmeticCompareNegateLeft(lhs, rhs);
|
return arithmeticCompareNegateLeft(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitPositiveInteger(UInt lhs) {
|
CompareResult visitPositiveInteger(UInt lhs) {
|
||||||
result = arithmeticCompare(lhs, rhs);
|
return arithmeticCompare(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitBoolean(bool lhs) {
|
CompareResult visitBoolean(bool lhs) {
|
||||||
visitPositiveInteger(static_cast<UInt>(lhs));
|
return visitPositiveInteger(static_cast<UInt>(lhs));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NullComparer : ComparerBase {
|
struct NullComparer : ComparerBase {
|
||||||
void visitNull() {
|
CompareResult visitNull() {
|
||||||
result = COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -99,9 +115,11 @@ struct ArrayComparer : ComparerBase {
|
|||||||
|
|
||||||
explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
|
explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
|
||||||
|
|
||||||
void visitArray(const CollectionData &lhs) {
|
CompareResult visitArray(const CollectionData &lhs) {
|
||||||
if (lhs.equalsArray(*_rhs))
|
if (lhs.equalsArray(*_rhs))
|
||||||
result = COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
|
else
|
||||||
|
return COMPARE_RESULT_DIFFER;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -110,20 +128,20 @@ struct NegativeIntegerComparer : ComparerBase {
|
|||||||
|
|
||||||
explicit NegativeIntegerComparer(UInt rhs) : _rhs(rhs) {}
|
explicit NegativeIntegerComparer(UInt rhs) : _rhs(rhs) {}
|
||||||
|
|
||||||
void visitFloat(Float lhs) {
|
CompareResult visitFloat(Float lhs) {
|
||||||
result = arithmeticCompareNegateRight(lhs, _rhs);
|
return arithmeticCompareNegateRight(lhs, _rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNegativeInteger(UInt lhs) {
|
CompareResult visitNegativeInteger(UInt lhs) {
|
||||||
result = arithmeticCompare(_rhs, lhs);
|
return arithmeticCompare(_rhs, lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitPositiveInteger(UInt) {
|
CompareResult visitPositiveInteger(UInt) {
|
||||||
result = COMPARE_RESULT_GREATER;
|
return COMPARE_RESULT_GREATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitBoolean(bool) {
|
CompareResult visitBoolean(bool) {
|
||||||
result = COMPARE_RESULT_GREATER;
|
return COMPARE_RESULT_GREATER;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,9 +150,11 @@ struct ObjectComparer : ComparerBase {
|
|||||||
|
|
||||||
explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
|
explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
|
||||||
|
|
||||||
void visitObject(const CollectionData &lhs) {
|
CompareResult visitObject(const CollectionData &lhs) {
|
||||||
if (lhs.equalsObject(*_rhs))
|
if (lhs.equalsObject(*_rhs))
|
||||||
result = COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
|
else
|
||||||
|
return COMPARE_RESULT_DIFFER;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -145,15 +165,15 @@ struct RawComparer : ComparerBase {
|
|||||||
explicit RawComparer(const char *rhsData, size_t rhsSize)
|
explicit RawComparer(const char *rhsData, size_t rhsSize)
|
||||||
: _rhsData(rhsData), _rhsSize(rhsSize) {}
|
: _rhsData(rhsData), _rhsSize(rhsSize) {}
|
||||||
|
|
||||||
void visitRawJson(const char *lhsData, size_t lhsSize) {
|
CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
|
||||||
size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
|
size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
|
||||||
int n = memcmp(lhsData, _rhsData, size);
|
int n = memcmp(lhsData, _rhsData, size);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
result = COMPARE_RESULT_LESS;
|
return COMPARE_RESULT_LESS;
|
||||||
else if (n > 0)
|
else if (n > 0)
|
||||||
result = COMPARE_RESULT_GREATER;
|
return COMPARE_RESULT_GREATER;
|
||||||
else
|
else
|
||||||
result = COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -164,65 +184,62 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
|
|||||||
|
|
||||||
explicit Comparer(T value) : rhs(value) {}
|
explicit Comparer(T value) : rhs(value) {}
|
||||||
|
|
||||||
void visitArray(const CollectionData &lhs) {
|
CompareResult visitArray(const CollectionData &lhs) {
|
||||||
ArrayComparer comparer(lhs);
|
ArrayComparer comparer(lhs);
|
||||||
accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitObject(const CollectionData &lhs) {
|
CompareResult visitObject(const CollectionData &lhs) {
|
||||||
ObjectComparer comparer(lhs);
|
ObjectComparer comparer(lhs);
|
||||||
accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitFloat(Float lhs) {
|
CompareResult visitFloat(Float lhs) {
|
||||||
Comparer<Float> comparer(lhs);
|
Comparer<Float> comparer(lhs);
|
||||||
accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitString(const char *lhs) {
|
CompareResult visitString(const char *lhs) {
|
||||||
Comparer<const char *> comparer(lhs);
|
Comparer<const char *> comparer(lhs);
|
||||||
accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitRawJson(const char *lhsData, size_t lhsSize) {
|
CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
|
||||||
RawComparer comparer(lhsData, lhsSize);
|
RawComparer comparer(lhsData, lhsSize);
|
||||||
accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNegativeInteger(UInt lhs) {
|
CompareResult visitNegativeInteger(UInt lhs) {
|
||||||
NegativeIntegerComparer comparer(lhs);
|
NegativeIntegerComparer comparer(lhs);
|
||||||
accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitPositiveInteger(UInt lhs) {
|
CompareResult visitPositiveInteger(UInt lhs) {
|
||||||
Comparer<UInt> comparer(lhs);
|
Comparer<UInt> comparer(lhs);
|
||||||
accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitBoolean(bool lhs) {
|
CompareResult visitBoolean(bool lhs) {
|
||||||
Comparer<bool> comparer(lhs);
|
Comparer<bool> comparer(lhs);
|
||||||
accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNull() {
|
CompareResult visitNull() {
|
||||||
NullComparer comparer;
|
NullComparer comparer;
|
||||||
accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename TComparer>
|
template <typename TComparer>
|
||||||
void accept(TComparer &comparer) {
|
CompareResult accept(TComparer &comparer) {
|
||||||
rhs.accept(comparer);
|
CompareResult reversedResult = rhs.accept(comparer);
|
||||||
switch (comparer.result) {
|
switch (reversedResult) {
|
||||||
case COMPARE_RESULT_GREATER:
|
case COMPARE_RESULT_GREATER:
|
||||||
result = COMPARE_RESULT_LESS;
|
return COMPARE_RESULT_LESS;
|
||||||
break;
|
|
||||||
case COMPARE_RESULT_LESS:
|
case COMPARE_RESULT_LESS:
|
||||||
result = COMPARE_RESULT_GREATER;
|
return COMPARE_RESULT_GREATER;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
result = comparer.result;
|
return reversedResult;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -230,8 +247,7 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
|
|||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
CompareResult compare(const T1 &lhs, const T2 &rhs) {
|
CompareResult compare(const T1 &lhs, const T2 &rhs) {
|
||||||
Comparer<T2> comparer(rhs);
|
Comparer<T2> comparer(rhs);
|
||||||
lhs.accept(comparer);
|
return lhs.accept(comparer);
|
||||||
return comparer.result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int variantCompare(const VariantData *a, const VariantData *b) {
|
inline int variantCompare(const VariantData *a, const VariantData *b) {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||||
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
||||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||||
#include <ArduinoJson/Polyfills/gsl/not_null.hpp>
|
|
||||||
#include <ArduinoJson/Strings/RamStringAdapter.hpp>
|
#include <ArduinoJson/Strings/RamStringAdapter.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||||
|
|
||||||
@@ -33,9 +32,12 @@ class VariantData {
|
|||||||
// - no destructor
|
// - no destructor
|
||||||
// - no virtual
|
// - no virtual
|
||||||
// - no inheritance
|
// - no inheritance
|
||||||
|
void init() {
|
||||||
|
_flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
void accept(Visitor &visitor) const {
|
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case VALUE_IS_FLOAT:
|
case VALUE_IS_FLOAT:
|
||||||
return visitor.visitFloat(_content.asFloat);
|
return visitor.visitFloat(_content.asFloat);
|
||||||
@@ -242,25 +244,14 @@ class VariantData {
|
|||||||
setType(VALUE_IS_NULL);
|
setType(VALUE_IS_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setString(not_null<const char *> s, storage_policies::store_by_copy) {
|
void setStringPointer(const char *s, storage_policies::store_by_copy) {
|
||||||
setType(VALUE_IS_OWNED_STRING);
|
setType(VALUE_IS_OWNED_STRING);
|
||||||
_content.asString = s.get();
|
_content.asString = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setString(not_null<const char *> s, storage_policies::store_by_address) {
|
void setStringPointer(const char *s, storage_policies::store_by_address) {
|
||||||
setType(VALUE_IS_LINKED_STRING);
|
setType(VALUE_IS_LINKED_STRING);
|
||||||
_content.asString = s.get();
|
_content.asString = s;
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TStoragePolicy>
|
|
||||||
bool setString(const char *s, TStoragePolicy storage_policy) {
|
|
||||||
if (s) {
|
|
||||||
setString(make_not_null(s), storage_policy);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
setType(VALUE_IS_NULL);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
@@ -280,14 +271,27 @@ class VariantData {
|
|||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
inline bool setString(TAdaptedString value, MemoryPool *,
|
inline bool setString(TAdaptedString value, MemoryPool *,
|
||||||
storage_policies::store_by_address) {
|
storage_policies::store_by_address) {
|
||||||
return setString(value.data(), storage_policies::store_by_address());
|
if (value.isNull())
|
||||||
|
setNull();
|
||||||
|
else
|
||||||
|
setStringPointer(value.data(), storage_policies::store_by_address());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
inline bool setString(TAdaptedString value, MemoryPool *pool,
|
inline bool setString(TAdaptedString value, MemoryPool *pool,
|
||||||
storage_policies::store_by_copy) {
|
storage_policies::store_by_copy) {
|
||||||
return setString(pool->saveString(value),
|
if (value.isNull()) {
|
||||||
storage_policies::store_by_copy());
|
setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const char *copy = pool->saveString(value);
|
||||||
|
if (!copy) {
|
||||||
|
setNull();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
setStringPointer(copy, storage_policies::store_by_copy());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionData &toArray() {
|
CollectionData &toArray() {
|
||||||
@@ -365,11 +369,11 @@ class VariantData {
|
|||||||
_content.asCollection.movePointers(stringDistance, variantDistance);
|
_content.asCollection.movePointers(stringDistance, variantDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t type() const {
|
uint8_t type() const {
|
||||||
return _flags & VALUE_MASK;
|
return _flags & VALUE_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
void setType(uint8_t t) {
|
void setType(uint8_t t) {
|
||||||
_flags &= KEY_IS_OWNED;
|
_flags &= KEY_IS_OWNED;
|
||||||
_flags |= t;
|
_flags |= t;
|
||||||
|
|||||||
@@ -9,12 +9,13 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
inline void variantAccept(const VariantData *var, Visitor &visitor) {
|
inline typename TVisitor::result_type variantAccept(const VariantData *var,
|
||||||
|
TVisitor &visitor) {
|
||||||
if (var != 0)
|
if (var != 0)
|
||||||
var->accept(visitor);
|
return var->accept(visitor);
|
||||||
else
|
else
|
||||||
visitor.visitNull();
|
return visitor.visitNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const CollectionData *variantAsArray(const VariantData *var) {
|
inline const CollectionData *variantAsArray(const VariantData *var) {
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Array/ArrayRef.hpp>
|
||||||
#include <ArduinoJson/Configuration.hpp>
|
#include <ArduinoJson/Configuration.hpp>
|
||||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||||
#include <ArduinoJson/Numbers/parseFloat.hpp>
|
#include <ArduinoJson/Numbers/parseNumber.hpp>
|
||||||
#include <ArduinoJson/Numbers/parseInteger.hpp>
|
#include <ArduinoJson/Object/ObjectRef.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantRef.hpp>
|
#include <ArduinoJson/Variant/VariantRef.hpp>
|
||||||
|
|
||||||
#include <string.h> // for strcmp
|
#include <string.h> // for strcmp
|
||||||
@@ -24,7 +25,7 @@ inline T VariantData::asIntegral() const {
|
|||||||
return convertNegativeInteger<T>(_content.asInteger);
|
return convertNegativeInteger<T>(_content.asInteger);
|
||||||
case VALUE_IS_LINKED_STRING:
|
case VALUE_IS_LINKED_STRING:
|
||||||
case VALUE_IS_OWNED_STRING:
|
case VALUE_IS_OWNED_STRING:
|
||||||
return parseInteger<T>(_content.asString);
|
return parseNumber<T>(_content.asString);
|
||||||
case VALUE_IS_FLOAT:
|
case VALUE_IS_FLOAT:
|
||||||
return convertFloat<T>(_content.asFloat);
|
return convertFloat<T>(_content.asFloat);
|
||||||
default:
|
default:
|
||||||
@@ -58,7 +59,7 @@ inline T VariantData::asFloat() const {
|
|||||||
return -static_cast<T>(_content.asInteger);
|
return -static_cast<T>(_content.asInteger);
|
||||||
case VALUE_IS_LINKED_STRING:
|
case VALUE_IS_LINKED_STRING:
|
||||||
case VALUE_IS_OWNED_STRING:
|
case VALUE_IS_OWNED_STRING:
|
||||||
return parseFloat<T>(_content.asString);
|
return parseNumber<T>(_content.asString);
|
||||||
case VALUE_IS_FLOAT:
|
case VALUE_IS_FLOAT:
|
||||||
return static_cast<T>(_content.asFloat);
|
return static_cast<T>(_content.asFloat);
|
||||||
default:
|
default:
|
||||||
@@ -138,4 +139,9 @@ template <typename TString>
|
|||||||
inline VariantRef VariantRef::getOrAddMember(const TString &key) const {
|
inline VariantRef VariantRef::getOrAddMember(const TString &key) const {
|
||||||
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
|
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline VariantConstRef operator|(VariantConstRef preferedValue,
|
||||||
|
VariantConstRef defaultValue) {
|
||||||
|
return preferedValue ? preferedValue : defaultValue;
|
||||||
|
}
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ template <typename TVariant>
|
|||||||
struct VariantOperators {
|
struct VariantOperators {
|
||||||
// Returns the default value if the VariantRef is undefined of incompatible
|
// Returns the default value if the VariantRef is undefined of incompatible
|
||||||
template <typename T>
|
template <typename T>
|
||||||
friend T operator|(const TVariant &variant, const T &defaultValue) {
|
friend typename enable_if<!IsVisitable<T>::value, T>::type operator|(
|
||||||
|
const TVariant &variant, const T &defaultValue) {
|
||||||
if (variant.template is<T>())
|
if (variant.template is<T>())
|
||||||
return variant.template as<T>();
|
return variant.template as<T>();
|
||||||
else
|
else
|
||||||
@@ -28,8 +29,9 @@ struct VariantOperators {
|
|||||||
|
|
||||||
// Returns the default value if the VariantRef is undefined of incompatible
|
// Returns the default value if the VariantRef is undefined of incompatible
|
||||||
// Special case for string: null is treated as undefined
|
// Special case for string: null is treated as undefined
|
||||||
friend const char *operator|(const TVariant &variant,
|
template <typename T>
|
||||||
const char *defaultValue) {
|
friend typename enable_if<is_same<T, const char *>::value, T>::type operator|(
|
||||||
|
const TVariant &variant, T defaultValue) {
|
||||||
const char *value = variant.template as<const char *>();
|
const char *value = variant.template as<const char *>();
|
||||||
return value ? value : defaultValue;
|
return value ? value : defaultValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -261,9 +261,9 @@ class VariantRef : public VariantRefBase<VariantData>,
|
|||||||
return variantAs<T>(_data, _pool);
|
return variantAs<T>(_data, _pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
void accept(Visitor &visitor) const {
|
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||||
variantAccept(_data, visitor);
|
return variantAccept(_data, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the type of the variant
|
// Change the type of the variant
|
||||||
@@ -347,9 +347,9 @@ class VariantConstRef : public VariantRefBase<const VariantData>,
|
|||||||
VariantConstRef(const VariantData *data) : base_type(data) {}
|
VariantConstRef(const VariantData *data) : base_type(data) {}
|
||||||
VariantConstRef(VariantRef var) : base_type(var._data) {}
|
VariantConstRef(VariantRef var) : base_type(var._data) {}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename TVisitor>
|
||||||
void accept(Visitor &visitor) const {
|
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||||
variantAccept(_data, visitor);
|
return variantAccept(_data, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#include <stdint.h> // int8_t, int16_t
|
#include <stdint.h> // int8_t, int16_t
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/gsl/not_null.hpp>
|
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ARDUINOJSON_VERSION "6.16.1"
|
#define ARDUINOJSON_VERSION "6.17.0"
|
||||||
#define ARDUINOJSON_VERSION_MAJOR 6
|
#define ARDUINOJSON_VERSION_MAJOR 6
|
||||||
#define ARDUINOJSON_VERSION_MINOR 16
|
#define ARDUINOJSON_VERSION_MINOR 17
|
||||||
#define ARDUINOJSON_VERSION_REVISION 1
|
#define ARDUINOJSON_VERSION_REVISION 0
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ int digitalRead(uint8_t pin);
|
|||||||
&__c[0]; \
|
&__c[0]; \
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
||||||
class __FlashStringHelper;
|
class __FlashStringHelper;
|
||||||
#define FPSTR(string_literal) (reinterpret_cast<const __FlashStringHelper *>(string_literal))
|
#define FPSTR(string_literal) (reinterpret_cast<const __FlashStringHelper *>(string_literal))
|
||||||
#define F(string_literal) (FPSTR(PSTR(string_literal)))
|
#define F(string_literal) (FPSTR(PSTR(string_literal)))
|
||||||
@@ -67,7 +66,13 @@ class __FlashStringHelper;
|
|||||||
int snprintf_P(char * str, size_t size, const char * format, ...);
|
int snprintf_P(char * str, size_t size, const char * format, ...);
|
||||||
int vsnprintf_P(char * str, size_t size, const char * format, va_list ap);
|
int vsnprintf_P(char * str, size_t size, const char * format, va_list ap);
|
||||||
|
|
||||||
#define pgm_read_byte(addr) (*reinterpret_cast<const char *>(addr))
|
// #define pgm_read_byte(addr) (*reinterpret_cast<const char *>(addr))
|
||||||
|
// #define pgm_read_ptr(p) (reinterpret_cast<const void *>(p))
|
||||||
|
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||||
|
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||||
|
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
|
||||||
|
#define pgm_read_float(addr) (*(const float *)(addr))
|
||||||
|
#define pgm_read_ptr(addr) (*(const void **)(addr))
|
||||||
|
|
||||||
class Print;
|
class Print;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user